Coverage Report

Created: 2023-02-13 06:21

/src/botan/src/lib/tls/msg_cert_verify.cpp
Line
Count
Source (jump to first uncovered line)
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
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,
28
                                             Handshake_State& state,
29
                                             const Policy& policy,
30
                                             RandomNumberGenerator& rng,
31
                                             const Private_Key* priv_key)
32
0
   {
33
0
   BOTAN_ASSERT_NONNULL(priv_key);
34
35
0
   std::pair<std::string, Signature_Format> format =
36
0
      state.choose_sig_format(*priv_key, m_scheme, true, policy);
37
38
0
   m_signature =
39
0
      state.callbacks().tls_sign_message(*priv_key, rng, format.first, format.second,
40
0
                                         state.hash().get_contents());
41
42
0
   state.hash().update(io.send(*this));
43
0
   }
44
45
/*
46
* Deserialize a Certificate Verify message
47
*/
48
Certificate_Verify::Certificate_Verify(const std::vector<uint8_t>& buf)
49
1.70k
   {
50
1.70k
   TLS_Data_Reader reader("CertificateVerify", buf);
51
52
1.70k
   m_scheme = Signature_Scheme(reader.get_uint16_t());
53
1.70k
   m_signature = reader.get_range<uint8_t>(2, 0, 65535);
54
1.70k
   reader.assert_done();
55
56
1.70k
   if(!m_scheme.is_set())
57
1
      { throw Decoding_Error("Counterparty did not send hash/sig IDS"); }
58
1.70k
   }
59
60
/*
61
* Serialize a Certificate Verify message
62
*/
63
std::vector<uint8_t> Certificate_Verify::serialize() const
64
0
   {
65
0
   BOTAN_ASSERT_NOMSG(m_scheme.is_set());
66
0
   std::vector<uint8_t> buf;
67
0
   buf.reserve(2 + 2 + m_signature.size()); // work around GCC warning
68
69
0
   const auto code = m_scheme.wire_code();
70
0
   buf.push_back(get_byte<0>(code));
71
0
   buf.push_back(get_byte<1>(code));
72
73
0
   if(m_signature.size() > 0xFFFF)
74
0
      { throw Encoding_Error("Certificate_Verify signature too long to encode"); }
75
76
0
   const uint16_t sig_len = static_cast<uint16_t>(m_signature.size());
77
0
   buf.push_back(get_byte<0>(sig_len));
78
0
   buf.push_back(get_byte<1>(sig_len));
79
0
   buf += m_signature;
80
81
0
   return buf;
82
0
   }
83
84
85
bool Certificate_Verify_12::verify(const X509_Certificate& cert,
86
                                   const Handshake_State& state,
87
                                   const Policy& policy) const
88
0
   {
89
0
   std::unique_ptr<Public_Key> key(cert.subject_public_key());
90
91
0
   policy.check_peer_key_acceptable(*key);
92
93
0
   std::pair<std::string, Signature_Format> format =
94
0
      state.parse_sig_format(*key.get(), m_scheme, state.client_hello()->signature_schemes(), true, policy);
95
96
0
   const bool signature_valid =
97
0
      state.callbacks().tls_verify_message(*key, format.first, format.second,
98
0
                                           state.hash().get_contents(), m_signature);
99
100
0
#if defined(BOTAN_UNSAFE_FUZZER_MODE)
101
0
   BOTAN_UNUSED(signature_valid);
102
0
   return true;
103
104
#else
105
   return signature_valid;
106
107
#endif
108
0
   }
109
110
#if defined(BOTAN_HAS_TLS_13)
111
112
namespace {
113
114
std::vector<uint8_t> message(Connection_Side side, const Transcript_Hash& hash)
115
0
   {
116
0
   std::vector<uint8_t> msg(64, 0x20);
117
0
   msg.reserve(64 + 33 + 1 + hash.size());
118
119
0
   const std::string context_string = (side == TLS::Connection_Side::Server)
120
0
                                      ? "TLS 1.3, server CertificateVerify"
121
0
                                      : "TLS 1.3, client CertificateVerify";
122
123
0
   msg.insert(msg.end(), context_string.cbegin(), context_string.cend());
124
0
   msg.push_back(0x00);
125
126
0
   msg.insert(msg.end(), hash.cbegin(), hash.cend());
127
0
   return msg;
128
0
   }
129
130
Signature_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
0
   {
135
0
   for(Signature_Scheme scheme : allowed_schemes)
136
0
      {
137
0
      if(scheme.is_available()
138
0
         && scheme.is_suitable_for(key)
139
0
         && value_exists(peer_allowed_schemes, scheme))
140
0
         {
141
0
         return scheme;
142
0
         }
143
0
      }
144
145
0
   throw TLS_Exception(Alert::HandshakeFailure, "Failed to agree on a signature algorithm");
146
0
   }
147
148
}
149
150
/*
151
* Create a new Certificate Verify message for TLS 1.3
152
*/
153
Certificate_Verify_13::Certificate_Verify_13(
154
      const Certificate_13& certificate_msg,
155
      const std::vector<Signature_Scheme>& peer_allowed_schemes,
156
      const std::string& 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
0
   {
165
0
   BOTAN_ASSERT_NOMSG(!certificate_msg.empty());
166
167
0
   const auto* private_key = creds_mgr.private_key_for(
168
0
                                       certificate_msg.leaf(),
169
0
                                       m_side == Connection_Side::Client ? "tls-client" : "tls-server",
170
0
                                       hostname);
171
0
   if(!private_key)
172
0
      { throw TLS_Exception(Alert::InternalError, "Application did not provide a private key for its certificate"); }
173
174
0
   m_scheme = choose_signature_scheme(*private_key, policy.allowed_signature_schemes(), peer_allowed_schemes);
175
0
   BOTAN_ASSERT_NOMSG(m_scheme.is_available());
176
0
   BOTAN_ASSERT_NOMSG(m_scheme.is_compatible_with(Protocol_Version::TLS_V13));
177
178
0
   m_signature =
179
0
      callbacks.tls_sign_message(*private_key,
180
0
                                 rng,
181
0
                                 m_scheme.padding_string(),
182
0
                                 m_scheme.format().value(),
183
0
                                 message(m_side, hash));
184
0
   }
185
186
187
Certificate_Verify_13::Certificate_Verify_13(const std::vector<uint8_t>& buf,
188
                                             const Connection_Side side)
189
   : Certificate_Verify(buf)
190
   , m_side(side)
191
1.70k
   {
192
1.70k
   if(!m_scheme.is_available())
193
27
      { throw TLS_Exception(Alert::HandshakeFailure, "Peer sent unknown signature scheme"); }
194
195
1.67k
   if(!m_scheme.is_compatible_with(Protocol_Version::TLS_V13))
196
3
      { throw TLS_Exception(Alert::IllegalParameter, "Peer sent signature algorithm that is not suitable for TLS 1.3"); }
197
1.67k
   }
198
199
/*
200
* Verify a Certificate Verify message
201
*/
202
bool Certificate_Verify_13::verify(const X509_Certificate& cert,
203
                                   Callbacks& callbacks,
204
                                   const Transcript_Hash& transcript_hash) const
205
0
   {
206
0
   BOTAN_ASSERT_NOMSG(m_scheme.is_available());
207
208
   // RFC 8446 4.2.3
209
   //    The keys found in certificates MUST [...] be of appropriate type for
210
   //    the signature algorithms they are used with.
211
0
   if(m_scheme.key_algorithm_identifier() != cert.subject_public_key_algo())
212
0
      { throw TLS_Exception(Alert::IllegalParameter, "Signature algorithm does not match certificate's public key"); }
213
214
0
   const auto key = cert.subject_public_key();
215
0
   const bool signature_valid =
216
0
      callbacks.tls_verify_message(*key,
217
0
                                   m_scheme.padding_string(),
218
0
                                   m_scheme.format().value(),
219
0
                                   message(m_side, transcript_hash),
220
0
                                   m_signature);
221
222
0
#if defined(BOTAN_UNSAFE_FUZZER_MODE)
223
0
   BOTAN_UNUSED(signature_valid);
224
0
   return true;
225
#else
226
   return signature_valid;
227
#endif
228
0
   }
229
230
#endif  // BOTAN_HAS_TLS_13
231
232
}