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