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

randombit / botan / 11087146043

28 Sep 2024 09:28PM UTC coverage: 92.003% (+0.7%) from 91.274%
11087146043

push

github

web-flow
Create terraform.yml

82959 of 90170 relevant lines covered (92.0%)

9376319.11 hits per line

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

96.64
/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)) {}
247✔
43

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

51
PK_Ops::Key_Agreement_with_KDF::Key_Agreement_with_KDF(std::string_view kdf) {
3,164✔
52
   if(kdf != "Raw") {
6,282✔
53
      m_kdf = KDF::create_or_throw(kdf);
46✔
54
   }
55
}
3,164✔
56

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

63
   secure_vector<uint8_t> z = raw_agree(w, w_len);
4,746✔
64
   if(m_kdf) {
4,744✔
65
      return m_kdf->derive_key(key_len, z, salt, salt_len);
56✔
66
   }
67
   return z;
4,744✔
68
}
4,744✔
69

70
namespace {
71

72
std::unique_ptr<HashFunction> create_signature_hash(std::string_view padding) {
13,396✔
73
   if(auto hash = HashFunction::create(padding)) {
13,396✔
74
      return hash;
9,083✔
75
   }
9,083✔
76

77
   SCAN_Name req(padding);
4,313✔
78

79
   if(req.algo_name() == "EMSA1" && req.arg_count() == 1) {
4,313✔
80
      if(auto hash = HashFunction::create(req.arg(0))) {
10✔
81
         return hash;
5✔
82
      }
5✔
83
   }
84

85
#if defined(BOTAN_HAS_RAW_HASH_FN)
86
   if(req.algo_name() == "Raw") {
4,308✔
87
      if(req.arg_count() == 0) {
58✔
88
         return std::make_unique<RawHashFunction>("Raw", 0);
43✔
89
      }
90

91
      if(req.arg_count() == 1) {
15✔
92
         if(auto hash = HashFunction::create(req.arg(0))) {
30✔
93
            return std::make_unique<RawHashFunction>(std::move(hash));
15✔
94
         }
15✔
95
      }
96
   }
97
#endif
98

99
   throw Algorithm_Not_Found(padding);
4,250✔
100
}
4,313✔
101

102
}  // namespace
103

104
PK_Ops::Signature_with_Hash::Signature_with_Hash(std::string_view hash) :
567✔
105
      Signature(), m_hash(create_signature_hash(hash)) {}
567✔
106

107
#if defined(BOTAN_HAS_RFC6979_GENERATOR)
108
std::string PK_Ops::Signature_with_Hash::rfc6979_hash_function() const {
478✔
109
   std::string hash = m_hash->name();
478✔
110
   if(hash != "Raw") {
478✔
111
      return hash;
948✔
112
   }
113
   return "SHA-512";
8✔
114
}
478✔
115
#endif
116

117
void PK_Ops::Signature_with_Hash::update(const uint8_t msg[], size_t msg_len) {
872✔
118
   m_hash->update(msg, msg_len);
872✔
119
}
872✔
120

121
secure_vector<uint8_t> PK_Ops::Signature_with_Hash::sign(RandomNumberGenerator& rng) {
618✔
122
   const secure_vector<uint8_t> msg = m_hash->final();
618✔
123
   return raw_sign(msg.data(), msg.size(), rng);
618✔
124
}
618✔
125

126
PK_Ops::Verification_with_Hash::Verification_with_Hash(std::string_view padding) :
12,829✔
127
      Verification(), m_hash(create_signature_hash(padding)) {}
12,829✔
128

129
PK_Ops::Verification_with_Hash::Verification_with_Hash(const AlgorithmIdentifier& alg_id,
2,551✔
130
                                                       std::string_view pk_algo,
131
                                                       bool allow_null_parameters) {
2,551✔
132
   const auto oid_info = split_on(alg_id.oid().to_formatted_string(), '/');
2,551✔
133

134
   if(oid_info.size() != 2 || oid_info[0] != pk_algo) {
2,551✔
135
      throw Decoding_Error(
11✔
136
         fmt("Unexpected AlgorithmIdentifier OID {} in association with {} key", alg_id.oid(), pk_algo));
22✔
137
   }
138

139
   if(!alg_id.parameters_are_empty()) {
2,540✔
140
      if(alg_id.parameters_are_null()) {
44✔
141
         if(!allow_null_parameters) {
44✔
142
            throw Decoding_Error(fmt("Unexpected NULL AlgorithmIdentifier parameters for {}", pk_algo));
82✔
143
         }
144
      } else {
145
         throw Decoding_Error(fmt("Unexpected AlgorithmIdentifier parameters for {}", pk_algo));
×
146
      }
147
   }
148

149
   m_hash = HashFunction::create_or_throw(oid_info[1]);
2,499✔
150
}
2,603✔
151

152
void PK_Ops::Verification_with_Hash::update(const uint8_t msg[], size_t msg_len) {
25,558✔
153
   m_hash->update(msg, msg_len);
25,558✔
154
}
25,558✔
155

156
bool PK_Ops::Verification_with_Hash::is_valid_signature(const uint8_t sig[], size_t sig_len) {
24,570✔
157
   const secure_vector<uint8_t> msg = m_hash->final();
24,570✔
158
   return verify(msg.data(), msg.size(), sig, sig_len);
24,570✔
159
}
24,570✔
160

161
size_t PK_Ops::KEM_Encryption_with_KDF::shared_key_length(size_t desired_shared_key_len) const {
6,231✔
162
   if(m_kdf) {
6,231✔
163
      return desired_shared_key_len;
164
   } else {
165
      return this->raw_kem_shared_key_length();
1,015✔
166
   }
167
}
168

169
void PK_Ops::KEM_Encryption_with_KDF::kem_encrypt(std::span<uint8_t> out_encapsulated_key,
3,092✔
170
                                                  std::span<uint8_t> out_shared_key,
171
                                                  RandomNumberGenerator& rng,
172
                                                  size_t desired_shared_key_len,
173
                                                  std::span<const uint8_t> salt) {
174
   BOTAN_ARG_CHECK(salt.empty() || m_kdf, "PK_KEM_Encryptor::encrypt requires a KDF to use a salt");
3,092✔
175
   BOTAN_ASSERT_NOMSG(out_encapsulated_key.size() == encapsulated_key_length());
3,092✔
176

177
   if(m_kdf) {
3,092✔
178
      BOTAN_ASSERT_EQUAL(
2,602✔
179
         out_shared_key.size(), desired_shared_key_len, "KDF output length and shared key length match");
180

181
      secure_vector<uint8_t> raw_shared(raw_kem_shared_key_length());
2,602✔
182
      this->raw_kem_encrypt(out_encapsulated_key, raw_shared, rng);
2,602✔
183
      m_kdf->derive_key(out_shared_key, raw_shared, salt, {});
5,204✔
184
   } else {
2,602✔
185
      BOTAN_ASSERT_EQUAL(out_shared_key.size(), raw_kem_shared_key_length(), "Shared key has raw KEM output length");
490✔
186
      this->raw_kem_encrypt(out_encapsulated_key, out_shared_key, rng);
490✔
187
   }
188
}
3,092✔
189

190
PK_Ops::KEM_Encryption_with_KDF::KEM_Encryption_with_KDF(std::string_view kdf) {
612✔
191
   if(kdf != "Raw") {
1,110✔
192
      m_kdf = KDF::create_or_throw(kdf);
114✔
193
   }
194
}
612✔
195

196
size_t PK_Ops::KEM_Decryption_with_KDF::shared_key_length(size_t desired_shared_key_len) const {
6,343✔
197
   if(m_kdf) {
6,343✔
198
      return desired_shared_key_len;
199
   } else {
200
      return this->raw_kem_shared_key_length();
1,127✔
201
   }
202
}
203

204
void PK_Ops::KEM_Decryption_with_KDF::kem_decrypt(std::span<uint8_t> out_shared_key,
3,149✔
205
                                                  std::span<const uint8_t> encapsulated_key,
206
                                                  size_t desired_shared_key_len,
207
                                                  std::span<const uint8_t> salt) {
208
   BOTAN_ARG_CHECK(salt.empty() || m_kdf, "PK_KEM_Decryptor::decrypt requires a KDF to use a salt");
3,149✔
209

210
   if(m_kdf) {
3,149✔
211
      BOTAN_ASSERT_EQUAL(
2,602✔
212
         out_shared_key.size(), desired_shared_key_len, "KDF output length and shared key length match");
213

214
      secure_vector<uint8_t> raw_shared(raw_kem_shared_key_length());
2,602✔
215
      this->raw_kem_decrypt(raw_shared, encapsulated_key);
2,602✔
216
      m_kdf->derive_key(out_shared_key, raw_shared, salt, {});
5,204✔
217
   } else {
2,602✔
218
      BOTAN_ASSERT_EQUAL(out_shared_key.size(), raw_kem_shared_key_length(), "Shared key has raw KEM output length");
547✔
219
      this->raw_kem_decrypt(out_shared_key, encapsulated_key);
547✔
220
   }
221
}
3,131✔
222

223
PK_Ops::KEM_Decryption_with_KDF::KEM_Decryption_with_KDF(std::string_view kdf) {
619✔
224
   if(kdf != "Raw") {
1,124✔
225
      m_kdf = KDF::create_or_throw(kdf);
114✔
226
   }
227
}
619✔
228

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