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

randombit / botan / 12831658451

17 Jan 2025 03:07PM UTC coverage: 91.206% (-0.006%) from 91.212%
12831658451

Pull #4567

github

web-flow
Merge 34786d9de into 6a97b80e9
Pull Request #4567: Context support for ML-DSA and SLH-DSA

93825 of 102871 relevant lines covered (91.21%)

11369960.98 hits per line

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

86.59
/src/lib/pubkey/pubkey.cpp
1
/*
2
* (C) 1999-2010,2015,2018,2024 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/pk_ops.h>
13
#include <botan/pss_params.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/stl_util.h>
19

20
namespace Botan {
21

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

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

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

31
   return decoded;
3,695✔
32
}
3,191✔
33

34
secure_vector<uint8_t> PK_Decryptor::decrypt_or_random(const uint8_t in[],
263✔
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
                                                       size_t required_contents_length) const {
41
   const secure_vector<uint8_t> fake_pms = rng.random_vec(expected_pt_len);
263✔
42

43
   uint8_t decrypt_valid = 0;
263✔
44
   secure_vector<uint8_t> decoded = do_decrypt(decrypt_valid, in, length);
263✔
45

46
   auto valid_mask = CT::Mask<uint8_t>::is_equal(decrypt_valid, 0xFF);
263✔
47
   valid_mask &= CT::Mask<uint8_t>(CT::Mask<size_t>::is_zero(decoded.size() ^ expected_pt_len));
263✔
48

49
   decoded.resize(expected_pt_len);
263✔
50

51
   for(size_t i = 0; i != required_contents_length; ++i) {
379✔
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
      const uint8_t exp = required_content_bytes[i];
116✔
64
      const uint8_t off = required_content_offsets[i];
116✔
65

66
      BOTAN_ASSERT(off < expected_pt_len, "Offset in range of plaintext");
116✔
67

68
      auto eq = CT::Mask<uint8_t>::is_equal(decoded[off], exp);
116✔
69

70
      valid_mask &= eq;
116✔
71
   }
72

73
   // If valid_mask is false, assign fake pre master instead
74
   valid_mask.select_n(decoded.data(), decoded.data(), fake_pms.data(), expected_pt_len);
263✔
75

76
   return decoded;
263✔
77
}
263✔
78

79
secure_vector<uint8_t> PK_Decryptor::decrypt_or_random(const uint8_t in[],
205✔
80
                                                       size_t length,
81
                                                       size_t expected_pt_len,
82
                                                       RandomNumberGenerator& rng) const {
83
   return decrypt_or_random(in, length, expected_pt_len, rng, nullptr, nullptr, 0);
205✔
84
}
85

86
PK_Encryptor_EME::PK_Encryptor_EME(const Public_Key& key,
882✔
87
                                   RandomNumberGenerator& rng,
88
                                   std::string_view padding,
89
                                   std::string_view provider) {
882✔
90
   m_op = key.create_encryption_op(rng, padding, provider);
882✔
91
   if(!m_op) {
285✔
92
      throw Invalid_Argument(fmt("Key type {} does not support encryption", key.algo_name()));
×
93
   }
94
}
882✔
95

96
PK_Encryptor_EME::~PK_Encryptor_EME() = default;
489✔
97

98
PK_Encryptor_EME::PK_Encryptor_EME(PK_Encryptor_EME&&) noexcept = default;
×
99
PK_Encryptor_EME& PK_Encryptor_EME::operator=(PK_Encryptor_EME&&) noexcept = default;
×
100

101
size_t PK_Encryptor_EME::ciphertext_length(size_t ptext_len) const {
204✔
102
   return m_op->ciphertext_length(ptext_len);
204✔
103
}
104

105
std::vector<uint8_t> PK_Encryptor_EME::enc(const uint8_t in[], size_t length, RandomNumberGenerator& rng) const {
353✔
106
   return m_op->encrypt(std::span{in, length}, rng);
353✔
107
}
108

109
size_t PK_Encryptor_EME::maximum_input_size() const {
209✔
110
   return m_op->max_input_bits() / 8;
209✔
111
}
112

113
PK_Decryptor_EME::PK_Decryptor_EME(const Private_Key& key,
1,050✔
114
                                   RandomNumberGenerator& rng,
115
                                   std::string_view padding,
116
                                   std::string_view provider) {
1,050✔
117
   m_op = key.create_decryption_op(rng, padding, provider);
1,050✔
118
   if(!m_op) {
327✔
119
      throw Invalid_Argument(fmt("Key type {} does not support decryption", key.algo_name()));
×
120
   }
121
}
1,050✔
122

123
PK_Decryptor_EME::~PK_Decryptor_EME() = default;
573✔
124

125
PK_Decryptor_EME::PK_Decryptor_EME(PK_Decryptor_EME&&) noexcept = default;
×
126
PK_Decryptor_EME& PK_Decryptor_EME::operator=(PK_Decryptor_EME&&) noexcept = default;
×
127

128
size_t PK_Decryptor_EME::plaintext_length(size_t ctext_len) const {
203✔
129
   return m_op->plaintext_length(ctext_len);
203✔
130
}
131

132
secure_vector<uint8_t> PK_Decryptor_EME::do_decrypt(uint8_t& valid_mask, const uint8_t in[], size_t in_len) const {
5,451✔
133
   return m_op->decrypt(valid_mask, {in, in_len});
5,451✔
134
}
135

136
PK_KEM_Encryptor::PK_KEM_Encryptor(const Public_Key& key, std::string_view param, std::string_view provider) {
862✔
137
   m_op = key.create_kem_encryption_op(param, provider);
862✔
138
   if(!m_op) {
862✔
139
      throw Invalid_Argument(fmt("Key type {} does not support KEM encryption", key.algo_name()));
×
140
   }
141
}
862✔
142

143
PK_KEM_Encryptor::~PK_KEM_Encryptor() = default;
862✔
144

145
PK_KEM_Encryptor::PK_KEM_Encryptor(PK_KEM_Encryptor&&) noexcept = default;
×
146
PK_KEM_Encryptor& PK_KEM_Encryptor::operator=(PK_KEM_Encryptor&&) noexcept = default;
×
147

148
size_t PK_KEM_Encryptor::shared_key_length(size_t desired_shared_key_len) const {
6,886✔
149
   return m_op->shared_key_length(desired_shared_key_len);
6,886✔
150
}
151

152
size_t PK_KEM_Encryptor::encapsulated_key_length() const {
6,886✔
153
   return m_op->encapsulated_key_length();
6,886✔
154
}
155

156
void PK_KEM_Encryptor::encrypt(std::span<uint8_t> out_encapsulated_key,
3,389✔
157
                               std::span<uint8_t> out_shared_key,
158
                               RandomNumberGenerator& rng,
159
                               size_t desired_shared_key_len,
160
                               std::span<const uint8_t> salt) {
161
   BOTAN_ARG_CHECK(out_encapsulated_key.size() == encapsulated_key_length(), "not enough space for encapsulated key");
3,389✔
162
   BOTAN_ARG_CHECK(out_shared_key.size() == shared_key_length(desired_shared_key_len),
3,389✔
163
                   "not enough space for shared key");
164
   m_op->kem_encrypt(out_encapsulated_key, out_shared_key, rng, desired_shared_key_len, salt);
3,389✔
165
}
3,386✔
166

167
size_t PK_KEM_Decryptor::shared_key_length(size_t desired_shared_key_len) const {
7,032✔
168
   return m_op->shared_key_length(desired_shared_key_len);
7,032✔
169
}
170

171
size_t PK_KEM_Decryptor::encapsulated_key_length() const {
132✔
172
   return m_op->encapsulated_key_length();
132✔
173
}
174

175
PK_KEM_Decryptor::PK_KEM_Decryptor(const Private_Key& key,
804✔
176
                                   RandomNumberGenerator& rng,
177
                                   std::string_view param,
178
                                   std::string_view provider) {
804✔
179
   m_op = key.create_kem_decryption_op(rng, param, provider);
804✔
180
   if(!m_op) {
804✔
181
      throw Invalid_Argument(fmt("Key type {} does not support KEM decryption", key.algo_name()));
×
182
   }
183
}
804✔
184

185
PK_KEM_Decryptor::~PK_KEM_Decryptor() = default;
804✔
186

187
PK_KEM_Decryptor::PK_KEM_Decryptor(PK_KEM_Decryptor&&) noexcept = default;
×
188
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,
3,460✔
191
                               std::span<const uint8_t> encap_key,
192
                               size_t desired_shared_key_len,
193
                               std::span<const uint8_t> salt) {
194
   BOTAN_ARG_CHECK(out_shared_key.size() == shared_key_length(desired_shared_key_len),
3,460✔
195
                   "inconsistent size of shared key output buffer");
196
   m_op->kem_decrypt(out_shared_key, encap_key, desired_shared_key_len, salt);
3,460✔
197
}
3,437✔
198

199
PK_Key_Agreement::PK_Key_Agreement(const Private_Key& key,
11,179✔
200
                                   RandomNumberGenerator& rng,
201
                                   std::string_view kdf,
202
                                   std::string_view provider) {
11,179✔
203
   m_op = key.create_key_agreement_op(rng, kdf, provider);
11,179✔
204
   if(!m_op) {
8,827✔
205
      throw Invalid_Argument(fmt("Key type {} does not support key agreement", key.algo_name()));
×
206
   }
207
}
11,179✔
208

209
PK_Key_Agreement::~PK_Key_Agreement() = default;
8,827✔
210

211
PK_Key_Agreement::PK_Key_Agreement(PK_Key_Agreement&&) noexcept = default;
×
212
PK_Key_Agreement& PK_Key_Agreement::operator=(PK_Key_Agreement&&) noexcept = default;
×
213

214
size_t PK_Key_Agreement::agreed_value_size() const {
872✔
215
   return m_op->agreed_value_size();
872✔
216
}
217

218
SymmetricKey PK_Key_Agreement::derive_key(size_t key_len,
185✔
219
                                          const uint8_t in[],
220
                                          size_t in_len,
221
                                          std::string_view params) const {
222
   return this->derive_key(key_len, in, in_len, cast_char_ptr_to_uint8(params.data()), params.length());
185✔
223
}
224

225
SymmetricKey PK_Key_Agreement::derive_key(size_t key_len,
10,204✔
226
                                          const std::span<const uint8_t> in,
227
                                          std::string_view params) const {
228
   return this->derive_key(key_len, in.data(), in.size(), cast_char_ptr_to_uint8(params.data()), params.length());
10,204✔
229
}
230

231
SymmetricKey PK_Key_Agreement::derive_key(
10,405✔
232
   size_t key_len, const uint8_t in[], size_t in_len, const uint8_t salt[], size_t salt_len) const {
233
   return SymmetricKey(m_op->agree(key_len, {in, in_len}, {salt, salt_len}));
10,405✔
234
}
235

236
namespace {
237

238
void check_der_format_supported(Signature_Format format, size_t parts) {
35,857✔
239
   if(format != Signature_Format::Standard && parts == 1) {
35,857✔
240
      throw Invalid_Argument("This algorithm does not support DER encoding");
×
241
   }
242
}
35,857✔
243

244
}  // namespace
245

246
PK_Signer::PK_Signer(PK_Signature_Options options) {
8,309✔
247
   // Appease GCC warning about a possibly dangling reference because when using
248
   // std::reference_wrapper's implicit conversion to the contained reference
249
   // the wrapper does not outlive the reference which seems to confuse GCC.
250
   const auto key_wrapped = options.private_key().required();
8,309✔
251
   const Private_Key& key = key_wrapped.get();
8,309✔
252

253
   // TODO: The downstream algorithms should decide whether to require an RNG
254
   //       (e.g. explicitly 'deterministic' signatures should not require it).
255
   RandomNumberGenerator& rng = options.rng().required();
8,309✔
256

257
   m_op = key._create_signature_op(rng, options);
8,309✔
258
   if(!m_op) {
4,562✔
259
      throw Invalid_Argument(fmt("Key type {} does not support signature generation", key.algo_name()));
×
260
   }
261
   m_sig_format = options.using_der_encoded_signature() ? Signature_Format::DerSequence : Signature_Format::Standard;
4,562✔
262
   m_parts = key.message_parts();
4,562✔
263
   m_part_size = key.message_part_size();
4,562✔
264
   check_der_format_supported(m_sig_format, m_parts);
4,562✔
265

266
   options.validate_option_consumption();
4,562✔
267
}
8,309✔
268

269
PK_Signer::PK_Signer(const Private_Key& key,
8,127✔
270
                     RandomNumberGenerator& rng,
271
                     std::string_view padding,
272
                     Signature_Format format,
273
                     std::string_view provider) :
8,127✔
274
      PK_Signer(PK_Signature_Options::from_legacy(key, rng, padding, format, provider)) {}
12,505✔
275

276
AlgorithmIdentifier PK_Signer::algorithm_identifier() const {
505✔
277
   return m_op->algorithm_identifier();
505✔
278
}
279

280
std::string PK_Signer::hash_function() const {
806✔
281
   return m_op->hash_function();
806✔
282
}
283

284
PK_Signer::~PK_Signer() = default;
4,562✔
285

286
PK_Signer::PK_Signer(PK_Signer&&) noexcept = default;
×
287
PK_Signer& PK_Signer::operator=(PK_Signer&&) noexcept = default;
×
288

289
void PK_Signer::update(std::string_view in) {
1✔
290
   this->update(cast_char_ptr_to_uint8(in.data()), in.size());
1✔
291
}
1✔
292

293
void PK_Signer::update(const uint8_t in[], size_t length) {
7,665✔
294
   m_op->update({in, length});
7,665✔
295
}
7,664✔
296

297
namespace {
298

299
std::vector<uint8_t> der_encode_signature(std::span<const uint8_t> sig, size_t parts, size_t part_size) {
8,943✔
300
   if(sig.size() % parts != 0 || sig.size() != parts * part_size) {
8,943✔
301
      throw Encoding_Error("Unexpected size for DER signature");
×
302
   }
303

304
   BufferSlicer bs_sig(sig);
8,943✔
305
   std::vector<BigInt> sig_parts;
8,943✔
306
   sig_parts.reserve(parts);
8,943✔
307
   for(size_t i = 0; i != parts; ++i) {
26,829✔
308
      sig_parts.emplace_back(BigInt::from_bytes(bs_sig.take(part_size)));
35,772✔
309
   }
310

311
   std::vector<uint8_t> output;
8,943✔
312
   DER_Encoder(output).start_sequence().encode_list(sig_parts).end_cons();
35,772✔
313
   return output;
8,943✔
314
}
8,943✔
315

316
}  // namespace
317

318
size_t PK_Signer::signature_length() const {
1,278✔
319
   if(m_sig_format == Signature_Format::Standard) {
1,278✔
320
      return m_op->signature_length();
1,275✔
321
   } else if(m_sig_format == Signature_Format::DerSequence) {
3✔
322
      // This is a large over-estimate but its easier than computing
323
      // the exact value
324
      return m_op->signature_length() + (8 + 4 * m_parts);
3✔
325
   } else {
326
      throw Internal_Error("PK_Signer: Invalid signature format enum");
×
327
   }
328
}
329

330
std::vector<uint8_t> PK_Signer::signature(RandomNumberGenerator& rng) {
7,633✔
331
   std::vector<uint8_t> sig = m_op->sign(rng);
7,633✔
332

333
   if(m_sig_format == Signature_Format::Standard) {
7,629✔
334
      return sig;
7,228✔
335
   } else if(m_sig_format == Signature_Format::DerSequence) {
401✔
336
      return der_encode_signature(sig, m_parts, m_part_size);
401✔
337
   } else {
338
      throw Internal_Error("PK_Signer: Invalid signature format enum");
×
339
   }
340
}
7,629✔
341

342
PK_Verifier::PK_Verifier(PK_Signature_Options options) {
63,406✔
343
   // Appease GCC warning about a possibly dangling reference because when using
344
   // std::reference_wrapper's implicit conversion to the contained reference
345
   // the wrapper does not outlive the reference which seems to confuse GCC.
346
   const auto key_wrapped = options.public_key().required();
63,406✔
347
   const Public_Key& key = key_wrapped.get();
63,406✔
348
   m_op = key._create_verification_op(options);
63,406✔
349
   if(!m_op) {
14,063✔
350
      throw Invalid_Argument(fmt("Key type {} does not support signature verification", key.algo_name()));
×
351
   }
352
   m_sig_format = options.using_der_encoded_signature() ? Signature_Format::DerSequence : Signature_Format::Standard;
14,063✔
353
   m_parts = key.message_parts();
14,063✔
354
   m_part_size = key.message_part_size();
14,063✔
355
   check_der_format_supported(m_sig_format, m_parts);
14,063✔
356

357
   options.validate_option_consumption();
14,063✔
358
}
63,406✔
359

360
PK_Verifier::PK_Verifier(const Public_Key& pub_key,
61,605✔
361
                         std::string_view padding,
362
                         Signature_Format format,
363
                         std::string_view provider) :
61,605✔
364
      PK_Verifier(PK_Signature_Options::from_legacy(pub_key, padding, format, provider)) {}
73,867✔
365

366
PK_Verifier::PK_Verifier(const Public_Key& key,
17,277✔
367
                         const AlgorithmIdentifier& signature_algorithm,
368
                         std::string_view provider) {
17,277✔
369
   m_op = key.create_x509_verification_op(signature_algorithm, provider);
17,277✔
370

371
   if(!m_op) {
17,232✔
372
      throw Invalid_Argument(fmt("Key type {} does not support X.509 signature verification", key.algo_name()));
×
373
   }
374

375
   m_sig_format = key.default_x509_signature_format();
17,232✔
376
   m_parts = key.message_parts();
17,232✔
377
   m_part_size = key.message_part_size();
17,232✔
378
   check_der_format_supported(m_sig_format, m_parts);
17,232✔
379
}
17,277✔
380

381
PK_Verifier::~PK_Verifier() = default;
31,295✔
382

383
PK_Verifier::PK_Verifier(PK_Verifier&&) noexcept = default;
×
384
PK_Verifier& PK_Verifier::operator=(PK_Verifier&&) noexcept = default;
×
385

386
std::string PK_Verifier::hash_function() const {
16,880✔
387
   return m_op->hash_function();
16,880✔
388
}
389

390
void PK_Verifier::set_input_format(Signature_Format format) {
×
391
   check_der_format_supported(format, m_parts);
×
392
   m_sig_format = format;
×
393
}
×
394

395
bool PK_Verifier::verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length) {
87,363✔
396
   update(msg, msg_length);
87,363✔
397
   return check_signature(sig, sig_length);
87,363✔
398
}
399

400
void PK_Verifier::update(std::string_view in) {
1✔
401
   this->update(cast_char_ptr_to_uint8(in.data()), in.size());
1✔
402
}
1✔
403

404
void PK_Verifier::update(const uint8_t in[], size_t length) {
92,097✔
405
   m_op->update({in, length});
92,097✔
406
}
92,097✔
407

408
namespace {
409

410
std::vector<uint8_t> decode_der_signature(const uint8_t sig[], size_t length, size_t sig_parts, size_t sig_part_size) {
10,790✔
411
   std::vector<uint8_t> real_sig;
10,790✔
412
   BER_Decoder decoder(sig, length);
10,790✔
413
   BER_Decoder ber_sig = decoder.start_sequence();
10,790✔
414

415
   BOTAN_ASSERT_NOMSG(sig_parts != 0 && sig_part_size != 0);
10,462✔
416

417
   size_t count = 0;
418

419
   while(ber_sig.more_items()) {
28,942✔
420
      BigInt sig_part;
20,298✔
421
      ber_sig.decode(sig_part);
20,298✔
422
      real_sig += sig_part.serialize(sig_part_size);
20,298✔
423
      ++count;
18,480✔
424
   }
20,298✔
425

426
   if(count != sig_parts) {
8,644✔
427
      throw Decoding_Error("PK_Verifier: signature size invalid");
102✔
428
   }
429

430
   const std::vector<uint8_t> reencoded = der_encode_signature(real_sig, sig_parts, sig_part_size);
8,542✔
431

432
   if(reencoded.size() != length || CT::is_equal(reencoded.data(), sig, reencoded.size()).as_bool() == false) {
16,782✔
433
      throw Decoding_Error("PK_Verifier: signature is not the canonical DER encoding");
703✔
434
   }
435
   return real_sig;
15,678✔
436
}
13,413✔
437

438
}  // namespace
439

440
bool PK_Verifier::check_signature(const uint8_t sig[], size_t length) {
93,383✔
441
   try {
93,383✔
442
      if(m_sig_format == Signature_Format::Standard) {
93,383✔
443
         return m_op->is_valid_signature({sig, length});
82,593✔
444
      } else if(m_sig_format == Signature_Format::DerSequence) {
10,790✔
445
         bool decoding_success = false;
10,790✔
446
         std::vector<uint8_t> real_sig;
10,790✔
447

448
         try {
10,790✔
449
            real_sig = decode_der_signature(sig, length, m_parts, m_part_size);
18,629✔
450
            decoding_success = true;
7,839✔
451
         } catch(Decoding_Error&) {}
2,951✔
452

453
         bool accept = m_op->is_valid_signature(real_sig);
10,790✔
454

455
         return accept && decoding_success;
10,567✔
456
      } else {
10,790✔
457
         throw Internal_Error("PK_Verifier: Invalid signature format enum");
×
458
      }
459
   } catch(Invalid_Argument&) {
335✔
460
      return false;
223✔
461
   } catch(Decoding_Error&) {
335✔
462
      return false;
112✔
463
   } catch(Encoding_Error&) {
112✔
464
      return false;
×
465
   }
×
466
}
467

468
}  // 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