Coverage Report

Created: 2026-02-14 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
0
      m_sig_format(format), m_sig_element_size(key._signature_element_size_for_DER_encoding()) {
259
0
   if(m_sig_format == Signature_Format::DerSequence) {
260
0
      BOTAN_ARG_CHECK(m_sig_element_size.has_value(), "This key does not support DER signatures");
261
0
   }
262
263
0
   m_op = key.create_signature_op(rng, padding, provider);
264
0
   if(!m_op) {
265
0
      throw Invalid_Argument(fmt("Key type {} does not support signature generation", key.algo_name()));
266
0
   }
267
0
}
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
0
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
0
void PK_Signer::update(const uint8_t in[], size_t length) {
287
0
   m_op->update({in, length});
288
0
}
289
290
namespace {
291
292
0
std::vector<uint8_t> der_encode_signature(std::span<const uint8_t> sig, size_t parts, size_t part_size) {
293
0
   if(sig.size() % parts != 0 || sig.size() != parts * part_size) {
294
0
      throw Encoding_Error("Unexpected size for DER signature");
295
0
   }
296
297
0
   BufferSlicer bs_sig(sig);
298
0
   std::vector<BigInt> sig_parts;
299
0
   sig_parts.reserve(parts);
300
0
   for(size_t i = 0; i != parts; ++i) {
301
0
      sig_parts.emplace_back(BigInt::from_bytes(bs_sig.take(part_size)));
302
0
   }
303
304
0
   std::vector<uint8_t> output;
305
0
   DER_Encoder(output).start_sequence().encode_list(sig_parts).end_cons();
306
0
   return output;
307
0
}
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
      size_t sig_len = m_op->signature_length();
316
317
0
      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
0
std::vector<uint8_t> PK_Signer::signature(RandomNumberGenerator& rng) {
356
0
   std::vector<uint8_t> sig = m_op->sign(rng);
357
358
0
   if(m_sig_format == Signature_Format::Standard) {
359
0
      return sig;
360
0
   } else if(m_sig_format == Signature_Format::DerSequence) {
361
0
      BOTAN_ASSERT_NOMSG(m_sig_element_size.has_value());
362
0
      return der_encode_signature(sig, 2, m_sig_element_size.value());
363
0
   } else {
364
0
      throw Internal_Error("PK_Signer: Invalid signature format enum");
365
0
   }
366
0
}
367
368
PK_Verifier::PK_Verifier(const Public_Key& key,
369
                         std::string_view padding,
370
                         Signature_Format format,
371
0
                         std::string_view provider) {
372
0
   m_op = key.create_verification_op(padding, provider);
373
0
   if(!m_op) {
374
0
      throw Invalid_Argument(fmt("Key type {} does not support signature verification", key.algo_name()));
375
0
   }
376
377
0
   m_sig_format = format;
378
0
   m_sig_element_size = key._signature_element_size_for_DER_encoding();
379
380
0
   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
0
}
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
0
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
0
bool PK_Verifier::verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length) {
414
0
   update(msg, msg_length);
415
0
   return check_signature(sig, sig_length);
416
0
}
417
418
0
void PK_Verifier::update(std::string_view in) {
419
0
   this->update(as_span_of_bytes(in));
420
0
}
421
422
0
void PK_Verifier::update(const uint8_t in[], size_t length) {
423
0
   m_op->update({in, length});
424
0
}
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
0
bool PK_Verifier::check_signature(const uint8_t sig[], size_t length) {
459
0
   try {
460
0
      if(m_sig_format == Signature_Format::Standard) {
461
0
         return m_op->is_valid_signature({sig, length});
462
0
      } 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
         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
0
   } 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
0
}
487
488
}  // namespace Botan