Skip to content

Commit

Permalink
Apply review suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
FAlbertDev committed Mar 27, 2024
1 parent 7984b10 commit f6333fd
Show file tree
Hide file tree
Showing 12 changed files with 197 additions and 174 deletions.
2 changes: 1 addition & 1 deletion src/cli/speed.cpp
Expand Up @@ -2137,7 +2137,7 @@ class Speed final : public Command {
};

for(auto cmce_set : cmce_param_sets) {
auto cmce_set_str = Botan::cmce_str_from_param_set(cmce_set);
auto cmce_set_str = cmce_set.to_string();

auto keygen_timer = make_timer(cmce_set_str, provider, "keygen");

Expand Down
41 changes: 5 additions & 36 deletions src/lib/pubkey/classic_mceliece/cmce.cpp
Expand Up @@ -22,7 +22,7 @@ namespace Botan {

Classic_McEliece_PublicKey::Classic_McEliece_PublicKey(const AlgorithmIdentifier& alg_id,
std::span<const uint8_t> key_bits) :
Classic_McEliece_PublicKey(key_bits, cmce_param_set_from_oid(alg_id.oid())) {}
Classic_McEliece_PublicKey(key_bits, Classic_McEliece_Parameter_Set::from_oid(alg_id.oid())) {}

Classic_McEliece_PublicKey::Classic_McEliece_PublicKey(std::span<const uint8_t> key_bits,
Classic_McEliece_Parameter_Set param_set) {
Expand Down Expand Up @@ -52,7 +52,8 @@ OID Classic_McEliece_PublicKey::object_identifier() const {
}

size_t Classic_McEliece_PublicKey::key_length() const {
return m_public->matrix().bytes().size();
// The key length is the dimension k of the goppa code (i.e. the code has 2^k codewords)
return m_public->params().pk_no_cols();
}

size_t Classic_McEliece_PublicKey::estimated_strength() const {
Expand Down Expand Up @@ -99,7 +100,7 @@ Classic_McEliece_PrivateKey::Classic_McEliece_PrivateKey(std::span<const uint8_t

Classic_McEliece_PrivateKey::Classic_McEliece_PrivateKey(const AlgorithmIdentifier& alg_id,
std::span<const uint8_t> key_bits) :
Classic_McEliece_PrivateKey(key_bits, cmce_param_set_from_oid(alg_id.oid())) {}
Classic_McEliece_PrivateKey(key_bits, Classic_McEliece_Parameter_Set::from_oid(alg_id.oid())) {}

std::unique_ptr<Public_Key> Classic_McEliece_PrivateKey::public_key() const {
return std::make_unique<Classic_McEliece_PublicKey>(*this);
Expand All @@ -114,39 +115,7 @@ secure_vector<uint8_t> Classic_McEliece_PrivateKey::raw_private_key_bits() const
}

bool Classic_McEliece_PrivateKey::check_key(RandomNumberGenerator&, bool) const {
auto prg = m_private->params().prg(m_private->delta());

const auto s = prg->output<CmceRejectionSeed>(m_private->params().n() / 8);
const auto ordering_bits =
prg->output<CmceOrderingBits>((m_private->params().sigma2() * m_private->params().q()) / 8);
const auto irreducible_bits =
prg->output<CmceIrreducibleBits>((m_private->params().sigma1() * m_private->params().t()) / 8);

// Recomputing s as hash of delta
auto ret =
CT::Mask<size_t>::expand(CT::is_equal<uint8_t>(s.data(), m_private->s().data(), m_private->params().n() / 8));

// Checking weight of c
ret &= CT::Mask<size_t>::is_equal(m_private->c().ct_hamming_weight(), 32);

if(auto g = m_private->params().poly_ring().compute_minimal_polynomial(irreducible_bits)) {
for(size_t i = 0; i < g->degree() - 1; ++i) {
ret &= CT::Mask<size_t>::expand(GF_Mask::is_equal(g->coef_at(i), m_private->g().coef_at(i)).elem_mask());
}
} else {
ret = CT::Mask<size_t>::cleared();
}

// Check alpha control bits
if(auto field_ord_from_seed =
Classic_McEliece_Field_Ordering::create_field_ordering(m_private->params(), ordering_bits)) {
field_ord_from_seed->permute_with_pivots(m_private->params(), m_private->c());
ret &= CT::Mask<size_t>::expand(field_ord_from_seed->ct_is_equal(m_private->field_ordering()));
} else {
ret = CT::Mask<size_t>::cleared();
}

return ret.as_bool();
return m_private->check_key();
}

std::unique_ptr<PK_Ops::KEM_Decryption> Classic_McEliece_PrivateKey::create_kem_decryption_op(
Expand Down
10 changes: 1 addition & 9 deletions src/lib/pubkey/classic_mceliece/cmce.h
Expand Up @@ -126,14 +126,6 @@ class BOTAN_PUBLIC_API(3, 4) Classic_McEliece_PrivateKey final : public virtual

secure_vector<uint8_t> raw_private_key_bits() const override;

/**
* @brief Checks the private key for consistency with the first component delta, i.e.,
* recomputes s as a hash of delta and checks equivalence with sk.s, checks the weight of c,
* and checks the control bits. It also recomputes beta based on delta and recomputes g based on beta,
* checking that g is equal to the value sk.s
*
* See NIST Impl. guide 6.3 Double-Checks on Private Keys.
*/
bool check_key(RandomNumberGenerator&, bool) const override;

std::unique_ptr<PK_Ops::KEM_Decryption> create_kem_decryption_op(RandomNumberGenerator& rng,
Expand All @@ -148,4 +140,4 @@ BOTAN_DIAGNOSTIC_POP

} // namespace Botan

#endif // BOTAN_CMCE_GF_H_
#endif // BOTAN_CMCE_H_
10 changes: 5 additions & 5 deletions src/lib/pubkey/classic_mceliece/cmce_field_ordering.cpp
Expand Up @@ -71,7 +71,7 @@ T min(const T& a, const T& b) {

namespace {
template <std::unsigned_integral T1, std::unsigned_integral T2>
std::vector<std::pair<T1, T2>> zip(const secure_vector<T1>& vec_1, const secure_vector<T2>& vec_2) {
std::vector<std::pair<T1, T2>> zip(std::span<const T1> vec_1, std::span<const T2> vec_2) {
BOTAN_ARG_CHECK(vec_1.size() == vec_2.size(), "Vectors' dimensions do not match");
std::vector<std::pair<T1, T2>> vec_zipped;
vec_zipped.reserve(vec_1.size());
Expand All @@ -82,7 +82,7 @@ std::vector<std::pair<T1, T2>> zip(const secure_vector<T1>& vec_1, const secure_
}

template <std::unsigned_integral T1, std::unsigned_integral T2>
std::pair<secure_vector<T1>, secure_vector<T2>> unzip(const std::vector<std::pair<T1, T2>>& vec_zipped) {
std::pair<secure_vector<T1>, secure_vector<T2>> unzip(const std::span<std::pair<T1, T2>>& vec_zipped) {
std::pair<secure_vector<T1>, secure_vector<T2>> res;

res.first.reserve(vec_zipped.size());
Expand All @@ -109,12 +109,12 @@ std::vector<std::pair<uint32_t, uint16_t>> enumerate(std::span<const uint32_t> v
/**
* @brief Create permutation pi as in (Section 8.2, Step 3).
*/
CmcePermutation create_pi(secure_vector<uint32_t>& a) {
CmcePermutation create_pi(std::span<const uint32_t> a) {
auto a_pi_zipped = enumerate(a);
CMCE_CT::bitonic_sort_pair(std::span(a_pi_zipped));

CmcePermutation pi_sorted;
std::tie(a, pi_sorted.get()) = unzip(a_pi_zipped);
std::tie(a, pi_sorted.get()) = unzip(std::span(a_pi_zipped));

return pi_sorted;
}
Expand All @@ -139,7 +139,7 @@ Classic_McEliece_GF from_pi(CmcePermutationElement pi_elem, CmceGfMod modulus, s
/**
* @brief Part of field ordering generation according to ISO 9.2.10
*/
secure_vector<uint16_t> composeinv(const secure_vector<uint16_t>& c, const secure_vector<uint16_t>& pi) {
secure_vector<uint16_t> composeinv(std::span<const uint16_t> c, std::span<const uint16_t> pi) {
auto pi_c_zipped = zip(pi, c);
CMCE_CT::bitonic_sort_pair(std::span(pi_c_zipped));
// Extract c from the sorted vector
Expand Down
32 changes: 32 additions & 0 deletions src/lib/pubkey/classic_mceliece/cmce_keys_internal.cpp
Expand Up @@ -97,6 +97,38 @@ secure_vector<uint8_t> Classic_McEliece_PrivateKeyInternal::serialize() const {
return concat(m_delta.get(), m_c.get().to_bytes(), m_g.serialize(), control_bits.to_bytes(), m_s);
}

bool Classic_McEliece_PrivateKeyInternal::check_key() const {
auto prg = m_params.prg(m_delta);

const auto s = prg->output<CmceRejectionSeed>(m_params.n() / 8);
const auto ordering_bits = prg->output<CmceOrderingBits>((m_params.sigma2() * m_params.q()) / 8);
const auto irreducible_bits = prg->output<CmceIrreducibleBits>((m_params.sigma1() * m_params.t()) / 8);

// Recomputing s as hash of delta
auto ret = CT::Mask<size_t>::expand(CT::is_equal<uint8_t>(s.data(), m_s.data(), m_params.n() / 8));

// Checking weight of c
ret &= CT::Mask<size_t>::is_equal(c().ct_hamming_weight(), 32);

if(auto g = m_params.poly_ring().compute_minimal_polynomial(irreducible_bits)) {
for(size_t i = 0; i < g->degree() - 1; ++i) {
ret &= CT::Mask<size_t>::expand(GF_Mask::is_equal(g->coef_at(i), m_g.coef_at(i)).elem_mask());
}
} else {
ret = CT::Mask<size_t>::cleared();
}

// Check alpha control bits
if(auto field_ord_from_seed = Classic_McEliece_Field_Ordering::create_field_ordering(m_params, ordering_bits)) {
field_ord_from_seed->permute_with_pivots(m_params, c());
ret &= CT::Mask<size_t>::expand(field_ord_from_seed->ct_is_equal(field_ordering()));
} else {
ret = CT::Mask<size_t>::cleared();
}

return ret.as_bool();
}

std::shared_ptr<Classic_McEliece_PublicKeyInternal> Classic_McEliece_PublicKeyInternal::create_from_private_key(
const Classic_McEliece_PrivateKeyInternal& sk) {
auto pk_matrix_and_pivot = Classic_McEliece_Matrix::create_matrix(sk.params(), sk.field_ordering(), sk.g());
Expand Down
10 changes: 10 additions & 0 deletions src/lib/pubkey/classic_mceliece/cmce_keys_internal.h
Expand Up @@ -158,6 +158,16 @@ class BOTAN_TEST_API Classic_McEliece_PrivateKeyInternal {
*/
const Classic_McEliece_Parameters& params() const { return m_params; }

/**
* @brief Checks the private key for consistency with the first component delta, i.e.,
* recomputes s as a hash of delta and checks equivalence with sk.s, checks the weight of c,
* and checks the control bits. It also recomputes beta based on delta and recomputes g based on beta,
* checking that g is equal to the value sk.s
*
* See NIST Impl. guide 6.3 Double-Checks on Private Keys.
*/
bool check_key() const;

private:
Classic_McEliece_Parameters m_params;
CmceKeyGenSeed m_delta;
Expand Down
143 changes: 73 additions & 70 deletions src/lib/pubkey/classic_mceliece/cmce_parameter_set.cpp
Expand Up @@ -10,99 +10,102 @@

namespace Botan {

Classic_McEliece_Parameter_Set cmce_param_set_from_str(std::string_view param_name) {
if(param_name == "mceliece348864") {
return Classic_McEliece_Parameter_Set::mceliece348864;
}
if(param_name == "mceliece348864f") {
return Classic_McEliece_Parameter_Set::mceliece348864f;
}
if(param_name == "mceliece460896") {
return Classic_McEliece_Parameter_Set::mceliece460896;
}
if(param_name == "mceliece460896f") {
return Classic_McEliece_Parameter_Set::mceliece460896f;
}
if(param_name == "mceliece6688128") {
return Classic_McEliece_Parameter_Set::mceliece6688128;
}
if(param_name == "mceliece6688128f") {
return Classic_McEliece_Parameter_Set::mceliece6688128f;
}
if(param_name == "mceliece6688128pc") {
return Classic_McEliece_Parameter_Set::mceliece6688128pc;
}
if(param_name == "mceliece6688128pcf") {
return Classic_McEliece_Parameter_Set::mceliece6688128pcf;
}
if(param_name == "mceliece6960119") {
return Classic_McEliece_Parameter_Set::mceliece6960119;
}
if(param_name == "mceliece6960119f") {
return Classic_McEliece_Parameter_Set::mceliece6960119f;
}
if(param_name == "mceliece6960119pc") {
return Classic_McEliece_Parameter_Set::mceliece6960119pc;
}
if(param_name == "mceliece6960119pcf") {
return Classic_McEliece_Parameter_Set::mceliece6960119pcf;
}
if(param_name == "mceliece8192128") {
return Classic_McEliece_Parameter_Set::mceliece8192128;
}
if(param_name == "mceliece8192128f") {
return Classic_McEliece_Parameter_Set::mceliece8192128f;
}
if(param_name == "mceliece8192128pc") {
return Classic_McEliece_Parameter_Set::mceliece8192128pc;
}
if(param_name == "mceliece8192128pcf") {
return Classic_McEliece_Parameter_Set::mceliece8192128pcf;
}
Classic_McEliece_Parameter_Set Classic_McEliece_Parameter_Set::from_string(std::string_view param_name) {
Code code = [&] {
if(param_name == "mceliece348864") {
return mceliece348864;
}
if(param_name == "mceliece348864f") {
return mceliece348864f;
}
if(param_name == "mceliece460896") {
return mceliece460896;
}
if(param_name == "mceliece460896f") {
return mceliece460896f;
}
if(param_name == "mceliece6688128") {
return mceliece6688128;
}
if(param_name == "mceliece6688128f") {
return mceliece6688128f;
}
if(param_name == "mceliece6688128pc") {
return mceliece6688128pc;
}
if(param_name == "mceliece6688128pcf") {
return mceliece6688128pcf;
}
if(param_name == "mceliece6960119") {
return mceliece6960119;
}
if(param_name == "mceliece6960119f") {
return mceliece6960119f;
}
if(param_name == "mceliece6960119pc") {
return mceliece6960119pc;
}
if(param_name == "mceliece6960119pcf") {
return mceliece6960119pcf;
}
if(param_name == "mceliece8192128") {
return mceliece8192128;
}
if(param_name == "mceliece8192128f") {
return mceliece8192128f;
}
if(param_name == "mceliece8192128pc") {
return mceliece8192128pc;
}
if(param_name == "mceliece8192128pcf") {
return mceliece8192128pcf;
}

throw Decoding_Error("Cannot convert string to CMCE parameter set");
throw Decoding_Error("Cannot convert string to CMCE parameter set");
}();
return Classic_McEliece_Parameter_Set(code);
}

std::string cmce_str_from_param_set(Classic_McEliece_Parameter_Set param) {
switch(param) {
case Classic_McEliece_Parameter_Set::mceliece348864:
std::string Classic_McEliece_Parameter_Set::to_string() const {
switch(m_code) {
case mceliece348864:
return "mceliece348864";
case Classic_McEliece_Parameter_Set::mceliece348864f:
case mceliece348864f:
return "mceliece348864f";
case Classic_McEliece_Parameter_Set::mceliece460896:
case mceliece460896:
return "mceliece460896";
case Classic_McEliece_Parameter_Set::mceliece460896f:
case mceliece460896f:
return "mceliece460896f";
case Classic_McEliece_Parameter_Set::mceliece6688128:
case mceliece6688128:
return "mceliece6688128";
case Classic_McEliece_Parameter_Set::mceliece6688128f:
case mceliece6688128f:
return "mceliece6688128f";
case Classic_McEliece_Parameter_Set::mceliece6688128pc:
case mceliece6688128pc:
return "mceliece6688128pc";
case Classic_McEliece_Parameter_Set::mceliece6688128pcf:
case mceliece6688128pcf:
return "mceliece6688128pcf";
case Classic_McEliece_Parameter_Set::mceliece6960119:
case mceliece6960119:
return "mceliece6960119";
case Classic_McEliece_Parameter_Set::mceliece6960119f:
case mceliece6960119f:
return "mceliece6960119f";
case Classic_McEliece_Parameter_Set::mceliece6960119pc:
case mceliece6960119pc:
return "mceliece6960119pc";
case Classic_McEliece_Parameter_Set::mceliece6960119pcf:
case mceliece6960119pcf:
return "mceliece6960119pcf";
case Classic_McEliece_Parameter_Set::mceliece8192128:
case mceliece8192128:
return "mceliece8192128";
case Classic_McEliece_Parameter_Set::mceliece8192128f:
case mceliece8192128f:
return "mceliece8192128f";
case Classic_McEliece_Parameter_Set::mceliece8192128pc:
case mceliece8192128pc:
return "mceliece8192128pc";
case Classic_McEliece_Parameter_Set::mceliece8192128pcf:
case mceliece8192128pcf:
return "mceliece8192128pcf";
}
BOTAN_ASSERT_UNREACHABLE();
}

Classic_McEliece_Parameter_Set cmce_param_set_from_oid(const OID& oid) {
return cmce_param_set_from_str(oid.to_formatted_string());
Classic_McEliece_Parameter_Set Classic_McEliece_Parameter_Set::from_oid(const OID& oid) {
return from_string(oid.to_formatted_string());
}

} // namespace Botan

0 comments on commit f6333fd

Please sign in to comment.