/src/botan/src/lib/pubkey/pubkey.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * (C) 1999-2010,2015,2018 Jack Lloyd |
3 | | * |
4 | | * Botan is released under the Simplified BSD License (see license.txt) |
5 | | */ |
6 | | |
7 | | #include <botan/pubkey.h> |
8 | | |
9 | | #include <botan/ber_dec.h> |
10 | | #include <botan/bigint.h> |
11 | | #include <botan/der_enc.h> |
12 | | #include <botan/mem_ops.h> |
13 | | #include <botan/pk_ops.h> |
14 | | #include <botan/rng.h> |
15 | | #include <botan/internal/ct_utils.h> |
16 | | #include <botan/internal/fmt.h> |
17 | | #include <botan/internal/parsing.h> |
18 | | #include <botan/internal/pss_params.h> |
19 | | #include <botan/internal/stl_util.h> |
20 | | |
21 | | namespace Botan { |
22 | | |
23 | 0 | secure_vector<uint8_t> PK_Decryptor::decrypt(const uint8_t in[], size_t length) const { |
24 | 0 | uint8_t valid_mask = 0; |
25 | |
|
26 | 0 | secure_vector<uint8_t> decoded = do_decrypt(valid_mask, in, length); |
27 | |
|
28 | 0 | if(valid_mask == 0) { |
29 | 0 | throw Decoding_Error("Invalid public key ciphertext, cannot decrypt"); |
30 | 0 | } |
31 | | |
32 | 0 | return decoded; |
33 | 0 | } |
34 | | |
35 | | secure_vector<uint8_t> PK_Decryptor::decrypt_or_random(const uint8_t in[], |
36 | | size_t length, |
37 | | size_t expected_pt_len, |
38 | | RandomNumberGenerator& rng, |
39 | | const uint8_t required_content_bytes[], |
40 | | const uint8_t required_content_offsets[], |
41 | 0 | size_t required_contents_length) const { |
42 | 0 | const secure_vector<uint8_t> fake_pms = rng.random_vec(expected_pt_len); |
43 | |
|
44 | 0 | uint8_t decrypt_valid = 0; |
45 | 0 | secure_vector<uint8_t> decoded = do_decrypt(decrypt_valid, in, length); |
46 | |
|
47 | 0 | auto valid_mask = CT::Mask<uint8_t>::is_equal(decrypt_valid, 0xFF); |
48 | 0 | valid_mask &= CT::Mask<uint8_t>(CT::Mask<size_t>::is_zero(decoded.size() ^ expected_pt_len)); |
49 | |
|
50 | 0 | decoded.resize(expected_pt_len); |
51 | |
|
52 | 0 | for(size_t i = 0; i != required_contents_length; ++i) { |
53 | | /* |
54 | | These values are chosen by the application and for TLS are constants, |
55 | | so this early failure via assert is fine since we know 0,1 < 48 |
56 | | |
57 | | If there is a protocol that has content checks on the key where |
58 | | the expected offsets are controllable by the attacker this could |
59 | | still leak. |
60 | | |
61 | | Alternately could always reduce the offset modulo the length? |
62 | | */ |
63 | |
|
64 | 0 | const uint8_t exp = required_content_bytes[i]; |
65 | 0 | const uint8_t off = required_content_offsets[i]; |
66 | |
|
67 | 0 | BOTAN_ASSERT(off < expected_pt_len, "Offset in range of plaintext"); |
68 | |
|
69 | 0 | auto eq = CT::Mask<uint8_t>::is_equal(decoded[off], exp); |
70 | |
|
71 | 0 | valid_mask &= eq; |
72 | 0 | } |
73 | | |
74 | | // If valid_mask is false, assign fake pre master instead |
75 | 0 | valid_mask.select_n(decoded.data(), decoded.data(), fake_pms.data(), expected_pt_len); |
76 | |
|
77 | 0 | return decoded; |
78 | 0 | } |
79 | | |
80 | | secure_vector<uint8_t> PK_Decryptor::decrypt_or_random(const uint8_t in[], |
81 | | size_t length, |
82 | | size_t expected_pt_len, |
83 | 0 | RandomNumberGenerator& rng) const { |
84 | 0 | return decrypt_or_random(in, length, expected_pt_len, rng, nullptr, nullptr, 0); |
85 | 0 | } |
86 | | |
87 | | PK_Encryptor_EME::PK_Encryptor_EME(const Public_Key& key, |
88 | | RandomNumberGenerator& rng, |
89 | | std::string_view padding, |
90 | 0 | std::string_view provider) { |
91 | 0 | m_op = key.create_encryption_op(rng, padding, provider); |
92 | 0 | if(!m_op) { |
93 | 0 | throw Invalid_Argument(fmt("Key type {} does not support encryption", key.algo_name())); |
94 | 0 | } |
95 | 0 | } |
96 | | |
97 | 0 | PK_Encryptor_EME::~PK_Encryptor_EME() = default; |
98 | | |
99 | 0 | PK_Encryptor_EME::PK_Encryptor_EME(PK_Encryptor_EME&&) noexcept = default; |
100 | 0 | PK_Encryptor_EME& PK_Encryptor_EME::operator=(PK_Encryptor_EME&&) noexcept = default; |
101 | | |
102 | 0 | size_t PK_Encryptor_EME::ciphertext_length(size_t ptext_len) const { |
103 | 0 | return m_op->ciphertext_length(ptext_len); |
104 | 0 | } |
105 | | |
106 | 0 | std::vector<uint8_t> PK_Encryptor_EME::enc(const uint8_t in[], size_t length, RandomNumberGenerator& rng) const { |
107 | 0 | return m_op->encrypt(std::span{in, length}, rng); |
108 | 0 | } |
109 | | |
110 | 0 | size_t PK_Encryptor_EME::maximum_input_size() const { |
111 | 0 | return m_op->max_input_bits() / 8; |
112 | 0 | } |
113 | | |
114 | | PK_Decryptor_EME::PK_Decryptor_EME(const Private_Key& key, |
115 | | RandomNumberGenerator& rng, |
116 | | std::string_view padding, |
117 | 0 | std::string_view provider) { |
118 | 0 | m_op = key.create_decryption_op(rng, padding, provider); |
119 | 0 | if(!m_op) { |
120 | 0 | throw Invalid_Argument(fmt("Key type {} does not support decryption", key.algo_name())); |
121 | 0 | } |
122 | 0 | } |
123 | | |
124 | 0 | PK_Decryptor_EME::~PK_Decryptor_EME() = default; |
125 | | |
126 | 0 | PK_Decryptor_EME::PK_Decryptor_EME(PK_Decryptor_EME&&) noexcept = default; |
127 | 0 | PK_Decryptor_EME& PK_Decryptor_EME::operator=(PK_Decryptor_EME&&) noexcept = default; |
128 | | |
129 | 0 | size_t PK_Decryptor_EME::plaintext_length(size_t ctext_len) const { |
130 | 0 | return m_op->plaintext_length(ctext_len); |
131 | 0 | } |
132 | | |
133 | 0 | secure_vector<uint8_t> PK_Decryptor_EME::do_decrypt(uint8_t& valid_mask, const uint8_t in[], size_t in_len) const { |
134 | 0 | return m_op->decrypt(valid_mask, {in, in_len}); |
135 | 0 | } |
136 | | |
137 | 0 | PK_KEM_Encryptor::PK_KEM_Encryptor(const Public_Key& key, std::string_view param, std::string_view provider) { |
138 | 0 | m_op = key.create_kem_encryption_op(param, provider); |
139 | 0 | if(!m_op) { |
140 | 0 | throw Invalid_Argument(fmt("Key type {} does not support KEM encryption", key.algo_name())); |
141 | 0 | } |
142 | 0 | } |
143 | | |
144 | 0 | PK_KEM_Encryptor::~PK_KEM_Encryptor() = default; |
145 | | |
146 | 0 | PK_KEM_Encryptor::PK_KEM_Encryptor(PK_KEM_Encryptor&&) noexcept = default; |
147 | 0 | PK_KEM_Encryptor& PK_KEM_Encryptor::operator=(PK_KEM_Encryptor&&) noexcept = default; |
148 | | |
149 | 0 | size_t PK_KEM_Encryptor::shared_key_length(size_t desired_shared_key_len) const { |
150 | 0 | return m_op->shared_key_length(desired_shared_key_len); |
151 | 0 | } |
152 | | |
153 | 0 | size_t PK_KEM_Encryptor::encapsulated_key_length() const { |
154 | 0 | return m_op->encapsulated_key_length(); |
155 | 0 | } |
156 | | |
157 | | void PK_KEM_Encryptor::encrypt(std::span<uint8_t> out_encapsulated_key, |
158 | | std::span<uint8_t> out_shared_key, |
159 | | RandomNumberGenerator& rng, |
160 | | size_t desired_shared_key_len, |
161 | 0 | std::span<const uint8_t> salt) { |
162 | 0 | BOTAN_ARG_CHECK(out_encapsulated_key.size() == encapsulated_key_length(), "not enough space for encapsulated key"); |
163 | 0 | BOTAN_ARG_CHECK(out_shared_key.size() == shared_key_length(desired_shared_key_len), |
164 | 0 | "not enough space for shared key"); |
165 | 0 | m_op->kem_encrypt(out_encapsulated_key, out_shared_key, rng, desired_shared_key_len, salt); |
166 | 0 | } |
167 | | |
168 | 0 | size_t PK_KEM_Decryptor::shared_key_length(size_t desired_shared_key_len) const { |
169 | 0 | return m_op->shared_key_length(desired_shared_key_len); |
170 | 0 | } |
171 | | |
172 | 0 | size_t PK_KEM_Decryptor::encapsulated_key_length() const { |
173 | 0 | return m_op->encapsulated_key_length(); |
174 | 0 | } |
175 | | |
176 | | PK_KEM_Decryptor::PK_KEM_Decryptor(const Private_Key& key, |
177 | | RandomNumberGenerator& rng, |
178 | | std::string_view param, |
179 | 0 | std::string_view provider) { |
180 | 0 | m_op = key.create_kem_decryption_op(rng, param, provider); |
181 | 0 | if(!m_op) { |
182 | 0 | throw Invalid_Argument(fmt("Key type {} does not support KEM decryption", key.algo_name())); |
183 | 0 | } |
184 | 0 | } |
185 | | |
186 | 0 | PK_KEM_Decryptor::~PK_KEM_Decryptor() = default; |
187 | | |
188 | 0 | PK_KEM_Decryptor::PK_KEM_Decryptor(PK_KEM_Decryptor&&) noexcept = default; |
189 | 0 | PK_KEM_Decryptor& PK_KEM_Decryptor::operator=(PK_KEM_Decryptor&&) noexcept = default; |
190 | | |
191 | | void PK_KEM_Decryptor::decrypt(std::span<uint8_t> out_shared_key, |
192 | | std::span<const uint8_t> encap_key, |
193 | | size_t desired_shared_key_len, |
194 | 0 | std::span<const uint8_t> salt) { |
195 | 0 | BOTAN_ARG_CHECK(out_shared_key.size() == shared_key_length(desired_shared_key_len), |
196 | 0 | "inconsistent size of shared key output buffer"); |
197 | 0 | m_op->kem_decrypt(out_shared_key, encap_key, desired_shared_key_len, salt); |
198 | 0 | } |
199 | | |
200 | | PK_Key_Agreement::PK_Key_Agreement(const Private_Key& key, |
201 | | RandomNumberGenerator& rng, |
202 | | std::string_view kdf, |
203 | 0 | std::string_view provider) { |
204 | 0 | m_op = key.create_key_agreement_op(rng, kdf, provider); |
205 | 0 | if(!m_op) { |
206 | 0 | throw Invalid_Argument(fmt("Key type {} does not support key agreement", key.algo_name())); |
207 | 0 | } |
208 | 0 | } |
209 | | |
210 | 0 | PK_Key_Agreement::~PK_Key_Agreement() = default; |
211 | | |
212 | 0 | PK_Key_Agreement::PK_Key_Agreement(PK_Key_Agreement&&) noexcept = default; |
213 | 0 | PK_Key_Agreement& PK_Key_Agreement::operator=(PK_Key_Agreement&&) noexcept = default; |
214 | | |
215 | 0 | size_t PK_Key_Agreement::agreed_value_size() const { |
216 | 0 | return m_op->agreed_value_size(); |
217 | 0 | } |
218 | | |
219 | | SymmetricKey PK_Key_Agreement::derive_key(size_t key_len, |
220 | | const uint8_t in[], |
221 | | size_t in_len, |
222 | 0 | std::string_view params) const { |
223 | 0 | return this->derive_key(key_len, in, in_len, cast_char_ptr_to_uint8(params.data()), params.length()); |
224 | 0 | } |
225 | | |
226 | | SymmetricKey PK_Key_Agreement::derive_key(size_t key_len, |
227 | | const std::span<const uint8_t> in, |
228 | 0 | std::string_view params) const { |
229 | 0 | return this->derive_key(key_len, in.data(), in.size(), cast_char_ptr_to_uint8(params.data()), params.length()); |
230 | 0 | } |
231 | | |
232 | | SymmetricKey PK_Key_Agreement::derive_key( |
233 | 0 | size_t key_len, const uint8_t in[], size_t in_len, const uint8_t salt[], size_t salt_len) const { |
234 | 0 | return SymmetricKey(m_op->agree(key_len, {in, in_len}, {salt, salt_len})); |
235 | 0 | } |
236 | | |
237 | | namespace { |
238 | | |
239 | 1.18k | void check_der_format_supported(Signature_Format format, size_t parts) { |
240 | 1.18k | if(format != Signature_Format::Standard && parts == 1) { |
241 | 0 | throw Invalid_Argument("This algorithm does not support DER encoding"); |
242 | 0 | } |
243 | 1.18k | } |
244 | | |
245 | | } // namespace |
246 | | |
247 | | PK_Signer::PK_Signer(const Private_Key& key, |
248 | | RandomNumberGenerator& rng, |
249 | | std::string_view emsa, |
250 | | Signature_Format format, |
251 | 417 | std::string_view provider) { |
252 | 417 | m_op = key.create_signature_op(rng, emsa, provider); |
253 | 417 | if(!m_op) { |
254 | 0 | throw Invalid_Argument(fmt("Key type {} does not support signature generation", key.algo_name())); |
255 | 0 | } |
256 | 417 | m_sig_format = format; |
257 | 417 | m_parts = key.message_parts(); |
258 | 417 | m_part_size = key.message_part_size(); |
259 | 417 | check_der_format_supported(format, m_parts); |
260 | 417 | } |
261 | | |
262 | 0 | AlgorithmIdentifier PK_Signer::algorithm_identifier() const { |
263 | 0 | return m_op->algorithm_identifier(); |
264 | 0 | } |
265 | | |
266 | 0 | std::string PK_Signer::hash_function() const { |
267 | 0 | return m_op->hash_function(); |
268 | 0 | } |
269 | | |
270 | 407 | PK_Signer::~PK_Signer() = default; |
271 | | |
272 | 0 | PK_Signer::PK_Signer(PK_Signer&&) noexcept = default; |
273 | 0 | PK_Signer& PK_Signer::operator=(PK_Signer&&) noexcept = default; |
274 | | |
275 | 0 | void PK_Signer::update(std::string_view in) { |
276 | 0 | this->update(cast_char_ptr_to_uint8(in.data()), in.size()); |
277 | 0 | } |
278 | | |
279 | 407 | void PK_Signer::update(const uint8_t in[], size_t length) { |
280 | 407 | m_op->update({in, length}); |
281 | 407 | } |
282 | | |
283 | | namespace { |
284 | | |
285 | 251 | std::vector<uint8_t> der_encode_signature(std::span<const uint8_t> sig, size_t parts, size_t part_size) { |
286 | 251 | if(sig.size() % parts != 0 || sig.size() != parts * part_size) { |
287 | 0 | throw Encoding_Error("Unexpected size for DER signature"); |
288 | 0 | } |
289 | | |
290 | 251 | BufferSlicer bs_sig(sig); |
291 | 251 | std::vector<BigInt> sig_parts; |
292 | 251 | sig_parts.reserve(parts); |
293 | 753 | for(size_t i = 0; i != parts; ++i) { |
294 | 502 | sig_parts.emplace_back(BigInt::from_bytes(bs_sig.take(part_size))); |
295 | 502 | } |
296 | | |
297 | 251 | std::vector<uint8_t> output; |
298 | 251 | DER_Encoder(output).start_sequence().encode_list(sig_parts).end_cons(); |
299 | 251 | return output; |
300 | 251 | } |
301 | | |
302 | | } // namespace |
303 | | |
304 | 0 | size_t PK_Signer::signature_length() const { |
305 | 0 | if(m_sig_format == Signature_Format::Standard) { |
306 | 0 | return m_op->signature_length(); |
307 | 0 | } else if(m_sig_format == Signature_Format::DerSequence) { |
308 | | // This is a large over-estimate but its easier than computing |
309 | | // the exact value |
310 | 0 | return m_op->signature_length() + (8 + 4 * m_parts); |
311 | 0 | } else { |
312 | 0 | throw Internal_Error("PK_Signer: Invalid signature format enum"); |
313 | 0 | } |
314 | 0 | } |
315 | | |
316 | 407 | std::vector<uint8_t> PK_Signer::signature(RandomNumberGenerator& rng) { |
317 | 407 | std::vector<uint8_t> sig = m_op->sign(rng); |
318 | | |
319 | 407 | if(m_sig_format == Signature_Format::Standard) { |
320 | 50 | return sig; |
321 | 357 | } else if(m_sig_format == Signature_Format::DerSequence) { |
322 | 251 | return der_encode_signature(sig, m_parts, m_part_size); |
323 | 251 | } else { |
324 | 106 | throw Internal_Error("PK_Signer: Invalid signature format enum"); |
325 | 106 | } |
326 | 407 | } |
327 | | |
328 | | PK_Verifier::PK_Verifier(const Public_Key& key, |
329 | | std::string_view emsa, |
330 | | Signature_Format format, |
331 | 775 | std::string_view provider) { |
332 | 775 | m_op = key.create_verification_op(emsa, provider); |
333 | 775 | if(!m_op) { |
334 | 0 | throw Invalid_Argument(fmt("Key type {} does not support signature verification", key.algo_name())); |
335 | 0 | } |
336 | 775 | m_sig_format = format; |
337 | 775 | m_parts = key.message_parts(); |
338 | 775 | m_part_size = key.message_part_size(); |
339 | 775 | check_der_format_supported(format, m_parts); |
340 | 775 | } |
341 | | |
342 | | PK_Verifier::PK_Verifier(const Public_Key& key, |
343 | | const AlgorithmIdentifier& signature_algorithm, |
344 | 0 | std::string_view provider) { |
345 | 0 | m_op = key.create_x509_verification_op(signature_algorithm, provider); |
346 | |
|
347 | 0 | if(!m_op) { |
348 | 0 | throw Invalid_Argument(fmt("Key type {} does not support X.509 signature verification", key.algo_name())); |
349 | 0 | } |
350 | | |
351 | 0 | m_sig_format = key.default_x509_signature_format(); |
352 | 0 | m_parts = key.message_parts(); |
353 | 0 | m_part_size = key.message_part_size(); |
354 | 0 | check_der_format_supported(m_sig_format, m_parts); |
355 | 0 | } |
356 | | |
357 | 775 | PK_Verifier::~PK_Verifier() = default; |
358 | | |
359 | 0 | PK_Verifier::PK_Verifier(PK_Verifier&&) noexcept = default; |
360 | 0 | PK_Verifier& PK_Verifier::operator=(PK_Verifier&&) noexcept = default; |
361 | | |
362 | 0 | std::string PK_Verifier::hash_function() const { |
363 | 0 | return m_op->hash_function(); |
364 | 0 | } |
365 | | |
366 | 0 | void PK_Verifier::set_input_format(Signature_Format format) { |
367 | 0 | check_der_format_supported(format, m_parts); |
368 | 0 | m_sig_format = format; |
369 | 0 | } |
370 | | |
371 | 775 | bool PK_Verifier::verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length) { |
372 | 775 | update(msg, msg_length); |
373 | 775 | return check_signature(sig, sig_length); |
374 | 775 | } |
375 | | |
376 | 0 | void PK_Verifier::update(std::string_view in) { |
377 | 0 | this->update(cast_char_ptr_to_uint8(in.data()), in.size()); |
378 | 0 | } |
379 | | |
380 | 775 | void PK_Verifier::update(const uint8_t in[], size_t length) { |
381 | 775 | m_op->update({in, length}); |
382 | 775 | } |
383 | | |
384 | | namespace { |
385 | | |
386 | 0 | std::vector<uint8_t> decode_der_signature(const uint8_t sig[], size_t length, size_t sig_parts, size_t sig_part_size) { |
387 | 0 | std::vector<uint8_t> real_sig; |
388 | 0 | BER_Decoder decoder(sig, length); |
389 | 0 | BER_Decoder ber_sig = decoder.start_sequence(); |
390 | |
|
391 | 0 | BOTAN_ASSERT_NOMSG(sig_parts != 0 && sig_part_size != 0); |
392 | |
|
393 | 0 | size_t count = 0; |
394 | |
|
395 | 0 | while(ber_sig.more_items()) { |
396 | 0 | BigInt sig_part; |
397 | 0 | ber_sig.decode(sig_part); |
398 | 0 | real_sig += sig_part.serialize(sig_part_size); |
399 | 0 | ++count; |
400 | 0 | } |
401 | |
|
402 | 0 | if(count != sig_parts) { |
403 | 0 | throw Decoding_Error("PK_Verifier: signature size invalid"); |
404 | 0 | } |
405 | | |
406 | 0 | const std::vector<uint8_t> reencoded = der_encode_signature(real_sig, sig_parts, sig_part_size); |
407 | |
|
408 | 0 | if(reencoded.size() != length || CT::is_equal(reencoded.data(), sig, reencoded.size()).as_bool() == false) { |
409 | 0 | throw Decoding_Error("PK_Verifier: signature is not the canonical DER encoding"); |
410 | 0 | } |
411 | 0 | return real_sig; |
412 | 0 | } |
413 | | |
414 | | } // namespace |
415 | | |
416 | 775 | bool PK_Verifier::check_signature(const uint8_t sig[], size_t length) { |
417 | 775 | try { |
418 | 775 | if(m_sig_format == Signature_Format::Standard) { |
419 | 775 | return m_op->is_valid_signature({sig, length}); |
420 | 775 | } else if(m_sig_format == Signature_Format::DerSequence) { |
421 | 0 | bool decoding_success = false; |
422 | 0 | std::vector<uint8_t> real_sig; |
423 | |
|
424 | 0 | try { |
425 | 0 | real_sig = decode_der_signature(sig, length, m_parts, m_part_size); |
426 | 0 | decoding_success = true; |
427 | 0 | } catch(Decoding_Error&) {} |
428 | |
|
429 | 0 | bool accept = m_op->is_valid_signature(real_sig); |
430 | |
|
431 | 0 | return accept && decoding_success; |
432 | 0 | } else { |
433 | 0 | throw Internal_Error("PK_Verifier: Invalid signature format enum"); |
434 | 0 | } |
435 | 775 | } catch(Invalid_Argument&) { |
436 | 0 | return false; |
437 | 0 | } catch(Decoding_Error&) { |
438 | 0 | return false; |
439 | 0 | } catch(Encoding_Error&) { |
440 | 0 | return false; |
441 | 0 | } |
442 | 775 | } |
443 | | |
444 | | } // namespace Botan |