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

randombit / botan / 5696981105

28 Jul 2023 12:55PM UTC coverage: 91.69% (+0.005%) from 91.685%
5696981105

push

github

randombit
Merge GH #3649 Remove some macros from loadstor.h

78267 of 85360 relevant lines covered (91.69%)

12322548.38 hits per line

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

86.6
/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/credentials_manager.h>
12
#include <botan/data_src.h>
13
#include <botan/pkcs8.h>
14
#include <botan/tls_policy.h>
15
#include <botan/x509self.h>
16
#include <fstream>
17
#include <memory>
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, const std::string& val) {
26
   for(size_t i = 0; i != vec.size(); ++i) {
27
      if(vec[i] == val) {
28
         return true;
29
      }
30
   }
31
   return false;
32
}
33

34
class Basic_Credentials_Manager : public Botan::Credentials_Manager {
35
   protected:
36
      void load_credentials(const std::string& crt, const std::string& key) {
39✔
37
         Certificate_Info cert;
39✔
38

39
         Botan::DataSource_Stream key_in(key);
39✔
40
         cert.key = Botan::PKCS8::load_key(key_in);
78✔
41

42
         Botan::DataSource_Stream in(crt);
39✔
43
         while(!in.end_of_data()) {
117✔
44
            try {
78✔
45
               cert.certs.push_back(Botan::X509_Certificate(in));
117✔
46
            } catch(std::exception&) {}
39✔
47
         }
48

49
         // TODO: attempt to validate chain ourselves
50

51
         m_creds.push_back(cert);
39✔
52
      }
39✔
53

54
   public:
55
      Basic_Credentials_Manager(bool use_system_store,
40✔
56
                                const std::string& ca_path,
57
                                std::optional<std::string> client_crt = std::nullopt,
58
                                std::optional<std::string> client_key = std::nullopt,
59
                                std::optional<Botan::secure_vector<uint8_t>> psk = std::nullopt,
60
                                std::optional<std::string> psk_identity = std::nullopt) :
40✔
61
            m_psk(std::move(psk)), m_psk_identity(std::move(psk_identity)) {
42✔
62
         if(ca_path.empty() == false) {
40✔
63
            m_certstores.push_back(std::make_shared<Botan::Certificate_Store_In_Memory>(ca_path));
4✔
64
         }
65

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

69
         if(client_crt.has_value() && client_key.has_value()) {
40✔
70
            load_credentials(client_crt.value(), client_key.value());
×
71
         }
72

73
#if defined(BOTAN_HAS_CERTSTOR_SYSTEM)
74
         if(use_system_store) {
40✔
75
            m_certstores.push_back(std::make_shared<Botan::System_Certificate_Store>());
40✔
76
         }
77
#else
78
         BOTAN_UNUSED(use_system_store);
79
#endif
80
      }
40✔
81

82
      Basic_Credentials_Manager(const std::string& server_crt,
39✔
83
                                const std::string& server_key,
84
                                std::optional<Botan::secure_vector<uint8_t>> psk = std::nullopt,
85
                                std::optional<std::string> psk_identity = std::nullopt) :
39✔
86
            m_psk(std::move(psk)), m_psk_identity(std::move(psk_identity)) {
41✔
87
         load_credentials(server_crt, server_key);
39✔
88
      }
39✔
89

90
      std::vector<Botan::Certificate_Store*> trusted_certificate_authorities(const std::string& type,
87✔
91
                                                                             const std::string& /*hostname*/) override {
92
         std::vector<Botan::Certificate_Store*> v;
87✔
93

94
         // don't ask for client certs
95
         if(type == "tls-server") {
87✔
96
            return v;
97
         }
98

99
         for(const auto& cs : m_certstores) {
81✔
100
            v.push_back(cs.get());
42✔
101
         }
102

103
         return v;
104
      }
×
105

106
      std::vector<Botan::X509_Certificate> find_cert_chain(
112✔
107
         const std::vector<std::string>& algos,
108
         const std::vector<Botan::AlgorithmIdentifier>& cert_signature_schemes,
109
         const std::vector<Botan::X509_DN>& acceptable_cas,
110
         const std::string& type,
111
         const std::string& hostname) override {
112
         BOTAN_UNUSED(cert_signature_schemes);
112✔
113

114
         if(type == "tls-client") {
112✔
115
            for(const auto& dn : acceptable_cas) {
×
116
               for(const auto& cred : m_creds) {
×
117
                  if(dn == cred.certs[0].issuer_dn()) {
×
118
                     return cred.certs;
×
119
                  }
120
               }
121
            }
122
         } else if(type == "tls-server") {
112✔
123
            for(const auto& i : m_creds) {
176✔
124
               if(std::find(algos.begin(), algos.end(), i.key->algo_name()) == algos.end()) {
112✔
125
                  continue;
64✔
126
               }
127

128
               if(!hostname.empty() && !i.certs[0].matches_dns_name(hostname)) {
48✔
129
                  continue;
×
130
               }
131

132
               return i.certs;
48✔
133
            }
134
         }
135

136
         return {};
64✔
137
      }
138

139
      std::shared_ptr<Botan::Private_Key> private_key_for(const Botan::X509_Certificate& cert,
47✔
140
                                                          const std::string& /*type*/,
141
                                                          const std::string& /*context*/) override {
142
         for(const auto& i : m_creds) {
47✔
143
            if(cert == i.certs[0]) {
47✔
144
               return i.key;
47✔
145
            }
146
         }
147

148
         return nullptr;
×
149
      }
150

151
      std::string psk_identity(const std::string& type,
1✔
152
                               const std::string& context,
153
                               const std::string& identity_hint) override {
154
         return (m_psk_identity && (type == "tls-client" || type == "tls-server"))
1✔
155
                   ? m_psk_identity.value()
2✔
156
                   : Botan::Credentials_Manager::psk_identity(type, context, identity_hint);
×
157
      }
158

159
      std::vector<Botan::TLS::ExternalPSK> find_preshared_keys(
2✔
160
         std::string_view host,
161
         Botan::TLS::Connection_Side peer_type,
162
         const std::vector<std::string>& ids = {},
163
         const std::optional<std::string>& prf = std::nullopt) override {
164
         if(!m_psk.has_value() || !m_psk_identity.has_value()) {
2✔
165
            return Botan::Credentials_Manager::find_preshared_keys(host, peer_type, ids, prf);
×
166
         }
167

168
         std::vector<Botan::TLS::ExternalPSK> psks;
2✔
169

170
         const bool prf_matches = !prf.has_value() || m_psk_prf == prf.value();
2✔
171
         const bool id_matches = ids.empty() || std::find(ids.begin(), ids.end(), m_psk_identity.value()) != ids.end();
2✔
172

173
         if(prf_matches && id_matches) {
2✔
174
            psks.emplace_back(m_psk_identity.value(), m_psk_prf, m_psk.value());
2✔
175
         }
176

177
         return psks;
2✔
178
      }
2✔
179

180
   private:
181
      struct Certificate_Info {
78✔
182
            std::vector<Botan::X509_Certificate> certs;
183
            std::shared_ptr<Botan::Private_Key> key;
184
      };
185

186
      std::vector<Certificate_Info> m_creds;
187
      std::vector<std::shared_ptr<Botan::Certificate_Store>> m_certstores;
188
      std::optional<Botan::secure_vector<uint8_t>> m_psk;
189
      std::optional<std::string> m_psk_identity;
190
      std::string m_psk_prf;
191
};
192

193
class TLS_All_Policy final : public Botan::TLS::Policy {
2✔
194
   public:
195
      std::vector<std::string> allowed_ciphers() const override {
90✔
196
         return std::vector<std::string>{"ChaCha20Poly1305",
90✔
197
                                         "AES-256/OCB(12)",
198
                                         "AES-128/OCB(12)",
199
                                         "AES-256/GCM",
200
                                         "AES-128/GCM",
201
                                         "AES-256/CCM",
202
                                         "AES-128/CCM",
203
                                         "AES-256/CCM(8)",
204
                                         "AES-128/CCM(8)",
205
                                         "Camellia-256/GCM",
206
                                         "Camellia-128/GCM",
207
                                         "ARIA-256/GCM",
208
                                         "ARIA-128/GCM",
209
                                         "AES-256",
210
                                         "AES-128",
211
                                         "Camellia-256",
212
                                         "Camellia-128",
213
                                         "SEED",
214
                                         "3DES"};
1,800✔
215
      }
216

217
      std::vector<std::string> allowed_key_exchange_methods() const override {
1✔
218
         return {"ECDHE_PSK", "DHE_PSK", "PSK", "ECDH", "DH", "RSA"};
7✔
219
      }
220

221
      std::vector<std::string> allowed_signature_methods() const override {
1✔
222
         return {"ECDSA", "RSA", "DSA", "IMPLICIT"};
5✔
223
      }
224

225
      bool allow_tls12() const override { return true; }
1✔
226
};
227

228
inline std::shared_ptr<Botan::TLS::Policy> load_tls_policy(const std::string& policy_type) {
12✔
229
   if(policy_type == "default" || policy_type.empty()) {
12✔
230
      return std::make_shared<Botan::TLS::Policy>();
3✔
231
   } else if(policy_type == "suiteb_128") {
9✔
232
      return std::make_shared<Botan::TLS::NSA_Suite_B_128>();
1✔
233
   } else if(policy_type == "suiteb_192" || policy_type == "suiteb") {
8✔
234
      return std::make_shared<Botan::TLS::NSA_Suite_B_192>();
1✔
235
   } else if(policy_type == "strict") {
7✔
236
      return std::make_shared<Botan::TLS::Strict_Policy>();
1✔
237
   } else if(policy_type == "bsi") {
6✔
238
      return std::make_shared<Botan::TLS::BSI_TR_02102_2>();
×
239
   } else if(policy_type == "datagram") {
6✔
240
      return std::make_shared<Botan::TLS::Strict_Policy>();
×
241
   } else if(policy_type == "all" || policy_type == "everything") {
6✔
242
      return std::make_shared<TLS_All_Policy>();
1✔
243
   }
244

245
   // if something we don't recognize, assume it's a file
246
   std::ifstream policy_stream(policy_type);
5✔
247
   if(!policy_stream.good()) {
5✔
248
      throw Botan_CLI::CLI_Usage_Error("Unknown TLS policy: not a file or known short name");
×
249
   }
250
   return std::make_shared<Botan::TLS::Text_Policy>(policy_stream);
5✔
251
}
5✔
252

253
#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