Botan 3.12.0
Crypto and TLS for C&
msg_certificate_req_13.cpp
Go to the documentation of this file.
1/*
2* (C) 2022 Jack Lloyd
3* (C) 2022 Hannes Rantzsch, René Meusel - neXenio GmbH
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/tls_messages_13.h>
9
10#include <botan/certstor.h>
11#include <botan/credentials_manager.h>
12#include <botan/pkix_types.h>
13#include <botan/tls_callbacks.h>
14#include <botan/tls_exceptn.h>
15#include <botan/tls_extensions_13.h>
16#include <botan/tls_policy.h>
17#include <botan/internal/tls_reader.h>
18
19namespace Botan::TLS {
20
24
25Certificate_Request_13::Certificate_Request_13(const std::vector<uint8_t>& buf, const Connection_Side side) {
26 TLS_Data_Reader reader("Certificate_Request_13", buf);
27
28 // RFC 8446 4.3.2
29 // A server which is authenticating with a certificate MAY optionally
30 // request a certificate from the client.
31 if(side != Connection_Side::Server) {
32 throw TLS_Exception(Alert::UnexpectedMessage, "Received a Certificate_Request message from a client");
33 }
34
35 m_context = reader.get_tls_length_value(1);
36 m_extensions.deserialize(reader, side, type());
37
38 // RFC 8446 4.3.2
39 // The "signature_algorithms" extension MUST be specified, and other
40 // extensions may optionally be included if defined for this message.
41 // Clients MUST ignore unrecognized extensions.
42
43 if(!m_extensions.has<Signature_Algorithms>()) {
44 throw TLS_Exception(Alert::MissingExtension,
45 "Certificate_Request message did not provide a signature_algorithms extension");
46 }
47
48 // RFC 8446 4.2.
49 // The table below indicates the messages where a given extension may
50 // appear [...]. If an implementation receives an extension which it
51 // recognizes and which is not specified for the message in which it
52 // appears, it MUST abort the handshake with an "illegal_parameter" alert.
53 //
54 // For Certificate Request said table states:
55 // "status_request", "signature_algorithms", "signed_certificate_timestamp",
56 // "certificate_authorities", "oid_filters", "signature_algorithms_cert",
57 const std::set<Extension_Code> allowed_extensions = {
60 // Extension_Code::SignedCertificateTimestamp, // NYI
62 // Extension_Code::OidFilters, // NYI
64 };
65
66 if(m_extensions.contains_implemented_extensions_other_than(allowed_extensions)) {
67 throw TLS_Exception(Alert::IllegalParameter, "Certificate Request contained an extension that is not allowed");
68 }
69
70 reader.assert_done();
71}
72
73Certificate_Request_13::Certificate_Request_13(const std::vector<X509_DN>& acceptable_CAs,
74 const Policy& policy,
75 Callbacks& callbacks) {
76 // RFC 8446 4.3.2
77 // The certificate_request_context [here: m_context] MUST be unique within
78 // the scope of this connection (thus preventing replay of client
79 // CertificateVerify messages). This field SHALL be zero length unless
80 // used for the post-handshake authentication exchanges described in
81 // Section 4.6.2.
82 //
83 // TODO: Post-Handshake auth must fill m_context in an unpredictable way
84
85 // RFC 8446 4.3.2
86 // [Supported signature algorithms are] expressed by sending the
87 // "signature_algorithms" and optionally "signature_algorithms_cert"
88 // extensions. [A list of certificate authorities which the server would
89 // accept] is expressed by sending the "certificate_authorities" extension.
90 //
91 // The "signature_algorithms" extension MUST be specified, and other
92 // extensions may optionally be included if defined for this message.
93 m_extensions.add(std::make_unique<Signature_Algorithms>(policy.acceptable_signature_schemes()));
94 if(auto cert_signing_prefs = policy.acceptable_certificate_signature_schemes()) {
95 // RFC 8446 4.2.3
96 // Implementations which have the same policy in both cases MAY omit
97 // the "signature_algorithms_cert" extension.
98 m_extensions.add(std::make_unique<Signature_Algorithms_Cert>(std::move(cert_signing_prefs.value())));
99 }
100
101 if(!acceptable_CAs.empty()) {
102 m_extensions.add(std::make_unique<Certificate_Authorities>(acceptable_CAs));
103 }
104
105 // TODO: Support cert_status_request for OCSP stapling
106
107 callbacks.tls_modify_extensions(m_extensions, Connection_Side::Server, type());
108
109 if(!m_extensions.has<Signature_Algorithms>()) {
110 throw TLS_Exception(
111 Alert::InternalError,
112 "Application tls_modify_extensions callback removed Signature_Algorithms from the CertificateRequest");
113 }
114}
115
116std::optional<Certificate_Request_13> Certificate_Request_13::maybe_create(const Client_Hello_13& client_hello,
117 Credentials_Manager& cred_mgr,
118 Callbacks& callbacks,
119 const Policy& policy) {
120 const auto trusted_CAs = cred_mgr.trusted_certificate_authorities("tls-server", client_hello.sni_hostname());
121
122 std::vector<X509_DN> client_auth_CAs;
123 for(auto* const store : trusted_CAs) {
124 const auto subjects = store->all_subjects();
125 client_auth_CAs.insert(client_auth_CAs.end(), subjects.begin(), subjects.end());
126 }
127
128 if(client_auth_CAs.empty() && !policy.request_client_certificate_authentication()) {
129 return std::nullopt;
130 }
131
132 return Certificate_Request_13(client_auth_CAs, policy, callbacks);
133}
134
135std::vector<X509_DN> Certificate_Request_13::acceptable_CAs() const {
136 if(m_extensions.has<Certificate_Authorities>()) {
137 return m_extensions.get<Certificate_Authorities>()->distinguished_names();
138 }
139 return {};
140}
141
142const std::vector<Signature_Scheme>& Certificate_Request_13::signature_schemes() const {
143 // RFC 8446 4.3.2
144 // The "signature_algorithms" extension MUST be specified
145 BOTAN_ASSERT_NOMSG(m_extensions.has<Signature_Algorithms>());
146
147 return m_extensions.get<Signature_Algorithms>()->supported_schemes();
148}
149
150const std::vector<Signature_Scheme>& Certificate_Request_13::certificate_signature_schemes() const {
151 // RFC 8446 4.2.3
152 // If no "signature_algorithms_cert" extension is present, then the
153 // "signature_algorithms" extension also applies to signatures appearing
154 // in certificates.
155 if(auto* sig_schemes_cert = m_extensions.get<Signature_Algorithms_Cert>()) {
156 return sig_schemes_cert->supported_schemes();
157 } else {
158 return signature_schemes();
159 }
160}
161
162std::vector<uint8_t> Certificate_Request_13::serialize() const {
163 std::vector<uint8_t> buf;
164 append_tls_length_value(buf, m_context, 1);
165 buf += m_extensions.serialize(Connection_Side::Server);
166 return buf;
167}
168
169} // namespace Botan::TLS
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
virtual std::vector< Certificate_Store * > trusted_certificate_authorities(const std::string &type, const std::string &context)
virtual void tls_modify_extensions(Extensions &extn, Connection_Side which_side, Handshake_Type which_message)
const std::vector< Signature_Scheme > & signature_schemes() const
std::vector< uint8_t > serialize() const override
Handshake_Type type() const override
const std::vector< Signature_Scheme > & certificate_signature_schemes() const
static std::optional< Certificate_Request_13 > maybe_create(const Client_Hello_13 &sni_hostname, Credentials_Manager &cred_mgr, Callbacks &callbacks, const Policy &policy)
std::vector< X509_DN > acceptable_CAs() const
Certificate_Request_13(const std::vector< uint8_t > &buf, Connection_Side side)
std::string sni_hostname() const
void add(std::unique_ptr< Extension > extn)
virtual bool request_client_certificate_authentication() const
virtual std::optional< std::vector< Signature_Scheme > > acceptable_certificate_signature_schemes() const
virtual std::vector< Signature_Scheme > acceptable_signature_schemes() const
std::vector< uint8_t > get_tls_length_value(size_t len_bytes)
Definition tls_reader.h:105
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