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

randombit / botan / 19012754211

02 Nov 2025 01:10PM UTC coverage: 90.677% (+0.006%) from 90.671%
19012754211

push

github

web-flow
Merge pull request #5137 from randombit/jack/clang-tidy-includes

Remove various unused includes flagged by clang-tidy misc-include-cleaner

100457 of 110786 relevant lines covered (90.68%)

12189873.8 hits per line

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

93.53
/src/lib/pubkey/pk_ops.cpp
1
/*
2
* PK Operation Types
3
* (C) 2010,2015,2023 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/internal/pk_ops_impl.h>
9

10
#include <botan/assert.h>
11
#include <botan/hash.h>
12
#include <botan/kdf.h>
13
#include <botan/rng.h>
14
#include <botan/internal/ct_utils.h>
15
#include <botan/internal/enc_padding.h>
16
#include <botan/internal/fmt.h>
17
#include <botan/internal/parsing.h>
18
#include <botan/internal/scan_name.h>
19

20
#if defined(BOTAN_HAS_RAW_HASH_FN)
21
   #include <botan/internal/raw_hash.h>
22
#endif
23

24
namespace Botan {
25

26
AlgorithmIdentifier PK_Ops::Signature::algorithm_identifier() const {
×
27
   throw Not_Implemented("This signature scheme does not have an algorithm identifier available");
×
28
}
29

30
PK_Ops::Encryption_with_Padding::Encryption_with_Padding(std::string_view padding) :
301✔
31
      m_padding(EncryptionPaddingScheme::create(padding)) {}
301✔
32

33
PK_Ops::Encryption_with_Padding::~Encryption_with_Padding() = default;
301✔
34

35
size_t PK_Ops::Encryption_with_Padding::max_input_bits() const {
204✔
36
   return 8 * m_padding->maximum_input_size(max_ptext_input_bits());
204✔
37
}
38

39
std::vector<uint8_t> PK_Ops::Encryption_with_Padding::encrypt(std::span<const uint8_t> msg,
369✔
40
                                                              RandomNumberGenerator& rng) {
41
   const size_t max_input_bits = max_ptext_input_bits();
369✔
42
   const size_t max_input_bytes = (max_input_bits + 7) / 8;
369✔
43
   BOTAN_ARG_CHECK(msg.size() <= max_input_bytes, "Plaintext too large");
369✔
44

45
   secure_vector<uint8_t> padded_ptext(max_input_bits);
369✔
46
   const size_t written = m_padding->pad(padded_ptext, msg, max_input_bits, rng);
369✔
47
   return raw_encrypt(std::span{padded_ptext}.first(written), rng);
369✔
48
}
738✔
49

50
PK_Ops::Decryption_with_Padding::Decryption_with_Padding(std::string_view padding) :
314✔
51
      m_padding(EncryptionPaddingScheme::create(padding)) {}
314✔
52

53
PK_Ops::Decryption_with_Padding::~Decryption_with_Padding() = default;
314✔
54

55
secure_vector<uint8_t> PK_Ops::Decryption_with_Padding::decrypt(uint8_t& valid_mask, std::span<const uint8_t> ctext) {
5,659✔
56
   const secure_vector<uint8_t> raw = raw_decrypt(ctext);
5,659✔
57

58
   secure_vector<uint8_t> ptext(raw.size());
5,636✔
59
   auto len = m_padding->unpad(ptext, raw);
5,636✔
60

61
   valid_mask = CT::Mask<uint8_t>::from_choice(len.has_value()).if_set_return(0xFF);
5,636✔
62

63
   /*
64
   This is potentially not const time, depending on how std::vector is
65
   implemented. But since we are always reducing length, it should
66
   just amount to setting the member var holding the length. Resizing
67
   downwards is guaranteed to not change the capacity, and since we
68
   set ctext to the maximum possible size (equal to the raw input) we
69
   know that this is always, if anything, resizing smaller than the
70
   capacity, so no reallocation occurs.
71
   */
72

73
   ptext.resize(len.value_or(0));
5,636✔
74
   return ptext;
5,636✔
75
}
5,636✔
76

77
PK_Ops::Key_Agreement_with_KDF::Key_Agreement_with_KDF(std::string_view kdf) {
8,856✔
78
   if(kdf != "Raw") {
17,671✔
79
      m_kdf = KDF::create_or_throw(kdf);
41✔
80
   }
81
}
8,856✔
82

83
PK_Ops::Key_Agreement_with_KDF::~Key_Agreement_with_KDF() = default;
8,856✔
84

85
secure_vector<uint8_t> PK_Ops::Key_Agreement_with_KDF::agree(size_t key_len,
10,437✔
86
                                                             std::span<const uint8_t> other_key,
87
                                                             std::span<const uint8_t> salt) {
88
   if(!salt.empty() && m_kdf == nullptr) {
10,437✔
89
      throw Invalid_Argument("PK_Key_Agreement::derive_key requires a KDF to use a salt");
×
90
   }
91

92
   secure_vector<uint8_t> z = raw_agree(other_key.data(), other_key.size());
10,437✔
93
   if(m_kdf) {
10,376✔
94
      return m_kdf->derive_key(key_len, z, salt.data(), salt.size());
106✔
95
   }
96
   return z;
10,323✔
97
}
10,376✔
98

99
namespace {
100

101
std::unique_ptr<HashFunction> create_signature_hash(std::string_view padding) {
15,537✔
102
   if(auto hash = HashFunction::create(padding)) {
15,537✔
103
      return hash;
11,158✔
104
   }
11,158✔
105

106
   SCAN_Name req(padding);
4,379✔
107

108
   if(req.algo_name() == "EMSA1" && req.arg_count() == 1) {
4,379✔
109
      if(auto hash = HashFunction::create(req.arg(0))) {
×
110
         return hash;
×
111
      }
×
112
   }
113

114
#if defined(BOTAN_HAS_RAW_HASH_FN)
115
   if(req.algo_name() == "Raw") {
4,379✔
116
      if(req.arg_count() == 0) {
129✔
117
         return std::make_unique<RawHashFunction>("Raw", 0);
114✔
118
      }
119

120
      if(req.arg_count() == 1) {
15✔
121
         if(auto hash = HashFunction::create(req.arg(0))) {
30✔
122
            return std::make_unique<RawHashFunction>(std::move(hash));
15✔
123
         }
15✔
124
      }
125
   }
126
#endif
127

128
   throw Algorithm_Not_Found(padding);
4,250✔
129
}
4,379✔
130

131
}  // namespace
132

133
PK_Ops::Signature_with_Hash::Signature_with_Hash(std::string_view hash) :
2,349✔
134
      Signature(), m_hash(create_signature_hash(hash)) {}
2,349✔
135

136
PK_Ops::Signature_with_Hash::~Signature_with_Hash() = default;
2,349✔
137

138
#if defined(BOTAN_HAS_RFC6979_GENERATOR)
139
std::string PK_Ops::Signature_with_Hash::rfc6979_hash_function() const {
2,260✔
140
   std::string hash = m_hash->name();
2,260✔
141
   if(hash != "Raw") {
2,260✔
142
      return hash;
2,248✔
143
   }
144
   return "SHA-512";
12✔
145
}
2,260✔
146
#endif
147

148
std::string PK_Ops::Signature_with_Hash::hash_function() const {
3,822✔
149
   return m_hash->name();
3,822✔
150
}
151

152
void PK_Ops::Signature_with_Hash::update(std::span<const uint8_t> msg) {
6,165✔
153
   m_hash->update(msg);
6,165✔
154
}
6,165✔
155

156
std::vector<uint8_t> PK_Ops::Signature_with_Hash::sign(RandomNumberGenerator& rng) {
6,160✔
157
   const std::vector<uint8_t> msg = m_hash->final_stdvec();
6,160✔
158
   return raw_sign(msg, rng);
6,160✔
159
}
6,160✔
160

161
PK_Ops::Verification_with_Hash::Verification_with_Hash(std::string_view padding) :
13,188✔
162
      Verification(), m_hash(create_signature_hash(padding)) {}
13,188✔
163

164
PK_Ops::Verification_with_Hash::~Verification_with_Hash() = default;
13,464✔
165

166
std::string PK_Ops::Verification_with_Hash::hash_function() const {
4,446✔
167
   return m_hash->name();
4,446✔
168
}
169

170
PK_Ops::Verification_with_Hash::Verification_with_Hash(const AlgorithmIdentifier& alg_id,
4,567✔
171
                                                       std::string_view pk_algo,
172
                                                       bool allow_null_parameters) {
4,567✔
173
   const auto oid_info = split_on(alg_id.oid().to_formatted_string(), '/');
4,567✔
174

175
   if(oid_info.size() != 2 || oid_info[0] != pk_algo) {
4,567✔
176
      throw Decoding_Error(
×
177
         fmt("Unexpected AlgorithmIdentifier OID {} in association with {} key", alg_id.oid(), pk_algo));
×
178
   }
179

180
   if(!alg_id.parameters_are_empty()) {
4,567✔
181
      if(alg_id.parameters_are_null()) {
44✔
182
         if(!allow_null_parameters) {
44✔
183
            throw Decoding_Error(fmt("Unexpected NULL AlgorithmIdentifier parameters for {}", pk_algo));
82✔
184
         }
185
      } else {
186
         throw Decoding_Error(fmt("Unexpected AlgorithmIdentifier parameters for {}", pk_algo));
×
187
      }
188
   }
189

190
   m_hash = HashFunction::create_or_throw(oid_info[1]);
4,526✔
191
}
4,608✔
192

193
void PK_Ops::Verification_with_Hash::update(std::span<const uint8_t> msg) {
36,473✔
194
   m_hash->update(msg);
36,473✔
195
}
36,473✔
196

197
bool PK_Ops::Verification_with_Hash::is_valid_signature(std::span<const uint8_t> sig) {
36,259✔
198
   const std::vector<uint8_t> msg = m_hash->final_stdvec();
36,259✔
199
   return verify(msg, sig);
36,259✔
200
}
36,259✔
201

202
size_t PK_Ops::KEM_Encryption_with_KDF::shared_key_length(size_t desired_shared_key_len) const {
6,962✔
203
   if(m_kdf) {
6,962✔
204
      return desired_shared_key_len;
205
   } else {
206
      return this->raw_kem_shared_key_length();
1,744✔
207
   }
208
}
209

210
void PK_Ops::KEM_Encryption_with_KDF::kem_encrypt(std::span<uint8_t> out_encapsulated_key,
3,361✔
211
                                                  std::span<uint8_t> out_shared_key,
212
                                                  RandomNumberGenerator& rng,
213
                                                  size_t desired_shared_key_len,
214
                                                  std::span<const uint8_t> salt) {
215
   BOTAN_ARG_CHECK(salt.empty() || m_kdf, "PK_KEM_Encryptor::encrypt requires a KDF to use a salt");
3,361✔
216
   BOTAN_ASSERT_NOMSG(out_encapsulated_key.size() == encapsulated_key_length());
3,361✔
217

218
   if(m_kdf) {
3,361✔
219
      BOTAN_ASSERT_EQUAL(
2,603✔
220
         out_shared_key.size(), desired_shared_key_len, "KDF output length and shared key length match");
221

222
      secure_vector<uint8_t> raw_shared(raw_kem_shared_key_length());
2,603✔
223
      this->raw_kem_encrypt(out_encapsulated_key, raw_shared, rng);
2,603✔
224
      m_kdf->derive_key(out_shared_key, raw_shared, salt, {});
5,206✔
225
   } else {
2,603✔
226
      BOTAN_ASSERT_EQUAL(out_shared_key.size(), raw_kem_shared_key_length(), "Shared key has raw KEM output length");
758✔
227
      this->raw_kem_encrypt(out_encapsulated_key, out_shared_key, rng);
758✔
228
   }
229
}
3,359✔
230

231
PK_Ops::KEM_Encryption_with_KDF::KEM_Encryption_with_KDF(std::string_view kdf) {
844✔
232
   if(kdf != "Raw") {
1,579✔
233
      m_kdf = KDF::create_or_throw(kdf);
109✔
234
   }
235
}
844✔
236

237
PK_Ops::KEM_Encryption_with_KDF::~KEM_Encryption_with_KDF() = default;
844✔
238

239
size_t PK_Ops::KEM_Decryption_with_KDF::shared_key_length(size_t desired_shared_key_len) const {
7,112✔
240
   if(m_kdf) {
7,112✔
241
      return desired_shared_key_len;
242
   } else {
243
      return this->raw_kem_shared_key_length();
1,894✔
244
   }
245
}
246

247
void PK_Ops::KEM_Decryption_with_KDF::kem_decrypt(std::span<uint8_t> out_shared_key,
3,430✔
248
                                                  std::span<const uint8_t> encapsulated_key,
249
                                                  size_t desired_shared_key_len,
250
                                                  std::span<const uint8_t> salt) {
251
   BOTAN_ARG_CHECK(salt.empty() || m_kdf, "PK_KEM_Decryptor::decrypt requires a KDF to use a salt");
3,430✔
252

253
   if(m_kdf) {
3,430✔
254
      BOTAN_ASSERT_EQUAL(
5,206✔
255
         out_shared_key.size(), desired_shared_key_len, "KDF output length and shared key length match");
256

257
      secure_vector<uint8_t> raw_shared(raw_kem_shared_key_length());
2,603✔
258
      this->raw_kem_decrypt(raw_shared, encapsulated_key);
2,603✔
259
      m_kdf->derive_key(out_shared_key, raw_shared, salt, {});
5,206✔
260
   } else {
2,603✔
261
      BOTAN_ASSERT_EQUAL(out_shared_key.size(), raw_kem_shared_key_length(), "Shared key has raw KEM output length");
827✔
262
      this->raw_kem_decrypt(out_shared_key, encapsulated_key);
827✔
263
   }
264
}
3,408✔
265

266
PK_Ops::KEM_Decryption_with_KDF::KEM_Decryption_with_KDF(std::string_view kdf) {
782✔
267
   if(kdf != "Raw") {
1,455✔
268
      m_kdf = KDF::create_or_throw(kdf);
109✔
269
   }
270
}
782✔
271

272
PK_Ops::KEM_Decryption_with_KDF::~KEM_Decryption_with_KDF() = default;
782✔
273

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