/src/botan/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/pss_params.h> |
15 | | #include <botan/rng.h> |
16 | | #include <botan/internal/ct_utils.h> |
17 | | #include <botan/internal/fmt.h> |
18 | | #include <botan/internal/mem_utils.h> |
19 | | #include <botan/internal/parsing.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 = [&]() { |
43 | 0 | auto pms = rng.random_vec(expected_pt_len); |
44 | |
|
45 | 0 | for(size_t i = 0; i != required_contents_length; ++i) { |
46 | 0 | const uint8_t exp = required_content_bytes[i]; |
47 | | |
48 | | /* |
49 | | If an offset repeats we don't detect this and just return a PMS that satisfies |
50 | | the last requested index. If the requested (idx,value) tuple is the same, that's |
51 | | fine and just redundant. If they disagree, decryption will always fail, since the |
52 | | same byte cannot possibly have two distinct values. |
53 | | */ |
54 | 0 | const uint8_t off = required_content_offsets[i]; |
55 | 0 | BOTAN_ASSERT(off < expected_pt_len, "Offset in range of plaintext"); |
56 | 0 | pms[off] = exp; |
57 | 0 | } |
58 | |
|
59 | 0 | return pms; |
60 | 0 | }(); |
61 | |
|
62 | 0 | uint8_t decrypt_valid = 0; |
63 | 0 | secure_vector<uint8_t> decoded = do_decrypt(decrypt_valid, in, length); |
64 | |
|
65 | 0 | auto valid_mask = CT::Mask<uint8_t>::is_equal(decrypt_valid, 0xFF); |
66 | 0 | valid_mask &= CT::Mask<uint8_t>(CT::Mask<size_t>::is_equal(decoded.size(), expected_pt_len)); |
67 | |
|
68 | 0 | decoded.resize(expected_pt_len); |
69 | |
|
70 | 0 | for(size_t i = 0; i != required_contents_length; ++i) { |
71 | 0 | const uint8_t exp = required_content_bytes[i]; |
72 | | |
73 | | // We know off is in range because we already checked it when creating the fake premaster above |
74 | 0 | const uint8_t off = required_content_offsets[i]; |
75 | |
|
76 | 0 | auto eq = CT::Mask<uint8_t>::is_equal(decoded[off], exp); |
77 | |
|
78 | 0 | valid_mask &= eq; |
79 | 0 | } |
80 | | |
81 | | // If valid_mask is false, assign fake pre master instead |
82 | 0 | valid_mask.select_n(decoded.data(), decoded.data(), fake_pms.data(), expected_pt_len); |
83 | |
|
84 | 0 | return decoded; |
85 | 0 | } |
86 | | |
87 | | secure_vector<uint8_t> PK_Decryptor::decrypt_or_random(const uint8_t in[], |
88 | | size_t length, |
89 | | size_t expected_pt_len, |
90 | 0 | RandomNumberGenerator& rng) const { |
91 | 0 | return decrypt_or_random(in, length, expected_pt_len, rng, nullptr, nullptr, 0); |
92 | 0 | } |
93 | | |
94 | | PK_Encryptor_EME::PK_Encryptor_EME(const Public_Key& key, |
95 | | RandomNumberGenerator& rng, |
96 | | std::string_view padding, |
97 | 0 | std::string_view provider) { |
98 | 0 | m_op = key.create_encryption_op(rng, padding, provider); |
99 | 0 | if(!m_op) { |
100 | 0 | throw Invalid_Argument(fmt("Key type {} does not support encryption", key.algo_name())); |
101 | 0 | } |
102 | 0 | } |
103 | | |
104 | 0 | PK_Encryptor_EME::~PK_Encryptor_EME() = default; |
105 | | |
106 | 0 | PK_Encryptor_EME::PK_Encryptor_EME(PK_Encryptor_EME&&) noexcept = default; |
107 | 0 | PK_Encryptor_EME& PK_Encryptor_EME::operator=(PK_Encryptor_EME&&) noexcept = default; |
108 | | |
109 | 0 | size_t PK_Encryptor_EME::ciphertext_length(size_t ptext_len) const { |
110 | 0 | return m_op->ciphertext_length(ptext_len); |
111 | 0 | } |
112 | | |
113 | 0 | std::vector<uint8_t> PK_Encryptor_EME::enc(const uint8_t ptext[], size_t len, RandomNumberGenerator& rng) const { |
114 | 0 | return m_op->encrypt(std::span{ptext, len}, rng); |
115 | 0 | } |
116 | | |
117 | 0 | size_t PK_Encryptor_EME::maximum_input_size() const { |
118 | 0 | return m_op->max_input_bits() / 8; |
119 | 0 | } |
120 | | |
121 | | PK_Decryptor_EME::PK_Decryptor_EME(const Private_Key& key, |
122 | | RandomNumberGenerator& rng, |
123 | | std::string_view padding, |
124 | 0 | std::string_view provider) { |
125 | 0 | m_op = key.create_decryption_op(rng, padding, provider); |
126 | 0 | if(!m_op) { |
127 | 0 | throw Invalid_Argument(fmt("Key type {} does not support decryption", key.algo_name())); |
128 | 0 | } |
129 | 0 | } |
130 | | |
131 | 0 | PK_Decryptor_EME::~PK_Decryptor_EME() = default; |
132 | | |
133 | 0 | PK_Decryptor_EME::PK_Decryptor_EME(PK_Decryptor_EME&&) noexcept = default; |
134 | 0 | PK_Decryptor_EME& PK_Decryptor_EME::operator=(PK_Decryptor_EME&&) noexcept = default; |
135 | | |
136 | 0 | size_t PK_Decryptor_EME::plaintext_length(size_t ctext_len) const { |
137 | 0 | return m_op->plaintext_length(ctext_len); |
138 | 0 | } |
139 | | |
140 | 0 | secure_vector<uint8_t> PK_Decryptor_EME::do_decrypt(uint8_t& valid_mask, const uint8_t in[], size_t in_len) const { |
141 | 0 | return m_op->decrypt(valid_mask, {in, in_len}); |
142 | 0 | } |
143 | | |
144 | 0 | PK_KEM_Encryptor::PK_KEM_Encryptor(const Public_Key& key, std::string_view param, std::string_view provider) { |
145 | 0 | m_op = key.create_kem_encryption_op(param, provider); |
146 | 0 | if(!m_op) { |
147 | 0 | throw Invalid_Argument(fmt("Key type {} does not support KEM encryption", key.algo_name())); |
148 | 0 | } |
149 | 0 | } |
150 | | |
151 | | PK_KEM_Encryptor::PK_KEM_Encryptor(const Public_Key& key, |
152 | | RandomNumberGenerator& rng, |
153 | | std::string_view kem_param, |
154 | | std::string_view provider) : |
155 | 0 | PK_KEM_Encryptor(key, kem_param, provider) { |
156 | 0 | BOTAN_UNUSED(rng); |
157 | 0 | } |
158 | | |
159 | 0 | PK_KEM_Encryptor::~PK_KEM_Encryptor() = default; |
160 | | |
161 | 0 | PK_KEM_Encryptor::PK_KEM_Encryptor(PK_KEM_Encryptor&&) noexcept = default; |
162 | 0 | PK_KEM_Encryptor& PK_KEM_Encryptor::operator=(PK_KEM_Encryptor&&) noexcept = default; |
163 | | |
164 | 0 | size_t PK_KEM_Encryptor::shared_key_length(size_t desired_shared_key_len) const { |
165 | 0 | return m_op->shared_key_length(desired_shared_key_len); |
166 | 0 | } |
167 | | |
168 | 0 | size_t PK_KEM_Encryptor::encapsulated_key_length() const { |
169 | 0 | return m_op->encapsulated_key_length(); |
170 | 0 | } |
171 | | |
172 | | void PK_KEM_Encryptor::encrypt(std::span<uint8_t> out_encapsulated_key, |
173 | | std::span<uint8_t> out_shared_key, |
174 | | RandomNumberGenerator& rng, |
175 | | size_t desired_shared_key_len, |
176 | 0 | std::span<const uint8_t> salt) { |
177 | 0 | BOTAN_ARG_CHECK(out_encapsulated_key.size() == encapsulated_key_length(), "not enough space for encapsulated key"); |
178 | 0 | BOTAN_ARG_CHECK(out_shared_key.size() == shared_key_length(desired_shared_key_len), |
179 | 0 | "not enough space for shared key"); |
180 | 0 | m_op->kem_encrypt(out_encapsulated_key, out_shared_key, rng, desired_shared_key_len, salt); |
181 | 0 | } |
182 | | |
183 | 0 | size_t PK_KEM_Decryptor::shared_key_length(size_t desired_shared_key_len) const { |
184 | 0 | return m_op->shared_key_length(desired_shared_key_len); |
185 | 0 | } |
186 | | |
187 | 0 | size_t PK_KEM_Decryptor::encapsulated_key_length() const { |
188 | 0 | return m_op->encapsulated_key_length(); |
189 | 0 | } |
190 | | |
191 | | PK_KEM_Decryptor::PK_KEM_Decryptor(const Private_Key& key, |
192 | | RandomNumberGenerator& rng, |
193 | | std::string_view param, |
194 | 0 | std::string_view provider) { |
195 | 0 | m_op = key.create_kem_decryption_op(rng, param, provider); |
196 | 0 | if(!m_op) { |
197 | 0 | throw Invalid_Argument(fmt("Key type {} does not support KEM decryption", key.algo_name())); |
198 | 0 | } |
199 | 0 | } |
200 | | |
201 | 0 | PK_KEM_Decryptor::~PK_KEM_Decryptor() = default; |
202 | | |
203 | 0 | PK_KEM_Decryptor::PK_KEM_Decryptor(PK_KEM_Decryptor&&) noexcept = default; |
204 | 0 | PK_KEM_Decryptor& PK_KEM_Decryptor::operator=(PK_KEM_Decryptor&&) noexcept = default; |
205 | | |
206 | | void PK_KEM_Decryptor::decrypt(std::span<uint8_t> out_shared_key, |
207 | | std::span<const uint8_t> encap_key, |
208 | | size_t desired_shared_key_len, |
209 | 0 | std::span<const uint8_t> salt) { |
210 | 0 | BOTAN_ARG_CHECK(out_shared_key.size() == shared_key_length(desired_shared_key_len), |
211 | 0 | "inconsistent size of shared key output buffer"); |
212 | 0 | m_op->kem_decrypt(out_shared_key, encap_key, desired_shared_key_len, salt); |
213 | 0 | } |
214 | | |
215 | | PK_Key_Agreement::PK_Key_Agreement(const Private_Key& key, |
216 | | RandomNumberGenerator& rng, |
217 | | std::string_view kdf, |
218 | 0 | std::string_view provider) { |
219 | 0 | m_op = key.create_key_agreement_op(rng, kdf, provider); |
220 | 0 | if(!m_op) { |
221 | 0 | throw Invalid_Argument(fmt("Key type {} does not support key agreement", key.algo_name())); |
222 | 0 | } |
223 | 0 | } |
224 | | |
225 | 0 | PK_Key_Agreement::~PK_Key_Agreement() = default; |
226 | | |
227 | 0 | PK_Key_Agreement::PK_Key_Agreement(PK_Key_Agreement&&) noexcept = default; |
228 | 0 | PK_Key_Agreement& PK_Key_Agreement::operator=(PK_Key_Agreement&&) noexcept = default; |
229 | | |
230 | 0 | size_t PK_Key_Agreement::agreed_value_size() const { |
231 | 0 | return m_op->agreed_value_size(); |
232 | 0 | } |
233 | | |
234 | | SymmetricKey PK_Key_Agreement::derive_key(size_t key_len, |
235 | | const uint8_t peer_key[], |
236 | | size_t peer_key_len, |
237 | 0 | std::string_view salt) const { |
238 | 0 | return this->derive_key(key_len, {peer_key, peer_key_len}, as_span_of_bytes(salt)); |
239 | 0 | } |
240 | | |
241 | | SymmetricKey PK_Key_Agreement::derive_key(size_t key_len, |
242 | | const std::span<const uint8_t> peer_key, |
243 | 0 | std::string_view salt) const { |
244 | 0 | return this->derive_key(key_len, peer_key, as_span_of_bytes(salt)); |
245 | 0 | } |
246 | | |
247 | | SymmetricKey PK_Key_Agreement::derive_key(size_t key_len, |
248 | | std::span<const uint8_t> peer_key, |
249 | 0 | std::span<const uint8_t> salt) const { |
250 | 0 | return SymmetricKey(m_op->agree(key_len, peer_key, salt)); |
251 | 0 | } |
252 | | |
253 | | PK_Signer::PK_Signer(const Private_Key& key, |
254 | | RandomNumberGenerator& rng, |
255 | | std::string_view padding, |
256 | | Signature_Format format, |
257 | | std::string_view provider) : |
258 | 484 | m_sig_format(format), m_sig_element_size(key._signature_element_size_for_DER_encoding()) { |
259 | 484 | if(m_sig_format == Signature_Format::DerSequence) { |
260 | 484 | BOTAN_ARG_CHECK(m_sig_element_size.has_value(), "This key does not support DER signatures"); |
261 | 484 | } |
262 | | |
263 | 484 | m_op = key.create_signature_op(rng, padding, provider); |
264 | 484 | if(!m_op) { |
265 | 0 | throw Invalid_Argument(fmt("Key type {} does not support signature generation", key.algo_name())); |
266 | 0 | } |
267 | 484 | } |
268 | | |
269 | 0 | AlgorithmIdentifier PK_Signer::algorithm_identifier() const { |
270 | 0 | return m_op->algorithm_identifier(); |
271 | 0 | } |
272 | | |
273 | 0 | std::string PK_Signer::hash_function() const { |
274 | 0 | return m_op->hash_function(); |
275 | 0 | } |
276 | | |
277 | 484 | PK_Signer::~PK_Signer() = default; |
278 | | |
279 | 0 | PK_Signer::PK_Signer(PK_Signer&&) noexcept = default; |
280 | 0 | PK_Signer& PK_Signer::operator=(PK_Signer&&) noexcept = default; |
281 | | |
282 | 0 | void PK_Signer::update(std::string_view in) { |
283 | 0 | this->update(as_span_of_bytes(in)); |
284 | 0 | } |
285 | | |
286 | 484 | void PK_Signer::update(const uint8_t in[], size_t length) { |
287 | 484 | m_op->update({in, length}); |
288 | 484 | } |
289 | | |
290 | | namespace { |
291 | | |
292 | 484 | std::vector<uint8_t> der_encode_signature(std::span<const uint8_t> sig, size_t parts, size_t part_size) { |
293 | 484 | if(sig.size() % parts != 0 || sig.size() != parts * part_size) { |
294 | 0 | throw Encoding_Error("Unexpected size for DER signature"); |
295 | 0 | } |
296 | | |
297 | 484 | BufferSlicer bs_sig(sig); |
298 | 484 | std::vector<BigInt> sig_parts; |
299 | 484 | sig_parts.reserve(parts); |
300 | 1.45k | for(size_t i = 0; i != parts; ++i) { |
301 | 968 | sig_parts.emplace_back(BigInt::from_bytes(bs_sig.take(part_size))); |
302 | 968 | } |
303 | | |
304 | 484 | std::vector<uint8_t> output; |
305 | 484 | DER_Encoder(output).start_sequence().encode_list(sig_parts).end_cons(); |
306 | 484 | return output; |
307 | 484 | } |
308 | | |
309 | | } // namespace |
310 | | |
311 | 0 | size_t PK_Signer::signature_length() const { |
312 | 0 | if(m_sig_format == Signature_Format::Standard) { |
313 | 0 | return m_op->signature_length(); |
314 | 0 | } else if(m_sig_format == Signature_Format::DerSequence) { |
315 | 0 | const size_t sig_len = m_op->signature_length(); |
316 | |
|
317 | 0 | const size_t der_overhead = [sig_len]() { |
318 | | /* |
319 | | This was computed by DER encoding of some maximal value signatures |
320 | | (since DER is variable length) |
321 | | |
322 | | The first two cases covers all EC schemes since groups are at most 521 |
323 | | bits. |
324 | | |
325 | | The other cases are only for finite field DSA which practically is only |
326 | | used up to 3072 bit groups but the calculation is correct up to a |
327 | | 262096 (!) bit group so allow it. There are some intermediate sizes but |
328 | | this function is allowed to (and indeed must) return an over-estimate |
329 | | rather than an exact value since the actual length will change based on |
330 | | the computed signature. |
331 | | */ |
332 | |
|
333 | 0 | if(sig_len <= 120) { |
334 | | // EC signatures <= 480 bits |
335 | 0 | return 8; |
336 | 0 | } else if(sig_len <= 248) { |
337 | | // EC signatures > 480 bits (or very small DSA groups...) |
338 | 0 | return 9; |
339 | 0 | } else { |
340 | | // Everything else. This is an over-estimate for groups under |
341 | | // 2040 bits but exact otherwise |
342 | | |
343 | | // This requires 15 bytes DER overhead and should never happen |
344 | 0 | BOTAN_ASSERT_NOMSG(sig_len < 65524); |
345 | 0 | return 14; |
346 | 0 | } |
347 | 0 | }(); |
348 | |
|
349 | 0 | return sig_len + der_overhead; |
350 | 0 | } else { |
351 | 0 | throw Internal_Error("PK_Signer: Invalid signature format enum"); |
352 | 0 | } |
353 | 0 | } |
354 | | |
355 | 484 | std::vector<uint8_t> PK_Signer::signature(RandomNumberGenerator& rng) { |
356 | 484 | std::vector<uint8_t> sig = m_op->sign(rng); |
357 | | |
358 | 484 | if(m_sig_format == Signature_Format::Standard) { |
359 | 0 | return sig; |
360 | 484 | } else if(m_sig_format == Signature_Format::DerSequence) { |
361 | 484 | BOTAN_ASSERT_NOMSG(m_sig_element_size.has_value()); |
362 | 484 | return der_encode_signature(sig, 2, m_sig_element_size.value()); |
363 | 484 | } else { |
364 | 0 | throw Internal_Error("PK_Signer: Invalid signature format enum"); |
365 | 0 | } |
366 | 484 | } |
367 | | |
368 | | PK_Verifier::PK_Verifier(const Public_Key& key, |
369 | | std::string_view padding, |
370 | | Signature_Format format, |
371 | 772 | std::string_view provider) { |
372 | 772 | m_op = key.create_verification_op(padding, provider); |
373 | 772 | if(!m_op) { |
374 | 0 | throw Invalid_Argument(fmt("Key type {} does not support signature verification", key.algo_name())); |
375 | 0 | } |
376 | | |
377 | 772 | m_sig_format = format; |
378 | 772 | m_sig_element_size = key._signature_element_size_for_DER_encoding(); |
379 | | |
380 | 772 | if(m_sig_format == Signature_Format::DerSequence) { |
381 | 0 | BOTAN_ARG_CHECK(m_sig_element_size.has_value(), "This key does not support DER signatures"); |
382 | 0 | } |
383 | 772 | } |
384 | | |
385 | | PK_Verifier::PK_Verifier(const Public_Key& key, |
386 | | const AlgorithmIdentifier& signature_algorithm, |
387 | 0 | std::string_view provider) { |
388 | 0 | m_op = key.create_x509_verification_op(signature_algorithm, provider); |
389 | 0 | if(!m_op) { |
390 | 0 | throw Invalid_Argument(fmt("Key type {} does not support X.509 signature verification", key.algo_name())); |
391 | 0 | } |
392 | | |
393 | 0 | m_sig_format = key._default_x509_signature_format(); |
394 | 0 | m_sig_element_size = key._signature_element_size_for_DER_encoding(); |
395 | 0 | } |
396 | | |
397 | 772 | PK_Verifier::~PK_Verifier() = default; |
398 | | |
399 | 0 | PK_Verifier::PK_Verifier(PK_Verifier&&) noexcept = default; |
400 | 0 | PK_Verifier& PK_Verifier::operator=(PK_Verifier&&) noexcept = default; |
401 | | |
402 | 0 | std::string PK_Verifier::hash_function() const { |
403 | 0 | return m_op->hash_function(); |
404 | 0 | } |
405 | | |
406 | 0 | void PK_Verifier::set_input_format(Signature_Format format) { |
407 | 0 | if(format == Signature_Format::DerSequence) { |
408 | 0 | BOTAN_ARG_CHECK(m_sig_element_size.has_value(), "This key does not support DER signatures"); |
409 | 0 | } |
410 | 0 | m_sig_format = format; |
411 | 0 | } |
412 | | |
413 | 772 | bool PK_Verifier::verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length) { |
414 | 772 | update(msg, msg_length); |
415 | 772 | return check_signature(sig, sig_length); |
416 | 772 | } |
417 | | |
418 | 0 | void PK_Verifier::update(std::string_view in) { |
419 | 0 | this->update(as_span_of_bytes(in)); |
420 | 0 | } |
421 | | |
422 | 772 | void PK_Verifier::update(const uint8_t in[], size_t length) { |
423 | 772 | m_op->update({in, length}); |
424 | 772 | } |
425 | | |
426 | | namespace { |
427 | | |
428 | 0 | std::vector<uint8_t> decode_der_signature(const uint8_t sig[], size_t length, size_t sig_parts, size_t sig_part_size) { |
429 | 0 | std::vector<uint8_t> real_sig; |
430 | 0 | BER_Decoder decoder(sig, length); |
431 | 0 | BER_Decoder ber_sig = decoder.start_sequence(); |
432 | |
|
433 | 0 | BOTAN_ASSERT_NOMSG(sig_parts != 0 && sig_part_size != 0); |
434 | |
|
435 | 0 | size_t count = 0; |
436 | |
|
437 | 0 | while(ber_sig.more_items()) { |
438 | 0 | BigInt sig_part; |
439 | 0 | ber_sig.decode(sig_part); |
440 | 0 | real_sig += sig_part.serialize(sig_part_size); |
441 | 0 | ++count; |
442 | 0 | } |
443 | |
|
444 | 0 | if(count != sig_parts) { |
445 | 0 | throw Decoding_Error("PK_Verifier: signature size invalid"); |
446 | 0 | } |
447 | | |
448 | 0 | const std::vector<uint8_t> reencoded = der_encode_signature(real_sig, sig_parts, sig_part_size); |
449 | |
|
450 | 0 | if(reencoded.size() != length || CT::is_equal(reencoded.data(), sig, reencoded.size()).as_bool() == false) { |
451 | 0 | throw Decoding_Error("PK_Verifier: signature is not the canonical DER encoding"); |
452 | 0 | } |
453 | 0 | return real_sig; |
454 | 0 | } |
455 | | |
456 | | } // namespace |
457 | | |
458 | 772 | bool PK_Verifier::check_signature(const uint8_t sig[], size_t length) { |
459 | 772 | try { |
460 | 772 | if(m_sig_format == Signature_Format::Standard) { |
461 | 772 | return m_op->is_valid_signature({sig, length}); |
462 | 772 | } else if(m_sig_format == Signature_Format::DerSequence) { |
463 | 0 | bool decoding_success = false; |
464 | 0 | std::vector<uint8_t> real_sig; |
465 | |
|
466 | 0 | BOTAN_ASSERT_NOMSG(m_sig_element_size.has_value()); |
467 | |
|
468 | 0 | try { |
469 | 0 | real_sig = decode_der_signature(sig, length, 2, m_sig_element_size.value()); |
470 | 0 | decoding_success = true; |
471 | 0 | } catch(Decoding_Error&) {} |
472 | |
|
473 | 0 | const bool accept = m_op->is_valid_signature(real_sig); |
474 | |
|
475 | 0 | return accept && decoding_success; |
476 | 0 | } else { |
477 | 0 | throw Internal_Error("PK_Verifier: Invalid signature format enum"); |
478 | 0 | } |
479 | 772 | } catch(Invalid_Argument&) { |
480 | 0 | return false; |
481 | 0 | } catch(Decoding_Error&) { |
482 | 0 | return false; |
483 | 0 | } catch(Encoding_Error&) { |
484 | 0 | return false; |
485 | 0 | } |
486 | 772 | } |
487 | | |
488 | | } // namespace Botan |