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; }
54 FrodoKEMConstants m_constants;
60class FrodoKEM_PrivateKeyInternal {
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;
82class Frodo_KEM_Encryptor
final :
public PK_Ops::KEM_Encryption_with_KDF {
84 Frodo_KEM_Encryptor(std::shared_ptr<FrodoKEM_PublicKeyInternal> key, std::string_view kdf) :
87 size_t raw_kem_shared_key_length()
const override {
return m_public_key->constants().len_sec_bytes(); }
89 size_t encapsulated_key_length()
const override {
return m_public_key->constants().len_ct_bytes(); }
91 void raw_kem_encrypt(std::span<uint8_t> out_encapsulated_key,
92 std::span<uint8_t> out_shared_key,
93 RandomNumberGenerator& rng)
override {
94 const auto& consts = m_public_key->constants();
95 auto& shake = consts.SHAKE_XOF();
98 BufferStuffer out_ct_bs(out_encapsulated_key);
102 auto salt = out_ct_bs.next<
FrodoSalt>(consts.len_salt_bytes());
106 const auto u = rng.random_vec<
FrodoPlaintext>(consts.len_sec_bytes());
111 shake.update(m_public_key->hash());
114 const auto seed_se = shake.output<
FrodoSeedSE>(consts.len_se_bytes());
118 shake.update(consts.encapsulation_domain_separator());
119 shake.update(seed_se);
121 const auto s_p = sample_generator(std::tuple(consts.n_bar(), consts.n()));
123 const auto e_p = sample_generator(std::tuple(consts.n_bar(), consts.n()));
127 b_p.pack(consts, c_1);
129 const auto e_pp = sample_generator(std::tuple(consts.n_bar(), consts.n_bar()));
140 shake.update(out_encapsulated_key);
142 shake.output(out_shared_key);
148 std::shared_ptr<FrodoKEM_PublicKeyInternal> m_public_key;
151class Frodo_KEM_Decryptor
final :
public PK_Ops::KEM_Decryption_with_KDF {
153 Frodo_KEM_Decryptor(std::shared_ptr<FrodoKEM_PublicKeyInternal> public_key,
154 std::shared_ptr<FrodoKEM_PrivateKeyInternal> private_key,
155 std::string_view kdf) :
158 size_t raw_kem_shared_key_length()
const override {
return m_public_key->constants().len_sec_bytes(); }
160 size_t encapsulated_key_length()
const override {
return m_public_key->constants().len_ct_bytes(); }
162 void raw_kem_decrypt(std::span<uint8_t> out_shared_key, std::span<const uint8_t> encapsulated_key)
override {
165 const auto& consts = m_public_key->constants();
166 auto& shake = consts.SHAKE_XOF();
169 if(encapsulated_key.size() != consts.len_ct_bytes()) {
170 throw Invalid_Argument(
"FrodoKEM ciphertext does not have the correct byte count");
173 BufferSlicer ct_bs(encapsulated_key);
176 auto salt = ct_bs.take<
FrodoSalt>(consts.len_salt_bytes());
185 const auto seed_u_p = m.decode(consts);
187 shake.update(m_public_key->hash());
188 shake.update(seed_u_p);
191 const auto seed_se_p = shake.output<
FrodoSeedSE>(consts.len_se_bytes());
195 shake.update(consts.encapsulation_domain_separator());
196 shake.update(seed_se_p);
197 const auto s_p = sample_generator(std::tuple(consts.n_bar(), consts.n()));
199 const auto e_p = sample_generator(std::tuple(consts.n_bar(), consts.n()));
203 const auto e_pp = sample_generator(std::tuple(consts.n_bar(), consts.n_bar()));
220 const auto cmp = b_p.constant_time_compare(b_pp) & c.constant_time_compare(c_p);
222 std::vector<uint8_t> k_bar(consts.len_sec_bytes(), 0);
225 shake.update(encapsulated_key);
227 shake.output(out_shared_key);
233 std::shared_ptr<FrodoKEM_PublicKeyInternal> m_public_key;
234 std::shared_ptr<FrodoKEM_PrivateKeyInternal> m_private_key;
244 throw Invalid_Argument(
"FrodoKEM public key does not have the correct byte count");
254 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(std::move(consts), std::move(seed_a), std::move(
b));
261 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(
267 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(
278 return m_public->constants().mode().object_identifier();
286 return m_public->constants().estimated_strength();
304 return std::make_unique<FrodoKEM_PrivateKey>(rng,
m_public->constants().mode());
308 std::string_view provider)
const {
309 if(provider.empty() || provider ==
"base") {
310 return std::make_unique<Frodo_KEM_Encryptor>(
m_public, params);
334 shake.update(seed_se);
337 auto s_trans = sample_generator(std::tuple(consts.
n_bar(), consts.
n()));
338 auto e = sample_generator(std::tuple(consts.
n(), consts.
n_bar()));
345 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(std::move(consts), std::move(seed_a), std::move(
b));
346 m_private = std::make_shared<FrodoKEM_PrivateKeyInternal>(std::move(s), std::move(s_trans));
353 throw Invalid_Argument(
"FrodoKEM private key does not have the correct byte count");
367 m_public = std::make_shared<FrodoKEM_PublicKeyInternal>(std::move(consts), std::move(seed_a), std::move(
b));
368 m_private = std::make_shared<FrodoKEM_PrivateKeyInternal>(std::move(s), std::move(s_trans));
377 return std::make_unique<FrodoKEM_PublicKey>(*
this);
388 m_private->s_trans().serialize(),
393 std::string_view params,
394 std::string_view provider)
const {
396 if(provider.empty() || provider ==
"base") {
397 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
std::vector< uint8_t > raw_public_key_bits() const override
bool check_key(RandomNumberGenerator &, bool) 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)
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 void unpoison_all(Ts &&... ts)
constexpr auto scoped_poison(const Ts &... xs)
constexpr Mask< T > conditional_copy_mem(Mask< T > mask, T *to, const T *from0, const T *from1, size_t elems)
constexpr void poison_all(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 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