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

randombit / botan / 5079590438

25 May 2023 12:28PM UTC coverage: 92.228% (+0.5%) from 91.723%
5079590438

Pull #3502

github

Pull Request #3502: Apply clang-format to the codebase

75589 of 81959 relevant lines covered (92.23%)

12139530.51 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,273✔
31
   // default is no op
32
}
6,273✔
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,071✔
39
   return std::chrono::system_clock::now();
5,071✔
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,
99✔
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())
99✔
72
      throw Invalid_Argument("Certificate chain was empty");
×
73

74
   Path_Validation_Restrictions restrictions(policy.require_cert_revocation_info(),
99✔
75
                                             policy.minimum_signature_strength());
297✔
76

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

86
   if(!result.successful_validation()) {
99✔
87
      throw TLS_Exception(Alert::BadCertificate, "Certificate validation failure: " + result.result_string());
×
88
   }
89
}
99✔
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,
912✔
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);
912✔
115

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

119
bool TLS::Callbacks::tls_verify_message(const Public_Key& key,
1,122✔
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,122✔
125

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

129
namespace {
130

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

135
DL_Group get_dl_group(const std::variant<TLS::Group_Params, DL_Group>& group) {
24✔
136
   BOTAN_ASSERT_NOMSG(is_dh_group(group));
24✔
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(
24✔
142
      overloaded{[](const DL_Group& dl_group) { return dl_group; },
10✔
143
                 [&](TLS::Group_Params group_param) { return DL_Group(group_param_to_string(group_param)); }},
28✔
144
      group);
24✔
145
}
146

147
}
148

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

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

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

164
#if defined(BOTAN_HAS_CURVE_25519)
165
   if(is_x25519(group_params)) {
2,252✔
166
      return std::make_unique<X25519_PrivateKey>(rng);
4,504✔
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,972✔
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,940✔
180
      PK_Key_Agreement ka(sk, rng, "Raw");
1,968✔
181
      return ka.derive_key(0, pk.public_value()).bits_of();
5,904✔
182
   };
3,940✔
183

184
   if(is_dh_group(group)) {
1,972✔
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);
10✔
188

189
      auto Y = BigInt::decode(public_value);
10✔
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)
20✔
198
         throw TLS_Exception(Alert::IllegalParameter, "Server sent bad DH key for DHE exchange");
×
199

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

203
      return agree(private_key, peer_key);
10✔
204
   }
30✔
205

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

209
   if(is_ecdh(group_params)) {
1,962✔
210
      const EC_Group ec_group(group_param_to_string(group_params));
229✔
211
      ECDH_PublicKey peer_key(ec_group, ec_group.OS2ECP(public_value));
458✔
212
      policy.check_peer_key_acceptable(peer_key);
225✔
213

214
      return agree(private_key, peer_key);
225✔
215
   }
229✔
216

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

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

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

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

233
}
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