Botan 3.0.0
Crypto and TLS for C&
msg_cert_verify.cpp
Go to the documentation of this file.
1/*
2* Certificate Verify Message
3* (C) 2004,2006,2011,2012 Jack Lloyd
4* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity
5* 2021 Elektrobit Automotive GmbH
6* 2022 René Meusel, Hannes Rantzsch - neXenio GmbH
7*
8* Botan is released under the Simplified BSD License (see license.txt)
9*/
10
11#include <botan/tls_messages.h>
12
13#include <botan/internal/tls_handshake_io.h>
14#include <botan/internal/tls_handshake_state.h>
15#include <botan/internal/tls_reader.h>
16#include <botan/internal/stl_util.h>
17#include <botan/pk_keys.h>
18#include <botan/tls_algos.h>
19#include <botan/tls_extensions.h>
20#include <botan/credentials_manager.h>
21
22namespace Botan::TLS {
23
24/*
25* Create a new Certificate Verify message for TLS 1.2
26*/
28 Handshake_State& state,
29 const Policy& policy,
31 const Private_Key* priv_key)
32 {
33 BOTAN_ASSERT_NONNULL(priv_key);
34
35 std::pair<std::string, Signature_Format> format =
36 state.choose_sig_format(*priv_key, m_scheme, true, policy);
37
39 state.callbacks().tls_sign_message(*priv_key, rng, format.first, format.second,
40 state.hash().get_contents());
41
42 state.hash().update(io.send(*this));
43 }
44
45/*
46* Deserialize a Certificate Verify message
47*/
48Certificate_Verify::Certificate_Verify(const std::vector<uint8_t>& buf)
49 {
50 TLS_Data_Reader reader("CertificateVerify", buf);
51
53 m_signature = reader.get_range<uint8_t>(2, 0, 65535);
54 reader.assert_done();
55
56 if(!m_scheme.is_set())
57 { throw Decoding_Error("Counterparty did not send hash/sig IDS"); }
58 }
59
60/*
61* Serialize a Certificate Verify message
62*/
63std::vector<uint8_t> Certificate_Verify::serialize() const
64 {
66 std::vector<uint8_t> buf;
67 buf.reserve(2 + 2 + m_signature.size()); // work around GCC warning
68
69 const auto code = m_scheme.wire_code();
70 buf.push_back(get_byte<0>(code));
71 buf.push_back(get_byte<1>(code));
72
73 if(m_signature.size() > 0xFFFF)
74 { throw Encoding_Error("Certificate_Verify signature too long to encode"); }
75
76 const uint16_t sig_len = static_cast<uint16_t>(m_signature.size());
77 buf.push_back(get_byte<0>(sig_len));
78 buf.push_back(get_byte<1>(sig_len));
79 buf += m_signature;
80
81 return buf;
82 }
83
84
86 const Handshake_State& state,
87 const Policy& policy) const
88 {
89 auto key = cert.subject_public_key();
90
91 policy.check_peer_key_acceptable(*key);
92
93 std::pair<std::string, Signature_Format> format =
94 state.parse_sig_format(*key, m_scheme, state.client_hello()->signature_schemes(), true, policy);
95
96 const bool signature_valid =
97 state.callbacks().tls_verify_message(*key, format.first, format.second,
98 state.hash().get_contents(), m_signature);
99
100#if defined(BOTAN_UNSAFE_FUZZER_MODE)
101 BOTAN_UNUSED(signature_valid);
102 return true;
103
104#else
105 return signature_valid;
106
107#endif
108 }
109
110#if defined(BOTAN_HAS_TLS_13)
111
112namespace {
113
114std::vector<uint8_t> message(Connection_Side side, const Transcript_Hash& hash)
115 {
116 std::vector<uint8_t> msg(64, 0x20);
117 msg.reserve(64 + 33 + 1 + hash.size());
118
119 const std::string context_string = (side == TLS::Connection_Side::Server)
120 ? "TLS 1.3, server CertificateVerify"
121 : "TLS 1.3, client CertificateVerify";
122
123 msg.insert(msg.end(), context_string.cbegin(), context_string.cend());
124 msg.push_back(0x00);
125
126 msg.insert(msg.end(), hash.cbegin(), hash.cend());
127 return msg;
128 }
129
130Signature_Scheme choose_signature_scheme(
131 const Private_Key& key,
132 const std::vector<Signature_Scheme>& allowed_schemes,
133 const std::vector<Signature_Scheme>& peer_allowed_schemes)
134 {
135 for(Signature_Scheme scheme : allowed_schemes)
136 {
137 if(scheme.is_available()
138 && scheme.is_suitable_for(key)
139 && value_exists(peer_allowed_schemes, scheme))
140 {
141 return scheme;
142 }
143 }
144
145 throw TLS_Exception(Alert::HandshakeFailure, "Failed to agree on a signature algorithm");
146 }
147
148}
149
150/*
151* Create a new Certificate Verify message for TLS 1.3
152*/
153Certificate_Verify_13::Certificate_Verify_13(
154 const Certificate_13& certificate_msg,
155 const std::vector<Signature_Scheme>& peer_allowed_schemes,
156 std::string_view hostname,
157 const Transcript_Hash& hash,
158 Connection_Side whoami,
159 Credentials_Manager& creds_mgr,
160 const Policy& policy,
161 Callbacks& callbacks,
162 RandomNumberGenerator& rng)
163 : m_side(whoami)
164 {
165 BOTAN_ASSERT_NOMSG(!certificate_msg.empty());
166
167 const auto private_key = creds_mgr.private_key_for(
168 certificate_msg.leaf(),
169 m_side == Connection_Side::Client ? "tls-client" : "tls-server",
170 std::string(hostname));
171
172 if(!private_key)
173 { throw TLS_Exception(Alert::InternalError, "Application did not provide a private key for its certificate"); }
174
175 m_scheme = choose_signature_scheme(*private_key, policy.allowed_signature_schemes(), peer_allowed_schemes);
177 BOTAN_ASSERT_NOMSG(m_scheme.is_compatible_with(Protocol_Version::TLS_V13));
178
180 callbacks.tls_sign_message(*private_key,
181 rng,
183 m_scheme.format().value(),
184 message(m_side, hash));
185 }
186
187
188Certificate_Verify_13::Certificate_Verify_13(const std::vector<uint8_t>& buf,
189 const Connection_Side side)
190 : Certificate_Verify(buf)
191 , m_side(side)
192 {
194 { throw TLS_Exception(Alert::HandshakeFailure, "Peer sent unknown signature scheme"); }
195
196 if(!m_scheme.is_compatible_with(Protocol_Version::TLS_V13))
197 { throw TLS_Exception(Alert::IllegalParameter, "Peer sent signature algorithm that is not suitable for TLS 1.3"); }
198 }
199
200/*
201* Verify a Certificate Verify message
202*/
203bool Certificate_Verify_13::verify(const X509_Certificate& cert,
204 Callbacks& callbacks,
205 const Transcript_Hash& transcript_hash) const
206 {
207 BOTAN_ASSERT_NOMSG(m_scheme.is_available());
208
209 // RFC 8446 4.2.3
210 // The keys found in certificates MUST [...] be of appropriate type for
211 // the signature algorithms they are used with.
212 if(m_scheme.key_algorithm_identifier() != cert.subject_public_key_algo())
213 { throw TLS_Exception(Alert::IllegalParameter, "Signature algorithm does not match certificate's public key"); }
214
215 const auto key = cert.subject_public_key();
216 const bool signature_valid =
217 callbacks.tls_verify_message(*key,
218 m_scheme.padding_string(),
219 m_scheme.format().value(),
220 message(m_side, transcript_hash),
221 m_signature);
222
223#if defined(BOTAN_UNSAFE_FUZZER_MODE)
224 BOTAN_UNUSED(signature_valid);
225 return true;
226#else
227 return signature_valid;
228#endif
229 }
230
231#endif // BOTAN_HAS_TLS_13
232
233}
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:67
#define BOTAN_UNUSED(...)
Definition: assert.h:141
#define BOTAN_ASSERT_NONNULL(ptr)
Definition: assert.h:106
std::vector< uint8_t > subject_public_key() const
Definition: pk_keys.cpp:55
virtual std::vector< uint8_t > tls_sign_message(const Private_Key &key, RandomNumberGenerator &rng, std::string_view padding, Signature_Format format, const std::vector< uint8_t > &msg)
virtual bool tls_verify_message(const Public_Key &key, std::string_view padding, Signature_Format format, const std::vector< uint8_t > &msg, const std::vector< uint8_t > &sig)
bool verify(const X509_Certificate &cert, const Handshake_State &state, const Policy &policy) const
Certificate_Verify_12(Handshake_IO &io, Handshake_State &state, const Policy &policy, RandomNumberGenerator &rng, const Private_Key *key)
std::vector< uint8_t > serialize() const override
std::vector< uint8_t > m_signature
Definition: tls_messages.h:735
const std::vector< uint8_t > & get_contents() const
void update(const uint8_t in[], size_t length)
virtual std::vector< uint8_t > send(const Handshake_Message &msg)=0
std::pair< std::string, Signature_Format > parse_sig_format(const Public_Key &key, Signature_Scheme scheme, const std::vector< Signature_Scheme > &offered_schemes, bool for_client_auth, const Policy &policy) const
void client_hello(Client_Hello_12 *client_hello)
std::pair< std::string, Signature_Format > choose_sig_format(const Private_Key &key, Signature_Scheme &scheme, bool for_client_auth, const Policy &policy) const
virtual void check_peer_key_acceptable(const Public_Key &public_key) const
Definition: tls_policy.cpp:245
bool is_compatible_with(const Protocol_Version &protocol_version) const noexcept
Signature_Scheme::Code wire_code() const noexcept
std::optional< Signature_Format > format() const noexcept
std::string padding_string() const noexcept
bool is_available() const noexcept
std::vector< T > get_range(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition: tls_reader.h:121
std::unique_ptr< Public_Key > subject_public_key() const
Definition: x509cert.cpp:621
std::vector< uint8_t > Transcript_Hash
Definition: tls_magic.h:83
bool value_exists(const std::vector< T > &vec, const OT &val)
Definition: stl_util.h:104