Botan 3.12.0
Crypto and TLS for C&
msg_cert_verify_13.cpp
Go to the documentation of this file.
1/*
2* Certificate Verify Message
3* (C) 2021-2022 Jack Lloyd
4* 2021 Elektrobit Automotive GmbH
5* 2022 René Meusel, Hannes Rantzsch - neXenio GmbH
6*
7* Botan is released under the Simplified BSD License (see license.txt)
8*/
9
10#include <botan/tls_messages_13.h>
11
12#include <botan/credentials_manager.h>
13#include <botan/pk_keys.h>
14#include <botan/tls_callbacks.h>
15#include <botan/tls_exceptn.h>
16#include <botan/tls_policy.h>
17#include <botan/internal/stl_util.h>
18
19namespace Botan::TLS {
20
21namespace {
22
23std::vector<uint8_t> message(Connection_Side side, const Transcript_Hash& hash) {
24 std::vector<uint8_t> msg(64, 0x20);
25 msg.reserve(64 + 33 + 1 + hash.size());
26
27 const std::string context_string = (side == TLS::Connection_Side::Server) ? "TLS 1.3, server CertificateVerify"
28 : "TLS 1.3, client CertificateVerify";
29
30 msg.insert(msg.end(), context_string.cbegin(), context_string.cend());
31 msg.push_back(0x00);
32
33 msg.insert(msg.end(), hash.cbegin(), hash.cend());
34 return msg;
35}
36
37Signature_Scheme choose_signature_scheme(const Private_Key& key,
38 const std::vector<Signature_Scheme>& allowed_schemes,
39 const std::vector<Signature_Scheme>& peer_allowed_schemes) {
40 for(Signature_Scheme scheme : allowed_schemes) {
41 // RFC 8446 4.4.3 forbids the rsa_pkcs1_* schemes in CertificateVerify, those are TLS 1.2 only.
42 if(scheme.is_available() && scheme.is_compatible_with(Protocol_Version::TLS_V13) && scheme.is_suitable_for(key) &&
43 value_exists(peer_allowed_schemes, scheme)) {
44 return scheme;
45 }
46 }
47
48 throw TLS_Exception(Alert::HandshakeFailure, "Failed to agree on a signature algorithm");
49}
50
51} // namespace
52
53/*
54* Create a new Certificate Verify message for TLS 1.3
55*/
57 const std::vector<Signature_Scheme>& peer_allowed_schemes,
58 std::string_view hostname,
59 const Transcript_Hash& hash,
60 Connection_Side whoami,
61 Credentials_Manager& creds_mgr,
62 const Policy& policy,
63 Callbacks& callbacks,
65 m_side(whoami) {
66 BOTAN_ASSERT_NOMSG(!certificate_msg.empty());
67
68 const std::string op_type((m_side == Connection_Side::Client) ? "tls-client" : "tls-server");
69 const auto context = std::string(hostname);
70
71 const auto private_key = (certificate_msg.has_certificate_chain())
72 ? creds_mgr.private_key_for(certificate_msg.leaf(), op_type, context)
73 : creds_mgr.private_key_for(*certificate_msg.public_key(), op_type, context);
74 if(!private_key) {
75 throw TLS_Exception(Alert::InternalError, "Application did not provide a private key for its credential");
76 }
77
78 m_scheme = choose_signature_scheme(*private_key, policy.allowed_signature_schemes(), peer_allowed_schemes);
79 BOTAN_ASSERT_NOMSG(m_scheme.is_available());
80 BOTAN_ASSERT_NOMSG(m_scheme.is_compatible_with(Protocol_Version::TLS_V13));
81
82 m_signature = callbacks.tls_sign_message(
83 *private_key, rng, m_scheme.padding_string(), m_scheme.format().value(), message(m_side, hash));
84}
85
86Certificate_Verify_13::Certificate_Verify_13(const std::vector<uint8_t>& buf, const Connection_Side side) :
87 Certificate_Verify(buf), m_side(side) {
88 if(!m_scheme.is_available()) {
89 throw TLS_Exception(Alert::IllegalParameter, "Peer sent unknown signature scheme");
90 }
91
92 if(!m_scheme.is_compatible_with(Protocol_Version::TLS_V13)) {
93 throw TLS_Exception(Alert::IllegalParameter, "Peer sent signature algorithm that is not suitable for TLS 1.3");
94 }
95}
96
97/*
98* Verify a Certificate Verify message
99*/
101 Callbacks& callbacks,
102 const Transcript_Hash& transcript_hash) const {
103 BOTAN_ASSERT_NOMSG(m_scheme.is_available());
104
105 // RFC 8446 4.2.3
106 // The keys found in certificates MUST [...] be of appropriate type for
107 // the signature algorithms they are used with.
108 if(m_scheme.key_algorithm_identifier() != public_key.algorithm_identifier()) {
109 throw TLS_Exception(Alert::IllegalParameter, "Signature algorithm does not match certificate's public key");
110 }
111
112 const bool signature_valid = callbacks.tls_verify_message(
113 public_key, m_scheme.padding_string(), m_scheme.format().value(), message(m_side, transcript_hash), m_signature);
114
115#if defined(BOTAN_UNSAFE_FUZZER_MODE)
116 BOTAN_UNUSED(signature_valid);
117 return true;
118#else
119 return signature_valid;
120#endif
121}
122
123} // namespace Botan::TLS
#define BOTAN_UNUSED
Definition assert.h:144
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
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 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 > m_signature
virtual std::vector< Signature_Scheme > allowed_signature_schemes() const
std::vector< uint8_t > Transcript_Hash
Definition tls_magic.h:93
bool value_exists(const std::vector< T > &vec, const V &val)
Definition stl_util.h:44