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

randombit / botan / 12999101703

27 Jan 2025 02:24PM UTC coverage: 91.243% (-0.01%) from 91.254%
12999101703

push

github

web-flow
Merge pull request #4592 from randombit/jack/split-key-prework

Some initial refactoring for splitting public and private keys

93963 of 102981 relevant lines covered (91.24%)

11538552.33 hits per line

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

84.06
/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/parsing.h>
19
#include <botan/internal/stl_util.h>
20

21
namespace Botan {
22

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

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

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

32
   return decoded;
3,688✔
33
}
3,186✔
34

35
secure_vector<uint8_t> PK_Decryptor::decrypt_or_random(const uint8_t in[],
587✔
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
                                                       size_t required_contents_length) const {
42
   const secure_vector<uint8_t> fake_pms = [&]() {
1,761✔
43
      auto pms = rng.random_vec(expected_pt_len);
587✔
44

45
      for(size_t i = 0; i != required_contents_length; ++i) {
2,687✔
46
         const uint8_t exp = required_content_bytes[i];
2,100✔
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
         const uint8_t off = required_content_offsets[i];
2,100✔
55
         BOTAN_ASSERT(off < expected_pt_len, "Offset in range of plaintext");
2,100✔
56
         pms[off] = exp;
2,100✔
57
      }
58

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

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

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

68
   decoded.resize(expected_pt_len);
587✔
69

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

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

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

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

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

84
   return decoded;
587✔
85
}
587✔
86

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

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

104
PK_Encryptor_EME::~PK_Encryptor_EME() = default;
491✔
105

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

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

113
std::vector<uint8_t> PK_Encryptor_EME::enc(const uint8_t in[], size_t length, RandomNumberGenerator& rng) const {
355✔
114
   return m_op->encrypt(std::span{in, length}, rng);
355✔
115
}
116

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

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

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

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

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

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

144
PK_KEM_Encryptor::PK_KEM_Encryptor(const Public_Key& key, std::string_view param, std::string_view provider) {
862✔
145
   m_op = key.create_kem_encryption_op(param, provider);
862✔
146
   if(!m_op) {
862✔
147
      throw Invalid_Argument(fmt("Key type {} does not support KEM encryption", key.algo_name()));
×
148
   }
149
}
862✔
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
      PK_KEM_Encryptor(key, kem_param, provider) {
×
156
   BOTAN_UNUSED(rng);
×
157
}
×
158

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

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

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

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

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

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

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

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

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

203
PK_KEM_Decryptor::PK_KEM_Decryptor(PK_KEM_Decryptor&&) noexcept = default;
×
204
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,
3,460✔
207
                               std::span<const uint8_t> encap_key,
208
                               size_t desired_shared_key_len,
209
                               std::span<const uint8_t> salt) {
210
   BOTAN_ARG_CHECK(out_shared_key.size() == shared_key_length(desired_shared_key_len),
3,460✔
211
                   "inconsistent size of shared key output buffer");
212
   m_op->kem_decrypt(out_shared_key, encap_key, desired_shared_key_len, salt);
3,460✔
213
}
3,437✔
214

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

225
PK_Key_Agreement::~PK_Key_Agreement() = default;
8,825✔
226

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

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

234
SymmetricKey PK_Key_Agreement::derive_key(size_t key_len,
185✔
235
                                          const uint8_t peer_key[],
236
                                          size_t peer_key_len,
237
                                          std::string_view salt) const {
238
   return this->derive_key(key_len, peer_key, peer_key_len, cast_char_ptr_to_uint8(salt.data()), salt.length());
185✔
239
}
240

241
SymmetricKey PK_Key_Agreement::derive_key(size_t key_len,
10,204✔
242
                                          const std::span<const uint8_t> peer_key,
243
                                          std::string_view salt) const {
244
   return this->derive_key(
10,204✔
245
      key_len, peer_key.data(), peer_key.size(), cast_char_ptr_to_uint8(salt.data()), salt.length());
10,204✔
246
}
247

248
SymmetricKey PK_Key_Agreement::derive_key(
10,405✔
249
   size_t key_len, const uint8_t peer_key[], size_t peer_key_len, const uint8_t salt[], size_t salt_len) const {
250
   return SymmetricKey(m_op->agree(key_len, {peer_key, peer_key_len}, {salt, salt_len}));
10,405✔
251
}
252

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

264
   m_op = key.create_signature_op(rng, emsa, provider);
8,311✔
265
   if(!m_op) {
4,562✔
266
      throw Invalid_Argument(fmt("Key type {} does not support signature generation", key.algo_name()));
×
267
   }
268
}
8,311✔
269

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

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

278
PK_Signer::~PK_Signer() = default;
4,562✔
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(cast_char_ptr_to_uint8(in.data()), in.size());
1✔
285
}
1✔
286

287
void PK_Signer::update(const uint8_t in[], size_t length) {
7,664✔
288
   m_op->update({in, length});
7,664✔
289
}
7,663✔
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) {
8,948✔
294
   if(sig.size() % parts != 0 || sig.size() != parts * part_size) {
8,948✔
295
      throw Encoding_Error("Unexpected size for DER signature");
×
296
   }
297

298
   BufferSlicer bs_sig(sig);
8,948✔
299
   std::vector<BigInt> sig_parts;
8,948✔
300
   sig_parts.reserve(parts);
8,948✔
301
   for(size_t i = 0; i != parts; ++i) {
26,844✔
302
      sig_parts.emplace_back(BigInt::from_bytes(bs_sig.take(part_size)));
35,792✔
303
   }
304

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

310
}  // namespace
311

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

318
      size_t der_overhead = [sig_len]() {
9✔
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) {
3✔
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
      }();
3✔
349

350
      return sig_len + der_overhead;
3✔
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) {
7,632✔
357
   std::vector<uint8_t> sig = m_op->sign(rng);
7,632✔
358

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

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

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

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

386
PK_Verifier::PK_Verifier(const Public_Key& key,
16,146✔
387
                         const AlgorithmIdentifier& signature_algorithm,
388
                         std::string_view provider) {
16,146✔
389
   m_op = key.create_x509_verification_op(signature_algorithm, provider);
16,146✔
390
   if(!m_op) {
16,101✔
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();
16,101✔
395
   m_sig_element_size = key._signature_element_size_for_DER_encoding();
16,101✔
396
}
16,146✔
397

398
PK_Verifier::~PK_Verifier() = default;
30,164✔
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 {
15,749✔
404
   return m_op->hash_function();
15,749✔
405
}
406

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

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

419
void PK_Verifier::update(std::string_view in) {
1✔
420
   this->update(cast_char_ptr_to_uint8(in.data()), in.size());
1✔
421
}
1✔
422

423
void PK_Verifier::update(const uint8_t in[], size_t length) {
90,962✔
424
   m_op->update({in, length});
90,962✔
425
}
90,962✔
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) {
10,794✔
430
   std::vector<uint8_t> real_sig;
10,794✔
431
   BER_Decoder decoder(sig, length);
10,794✔
432
   BER_Decoder ber_sig = decoder.start_sequence();
10,794✔
433

434
   BOTAN_ASSERT_NOMSG(sig_parts != 0 && sig_part_size != 0);
10,466✔
435

436
   size_t count = 0;
437

438
   while(ber_sig.more_items()) {
28,954✔
439
      BigInt sig_part;
20,306✔
440
      ber_sig.decode(sig_part);
20,306✔
441
      real_sig += sig_part.serialize(sig_part_size);
20,306✔
442
      ++count;
18,488✔
443
   }
20,306✔
444

445
   if(count != sig_parts) {
8,648✔
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);
8,546✔
450

451
   if(reencoded.size() != length || CT::is_equal(reencoded.data(), sig, reencoded.size()).as_bool() == false) {
16,789✔
452
      throw Decoding_Error("PK_Verifier: signature is not the canonical DER encoding");
705✔
453
   }
454
   return real_sig;
15,682✔
455
}
13,419✔
456

457
}  // namespace
458

459
bool PK_Verifier::check_signature(const uint8_t sig[], size_t length) {
92,248✔
460
   try {
92,248✔
461
      if(m_sig_format == Signature_Format::Standard) {
92,248✔
462
         return m_op->is_valid_signature({sig, length});
81,454✔
463
      } else if(m_sig_format == Signature_Format::DerSequence) {
10,794✔
464
         bool decoding_success = false;
10,794✔
465
         std::vector<uint8_t> real_sig;
10,794✔
466

467
         BOTAN_ASSERT_NOMSG(m_sig_element_size.has_value());
10,794✔
468

469
         try {
10,794✔
470
            real_sig = decode_der_signature(sig, length, 2, m_sig_element_size.value());
18,635✔
471
            decoding_success = true;
7,841✔
472
         } catch(Decoding_Error&) {}
2,953✔
473

474
         bool accept = m_op->is_valid_signature(real_sig);
10,794✔
475

476
         return accept && decoding_success;
10,571✔
477
      } else {
10,794✔
478
         throw Internal_Error("PK_Verifier: Invalid signature format enum");
×
479
      }
480
   } catch(Invalid_Argument&) {
328✔
481
      return false;
223✔
482
   } catch(Decoding_Error&) {
328✔
483
      return false;
105✔
484
   } catch(Encoding_Error&) {
105✔
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