Skip to content

Commit

Permalink
Update EC keys and ops to use EC_Scalar / EC_AffinePoint internally
Browse files Browse the repository at this point in the history
  • Loading branch information
randombit committed Jul 22, 2024
1 parent 5454fa1 commit 329f500
Show file tree
Hide file tree
Showing 15 changed files with 98 additions and 94 deletions.
3 changes: 0 additions & 3 deletions src/lib/pubkey/ec_group/ec_group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -745,9 +745,6 @@ bool EC_Group::verify_group(RandomNumberGenerator& rng, bool strong) const {
return true;
}

EC_Group::Mul2Table::Mul2Table(const EC_Group& group, const EC_Point& h) :
EC_Group::Mul2Table(EC_AffinePoint(group, h)) {}

EC_Group::Mul2Table::Mul2Table(const EC_AffinePoint& h) : m_tbl(h._group()->make_mul2_table(h._inner())) {}

EC_Group::Mul2Table::~Mul2Table() = default;
Expand Down
7 changes: 0 additions & 7 deletions src/lib/pubkey/ec_group/ec_group.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,13 +229,6 @@ class BOTAN_PUBLIC_API(2, 0) EC_Group final {
/// Table for computing g*x + h*y
class Mul2Table final {
public:
/**
* Internal transition function
*
* @warning this will be removed in 3.6.0, NOT COVERED BY SEMVER
*/
Mul2Table(const EC_Group& group, const EC_Point& h);

/**
* Create a table for computing g*x + h*y
*/
Expand Down
2 changes: 2 additions & 0 deletions src/lib/pubkey/ecc_key/ecc_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ class BOTAN_PUBLIC_API(2, 0) EC_PublicKey : public virtual Public_Key {
const BigInt& get_int_field(std::string_view field) const override;

const EC_AffinePoint& _public_key() const;

protected:
/**
* Load a public key from the point.
Expand Down Expand Up @@ -159,6 +160,7 @@ class BOTAN_PUBLIC_API(2, 0) EC_PrivateKey : public virtual EC_PublicKey,
const BigInt& get_int_field(std::string_view field) const final;

const EC_Scalar& _private_key() const;

protected:
/*
* If x=0, creates a new private key in the domain
Expand Down
10 changes: 4 additions & 6 deletions src/lib/pubkey/ecdh/ecdh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF {
ECDH_KA_Operation(const ECDH_PrivateKey& key, std::string_view kdf, RandomNumberGenerator& rng) :
PK_Ops::Key_Agreement_with_KDF(kdf),
m_group(key.domain()),
m_l_times_priv(mul_cofactor_inv(m_group, key.private_value())),
m_l_times_priv(mul_cofactor_inv(m_group, key._private_key())),
m_rng(rng) {}

size_t agreed_value_size() const override { return m_group.get_p_bytes(); }
Expand All @@ -47,18 +47,16 @@ class ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF {
}

private:
static EC_Scalar mul_cofactor_inv(const EC_Group& group, const BigInt& bn) {
static EC_Scalar mul_cofactor_inv(const EC_Group& group, const EC_Scalar& x) {
// We implement BSI TR-03111 ECKAEG which only matters in the (rare/deprecated)
// case of a curve with cofactor.

auto private_key = EC_Scalar::from_bigint(group, bn);

if(group.has_cofactor()) {
// We could precompute this but cofactors are rare
auto l = group.inverse_mod_order(group.get_cofactor());
return private_key * EC_Scalar::from_bigint(group, l);
return x * EC_Scalar::from_bigint(group, l);
} else {
return private_key;
return x;
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/lib/pubkey/ecdsa/ecdsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,12 +122,12 @@ class ECDSA_Signature_Operation final : public PK_Ops::Signature_with_Hash {
ECDSA_Signature_Operation(const ECDSA_PrivateKey& ecdsa, std::string_view padding, RandomNumberGenerator& rng) :
PK_Ops::Signature_with_Hash(padding),
m_group(ecdsa.domain()),
m_x(EC_Scalar::from_bigint(m_group, ecdsa.private_value())),
m_x(ecdsa._private_key()),
m_b(EC_Scalar::random(m_group, rng)),
m_b_inv(m_b.invert()) {
#if defined(BOTAN_HAS_RFC6979_GENERATOR)
m_rfc6979 = std::make_unique<RFC6979_Nonce_Generator>(
this->rfc6979_hash_function(), m_group.get_order(), ecdsa.private_value());
this->rfc6979_hash_function(), m_group.get_order_bits(), ecdsa._private_key());
#endif
}

Expand Down Expand Up @@ -194,12 +194,12 @@ std::vector<uint8_t> ECDSA_Signature_Operation::raw_sign(std::span<const uint8_t
class ECDSA_Verification_Operation final : public PK_Ops::Verification_with_Hash {
public:
ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa, std::string_view padding) :
PK_Ops::Verification_with_Hash(padding), m_group(ecdsa.domain()), m_gy_mul(m_group, ecdsa.public_point()) {}
PK_Ops::Verification_with_Hash(padding), m_group(ecdsa.domain()), m_gy_mul(ecdsa._public_key()) {}

ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa, const AlgorithmIdentifier& alg_id) :
PK_Ops::Verification_with_Hash(alg_id, "ECDSA", true),
m_group(ecdsa.domain()),
m_gy_mul(m_group, ecdsa.public_point()) {}
m_gy_mul(ecdsa._public_key()) {}

bool verify(std::span<const uint8_t> msg, std::span<const uint8_t> sig) override;

Expand Down
10 changes: 3 additions & 7 deletions src/lib/pubkey/ecgdsa/ecgdsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@ namespace {
class ECGDSA_Signature_Operation final : public PK_Ops::Signature_with_Hash {
public:
ECGDSA_Signature_Operation(const ECGDSA_PrivateKey& ecgdsa, std::string_view emsa) :
PK_Ops::Signature_with_Hash(emsa),
m_group(ecgdsa.domain()),
m_x(EC_Scalar::from_bigint(m_group, ecgdsa.private_value())) {}
PK_Ops::Signature_with_Hash(emsa), m_group(ecgdsa.domain()), m_x(ecgdsa._private_key()) {}

std::vector<uint8_t> raw_sign(std::span<const uint8_t> msg, RandomNumberGenerator& rng) override;

Expand Down Expand Up @@ -82,14 +80,12 @@ std::vector<uint8_t> ECGDSA_Signature_Operation::raw_sign(std::span<const uint8_
class ECGDSA_Verification_Operation final : public PK_Ops::Verification_with_Hash {
public:
ECGDSA_Verification_Operation(const ECGDSA_PublicKey& ecgdsa, std::string_view padding) :
PK_Ops::Verification_with_Hash(padding),
m_group(ecgdsa.domain()),
m_gy_mul(m_group, ecgdsa.public_point()) {}
PK_Ops::Verification_with_Hash(padding), m_group(ecgdsa.domain()), m_gy_mul(ecgdsa._public_key()) {}

ECGDSA_Verification_Operation(const ECGDSA_PublicKey& ecgdsa, const AlgorithmIdentifier& alg_id) :
PK_Ops::Verification_with_Hash(alg_id, "ECGDSA"),
m_group(ecgdsa.domain()),
m_gy_mul(m_group, ecgdsa.public_point()) {}
m_gy_mul(ecgdsa._public_key()) {}

bool verify(std::span<const uint8_t> msg, std::span<const uint8_t> sig) override;

Expand Down
3 changes: 1 addition & 2 deletions src/lib/pubkey/ecies/ecies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,8 @@ class ECIES_ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF {

secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override {
const EC_Group& group = m_key.domain();
const auto x = EC_Scalar::from_bigint(group, m_key.private_value());
if(auto input_point = EC_AffinePoint::deserialize(group, {w, w_len})) {
return input_point->mul(x, m_rng, m_ws).x_bytes();
return input_point->mul(m_key._private_key(), m_rng, m_ws).x_bytes();
} else {
throw Decoding_Error("ECIES - Invalid elliptic curve point");
}
Expand Down
16 changes: 8 additions & 8 deletions src/lib/pubkey/eckcdsa/eckcdsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ std::unique_ptr<HashFunction> eckcdsa_signature_hash(const AlgorithmIdentifier&
return HashFunction::create_or_throw(oid_info[1]);
}

std::vector<uint8_t> eckcdsa_prefix(const EC_Point& point, size_t hash_block_size) {
auto prefix = concat<std::vector<uint8_t>>(point.x_bytes(), point.y_bytes());
std::vector<uint8_t> eckcdsa_prefix(const EC_AffinePoint& point, size_t hash_block_size) {
auto prefix = point.xy_bytes<std::vector<uint8_t>>();

// Either truncate or zero-extend to match the hash block size
prefix.resize(hash_block_size);
Expand Down Expand Up @@ -117,10 +117,10 @@ class ECKCDSA_Signature_Operation final : public PK_Ops::Signature {
public:
ECKCDSA_Signature_Operation(const ECKCDSA_PrivateKey& eckcdsa, std::string_view padding) :
m_group(eckcdsa.domain()),
m_x(EC_Scalar::from_bigint(m_group, eckcdsa.private_value())),
m_x(eckcdsa._private_key()),
m_hash(eckcdsa_signature_hash(padding)),
m_prefix_used(false) {
m_prefix = eckcdsa_prefix(eckcdsa.public_point(), m_hash->hash_block_size());
m_prefix = eckcdsa_prefix(eckcdsa._public_key(), m_hash->hash_block_size());
}

void update(std::span<const uint8_t> input) override {
Expand Down Expand Up @@ -188,18 +188,18 @@ class ECKCDSA_Verification_Operation final : public PK_Ops::Verification {
public:
ECKCDSA_Verification_Operation(const ECKCDSA_PublicKey& eckcdsa, std::string_view padding) :
m_group(eckcdsa.domain()),
m_gy_mul(m_group, eckcdsa.public_point()),
m_gy_mul(eckcdsa._public_key()),
m_hash(eckcdsa_signature_hash(padding)),
m_prefix_used(false) {
m_prefix = eckcdsa_prefix(eckcdsa.public_point(), m_hash->hash_block_size());
m_prefix = eckcdsa_prefix(eckcdsa._public_key(), m_hash->hash_block_size());
}

ECKCDSA_Verification_Operation(const ECKCDSA_PublicKey& eckcdsa, const AlgorithmIdentifier& alg_id) :
m_group(eckcdsa.domain()),
m_gy_mul(m_group, eckcdsa.public_point()),
m_gy_mul(eckcdsa._public_key()),
m_hash(eckcdsa_signature_hash(alg_id)),
m_prefix_used(false) {
m_prefix = eckcdsa_prefix(eckcdsa.public_point(), m_hash->hash_block_size());
m_prefix = eckcdsa_prefix(eckcdsa._public_key(), m_hash->hash_block_size());
}

void update(std::span<const uint8_t> msg) override;
Expand Down
8 changes: 3 additions & 5 deletions src/lib/pubkey/gost_3410/gost_3410.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,7 @@ EC_Scalar gost_msg_to_scalar(const EC_Group& group, std::span<const uint8_t> msg
class GOST_3410_Signature_Operation final : public PK_Ops::Signature_with_Hash {
public:
GOST_3410_Signature_Operation(const GOST_3410_PrivateKey& gost_3410, std::string_view emsa) :
PK_Ops::Signature_with_Hash(emsa),
m_group(gost_3410.domain()),
m_x(EC_Scalar::from_bigint(m_group, gost_3410.private_value())) {}
PK_Ops::Signature_with_Hash(emsa), m_group(gost_3410.domain()), m_x(gost_3410._private_key()) {}

size_t signature_length() const override { return 2 * m_group.get_order_bytes(); }

Expand Down Expand Up @@ -198,12 +196,12 @@ std::string gost_hash_from_algid(const AlgorithmIdentifier& alg_id) {
class GOST_3410_Verification_Operation final : public PK_Ops::Verification_with_Hash {
public:
GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost, std::string_view padding) :
PK_Ops::Verification_with_Hash(padding), m_group(gost.domain()), m_gy_mul(m_group, gost.public_point()) {}
PK_Ops::Verification_with_Hash(padding), m_group(gost.domain()), m_gy_mul(gost._public_key()) {}

GOST_3410_Verification_Operation(const GOST_3410_PublicKey& gost, const AlgorithmIdentifier& alg_id) :
PK_Ops::Verification_with_Hash(gost_hash_from_algid(alg_id)),
m_group(gost.domain()),
m_gy_mul(m_group, gost.public_point()) {}
m_gy_mul(gost._public_key()) {}

bool verify(std::span<const uint8_t> msg, std::span<const uint8_t> sig) override;

Expand Down
25 changes: 15 additions & 10 deletions src/lib/pubkey/rfc6979/rfc6979.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* RFC 6979 Deterministic Nonce Generator
* (C) 2014,2015 Jack Lloyd
* (C) 2014,2015,2024 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
Expand All @@ -13,20 +13,18 @@

namespace Botan {

RFC6979_Nonce_Generator::RFC6979_Nonce_Generator(std::string_view hash, const BigInt& order, const BigInt& x) :
m_order(order),
m_qlen(m_order.bits()),
m_rlen(m_qlen / 8 + (m_qlen % 8 ? 1 : 0)),
m_rng_in(m_rlen * 2),
m_rng_out(m_rlen) {
RFC6979_Nonce_Generator::~RFC6979_Nonce_Generator() = default;

RFC6979_Nonce_Generator::RFC6979_Nonce_Generator(std::string_view hash, size_t order_bits, const BigInt& x) :
m_qlen(order_bits), m_rlen((m_qlen + 7) / 8), m_rng_in(m_rlen * 2), m_rng_out(m_rlen) {
m_hmac_drbg = std::make_unique<HMAC_DRBG>(MessageAuthenticationCode::create_or_throw(fmt("HMAC({})", hash)));

x.serialize_to(std::span{m_rng_in}.first(m_rlen));
}

RFC6979_Nonce_Generator::~RFC6979_Nonce_Generator() = default;
BigInt RFC6979_Nonce_Generator::nonce_for(const BigInt& order, const BigInt& m) {
BOTAN_DEBUG_ASSERT(order.bits() == m_qlen);

BigInt RFC6979_Nonce_Generator::nonce_for(const BigInt& m) {
m.serialize_to(std::span{m_rng_in}.last(m_rlen));

m_hmac_drbg->initialize_with(m_rng_in);
Expand All @@ -43,12 +41,19 @@ BigInt RFC6979_Nonce_Generator::nonce_for(const BigInt& m) {
if(shift > 0) {
k >>= shift;
}
} while(k == 0 || k >= m_order);
} while(k == 0 || k >= order);

return k;
}

#if defined(BOTAN_HAS_ECC_GROUP)
RFC6979_Nonce_Generator::RFC6979_Nonce_Generator(std::string_view hash, size_t order_bits, const EC_Scalar& scalar) :
m_qlen(order_bits), m_rlen((m_qlen + 7) / 8), m_rng_in(m_rlen * 2), m_rng_out(m_rlen) {
m_hmac_drbg = std::make_unique<HMAC_DRBG>(MessageAuthenticationCode::create_or_throw(fmt("HMAC({})", hash)));

scalar.serialize_to(std::span{m_rng_in}.first(m_rlen));
}

EC_Scalar RFC6979_Nonce_Generator::nonce_for(const EC_Group& group, const EC_Scalar& m) {
m.serialize_to(std::span{m_rng_in}.last(m_rlen));

Expand Down
27 changes: 14 additions & 13 deletions src/lib/pubkey/rfc6979/rfc6979.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* RFC 6979 Deterministic Nonce Generator
* (C) 2014,2015 Jack Lloyd
* (C) 2014,2015,2024 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
Expand All @@ -10,7 +10,8 @@

#include <botan/bigint.h>
#include <memory>
#include <string>
#include <span>
#include <string_view>

#if defined(BOTAN_HAS_ECC_GROUP)
#include <botan/ec_scalar.h>
Expand All @@ -22,24 +23,24 @@ class HMAC_DRBG;

class BOTAN_TEST_API RFC6979_Nonce_Generator final {
public:
/**
* Note: keeps persistent reference to order
*/
RFC6979_Nonce_Generator(std::string_view hash, const BigInt& order, const BigInt& x);
RFC6979_Nonce_Generator(std::string_view hash, size_t order_bits, const BigInt& x);

~RFC6979_Nonce_Generator();
BigInt nonce_for(const BigInt& group_order, const BigInt& m);

#if defined(BOTAN_HAS_ECC_GROUP)
RFC6979_Nonce_Generator(std::string_view hash, size_t order_bits, const EC_Scalar& scalar);

EC_Scalar nonce_for(const EC_Group& group, const EC_Scalar& m);
#endif

BigInt nonce_for(const BigInt& m);
~RFC6979_Nonce_Generator();

private:
const BigInt& m_order;
size_t m_qlen, m_rlen;
size_t m_qlen;
size_t m_rlen;
std::unique_ptr<HMAC_DRBG> m_hmac_drbg;
secure_vector<uint8_t> m_rng_in, m_rng_out;
secure_vector<uint8_t> m_rng_in;
secure_vector<uint8_t> m_rng_out;
};

/**
Expand All @@ -49,8 +50,8 @@ class BOTAN_TEST_API RFC6979_Nonce_Generator final {
* @param hash the hash function used to generate h
*/
inline BigInt generate_rfc6979_nonce(const BigInt& x, const BigInt& q, const BigInt& h, std::string_view hash) {
RFC6979_Nonce_Generator gen(hash, q, x);
return gen.nonce_for(h);
RFC6979_Nonce_Generator gen(hash, q.bits(), x);
return gen.nonce_for(q, h);
}

} // namespace Botan
Expand Down
Loading

0 comments on commit 329f500

Please sign in to comment.