• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 21712452049

05 Feb 2026 01:00PM UTC coverage: 90.071% (-0.003%) from 90.074%
21712452049

push

github

web-flow
Merge pull request #5286 from randombit/jack/scoped-cleanup-h

Split out scoped_cleanup to its own header

102233 of 113503 relevant lines covered (90.07%)

11479296.78 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.94
/src/lib/pubkey/pubkey.cpp
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
#include <botan/internal/stl_util.h>
21

22
namespace Botan {
23

24
secure_vector<uint8_t> PK_Decryptor::decrypt(const uint8_t in[], size_t length) const {
6,909✔
25
   uint8_t valid_mask = 0;
6,909✔
26

27
   secure_vector<uint8_t> decoded = do_decrypt(valid_mask, in, length);
6,909✔
28

29
   if(valid_mask == 0) {
6,874✔
30
      throw Decoding_Error("Invalid public key ciphertext, cannot decrypt");
3,183✔
31
   }
32

33
   return decoded;
3,691✔
34
}
3,183✔
35

36
secure_vector<uint8_t> PK_Decryptor::decrypt_or_random(const uint8_t in[],
587✔
37
                                                       size_t length,
38
                                                       size_t expected_pt_len,
39
                                                       RandomNumberGenerator& rng,
40
                                                       const uint8_t required_content_bytes[],
41
                                                       const uint8_t required_content_offsets[],
42
                                                       size_t required_contents_length) const {
43
   const secure_vector<uint8_t> fake_pms = [&]() {
1,761✔
44
      auto pms = rng.random_vec(expected_pt_len);
587✔
45

46
      for(size_t i = 0; i != required_contents_length; ++i) {
2,687✔
47
         const uint8_t exp = required_content_bytes[i];
2,100✔
48

49
         /*
50
         If an offset repeats we don't detect this and just return a PMS that satisfies
51
         the last requested index. If the requested (idx,value) tuple is the same, that's
52
         fine and just redundant. If they disagree, decryption will always fail, since the
53
         same byte cannot possibly have two distinct values.
54
         */
55
         const uint8_t off = required_content_offsets[i];
2,100✔
56
         BOTAN_ASSERT(off < expected_pt_len, "Offset in range of plaintext");
2,100✔
57
         pms[off] = exp;
2,100✔
58
      }
59

60
      return pms;
587✔
61
   }();
587✔
62

63
   uint8_t decrypt_valid = 0;
587✔
64
   secure_vector<uint8_t> decoded = do_decrypt(decrypt_valid, in, length);
587✔
65

66
   auto valid_mask = CT::Mask<uint8_t>::is_equal(decrypt_valid, 0xFF);
587✔
67
   valid_mask &= CT::Mask<uint8_t>(CT::Mask<size_t>::is_equal(decoded.size(), expected_pt_len));
587✔
68

69
   decoded.resize(expected_pt_len);
587✔
70

71
   for(size_t i = 0; i != required_contents_length; ++i) {
2,687✔
72
      const uint8_t exp = required_content_bytes[i];
2,100✔
73

74
      // We know off is in range because we already checked it when creating the fake premaster above
75
      const uint8_t off = required_content_offsets[i];
2,100✔
76

77
      auto eq = CT::Mask<uint8_t>::is_equal(decoded[off], exp);
2,100✔
78

79
      valid_mask &= eq;
2,100✔
80
   }
81

82
   // If valid_mask is false, assign fake pre master instead
83
   valid_mask.select_n(decoded.data(), decoded.data(), fake_pms.data(), expected_pt_len);
587✔
84

85
   return decoded;
587✔
86
}
587✔
87

88
secure_vector<uint8_t> PK_Decryptor::decrypt_or_random(const uint8_t in[],
405✔
89
                                                       size_t length,
90
                                                       size_t expected_pt_len,
91
                                                       RandomNumberGenerator& rng) const {
92
   return decrypt_or_random(in, length, expected_pt_len, rng, nullptr, nullptr, 0);
405✔
93
}
94

95
PK_Encryptor_EME::PK_Encryptor_EME(const Public_Key& key,
910✔
96
                                   RandomNumberGenerator& rng,
97
                                   std::string_view padding,
98
                                   std::string_view provider) {
910✔
99
   m_op = key.create_encryption_op(rng, padding, provider);
910✔
100
   if(!m_op) {
313✔
101
      throw Invalid_Argument(fmt("Key type {} does not support encryption", key.algo_name()));
×
102
   }
103
}
910✔
104

105
PK_Encryptor_EME::~PK_Encryptor_EME() = default;
517✔
106

107
PK_Encryptor_EME::PK_Encryptor_EME(PK_Encryptor_EME&&) noexcept = default;
×
108
PK_Encryptor_EME& PK_Encryptor_EME::operator=(PK_Encryptor_EME&&) noexcept = default;
×
109

110
size_t PK_Encryptor_EME::ciphertext_length(size_t ptext_len) const {
204✔
111
   return m_op->ciphertext_length(ptext_len);
204✔
112
}
113

114
std::vector<uint8_t> PK_Encryptor_EME::enc(const uint8_t ptext[], size_t len, RandomNumberGenerator& rng) const {
381✔
115
   return m_op->encrypt(std::span{ptext, len}, rng);
381✔
116
}
117

118
size_t PK_Encryptor_EME::maximum_input_size() const {
209✔
119
   return m_op->max_input_bits() / 8;
209✔
120
}
121

122
PK_Decryptor_EME::PK_Decryptor_EME(const Private_Key& key,
1,052✔
123
                                   RandomNumberGenerator& rng,
124
                                   std::string_view padding,
125
                                   std::string_view provider) {
1,052✔
126
   m_op = key.create_decryption_op(rng, padding, provider);
1,052✔
127
   if(!m_op) {
329✔
128
      throw Invalid_Argument(fmt("Key type {} does not support decryption", key.algo_name()));
×
129
   }
130
}
1,052✔
131

132
PK_Decryptor_EME::~PK_Decryptor_EME() = default;
575✔
133

134
PK_Decryptor_EME::PK_Decryptor_EME(PK_Decryptor_EME&&) noexcept = default;
×
135
PK_Decryptor_EME& PK_Decryptor_EME::operator=(PK_Decryptor_EME&&) noexcept = default;
×
136

137
size_t PK_Decryptor_EME::plaintext_length(size_t ctext_len) const {
203✔
138
   return m_op->plaintext_length(ctext_len);
203✔
139
}
140

141
secure_vector<uint8_t> PK_Decryptor_EME::do_decrypt(uint8_t& valid_mask, const uint8_t in[], size_t in_len) const {
5,775✔
142
   return m_op->decrypt(valid_mask, {in, in_len});
5,775✔
143
}
144

145
PK_KEM_Encryptor::PK_KEM_Encryptor(const Public_Key& key, std::string_view param, std::string_view provider) {
862✔
146
   m_op = key.create_kem_encryption_op(param, provider);
862✔
147
   if(!m_op) {
862✔
148
      throw Invalid_Argument(fmt("Key type {} does not support KEM encryption", key.algo_name()));
×
149
   }
150
}
862✔
151

152
PK_KEM_Encryptor::PK_KEM_Encryptor(const Public_Key& key,
×
153
                                   RandomNumberGenerator& rng,
154
                                   std::string_view kem_param,
155
                                   std::string_view provider) :
×
156
      PK_KEM_Encryptor(key, kem_param, provider) {
×
157
   BOTAN_UNUSED(rng);
×
158
}
×
159

160
PK_KEM_Encryptor::~PK_KEM_Encryptor() = default;
862✔
161

162
PK_KEM_Encryptor::PK_KEM_Encryptor(PK_KEM_Encryptor&&) noexcept = default;
×
163
PK_KEM_Encryptor& PK_KEM_Encryptor::operator=(PK_KEM_Encryptor&&) noexcept = default;
×
164

165
size_t PK_KEM_Encryptor::shared_key_length(size_t desired_shared_key_len) const {
6,976✔
166
   return m_op->shared_key_length(desired_shared_key_len);
6,976✔
167
}
168

169
size_t PK_KEM_Encryptor::encapsulated_key_length() const {
6,881✔
170
   return m_op->encapsulated_key_length();
6,881✔
171
}
172

173
void PK_KEM_Encryptor::encrypt(std::span<uint8_t> out_encapsulated_key,
3,366✔
174
                               std::span<uint8_t> out_shared_key,
175
                               RandomNumberGenerator& rng,
176
                               size_t desired_shared_key_len,
177
                               std::span<const uint8_t> salt) {
178
   BOTAN_ARG_CHECK(out_encapsulated_key.size() == encapsulated_key_length(), "not enough space for encapsulated key");
3,366✔
179
   BOTAN_ARG_CHECK(out_shared_key.size() == shared_key_length(desired_shared_key_len),
3,366✔
180
                   "not enough space for shared key");
181
   m_op->kem_encrypt(out_encapsulated_key, out_shared_key, rng, desired_shared_key_len, salt);
3,366✔
182
}
3,363✔
183

184
size_t PK_KEM_Decryptor::shared_key_length(size_t desired_shared_key_len) const {
7,130✔
185
   return m_op->shared_key_length(desired_shared_key_len);
7,130✔
186
}
187

188
size_t PK_KEM_Decryptor::encapsulated_key_length() const {
132✔
189
   return m_op->encapsulated_key_length();
132✔
190
}
191

192
PK_KEM_Decryptor::PK_KEM_Decryptor(const Private_Key& key,
804✔
193
                                   RandomNumberGenerator& rng,
194
                                   std::string_view param,
195
                                   std::string_view provider) {
804✔
196
   m_op = key.create_kem_decryption_op(rng, param, provider);
804✔
197
   if(!m_op) {
804✔
198
      throw Invalid_Argument(fmt("Key type {} does not support KEM decryption", key.algo_name()));
×
199
   }
200
}
804✔
201

202
PK_KEM_Decryptor::~PK_KEM_Decryptor() = default;
804✔
203

204
PK_KEM_Decryptor::PK_KEM_Decryptor(PK_KEM_Decryptor&&) noexcept = default;
×
205
PK_KEM_Decryptor& PK_KEM_Decryptor::operator=(PK_KEM_Decryptor&&) noexcept = default;
×
206

207
void PK_KEM_Decryptor::decrypt(std::span<uint8_t> out_shared_key,
3,437✔
208
                               std::span<const uint8_t> encap_key,
209
                               size_t desired_shared_key_len,
210
                               std::span<const uint8_t> salt) {
211
   BOTAN_ARG_CHECK(out_shared_key.size() == shared_key_length(desired_shared_key_len),
3,437✔
212
                   "inconsistent size of shared key output buffer");
213
   m_op->kem_decrypt(out_shared_key, encap_key, desired_shared_key_len, salt);
3,437✔
214
}
3,414✔
215

216
PK_Key_Agreement::PK_Key_Agreement(const Private_Key& key,
11,220✔
217
                                   RandomNumberGenerator& rng,
218
                                   std::string_view kdf,
219
                                   std::string_view provider) {
11,220✔
220
   m_op = key.create_key_agreement_op(rng, kdf, provider);
11,220✔
221
   if(!m_op) {
8,868✔
222
      throw Invalid_Argument(fmt("Key type {} does not support key agreement", key.algo_name()));
×
223
   }
224
}
11,220✔
225

226
PK_Key_Agreement::~PK_Key_Agreement() = default;
8,868✔
227

228
PK_Key_Agreement::PK_Key_Agreement(PK_Key_Agreement&&) noexcept = default;
×
229
PK_Key_Agreement& PK_Key_Agreement::operator=(PK_Key_Agreement&&) noexcept = default;
×
230

231
size_t PK_Key_Agreement::agreed_value_size() const {
946✔
232
   return m_op->agreed_value_size();
946✔
233
}
234

235
SymmetricKey PK_Key_Agreement::derive_key(size_t key_len,
182✔
236
                                          const uint8_t peer_key[],
237
                                          size_t peer_key_len,
238
                                          std::string_view salt) const {
239
   return this->derive_key(key_len, {peer_key, peer_key_len}, as_span_of_bytes(salt));
182✔
240
}
241

242
SymmetricKey PK_Key_Agreement::derive_key(size_t key_len,
10,250✔
243
                                          const std::span<const uint8_t> peer_key,
244
                                          std::string_view salt) const {
245
   return this->derive_key(key_len, peer_key, as_span_of_bytes(salt));
10,250✔
246
}
247

248
SymmetricKey PK_Key_Agreement::derive_key(size_t key_len,
10,451✔
249
                                          std::span<const uint8_t> peer_key,
250
                                          std::span<const uint8_t> salt) const {
251
   return SymmetricKey(m_op->agree(key_len, peer_key, salt));
10,451✔
252
}
253

254
PK_Signer::PK_Signer(const Private_Key& key,
9,920✔
255
                     RandomNumberGenerator& rng,
256
                     std::string_view padding,
257
                     Signature_Format format,
258
                     std::string_view provider) :
9,920✔
259
      m_sig_format(format), m_sig_element_size(key._signature_element_size_for_DER_encoding()) {
9,920✔
260
   if(m_sig_format == Signature_Format::DerSequence) {
9,920✔
261
      BOTAN_ARG_CHECK(m_sig_element_size.has_value(), "This key does not support DER signatures");
1,952✔
262
   }
263

264
   m_op = key.create_signature_op(rng, padding, provider);
9,920✔
265
   if(!m_op) {
6,146✔
266
      throw Invalid_Argument(fmt("Key type {} does not support signature generation", key.algo_name()));
×
267
   }
268
}
9,920✔
269

270
AlgorithmIdentifier PK_Signer::algorithm_identifier() const {
2,067✔
271
   return m_op->algorithm_identifier();
2,067✔
272
}
273

274
std::string PK_Signer::hash_function() const {
2,576✔
275
   return m_op->hash_function();
2,576✔
276
}
277

278
PK_Signer::~PK_Signer() = default;
6,146✔
279

280
PK_Signer::PK_Signer(PK_Signer&&) noexcept = default;
×
281
PK_Signer& PK_Signer::operator=(PK_Signer&&) noexcept = default;
×
282

283
void PK_Signer::update(std::string_view in) {
1✔
284
   this->update(as_span_of_bytes(in));
1✔
285
}
1✔
286

287
void PK_Signer::update(const uint8_t in[], size_t length) {
10,489✔
288
   m_op->update({in, length});
10,489✔
289
}
10,488✔
290

291
namespace {
292

293
std::vector<uint8_t> der_encode_signature(std::span<const uint8_t> sig, size_t parts, size_t part_size) {
13,487✔
294
   if(sig.size() % parts != 0 || sig.size() != parts * part_size) {
13,487✔
295
      throw Encoding_Error("Unexpected size for DER signature");
×
296
   }
297

298
   BufferSlicer bs_sig(sig);
13,487✔
299
   std::vector<BigInt> sig_parts;
13,487✔
300
   sig_parts.reserve(parts);
13,487✔
301
   for(size_t i = 0; i != parts; ++i) {
40,461✔
302
      sig_parts.emplace_back(BigInt::from_bytes(bs_sig.take(part_size)));
26,974✔
303
   }
304

305
   std::vector<uint8_t> output;
13,487✔
306
   DER_Encoder(output).start_sequence().encode_list(sig_parts).end_cons();
53,948✔
307
   return output;
13,487✔
308
}
13,487✔
309

310
}  // namespace
311

312
size_t PK_Signer::signature_length() const {
1,332✔
313
   if(m_sig_format == Signature_Format::Standard) {
1,332✔
314
      return m_op->signature_length();
1,330✔
315
   } else if(m_sig_format == Signature_Format::DerSequence) {
2✔
316
      const size_t sig_len = m_op->signature_length();
2✔
317

318
      const size_t der_overhead = [sig_len]() {
6✔
319
         /*
320
         This was computed by DER encoding of some maximal value signatures
321
         (since DER is variable length)
322

323
         The first two cases covers all EC schemes since groups are at most 521
324
         bits.
325

326
         The other cases are only for finite field DSA which practically is only
327
         used up to 3072 bit groups but the calculation is correct up to a
328
         262096 (!) bit group so allow it. There are some intermediate sizes but
329
         this function is allowed to (and indeed must) return an over-estimate
330
         rather than an exact value since the actual length will change based on
331
         the computed signature.
332
         */
333

334
         if(sig_len <= 120) {
2✔
335
            // EC signatures <= 480 bits
336
            return 8;
337
         } else if(sig_len <= 248) {
×
338
            // EC signatures > 480 bits (or very small DSA groups...)
339
            return 9;
340
         } else {
341
            // Everything else. This is an over-estimate for groups under
342
            // 2040 bits but exact otherwise
343

344
            // This requires 15 bytes DER overhead and should never happen
345
            BOTAN_ASSERT_NOMSG(sig_len < 65524);
×
346
            return 14;
347
         }
348
      }();
2✔
349

350
      return sig_len + der_overhead;
2✔
351
   } else {
352
      throw Internal_Error("PK_Signer: Invalid signature format enum");
×
353
   }
354
}
355

356
std::vector<uint8_t> PK_Signer::signature(RandomNumberGenerator& rng) {
10,443✔
357
   std::vector<uint8_t> sig = m_op->sign(rng);
10,443✔
358

359
   if(m_sig_format == Signature_Format::Standard) {
10,439✔
360
      return sig;
7,232✔
361
   } else if(m_sig_format == Signature_Format::DerSequence) {
3,207✔
362
      BOTAN_ASSERT_NOMSG(m_sig_element_size.has_value());
3,207✔
363
      return der_encode_signature(sig, 2, m_sig_element_size.value());
3,207✔
364
   } else {
365
      throw Internal_Error("PK_Signer: Invalid signature format enum");
×
366
   }
367
}
10,439✔
368

369
PK_Verifier::PK_Verifier(const Public_Key& key,
63,601✔
370
                         std::string_view padding,
371
                         Signature_Format format,
372
                         std::string_view provider) {
63,601✔
373
   m_op = key.create_verification_op(padding, provider);
63,601✔
374
   if(!m_op) {
14,216✔
375
      throw Invalid_Argument(fmt("Key type {} does not support signature verification", key.algo_name()));
×
376
   }
377

378
   m_sig_format = format;
14,216✔
379
   m_sig_element_size = key._signature_element_size_for_DER_encoding();
14,216✔
380

381
   if(m_sig_format == Signature_Format::DerSequence) {
14,216✔
382
      BOTAN_ARG_CHECK(m_sig_element_size.has_value(), "This key does not support DER signatures");
7,915✔
383
   }
384
}
63,601✔
385

386
PK_Verifier::PK_Verifier(const Public_Key& key,
21,182✔
387
                         const AlgorithmIdentifier& signature_algorithm,
388
                         std::string_view provider) {
21,182✔
389
   m_op = key.create_x509_verification_op(signature_algorithm, provider);
21,182✔
390
   if(!m_op) {
21,137✔
391
      throw Invalid_Argument(fmt("Key type {} does not support X.509 signature verification", key.algo_name()));
×
392
   }
393

394
   m_sig_format = key._default_x509_signature_format();
21,137✔
395
   m_sig_element_size = key._signature_element_size_for_DER_encoding();
21,137✔
396
}
21,182✔
397

398
PK_Verifier::~PK_Verifier() = default;
35,353✔
399

400
PK_Verifier::PK_Verifier(PK_Verifier&&) noexcept = default;
×
401
PK_Verifier& PK_Verifier::operator=(PK_Verifier&&) noexcept = default;
×
402

403
std::string PK_Verifier::hash_function() const {
20,708✔
404
   return m_op->hash_function();
20,708✔
405
}
406

407
void PK_Verifier::set_input_format(Signature_Format format) {
1✔
408
   if(format == Signature_Format::DerSequence) {
1✔
409
      BOTAN_ARG_CHECK(m_sig_element_size.has_value(), "This key does not support DER signatures");
1✔
410
   }
411
   m_sig_format = format;
1✔
412
}
1✔
413

414
bool PK_Verifier::verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length) {
91,564✔
415
   update(msg, msg_length);
91,564✔
416
   return check_signature(sig, sig_length);
91,564✔
417
}
418

419
void PK_Verifier::update(std::string_view in) {
48✔
420
   this->update(as_span_of_bytes(in));
48✔
421
}
48✔
422

423
void PK_Verifier::update(const uint8_t in[], size_t length) {
96,329✔
424
   m_op->update({in, length});
96,329✔
425
}
96,329✔
426

427
namespace {
428

429
std::vector<uint8_t> decode_der_signature(const uint8_t sig[], size_t length, size_t sig_parts, size_t sig_part_size) {
12,538✔
430
   std::vector<uint8_t> real_sig;
12,538✔
431
   BER_Decoder decoder(sig, length);
12,538✔
432
   BER_Decoder ber_sig = decoder.start_sequence();
12,538✔
433

434
   BOTAN_ASSERT_NOMSG(sig_parts != 0 && sig_part_size != 0);
12,209✔
435

436
   size_t count = 0;
437

438
   while(ber_sig.more_items()) {
34,172✔
439
      BigInt sig_part;
23,790✔
440
      ber_sig.decode(sig_part);
23,790✔
441
      real_sig += sig_part.serialize(sig_part_size);
22,190✔
442
      ++count;
21,963✔
443
   }
23,790✔
444

445
   if(count != sig_parts) {
10,382✔
446
      throw Decoding_Error("PK_Verifier: signature size invalid");
102✔
447
   }
448

449
   const std::vector<uint8_t> reencoded = der_encode_signature(real_sig, sig_parts, sig_part_size);
10,280✔
450

451
   if(reencoded.size() != length || CT::is_equal(reencoded.data(), sig, reencoded.size()).as_bool() == false) {
10,280✔
452
      throw Decoding_Error("PK_Verifier: signature is not the canonical DER encoding");
707✔
453
   }
454
   return real_sig;
19,146✔
455
}
15,174✔
456

457
}  // namespace
458

459
bool PK_Verifier::check_signature(const uint8_t sig[], size_t length) {
97,654✔
460
   try {
97,654✔
461
      if(m_sig_format == Signature_Format::Standard) {
97,654✔
462
         return m_op->is_valid_signature({sig, length});
85,116✔
463
      } else if(m_sig_format == Signature_Format::DerSequence) {
12,538✔
464
         bool decoding_success = false;
12,538✔
465
         std::vector<uint8_t> real_sig;
12,538✔
466

467
         BOTAN_ASSERT_NOMSG(m_sig_element_size.has_value());
12,538✔
468

469
         try {
12,538✔
470
            real_sig = decode_der_signature(sig, length, 2, m_sig_element_size.value());
22,111✔
471
            decoding_success = true;
9,573✔
472
         } catch(Decoding_Error&) {}
2,965✔
473

474
         const bool accept = m_op->is_valid_signature(real_sig);
12,538✔
475

476
         return accept && decoding_success;
12,311✔
477
      } else {
12,538✔
478
         throw Internal_Error("PK_Verifier: Invalid signature format enum");
×
479
      }
480
   } catch(Invalid_Argument&) {
346✔
481
      return false;
227✔
482
   } catch(Decoding_Error&) {
346✔
483
      return false;
119✔
484
   } catch(Encoding_Error&) {
119✔
485
      return false;
×
486
   }
×
487
}
488

489
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc