13#include <botan/frodokem.h>
15#include <botan/assert.h>
19#include <botan/internal/ct_utils.h>
20#include <botan/internal/frodo_constants.h>
21#include <botan/internal/frodo_matrix.h>
22#include <botan/internal/frodo_types.h>
23#include <botan/internal/loadstor.h>
24#include <botan/internal/pk_ops_impl.h>
25#include <botan/internal/stl_util.h>
34class FrodoKEM_PublicKeyInternal {
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)) {
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; }
51 std::vector<uint8_t> serialize()
const {
52 return concat_as<std::vector<uint8_t>>(seed_a(), b().pack(m_constants));
56 FrodoKEMConstants m_constants;
62class FrodoKEM_PrivateKeyInternal {
64 FrodoKEM_PrivateKeyInternal(
FrodoSeedS s, FrodoMatrix s_trans) :
65 m_s(std::move(s)), m_s_trans(std::move(s_trans)) {}
69 const FrodoMatrix& s_trans()
const {
return m_s_trans; }
73 FrodoMatrix m_s_trans;
80class Frodo_KEM_Encryptor
final :
public PK_Ops::KEM_Encryption_with_KDF {
82 Frodo_KEM_Encryptor(std::shared_ptr<FrodoKEM_PublicKeyInternal> key, std::string_view kdf) :
85 size_t raw_kem_shared_key_length()
const override {
return m_public_key->constants().len_sec_bytes(); }
87 size_t encapsulated_key_length()
const override {
return m_public_key->constants().len_ct_bytes(); }
89 void raw_kem_encrypt(std::span<uint8_t> out_encapsulated_key,
90 std::span<uint8_t> out_shared_key,
91 RandomNumberGenerator& rng)
override {
92 const auto& consts = m_public_key->constants();
93 auto& shake = consts.SHAKE_XOF();
96 BufferStuffer out_ct_bs(out_encapsulated_key);
100 auto salt = out_ct_bs.next<
FrodoSalt>(consts.len_salt_bytes());
104 const auto u = rng.random_vec<
FrodoPlaintext>(consts.len_sec_bytes());
107 shake.update(m_public_key->hash());
110 const auto seed_se = shake.output<
FrodoSeedSE>(consts.len_se_bytes());
114 shake.update(consts.encapsulation_domain_separator());
115 shake.update(seed_se);
117 const auto s_p = sample_generator(std::tuple(consts.n_bar(), consts.n()));
119 const auto e_p = sample_generator(std::tuple(consts.n_bar(), consts.n()));
123 b_p.pack(consts, c_1);
125 const auto e_pp = sample_generator(std::tuple(consts.n_bar(), consts.n_bar()));
136 shake.update(out_encapsulated_key);
138 shake.output(out_shared_key);
142 std::shared_ptr<FrodoKEM_PublicKeyInternal> m_public_key;
145class Frodo_KEM_Decryptor
final :
public PK_Ops::KEM_Decryption_with_KDF {
147 Frodo_KEM_Decryptor(std::shared_ptr<FrodoKEM_PublicKeyInternal> public_key,
148 std::shared_ptr<FrodoKEM_PrivateKeyInternal> private_key,
149 std::string_view kdf) :
152 size_t raw_kem_shared_key_length()
const override {
return m_public_key->constants().len_sec_bytes(); }
154 size_t encapsulated_key_length()
const override {
return m_public_key->constants().len_ct_bytes(); }
156 void raw_kem_decrypt(std::span<uint8_t> out_shared_key, std::span<const uint8_t> encapsulated_key)
override {
157 const auto& consts = m_public_key->constants();
158 auto& shake = consts.SHAKE_XOF();
161 if(encapsulated_key.size() != consts.len_ct_bytes()) {
162 throw Invalid_Argument(
"FrodoKEM ciphertext does not have the correct byte count");
165 BufferSlicer ct_bs(encapsulated_key);
168 auto salt = ct_bs.take<
FrodoSalt>(consts.len_salt_bytes());
177 const auto seed_u_p = m.decode(consts);
179 shake.update(m_public_key->hash());
180 shake.update(seed_u_p);
183 const auto seed_se_p = shake.output<
FrodoSeedSE>(consts.len_se_bytes());
187 shake.update(consts.encapsulation_domain_separator());
188 shake.update(seed_se_p);
189 const auto s_p = sample_generator(std::tuple(consts.n_bar(), consts.n()));
191 const auto e_p = sample_generator(std::tuple(consts.n_bar(), consts.n()));
195 const auto e_pp = sample_generator(std::tuple(consts.n_bar(), consts.n_bar()));
212 const auto cmp = b_p.constant_time_compare(b_pp) & c.constant_time_compare(c_p);
214 std::vector<uint8_t> k_bar(consts.len_sec_bytes(), 0);
217 shake.update(encapsulated_key);
219 shake.output(out_shared_key);
223 std::shared_ptr<FrodoKEM_PublicKeyInternal> m_public_key;
224 std::shared_ptr<FrodoKEM_PrivateKeyInternal> m_private_key;
234 throw Invalid_Argument(
"FrodoKEM public key does not have the correct byte count");
244 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(std::move(consts), std::move(seed_a), std::move(b));
251 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(
257 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(
268 return m_public->constants().mode().object_identifier();
276 return m_public->constants().estimated_strength();
288 return std::make_unique<FrodoKEM_PrivateKey>(rng,
m_public->constants().mode());
292 std::string_view provider)
const {
293 if(provider.empty() || provider ==
"base") {
294 return std::make_unique<Frodo_KEM_Encryptor>(
m_public, params);
317 shake.update(seed_se);
319 auto s_trans = sample_generator(std::tuple(consts.
n_bar(), consts.
n()));
320 auto e = sample_generator(std::tuple(consts.
n(), consts.
n_bar()));
324 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(std::move(consts), std::move(seed_a), std::move(b));
325 m_private = std::make_shared<FrodoKEM_PrivateKeyInternal>(std::move(s), std::move(s_trans));
332 throw Invalid_Argument(
"FrodoKEM private key does not have the correct byte count");
346 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(std::move(consts), std::move(seed_a), std::move(b));
347 m_private = std::make_shared<FrodoKEM_PrivateKeyInternal>(std::move(s), std::move(s_trans));
356 return std::make_unique<FrodoKEM_PublicKey>(*
this);
364 return concat_as<secure_vector<uint8_t>>(m_private->s(),
367 m_private->s_trans().serialize(),
372 std::string_view params,
373 std::string_view provider)
const {
375 if(provider.empty() || provider ==
"base") {
376 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
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 &, bool) const override
FrodoKEM_PublicKey()=default
OID object_identifier() const override
static std::function< FrodoMatrix(const Dimensions &dimensions) make_sample_generator)(const FrodoKEMConstants &constants, Botan::XOF &shake)
static FrodoMatrix mul_add_sa_plus_e(const FrodoKEMConstants &constants, const FrodoMatrix &s, const FrodoMatrix &e, StrongSpan< const FrodoSeedA > seed_a)
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)
KEM_Encryption_with_KDF(std::string_view kdf)
void random_vec(std::span< uint8_t > v)
void update(std::span< const uint8_t > input)
int(* final)(unsigned char *, CTX *)
constexpr Mask< T > conditional_copy_mem(Mask< T > mask, T *to, const T *from0, const T *from1, size_t elems)
Strong< secure_vector< uint8_t >, struct FrodoSeedSE_ > FrodoSeedSE
Strong< secure_vector< uint8_t >, struct FrodoIntermediateSharedSecret_ > FrodoIntermediateSharedSecret
Strong< std::vector< uint8_t >, struct FrodoPublicKeyHash_ > FrodoPublicKeyHash
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