Botan 3.7.1
Crypto and TLS for C&
cmce_keys_internal.cpp
Go to the documentation of this file.
1/*
2 * Classic McEliece key generation with Internal Private and Public Key classes
3 * (C) 2023 Jack Lloyd
4 * 2023,2024 Fabian Albert, Amos Treiber - Rohde & Schwarz Cybersecurity
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 **/
8
9#include <botan/internal/cmce_keys_internal.h>
10
11namespace Botan {
12
13namespace {
14
15/**
16 * @brief Try to generate a Classic McEliece keypair for a given seed.
17 *
18 * @param[out] out_next_seed The next seed to use for key generation, if this iteration fails
19 * @param params Classic McEliece parameters
20 * @param seed The seed to used for this key generation iteration
21 * @return a keypair on success, std::nullopt otherwise
22 */
23std::optional<Classic_McEliece_KeyPair_Internal> try_generate_keypair(std::span<uint8_t> out_next_seed,
24 const Classic_McEliece_Parameters& params,
25 CmceKeyGenSeed seed) {
26 BOTAN_ASSERT_EQUAL(seed.size(), 32, "Valid seed length");
27 BOTAN_ASSERT_EQUAL(out_next_seed.size(), 32, "Valid output seed length");
28
29 auto big_e_xof = params.prg(seed);
30
31 auto s = big_e_xof->output<CmceRejectionSeed>(params.n() / 8);
32 auto ordering_bits = big_e_xof->output<CmceOrderingBits>((params.sigma2() * params.q()) / 8);
33 auto irreducible_bits = big_e_xof->output<CmceIrreducibleBits>((params.sigma1() * params.t()) / 8);
34 big_e_xof->output(out_next_seed);
35
36 // Field-ordering generation - Classic McEliece ISO 8.2
37 auto field_ordering = Classic_McEliece_Field_Ordering::create_field_ordering(params, ordering_bits);
38 if(!field_ordering) {
39 return std::nullopt;
40 }
41
42 // Irreducible-polynomial generation - Classic McEliece ISO 8.1
43 auto g = params.poly_ring().compute_minimal_polynomial(irreducible_bits);
44 if(!g) {
45 return std::nullopt;
46 }
47
48 // Matrix generation for Goppa codes - Classic McEliece ISO 7.2
49 auto pk_matrix_and_pivots =
50 Classic_McEliece_Matrix::create_matrix_and_apply_pivots(params, field_ordering.value(), g.value());
51 if(!pk_matrix_and_pivots) {
52 return std::nullopt;
53 }
54 auto& [pk_matrix, pivots] = pk_matrix_and_pivots.value();
55
56 // Key generation was successful - Create and return keys
57 return Classic_McEliece_KeyPair_Internal{
58 .private_key = std::make_shared<Classic_McEliece_PrivateKeyInternal>(
59 params, std::move(seed), pivots, std::move(g.value()), std::move(field_ordering.value()), std::move(s)),
60 .public_key = std::make_shared<Classic_McEliece_PublicKeyInternal>(params, std::move(pk_matrix))};
61}
62
63} // namespace
64
66 const Classic_McEliece_Parameters& params, std::span<const uint8_t> sk_bytes) {
67 BOTAN_ASSERT(sk_bytes.size() == params.sk_size_bytes(), "Valid private key size");
68 BufferSlicer sk_slicer(sk_bytes);
69
70 auto delta = sk_slicer.copy<CmceKeyGenSeed>(params.seed_len());
71 auto c = CmceColumnSelection(sk_slicer.take(params.sk_c_bytes()));
75 auto s = sk_slicer.copy<CmceRejectionSeed>(params.sk_s_bytes());
76 BOTAN_ASSERT_NOMSG(sk_slicer.empty());
77
79 params, std::move(delta), std::move(c), std::move(g), std::move(field_ordering), std::move(s));
80}
81
83 auto control_bits = m_field_ordering.alphas_control_bits();
84
85 /* NIST Impl. guide 6.1 Control-Bit Gen:
86 * As low-cost protection against faults in the control-bit computation, implementors are advised
87 * to check after the computation that applying the Benes network produces pi, and to
88 * restart key generation if this test fails; applying the Benes network is very fast.
89 *
90 * Here, we just assert that applying the Benes network produces pi.
91 */
93 .ct_is_equal(m_field_ordering)
94 .as_bool(),
95 "Control Bit Computation Check");
96
97 return concat(m_delta.get(), m_c.get().to_bytes(), m_g.serialize(), control_bits.to_bytes(), m_s);
98}
99
101 auto prg = m_params.prg(m_delta);
102
103 const auto s = prg->output<CmceRejectionSeed>(m_params.n() / 8);
104 const auto ordering_bits = prg->output<CmceOrderingBits>((m_params.sigma2() * m_params.q()) / 8);
105 const auto irreducible_bits = prg->output<CmceIrreducibleBits>((m_params.sigma1() * m_params.t()) / 8);
106
107 // Recomputing s as hash of delta
108 auto ret = CT::Mask<size_t>::expand(CT::is_equal<uint8_t>(s.data(), m_s.data(), m_params.n() / 8));
109
110 // Checking weight of c
111 ret &= CT::Mask<size_t>::is_equal(c().hamming_weight(), 32);
112
113 if(auto g = m_params.poly_ring().compute_minimal_polynomial(irreducible_bits)) {
114 for(size_t i = 0; i < g->degree() - 1; ++i) {
116 }
117 } else {
119 }
120
121 // Check alpha control bits
122 if(auto field_ord_from_seed = Classic_McEliece_Field_Ordering::create_field_ordering(m_params, ordering_bits)) {
123 field_ord_from_seed->permute_with_pivots(m_params, c());
124 ret &= CT::Mask<size_t>::expand(field_ord_from_seed->ct_is_equal(field_ordering()));
125 } else {
127 }
128
129 return ret.as_bool();
130}
131
132std::shared_ptr<Classic_McEliece_PublicKeyInternal> Classic_McEliece_PublicKeyInternal::create_from_private_key(
134 auto pk_matrix_and_pivot = Classic_McEliece_Matrix::create_matrix(sk.params(), sk.field_ordering(), sk.g());
135 if(!pk_matrix_and_pivot.has_value()) {
136 throw Decoding_Error("Cannot create public key from private key. Private key is invalid.");
137 }
138 auto& [pk_matrix, pivot] = pk_matrix_and_pivot.value();
139
140 // There should not be a pivot of any other form. Otherwise the gauss
141 // algorithm failed effectively.
142 if(!CT::driveby_unpoison(pivot.equals(bitvector{0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}))) {
143 throw Decoding_Error("Cannot create public key from private key. Private key is invalid.");
144 }
145
146 return std::make_shared<Classic_McEliece_PublicKeyInternal>(sk.params(), std::move(pk_matrix));
147}
148
151 BOTAN_ASSERT_EQUAL(seed.size(), params.seed_len(), "Valid seed length");
152
153 CmceKeyGenSeed next_seed(seed.size());
154 CmceKeyGenSeed current_seed(seed.begin(), seed.end());
155
156 while(true) {
157 if(auto keypair = try_generate_keypair(next_seed, params, std::move(current_seed))) {
158 return keypair.value();
159 }
160 current_seed = next_seed;
161 }
162}
163
164} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition assert.h:68
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:50
auto copy(const size_t count)
Definition stl_util.h:89
bool empty() const
Definition stl_util.h:129
std::span< const uint8_t > take(const size_t count)
Definition stl_util.h:98
static constexpr Mask< T > expand(T v)
Definition ct_utils.h:408
static constexpr Mask< T > is_equal(T x, T y)
Definition ct_utils.h:453
static constexpr Mask< T > cleared()
Definition ct_utils.h:403
static std::optional< Classic_McEliece_Field_Ordering > create_field_ordering(const Classic_McEliece_Parameters &params, StrongSpan< const CmceOrderingBits > random_bits)
Creates a field ordering from a random bit sequence. Corresponds to the algorithm described in Classi...
static Classic_McEliece_Field_Ordering create_from_control_bits(const Classic_McEliece_Parameters &params, const secure_bitvector &control_bits)
Create the field ordering from the control bits of a benes network.
secure_bitvector alphas_control_bits() const
Generates the control bits of the benes network corresponding to the field ordering.
static std::optional< std::pair< Classic_McEliece_Matrix, CmceColumnSelection > > create_matrix(const Classic_McEliece_Parameters &params, const Classic_McEliece_Field_Ordering &field_ordering, const Classic_McEliece_Minimal_Polynomial &g)
Create the matrix H for a Classic McEliece instance given its parameters, field ordering and minimal ...
static std::optional< std::pair< Classic_McEliece_Matrix, CmceColumnSelection > > create_matrix_and_apply_pivots(const Classic_McEliece_Parameters &params, Classic_McEliece_Field_Ordering &field_ordering, const Classic_McEliece_Minimal_Polynomial &g)
Create the matrix H for a Classic McEliece instance given its parameters, field ordering and minimal ...
secure_vector< uint8_t > serialize() const
Serialize the polynomial to bytes according to ISO Section 9.2.9.
static Classic_McEliece_Minimal_Polynomial from_bytes(std::span< const uint8_t > bytes, CmceGfMod poly_f)
Create a polynomial from bytes according to ISO Section 9.2.9.
static constexpr size_t seed_len()
The byte length of the seed delta. See ISO 9.2.12.
size_t q() const
The field size of the Classic McEliece instance's underlying Galois Field, i.e. GF(q) is the underlyi...
CmceGfMod poly_f() const
The monic irreducible polynomial f(z) of degree m over GF(2). Used for modular reduction in GF(2^m).
static constexpr size_t sk_c_bytes()
The byte length of the column selection c. See ISO 9.2.12.
std::unique_ptr< XOF > prg(std::span< const uint8_t > seed) const
Create a seeded XOF object representing Classic McEliece's PRG. See Classic McEliece ISO 9....
size_t n() const
The code length of the Classic McEliece instance.
size_t sk_poly_g_bytes() const
The length of the byte representation of the minimal polynomial g. See ISO 9.2.12.
size_t sk_alpha_control_bytes() const
The length of the byte representation of the field ordering's control bits. See ISO 9....
const Classic_McEliece_Polynomial_Ring & poly_ring() const
The underlying polynomial ring.
size_t sk_s_bytes() const
The byte length of the seed s. s is used for implicit rejection. See ISO 9.2.12.
static constexpr size_t sigma2()
Constant for field-ordering generation. (see Classic McEliece ISO 8.2)
size_t sk_size_bytes() const
The byte length of the secret key sk. See ISO 9.2.12.
static constexpr size_t sigma1()
The number of bits each GF element is encoded with.
size_t t() const
The weight of the error vector e.
std::optional< Classic_McEliece_Minimal_Polynomial > compute_minimal_polynomial(StrongSpan< const CmceIrreducibleBits > seed) const
Compute the minimal polynomial g of polynomial created from a seed.
Definition cmce_poly.cpp:72
size_t degree() const
Get the degree of the polynomial.
Definition cmce_poly.h:66
Classic_McEliece_GF & coef_at(size_t i)
Get the coefficient of the i-th monomial as a reference (from low to high degree).
Definition cmce_poly.h:49
Representation of a Classic McEliece private key.
const CmceRejectionSeed & s() const
The seed s for implicit rejection on decryption failure.
const Classic_McEliece_Field_Ordering & field_ordering() const
The field ordering alpha.
bool check_key() const
Checks the private key for consistency with the first component delta, i.e., recomputes s as a hash o...
secure_vector< uint8_t > serialize() const
Serializes the Classic McEliece private key as defined in Classic McEliece ISO Section 9....
const CmceKeyGenSeed & delta() const
The seed delta that was used to create the private key.
const Classic_McEliece_Parameters & params() const
The Classic McEliece parameters.
static Classic_McEliece_PrivateKeyInternal from_bytes(const Classic_McEliece_Parameters &params, std::span< const uint8_t > sk_bytes)
Parses a Classic McEliece private key from a byte sequence.
Classic_McEliece_PrivateKeyInternal(const Classic_McEliece_Parameters &params, CmceKeyGenSeed delta, CmceColumnSelection c, Classic_McEliece_Minimal_Polynomial g, Classic_McEliece_Field_Ordering alpha, CmceRejectionSeed s)
Construct a Classic McEliece private key.
const CmceColumnSelection & c() const
The column selection pivot vector c as defined in Classic McEliece ISO Section 9.2....
const Classic_McEliece_Minimal_Polynomial & g() const
The minimal polynomial g.
static std::shared_ptr< Classic_McEliece_PublicKeyInternal > create_from_private_key(const Classic_McEliece_PrivateKeyInternal &sk)
Create a Classic McEliece public key from a private key.
static GF_Mask is_equal(Classic_McEliece_GF a, Classic_McEliece_GF b)
Definition cmce_gf.h:168
CT::Mask< uint16_t > & elem_mask()
Definition cmce_gf.h:197
decltype(auto) begin() noexcept(noexcept(this->m_span.begin()))
decltype(auto) end() noexcept(noexcept(this->m_span.end()))
decltype(auto) size() const noexcept(noexcept(this->m_span.size()))
OutT to_bytes() const
Definition bitvector.h:489
constexpr T & get() &
Definition strong_type.h:50
decltype(auto) driveby_unpoison(T &&v)
Definition ct_utils.h:237
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
Definition ct_utils.h:788
Strong< secure_vector< uint8_t >, struct CmceOrderingBits_ > CmceOrderingBits
Definition cmce_types.h:37
bitvector_base< secure_allocator > secure_bitvector
Definition bitvector.h:1297
Strong< secure_vector< uint8_t >, struct CmceIrreducibleBits_ > CmceIrreducibleBits
Definition cmce_types.h:40
Strong< secure_bitvector, struct CmceColumnSelection_ > CmceColumnSelection
Represents c of private key.
Definition cmce_types.h:46
constexpr auto concat(Rs &&... ranges)
Definition stl_util.h:263
Strong< secure_vector< uint8_t >, struct CmceKeyGenSeed_ > CmceKeyGenSeed
Represents a delta (can be altered; final value stored in private key)
Definition cmce_types.h:34
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
Strong< secure_vector< uint8_t >, struct CmceRejectionSeed_ > CmceRejectionSeed
Represents s of private key.
Definition cmce_types.h:43
Representation of a Classic McEliece key pair.
static Classic_McEliece_KeyPair_Internal generate(const Classic_McEliece_Parameters &params, StrongSpan< const CmceInitialSeed > seed)
Generate a Classic McEliece key pair using the algorithm described in Classic McEliece ISO Section 8....