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

randombit / botan / 5111374265

29 May 2023 11:19AM UTC coverage: 92.227% (+0.5%) from 91.723%
5111374265

push

github

randombit
Next release will be 3.1.0. Update release notes

75588 of 81959 relevant lines covered (92.23%)

11886470.91 hits per line

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

92.66
/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/hash.h>
11
#include <botan/rng.h>
12
#include <botan/internal/bit_ops.h>
13
#include <botan/internal/fmt.h>
14
#include <botan/internal/parsing.h>
15
#include <botan/internal/scan_name.h>
16
#include <sstream>
17

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

22
namespace Botan {
23

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

28
PK_Ops::Encryption_with_EME::Encryption_with_EME(std::string_view eme) : m_eme(EME::create(eme)) {}
198✔
29

30
size_t PK_Ops::Encryption_with_EME::max_input_bits() const {
139✔
31
   return 8 * m_eme->maximum_input_size(max_ptext_input_bits());
139✔
32
}
33

34
secure_vector<uint8_t> PK_Ops::Encryption_with_EME::encrypt(const uint8_t msg[],
266✔
35
                                                            size_t msg_len,
36
                                                            RandomNumberGenerator& rng) {
37
   const size_t max_raw = max_ptext_input_bits();
266✔
38
   const auto encoded = m_eme->encode(msg, msg_len, max_raw, rng);
266✔
39
   return raw_encrypt(encoded.data(), encoded.size(), rng);
266✔
40
}
266✔
41

42
PK_Ops::Decryption_with_EME::Decryption_with_EME(std::string_view eme) : m_eme(EME::create(eme)) {}
246✔
43

44
secure_vector<uint8_t> PK_Ops::Decryption_with_EME::decrypt(uint8_t& valid_mask,
3,842✔
45
                                                            const uint8_t ciphertext[],
46
                                                            size_t ciphertext_len) {
47
   const secure_vector<uint8_t> raw = raw_decrypt(ciphertext, ciphertext_len);
3,842✔
48
   return m_eme->unpad(valid_mask, raw.data(), raw.size());
3,827✔
49
}
3,827✔
50

51
PK_Ops::Key_Agreement_with_KDF::Key_Agreement_with_KDF(std::string_view kdf) {
2,601✔
52
   if(kdf != "Raw")
5,154✔
53
      m_kdf = KDF::create_or_throw(kdf);
48✔
54
}
2,601✔
55

56
secure_vector<uint8_t> PK_Ops::Key_Agreement_with_KDF::agree(
4,186✔
57
   size_t key_len, const uint8_t w[], size_t w_len, const uint8_t salt[], size_t salt_len) {
58
   if(salt_len > 0 && m_kdf == nullptr)
4,186✔
59
      throw Invalid_Argument("PK_Key_Agreement::derive_key requires a KDF to use a salt");
×
60

61
   secure_vector<uint8_t> z = raw_agree(w, w_len);
4,186✔
62
   if(m_kdf)
4,184✔
63
      return m_kdf->derive_key(key_len, z, salt, salt_len);
56✔
64
   return z;
4,184✔
65
}
4,184✔
66

67
namespace {
68

69
std::unique_ptr<HashFunction> create_signature_hash(std::string_view padding) {
13,386✔
70
   if(auto hash = HashFunction::create(padding))
13,386✔
71
      return hash;
9,075✔
72

73
   SCAN_Name req(padding);
4,311✔
74

75
   if(req.algo_name() == "EMSA1" && req.arg_count() == 1) {
12,933✔
76
      if(auto hash = HashFunction::create(req.arg(0)))
10✔
77
         return hash;
5✔
78
   }
79

80
#if defined(BOTAN_HAS_RAW_HASH_FN)
81
   if(req.algo_name() == "Raw") {
8,612✔
82
      if(req.arg_count() == 0) {
56✔
83
         return std::make_unique<RawHashFunction>("Raw", 0);
41✔
84
      }
85

86
      if(req.arg_count() == 1) {
15✔
87
         if(auto hash = HashFunction::create(req.arg(0)))
30✔
88
            return std::make_unique<RawHashFunction>(std::move(hash));
15✔
89
      }
90
   }
91
#endif
92

93
   throw Algorithm_Not_Found(padding);
4,250✔
94
}
4,311✔
95

96
}  // namespace
97

98
PK_Ops::Signature_with_Hash::Signature_with_Hash(std::string_view hash) :
563✔
99
      Signature(), m_hash(create_signature_hash(hash)) {}
563✔
100

101
#if defined(BOTAN_HAS_RFC6979_GENERATOR)
102
std::string PK_Ops::Signature_with_Hash::rfc6979_hash_function() const {
475✔
103
   std::string hash = m_hash->name();
475✔
104
   if(hash != "Raw")
475✔
105
      return hash;
942✔
106
   return "SHA-512";
8✔
107
}
475✔
108
#endif
109

110
void PK_Ops::Signature_with_Hash::update(const uint8_t msg[], size_t msg_len) { m_hash->update(msg, msg_len); }
855✔
111

112
secure_vector<uint8_t> PK_Ops::Signature_with_Hash::sign(RandomNumberGenerator& rng) {
601✔
113
   const secure_vector<uint8_t> msg = m_hash->final();
601✔
114
   return raw_sign(msg.data(), msg.size(), rng);
601✔
115
}
601✔
116

117
PK_Ops::Verification_with_Hash::Verification_with_Hash(std::string_view padding) :
12,823✔
118
      Verification(), m_hash(create_signature_hash(padding)) {}
12,823✔
119

120
PK_Ops::Verification_with_Hash::Verification_with_Hash(const AlgorithmIdentifier& alg_id,
1,791✔
121
                                                       std::string_view pk_algo,
122
                                                       bool allow_null_parameters) {
1,791✔
123
   const auto oid_info = split_on(alg_id.oid().to_formatted_string(), '/');
1,791✔
124

125
   if(oid_info.size() != 2 || oid_info[0] != pk_algo) {
1,791✔
126
      throw Decoding_Error(
11✔
127
         fmt("Unexpected AlgorithmIdentifier OID {} in association with {} key", alg_id.oid(), pk_algo));
22✔
128
   }
129

130
   if(!alg_id.parameters_are_empty()) {
1,780✔
131
      if(alg_id.parameters_are_null()) {
44✔
132
         if(!allow_null_parameters) {
44✔
133
            throw Decoding_Error(fmt("Unexpected NULL AlgorithmIdentifier parameters for {}", pk_algo));
82✔
134
         }
135
      } else {
136
         throw Decoding_Error(fmt("Unexpected AlgorithmIdentifier parameters for {}", pk_algo));
×
137
      }
138
   }
139

140
   m_hash = HashFunction::create_or_throw(oid_info[1]);
1,739✔
141
}
1,843✔
142

143
void PK_Ops::Verification_with_Hash::update(const uint8_t msg[], size_t msg_len) { m_hash->update(msg, msg_len); }
24,790✔
144

145
bool PK_Ops::Verification_with_Hash::is_valid_signature(const uint8_t sig[], size_t sig_len) {
23,804✔
146
   const secure_vector<uint8_t> msg = m_hash->final();
23,804✔
147
   return verify(msg.data(), msg.size(), sig, sig_len);
23,804✔
148
}
23,804✔
149

150
size_t PK_Ops::KEM_Encryption_with_KDF::shared_key_length(size_t desired_shared_key_len) const {
12✔
151
   if(m_kdf)
12✔
152
      return desired_shared_key_len;
153
   else
154
      return this->raw_kem_shared_key_length();
×
155
}
156

157
void PK_Ops::KEM_Encryption_with_KDF::kem_encrypt(secure_vector<uint8_t>& out_encapsulated_key,
3,198✔
158
                                                  secure_vector<uint8_t>& out_shared_key,
159
                                                  size_t desired_shared_key_len,
160
                                                  RandomNumberGenerator& rng,
161
                                                  const uint8_t salt[],
162
                                                  size_t salt_len) {
163
   if(salt_len > 0 && m_kdf == nullptr)
3,198✔
164
      throw Invalid_Argument("PK_KEM_Encryptor::encrypt requires a KDF to use a salt");
×
165

166
   secure_vector<uint8_t> raw_shared;
3,198✔
167
   this->raw_kem_encrypt(out_encapsulated_key, raw_shared, rng);
3,198✔
168

169
   BOTAN_ASSERT_EQUAL(out_encapsulated_key.size(),
3,198✔
170
                      this->encapsulated_key_length(),
171
                      "KEM produced encapsulated key with different length than expected");
172

173
   BOTAN_ASSERT_EQUAL(raw_shared.size(),
3,198✔
174
                      this->raw_kem_shared_key_length(),
175
                      "KEM produced shared key with different length than expected");
176

177
   out_shared_key = (m_kdf)
3,198✔
178
                       ? m_kdf->derive_key(desired_shared_key_len, raw_shared.data(), raw_shared.size(), salt, salt_len)
6,396✔
179
                       : raw_shared;
6,396✔
180
}
3,198✔
181

182
PK_Ops::KEM_Encryption_with_KDF::KEM_Encryption_with_KDF(std::string_view kdf) {
720✔
183
   if(kdf != "Raw")
1,326✔
184
      m_kdf = KDF::create_or_throw(kdf);
114✔
185
}
720✔
186

187
size_t PK_Ops::KEM_Decryption_with_KDF::shared_key_length(size_t desired_shared_key_len) const {
12✔
188
   if(m_kdf)
12✔
189
      return desired_shared_key_len;
190
   else
191
      return this->raw_kem_shared_key_length();
×
192
}
193

194
secure_vector<uint8_t> PK_Ops::KEM_Decryption_with_KDF::kem_decrypt(
3,216✔
195
   const uint8_t encap_key[], size_t len, size_t desired_shared_key_len, const uint8_t salt[], size_t salt_len) {
196
   if(salt_len > 0 && m_kdf == nullptr)
3,216✔
197
      throw Invalid_Argument("PK_KEM_Decryptor::decrypt requires a KDF to use a salt");
×
198

199
   secure_vector<uint8_t> raw_shared = this->raw_kem_decrypt(encap_key, len);
3,216✔
200

201
   BOTAN_ASSERT_EQUAL(raw_shared.size(),
3,210✔
202
                      this->raw_kem_shared_key_length(),
203
                      "KEM produced shared key with different length than expected");
204

205
   if(m_kdf)
3,210✔
206
      return m_kdf->derive_key(desired_shared_key_len, raw_shared.data(), raw_shared.size(), salt, salt_len);
2,592✔
207
   return raw_shared;
3,210✔
208
}
3,210✔
209

210
PK_Ops::KEM_Decryption_with_KDF::KEM_Decryption_with_KDF(std::string_view kdf) {
720✔
211
   if(kdf != "Raw")
1,326✔
212
      m_kdf = KDF::create_or_throw(kdf);
114✔
213
}
720✔
214

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