Botan 3.9.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/credentials_manager.h>
14#include <botan/pk_keys.h>
15#include <botan/tls_algos.h>
16#include <botan/tls_extensions.h>
17#include <botan/internal/stl_util.h>
18#include <botan/internal/target_info.h>
19#include <botan/internal/tls_handshake_io.h>
20#include <botan/internal/tls_handshake_state.h>
21#include <botan/internal/tls_reader.h>
22
23namespace Botan::TLS {
24
25/*
26* Create a new Certificate Verify message for TLS 1.2
27*/
29 Handshake_State& state,
30 const Policy& policy,
32 const Private_Key* priv_key) {
33 BOTAN_ASSERT_NONNULL(priv_key);
34
35 std::pair<std::string, Signature_Format> format = state.choose_sig_format(*priv_key, m_scheme, true, policy);
36
38 state.callbacks().tls_sign_message(*priv_key, rng, format.first, format.second, state.hash().get_contents());
39
40 state.hash().update(io.send(*this));
41}
42
43/*
44* Deserialize a Certificate Verify message
45*/
46Certificate_Verify::Certificate_Verify(const std::vector<uint8_t>& buf) {
47 TLS_Data_Reader reader("CertificateVerify", buf);
48
50 m_signature = reader.get_range<uint8_t>(2, 0, 65535);
51 reader.assert_done();
52
53 if(!m_scheme.is_set()) {
54 throw Decoding_Error("Counterparty did not send hash/sig IDS");
55 }
56}
57
58/*
59* Serialize a Certificate Verify message
60*/
61std::vector<uint8_t> Certificate_Verify::serialize() const {
63 std::vector<uint8_t> buf;
64 buf.reserve(2 + 2 + m_signature.size()); // work around GCC warning
65
66 const auto code = m_scheme.wire_code();
67 buf.push_back(get_byte<0>(code));
68 buf.push_back(get_byte<1>(code));
69
70 if(m_signature.size() > 0xFFFF) {
71 throw Encoding_Error("Certificate_Verify signature too long to encode");
72 }
73
74 const uint16_t sig_len = static_cast<uint16_t>(m_signature.size());
75 buf.push_back(get_byte<0>(sig_len));
76 buf.push_back(get_byte<1>(sig_len));
77 buf += m_signature;
78
79 return buf;
80}
81
83 const Handshake_State& state,
84 const Policy& policy) const {
85 auto key = cert.subject_public_key();
86
87 policy.check_peer_key_acceptable(*key);
88
89 std::pair<std::string, Signature_Format> format =
90 state.parse_sig_format(*key, m_scheme, state.client_hello()->signature_schemes(), true, policy);
91
92 const bool signature_valid =
93 state.callbacks().tls_verify_message(*key, format.first, format.second, state.hash().get_contents(), m_signature);
94
95#if defined(BOTAN_UNSAFE_FUZZER_MODE)
96 BOTAN_UNUSED(signature_valid);
97 return true;
98
99#else
100 return signature_valid;
101
102#endif
103}
104
105#if defined(BOTAN_HAS_TLS_13)
106
107namespace {
108
109std::vector<uint8_t> message(Connection_Side side, const Transcript_Hash& hash) {
110 std::vector<uint8_t> msg(64, 0x20);
111 msg.reserve(64 + 33 + 1 + hash.size());
112
113 const std::string context_string = (side == TLS::Connection_Side::Server) ? "TLS 1.3, server CertificateVerify"
114 : "TLS 1.3, client CertificateVerify";
115
116 msg.insert(msg.end(), context_string.cbegin(), context_string.cend());
117 msg.push_back(0x00);
118
119 msg.insert(msg.end(), hash.cbegin(), hash.cend());
120 return msg;
121}
122
123Signature_Scheme choose_signature_scheme(const Private_Key& key,
124 const std::vector<Signature_Scheme>& allowed_schemes,
125 const std::vector<Signature_Scheme>& peer_allowed_schemes) {
126 for(Signature_Scheme scheme : allowed_schemes) {
127 if(scheme.is_available() && scheme.is_suitable_for(key) && value_exists(peer_allowed_schemes, scheme)) {
128 return scheme;
129 }
130 }
131
132 throw TLS_Exception(Alert::HandshakeFailure, "Failed to agree on a signature algorithm");
133}
134
135} // namespace
136
137/*
138* Create a new Certificate Verify message for TLS 1.3
139*/
141 const std::vector<Signature_Scheme>& peer_allowed_schemes,
142 std::string_view hostname,
143 const Transcript_Hash& hash,
144 Connection_Side whoami,
145 Credentials_Manager& creds_mgr,
146 const Policy& policy,
147 Callbacks& callbacks,
149 m_side(whoami) {
150 BOTAN_ASSERT_NOMSG(!certificate_msg.empty());
151
152 const std::string op_type((m_side == Connection_Side::Client) ? "tls-client" : "tls-server");
153 const auto context = std::string(hostname);
154
155 const auto private_key = (certificate_msg.has_certificate_chain())
156 ? creds_mgr.private_key_for(certificate_msg.leaf(), op_type, context)
157 : creds_mgr.private_key_for(*certificate_msg.public_key(), op_type, context);
158 if(!private_key) {
159 throw TLS_Exception(Alert::InternalError, "Application did not provide a private key for its credential");
160 }
161
162 m_scheme = choose_signature_scheme(*private_key, policy.allowed_signature_schemes(), peer_allowed_schemes);
163 BOTAN_ASSERT_NOMSG(m_scheme.is_available());
164 BOTAN_ASSERT_NOMSG(m_scheme.is_compatible_with(Protocol_Version::TLS_V13));
165
166 m_signature = callbacks.tls_sign_message(
167 *private_key, rng, m_scheme.padding_string(), m_scheme.format().value(), message(m_side, hash));
168}
169
170Certificate_Verify_13::Certificate_Verify_13(const std::vector<uint8_t>& buf, const Connection_Side side) :
171 Certificate_Verify(buf), m_side(side) {
172 if(!m_scheme.is_available()) {
173 throw TLS_Exception(Alert::IllegalParameter, "Peer sent unknown signature scheme");
174 }
175
176 if(!m_scheme.is_compatible_with(Protocol_Version::TLS_V13)) {
177 throw TLS_Exception(Alert::IllegalParameter, "Peer sent signature algorithm that is not suitable for TLS 1.3");
178 }
179}
180
181/*
182* Verify a Certificate Verify message
183*/
185 Callbacks& callbacks,
186 const Transcript_Hash& transcript_hash) const {
187 BOTAN_ASSERT_NOMSG(m_scheme.is_available());
188
189 // RFC 8446 4.2.3
190 // The keys found in certificates MUST [...] be of appropriate type for
191 // the signature algorithms they are used with.
192 if(m_scheme.key_algorithm_identifier() != public_key.algorithm_identifier()) {
193 throw TLS_Exception(Alert::IllegalParameter, "Signature algorithm does not match certificate's public key");
194 }
195
196 const bool signature_valid = callbacks.tls_verify_message(
197 public_key, m_scheme.padding_string(), m_scheme.format().value(), message(m_side, transcript_hash), m_signature);
198
199 #if defined(BOTAN_UNSAFE_FUZZER_MODE)
200 BOTAN_UNUSED(signature_valid);
201 return true;
202 #else
203 return signature_valid;
204 #endif
205}
206
207#endif // BOTAN_HAS_TLS_13
208
209} // namespace Botan::TLS
#define BOTAN_UNUSED
Definition assert.h:144
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114
virtual std::shared_ptr< Private_Key > private_key_for(const X509_Certificate &cert, const std::string &type, const std::string &context)
virtual AlgorithmIdentifier algorithm_identifier() const =0
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)
const X509_Certificate & leaf() const
std::shared_ptr< const Public_Key > public_key() const
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)
bool verify(const Public_Key &public_key, Callbacks &callbacks, const Transcript_Hash &transcript_hash) const
Certificate_Verify_13(const std::vector< uint8_t > &buf, Connection_Side side)
Certificate_Verify(const std::vector< uint8_t > &buf)
std::vector< uint8_t > serialize() const override
std::vector< uint8_t > m_signature
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(std::unique_ptr< 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
virtual std::vector< Signature_Scheme > allowed_signature_schemes() const
std::vector< T > get_range(size_t len_bytes, size_t min_elems, size_t max_elems)
Definition tls_reader.h:110
std::unique_ptr< Public_Key > subject_public_key() const
Definition x509cert.cpp:609
std::vector< uint8_t > Transcript_Hash
Definition tls_magic.h:81
constexpr uint8_t get_byte(T input)
Definition loadstor.h:79
bool value_exists(const std::vector< T > &vec, const OT &val)
Definition stl_util.h:52