13#include <botan/frodokem.h>
15#include <botan/assert.h>
18#include <botan/internal/ct_utils.h>
19#include <botan/internal/frodo_constants.h>
20#include <botan/internal/frodo_matrix.h>
21#include <botan/internal/frodo_types.h>
22#include <botan/internal/pk_ops_impl.h>
23#include <botan/internal/stl_util.h>
31class FrodoKEM_PublicKeyInternal {
33 FrodoKEM_PublicKeyInternal(FrodoKEMConstants constants,
FrodoSeedA seed_a, FrodoMatrix b) :
34 m_constants(std::move(constants)), m_seed_a(std::move(seed_a)), m_b(std::move(b)) {
35 auto& shake = m_constants.SHAKE_XOF();
36 shake.update(serialize());
40 const FrodoKEMConstants& constants()
const {
return m_constants; }
42 const FrodoSeedA& seed_a()
const {
return m_seed_a; }
44 const FrodoMatrix& b()
const {
return m_b; }
51 FrodoKEMConstants m_constants;
57class FrodoKEM_PrivateKeyInternal {
59 FrodoKEM_PrivateKeyInternal(
FrodoSeedS s, FrodoMatrix s_trans) :
60 m_s(std::move(s)), m_s_trans(std::move(s_trans)) {}
64 const FrodoMatrix& s_trans()
const {
return m_s_trans; }
66 constexpr void _const_time_poison()
const {
CT::poison_all(m_s, m_s_trans); }
68 constexpr void _const_time_unpoison()
const {
CT::unpoison_all(m_s, m_s_trans); }
72 FrodoMatrix m_s_trans;
81 Frodo_KEM_Encryptor(std::shared_ptr<FrodoKEM_PublicKeyInternal> key, std::string_view kdf) :
88 void raw_kem_encrypt(std::span<uint8_t> out_encapsulated_key,
89 std::span<uint8_t> out_shared_key,
90 RandomNumberGenerator& rng)
override {
91 const auto& consts = m_public_key->constants();
92 auto& shake = consts.SHAKE_XOF();
95 BufferStuffer out_ct_bs(out_encapsulated_key);
99 auto salt = out_ct_bs.next<
FrodoSalt>(consts.len_salt_bytes());
103 const auto u = rng.random_vec<
FrodoPlaintext>(consts.len_sec_bytes());
108 shake.update(m_public_key->hash());
111 const auto seed_se = shake.output<
FrodoSeedSE>(consts.len_se_bytes());
115 shake.update(consts.encapsulation_domain_separator());
116 shake.update(seed_se);
118 const auto s_p = sample_generator(std::tuple(consts.n_bar(), consts.n()));
120 const auto e_p = sample_generator(std::tuple(consts.n_bar(), consts.n()));
124 b_p.pack(consts, c_1);
126 const auto e_pp = sample_generator(std::tuple(consts.n_bar(), consts.n_bar()));
137 shake.update(out_encapsulated_key);
139 shake.output(out_shared_key);
145 std::shared_ptr<FrodoKEM_PublicKeyInternal> m_public_key;
150 Frodo_KEM_Decryptor(std::shared_ptr<FrodoKEM_PublicKeyInternal> public_key,
151 std::shared_ptr<FrodoKEM_PrivateKeyInternal> private_key,
152 std::string_view kdf) :
159 void raw_kem_decrypt(std::span<uint8_t> out_shared_key, std::span<const uint8_t> encapsulated_key)
override {
162 const auto& consts = m_public_key->constants();
163 auto& shake = consts.SHAKE_XOF();
166 if(encapsulated_key.size() != consts.len_ct_bytes()) {
167 throw Invalid_Argument(
"FrodoKEM ciphertext does not have the correct byte count");
170 BufferSlicer ct_bs(encapsulated_key);
173 auto salt = ct_bs.take<
FrodoSalt>(consts.len_salt_bytes());
182 const auto seed_u_p = m.decode(consts);
184 shake.update(m_public_key->hash());
185 shake.update(seed_u_p);
188 const auto seed_se_p = shake.output<
FrodoSeedSE>(consts.len_se_bytes());
192 shake.update(consts.encapsulation_domain_separator());
193 shake.update(seed_se_p);
194 const auto s_p = sample_generator(std::tuple(consts.n_bar(), consts.n()));
196 const auto e_p = sample_generator(std::tuple(consts.n_bar(), consts.n()));
200 const auto e_pp = sample_generator(std::tuple(consts.n_bar(), consts.n_bar()));
217 const auto cmp = b_p.constant_time_compare(b_pp) & c.constant_time_compare(c_p);
219 std::vector<uint8_t> k_bar(consts.len_sec_bytes(), 0);
222 shake.update(encapsulated_key);
224 shake.output(out_shared_key);
230 std::shared_ptr<FrodoKEM_PublicKeyInternal> m_public_key;
231 std::shared_ptr<FrodoKEM_PrivateKeyInternal> m_private_key;
241 throw Invalid_Argument(
"FrodoKEM public key does not have the correct byte count");
251 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(std::move(consts), std::move(seed_a), std::move(b));
258 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(
264 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(
275 return m_public->constants().mode().object_identifier();
283 return m_public->constants().estimated_strength();
301 return std::make_unique<FrodoKEM_PrivateKey>(rng,
m_public->constants().mode());
305 std::string_view provider)
const {
306 if(provider.empty() || provider ==
"base") {
307 return std::make_unique<Frodo_KEM_Encryptor>(
m_public, params);
331 shake.update(seed_se);
334 auto s_trans = sample_generator(std::tuple(consts.
n_bar(), consts.
n()));
335 auto e = sample_generator(std::tuple(consts.
n(), consts.
n_bar()));
342 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(std::move(consts), std::move(seed_a), std::move(b));
343 m_private = std::make_shared<FrodoKEM_PrivateKeyInternal>(std::move(s), std::move(s_trans));
350 throw Invalid_Argument(
"FrodoKEM private key does not have the correct byte count");
364 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(std::move(consts), std::move(seed_a), std::move(b));
365 m_private = std::make_shared<FrodoKEM_PrivateKeyInternal>(std::move(s), std::move(s_trans));
374 return std::make_unique<FrodoKEM_PublicKey>(*
this);
385 m_private->s_trans().serialize(),
390 std::string_view params,
391 std::string_view provider)
const {
393 if(provider.empty() || provider ==
"base") {
394 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
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
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)
KEM_Decryption_with_KDF(std::string_view kdf)
virtual size_t raw_kem_shared_key_length() const =0
virtual size_t encapsulated_key_length() const =0
virtual size_t raw_kem_shared_key_length() const =0
KEM_Encryption_with_KDF(std::string_view kdf)
virtual size_t encapsulated_key_length() const =0
void random_vec(std::span< uint8_t > v)
constexpr void poison_all(const Ts &... ts)
constexpr Mask< T > conditional_copy_mem(Mask< T > mask, T *dest, const T *if_set, const T *if_unset, size_t elems)
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