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

randombit / botan / 21610880055

03 Feb 2026 12:00AM UTC coverage: 90.07%. Remained the same
21610880055

push

github

web-flow
Merge pull request #5280 from randombit/jack/reduce-tls-headers

Reduce header pollution in TLS headers

102228 of 113498 relevant lines covered (90.07%)

11548178.67 hits per line

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

95.35
/src/lib/tls/msg_cert_verify.cpp
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_callbacks.h>
16
#include <botan/tls_extensions.h>
17
#include <botan/tls_policy.h>
18
#include <botan/internal/stl_util.h>
19
#include <botan/internal/target_info.h>
20
#include <botan/internal/tls_handshake_io.h>
21
#include <botan/internal/tls_handshake_state.h>
22
#include <botan/internal/tls_reader.h>
23

24
namespace Botan::TLS {
25

26
/*
27
* Create a new Certificate Verify message for TLS 1.2
28
*/
29
Certificate_Verify_12::Certificate_Verify_12(Handshake_IO& io,
92✔
30
                                             Handshake_State& state,
31
                                             const Policy& policy,
32
                                             RandomNumberGenerator& rng,
33
                                             const Private_Key* priv_key) {
92✔
34
   BOTAN_ASSERT_NONNULL(priv_key);
92✔
35

36
   const std::pair<std::string, Signature_Format> format = state.choose_sig_format(*priv_key, m_scheme, true, policy);
92✔
37

38
   m_signature =
89✔
39
      state.callbacks().tls_sign_message(*priv_key, rng, format.first, format.second, state.hash().get_contents());
89✔
40

41
   state.hash().update(io.send(*this));
267✔
42
}
92✔
43

44
/*
45
* Deserialize a Certificate Verify message
46
*/
47
Certificate_Verify::Certificate_Verify(const std::vector<uint8_t>& buf) {
528✔
48
   TLS_Data_Reader reader("CertificateVerify", buf);
528✔
49

50
   m_scheme = Signature_Scheme(reader.get_uint16_t());
528✔
51
   m_signature = reader.get_range<uint8_t>(2, 0, 65535);
527✔
52
   reader.assert_done();
526✔
53

54
   if(!m_scheme.is_set()) {
522✔
55
      throw Decoding_Error("Counterparty did not send hash/sig IDS");
×
56
   }
57
}
528✔
58

59
/*
60
* Serialize a Certificate Verify message
61
*/
62
std::vector<uint8_t> Certificate_Verify::serialize() const {
399✔
63
   BOTAN_ASSERT_NOMSG(m_scheme.is_set());
399✔
64
   std::vector<uint8_t> buf;
399✔
65
   buf.reserve(2 + 2 + m_signature.size());  // work around GCC warning
399✔
66

67
   const auto code = m_scheme.wire_code();
798✔
68
   buf.push_back(get_byte<0>(code));
399✔
69
   buf.push_back(get_byte<1>(code));
399✔
70

71
   if(m_signature.size() > 0xFFFF) {
399✔
72
      throw Encoding_Error("Certificate_Verify signature too long to encode");
×
73
   }
74

75
   const uint16_t sig_len = static_cast<uint16_t>(m_signature.size());
399✔
76
   buf.push_back(get_byte<0>(sig_len));
399✔
77
   buf.push_back(get_byte<1>(sig_len));
399✔
78
   buf += m_signature;
399✔
79

80
   return buf;
399✔
81
}
×
82

83
bool Certificate_Verify_12::verify(const X509_Certificate& cert,
168✔
84
                                   const Handshake_State& state,
85
                                   const Policy& policy) const {
86
   auto key = cert.subject_public_key();
168✔
87

88
   policy.check_peer_key_acceptable(*key);
168✔
89

90
   const std::pair<std::string, Signature_Format> format =
168✔
91
      state.parse_sig_format(*key, m_scheme, state.client_hello()->signature_schemes(), true, policy);
172✔
92

93
   const bool signature_valid =
164✔
94
      state.callbacks().tls_verify_message(*key, format.first, format.second, state.hash().get_contents(), m_signature);
164✔
95

96
#if defined(BOTAN_UNSAFE_FUZZER_MODE)
97
   BOTAN_UNUSED(signature_valid);
98
   return true;
99

100
#else
101
   return signature_valid;
164✔
102

103
#endif
104
}
328✔
105

106
#if defined(BOTAN_HAS_TLS_13)
107

108
namespace {
109

110
std::vector<uint8_t> message(Connection_Side side, const Transcript_Hash& hash) {
620✔
111
   std::vector<uint8_t> msg(64, 0x20);
620✔
112
   msg.reserve(64 + 33 + 1 + hash.size());
620✔
113

114
   const std::string context_string = (side == TLS::Connection_Side::Server) ? "TLS 1.3, server CertificateVerify"
620✔
115
                                                                             : "TLS 1.3, client CertificateVerify";
713✔
116

117
   msg.insert(msg.end(), context_string.cbegin(), context_string.cend());
620✔
118
   msg.push_back(0x00);
620✔
119

120
   msg.insert(msg.end(), hash.cbegin(), hash.cend());
620✔
121
   return msg;
620✔
122
}
620✔
123

124
Signature_Scheme choose_signature_scheme(const Private_Key& key,
302✔
125
                                         const std::vector<Signature_Scheme>& allowed_schemes,
126
                                         const std::vector<Signature_Scheme>& peer_allowed_schemes) {
127
   for(Signature_Scheme scheme : allowed_schemes) {
555✔
128
      if(scheme.is_available() && scheme.is_suitable_for(key) && value_exists(peer_allowed_schemes, scheme)) {
860✔
129
         return scheme;
297✔
130
      }
131
   }
132

133
   throw TLS_Exception(Alert::HandshakeFailure, "Failed to agree on a signature algorithm");
5✔
134
}
135

136
}  // namespace
137

138
/*
139
* Create a new Certificate Verify message for TLS 1.3
140
*/
141
Certificate_Verify_13::Certificate_Verify_13(const Certificate_13& certificate_msg,
302✔
142
                                             const std::vector<Signature_Scheme>& peer_allowed_schemes,
143
                                             std::string_view hostname,
144
                                             const Transcript_Hash& hash,
145
                                             Connection_Side whoami,
146
                                             Credentials_Manager& creds_mgr,
147
                                             const Policy& policy,
148
                                             Callbacks& callbacks,
149
                                             RandomNumberGenerator& rng) :
302✔
150
      m_side(whoami) {
302✔
151
   BOTAN_ASSERT_NOMSG(!certificate_msg.empty());
302✔
152

153
   const std::string op_type((m_side == Connection_Side::Client) ? "tls-client" : "tls-server");
558✔
154
   const auto context = std::string(hostname);
610✔
155

156
   const auto private_key = (certificate_msg.has_certificate_chain())
302✔
157
                               ? creds_mgr.private_key_for(certificate_msg.leaf(), op_type, context)
302✔
158
                               : creds_mgr.private_key_for(*certificate_msg.public_key(), op_type, context);
310✔
159
   if(!private_key) {
302✔
160
      throw TLS_Exception(Alert::InternalError, "Application did not provide a private key for its credential");
×
161
   }
162

163
   m_scheme = choose_signature_scheme(*private_key, policy.allowed_signature_schemes(), peer_allowed_schemes);
302✔
164
   BOTAN_ASSERT_NOMSG(m_scheme.is_available());
297✔
165
   BOTAN_ASSERT_NOMSG(m_scheme.is_compatible_with(Protocol_Version::TLS_V13));
297✔
166

167
   m_signature = callbacks.tls_sign_message(
593✔
168
      *private_key, rng, m_scheme.padding_string(), m_scheme.format().value(), message(m_side, hash));
896✔
169
}
314✔
170

171
Certificate_Verify_13::Certificate_Verify_13(const std::vector<uint8_t>& buf, const Connection_Side side) :
353✔
172
      Certificate_Verify(buf), m_side(side) {
353✔
173
   if(!m_scheme.is_available()) {
351✔
174
      throw TLS_Exception(Alert::IllegalParameter, "Peer sent unknown signature scheme");
2✔
175
   }
176

177
   if(!m_scheme.is_compatible_with(Protocol_Version::TLS_V13)) {
349✔
178
      throw TLS_Exception(Alert::IllegalParameter, "Peer sent signature algorithm that is not suitable for TLS 1.3");
12✔
179
   }
180
}
351✔
181

182
/*
183
* Verify a Certificate Verify message
184
*/
185
bool Certificate_Verify_13::verify(const Public_Key& public_key,
330✔
186
                                   Callbacks& callbacks,
187
                                   const Transcript_Hash& transcript_hash) const {
188
   BOTAN_ASSERT_NOMSG(m_scheme.is_available());
330✔
189

190
   // RFC 8446 4.2.3
191
   //    The keys found in certificates MUST [...] be of appropriate type for
192
   //    the signature algorithms they are used with.
193
   if(m_scheme.key_algorithm_identifier() != public_key.algorithm_identifier()) {
330✔
194
      throw TLS_Exception(Alert::IllegalParameter, "Signature algorithm does not match certificate's public key");
7✔
195
   }
196

197
   const bool signature_valid = callbacks.tls_verify_message(
323✔
198
      public_key, m_scheme.padding_string(), m_scheme.format().value(), message(m_side, transcript_hash), m_signature);
646✔
199

200
   #if defined(BOTAN_UNSAFE_FUZZER_MODE)
201
   BOTAN_UNUSED(signature_valid);
202
   return true;
203
   #else
204
   return signature_valid;
323✔
205
   #endif
206
}
207

208
#endif  // BOTAN_HAS_TLS_13
209

210
}  // 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