11#include <botan/internal/kex_to_kem_adapter.h>
13#include <botan/assert.h>
14#include <botan/internal/fmt.h>
15#include <botan/internal/pk_ops_impl.h>
17#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
19 #include <botan/dl_group.h>
22#if defined(BOTAN_HAS_ECDH)
23 #include <botan/ec_group.h>
24 #include <botan/ecdh.h>
27#if defined(BOTAN_HAS_X25519)
28 #include <botan/x25519.h>
31#if defined(BOTAN_HAS_X448)
32 #include <botan/x448.h>
49size_t kex_shared_key_length(
const Public_Key& kex_public_key) {
52#if defined(BOTAN_HAS_ECDH)
53 if(
const auto* ecdh =
dynamic_cast<const ECDH_PublicKey*
>(&kex_public_key)) {
54 return ecdh->domain().get_p_bytes();
58#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
59 if(
const auto* dh =
dynamic_cast<const DH_PublicKey*
>(&kex_public_key)) {
60 return dh->group().p_bytes();
64#if defined(BOTAN_HAS_X25519)
65 if(
const auto* curve =
dynamic_cast<const X25519_PublicKey*
>(&kex_public_key)) {
71#if defined(BOTAN_HAS_X448)
72 if(
const auto* curve =
dynamic_cast<const X448_PublicKey*
>(&kex_public_key)) {
79 fmt(
"Cannot get shared kex key length from unknown key agreement public key of type '{}' in the hybrid KEM key",
80 kex_public_key.algo_name()));
87std::unique_ptr<PK_Key_Agreement_Key> generate_key_agreement_private_key(
const Public_Key& kex_public_key,
91 auto new_kex_key = [&] {
92 auto new_private_key = kex_public_key.generate_another(rng);
94 if(kex_key !=
nullptr) [[likely]] {
98 (void)new_private_key.release();
100 return std::unique_ptr<PK_Key_Agreement_Key>(kex_key);
103 BOTAN_ASSERT(new_kex_key,
"Keys wrapped in this adapter are always key-agreement keys");
107std::unique_ptr<Public_Key> maybe_get_public_key(
const std::unique_ptr<Private_Key>& private_key) {
109 return private_key->public_key();
114 KEX_to_KEM_Adapter_Encryption_Operation(
const Public_Key& key, std::string_view kdf, std::string_view provider) :
115 PK_Ops::KEM_Encryption_with_KDF(kdf), m_provider(provider), m_public_key(key) {}
117 size_t raw_kem_shared_key_length()
const override {
return kex_shared_key_length(m_public_key); }
119 size_t encapsulated_key_length()
const override {
125 return m_public_key.raw_public_key_bits().size();
128 void raw_kem_encrypt(std::span<uint8_t> out_encapsulated_key,
129 std::span<uint8_t> raw_shared_key,
130 Botan::RandomNumberGenerator& rng)
override {
131 const auto sk = generate_key_agreement_private_key(m_public_key, rng);
132 const auto shared_key = PK_Key_Agreement(*sk, rng,
"Raw", m_provider)
133 .derive_key(0 , m_public_key.raw_public_key_bits())
136 const auto public_value = sk->public_value();
142 out_encapsulated_key.size(),
143 "KEX-to-KEM Adapter: encapsulated key out-param has correct length");
145 shared_key.size(), raw_shared_key.size(),
"KEX-to-KEM Adapter: shared key out-param has correct length");
146 std::copy(public_value.begin(), public_value.end(), out_encapsulated_key.begin());
147 std::copy(shared_key.begin(), shared_key.end(), raw_shared_key.begin());
151 std::string m_provider;
152 const Public_Key& m_public_key;
157 KEX_to_KEM_Decryption_Operation(
const PK_Key_Agreement_Key& key,
158 RandomNumberGenerator& rng,
159 const std::string_view kdf,
160 const std::string_view provider) :
161 PK_Ops::KEM_Decryption_with_KDF(kdf),
162 m_operation(key, rng,
"Raw", provider),
163 m_encapsulated_key_length(key.public_value().size()) {}
165 void raw_kem_decrypt(std::span<uint8_t> out_shared_key, std::span<const uint8_t> encap_key)
override {
168 shared_secret.size(), out_shared_key.size(),
"KEX-to-KEM Adapter: shared key out-param has correct length");
169 std::copy(shared_secret.begin(), shared_secret.end(), out_shared_key.begin());
172 size_t encapsulated_key_length()
const override {
return m_encapsulated_key_length; }
174 size_t raw_kem_shared_key_length()
const override {
return m_operation.agreed_value_size(); }
177 PK_Key_Agreement m_operation;
178 size_t m_encapsulated_key_length;
184 m_public_key(std::move(public_key)) {
190 return fmt(
"KEX-to-KEM({})", m_public_key->algo_name());
194 return m_public_key->estimated_strength();
198 return m_public_key->key_length();
202 return m_public_key->check_key(rng, strong);
206 return m_public_key->algorithm_identifier();
210 return m_public_key->raw_public_key_bits();
214 return m_public_key->public_key_bits();
218 return std::make_unique<KEX_to_KEM_Adapter_PrivateKey>(generate_key_agreement_private_key(*m_public_key, rng));
227std::unique_ptr<PK_Key_Agreement_Key> capture_as_ka_key(std::unique_ptr<Private_Key> private_key) {
228 auto* raw_ptr = private_key.release();
230 return std::unique_ptr<PK_Key_Agreement_Key>(sk);
234 "Private key must implement PK_Key_Agreement_Key",
"KEX_to_KEM_Adapter_PrivateKey", __FILE__);
242 m_private_key(capture_as_ka_key(std::move(private_key))) {}
245 return m_private_key->private_key_bits();
249 return m_private_key->raw_private_key_bits();
253 return std::make_unique<KEX_to_KEM_Adapter_PublicKey>(m_private_key->public_key());
257 return m_private_key->check_key(rng, strong);
261 std::string_view kdf, std::string_view provider)
const {
262 return std::make_unique<KEX_to_KEM_Adapter_Encryption_Operation>(*m_public_key, kdf, provider);
267 return std::make_unique<KEX_to_KEM_Decryption_Operation>(*m_private_key, rng, kdf, provider);
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
#define BOTAN_ARG_CHECK(expr, msg)
#define BOTAN_ASSERT(expr, assertion_made)
secure_vector< uint8_t > private_key_bits() const override
std::unique_ptr< Public_Key > public_key() const override
secure_vector< uint8_t > raw_private_key_bits() const override
KEX_to_KEM_Adapter_PrivateKey(std::unique_ptr< Private_Key > private_key)
bool check_key(RandomNumberGenerator &rng, bool strong) const override
std::unique_ptr< PK_Ops::KEM_Decryption > create_kem_decryption_op(RandomNumberGenerator &rng, std::string_view kdf, std::string_view provider="base") const override
size_t estimated_strength() const override
KEX_to_KEM_Adapter_PublicKey(std::unique_ptr< Public_Key > public_key)
std::string algo_name() const override
std::unique_ptr< PK_Ops::KEM_Encryption > create_kem_encryption_op(std::string_view kdf, std::string_view provider="base") const override
bool check_key(RandomNumberGenerator &rng, bool strong) const override
std::vector< uint8_t > raw_public_key_bits() const override
size_t key_length() const override
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
AlgorithmIdentifier algorithm_identifier() const override
bool supports_operation(PublicKeyOperation op) const override
std::vector< uint8_t > public_key_bits() const override
A public key for the X448 key agreement scheme according to RFC 7748.
void throw_invalid_argument(const char *message, const char *func, const char *file)
std::string fmt(std::string_view format, const T &... args)
std::vector< T, secure_allocator< T > > secure_vector