Botan 3.0.0
Crypto and TLS for C&
pk_ops.cpp
Go to the documentation of this file.
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#include <botan/internal/bit_ops.h>
10#include <botan/internal/scan_name.h>
11#include <botan/internal/parsing.h>
12#include <botan/internal/fmt.h>
13#include <botan/hash.h>
14#include <botan/rng.h>
15#include <sstream>
16
17#if defined(BOTAN_HAS_RAW_HASH_FN)
18 #include <botan/internal/raw_hash.h>
19#endif
20
21namespace Botan {
22
24 {
25 throw Not_Implemented("This signature scheme does not have an algorithm identifier available");
26 }
27
29 m_eme(EME::create(eme))
30 {
31 }
32
34 {
35 return 8 * m_eme->maximum_input_size(max_ptext_input_bits());
36 }
37
40 {
41 const size_t max_raw = max_ptext_input_bits();
42 const auto encoded = m_eme->encode(msg, msg_len, max_raw, rng);
43 return raw_encrypt(encoded.data(), encoded.size(), rng);
44 }
45
47 m_eme(EME::create(eme))
48 {
49 }
50
53 const uint8_t ciphertext[],
54 size_t ciphertext_len)
55 {
56 const secure_vector<uint8_t> raw = raw_decrypt(ciphertext, ciphertext_len);
57 return m_eme->unpad(valid_mask, raw.data(), raw.size());
58 }
59
61 {
62 if(kdf != "Raw")
63 m_kdf = KDF::create_or_throw(kdf);
64 }
65
67 const uint8_t w[], size_t w_len,
68 const uint8_t salt[], size_t salt_len)
69 {
70 if(salt_len > 0 && m_kdf == nullptr)
71 throw Invalid_Argument("PK_Key_Agreement::derive_key requires a KDF to use a salt");
72
73 secure_vector<uint8_t> z = raw_agree(w, w_len);
74 if(m_kdf)
75 return m_kdf->derive_key(key_len, z, salt, salt_len);
76 return z;
77 }
78
79namespace {
80
81std::unique_ptr<HashFunction> create_signature_hash(std::string_view padding)
82 {
83 if(auto hash = HashFunction::create(padding))
84 return hash;
85
86 SCAN_Name req(padding);
87
88 if(req.algo_name() == "EMSA1" && req.arg_count() == 1)
89 {
90 if(auto hash = HashFunction::create(req.arg(0)))
91 return hash;
92 }
93
94#if defined(BOTAN_HAS_RAW_HASH_FN)
95 if(req.algo_name() == "Raw")
96 {
97 if(req.arg_count() == 0)
98 {
99 return std::make_unique<RawHashFunction>("Raw", 0);
100 }
101
102 if(req.arg_count() == 1)
103 {
104 if(auto hash = HashFunction::create(req.arg(0)))
105 return std::make_unique<RawHashFunction>(std::move(hash));
106 }
107 }
108#endif
109
110 throw Algorithm_Not_Found(padding);
111 }
112
113}
114
116 Signature(),
117 m_hash(create_signature_hash(hash))
118 {
119 }
120
121#if defined(BOTAN_HAS_RFC6979_GENERATOR)
122std::string PK_Ops::Signature_with_Hash::rfc6979_hash_function() const
123 {
124 std::string hash = m_hash->name();
125 if(hash != "Raw")
126 return hash;
127 return "SHA-512";
128 }
129#endif
130
131void PK_Ops::Signature_with_Hash::update(const uint8_t msg[], size_t msg_len)
132 {
133 m_hash->update(msg, msg_len);
134 }
135
137 {
138 const secure_vector<uint8_t> msg = m_hash->final();
139 return raw_sign(msg.data(), msg.size(), rng);
140 }
141
143 Verification(),
144 m_hash(create_signature_hash(padding))
145 {
146 }
147
149 std::string_view pk_algo,
150 bool allow_null_parameters)
151 {
152 const auto oid_info = split_on(alg_id.oid().to_formatted_string(), '/');
153
154 if(oid_info.size() != 2 || oid_info[0] != pk_algo)
155 {
156 throw Decoding_Error(
157 fmt("Unexpected AlgorithmIdentifier OID {} in association with {} key",
158 alg_id.oid(), pk_algo));
159 }
160
161 if(!alg_id.parameters_are_empty())
162 {
163 if(alg_id.parameters_are_null())
164 {
165 if(!allow_null_parameters)
166 {
167 throw Decoding_Error(fmt("Unexpected NULL AlgorithmIdentifier parameters for {}", pk_algo));
168 }
169 }
170 else
171 {
172 throw Decoding_Error(fmt("Unexpected AlgorithmIdentifier parameters for {}", pk_algo));
173 }
174 }
175
176 m_hash = HashFunction::create_or_throw(oid_info[1]);
177 }
178
179void PK_Ops::Verification_with_Hash::update(const uint8_t msg[], size_t msg_len)
180 {
181 m_hash->update(msg, msg_len);
182 }
183
184bool PK_Ops::Verification_with_Hash::is_valid_signature(const uint8_t sig[], size_t sig_len)
185 {
186 const secure_vector<uint8_t> msg = m_hash->final();
187 return verify(msg.data(), msg.size(), sig, sig_len);
188 }
189
190size_t PK_Ops::KEM_Encryption_with_KDF::shared_key_length(size_t desired_shared_key_len) const
191 {
192 if(m_kdf)
193 return desired_shared_key_len;
194 else
195 return this->raw_kem_shared_key_length();
196 }
197
199 secure_vector<uint8_t>& out_shared_key,
200 size_t desired_shared_key_len,
202 const uint8_t salt[],
203 size_t salt_len)
204 {
205 if(salt_len > 0 && m_kdf == nullptr)
206 throw Invalid_Argument("PK_KEM_Encryptor::encrypt requires a KDF to use a salt");
207
208 secure_vector<uint8_t> raw_shared;
209 this->raw_kem_encrypt(out_encapsulated_key, raw_shared, rng);
210
211 BOTAN_ASSERT_EQUAL(out_encapsulated_key.size(), this->encapsulated_key_length(),
212 "KEM produced encapsulated key with different length than expected");
213
214 BOTAN_ASSERT_EQUAL(raw_shared.size(), this->raw_kem_shared_key_length(),
215 "KEM produced shared key with different length than expected");
216
217 out_shared_key = (m_kdf)
218 ? m_kdf->derive_key(desired_shared_key_len,
219 raw_shared.data(), raw_shared.size(),
220 salt, salt_len)
221 : raw_shared;
222 }
223
225 {
226 if(kdf != "Raw")
227 m_kdf = KDF::create_or_throw(kdf);
228 }
229
230size_t PK_Ops::KEM_Decryption_with_KDF::shared_key_length(size_t desired_shared_key_len) const
231 {
232 if(m_kdf)
233 return desired_shared_key_len;
234 else
235 return this->raw_kem_shared_key_length();
236 }
237
240 size_t len,
241 size_t desired_shared_key_len,
242 const uint8_t salt[],
243 size_t salt_len)
244 {
245 if(salt_len > 0 && m_kdf == nullptr)
246 throw Invalid_Argument("PK_KEM_Decryptor::decrypt requires a KDF to use a salt");
247
248 secure_vector<uint8_t> raw_shared = this->raw_kem_decrypt(encap_key, len);
249
250 BOTAN_ASSERT_EQUAL(raw_shared.size(), this->raw_kem_shared_key_length(),
251 "KEM produced shared key with different length than expected");
252
253 if(m_kdf)
254 return m_kdf->derive_key(desired_shared_key_len,
255 raw_shared.data(), raw_shared.size(),
256 salt, salt_len);
257 return raw_shared;
258 }
259
261 {
262 if(kdf != "Raw")
263 m_kdf = KDF::create_or_throw(kdf);
264 }
265
266}
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition: assert.h:80
bool parameters_are_empty() const
Definition: asn1_obj.h:487
bool parameters_are_null() const
Definition: alg_id.cpp:59
const OID & oid() const
Definition: asn1_obj.h:477
Definition: eme.h:22
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition: hash.cpp:320
static std::unique_ptr< HashFunction > create(std::string_view algo_spec, std::string_view provider="")
Definition: hash.cpp:102
static std::unique_ptr< KDF > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition: kdf.cpp:213
std::string to_formatted_string() const
Definition: asn1_oid.cpp:120
secure_vector< uint8_t > decrypt(uint8_t &valid_mask, const uint8_t msg[], size_t msg_len) override
Definition: pk_ops.cpp:52
Decryption_with_EME(std::string_view eme)
Definition: pk_ops.cpp:46
size_t max_input_bits() const override
Definition: pk_ops.cpp:33
secure_vector< uint8_t > encrypt(const uint8_t msg[], size_t msg_len, RandomNumberGenerator &rng) override
Definition: pk_ops.cpp:38
Encryption_with_EME(std::string_view eme)
Definition: pk_ops.cpp:28
size_t shared_key_length(size_t desired_shared_key_len) const override final
Definition: pk_ops.cpp:230
secure_vector< uint8_t > kem_decrypt(const uint8_t encap_key[], size_t len, size_t desired_shared_key_len, const uint8_t salt[], size_t salt_len) override final
Definition: pk_ops.cpp:239
KEM_Decryption_with_KDF(std::string_view kdf)
Definition: pk_ops.cpp:260
size_t shared_key_length(size_t desired_shared_key_len) const override final
Definition: pk_ops.cpp:190
void kem_encrypt(secure_vector< uint8_t > &out_encapsulated_key, secure_vector< uint8_t > &out_shared_key, size_t desired_shared_key_len, RandomNumberGenerator &rng, const uint8_t salt[], size_t salt_len) override final
Definition: pk_ops.cpp:198
KEM_Encryption_with_KDF(std::string_view kdf)
Definition: pk_ops.cpp:224
Key_Agreement_with_KDF(std::string_view kdf)
Definition: pk_ops.cpp:60
secure_vector< uint8_t > agree(size_t key_len, const uint8_t other_key[], size_t other_key_len, const uint8_t salt[], size_t salt_len) override
Definition: pk_ops.cpp:66
secure_vector< uint8_t > sign(RandomNumberGenerator &rng) override
Definition: pk_ops.cpp:136
Signature_with_Hash(std::string_view hash)
Definition: pk_ops.cpp:115
void update(const uint8_t msg[], size_t msg_len) override
Definition: pk_ops.cpp:131
virtual AlgorithmIdentifier algorithm_identifier() const
Definition: pk_ops.cpp:23
void update(const uint8_t msg[], size_t msg_len) override
Definition: pk_ops.cpp:179
Verification_with_Hash(std::string_view hash)
Definition: pk_ops.cpp:142
bool is_valid_signature(const uint8_t sig[], size_t sig_len) override
Definition: pk_ops.cpp:184
Definition: alg_id.cpp:12
std::string fmt(std::string_view format, const T &... args)
Definition: fmt.h:60
std::vector< std::string > split_on(std::string_view str, char delim)
Definition: parsing.cpp:117
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:64