13#include <botan/frodokem.h>
15#include <botan/assert.h>
16#include <botan/pubkey.h>
19#include <botan/internal/buffer_slicer.h>
20#include <botan/internal/buffer_stuffer.h>
21#include <botan/internal/concat_util.h>
22#include <botan/internal/ct_utils.h>
23#include <botan/internal/frodo_constants.h>
24#include <botan/internal/frodo_matrix.h>
25#include <botan/internal/frodo_types.h>
26#include <botan/internal/pk_ops_impl.h>
34class FrodoKEM_PublicKeyInternal final {
36 FrodoKEM_PublicKeyInternal(FrodoKEMConstants constants,
FrodoSeedA seed_a, FrodoMatrix b) :
37 m_constants(std::move(constants)), m_seed_a(std::move(seed_a)), m_b(std::move(b)) {
38 auto shake = m_constants.create_xof();
39 shake->update(serialize());
43 const FrodoKEMConstants& constants()
const {
return m_constants; }
45 const FrodoSeedA& seed_a()
const {
return m_seed_a; }
47 const FrodoMatrix& b()
const {
return m_b; }
54 FrodoKEMConstants m_constants;
60class FrodoKEM_PrivateKeyInternal final {
62 FrodoKEM_PrivateKeyInternal(
FrodoSeedS s, FrodoMatrix s_trans) :
63 m_s(std::move(s)), m_s_trans(std::move(s_trans)) {}
67 const FrodoMatrix& s_trans()
const {
return m_s_trans; }
69 constexpr void _const_time_poison()
const {
CT::poison_all(m_s, m_s_trans); }
71 constexpr void _const_time_unpoison()
const {
CT::unpoison_all(m_s, m_s_trans); }
75 FrodoMatrix m_s_trans;
86 Frodo_KEM_Encryptor(std::shared_ptr<FrodoKEM_PublicKeyInternal> key, std::string_view kdf) :
87 KEM_Encryption_with_KDF(kdf), m_public_key(std::move(key)) {}
89 size_t raw_kem_shared_key_length()
const override {
return m_public_key->constants().len_sec_bytes(); }
91 size_t encapsulated_key_length()
const override {
return m_public_key->constants().len_ct_bytes(); }
93 void raw_kem_encrypt(std::span<uint8_t> out_encapsulated_key,
94 std::span<uint8_t> out_shared_key,
95 RandomNumberGenerator& rng)
override {
96 const auto& constants = m_public_key->constants();
97 auto shake = constants.create_xof();
100 BufferStuffer out_ct_bs(out_encapsulated_key);
104 auto salt = out_ct_bs.next<
FrodoSalt>(constants.len_salt_bytes());
108 const auto u = rng.random_vec<
FrodoPlaintext>(constants.len_sec_bytes());
113 shake->update(m_public_key->hash());
116 const auto seed_se = shake->output<
FrodoSeedSE>(constants.len_se_bytes());
120 shake->update(constants.encapsulation_domain_separator());
121 shake->update(seed_se);
123 const auto s_p = sample_generator(std::tuple(constants.n_bar(), constants.n()));
125 const auto e_p = sample_generator(std::tuple(constants.n_bar(), constants.n()));
129 b_p.pack(constants, c_1);
131 const auto e_pp = sample_generator(std::tuple(constants.n_bar(), constants.n_bar()));
140 c.pack(constants, c_2);
142 shake->update(out_encapsulated_key);
144 shake->output(out_shared_key);
150 std::shared_ptr<FrodoKEM_PublicKeyInternal> m_public_key;
155 Frodo_KEM_Decryptor(std::shared_ptr<FrodoKEM_PublicKeyInternal> public_key,
156 std::shared_ptr<FrodoKEM_PrivateKeyInternal> private_key,
157 std::string_view kdf) :
158 KEM_Decryption_with_KDF(kdf), m_public_key(std::move(public_key)), m_private_key(std::move(private_key)) {}
160 size_t raw_kem_shared_key_length()
const override {
return m_public_key->constants().len_sec_bytes(); }
162 size_t encapsulated_key_length()
const override {
return m_public_key->constants().len_ct_bytes(); }
164 void raw_kem_decrypt(std::span<uint8_t> out_shared_key, std::span<const uint8_t> encapsulated_key)
override {
167 const auto& constants = m_public_key->constants();
168 auto shake = constants.create_xof();
171 if(encapsulated_key.size() != constants.len_ct_bytes()) {
172 throw Invalid_Argument(
"FrodoKEM ciphertext does not have the correct byte count");
175 BufferSlicer ct_bs(encapsulated_key);
178 auto salt = ct_bs.take<
FrodoSalt>(constants.len_salt_bytes());
182 const auto c =
FrodoMatrix::unpack(constants, {constants.n_bar(), constants.n_bar()}, c_2);
187 const auto seed_u_p = m.decode(constants);
189 shake->update(m_public_key->hash());
190 shake->update(seed_u_p);
193 const auto seed_se_p = shake->output<
FrodoSeedSE>(constants.len_se_bytes());
197 shake->update(constants.encapsulation_domain_separator());
198 shake->update(seed_se_p);
199 const auto s_p = sample_generator(std::tuple(constants.n_bar(), constants.n()));
201 const auto e_p = sample_generator(std::tuple(constants.n_bar(), constants.n()));
205 const auto e_pp = sample_generator(std::tuple(constants.n_bar(), constants.n_bar()));
216 b_pp.reduce(constants);
217 c_p.reduce(constants);
222 const auto cmp = b_p.constant_time_compare(b_pp) & c.constant_time_compare(c_p);
227 shake->update(encapsulated_key);
228 shake->update(k_bar);
229 shake->output(out_shared_key);
235 std::shared_ptr<FrodoKEM_PublicKeyInternal> m_public_key;
236 std::shared_ptr<FrodoKEM_PrivateKeyInternal> m_private_key;
248 throw Invalid_Argument(
"FrodoKEM public key does not have the correct byte count");
258 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(std::move(constants), std::move(seed_a), std::move(b));
265 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(
271 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(
282 return m_public->constants().mode().object_identifier();
290 return m_public->constants().estimated_strength();
312 return std::make_unique<FrodoKEM_PrivateKey>(rng,
m_public->constants().mode());
316 std::string_view provider)
const {
317 if(provider.empty() || provider ==
"base") {
318 return std::make_unique<Frodo_KEM_Encryptor>(
m_public, params);
342 shake->update(seed_se);
345 auto s_trans = sample_generator(std::tuple(constants.
n_bar(), constants.
n()));
346 auto e = sample_generator(std::tuple(constants.
n(), constants.
n_bar()));
353 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(std::move(constants), std::move(seed_a), std::move(b));
354 m_private = std::make_shared<FrodoKEM_PrivateKeyInternal>(std::move(s), std::move(s_trans));
361 throw Invalid_Argument(
"FrodoKEM private key does not have the correct byte count");
375 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(std::move(constants), std::move(seed_a), std::move(b));
376 m_private = std::make_shared<FrodoKEM_PrivateKeyInternal>(std::move(s), std::move(s_trans));
385 return std::make_unique<FrodoKEM_PublicKey>(*
this);
397 const auto K_prime = dec.
decrypt(c);
412 m_private->s_trans().serialize(),
417 std::string_view params,
418 std::string_view provider)
const {
420 if(provider.empty() || provider ==
"base") {
421 return std::make_unique<Frodo_KEM_Decryptor>(
m_public, m_private, params);
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_STATE_CHECK(expr)
auto copy(const size_t count)
std::span< const uint8_t > take(const size_t count)
FrodoDomainSeparator keygen_domain_separator() const
size_t len_private_key_bytes() const
size_t len_public_key_bytes() const
std::unique_ptr< XOF > create_xof() const
size_t len_sec_bytes() const
size_t len_se_bytes() const
size_t len_a_bytes() const
FrodoKEM_PrivateKey(RandomNumberGenerator &rng, FrodoKEMMode mode)
std::unique_ptr< PK_Ops::KEM_Decryption > create_kem_decryption_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
secure_vector< uint8_t > raw_private_key_bits() const override
bool check_key(RandomNumberGenerator &rng, bool strong) const override
secure_vector< uint8_t > private_key_bits() const override
std::unique_ptr< Public_Key > public_key() const override
size_t estimated_strength() const override
AlgorithmIdentifier algorithm_identifier() const override
std::unique_ptr< PK_Ops::KEM_Encryption > create_kem_encryption_op(std::string_view params, std::string_view provider) const override
size_t key_length() const override
std::shared_ptr< FrodoKEM_PublicKeyInternal > m_public
FrodoKEM_PublicKey(std::span< const uint8_t > pub_key, FrodoKEMMode mode)
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
std::vector< uint8_t > public_key_bits() const override
FrodoKEM_PublicKey & operator=(const FrodoKEM_PublicKey &other)
std::string algo_name() const override
bool check_key(RandomNumberGenerator &rng, bool strong) const override
std::vector< uint8_t > raw_public_key_bits() const override
FrodoKEM_PublicKey()=default
OID object_identifier() const override
static FrodoMatrix mul_add_sa_plus_e(const FrodoKEMConstants &constants, const FrodoMatrix &s, const FrodoMatrix &e, StrongSpan< const FrodoSeedA > seed_a)
static std::function< FrodoMatrix(const Dimensions &dimensions)> make_sample_generator(const FrodoKEMConstants &constants, Botan::XOF &shake)
static FrodoMatrix mul_add_sb_plus_e(const FrodoKEMConstants &constants, const FrodoMatrix &b, const FrodoMatrix &s, const FrodoMatrix &e)
static FrodoMatrix mul_add_as_plus_e(const FrodoKEMConstants &constants, const FrodoMatrix &s, const FrodoMatrix &e, StrongSpan< const FrodoSeedA > seed_a)
static FrodoMatrix sub(const FrodoKEMConstants &constants, const FrodoMatrix &a, const FrodoMatrix &b)
static FrodoMatrix add(const FrodoKEMConstants &constants, const FrodoMatrix &a, const FrodoMatrix &b)
static FrodoMatrix encode(const FrodoKEMConstants &constants, StrongSpan< const FrodoPlaintext > in)
static FrodoMatrix unpack(const FrodoKEMConstants &constants, const Dimensions &dimensions, StrongSpan< const FrodoPackedMatrix > packed_bytes)
static FrodoMatrix mul_bs(const FrodoKEMConstants &constants, const FrodoMatrix &b_p, const FrodoMatrix &s)
static FrodoMatrix deserialize(const Dimensions &dimensions, StrongSpan< const FrodoSerializedMatrix > bytes)
static std::pair< std::vector< uint8_t >, secure_vector< uint8_t > > destructure(KEM_Encapsulation &&kem)
void decrypt(std::span< uint8_t > out_shared_key, std::span< const uint8_t > encap_key, size_t desired_shared_key_len=32, std::span< const uint8_t > salt={})
KEM_Encapsulation encrypt(RandomNumberGenerator &rng, size_t desired_shared_key_len=32, std::span< const uint8_t > salt={})
void random_vec(std::span< uint8_t > v)
constexpr Mask< T > conditional_copy_mem(Mask< T > mask, T *dest, const T *if_set, const T *if_unset, size_t elems)
constexpr void poison_all(const Ts &... ts)
constexpr auto scoped_poison(const Ts &... xs)
constexpr void unpoison_all(const Ts &... ts)
constexpr void unpoison(const T *p, size_t n)
constexpr void poison(const T *p, size_t n)
Strong< secure_vector< uint8_t >, struct FrodoSeedSE_ > FrodoSeedSE
Strong< secure_vector< uint8_t >, struct FrodoSerializedMatrix_ > FrodoSerializedMatrix
Strong< std::vector< uint8_t >, struct FrodoSeedZ_ > FrodoSeedZ
Strong< secure_vector< uint8_t >, struct FrodoIntermediateSharedSecret_ > FrodoIntermediateSharedSecret
Strong< std::vector< uint8_t >, struct FrodoPublicKeyHash_ > FrodoPublicKeyHash
constexpr auto concat(Rs &&... ranges)
std::vector< T, secure_allocator< T > > secure_vector
Strong< std::vector< uint8_t >, struct FrodoSeedA_ > FrodoSeedA
Strong< secure_vector< uint8_t >, struct FrodoPlaintext_ > FrodoPlaintext
Strong< std::vector< uint8_t >, struct FrodoSalt_ > FrodoSalt
Strong< std::vector< uint8_t >, struct FrodoPackedMatrix_ > FrodoPackedMatrix
Strong< secure_vector< uint8_t >, struct FrodoSeedS_ > FrodoSeedS