Botan 3.4.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
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
35 size_t msg_len,
37 const size_t max_raw = max_ptext_input_bits();
38 const auto encoded = m_eme->encode(msg, msg_len, max_raw, rng);
39 return raw_encrypt(encoded.data(), encoded.size(), rng);
40}
41
42PK_Ops::Decryption_with_EME::Decryption_with_EME(std::string_view eme) : m_eme(EME::create(eme)) {}
43
45 const uint8_t ciphertext[],
46 size_t ciphertext_len) {
47 const secure_vector<uint8_t> raw = raw_decrypt(ciphertext, ciphertext_len);
48 return m_eme->unpad(valid_mask, raw.data(), raw.size());
49}
50
52 if(kdf != "Raw") {
53 m_kdf = KDF::create_or_throw(kdf);
54 }
55}
56
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) {
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);
64 if(m_kdf) {
65 return m_kdf->derive_key(key_len, z, salt, salt_len);
66 }
67 return z;
68}
69
70namespace {
71
72std::unique_ptr<HashFunction> create_signature_hash(std::string_view padding) {
73 if(auto hash = HashFunction::create(padding)) {
74 return hash;
75 }
76
77 SCAN_Name req(padding);
78
79 if(req.algo_name() == "EMSA1" && req.arg_count() == 1) {
80 if(auto hash = HashFunction::create(req.arg(0))) {
81 return hash;
82 }
83 }
84
85#if defined(BOTAN_HAS_RAW_HASH_FN)
86 if(req.algo_name() == "Raw") {
87 if(req.arg_count() == 0) {
88 return std::make_unique<RawHashFunction>("Raw", 0);
89 }
90
91 if(req.arg_count() == 1) {
92 if(auto hash = HashFunction::create(req.arg(0))) {
93 return std::make_unique<RawHashFunction>(std::move(hash));
94 }
95 }
96 }
97#endif
98
99 throw Algorithm_Not_Found(padding);
100}
101
102} // namespace
103
105 Signature(), m_hash(create_signature_hash(hash)) {}
106
107#if defined(BOTAN_HAS_RFC6979_GENERATOR)
108std::string PK_Ops::Signature_with_Hash::rfc6979_hash_function() const {
109 std::string hash = m_hash->name();
110 if(hash != "Raw") {
111 return hash;
112 }
113 return "SHA-512";
114}
115#endif
116
117void PK_Ops::Signature_with_Hash::update(const uint8_t msg[], size_t msg_len) {
118 m_hash->update(msg, msg_len);
119}
120
122 const secure_vector<uint8_t> msg = m_hash->final();
123 return raw_sign(msg.data(), msg.size(), rng);
124}
125
127 Verification(), m_hash(create_signature_hash(padding)) {}
128
130 std::string_view pk_algo,
131 bool allow_null_parameters) {
132 const auto oid_info = split_on(alg_id.oid().to_formatted_string(), '/');
133
134 if(oid_info.size() != 2 || oid_info[0] != pk_algo) {
135 throw Decoding_Error(
136 fmt("Unexpected AlgorithmIdentifier OID {} in association with {} key", alg_id.oid(), pk_algo));
137 }
138
139 if(!alg_id.parameters_are_empty()) {
140 if(alg_id.parameters_are_null()) {
141 if(!allow_null_parameters) {
142 throw Decoding_Error(fmt("Unexpected NULL AlgorithmIdentifier parameters for {}", pk_algo));
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]);
150}
151
152void PK_Ops::Verification_with_Hash::update(const uint8_t msg[], size_t msg_len) {
153 m_hash->update(msg, msg_len);
154}
155
156bool PK_Ops::Verification_with_Hash::is_valid_signature(const uint8_t sig[], size_t sig_len) {
157 const secure_vector<uint8_t> msg = m_hash->final();
158 return verify(msg.data(), msg.size(), sig, sig_len);
159}
160
161size_t PK_Ops::KEM_Encryption_with_KDF::shared_key_length(size_t desired_shared_key_len) const {
162 if(m_kdf) {
163 return desired_shared_key_len;
164 } else {
165 return this->raw_kem_shared_key_length();
166 }
167}
168
169void PK_Ops::KEM_Encryption_with_KDF::kem_encrypt(std::span<uint8_t> out_encapsulated_key,
170 std::span<uint8_t> out_shared_key,
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");
175 BOTAN_ASSERT_NOMSG(out_encapsulated_key.size() == encapsulated_key_length());
176
177 if(m_kdf) {
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());
182 this->raw_kem_encrypt(out_encapsulated_key, raw_shared, rng);
183 m_kdf->derive_key(out_shared_key, raw_shared, salt, {});
184 } else {
185 BOTAN_ASSERT_EQUAL(out_shared_key.size(), raw_kem_shared_key_length(), "Shared key has raw KEM output length");
186 this->raw_kem_encrypt(out_encapsulated_key, out_shared_key, rng);
187 }
188}
189
191 if(kdf != "Raw") {
192 m_kdf = KDF::create_or_throw(kdf);
193 }
194}
195
196size_t PK_Ops::KEM_Decryption_with_KDF::shared_key_length(size_t desired_shared_key_len) const {
197 if(m_kdf) {
198 return desired_shared_key_len;
199 } else {
200 return this->raw_kem_shared_key_length();
201 }
202}
203
204void PK_Ops::KEM_Decryption_with_KDF::kem_decrypt(std::span<uint8_t> out_shared_key,
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");
209
210 if(m_kdf) {
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());
215 this->raw_kem_decrypt(raw_shared, encapsulated_key);
216 m_kdf->derive_key(out_shared_key, raw_shared, salt, {});
217 } else {
218 BOTAN_ASSERT_EQUAL(out_shared_key.size(), raw_kem_shared_key_length(), "Shared key has raw KEM output length");
219 this->raw_kem_decrypt(out_shared_key, encapsulated_key);
220 }
221}
222
224 if(kdf != "Raw") {
225 m_kdf = KDF::create_or_throw(kdf);
226 }
227}
228
229} // 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:469
bool parameters_are_null() const
Definition alg_id.cpp:50
const OID & oid() const
Definition asn1_obj.h:455
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:193
std::string to_formatted_string() const
Definition asn1_oid.cpp:114
secure_vector< uint8_t > decrypt(uint8_t &valid_mask, const uint8_t msg[], size_t msg_len) override
Definition pk_ops.cpp:44
Decryption_with_EME(std::string_view eme)
Definition pk_ops.cpp:42
size_t max_input_bits() const override
Definition pk_ops.cpp:30
secure_vector< uint8_t > encrypt(const uint8_t msg[], size_t msg_len, RandomNumberGenerator &rng) override
Definition pk_ops.cpp:34
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:204
KEM_Decryption_with_KDF(std::string_view kdf)
Definition pk_ops.cpp:223
size_t shared_key_length(size_t desired_shared_key_len) const final
Definition pk_ops.cpp:196
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:169
size_t shared_key_length(size_t desired_shared_key_len) const final
Definition pk_ops.cpp:161
KEM_Encryption_with_KDF(std::string_view kdf)
Definition pk_ops.cpp:190
Key_Agreement_with_KDF(std::string_view kdf)
Definition pk_ops.cpp:51
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:57
secure_vector< uint8_t > sign(RandomNumberGenerator &rng) override
Definition pk_ops.cpp:121
Signature_with_Hash(std::string_view hash)
Definition pk_ops.cpp:104
void update(const uint8_t msg[], size_t msg_len) override
Definition pk_ops.cpp:117
virtual AlgorithmIdentifier algorithm_identifier() const
Definition pk_ops.cpp:24
void update(const uint8_t msg[], size_t msg_len) override
Definition pk_ops.cpp:152
Verification_with_Hash(std::string_view hash)
Definition pk_ops.cpp:126
bool is_valid_signature(const uint8_t sig[], size_t sig_len) override
Definition pk_ops.cpp:156
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