• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 25139258422

29 Apr 2026 08:02PM UTC coverage: 89.37% (-0.02%) from 89.385%
25139258422

push

github

web-flow
Merge pull request #5550 from randombit/jack/tls-misc

TLS conformance, hardening, and performance fixes

107055 of 119789 relevant lines covered (89.37%)

11415549.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.21
/src/lib/tls/tls13/msg_certificate_req_13.cpp
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

19
namespace Botan::TLS {
20

21
Handshake_Type Certificate_Request_13::type() const {
514✔
22
   return TLS::Handshake_Type::CertificateRequest;
514✔
23
}
24

25
Certificate_Request_13::Certificate_Request_13(const std::vector<uint8_t>& buf, const Connection_Side side) {
70✔
26
   TLS_Data_Reader reader("Certificate_Request_13", buf);
70✔
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) {
70✔
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);
140✔
36
   m_extensions.deserialize(reader, side, type());
70✔
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>()) {
68✔
44
      throw TLS_Exception(Alert::MissingExtension,
1✔
45
                          "Certificate_Request message did not provide a signature_algorithms extension");
1✔
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 = {
67✔
58
      Extension_Code::CertificateStatusRequest,
59
      Extension_Code::SignatureAlgorithms,
60
      // Extension_Code::SignedCertificateTimestamp,  // NYI
61
      Extension_Code::CertificateAuthorities,
62
      // Extension_Code::OidFilters,                   // NYI
63
      Extension_Code::CertSignatureAlgorithms,
64
   };
67✔
65

66
   if(m_extensions.contains_implemented_extensions_other_than(allowed_extensions)) {
67✔
67
      throw TLS_Exception(Alert::IllegalParameter, "Certificate Request contained an extension that is not allowed");
×
68
   }
69

70
   reader.assert_done();
67✔
71
}
73✔
72

73
Certificate_Request_13::Certificate_Request_13(const std::vector<X509_DN>& acceptable_CAs,
104✔
74
                                               const Policy& policy,
75
                                               Callbacks& callbacks) {
104✔
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()));
208✔
94
   if(auto cert_signing_prefs = policy.acceptable_certificate_signature_schemes()) {
104✔
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()) {
104✔
102
      m_extensions.add(std::make_unique<Certificate_Authorities>(acceptable_CAs));
160✔
103
   }
104

105
   // TODO: Support cert_status_request for OCSP stapling
106

107
   callbacks.tls_modify_extensions(m_extensions, Connection_Side::Server, type());
104✔
108

109
   if(!m_extensions.has<Signature_Algorithms>()) {
104✔
110
      throw TLS_Exception(
×
111
         Alert::InternalError,
112
         "Application tls_modify_extensions callback removed Signature_Algorithms from the CertificateRequest");
×
113
   }
114
}
104✔
115

116
std::optional<Certificate_Request_13> Certificate_Request_13::maybe_create(const Client_Hello_13& client_hello,
285✔
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());
570✔
121

122
   std::vector<X509_DN> client_auth_CAs;
285✔
123
   for(auto* const store : trusted_CAs) {
545✔
124
      const auto subjects = store->all_subjects();
260✔
125
      client_auth_CAs.insert(client_auth_CAs.end(), subjects.begin(), subjects.end());
260✔
126
   }
260✔
127

128
   if(client_auth_CAs.empty() && !policy.request_client_certificate_authentication()) {
285✔
129
      return std::nullopt;
181✔
130
   }
131

132
   return Certificate_Request_13(client_auth_CAs, policy, callbacks);
208✔
133
}
545✔
134

135
std::vector<X509_DN> Certificate_Request_13::acceptable_CAs() const {
55✔
136
   if(m_extensions.has<Certificate_Authorities>()) {
55✔
137
      return m_extensions.get<Certificate_Authorities>()->distinguished_names();
3✔
138
   }
139
   return {};
52✔
140
}
141

142
const std::vector<Signature_Scheme>& Certificate_Request_13::signature_schemes() const {
213✔
143
   // RFC 8446 4.3.2
144
   //    The "signature_algorithms" extension MUST be specified
145
   BOTAN_ASSERT_NOMSG(m_extensions.has<Signature_Algorithms>());
213✔
146

147
   return m_extensions.get<Signature_Algorithms>()->supported_schemes();
213✔
148
}
149

150
const std::vector<Signature_Scheme>& Certificate_Request_13::certificate_signature_schemes() const {
55✔
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>()) {
55✔
156
      return sig_schemes_cert->supported_schemes();
×
157
   } else {
158
      return signature_schemes();
55✔
159
   }
160
}
161

162
std::vector<uint8_t> Certificate_Request_13::serialize() const {
108✔
163
   std::vector<uint8_t> buf;
108✔
164
   append_tls_length_value(buf, m_context, 1);
108✔
165
   buf += m_extensions.serialize(Connection_Side::Server);
108✔
166
   return buf;
108✔
167
}
×
168

169
}  // namespace Botan::TLS
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc