Skip to content

Commit

Permalink
Rework Kyber using the common CRYSTALS structs
Browse files Browse the repository at this point in the history
  • Loading branch information
reneme committed Jun 20, 2024
1 parent 020fba6 commit 3ceac47
Show file tree
Hide file tree
Showing 19 changed files with 961 additions and 929 deletions.
5 changes: 4 additions & 1 deletion src/lib/pubkey/kyber/kyber_common/info.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,19 @@ type -> "Internal"
</module_info>

<requires>
pqcrystals
pubkey
hash
rng
</requires>

<header:internal>
kyber_algos.h
kyber_constants.h
kyber_encaps_base.h
kyber_helpers.h
kyber_keys.h
kyber_structures.h
kyber_polynomial.h
kyber_symmetric_primitives.h
kyber_types.h
</header:internal>
Expand Down
43 changes: 22 additions & 21 deletions src/lib/pubkey/kyber/kyber_common/kyber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <botan/secmem.h>

#include <botan/internal/fmt.h>
#include <botan/internal/kyber_algos.h>
#include <botan/internal/kyber_constants.h>
#include <botan/internal/kyber_keys.h>
#include <botan/internal/kyber_symmetric_primitives.h>
Expand All @@ -38,8 +39,6 @@
#include <botan/internal/kyber_encaps.h>
#endif

#include <array>
#include <limits>
#include <memory>
#include <vector>

Expand Down Expand Up @@ -154,14 +153,14 @@ std::shared_ptr<Kyber_PublicKeyInternal> Kyber_PublicKey::initialize_from_encodi
KyberMode m) {
KyberConstants mode(m);

if(pub_key.size() != mode.public_key_byte_length()) {
if(pub_key.size() != mode.public_key_bytes()) {
throw Invalid_Argument("kyber public key does not have the correct byte count");
}

BufferSlicer s(pub_key);

auto poly_vec = s.take(mode.polynomial_vector_byte_length());
auto seed = s.copy<KyberSeedRho>(KyberConstants::kSeedLength);
auto poly_vec = s.take(mode.polynomial_vector_bytes());
auto seed = s.copy<KyberSeedRho>(KyberConstants::SEED_BYTES);
BOTAN_ASSERT_NOMSG(s.empty());

return std::make_shared<Kyber_PublicKeyInternal>(std::move(mode), poly_vec, std::move(seed));
Expand All @@ -188,7 +187,7 @@ std::vector<uint8_t> Kyber_PublicKey::public_key_bits() const {

size_t Kyber_PublicKey::key_length() const {
// TODO: this should report 512, 768, 1024
return m_public->mode().public_key_byte_length();
return m_public->mode().public_key_bytes();
}

bool Kyber_PublicKey::check_key(RandomNumberGenerator&, bool) const {
Expand All @@ -207,25 +206,27 @@ Kyber_PrivateKey::Kyber_PrivateKey(RandomNumberGenerator& rng, KyberMode m) {

// Algorithm 12 (K-PKE.KeyGen) ----------------

const auto d = rng.random_vec<KyberSeedRandomness>(KyberConstants::kSymBytes);
const auto d = rng.random_vec<KyberSeedRandomness>(KyberConstants::SEED_BYTES);
auto [rho, sigma] = mode.symmetric_primitives().G(d);
KyberPolynomialSampler ps(sigma, mode);

auto a = PolynomialMatrix::generate(rho, false /* not transposed */, mode);
auto s = PolynomialVector::getnoise_eta1(sigma, 0 /* N */, mode);
auto e = PolynomialVector::getnoise_eta1(sigma, mode.k() /* N */, mode);
// TODO: Remove the need for the montgomery transformation
//
// -> When calculating A*s below, A is not in montgomery form, but s is. The
// operation uses fqmul internally, which performs a montgomery reduction.
auto A = montgomery(kyber_sample_matrix(rho, false /* not transposed */, mode));
auto s = ntt(ps.sample_polynomial_vector_cbd_eta1());
const auto e = ntt(ps.sample_polynomial_vector_cbd_eta1());

s.ntt();
e.ntt();

auto t = a.pointwise_acc_montgomery(s, true);
auto t = A * s;
t += e;
t.reduce();

// End Algorithm 12 ---------------------------

m_public = std::make_shared<Kyber_PublicKeyInternal>(mode, std::move(t), std::move(rho));
m_private = std::make_shared<Kyber_PrivateKeyInternal>(
std::move(mode), std::move(s), rng.random_vec<KyberImplicitRejectionValue>(KyberConstants::kZLength));
std::move(mode), std::move(s), rng.random_vec<KyberImplicitRejectionValue>(KyberConstants::SEED_BYTES));
}

Kyber_PrivateKey::Kyber_PrivateKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) :
Expand All @@ -234,16 +235,16 @@ Kyber_PrivateKey::Kyber_PrivateKey(const AlgorithmIdentifier& alg_id, std::span<
Kyber_PrivateKey::Kyber_PrivateKey(std::span<const uint8_t> sk, KyberMode m) {
KyberConstants mode(m);

if(mode.private_key_byte_length() != sk.size()) {
if(mode.private_key_bytes() != sk.size()) {
throw Invalid_Argument("kyber private key does not have the correct byte count");
}

BufferSlicer s(sk);

auto skpv = PolynomialVector::from_bytes(s.take(mode.polynomial_vector_byte_length()), mode);
auto pub_key = s.take<KyberSerializedPublicKey>(mode.public_key_byte_length());
auto puk_key_hash = s.take<KyberHashedPublicKey>(KyberConstants::kPublicKeyHashLength);
auto z = s.copy<KyberImplicitRejectionValue>(KyberConstants::kZLength);
auto skpv = kyber_decode_polynomial_vector(s.take(mode.polynomial_vector_bytes()), mode);
auto pub_key = s.take<KyberSerializedPublicKey>(mode.public_key_bytes());
auto puk_key_hash = s.take<KyberHashedPublicKey>(KyberConstants::PUBLIC_KEY_HASH_BYTES);
auto z = s.copy<KyberImplicitRejectionValue>(KyberConstants::SEED_BYTES);

BOTAN_ASSERT_NOMSG(s.empty());

Expand All @@ -266,7 +267,7 @@ secure_vector<uint8_t> Kyber_PrivateKey::raw_private_key_bits() const {
}

secure_vector<uint8_t> Kyber_PrivateKey::private_key_bits() const {
return concat(m_private->s().to_bytes<secure_vector<uint8_t>>(),
return concat(kyber_encode_polynomial_vector<secure_vector<uint8_t>>(m_private->s().reduce(), m_private->mode()),
m_public->public_key_bits_raw(),
m_public->H_public_key_bits_raw(),
m_private->z());
Expand Down
Loading

0 comments on commit 3ceac47

Please sign in to comment.