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

randombit / botan / 5230455705

10 Jun 2023 02:30PM UTC coverage: 91.715% (-0.03%) from 91.746%
5230455705

push

github

randombit
Merge GH #3584 Change clang-format AllowShortFunctionsOnASingleLine config from All to Inline

77182 of 84154 relevant lines covered (91.72%)

11975295.43 hits per line

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

85.71
/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,309✔
31
   // default is no op
32
}
6,309✔
33

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

38
std::string TLS::Callbacks::tls_peer_network_identity() {
734✔
39
   return "";
734✔
40
}
41

42
std::chrono::system_clock::time_point TLS::Callbacks::tls_current_timestamp() {
5,085✔
43
   return std::chrono::system_clock::now();
5,085✔
44
}
45

46
void TLS::Callbacks::tls_modify_extensions(Extensions& /*unused*/,
5,567✔
47
                                           Connection_Side /*unused*/,
48
                                           Handshake_Type /*unused*/) {}
5,567✔
49

50
void TLS::Callbacks::tls_examine_extensions(const Extensions& /*unused*/,
4,080✔
51
                                            Connection_Side /*unused*/,
52
                                            Handshake_Type /*unused*/) {}
4,080✔
53

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

69
void TLS::Callbacks::tls_verify_cert_chain(const std::vector<X509_Certificate>& cert_chain,
103✔
70
                                           const std::vector<std::optional<OCSP::Response>>& ocsp_responses,
71
                                           const std::vector<Certificate_Store*>& trusted_roots,
72
                                           Usage_Type usage,
73
                                           std::string_view hostname,
74
                                           const TLS::Policy& policy) {
75
   if(cert_chain.empty()) {
103✔
76
      throw Invalid_Argument("Certificate chain was empty");
×
77
   }
78

79
   Path_Validation_Restrictions restrictions(policy.require_cert_revocation_info(),
103✔
80
                                             policy.minimum_signature_strength());
309✔
81

82
   Path_Validation_Result result = x509_path_validate(cert_chain,
103✔
83
                                                      restrictions,
84
                                                      trusted_roots,
85
                                                      (usage == Usage_Type::TLS_SERVER_AUTH ? hostname : ""),
86
                                                      usage,
87
                                                      tls_current_timestamp(),
103✔
88
                                                      tls_verify_cert_chain_ocsp_timeout(),
103✔
89
                                                      ocsp_responses);
106✔
90

91
   if(!result.successful_validation()) {
103✔
92
      throw TLS_Exception(Alert::BadCertificate, "Certificate validation failure: " + result.result_string());
×
93
   }
94
}
103✔
95

96
std::optional<OCSP::Response> TLS::Callbacks::tls_parse_ocsp_response(const std::vector<uint8_t>& raw_response) {
×
97
   try {
×
98
      return OCSP::Response(raw_response);
×
99
   } catch(const Decoding_Error&) {
×
100
      // ignore parsing errors and just ignore the broken OCSP response
101
      return std::nullopt;
×
102
   }
×
103
}
104

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

114
std::vector<uint8_t> TLS::Callbacks::tls_sign_message(const Private_Key& key,
915✔
115
                                                      RandomNumberGenerator& rng,
116
                                                      std::string_view padding,
117
                                                      Signature_Format format,
118
                                                      const std::vector<uint8_t>& msg) {
119
   PK_Signer signer(key, rng, padding, format);
915✔
120

121
   return signer.sign_message(msg, rng);
1,829✔
122
}
915✔
123

124
bool TLS::Callbacks::tls_verify_message(const Public_Key& key,
1,125✔
125
                                        std::string_view padding,
126
                                        Signature_Format format,
127
                                        const std::vector<uint8_t>& msg,
128
                                        const std::vector<uint8_t>& sig) {
129
   PK_Verifier verifier(key, padding, format);
1,125✔
130

131
   return verifier.verify_message(msg, sig);
2,250✔
132
}
1,125✔
133

134
namespace {
135

136
bool is_dh_group(const std::variant<TLS::Group_Params, DL_Group>& group) {
4,570✔
137
   return std::holds_alternative<DL_Group>(group) || is_dh(std::get<TLS::Group_Params>(group));
9,120✔
138
}
139

140
DL_Group get_dl_group(const std::variant<TLS::Group_Params, DL_Group>& group) {
24✔
141
   BOTAN_ASSERT_NOMSG(is_dh_group(group));
24✔
142

143
   // TLS 1.2 allows specifying arbitrary DL_Group parameters in-lieu of
144
   // a standardized DH group identifier. TLS 1.3 just offers pre-defined
145
   // groups.
146
   return std::visit(
24✔
147
      overloaded{[](const DL_Group& dl_group) { return dl_group; },
10✔
148
                 [&](TLS::Group_Params group_param) { return DL_Group(group_param_to_string(group_param)); }},
28✔
149
      group);
24✔
150
}
151

152
}  // namespace
153

154
std::unique_ptr<PK_Key_Agreement_Key> TLS::Callbacks::tls_generate_ephemeral_key(
2,570✔
155
   const std::variant<TLS::Group_Params, DL_Group>& group, RandomNumberGenerator& rng) {
156
   if(is_dh_group(group)) {
2,570✔
157
      const DL_Group dl_group = get_dl_group(group);
14✔
158
      return std::make_unique<DH_PrivateKey>(rng, dl_group);
28✔
159
   }
14✔
160

161
   BOTAN_ASSERT_NOMSG(std::holds_alternative<TLS::Group_Params>(group));
2,556✔
162
   const auto group_params = std::get<TLS::Group_Params>(group);
2,556✔
163

164
   if(is_ecdh(group_params)) {
2,556✔
165
      const EC_Group ec_group(group_param_to_string(group_params));
300✔
166
      return std::make_unique<ECDH_PrivateKey>(rng, ec_group);
600✔
167
   }
300✔
168

169
#if defined(BOTAN_HAS_CURVE_25519)
170
   if(is_x25519(group_params)) {
2,256✔
171
      return std::make_unique<X25519_PrivateKey>(rng);
4,512✔
172
   }
173
#endif
174

175
   throw TLS_Exception(Alert::DecodeError, "cannot create a key offering without a group definition");
×
176
}
177

178
secure_vector<uint8_t> TLS::Callbacks::tls_ephemeral_key_agreement(
1,976✔
179
   const std::variant<TLS::Group_Params, DL_Group>& group,
180
   const PK_Key_Agreement_Key& private_key,
181
   const std::vector<uint8_t>& public_value,
182
   RandomNumberGenerator& rng,
183
   const Policy& policy) {
184
   auto agree = [&](const PK_Key_Agreement_Key& sk, const auto& pk) {
3,948✔
185
      PK_Key_Agreement ka(sk, rng, "Raw");
1,972✔
186
      return ka.derive_key(0, pk.public_value()).bits_of();
5,916✔
187
   };
3,948✔
188

189
   if(is_dh_group(group)) {
1,976✔
190
      // TLS 1.2 allows specifying arbitrary DL_Group parameters in-lieu of
191
      // a standardized DH group identifier.
192
      const auto dl_group = get_dl_group(group);
10✔
193

194
      auto Y = BigInt::decode(public_value);
10✔
195

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

206
      DH_PublicKey peer_key(dl_group, Y);
10✔
207
      policy.check_peer_key_acceptable(peer_key);
10✔
208

209
      return agree(private_key, peer_key);
10✔
210
   }
30✔
211

212
   BOTAN_ASSERT_NOMSG(std::holds_alternative<TLS::Group_Params>(group));
1,966✔
213
   const auto group_params = std::get<TLS::Group_Params>(group);
1,966✔
214

215
   if(is_ecdh(group_params)) {
1,966✔
216
      const EC_Group ec_group(group_param_to_string(group_params));
229✔
217
      ECDH_PublicKey peer_key(ec_group, ec_group.OS2ECP(public_value));
229✔
218
      policy.check_peer_key_acceptable(peer_key);
225✔
219

220
      return agree(private_key, peer_key);
225✔
221
   }
229✔
222

223
#if defined(BOTAN_HAS_CURVE_25519)
224
   if(is_x25519(group_params)) {
1,737✔
225
      if(public_value.size() != 32) {
1,737✔
226
         throw TLS_Exception(Alert::HandshakeFailure, "Invalid X25519 key size");
×
227
      }
228

229
      Curve25519_PublicKey peer_key(public_value);
1,737✔
230
      policy.check_peer_key_acceptable(peer_key);
1,737✔
231

232
      return agree(private_key, peer_key);
1,737✔
233
   }
1,737✔
234
#endif
235

236
   throw TLS_Exception(Alert::IllegalParameter, "Did not recognize the key exchange group");
×
237
}
238

239
}  // 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