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