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

randombit / botan / 5111374265

29 May 2023 11:19AM UTC coverage: 92.227% (+0.5%) from 91.723%
5111374265

push

github

randombit
Next release will be 3.1.0. Update release notes

75588 of 81959 relevant lines covered (92.23%)

11886470.91 hits per line

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

86.46
/src/lib/tls/tls_callbacks.cpp
1
/*
2
* TLS Callbacks
3
* (C) 2016 Jack Lloyd
4
*     2017 Harry Reimann, Rohde & Schwarz Cybersecurity
5
*     2022 René Meusel, Hannes Rantzsch - neXenio GmbH
6
*     2023 René Meusel - Rohde & Schwarz Cybersecurity
7
*
8
* Botan is released under the Simplified BSD License (see license.txt)
9
*/
10

11
#include <botan/tls_callbacks.h>
12

13
#include <botan/dh.h>
14
#include <botan/dl_group.h>
15
#include <botan/ecdh.h>
16
#include <botan/ocsp.h>
17
#include <botan/tls_algos.h>
18
#include <botan/tls_exceptn.h>
19
#include <botan/tls_policy.h>
20
#include <botan/x509path.h>
21
#include <botan/internal/ct_utils.h>
22
#include <botan/internal/stl_util.h>
23

24
#if defined(BOTAN_HAS_CURVE_25519)
25
   #include <botan/curve25519.h>
26
#endif
27

28
namespace Botan {
29

30
void TLS::Callbacks::tls_inspect_handshake_msg(const Handshake_Message& /*unused*/) {
6,321✔
31
   // default is no op
32
}
6,321✔
33

34
std::string TLS::Callbacks::tls_server_choose_app_protocol(const std::vector<std::string>& /*unused*/) { return ""; }
×
35

36
std::string TLS::Callbacks::tls_peer_network_identity() { return ""; }
734✔
37

38
std::chrono::system_clock::time_point TLS::Callbacks::tls_current_timestamp() {
5,078✔
39
   return std::chrono::system_clock::now();
5,078✔
40
}
41

42
void TLS::Callbacks::tls_modify_extensions(Extensions& /*unused*/,
5,567✔
43
                                           Connection_Side /*unused*/,
44
                                           Handshake_Type /*unused*/) {}
5,567✔
45

46
void TLS::Callbacks::tls_examine_extensions(const Extensions& /*unused*/,
4,080✔
47
                                            Connection_Side /*unused*/,
48
                                            Handshake_Type /*unused*/) {}
4,080✔
49

50
bool TLS::Callbacks::tls_should_persist_resumption_information(const Session& session) {
2,537✔
51
   // RFC 5077 3.3
52
   //    The ticket_lifetime_hint field contains a hint from the server about
53
   //    how long the ticket should be stored. A value of zero is reserved to
54
   //    indicate that the lifetime of the ticket is unspecified.
55
   //
56
   // RFC 8446 4.6.1
57
   //    [A ticket_lifetime] of zero indicates that the ticket should be discarded
58
   //    immediately.
59
   //
60
   // By default we opt to keep all sessions, except for TLS 1.3 with a lifetime
61
   // hint of zero.
62
   return session.lifetime_hint().count() > 0 || session.version().is_pre_tls_13();
2,537✔
63
}
64

65
void TLS::Callbacks::tls_verify_cert_chain(const std::vector<X509_Certificate>& cert_chain,
104✔
66
                                           const std::vector<std::optional<OCSP::Response>>& ocsp_responses,
67
                                           const std::vector<Certificate_Store*>& trusted_roots,
68
                                           Usage_Type usage,
69
                                           std::string_view hostname,
70
                                           const TLS::Policy& policy) {
71
   if(cert_chain.empty())
104✔
72
      throw Invalid_Argument("Certificate chain was empty");
×
73

74
   Path_Validation_Restrictions restrictions(policy.require_cert_revocation_info(),
104✔
75
                                             policy.minimum_signature_strength());
312✔
76

77
   Path_Validation_Result result = x509_path_validate(cert_chain,
104✔
78
                                                      restrictions,
79
                                                      trusted_roots,
80
                                                      (usage == Usage_Type::TLS_SERVER_AUTH ? hostname : ""),
81
                                                      usage,
82
                                                      tls_current_timestamp(),
104✔
83
                                                      tls_verify_cert_chain_ocsp_timeout(),
104✔
84
                                                      ocsp_responses);
107✔
85

86
   if(!result.successful_validation()) {
104✔
87
      throw TLS_Exception(Alert::BadCertificate, "Certificate validation failure: " + result.result_string());
×
88
   }
89
}
104✔
90

91
std::optional<OCSP::Response> TLS::Callbacks::tls_parse_ocsp_response(const std::vector<uint8_t>& raw_response) {
×
92
   try {
×
93
      return OCSP::Response(raw_response);
×
94
   } catch(const Decoding_Error&) {
×
95
      // ignore parsing errors and just ignore the broken OCSP response
96
      return std::nullopt;
×
97
   }
×
98
}
99

100
std::vector<std::vector<uint8_t>> TLS::Callbacks::tls_provide_cert_chain_status(
245✔
101
   const std::vector<X509_Certificate>& chain, const Certificate_Status_Request& csr) {
102
   std::vector<std::vector<uint8_t>> result(chain.size());
245✔
103
   if(!chain.empty()) {
245✔
104
      result[0] = tls_provide_cert_status(chain, csr);
245✔
105
   }
106
   return result;
237✔
107
}
8✔
108

109
std::vector<uint8_t> TLS::Callbacks::tls_sign_message(const Private_Key& key,
916✔
110
                                                      RandomNumberGenerator& rng,
111
                                                      std::string_view padding,
112
                                                      Signature_Format format,
113
                                                      const std::vector<uint8_t>& msg) {
114
   PK_Signer signer(key, rng, padding, format);
916✔
115

116
   return signer.sign_message(msg, rng);
1,831✔
117
}
916✔
118

119
bool TLS::Callbacks::tls_verify_message(const Public_Key& key,
1,126✔
120
                                        std::string_view padding,
121
                                        Signature_Format format,
122
                                        const std::vector<uint8_t>& msg,
123
                                        const std::vector<uint8_t>& sig) {
124
   PK_Verifier verifier(key, padding, format);
1,126✔
125

126
   return verifier.verify_message(msg, sig);
2,252✔
127
}
1,126✔
128

129
namespace {
130

131
bool is_dh_group(const std::variant<TLS::Group_Params, DL_Group>& group) {
4,574✔
132
   return std::holds_alternative<DL_Group>(group) || is_dh(std::get<TLS::Group_Params>(group));
9,132✔
133
}
134

135
DL_Group get_dl_group(const std::variant<TLS::Group_Params, DL_Group>& group) {
20✔
136
   BOTAN_ASSERT_NOMSG(is_dh_group(group));
20✔
137

138
   // TLS 1.2 allows specifying arbitrary DL_Group parameters in-lieu of
139
   // a standardized DH group identifier. TLS 1.3 just offers pre-defined
140
   // groups.
141
   return std::visit(
20✔
142
      overloaded{[](const DL_Group& dl_group) { return dl_group; },
8✔
143
                 [&](TLS::Group_Params group_param) { return DL_Group(group_param_to_string(group_param)); }},
24✔
144
      group);
20✔
145
}
146

147
}  // namespace
148

149
std::unique_ptr<PK_Key_Agreement_Key> TLS::Callbacks::tls_generate_ephemeral_key(
2,574✔
150
   const std::variant<TLS::Group_Params, DL_Group>& group, RandomNumberGenerator& rng) {
151
   if(is_dh_group(group)) {
2,574✔
152
      const DL_Group dl_group = get_dl_group(group);
12✔
153
      return std::make_unique<DH_PrivateKey>(rng, dl_group);
24✔
154
   }
12✔
155

156
   BOTAN_ASSERT_NOMSG(std::holds_alternative<TLS::Group_Params>(group));
2,562✔
157
   const auto group_params = std::get<TLS::Group_Params>(group);
2,562✔
158

159
   if(is_ecdh(group_params)) {
2,562✔
160
      const EC_Group ec_group(group_param_to_string(group_params));
302✔
161
      return std::make_unique<ECDH_PrivateKey>(rng, ec_group);
604✔
162
   }
302✔
163

164
#if defined(BOTAN_HAS_CURVE_25519)
165
   if(is_x25519(group_params)) {
2,260✔
166
      return std::make_unique<X25519_PrivateKey>(rng);
4,520✔
167
   }
168
#endif
169

170
   throw TLS_Exception(Alert::DecodeError, "cannot create a key offering without a group definition");
×
171
}
172

173
secure_vector<uint8_t> TLS::Callbacks::tls_ephemeral_key_agreement(
1,980✔
174
   const std::variant<TLS::Group_Params, DL_Group>& group,
175
   const PK_Key_Agreement_Key& private_key,
176
   const std::vector<uint8_t>& public_value,
177
   RandomNumberGenerator& rng,
178
   const Policy& policy) {
179
   auto agree = [&](const PK_Key_Agreement_Key& sk, const auto& pk) {
3,956✔
180
      PK_Key_Agreement ka(sk, rng, "Raw");
1,976✔
181
      return ka.derive_key(0, pk.public_value()).bits_of();
5,928✔
182
   };
3,956✔
183

184
   if(is_dh_group(group)) {
1,980✔
185
      // TLS 1.2 allows specifying arbitrary DL_Group parameters in-lieu of
186
      // a standardized DH group identifier.
187
      const auto dl_group = get_dl_group(group);
8✔
188

189
      auto Y = BigInt::decode(public_value);
8✔
190

191
      /*
192
       * A basic check for key validity. As we do not know q here we
193
       * cannot check that Y is in the right subgroup. However since
194
       * our key is ephemeral there does not seem to be any
195
       * advantage to bogus keys anyway.
196
       */
197
      if(Y <= 1 || Y >= dl_group.get_p() - 1)
16✔
198
         throw TLS_Exception(Alert::IllegalParameter, "Server sent bad DH key for DHE exchange");
×
199

200
      DH_PublicKey peer_key(dl_group, Y);
8✔
201
      policy.check_peer_key_acceptable(peer_key);
8✔
202

203
      return agree(private_key, peer_key);
8✔
204
   }
24✔
205

206
   BOTAN_ASSERT_NOMSG(std::holds_alternative<TLS::Group_Params>(group));
1,972✔
207
   const auto group_params = std::get<TLS::Group_Params>(group);
1,972✔
208

209
   if(is_ecdh(group_params)) {
1,972✔
210
      const EC_Group ec_group(group_param_to_string(group_params));
231✔
211
      ECDH_PublicKey peer_key(ec_group, ec_group.OS2ECP(public_value));
462✔
212
      policy.check_peer_key_acceptable(peer_key);
227✔
213

214
      return agree(private_key, peer_key);
227✔
215
   }
231✔
216

217
#if defined(BOTAN_HAS_CURVE_25519)
218
   if(is_x25519(group_params)) {
1,741✔
219
      if(public_value.size() != 32) {
1,741✔
220
         throw TLS_Exception(Alert::HandshakeFailure, "Invalid X25519 key size");
×
221
      }
222

223
      Curve25519_PublicKey peer_key(public_value);
1,741✔
224
      policy.check_peer_key_acceptable(peer_key);
1,741✔
225

226
      return agree(private_key, peer_key);
1,741✔
227
   }
1,741✔
228
#endif
229

230
   throw TLS_Exception(Alert::IllegalParameter, "Did not recognize the key exchange group");
×
231
}
232

233
}  // namespace Botan
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

© 2026 Coveralls, Inc