Coverage Report

Created: 2025-04-11 06:34

/src/botan/src/lib/tls/tls13/msg_certificate_13.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* Certificate Message
3
* (C) 2022 Jack Lloyd
4
*     2022 Hannes Rantzsch, René Meusel - neXenio GmbH
5
*     2023 René Meusel, Fabian Albert - Rohde & Schwarz Cybersecurity
6
*
7
* Botan is released under the Simplified BSD License (see license.txt)
8
*/
9
10
#include <botan/tls_messages.h>
11
12
#include <botan/credentials_manager.h>
13
#include <botan/data_src.h>
14
#include <botan/ocsp.h>
15
#include <botan/tls_alert.h>
16
#include <botan/tls_callbacks.h>
17
#include <botan/tls_exceptn.h>
18
#include <botan/tls_extensions.h>
19
#include <botan/x509_key.h>
20
#include <botan/internal/loadstor.h>
21
#include <botan/internal/stl_util.h>
22
#include <botan/internal/tls_handshake_hash.h>
23
#include <botan/internal/tls_handshake_io.h>
24
#include <botan/internal/tls_reader.h>
25
26
#include <iterator>
27
#include <memory>
28
29
namespace Botan::TLS {
30
31
namespace {
32
33
0
bool certificate_allows_signing(const X509_Certificate& cert) {
34
0
   const auto constraints = cert.constraints();
35
0
   if(constraints.empty()) {
36
0
      return true;
37
0
   }
38
39
0
   return constraints.includes_any(Key_Constraints::DigitalSignature, Key_Constraints::NonRepudiation);
40
0
}
41
42
0
std::vector<std::string> filter_signature_schemes(const std::vector<Signature_Scheme>& peer_scheme_preference) {
43
0
   std::vector<std::string> compatible_schemes;
44
0
   for(const auto& scheme : peer_scheme_preference) {
45
0
      if(scheme.is_available() && scheme.is_compatible_with(Protocol_Version::TLS_V13)) {
46
0
         compatible_schemes.push_back(scheme.algorithm_name());
47
0
      }
48
0
   }
49
50
0
   if(compatible_schemes.empty()) {
51
0
      throw TLS_Exception(Alert::HandshakeFailure, "Failed to agree on any signature algorithm");
52
0
   }
53
54
0
   return compatible_schemes;
55
0
}
56
57
}  // namespace
58
59
0
bool Certificate_13::has_certificate_chain() const {
60
0
   return !empty() && m_entries.front().has_certificate();
61
0
}
62
63
0
bool Certificate_13::is_raw_public_key() const {
64
0
   return !empty() && !has_certificate_chain();
65
0
}
66
67
0
std::vector<X509_Certificate> Certificate_13::cert_chain() const {
68
0
   BOTAN_STATE_CHECK(has_certificate_chain());
69
0
   std::vector<X509_Certificate> result;
70
0
   std::transform(m_entries.cbegin(), m_entries.cend(), std::back_inserter(result), [](const auto& cert_entry) {
71
0
      return cert_entry.certificate();
72
0
   });
73
0
   return result;
74
0
}
75
76
0
void Certificate_13::validate_extensions(const std::set<Extension_Code>& requested_extensions, Callbacks& cb) const {
77
   // RFC 8446 4.4.2
78
   //    Extensions in the Certificate message from the server MUST
79
   //    correspond to ones from the ClientHello message.  Extensions in
80
   //    the Certificate message from the client MUST correspond to
81
   //    extensions in the CertificateRequest message from the server.
82
0
   for(const auto& entry : m_entries) {
83
0
      if(entry.extensions().contains_other_than(requested_extensions)) {
84
0
         throw TLS_Exception(Alert::IllegalParameter, "Certificate Entry contained an extension that was not offered");
85
0
      }
86
87
0
      cb.tls_examine_extensions(entry.extensions(), m_side, type());
88
0
   }
89
0
}
90
91
0
std::shared_ptr<const Public_Key> Certificate_13::public_key() const {
92
0
   BOTAN_STATE_CHECK(!empty());
93
0
   return m_entries.front().public_key();
94
0
}
95
96
0
const X509_Certificate& Certificate_13::leaf() const {
97
0
   BOTAN_STATE_CHECK(!empty());
98
0
   return m_entries.front().certificate();
99
0
}
100
101
void Certificate_13::verify(Callbacks& callbacks,
102
                            const Policy& policy,
103
                            Credentials_Manager& creds,
104
                            std::string_view hostname,
105
0
                            bool use_ocsp) const {
106
0
   const auto usage = (m_side == Connection_Side::Client) ? Usage_Type::TLS_CLIENT_AUTH : Usage_Type::TLS_SERVER_AUTH;
107
108
0
   if(is_raw_public_key()) {
109
0
      callbacks.tls_verify_raw_public_key(*public_key(), usage, hostname, policy);
110
0
   } else {
111
0
      verify_certificate_chain(callbacks, policy, creds, hostname, use_ocsp, usage);
112
0
   }
113
0
}
114
115
void Certificate_13::verify_certificate_chain(Callbacks& callbacks,
116
                                              const Policy& policy,
117
                                              Credentials_Manager& creds,
118
                                              std::string_view hostname,
119
                                              bool use_ocsp,
120
0
                                              Usage_Type usage_type) const {
121
0
   std::vector<X509_Certificate> certs;
122
0
   std::vector<std::optional<OCSP::Response>> ocsp_responses;
123
0
   for(const auto& entry : m_entries) {
124
0
      certs.push_back(entry.certificate());
125
0
      if(use_ocsp) {
126
0
         if(entry.extensions().has<Certificate_Status_Request>()) {
127
0
            ocsp_responses.push_back(callbacks.tls_parse_ocsp_response(
128
0
               entry.extensions().get<Certificate_Status_Request>()->get_ocsp_response()));
129
0
         } else {
130
0
            ocsp_responses.emplace_back();
131
0
         }
132
0
      }
133
0
   }
134
135
0
   const auto& server_cert = m_entries.front().certificate();
136
0
   if(!certificate_allows_signing(server_cert)) {
137
0
      throw TLS_Exception(Alert::BadCertificate, "Certificate usage constraints do not allow signing");
138
0
   }
139
140
   // Note that m_side represents the sender, so the usages here are swapped
141
0
   const auto trusted_CAs = creds.trusted_certificate_authorities(
142
0
      m_side == Connection_Side::Client ? "tls-server" : "tls-client", std::string(hostname));
143
144
0
   callbacks.tls_verify_cert_chain(certs, ocsp_responses, trusted_CAs, usage_type, hostname, policy);
145
0
}
146
147
void Certificate_13::setup_entries(std::vector<X509_Certificate> cert_chain,
148
                                   const Certificate_Status_Request* csr,
149
0
                                   Callbacks& callbacks) {
150
   // RFC 8446 4.4.2.1
151
   //    A server MAY request that a client present an OCSP response with its
152
   //    certificate by sending an empty "status_request" extension in its
153
   //    CertificateRequest message.
154
0
   const auto ocsp_responses = (csr != nullptr) ? callbacks.tls_provide_cert_chain_status(cert_chain, *csr)
155
0
                                                : std::vector<std::vector<uint8_t>>(cert_chain.size());
156
157
0
   if(ocsp_responses.size() != cert_chain.size()) {
158
0
      throw TLS_Exception(Alert::InternalError, "Application didn't provide the correct number of OCSP responses");
159
0
   }
160
161
0
   for(size_t i = 0; i < cert_chain.size(); ++i) {
162
0
      auto& entry = m_entries.emplace_back(cert_chain[i]);
163
0
      if(!ocsp_responses[i].empty()) {
164
0
         entry.extensions().add(new Certificate_Status_Request(ocsp_responses[i]));
165
0
      }
166
167
      // This will call the modification callback multiple times. Once for
168
      // each certificate in the `cert_chain`. Users that want to add an
169
      // extension to a specific Certificate Entry might have a hard time
170
      // to distinguish them.
171
      //
172
      // TODO: Callbacks::tls_modify_extensions() might need even more
173
      //       context depending on the message whose extensions should be
174
      //       manipulatable.
175
0
      callbacks.tls_modify_extensions(entry.extensions(), m_side, type());
176
0
   }
177
0
}
178
179
0
void Certificate_13::setup_entry(std::shared_ptr<Public_Key> raw_public_key, Callbacks& callbacks) {
180
0
   BOTAN_ASSERT_NONNULL(raw_public_key);
181
0
   auto& entry = m_entries.emplace_back(std::move(raw_public_key));
182
0
   callbacks.tls_modify_extensions(entry.extensions(), m_side, type());
183
0
}
184
185
/**
186
 * Create a Client Certificate message
187
 */
188
Certificate_13::Certificate_13(const Certificate_Request_13& cert_request,
189
                               std::string_view hostname,
190
                               Credentials_Manager& credentials_manager,
191
                               Callbacks& callbacks,
192
                               Certificate_Type cert_type) :
193
0
      m_request_context(cert_request.context()), m_side(Connection_Side::Client) {
194
0
   const auto key_types = filter_signature_schemes(cert_request.signature_schemes());
195
0
   const auto op_type = "tls-client";
196
197
0
   if(cert_type == Certificate_Type::X509) {
198
0
      setup_entries(
199
0
         credentials_manager.find_cert_chain(key_types,
200
0
                                             to_algorithm_identifiers(cert_request.certificate_signature_schemes()),
201
0
                                             cert_request.acceptable_CAs(),
202
0
                                             op_type,
203
0
                                             std::string(hostname)),
204
0
         cert_request.extensions().get<Certificate_Status_Request>(),
205
0
         callbacks);
206
0
   } else if(cert_type == Certificate_Type::RawPublicKey) {
207
0
      auto raw_public_key = credentials_manager.find_raw_public_key(key_types, op_type, std::string(hostname));
208
209
      // RFC 8446 4.4.2
210
      //     If the RawPublicKey certificate type was negotiated, then the
211
      //     certificate_list MUST contain no more than one CertificateEntry
212
      //     [...].
213
      //     A client will send an empty certificate_list if it does not have
214
      //     an appropriate certificate to send in response to the server's
215
      //     authentication request.
216
0
      if(raw_public_key) {
217
0
         setup_entry(std::move(raw_public_key), callbacks);
218
0
      }
219
0
   }
220
0
}
221
222
/**
223
 * Create a Server Certificate message
224
 */
225
Certificate_13::Certificate_13(const Client_Hello_13& client_hello,
226
                               Credentials_Manager& credentials_manager,
227
                               Callbacks& callbacks,
228
                               Certificate_Type cert_type) :
229
      // RFC 8446 4.4.2:
230
      //    [In the case of server authentication], this field
231
      //    SHALL be zero length
232
0
      m_request_context(), m_side(Connection_Side::Server) {
233
0
   BOTAN_ASSERT_NOMSG(client_hello.extensions().has<Signature_Algorithms>());
234
235
0
   const auto key_types = filter_signature_schemes(client_hello.signature_schemes());
236
0
   const auto op_type = "tls-server";
237
0
   const auto context = client_hello.sni_hostname();
238
239
0
   if(cert_type == Certificate_Type::X509) {
240
0
      auto cert_chain = credentials_manager.find_cert_chain(
241
0
         key_types, to_algorithm_identifiers(client_hello.certificate_signature_schemes()), {}, op_type, context);
242
243
      // RFC 8446 4.4.2
244
      //    The server's certificate_list MUST always be non-empty.
245
0
      if(cert_chain.empty()) {
246
0
         throw TLS_Exception(Alert::HandshakeFailure, "No sufficient server certificate available");
247
0
      }
248
249
0
      setup_entries(std::move(cert_chain), client_hello.extensions().get<Certificate_Status_Request>(), callbacks);
250
0
   } else if(cert_type == Certificate_Type::RawPublicKey) {
251
0
      auto raw_public_key = credentials_manager.find_raw_public_key(key_types, op_type, context);
252
253
      // RFC 8446 4.4.2
254
      //     If the RawPublicKey certificate type was negotiated, then the
255
      //     certificate_list MUST contain no more than one CertificateEntry
256
      //     [...].
257
      //     The server's certificate_list MUST always be non-empty
258
0
      if(!raw_public_key) {
259
0
         throw TLS_Exception(Alert::HandshakeFailure, "No sufficient server raw public key available");
260
0
      }
261
262
0
      setup_entry(std::move(raw_public_key), callbacks);
263
0
   }
264
0
}
265
266
Certificate_13::Certificate_Entry::Certificate_Entry(TLS_Data_Reader& reader,
267
                                                     const Connection_Side side,
268
2.40k
                                                     const Certificate_Type cert_type) {
269
2.40k
   switch(cert_type) {
270
2.40k
      case Certificate_Type::X509:
271
         // RFC 8446 4.2.2
272
         //    [...] each CertificateEntry contains a DER-encoded X.509
273
         //    certificate.
274
2.40k
         m_certificate = X509_Certificate(reader.get_tls_length_value(3));
275
2.40k
         m_raw_public_key = m_certificate->subject_public_key();
276
2.40k
         break;
277
0
      case Certificate_Type::RawPublicKey:
278
         // RFC 7250 3.
279
         //    This specification uses raw public keys whereby the already
280
         //    available encoding used in a PKIX certificate in the form of a
281
         //    SubjectPublicKeyInfo structure is reused.
282
0
         m_raw_public_key = X509::load_key(reader.get_tls_length_value(3));
283
0
         break;
284
0
      default:
285
0
         throw TLS_Exception(Alert::InternalError, "Unknown certificate type");
286
2.40k
   }
287
288
   // Extensions are simply tacked at the end of the certificate entry. This
289
   // is a departure from the typical "tag-length-value" in a sense that the
290
   // Extensions deserializer needs the length value of the extensions.
291
0
   const auto extensions_length = reader.peek_uint16_t();
292
0
   const auto exts_buf = reader.get_fixed<uint8_t>(extensions_length + 2);
293
0
   TLS_Data_Reader exts_reader("extensions reader", exts_buf);
294
0
   m_extensions.deserialize(exts_reader, side, Handshake_Type::Certificate);
295
296
0
   if(cert_type == Certificate_Type::X509) {
297
      // RFC 8446 4.4.2
298
      //    Valid extensions for server certificates at present include the
299
      //    OCSP Status extension [RFC6066] and the SignedCertificateTimestamp
300
      //    extension [RFC6962]; future extensions may be defined for this
301
      //    message as well.
302
      //
303
      // RFC 8446 4.4.2.1
304
      //    A server MAY request that a client present an OCSP response with its
305
      //    certificate by sending an empty "status_request" extension in its
306
      //    CertificateRequest message.
307
0
      if(m_extensions.contains_implemented_extensions_other_than({
308
0
            Extension_Code::CertificateStatusRequest,
309
            // Extension_Code::SignedCertificateTimestamp
310
0
         })) {
311
0
         throw TLS_Exception(Alert::IllegalParameter, "Certificate Entry contained an extension that is not allowed");
312
0
      }
313
0
   } else if(m_extensions.contains_implemented_extensions_other_than({})) {
314
0
      throw TLS_Exception(
315
0
         Alert::IllegalParameter,
316
0
         "Certificate Entry holding something else than a certificate contained unexpected extensions");
317
0
   }
318
0
}
319
320
Certificate_13::Certificate_Entry::Certificate_Entry(X509_Certificate cert) :
321
0
      m_certificate(std::move(cert)), m_raw_public_key(m_certificate->subject_public_key()) {}
322
323
Certificate_13::Certificate_Entry::Certificate_Entry(std::shared_ptr<Public_Key> raw_public_key) :
324
0
      m_certificate(std::nullopt), m_raw_public_key(std::move(raw_public_key)) {
325
0
   BOTAN_ASSERT_NONNULL(m_raw_public_key);
326
0
}
327
328
0
const X509_Certificate& Certificate_13::Certificate_Entry::certificate() const {
329
0
   BOTAN_STATE_CHECK(has_certificate());
330
0
   return m_certificate.value();
331
0
}
332
333
0
std::shared_ptr<const Public_Key> Certificate_13::Certificate_Entry::public_key() const {
334
0
   BOTAN_ASSERT_NONNULL(m_raw_public_key);
335
0
   return m_raw_public_key;
336
0
}
337
338
0
std::vector<uint8_t> Certificate_13::Certificate_Entry::serialize() const {
339
0
   return (has_certificate()) ? m_certificate->BER_encode() : X509::BER_encode(*m_raw_public_key);
340
0
}
341
342
/**
343
* Deserialize a Certificate message
344
*/
345
Certificate_13::Certificate_13(const std::vector<uint8_t>& buf,
346
                               const Policy& policy,
347
                               Connection_Side side,
348
                               Certificate_Type cert_type) :
349
2.50k
      m_side(side) {
350
2.50k
   TLS_Data_Reader reader("cert message reader", buf);
351
352
2.50k
   m_request_context = reader.get_range<uint8_t>(1, 0, 255);
353
354
   // RFC 8446 4.4.2
355
   //    [...] in the case of server authentication, this field SHALL be zero length.
356
2.50k
   if(m_side == Connection_Side::Server && !m_request_context.empty()) {
357
13
      throw TLS_Exception(Alert::IllegalParameter, "Server Certificate message must not contain a request context");
358
13
   }
359
360
2.49k
   const auto cert_entries_len = reader.get_uint24_t();
361
362
2.49k
   if(reader.remaining_bytes() != cert_entries_len) {
363
73
      throw TLS_Exception(Alert::DecodeError, "Certificate: Message malformed");
364
73
   }
365
366
2.42k
   const size_t max_size = policy.maximum_certificate_chain_size();
367
2.42k
   if(max_size > 0 && cert_entries_len > max_size) {
368
0
      throw Decoding_Error("Certificate chain exceeds policy specified maximum size");
369
0
   }
370
371
4.82k
   while(reader.has_remaining()) {
372
2.40k
      m_entries.emplace_back(reader, side, cert_type);
373
2.40k
   }
374
375
   // RFC 8446 4.4.2
376
   //    The server's certificate_list MUST always be non-empty.  A client
377
   //    will send an empty certificate_list if it does not have an
378
   //    appropriate certificate to send in response to the server's
379
   //    authentication request.
380
2.42k
   if(m_entries.empty()) {
381
      // RFC 8446 4.4.2.4
382
      //    If the server supplies an empty Certificate message, the client MUST
383
      //    abort the handshake with a "decode_error" alert.
384
3
      if(m_side == Connection_Side::Server) {
385
1
         throw TLS_Exception(Alert::DecodeError, "No certificates sent by server");
386
1
      }
387
388
2
      return;
389
3
   }
390
391
2.41k
   BOTAN_ASSERT_NOMSG(!m_entries.empty());
392
393
   // RFC 8446 4.4.2.2
394
   //    The certificate type MUST be X.509v3 [RFC5280], unless explicitly
395
   //    negotiated otherwise (e.g., [RFC7250]).
396
   //
397
   // TLS 1.0 through 1.3 all seem to require that the certificate be
398
   // precisely a v3 certificate. In fact the strict wording would seem
399
   // to require that every certificate in the chain be v3. But often
400
   // the intermediates are outside of the control of the server.
401
   // But, require that the leaf certificate be v3.
402
2.41k
   if(cert_type == Certificate_Type::X509 && m_entries.front().certificate().x509_version() != 3) {
403
0
      throw TLS_Exception(Alert::BadCertificate, "The leaf certificate must be v3");
404
0
   }
405
406
   // RFC 8446 4.4.2
407
   //    If the RawPublicKey certificate type was negotiated, then the
408
   //    certificate_list MUST contain no more than one CertificateEntry.
409
2.41k
   if(cert_type == Certificate_Type::RawPublicKey && m_entries.size() != 1) {
410
0
      throw TLS_Exception(Alert::IllegalParameter, "Certificate message contained more than one RawPublicKey");
411
0
   }
412
413
   // Validate the provided (certificate) public key against our policy
414
2.41k
   auto pubkey = public_key();
415
2.41k
   policy.check_peer_key_acceptable(*pubkey);
416
417
2.41k
   if(!policy.allowed_signature_method(pubkey->algo_name())) {
418
0
      throw TLS_Exception(Alert::HandshakeFailure, "Rejecting " + pubkey->algo_name() + " signature");
419
0
   }
420
2.41k
}
421
422
/**
423
* Serialize a Certificate message
424
*/
425
0
std::vector<uint8_t> Certificate_13::serialize() const {
426
0
   std::vector<uint8_t> buf;
427
428
0
   append_tls_length_value(buf, m_request_context, 1);
429
430
0
   std::vector<uint8_t> entries;
431
0
   for(const auto& entry : m_entries) {
432
0
      append_tls_length_value(entries, entry.serialize(), 3);
433
434
      // Extensions are tacked at the end of certificate entries. Note that
435
      // Extensions::serialize() usually emits the required length field,
436
      // except when no extensions are added at all, then it  returns an
437
      // empty buffer.
438
      //
439
      // TODO: look into this issue more generally when overhauling the
440
      //       message marshalling.
441
0
      auto extensions = entry.extensions().serialize(m_side);
442
0
      entries += (!extensions.empty()) ? extensions : std::vector<uint8_t>{0, 0};
443
0
   }
444
445
0
   append_tls_length_value(buf, entries, 3);
446
447
0
   return buf;
448
0
}
449
450
}  // namespace Botan::TLS