Coverage Report

Created: 2022-06-23 06:44

/src/botan/src/lib/tls/tls_callbacks.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* TLS Callbacks
3
* (C) 2016 Jack Lloyd
4
*     2017 Harry Reimann, Rohde & Schwarz Cybersecurity
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8
9
#include <botan/tls_callbacks.h>
10
#include <botan/tls_policy.h>
11
#include <botan/tls_algos.h>
12
#include <botan/x509path.h>
13
#include <botan/ocsp.h>
14
#include <botan/dh.h>
15
#include <botan/ecdh.h>
16
#include <botan/tls_exceptn.h>
17
#include <botan/internal/ct_utils.h>
18
19
#if defined(BOTAN_HAS_CURVE_25519)
20
  #include <botan/curve25519.h>
21
#endif
22
23
namespace Botan {
24
25
void TLS::Callbacks::tls_inspect_handshake_msg(const Handshake_Message& /*unused*/)
26
96.3k
   {
27
   // default is no op
28
96.3k
   }
29
30
std::string TLS::Callbacks::tls_server_choose_app_protocol(const std::vector<std::string>& /*unused*/)
31
0
   {
32
0
   return "";
33
0
   }
34
35
std::string TLS::Callbacks::tls_peer_network_identity()
36
1.17k
   {
37
1.17k
   return "";
38
1.17k
   }
39
40
std::chrono::system_clock::time_point TLS::Callbacks::tls_current_timestamp()
41
41.3k
   {
42
41.3k
   return std::chrono::system_clock::now();
43
41.3k
   }
44
45
void TLS::Callbacks::tls_modify_extensions(Extensions& /*unused*/, Connection_Side /*unused*/)
46
21.2k
   {
47
21.2k
   }
48
49
void TLS::Callbacks::tls_examine_extensions(const Extensions& /*unused*/, Connection_Side /*unused*/)
50
19.9k
   {
51
19.9k
   }
52
53
std::string TLS::Callbacks::tls_decode_group_param(Group_Params group_param)
54
18.2k
   {
55
18.2k
   return group_param_to_string(group_param);
56
18.2k
   }
57
58
void TLS::Callbacks::tls_verify_cert_chain(
59
   const std::vector<X509_Certificate>& cert_chain,
60
   const std::vector<std::optional<OCSP::Response>>& ocsp_responses,
61
   const std::vector<Certificate_Store*>& trusted_roots,
62
   Usage_Type usage,
63
   const std::string& hostname,
64
   const TLS::Policy& policy)
65
0
   {
66
0
   if(cert_chain.empty())
67
0
      throw Invalid_Argument("Certificate chain was empty");
68
69
0
   Path_Validation_Restrictions restrictions(policy.require_cert_revocation_info(),
70
0
                                             policy.minimum_signature_strength());
71
72
0
   Path_Validation_Result result =
73
0
      x509_path_validate(cert_chain,
74
0
                         restrictions,
75
0
                         trusted_roots,
76
0
                         (usage == Usage_Type::TLS_SERVER_AUTH ? hostname : ""),
77
0
                         usage,
78
0
                         tls_current_timestamp(),
79
0
                         tls_verify_cert_chain_ocsp_timeout(),
80
0
                         ocsp_responses);
81
82
0
   if(!result.successful_validation())
83
0
      {
84
0
      throw TLS_Exception(Alert::BAD_CERTIFICATE,
85
0
                          "Certificate validation failure: " + result.result_string());
86
0
      }
87
0
   }
88
89
std::optional<OCSP::Response> TLS::Callbacks::tls_parse_ocsp_response(const std::vector<uint8_t>& raw_response)
90
0
   {
91
0
   try
92
0
      {
93
0
      return OCSP::Response(raw_response);
94
0
      }
95
0
   catch(const Decoding_Error&)
96
0
      {
97
      // ignore parsing errors and just ignore the broken OCSP response
98
0
      return std::nullopt;
99
0
      }
100
0
   }
101
102
std::vector<uint8_t> TLS::Callbacks::tls_sign_message(
103
   const Private_Key& key,
104
   RandomNumberGenerator& rng,
105
   const std::string& emsa,
106
   Signature_Format format,
107
   const std::vector<uint8_t>& msg)
108
0
   {
109
0
   PK_Signer signer(key, rng, emsa, format);
110
111
0
   return signer.sign_message(msg, rng);
112
0
   }
113
114
bool TLS::Callbacks::tls_verify_message(
115
   const Public_Key& key,
116
   const std::string& emsa,
117
   Signature_Format format,
118
   const std::vector<uint8_t>& msg,
119
   const std::vector<uint8_t>& sig)
120
0
   {
121
0
   PK_Verifier verifier(key, emsa, format);
122
123
0
   return verifier.verify_message(msg, sig);
124
0
   }
125
126
std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> TLS::Callbacks::tls_dh_agree(
127
   const std::vector<uint8_t>& modulus,
128
   const std::vector<uint8_t>& generator,
129
   const std::vector<uint8_t>& peer_public_value,
130
   const Policy& policy,
131
   RandomNumberGenerator& rng)
132
0
   {
133
0
   BigInt p = BigInt::decode(modulus);
134
0
   BigInt g = BigInt::decode(generator);
135
0
   BigInt Y = BigInt::decode(peer_public_value);
136
137
   /*
138
    * A basic check for key validity. As we do not know q here we
139
    * cannot check that Y is in the right subgroup. However since
140
    * our key is ephemeral there does not seem to be any
141
    * advantage to bogus keys anyway.
142
    */
143
0
   if(Y <= 1 || Y >= p - 1)
144
0
      throw TLS_Exception(Alert::ILLEGAL_PARAMETER,
145
0
                          "Server sent bad DH key for DHE exchange");
146
147
0
   DL_Group group(p, g);
148
149
0
   if(!group.verify_group(rng, false))
150
0
      throw TLS_Exception(Alert::INSUFFICIENT_SECURITY,
151
0
                          "DH group validation failed");
152
153
0
   DH_PublicKey peer_key(group, Y);
154
155
0
   policy.check_peer_key_acceptable(peer_key);
156
157
0
   DH_PrivateKey priv_key(rng, group);
158
0
   PK_Key_Agreement ka(priv_key, rng, "Raw");
159
0
   secure_vector<uint8_t> dh_secret = CT::strip_leading_zeros(
160
0
      ka.derive_key(0, peer_key.public_value()).bits_of());
161
162
0
   return std::make_pair(dh_secret, priv_key.public_value());
163
0
   }
164
165
std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> TLS::Callbacks::tls_ecdh_agree(
166
   const std::string& curve_name,
167
   const std::vector<uint8_t>& peer_public_value,
168
   const Policy& policy,
169
   RandomNumberGenerator& rng,
170
   bool compressed)
171
0
   {
172
0
   secure_vector<uint8_t> ecdh_secret;
173
0
   std::vector<uint8_t> our_public_value;
174
175
0
   if(curve_name == "x25519")
176
0
      {
177
0
#if defined(BOTAN_HAS_CURVE_25519)
178
0
      if(peer_public_value.size() != 32)
179
0
         {
180
0
         throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Invalid X25519 key size");
181
0
         }
182
183
0
      Curve25519_PublicKey peer_key(peer_public_value);
184
0
      policy.check_peer_key_acceptable(peer_key);
185
0
      Curve25519_PrivateKey priv_key(rng);
186
0
      PK_Key_Agreement ka(priv_key, rng, "Raw");
187
0
      ecdh_secret = ka.derive_key(0, peer_key.public_value()).bits_of();
188
189
      // X25519 is always compressed but sent as "uncompressed" in TLS
190
0
      our_public_value = priv_key.public_value();
191
#else
192
      throw Internal_Error("Negotiated X25519 somehow, but it is disabled");
193
#endif
194
0
      }
195
0
   else
196
0
      {
197
0
      EC_Group group(OID::from_string(curve_name));
198
0
      ECDH_PublicKey peer_key(group, group.OS2ECP(peer_public_value));
199
0
      policy.check_peer_key_acceptable(peer_key);
200
0
      ECDH_PrivateKey priv_key(rng, group);
201
0
      PK_Key_Agreement ka(priv_key, rng, "Raw");
202
0
      ecdh_secret = ka.derive_key(0, peer_key.public_value()).bits_of();
203
0
      our_public_value = priv_key.public_value(compressed ? PointGFp::COMPRESSED : PointGFp::UNCOMPRESSED);
204
0
      }
205
206
0
   return std::make_pair(ecdh_secret, our_public_value);
207
0
   }
208
209
}