• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5026365759

19 May 2023 05:16PM UTC coverage: 91.713% (-0.003%) from 91.716%
5026365759

push

github

77651 of 84667 relevant lines covered (91.71%)

11911574.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.02
/src/cli/tls_helpers.h
1
/*
2
* (C) 2014,2015,2019 Jack Lloyd
3
*     2023           René Meusel, Rohde & Schwarz Cybersecurity
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#ifndef BOTAN_CLI_TLS_HELPERS_H_
9
#define BOTAN_CLI_TLS_HELPERS_H_
10

11
#include <botan/pkcs8.h>
12
#include <botan/credentials_manager.h>
13
#include <botan/tls_policy.h>
14
#include <botan/x509self.h>
15
#include <botan/data_src.h>
16
#include <memory>
17
#include <fstream>
18

19
#include "cli_exceptions.h"
20

21
#if defined(BOTAN_HAS_CERTSTOR_SYSTEM)
22
   #include <botan/certstor_system.h>
23
#endif
24

25
inline bool value_exists(const std::vector<std::string>& vec,
26
                         const std::string& val)
27
   {
28
   for(size_t i = 0; i != vec.size(); ++i)
29
      {
30
      if(vec[i] == val)
31
         {
32
         return true;
33
         }
34
      }
35
   return false;
36
   }
37

38
class Basic_Credentials_Manager : public Botan::Credentials_Manager
39
   {
40
   protected:
41
      void load_credentials(const std::string& crt, const std::string& key)
39✔
42
         {
43
         Certificate_Info cert;
39✔
44

45
         Botan::DataSource_Stream key_in(key);
39✔
46
         cert.key = Botan::PKCS8::load_key(key_in);
78✔
47

48
         Botan::DataSource_Stream in(crt);
39✔
49
         while(!in.end_of_data())
117✔
50
            {
51
            try
78✔
52
               {
53
               cert.certs.push_back(Botan::X509_Certificate(in));
117✔
54
               }
55
            catch(std::exception&)
39✔
56
               {
57
               }
39✔
58
            }
59

60
         // TODO: attempt to validate chain ourselves
61

62
         m_creds.push_back(cert);
39✔
63
         }
39✔
64

65
   public:
66
      Basic_Credentials_Manager(bool use_system_store,
40✔
67
                                std::string ca_path,
68
                                std::optional<std::string> client_crt = std::nullopt,
69
                                std::optional<std::string> client_key = std::nullopt,
70
                                std::optional<Botan::SymmetricKey> psk = std::nullopt,
71
                                std::optional<std::string> psk_identity = std::nullopt)
72
         : m_psk(std::move(psk))
80✔
73
         , m_psk_identity(std::move(psk_identity))
41✔
74
         {
75
         if(ca_path.empty() == false)
40✔
76
            {
77
            m_certstores.push_back(std::make_shared<Botan::Certificate_Store_In_Memory>(ca_path));
4✔
78
            }
79

80
         BOTAN_ARG_CHECK(client_crt.has_value() == client_key.has_value(), "either provide both client certificate and key or neither");
40✔
81

82
         if(client_crt.has_value() && client_key.has_value())
40✔
83
            {
84
            load_credentials(client_crt.value(), client_key.value());
×
85
            }
86

87
#if defined(BOTAN_HAS_CERTSTOR_SYSTEM)
88
         if(use_system_store)
40✔
89
            {
90
            m_certstores.push_back(std::make_shared<Botan::System_Certificate_Store>());
40✔
91
            }
92
#else
93
         BOTAN_UNUSED(use_system_store);
94
#endif
95
         }
40✔
96

97
      Basic_Credentials_Manager(const std::string& server_crt,
39✔
98
                                const std::string& server_key,
99
                                std::optional<Botan::SymmetricKey> psk = std::nullopt,
100
                                std::optional<std::string> psk_identity = std::nullopt)
101
         : m_psk(std::move(psk))
78✔
102
         , m_psk_identity(std::move(psk_identity))
40✔
103
         {
104
         load_credentials(server_crt, server_key);
39✔
105
         }
39✔
106

107
      std::vector<Botan::Certificate_Store*>
108
      trusted_certificate_authorities(const std::string& type,
87✔
109
                                      const std::string& /*hostname*/) override
110
         {
111
         std::vector<Botan::Certificate_Store*> v;
87✔
112

113
         // don't ask for client certs
114
         if(type == "tls-server")
87✔
115
            {
116
            return v;
117
            }
118

119
         for(auto const& cs : m_certstores)
81✔
120
            {
121
            v.push_back(cs.get());
42✔
122
            }
123

124
         return v;
125
         }
×
126

127
      std::vector<Botan::X509_Certificate> find_cert_chain(
112✔
128
         const std::vector<std::string>& algos,
129
         const std::vector<Botan::AlgorithmIdentifier>& cert_signature_schemes,
130
         const std::vector<Botan::X509_DN>& acceptable_cas,
131
         const std::string& type,
132
         const std::string& hostname) override
133
         {
134
         BOTAN_UNUSED(cert_signature_schemes);
112✔
135

136
         if(type == "tls-client")
112✔
137
            {
138
            for(const auto& dn : acceptable_cas)
×
139
               {
140
               for(const auto &cred : m_creds)
×
141
                  {
142
                  if(dn == cred.certs[0].issuer_dn())
×
143
                     return cred.certs;
×
144
                  }
145
               }
146
            }
147
         else if(type == "tls-server")
112✔
148
            {
149
            for(auto const& i : m_creds)
176✔
150
               {
151
               if(std::find(algos.begin(), algos.end(), i.key->algo_name()) == algos.end())
112✔
152
                  {
153
                  continue;
64✔
154
                  }
155

156
               if(hostname != "" && !i.certs[0].matches_dns_name(hostname))
48✔
157
                  {
158
                  continue;
×
159
                  }
160

161
               return i.certs;
48✔
162
               }
163
            }
164

165
         return {};
64✔
166
         }
167

168
      std::shared_ptr<Botan::Private_Key>
169
      private_key_for(const Botan::X509_Certificate& cert,
47✔
170
                      const std::string& /*type*/,
171
                      const std::string& /*context*/) override
172
         {
173
         for(auto const& i : m_creds)
47✔
174
            {
175
            if(cert == i.certs[0])
47✔
176
               {
177
               return i.key;
47✔
178
               }
179
            }
180

181
         return nullptr;
×
182
         }
183

184
      std::string psk_identity(const std::string& type,
1✔
185
                               const std::string& context,
186
                               const std::string& identity_hint) override
187
         {
188
         return (m_psk_identity && (type == "tls-client" || type == "tls-server"))
1✔
189
            ? m_psk_identity.value()
2✔
190
            : Botan::Credentials_Manager::psk_identity(type, context, identity_hint);
×
191
         }
192

193
      Botan::SymmetricKey psk(const std::string& type,
2✔
194
                              const std::string& context,
195
                              const std::string& identity) override
196
         {
197
         return (m_psk && m_psk_identity && identity == m_psk_identity.value() &&
2✔
198
                 (type == "tls-client" || type == "tls-server"))
2✔
199
            ? m_psk.value()
4✔
200
            : Botan::Credentials_Manager::psk(type, context, identity);
×
201
         }
202

203
   private:
204
      struct Certificate_Info
78✔
205
         {
206
         std::vector<Botan::X509_Certificate> certs;
207
         std::shared_ptr<Botan::Private_Key> key;
208
         };
209

210
      std::vector<Certificate_Info> m_creds;
211
      std::vector<std::shared_ptr<Botan::Certificate_Store>> m_certstores;
212
      std::optional<Botan::SymmetricKey> m_psk;
213
      std::optional<std::string> m_psk_identity;
214
   };
215

216
class TLS_All_Policy final : public Botan::TLS::Policy
2✔
217
   {
218
   public:
219
      std::vector<std::string> allowed_ciphers() const override
90✔
220
         {
221
         return std::vector<std::string>
90✔
222
            {
223
            "ChaCha20Poly1305",
224
            "AES-256/OCB(12)",
225
            "AES-128/OCB(12)",
226
            "AES-256/GCM",
227
            "AES-128/GCM",
228
            "AES-256/CCM",
229
            "AES-128/CCM",
230
            "AES-256/CCM(8)",
231
            "AES-128/CCM(8)",
232
            "Camellia-256/GCM",
233
            "Camellia-128/GCM",
234
            "ARIA-256/GCM",
235
            "ARIA-128/GCM",
236
            "AES-256",
237
            "AES-128",
238
            "Camellia-256",
239
            "Camellia-128",
240
            "SEED",
241
            "3DES"
242
            };
1,800✔
243
         }
244

245
      std::vector<std::string> allowed_key_exchange_methods() const override
1✔
246
         {
247
         return { "ECDHE_PSK", "DHE_PSK", "PSK", "ECDH", "DH", "RSA" };
7✔
248
         }
249

250
      std::vector<std::string> allowed_signature_methods() const override
1✔
251
         {
252
         return { "ECDSA", "RSA", "DSA", "IMPLICIT" };
5✔
253
         }
254

255
      bool allow_tls12() const override { return true; }
1✔
256
   };
257

258
inline std::shared_ptr<Botan::TLS::Policy> load_tls_policy(const std::string policy_type)
12✔
259
   {
260
   if(policy_type == "default" || policy_type == "")
12✔
261
      {
262
      return std::make_shared<Botan::TLS::Policy>();
3✔
263
      }
264
   else if(policy_type == "suiteb_128")
9✔
265
      {
266
      return std::make_shared<Botan::TLS::NSA_Suite_B_128>();
1✔
267
      }
268
   else if(policy_type == "suiteb_192" || policy_type == "suiteb")
8✔
269
      {
270
      return std::make_shared<Botan::TLS::NSA_Suite_B_192>();
1✔
271
      }
272
   else if(policy_type == "strict")
7✔
273
      {
274
      return std::make_shared<Botan::TLS::Strict_Policy>();
1✔
275
      }
276
   else if(policy_type == "bsi")
6✔
277
      {
278
      return std::make_shared<Botan::TLS::BSI_TR_02102_2>();
×
279
      }
280
   else if(policy_type == "datagram")
6✔
281
      {
282
      return std::make_shared<Botan::TLS::Strict_Policy>();
×
283
      }
284
   else if(policy_type == "all" || policy_type == "everything")
6✔
285
      {
286
      return std::make_shared<TLS_All_Policy>();
1✔
287
      }
288

289
   // if something we don't recognize, assume it's a file
290
   std::ifstream policy_stream(policy_type);
5✔
291
   if(!policy_stream.good())
5✔
292
      {
293
      throw Botan_CLI::CLI_Usage_Error("Unknown TLS policy: not a file or known short name");
×
294
      }
295
   return std::make_shared<Botan::TLS::Text_Policy>(policy_stream);
5✔
296
   }
5✔
297

298
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc