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

randombit / botan / 5079590438

25 May 2023 12:28PM UTC coverage: 92.228% (+0.5%) from 91.723%
5079590438

Pull #3502

github

Pull Request #3502: Apply clang-format to the codebase

75589 of 81959 relevant lines covered (92.23%)

12139530.51 hits per line

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

95.29
/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_algos.h>
16
#include <botan/tls_extensions.h>
17
#include <botan/internal/stl_util.h>
18
#include <botan/internal/tls_handshake_io.h>
19
#include <botan/internal/tls_handshake_state.h>
20
#include <botan/internal/tls_reader.h>
21

22
namespace Botan::TLS {
23

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

34
   std::pair<std::string, Signature_Format> format = state.choose_sig_format(*priv_key, m_scheme, true, policy);
80✔
35

36
   m_signature =
79✔
37
      state.callbacks().tls_sign_message(*priv_key, rng, format.first, format.second, state.hash().get_contents());
79✔
38

39
   state.hash().update(io.send(*this));
237✔
40
}
80✔
41

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

48
   m_scheme = Signature_Scheme(reader.get_uint16_t());
482✔
49
   m_signature = reader.get_range<uint8_t>(2, 0, 65535);
481✔
50
   reader.assert_done();
480✔
51

52
   if(!m_scheme.is_set()) {
476✔
53
      throw Decoding_Error("Counterparty did not send hash/sig IDS");
×
54
   }
55
}
482✔
56

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

65
   const auto code = m_scheme.wire_code();
369✔
66
   buf.push_back(get_byte<0>(code));
369✔
67
   buf.push_back(get_byte<1>(code));
369✔
68

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

73
   const uint16_t sig_len = static_cast<uint16_t>(m_signature.size());
369✔
74
   buf.push_back(get_byte<0>(sig_len));
369✔
75
   buf.push_back(get_byte<1>(sig_len));
369✔
76
   buf += m_signature;
369✔
77

78
   return buf;
369✔
79
}
×
80

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

86
   policy.check_peer_key_acceptable(*key);
128✔
87

88
   std::pair<std::string, Signature_Format> format =
128✔
89
      state.parse_sig_format(*key, m_scheme, state.client_hello()->signature_schemes(), true, policy);
130✔
90

91
   const bool signature_valid =
126✔
92
      state.callbacks().tls_verify_message(*key, format.first, format.second, state.hash().get_contents(), m_signature);
126✔
93

94
#if defined(BOTAN_UNSAFE_FUZZER_MODE)
95
   BOTAN_UNUSED(signature_valid);
96
   return true;
97

98
#else
99
   return signature_valid;
126✔
100

101
#endif
102
}
252✔
103

104
#if defined(BOTAN_HAS_TLS_13)
105

106
namespace {
107

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

112
   const std::string context_string = (side == TLS::Connection_Side::Server) ? "TLS 1.3, server CertificateVerify"
590✔
113
                                                                             : "TLS 1.3, client CertificateVerify";
675✔
114

115
   msg.insert(msg.end(), context_string.cbegin(), context_string.cend());
590✔
116
   msg.push_back(0x00);
590✔
117

118
   msg.insert(msg.end(), hash.cbegin(), hash.cend());
590✔
119
   return msg;
590✔
120
}
590✔
121

122
Signature_Scheme choose_signature_scheme(const Private_Key& key,
284✔
123
                                         const std::vector<Signature_Scheme>& allowed_schemes,
124
                                         const std::vector<Signature_Scheme>& peer_allowed_schemes) {
125
   for(Signature_Scheme scheme : allowed_schemes) {
721✔
126
      if(scheme.is_available() && scheme.is_suitable_for(key) && value_exists(peer_allowed_schemes, scheme)) {
1,233✔
127
         return scheme;
281✔
128
      }
129
   }
130

131
   throw TLS_Exception(Alert::HandshakeFailure, "Failed to agree on a signature algorithm");
3✔
132
}
133

134
}
135

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

151
   const auto private_key = creds_mgr.private_key_for(
284✔
152
      certificate_msg.leaf(), m_side == Connection_Side::Client ? "tls-client" : "tls-server", std::string(hostname));
1,098✔
153

154
   if(!private_key) {
284✔
155
      throw TLS_Exception(Alert::InternalError, "Application did not provide a private key for its certificate");
×
156
   }
157

158
   m_scheme = choose_signature_scheme(*private_key, policy.allowed_signature_schemes(), peer_allowed_schemes);
287✔
159
   BOTAN_ASSERT_NOMSG(m_scheme.is_available());
281✔
160
   BOTAN_ASSERT_NOMSG(m_scheme.is_compatible_with(Protocol_Version::TLS_V13));
281✔
161

162
   m_signature = callbacks.tls_sign_message(
561✔
163
      *private_key, rng, m_scheme.padding_string(), m_scheme.format().value(), message(m_side, hash));
846✔
164
}
284✔
165

166
Certificate_Verify_13::Certificate_Verify_13(const std::vector<uint8_t>& buf, const Connection_Side side) :
347✔
167
      Certificate_Verify(buf), m_side(side) {
347✔
168
   if(!m_scheme.is_available()) {
345✔
169
      throw TLS_Exception(Alert::HandshakeFailure, "Peer sent unknown signature scheme");
10✔
170
   }
171

172
   if(!m_scheme.is_compatible_with(Protocol_Version::TLS_V13)) {
335✔
173
      throw TLS_Exception(Alert::IllegalParameter, "Peer sent signature algorithm that is not suitable for TLS 1.3");
12✔
174
   }
175
}
345✔
176

177
/*
178
* Verify a Certificate Verify message
179
*/
180
bool Certificate_Verify_13::verify(const X509_Certificate& cert,
316✔
181
                                   Callbacks& callbacks,
182
                                   const Transcript_Hash& transcript_hash) const {
183
   BOTAN_ASSERT_NOMSG(m_scheme.is_available());
316✔
184

185
   // RFC 8446 4.2.3
186
   //    The keys found in certificates MUST [...] be of appropriate type for
187
   //    the signature algorithms they are used with.
188
   if(m_scheme.key_algorithm_identifier() != cert.subject_public_key_algo()) {
316✔
189
      throw TLS_Exception(Alert::IllegalParameter, "Signature algorithm does not match certificate's public key");
7✔
190
   }
191

192
   const auto key = cert.subject_public_key();
309✔
193
   const bool signature_valid = callbacks.tls_verify_message(
309✔
194
      *key, m_scheme.padding_string(), m_scheme.format().value(), message(m_side, transcript_hash), m_signature);
618✔
195

196
   #if defined(BOTAN_UNSAFE_FUZZER_MODE)
197
   BOTAN_UNUSED(signature_valid);
198
   return true;
199
   #else
200
   return signature_valid;
309✔
201
   #endif
202
}
309✔
203

204
#endif  // BOTAN_HAS_TLS_13
205

206
}
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

© 2025 Coveralls, Inc