Botan 3.13.0
Crypto and TLS for C&
msg_certificate_13.cpp
Go to the documentation of this file.
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_13.h>
11
12#include <botan/credentials_manager.h>
13#include <botan/ocsp.h>
14#include <botan/tls_alert.h>
15#include <botan/tls_callbacks.h>
16#include <botan/tls_exceptn.h>
17#include <botan/tls_extensions.h>
18#include <botan/tls_policy.h>
19#include <botan/x509_key.h>
20#include <botan/internal/stl_util.h>
21#include <botan/internal/tls_reader.h>
22#include <algorithm>
23#include <iterator>
24#include <memory>
25
26namespace Botan::TLS {
27
28namespace {
29
30bool certificate_allows_signing(const X509_Certificate& cert) {
31 const auto constraints = cert.constraints();
32 if(constraints.empty()) {
33 return true;
34 }
35
37}
38
39std::vector<std::string> filter_signature_schemes(const std::vector<Signature_Scheme>& peer_scheme_preference) {
40 std::vector<std::string> compatible_schemes;
41 for(const auto& scheme : peer_scheme_preference) {
42 if(scheme.is_available() && scheme.is_compatible_with(Protocol_Version::TLS_V13)) {
43 const auto algo_name = scheme.algorithm_name();
44 if(!value_exists(compatible_schemes, algo_name)) {
45 compatible_schemes.push_back(algo_name);
46 }
47 }
48 }
49
50 if(compatible_schemes.empty()) {
51 throw TLS_Exception(Alert::HandshakeFailure, "Failed to agree on any signature algorithm");
52 }
53
54 return compatible_schemes;
55}
56
57} // namespace
58
60 return !empty() && m_entries.front().has_certificate();
61}
62
64 return !empty() && !has_certificate_chain();
65}
66
67std::vector<X509_Certificate> Certificate_13::cert_chain() const {
69 std::vector<X509_Certificate> result;
70 std::transform(m_entries.cbegin(), m_entries.cend(), std::back_inserter(result), [](const auto& cert_entry) {
71 return cert_entry.certificate();
72 });
73 return result;
74}
75
76void 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 for(const auto& entry : m_entries) {
83 if(entry.extensions().contains_other_than(requested_extensions)) {
84 throw TLS_Exception(Alert::IllegalParameter, "Certificate Entry contained an extension that was not offered");
85 }
86
87 cb.tls_examine_extensions(entry.extensions(), m_side, type());
88 }
89}
90
91std::shared_ptr<const Public_Key> Certificate_13::public_key() const {
93 return m_entries.front().public_key();
94}
95
98 return m_entries.front().certificate();
99}
100
102 const Policy& policy,
103 Credentials_Manager& creds,
104 std::string_view hostname,
105 bool use_ocsp) const {
107
108 if(is_raw_public_key()) {
109 callbacks.tls_verify_raw_public_key(*public_key(), usage, hostname, policy);
110 } else {
111 verify_certificate_chain(callbacks, policy, creds, hostname, use_ocsp, usage);
112 }
113}
114
115void 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 Usage_Type usage_type) const {
121 std::vector<X509_Certificate> certs;
122 std::vector<std::optional<OCSP::Response>> ocsp_responses;
123 for(const auto& entry : m_entries) {
124 certs.push_back(entry.certificate());
125 if(use_ocsp) {
126 if(entry.extensions().has<Certificate_Status_Request>()) {
127 ocsp_responses.push_back(callbacks.tls_parse_ocsp_response(
128 entry.extensions().get<Certificate_Status_Request>()->get_ocsp_response()));
129 } else {
130 ocsp_responses.emplace_back();
131 }
132 }
133 }
134
135 const auto& server_cert = m_entries.front().certificate();
136 if(!certificate_allows_signing(server_cert)) {
137 throw TLS_Exception(Alert::BadCertificate, "Certificate usage constraints do not allow signing");
138 }
139
140 // Note that m_side represents the sender, so the usages here are swapped
141 const auto trusted_CAs = creds.trusted_certificate_authorities(
142 m_side == Connection_Side::Client ? "tls-server" : "tls-client", std::string(hostname));
143
144 callbacks.tls_verify_cert_chain(certs, ocsp_responses, trusted_CAs, usage_type, hostname, policy);
145}
146
147void Certificate_13::setup_entries(std::vector<X509_Certificate> cert_chain,
149 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 const auto ocsp_responses = (csr != nullptr) ? callbacks.tls_provide_cert_chain_status(cert_chain, *csr)
155 : std::vector<std::vector<uint8_t>>(cert_chain.size());
156
157 if(ocsp_responses.size() != cert_chain.size()) {
158 throw TLS_Exception(Alert::InternalError, "Application didn't provide the correct number of OCSP responses");
159 }
160
161 for(size_t i = 0; i < cert_chain.size(); ++i) {
162 auto& entry = m_entries.emplace_back(cert_chain[i]);
163 if(!ocsp_responses[i].empty()) {
164 entry.extensions().add(new Certificate_Status_Request(ocsp_responses[i])); // NOLINT(*-owning-memory)
165 }
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 callbacks.tls_modify_extensions(entry.extensions(), m_side, type());
176 }
177}
178
179void Certificate_13::setup_entry(std::shared_ptr<Public_Key> raw_public_key, Callbacks& callbacks) {
180 BOTAN_ASSERT_NONNULL(raw_public_key);
181 auto& entry = m_entries.emplace_back(std::move(raw_public_key));
182 callbacks.tls_modify_extensions(entry.extensions(), m_side, type());
183}
184
185/**
186 * Create a Client Certificate message
187 */
189 std::string_view hostname,
190 Credentials_Manager& credentials_manager,
191 Callbacks& callbacks,
192 Certificate_Type cert_type) :
193 m_request_context(cert_request.context()), m_side(Connection_Side::Client) {
194 const auto key_types = filter_signature_schemes(cert_request.signature_schemes());
195 const std::string op_type = "tls-client";
196
197 if(cert_type == Certificate_Type::X509) {
198 setup_entries(
199 credentials_manager.find_cert_chain(key_types,
201 cert_request.acceptable_CAs(),
202 op_type,
203 std::string(hostname)),
204 cert_request.extensions().get<Certificate_Status_Request>(),
205 callbacks);
206 } else if(cert_type == Certificate_Type::RawPublicKey) {
207 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 if(raw_public_key) {
217 setup_entry(std::move(raw_public_key), callbacks);
218 }
219 }
220}
221
222/**
223 * Create a Server Certificate message
224 */
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], the request context
231 // SHALL be zero length
232 m_request_context(/* NOLINT(*-redundant-member-init) */), m_side(Connection_Side::Server) {
233 /*
234 RFC 8446 4.2.3:
235 Clients which desire the server to authenticate itself via a
236 certificate MUST send the "signature_algorithms" extension. If a
237 server is authenticating via a certificate and the client has not sent
238 a "signature_algorithms" extension, then the server MUST abort the
239 handshake with a "missing_extension" alert.
240 */
241 if(!client_hello.extensions().has<Signature_Algorithms>()) {
242 throw TLS_Exception(Alert::MissingExtension, "Client Hello is missing required signature_algorithms extension");
243 }
244
245 const auto key_types = filter_signature_schemes(client_hello.signature_schemes());
246 const std::string op_type = "tls-server";
247 const std::string context = client_hello.sni_hostname();
248
249 if(cert_type == Certificate_Type::X509) {
250 auto cert_chain = credentials_manager.find_cert_chain(
251 key_types, to_algorithm_identifiers(client_hello.certificate_signature_schemes()), {}, op_type, context);
252
253 // RFC 8446 4.4.2
254 // The server's certificate_list MUST always be non-empty.
255 if(cert_chain.empty()) {
256 throw TLS_Exception(Alert::HandshakeFailure, "No sufficient server certificate available");
257 }
258
259 setup_entries(std::move(cert_chain), client_hello.extensions().get<Certificate_Status_Request>(), callbacks);
260 } else if(cert_type == Certificate_Type::RawPublicKey) {
261 auto raw_public_key = credentials_manager.find_raw_public_key(key_types, op_type, context);
262
263 // RFC 8446 4.4.2
264 // If the RawPublicKey certificate type was negotiated, then the
265 // certificate_list MUST contain no more than one CertificateEntry
266 // [...].
267 // The server's certificate_list MUST always be non-empty
268 if(!raw_public_key) {
269 throw TLS_Exception(Alert::HandshakeFailure, "No sufficient server raw public key available");
270 }
271
272 setup_entry(std::move(raw_public_key), callbacks);
273 }
274}
275
277 Connection_Side side,
278 Certificate_Type cert_type) {
279 if(cert_type == Certificate_Type::X509) {
280 // RFC 8446 4.2.2
281 // [...] each CertificateEntry contains a DER-encoded X.509
282 // certificate.
283 const auto cert_bytes = reader.get_tls_length_value(3);
284 try {
285 m_certificate = std::make_unique<X509_Certificate>(cert_bytes);
286 m_raw_public_key = m_certificate->subject_public_key();
287 } catch(Exception& e) {
288 // bad_certificate would make more sense but BoGo expects decoding_error
289 throw TLS_Exception(Alert::DecodeError, e.what());
290 }
291 } else if(cert_type == Certificate_Type::RawPublicKey) {
292 // RFC 7250 3.
293 // This specification uses raw public keys whereby the already
294 // available encoding used in a PKIX certificate in the form of a
295 // SubjectPublicKeyInfo structure is reused.
296 try {
297 m_raw_public_key = X509::load_key(reader.get_tls_length_value(3));
298 } catch(Exception& e) {
299 throw TLS_Exception(Alert::DecodeError, e.what());
300 }
301 } else {
302 throw TLS_Exception(Alert::InternalError, "Unknown certificate type");
303 }
304
305 // Extensions are simply tacked at the end of the certificate entry. This
306 // is a departure from the typical "tag-length-value" in a sense that the
307 // Extensions deserializer needs the length value of the extensions.
308 const size_t extensions_length = reader.peek_uint16_t();
309 const auto exts_buf = reader.get_fixed<uint8_t>(extensions_length + 2);
310 TLS_Data_Reader exts_reader("extensions reader", exts_buf);
311 m_extensions.deserialize(exts_reader, side, Handshake_Type::Certificate);
312
313 if(cert_type == Certificate_Type::X509) {
314 // RFC 8446 4.4.2
315 // Valid extensions for server certificates at present include the
316 // OCSP Status extension [RFC6066] and the SignedCertificateTimestamp
317 // extension [RFC6962]; future extensions may be defined for this
318 // message as well.
319 //
320 // RFC 8446 4.4.2.1
321 // A server MAY request that a client present an OCSP response with its
322 // certificate by sending an empty "status_request" extension in its
323 // CertificateRequest message.
324 if(m_extensions.contains_implemented_extensions_other_than({
325 Extension_Code::CertificateStatusRequest,
326 // Extension_Code::SignedCertificateTimestamp
327 })) {
328 throw TLS_Exception(Alert::IllegalParameter, "Certificate Entry contained an extension that is not allowed");
329 }
330 } else if(m_extensions.contains_implemented_extensions_other_than({})) {
331 throw TLS_Exception(
332 Alert::IllegalParameter,
333 "Certificate Entry holding something else than a certificate contained unexpected extensions");
334 }
335}
336
338
341 Certificate_13::Certificate_Entry&& other) noexcept = default;
342
344 m_certificate(std::make_unique<X509_Certificate>(cert)), m_raw_public_key(m_certificate->subject_public_key()) {}
345
346Certificate_13::Certificate_Entry::Certificate_Entry(std::shared_ptr<Public_Key> raw_public_key) :
347 m_raw_public_key(std::move(raw_public_key)) {
348 BOTAN_ASSERT_NONNULL(m_raw_public_key);
349}
350
355
356std::shared_ptr<const Public_Key> Certificate_13::Certificate_Entry::public_key() const {
357 BOTAN_ASSERT_NONNULL(m_raw_public_key);
358 return m_raw_public_key;
359}
360
362 return (has_certificate()) ? m_certificate->BER_encode() : X509::BER_encode(*m_raw_public_key);
363}
364
365/**
366* Deserialize a Certificate message
367*/
368Certificate_13::Certificate_13(std::span<const uint8_t> buf,
369 const Policy& policy,
370 Connection_Side side,
371 Certificate_Type cert_type) :
372 m_side(side) {
373 TLS_Data_Reader reader("cert message reader", buf);
374
375 m_request_context = reader.get_range<uint8_t>(1, 0, 255);
376
377 // RFC 8446 4.4.2
378 // [...] in the case of server authentication, this field SHALL be zero length.
379 if(m_side == Connection_Side::Server && !m_request_context.empty()) {
380 throw TLS_Exception(Alert::IllegalParameter, "Server Certificate message must not contain a request context");
381 }
382
383 const auto cert_entries_len = reader.get_uint24_t();
384
385 if(reader.remaining_bytes() != cert_entries_len) {
386 throw TLS_Exception(Alert::DecodeError, "Certificate: Message malformed");
387 }
388
389 const size_t max_size = policy.maximum_certificate_chain_size();
390 if(max_size > 0 && cert_entries_len > max_size) {
391 throw Decoding_Error("Certificate chain exceeds policy specified maximum size");
392 }
393
394 while(reader.has_remaining()) {
395 m_entries.emplace_back(reader, side, cert_type);
396 }
397
398 // RFC 8446 4.4.2
399 // The server's certificate_list MUST always be non-empty. A client
400 // will send an empty certificate_list if it does not have an
401 // appropriate certificate to send in response to the server's
402 // authentication request.
403 if(m_entries.empty()) {
404 // RFC 8446 4.4.2.4
405 // If the server supplies an empty Certificate message, the client MUST
406 // abort the handshake with a "decode_error" alert.
407 if(m_side == Connection_Side::Server) {
408 throw TLS_Exception(Alert::DecodeError, "No certificates sent by server");
409 }
410
411 return;
412 }
413
414 BOTAN_ASSERT_NOMSG(!m_entries.empty());
415
416 // RFC 8446 4.4.2.2
417 // The certificate type MUST be X.509v3 [RFC5280], unless explicitly
418 // negotiated otherwise (e.g., [RFC7250]).
419 //
420 // TLS 1.0 through 1.3 all seem to require that the certificate be
421 // precisely a v3 certificate. In fact the strict wording would seem
422 // to require that every certificate in the chain be v3. But often
423 // the intermediates are outside of the control of the server.
424 // But, require that the leaf certificate be v3.
425 if(cert_type == Certificate_Type::X509 && m_entries.front().certificate().x509_version() != 3) {
426 throw TLS_Exception(Alert::BadCertificate, "The leaf certificate must be v3");
427 }
428
429 // RFC 8446 4.4.2
430 // If the RawPublicKey certificate type was negotiated, then the
431 // certificate_list MUST contain no more than one CertificateEntry.
432 if(cert_type == Certificate_Type::RawPublicKey && m_entries.size() != 1) {
433 throw TLS_Exception(Alert::IllegalParameter, "Certificate message contained more than one RawPublicKey");
434 }
435
436 // Validate the provided (certificate) public key against our policy
437 auto pubkey = public_key();
438 policy.check_peer_key_acceptable(*pubkey);
439
440 if(!policy.allowed_signature_method(pubkey->algo_name())) {
441 throw TLS_Exception(Alert::HandshakeFailure, "Rejecting " + pubkey->algo_name() + " signature");
442 }
443}
444
445/**
446* Serialize a Certificate message
447*/
448std::vector<uint8_t> Certificate_13::serialize() const {
449 std::vector<uint8_t> buf;
450
451 append_tls_length_value(buf, m_request_context, 1);
452
453 std::vector<uint8_t> entries;
454 for(const auto& entry : m_entries) {
455 append_tls_length_value(entries, entry.serialize(), 3);
456
457 // Extensions are tacked at the end of certificate entries. Note that
458 // Extensions::serialize() usually emits the required length field,
459 // except when no extensions are added at all, then it returns an
460 // empty buffer.
461 //
462 // TODO: look into this issue more generally when overhauling the
463 // message marshalling.
464 auto extensions = entry.extensions().serialize(m_side);
465 entries += (!extensions.empty()) ? extensions : std::vector<uint8_t>{0, 0};
466 }
467
468 append_tls_length_value(buf, entries, 3);
469
470 return buf;
471}
472
473} // namespace Botan::TLS
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114
virtual std::vector< Certificate_Store * > trusted_certificate_authorities(const std::string &type, const std::string &context)
virtual std::vector< X509_Certificate > find_cert_chain(const std::vector< std::string > &cert_key_types, const std::vector< AlgorithmIdentifier > &cert_signature_schemes, const std::vector< X509_DN > &acceptable_CAs, const std::string &type, const std::string &context)
virtual std::shared_ptr< Public_Key > find_raw_public_key(const std::vector< std::string > &key_types, const std::string &type, const std::string &context)
const char * what() const noexcept override
Definition exceptn.h:94
virtual std::optional< OCSP::Response > tls_parse_ocsp_response(const std::vector< uint8_t > &raw_response)
virtual void tls_examine_extensions(const Extensions &extn, Connection_Side which_side, Handshake_Type which_message)
virtual void tls_verify_raw_public_key(const Public_Key &raw_public_key, Usage_Type usage, std::string_view hostname, const TLS::Policy &policy)
virtual void tls_verify_cert_chain(const std::vector< X509_Certificate > &cert_chain, const std::vector< std::optional< OCSP::Response > > &ocsp_responses, const std::vector< Certificate_Store * > &trusted_roots, Usage_Type usage, std::string_view hostname, const TLS::Policy &policy)
Certificate_Entry & operator=(const Certificate_Entry &other)=delete
const X509_Certificate & certificate() const
std::shared_ptr< const Public_Key > public_key() const
Certificate_Entry(TLS_Data_Reader &reader, Connection_Side side, Certificate_Type cert_type)
~Certificate_Entry()
bool has_certificate() const
std::vector< uint8_t > serialize() const
const X509_Certificate & leaf() const
void validate_extensions(const std::set< Extension_Code > &requested_extensions, Callbacks &cb) const
std::shared_ptr< const Public_Key > public_key() const
Handshake_Type type() const override
void verify(Callbacks &callbacks, const Policy &policy, Credentials_Manager &creds, std::string_view hostname, bool use_ocsp) const
std::vector< uint8_t > serialize() const override
std::vector< X509_Certificate > cert_chain() const
Certificate_13(const Certificate_Request_13 &cert_request, std::string_view hostname, Credentials_Manager &credentials_manager, Callbacks &callbacks, Certificate_Type cert_type)
const std::vector< Signature_Scheme > & signature_schemes() const
const Extensions & extensions() const
const std::vector< Signature_Scheme > & certificate_signature_schemes() const
std::vector< X509_DN > acceptable_CAs() const
const std::vector< uint8_t > & get_ocsp_response() const
std::string sni_hostname() const
std::vector< Signature_Scheme > signature_schemes() const
const Extensions & extensions() const
virtual void check_peer_key_acceptable(const Public_Key &public_key) const
bool allowed_signature_method(std::string_view sig_method) const
virtual size_t maximum_certificate_chain_size() const
std::vector< T > get_range(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition tls_reader.h:110
size_t remaining_bytes() const
Definition tls_reader.h:37
std::vector< uint8_t > get_tls_length_value(size_t len_bytes)
Definition tls_reader.h:105
std::vector< T > get_fixed(size_t size)
Definition tls_reader.h:129
uint16_t peek_uint16_t() const
Definition tls_reader.h:78
std::vector< AlgorithmIdentifier > to_algorithm_identifiers(const std::vector< Signature_Scheme > &schemes)
void append_tls_length_value(std::vector< uint8_t, Alloc > &buf, const T *vals, size_t vals_size, size_t tag_size)
Definition tls_reader.h:177
std::vector< uint8_t > BER_encode(const Public_Key &key)
Definition x509_key.h:24
std::unique_ptr< Public_Key > load_key(DataSource &source)
Definition x509_key.cpp:28
bool value_exists(const std::vector< T > &vec, const V &val)
Definition stl_util.h:44