Coverage Report

Created: 2024-11-29 06:10

/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