Botan 3.6.1
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
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
22namespace Botan {
23
25 throw Not_Implemented("This signature scheme does not have an algorithm identifier available");
26}
27
28PK_Ops::Encryption_with_EME::Encryption_with_EME(std::string_view eme) : m_eme(EME::create(eme)) {}
29
31 return 8 * m_eme->maximum_input_size(max_ptext_input_bits());
32}
33
34std::vector<uint8_t> PK_Ops::Encryption_with_EME::encrypt(std::span<const uint8_t> msg, RandomNumberGenerator& rng) {
35 const size_t max_raw = max_ptext_input_bits();
36 secure_vector<uint8_t> eme_output((max_raw + 7) / 8);
37 size_t written = m_eme->pad(eme_output, msg, max_raw, rng);
38 return raw_encrypt(std::span{eme_output}.first(written), rng);
39}
40
41PK_Ops::Decryption_with_EME::Decryption_with_EME(std::string_view eme) : m_eme(EME::create(eme)) {}
42
43secure_vector<uint8_t> PK_Ops::Decryption_with_EME::decrypt(uint8_t& valid_mask, std::span<const uint8_t> ctext) {
44 const secure_vector<uint8_t> raw = raw_decrypt(ctext);
45
46 secure_vector<uint8_t> ptext(raw.size());
47 auto len = m_eme->unpad(ptext, raw);
48
49 valid_mask = CT::Mask<uint8_t>::from_choice(len.has_value()).if_set_return(0xFF);
50
51 /*
52 This is potentially not const time, depending on how std::vector is
53 implemented. But since we are always reducing length, it should
54 just amount to setting the member var holding the length. Resizing
55 downwards is guaranteed to not change the capacity, and since we
56 set ctext to the maximum possible size (equal to the raw input) we
57 know that this is always, if anything, resizing smaller than the
58 capacity, so no reallocation occurs.
59 */
60
61 ptext.resize(len.value_or(0));
62 return ptext;
63}
64
66 if(kdf != "Raw") {
67 m_kdf = KDF::create_or_throw(kdf);
68 }
69}
70
72 std::span<const uint8_t> other_key,
73 std::span<const uint8_t> salt) {
74 if(!salt.empty() && m_kdf == nullptr) {
75 throw Invalid_Argument("PK_Key_Agreement::derive_key requires a KDF to use a salt");
76 }
77
78 secure_vector<uint8_t> z = raw_agree(other_key.data(), other_key.size());
79 if(m_kdf) {
80 return m_kdf->derive_key(key_len, z, salt.data(), salt.size());
81 }
82 return z;
83}
84
85namespace {
86
87std::unique_ptr<HashFunction> create_signature_hash(std::string_view padding) {
88 if(auto hash = HashFunction::create(padding)) {
89 return hash;
90 }
91
92 SCAN_Name req(padding);
93
94 if(req.algo_name() == "EMSA1" && req.arg_count() == 1) {
95 if(auto hash = HashFunction::create(req.arg(0))) {
96 return hash;
97 }
98 }
99
100#if defined(BOTAN_HAS_RAW_HASH_FN)
101 if(req.algo_name() == "Raw") {
102 if(req.arg_count() == 0) {
103 return std::make_unique<RawHashFunction>("Raw", 0);
104 }
105
106 if(req.arg_count() == 1) {
107 if(auto hash = HashFunction::create(req.arg(0))) {
108 return std::make_unique<RawHashFunction>(std::move(hash));
109 }
110 }
111 }
112#endif
113
114 throw Algorithm_Not_Found(padding);
115}
116
117} // namespace
118
120 Signature(), m_hash(create_signature_hash(hash)) {}
121
122#if defined(BOTAN_HAS_RFC6979_GENERATOR)
123std::string PK_Ops::Signature_with_Hash::rfc6979_hash_function() const {
124 std::string hash = m_hash->name();
125 if(hash != "Raw") {
126 return hash;
127 }
128 return "SHA-512";
129}
130#endif
131
132void PK_Ops::Signature_with_Hash::update(std::span<const uint8_t> msg) {
133 m_hash->update(msg);
134}
135
137 const std::vector<uint8_t> msg = m_hash->final_stdvec();
138 return raw_sign(msg, rng);
139}
140
142 Verification(), m_hash(create_signature_hash(padding)) {}
143
145 std::string_view pk_algo,
146 bool allow_null_parameters) {
147 const auto oid_info = split_on(alg_id.oid().to_formatted_string(), '/');
148
149 if(oid_info.size() != 2 || oid_info[0] != pk_algo) {
150 throw Decoding_Error(
151 fmt("Unexpected AlgorithmIdentifier OID {} in association with {} key", alg_id.oid(), pk_algo));
152 }
153
154 if(!alg_id.parameters_are_empty()) {
155 if(alg_id.parameters_are_null()) {
156 if(!allow_null_parameters) {
157 throw Decoding_Error(fmt("Unexpected NULL AlgorithmIdentifier parameters for {}", pk_algo));
158 }
159 } else {
160 throw Decoding_Error(fmt("Unexpected AlgorithmIdentifier parameters for {}", pk_algo));
161 }
162 }
163
164 m_hash = HashFunction::create_or_throw(oid_info[1]);
165}
166
167void PK_Ops::Verification_with_Hash::update(std::span<const uint8_t> msg) {
168 m_hash->update(msg);
169}
170
171bool PK_Ops::Verification_with_Hash::is_valid_signature(std::span<const uint8_t> sig) {
172 const std::vector<uint8_t> msg = m_hash->final_stdvec();
173 return verify(msg, sig);
174}
175
176size_t PK_Ops::KEM_Encryption_with_KDF::shared_key_length(size_t desired_shared_key_len) const {
177 if(m_kdf) {
178 return desired_shared_key_len;
179 } else {
180 return this->raw_kem_shared_key_length();
181 }
182}
183
184void PK_Ops::KEM_Encryption_with_KDF::kem_encrypt(std::span<uint8_t> out_encapsulated_key,
185 std::span<uint8_t> out_shared_key,
187 size_t desired_shared_key_len,
188 std::span<const uint8_t> salt) {
189 BOTAN_ARG_CHECK(salt.empty() || m_kdf, "PK_KEM_Encryptor::encrypt requires a KDF to use a salt");
190 BOTAN_ASSERT_NOMSG(out_encapsulated_key.size() == encapsulated_key_length());
191
192 if(m_kdf) {
194 out_shared_key.size(), desired_shared_key_len, "KDF output length and shared key length match");
195
196 secure_vector<uint8_t> raw_shared(raw_kem_shared_key_length());
197 this->raw_kem_encrypt(out_encapsulated_key, raw_shared, rng);
198 m_kdf->derive_key(out_shared_key, raw_shared, salt, {});
199 } else {
200 BOTAN_ASSERT_EQUAL(out_shared_key.size(), raw_kem_shared_key_length(), "Shared key has raw KEM output length");
201 this->raw_kem_encrypt(out_encapsulated_key, out_shared_key, rng);
202 }
203}
204
206 if(kdf != "Raw") {
207 m_kdf = KDF::create_or_throw(kdf);
208 }
209}
210
211size_t PK_Ops::KEM_Decryption_with_KDF::shared_key_length(size_t desired_shared_key_len) const {
212 if(m_kdf) {
213 return desired_shared_key_len;
214 } else {
215 return this->raw_kem_shared_key_length();
216 }
217}
218
219void PK_Ops::KEM_Decryption_with_KDF::kem_decrypt(std::span<uint8_t> out_shared_key,
220 std::span<const uint8_t> encapsulated_key,
221 size_t desired_shared_key_len,
222 std::span<const uint8_t> salt) {
223 BOTAN_ARG_CHECK(salt.empty() || m_kdf, "PK_KEM_Decryptor::decrypt requires a KDF to use a salt");
224
225 if(m_kdf) {
227 out_shared_key.size(), desired_shared_key_len, "KDF output length and shared key length match");
228
229 secure_vector<uint8_t> raw_shared(raw_kem_shared_key_length());
230 this->raw_kem_decrypt(raw_shared, encapsulated_key);
231 m_kdf->derive_key(out_shared_key, raw_shared, salt, {});
232 } else {
233 BOTAN_ASSERT_EQUAL(out_shared_key.size(), raw_kem_shared_key_length(), "Shared key has raw KEM output length");
234 this->raw_kem_decrypt(out_shared_key, encapsulated_key);
235 }
236}
237
239 if(kdf != "Raw") {
240 m_kdf = KDF::create_or_throw(kdf);
241 }
242}
243
244} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition assert.h:68
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:29
bool parameters_are_empty() const
Definition asn1_obj.h:476
bool parameters_are_null() const
Definition alg_id.cpp:50
const OID & oid() const
Definition asn1_obj.h:464
static constexpr Mask< T > from_choice(Choice c)
Definition ct_utils.h:394
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:298
static std::unique_ptr< HashFunction > create(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:107
static std::unique_ptr< KDF > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition kdf.cpp:199
std::string to_formatted_string() const
Definition asn1_oid.cpp:139
Decryption_with_EME(std::string_view eme)
Definition pk_ops.cpp:41
secure_vector< uint8_t > decrypt(uint8_t &valid_mask, std::span< const uint8_t > ctext) override
Definition pk_ops.cpp:43
std::vector< uint8_t > encrypt(std::span< const uint8_t > ptext, RandomNumberGenerator &rng) override
Definition pk_ops.cpp:34
size_t max_input_bits() const override
Definition pk_ops.cpp:30
Encryption_with_EME(std::string_view eme)
Definition pk_ops.cpp:28
void kem_decrypt(std::span< uint8_t > out_shared_key, std::span< const uint8_t > encapsulated_key, size_t desired_shared_key_len, std::span< const uint8_t > salt) final
Definition pk_ops.cpp:219
KEM_Decryption_with_KDF(std::string_view kdf)
Definition pk_ops.cpp:238
size_t shared_key_length(size_t desired_shared_key_len) const final
Definition pk_ops.cpp:211
void kem_encrypt(std::span< uint8_t > out_encapsulated_key, std::span< uint8_t > out_shared_key, RandomNumberGenerator &rng, size_t desired_shared_key_len, std::span< const uint8_t > salt) final
Definition pk_ops.cpp:184
size_t shared_key_length(size_t desired_shared_key_len) const final
Definition pk_ops.cpp:176
KEM_Encryption_with_KDF(std::string_view kdf)
Definition pk_ops.cpp:205
Key_Agreement_with_KDF(std::string_view kdf)
Definition pk_ops.cpp:65
secure_vector< uint8_t > agree(size_t key_len, std::span< const uint8_t > other_key, std::span< const uint8_t > salt) override
Definition pk_ops.cpp:71
std::vector< uint8_t > sign(RandomNumberGenerator &rng) override
Definition pk_ops.cpp:136
void update(std::span< const uint8_t > input) override
Definition pk_ops.cpp:132
Signature_with_Hash(std::string_view hash)
Definition pk_ops.cpp:119
virtual AlgorithmIdentifier algorithm_identifier() const
Definition pk_ops.cpp:24
void update(std::span< const uint8_t > input) override
Definition pk_ops.cpp:167
Verification_with_Hash(std::string_view hash)
Definition pk_ops.cpp:141
bool is_valid_signature(std::span< const uint8_t > sig) override
Definition pk_ops.cpp:171
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
std::vector< std::string > split_on(std::string_view str, char delim)
Definition parsing.cpp:111
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61