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

randombit / botan / 6449923637

08 Oct 2023 08:54PM UTC coverage: 91.69% (+0.003%) from 91.687%
6449923637

push

github

web-flow
Merge pull request #3735 from randombit/jack/tidy-20231006

Some small updates for clang-tidy 16

79975 of 87223 relevant lines covered (91.69%)

8556149.88 hits per line

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

85.65
/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/rng.h>
13
#include <botan/internal/ct_utils.h>
14
#include <botan/internal/fmt.h>
15
#include <botan/internal/parsing.h>
16
#include <botan/internal/pk_ops.h>
17
#include <botan/internal/pss_params.h>
18

19
namespace Botan {
20

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

24
   secure_vector<uint8_t> decoded = do_decrypt(valid_mask, in, length);
5,541✔
25

26
   if(valid_mask == 0) {
5,513✔
27
      throw Decoding_Error("Invalid public key ciphertext, cannot decrypt");
3,180✔
28
   }
29

30
   return decoded;
2,333✔
31
}
3,180✔
32

33
secure_vector<uint8_t> PK_Decryptor::decrypt_or_random(const uint8_t in[],
135✔
34
                                                       size_t length,
35
                                                       size_t expected_pt_len,
36
                                                       RandomNumberGenerator& rng,
37
                                                       const uint8_t required_content_bytes[],
38
                                                       const uint8_t required_content_offsets[],
39
                                                       size_t required_contents_length) const {
40
   const secure_vector<uint8_t> fake_pms = rng.random_vec(expected_pt_len);
135✔
41

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

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

48
   decoded.resize(expected_pt_len);
135✔
49

50
   for(size_t i = 0; i != required_contents_length; ++i) {
251✔
51
      /*
52
      These values are chosen by the application and for TLS are constants,
53
      so this early failure via assert is fine since we know 0,1 < 48
54

55
      If there is a protocol that has content checks on the key where
56
      the expected offsets are controllable by the attacker this could
57
      still leak.
58

59
      Alternately could always reduce the offset modulo the length?
60
      */
61

62
      const uint8_t exp = required_content_bytes[i];
116✔
63
      const uint8_t off = required_content_offsets[i];
116✔
64

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

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

69
      valid_mask &= eq;
116✔
70
   }
71

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

75
   return decoded;
135✔
76
}
135✔
77

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

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

95
PK_Encryptor_EME::~PK_Encryptor_EME() = default;
348✔
96

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

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

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

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

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

122
PK_Decryptor_EME::~PK_Decryptor_EME() = default;
438✔
123

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

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

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

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

142
PK_KEM_Encryptor::~PK_KEM_Encryptor() = default;
750✔
143

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

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

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

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

166
size_t PK_KEM_Decryptor::shared_key_length(size_t desired_shared_key_len) const {
6,515✔
167
   return m_op->shared_key_length(desired_shared_key_len);
6,515✔
168
}
169

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

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

184
PK_KEM_Decryptor::~PK_KEM_Decryptor() = default;
745✔
185

186
PK_KEM_Decryptor::PK_KEM_Decryptor(PK_KEM_Decryptor&&) noexcept = default;
×
187
PK_KEM_Decryptor& PK_KEM_Decryptor::operator=(PK_KEM_Decryptor&&) noexcept = default;
×
188

189
void PK_KEM_Decryptor::decrypt(std::span<uint8_t> out_shared_key,
3,241✔
190
                               std::span<const uint8_t> encap_key,
191
                               size_t desired_shared_key_len,
192
                               std::span<const uint8_t> salt) {
193
   BOTAN_ARG_CHECK(out_shared_key.size() == shared_key_length(desired_shared_key_len),
3,241✔
194
                   "inconsistent size of shared key output buffer");
195
   m_op->kem_decrypt(out_shared_key, encap_key, desired_shared_key_len, salt);
3,241✔
196
}
3,235✔
197

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

208
PK_Key_Agreement::~PK_Key_Agreement() = default;
2,633✔
209

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

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

217
SymmetricKey PK_Key_Agreement::derive_key(
4,213✔
218
   size_t key_len, const uint8_t in[], size_t in_len, const uint8_t salt[], size_t salt_len) const {
219
   return SymmetricKey(m_op->agree(key_len, in, in_len, salt, salt_len));
4,213✔
220
}
221

222
namespace {
223

224
void check_der_format_supported(Signature_Format format, size_t parts) {
28,456✔
225
   if(format != Signature_Format::Standard && parts == 1) {
28,456✔
226
      throw Invalid_Argument("This algorithm does not support DER encoding");
×
227
   }
228
}
28,456✔
229

230
}  // namespace
231

232
PK_Signer::PK_Signer(const Private_Key& key,
7,333✔
233
                     RandomNumberGenerator& rng,
234
                     std::string_view emsa,
235
                     Signature_Format format,
236
                     std::string_view provider) {
7,333✔
237
   m_op = key.create_signature_op(rng, emsa, provider);
7,333✔
238
   if(!m_op) {
3,848✔
239
      throw Invalid_Argument(fmt("Key type {} does not support signature generation", key.algo_name()));
×
240
   }
241
   m_sig_format = format;
3,848✔
242
   m_parts = key.message_parts();
3,848✔
243
   m_part_size = key.message_part_size();
3,848✔
244
   check_der_format_supported(format, m_parts);
3,848✔
245
}
7,333✔
246

247
AlgorithmIdentifier PK_Signer::algorithm_identifier() const {
368✔
248
   return m_op->algorithm_identifier();
368✔
249
}
250

251
std::string PK_Signer::hash_function() const {
587✔
252
   return m_op->hash_function();
587✔
253
}
254

255
PK_Signer::~PK_Signer() = default;
3,848✔
256

257
PK_Signer::PK_Signer(PK_Signer&&) noexcept = default;
×
258
PK_Signer& PK_Signer::operator=(PK_Signer&&) noexcept = default;
×
259

260
void PK_Signer::update(const uint8_t in[], size_t length) {
4,577✔
261
   m_op->update(in, length);
4,577✔
262
}
4,576✔
263

264
namespace {
265

266
std::vector<uint8_t> der_encode_signature(const std::vector<uint8_t>& sig, size_t parts, size_t part_size) {
8,115✔
267
   if(sig.size() % parts != 0 || sig.size() != parts * part_size) {
8,115✔
268
      throw Encoding_Error("Unexpected size for DER signature");
×
269
   }
270

271
   std::vector<BigInt> sig_parts(parts);
8,115✔
272
   for(size_t i = 0; i != sig_parts.size(); ++i) {
24,345✔
273
      sig_parts[i].binary_decode(&sig[part_size * i], part_size);
16,230✔
274
   }
275

276
   std::vector<uint8_t> output;
8,115✔
277
   DER_Encoder(output).start_sequence().encode_list(sig_parts).end_cons();
32,460✔
278
   return output;
8,115✔
279
}
8,115✔
280

281
}  // namespace
282

283
size_t PK_Signer::signature_length() const {
1,172✔
284
   if(m_sig_format == Signature_Format::Standard) {
1,172✔
285
      return m_op->signature_length();
1,169✔
286
   } else if(m_sig_format == Signature_Format::DerSequence) {
3✔
287
      // This is a large over-estimate but its easier than computing
288
      // the exact value
289
      return m_op->signature_length() + (8 + 4 * m_parts);
3✔
290
   } else {
291
      throw Internal_Error("PK_Signer: Invalid signature format enum");
×
292
   }
293
}
294

295
std::vector<uint8_t> PK_Signer::signature(RandomNumberGenerator& rng) {
4,320✔
296
   std::vector<uint8_t> sig = unlock(m_op->sign(rng));
8,639✔
297

298
   if(m_sig_format == Signature_Format::Standard) {
4,319✔
299
      return sig;
4,319✔
300
   } else if(m_sig_format == Signature_Format::DerSequence) {
382✔
301
      return der_encode_signature(sig, m_parts, m_part_size);
382✔
302
   } else {
303
      throw Internal_Error("PK_Signer: Invalid signature format enum");
×
304
   }
305
}
4,319✔
306

307
PK_Verifier::PK_Verifier(const Public_Key& key,
60,698✔
308
                         std::string_view emsa,
309
                         Signature_Format format,
310
                         std::string_view provider) {
60,698✔
311
   m_op = key.create_verification_op(emsa, provider);
60,698✔
312
   if(!m_op) {
12,963✔
313
      throw Invalid_Argument(fmt("Key type {} does not support signature verification", key.algo_name()));
×
314
   }
315
   m_sig_format = format;
12,963✔
316
   m_parts = key.message_parts();
12,963✔
317
   m_part_size = key.message_part_size();
12,963✔
318
   check_der_format_supported(format, m_parts);
12,963✔
319
}
60,698✔
320

321
PK_Verifier::PK_Verifier(const Public_Key& key,
11,701✔
322
                         const AlgorithmIdentifier& signature_algorithm,
323
                         std::string_view provider) {
11,701✔
324
   m_op = key.create_x509_verification_op(signature_algorithm, provider);
11,701✔
325

326
   if(!m_op) {
11,645✔
327
      throw Invalid_Argument(fmt("Key type {} does not support X.509 signature verification", key.algo_name()));
×
328
   }
329

330
   m_sig_format = key.default_x509_signature_format();
11,645✔
331
   m_parts = key.message_parts();
11,645✔
332
   m_part_size = key.message_part_size();
11,645✔
333
   check_der_format_supported(m_sig_format, m_parts);
11,645✔
334
}
11,701✔
335

336
PK_Verifier::~PK_Verifier() = default;
24,608✔
337

338
PK_Verifier::PK_Verifier(PK_Verifier&&) noexcept = default;
×
339
PK_Verifier& PK_Verifier::operator=(PK_Verifier&&) noexcept = default;
×
340

341
std::string PK_Verifier::hash_function() const {
10,994✔
342
   return m_op->hash_function();
10,994✔
343
}
344

345
void PK_Verifier::set_input_format(Signature_Format format) {
×
346
   check_der_format_supported(format, m_parts);
×
347
   m_sig_format = format;
×
348
}
×
349

350
bool PK_Verifier::verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length) {
64,050✔
351
   update(msg, msg_length);
64,050✔
352
   return check_signature(sig, sig_length);
64,050✔
353
}
354

355
void PK_Verifier::update(const uint8_t in[], size_t length) {
67,540✔
356
   m_op->update(in, length);
67,540✔
357
}
67,540✔
358

359
namespace {
360

361
std::vector<uint8_t> decode_der_signature(const uint8_t sig[], size_t length, size_t sig_parts, size_t sig_part_size) {
10,028✔
362
   std::vector<uint8_t> real_sig;
10,028✔
363
   BER_Decoder decoder(sig, length);
10,028✔
364
   BER_Decoder ber_sig = decoder.start_sequence();
10,028✔
365

366
   BOTAN_ASSERT_NOMSG(sig_parts != 0 && sig_part_size != 0);
9,685✔
367

368
   size_t count = 0;
369

370
   while(ber_sig.more_items()) {
26,967✔
371
      BigInt sig_part;
19,119✔
372
      ber_sig.decode(sig_part);
19,119✔
373
      real_sig += BigInt::encode_1363(sig_part, sig_part_size);
19,119✔
374
      ++count;
17,282✔
375
   }
19,119✔
376

377
   if(count != sig_parts) {
7,848✔
378
      throw Decoding_Error("PK_Verifier: signature size invalid");
115✔
379
   }
380

381
   const std::vector<uint8_t> reencoded = der_encode_signature(real_sig, sig_parts, sig_part_size);
7,733✔
382

383
   if(reencoded.size() != length || same_mem(reencoded.data(), sig, reencoded.size()) == false) {
15,028✔
384
      throw Decoding_Error("PK_Verifier: signature is not the canonical DER encoding");
926✔
385
   }
386
   return real_sig;
13,614✔
387
}
12,906✔
388

389
}  // namespace
390

391
bool PK_Verifier::check_signature(const uint8_t sig[], size_t length) {
67,927✔
392
   try {
67,927✔
393
      if(m_sig_format == Signature_Format::Standard) {
67,927✔
394
         return m_op->is_valid_signature(sig, length);
57,899✔
395
      } else if(m_sig_format == Signature_Format::DerSequence) {
10,028✔
396
         bool decoding_success = false;
10,028✔
397
         std::vector<uint8_t> real_sig;
10,028✔
398

399
         try {
10,028✔
400
            real_sig = decode_der_signature(sig, length, m_parts, m_part_size);
16,835✔
401
            decoding_success = true;
6,807✔
402
         } catch(Decoding_Error&) {}
3,221✔
403

404
         bool accept = m_op->is_valid_signature(real_sig.data(), real_sig.size());
9,803✔
405

406
         return accept && decoding_success;
9,803✔
407
      } else {
10,028✔
408
         throw Internal_Error("PK_Verifier: Invalid signature format enum");
×
409
      }
410
   } catch(Invalid_Argument&) {
328✔
411
      return false;
×
412
   } catch(Decoding_Error&) {
103✔
413
      return false;
103✔
414
   } catch(Encoding_Error&) {
328✔
415
      return false;
225✔
416
   }
225✔
417
}
418

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