Skip to content

Commit

Permalink
Remove the workspace argument to various ECC interfaces
Browse files Browse the repository at this point in the history
This was a performance crutch for EC_Point and is no longer required.
  • Loading branch information
randombit committed Jan 15, 2025
1 parent 1afcdf2 commit 8704987
Show file tree
Hide file tree
Showing 24 changed files with 97 additions and 132 deletions.
6 changes: 2 additions & 4 deletions src/cli/perf_ec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ class PerfTest_EllipticCurve final : public PerfTest {
auto h2c_nu_timer = config.make_timer(group_name + " hash to curve (NU)");
auto h2c_ro_timer = config.make_timer(group_name + " hash to curve (RO)");

std::vector<Botan::BigInt> ws;

auto g = Botan::EC_AffinePoint::generator(group);

const bool h2c_supported = [&]() {
Expand All @@ -58,8 +56,8 @@ class PerfTest_EllipticCurve final : public PerfTest {

while(bp_timer->under(run) && vp_timer->under(run)) {
const auto k = Botan::EC_Scalar::random(group, rng);
const auto r1 = bp_timer->run([&]() { return Botan::EC_AffinePoint::g_mul(k, rng, ws); });
const auto r2 = vp_timer->run([&]() { return g.mul(k, rng, ws); });
const auto r1 = bp_timer->run([&]() { return Botan::EC_AffinePoint::g_mul(k, rng); });
const auto r2 = vp_timer->run([&]() { return g.mul(k, rng); });

const auto r1_bytes = r1.serialize_uncompressed();
const auto r2_bytes = r2.serialize_uncompressed();
Expand Down
6 changes: 2 additions & 4 deletions src/cli/timing_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,6 @@ class ECDSA_Timing_Test final : public Timing_Test {
const Botan::EC_Scalar m_x;
Botan::EC_Scalar m_b;
Botan::EC_Scalar m_b_inv;
std::vector<Botan::BigInt> m_ws;
};

ECDSA_Timing_Test::ECDSA_Timing_Test(const std::string& ecgroup) :
Expand All @@ -283,7 +282,7 @@ uint64_t ECDSA_Timing_Test::measure_critical_function(const std::vector<uint8_t>
TimingTestTimer timer;

// the following ECDSA operations involve and should not leak any information about k
const auto r = Botan::EC_Scalar::gk_x_mod_order(k, timing_test_rng(), m_ws);
const auto r = Botan::EC_Scalar::gk_x_mod_order(k, timing_test_rng());
const auto k_inv = k.invert();
m_b.square_self();
m_b_inv.square_self();
Expand All @@ -306,14 +305,13 @@ class ECC_Mul_Timing_Test final : public Timing_Test {

private:
const Botan::EC_Group m_group;
std::vector<Botan::BigInt> m_ws;
};

uint64_t ECC_Mul_Timing_Test::measure_critical_function(const std::vector<uint8_t>& input) {
const auto k = Botan::EC_Scalar::from_bytes_with_trunc(m_group, input);

TimingTestTimer timer;
const auto kG = Botan::EC_AffinePoint::g_mul(k, timing_test_rng(), m_ws);
const auto kG = Botan::EC_AffinePoint::g_mul(k, timing_test_rng());
return timer.complete();
}

Expand Down
14 changes: 6 additions & 8 deletions src/lib/pubkey/ec_group/ec_apoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,19 +133,17 @@ std::optional<EC_AffinePoint> EC_AffinePoint::deserialize(const EC_Group& group,
}
}

EC_AffinePoint EC_AffinePoint::g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws) {
auto pt = scalar._inner().group()->point_g_mul(scalar.inner(), rng, ws);
EC_AffinePoint EC_AffinePoint::g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng) {
auto pt = scalar._inner().group()->point_g_mul(scalar.inner(), rng);
return EC_AffinePoint(std::move(pt));
}

EC_AffinePoint EC_AffinePoint::mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws) const {
return EC_AffinePoint(inner().mul(scalar._inner(), rng, ws));
EC_AffinePoint EC_AffinePoint::mul(const EC_Scalar& scalar, RandomNumberGenerator& rng) const {
return EC_AffinePoint(inner().mul(scalar._inner(), rng));
}

secure_vector<uint8_t> EC_AffinePoint::mul_x_only(const EC_Scalar& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const {
return inner().mul_x_only(scalar._inner(), rng, ws);
secure_vector<uint8_t> EC_AffinePoint::mul_x_only(const EC_Scalar& scalar, RandomNumberGenerator& rng) const {
return inner().mul_x_only(scalar._inner(), rng);
}

std::optional<EC_AffinePoint> EC_AffinePoint::mul_px_qy(const EC_AffinePoint& p,
Expand Down
26 changes: 15 additions & 11 deletions src/lib/pubkey/ec_group/ec_apoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,13 @@ class BOTAN_UNSTABLE_API EC_AffinePoint final {
static std::optional<EC_AffinePoint> from_bigint_xy(const EC_Group& group, const BigInt& x, const BigInt& y);

/// Multiply by the group generator returning a complete point
///
/// Workspace argument is transitional
static EC_AffinePoint g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws);
static EC_AffinePoint g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng);

BOTAN_DEPRECATED("Use version without workspace arg")
static EC_AffinePoint g_mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws) {
BOTAN_UNUSED(ws);
return EC_AffinePoint::g_mul(scalar, rng);
}

/// Return the identity element
static EC_AffinePoint identity(const EC_Group& group);
Expand All @@ -78,16 +82,16 @@ class BOTAN_UNSTABLE_API EC_AffinePoint final {
std::span<const uint8_t> domain_sep);

/// Multiply a point by a scalar returning a complete point
///
/// Workspace argument is transitional
EC_AffinePoint mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws) const;
EC_AffinePoint mul(const EC_Scalar& scalar, RandomNumberGenerator& rng) const;

BOTAN_DEPRECATED("Use version without workspace arg")
EC_AffinePoint mul(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws) const {
BOTAN_UNUSED(ws);
return this->mul(scalar, rng);
}

/// Multiply a point by a scalar, returning the byte encoding of the x coordinate only
///
/// Workspace argument is transitional
secure_vector<uint8_t> mul_x_only(const EC_Scalar& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const;
secure_vector<uint8_t> mul_x_only(const EC_Scalar& scalar, RandomNumberGenerator& rng) const;

/// Compute 2-ary multiscalar multiplication - p*x + q*y
///
Expand Down
15 changes: 9 additions & 6 deletions src/lib/pubkey/ec_group/ec_group.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,14 +438,15 @@ class BOTAN_PUBLIC_API(2, 0) EC_Group final {
* Blinded point multiplication, attempts resistance to side channels
* @param k_bn the scalar
* @param rng a random number generator
* @param ws a temp workspace
* @param ws a (no longer used) temp workspace
* @return base_point*k
*/
BOTAN_DEPRECATED("Use EC_AffinePoint and EC_Scalar")
EC_Point
blinded_base_point_multiply(const BigInt& k_bn, RandomNumberGenerator& rng, std::vector<BigInt>& ws) const {
BOTAN_UNUSED(ws);
auto k = EC_Scalar::from_bigint(*this, k_bn);
auto pt = EC_AffinePoint::g_mul(k, rng, ws);
auto pt = EC_AffinePoint::g_mul(k, rng);
return pt.to_legacy_point();
}

Expand All @@ -455,32 +456,34 @@ class BOTAN_PUBLIC_API(2, 0) EC_Group final {
*
* @param k_bn the scalar
* @param rng a random number generator
* @param ws a temp workspace
* @param ws a (no longer used) temp workspace
* @return x coordinate of base_point*k
*/
BOTAN_DEPRECATED("Use EC_AffinePoint and EC_Scalar")
BigInt
blinded_base_point_multiply_x(const BigInt& k_bn, RandomNumberGenerator& rng, std::vector<BigInt>& ws) const {
BOTAN_UNUSED(ws);
auto k = EC_Scalar::from_bigint(*this, k_bn);
return BigInt(EC_AffinePoint::g_mul(k, rng, ws).x_bytes());
return BigInt(EC_AffinePoint::g_mul(k, rng).x_bytes());
}

/**
* Blinded point multiplication, attempts resistance to side channels
* @param point input point
* @param k_bn the scalar
* @param rng a random number generator
* @param ws a temp workspace
* @param ws a (no longer used) temp workspace
* @return point*k
*/
BOTAN_DEPRECATED("Use EC_AffinePoint and EC_Scalar")
EC_Point blinded_var_point_multiply(const EC_Point& point,
const BigInt& k_bn,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const {
BOTAN_UNUSED(ws);
auto k = EC_Scalar::from_bigint(*this, k_bn);
auto pt = EC_AffinePoint(*this, point);
return pt.mul(k, rng, ws).to_legacy_point();
return pt.mul(k, rng).to_legacy_point();
}

/**
Expand Down
10 changes: 4 additions & 6 deletions src/lib/pubkey/ec_group/ec_inner_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,7 @@ std::unique_ptr<EC_Scalar_Data> EC_Group_Data::scalar_from_bigint(const BigInt&
}

std::unique_ptr<EC_Scalar_Data> EC_Group_Data::gk_x_mod_order(const EC_Scalar_Data& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const {
RandomNumberGenerator& rng) const {
if(m_pcurve) {
const auto& k = EC_Scalar_Data_PC::checked_ref(scalar);
auto gk_x_mod_order = m_pcurve->base_point_mul_x_mod_order(k.value(), rng);
Expand All @@ -232,6 +231,7 @@ std::unique_ptr<EC_Scalar_Data> EC_Group_Data::gk_x_mod_order(const EC_Scalar_Da
#if defined(BOTAN_HAS_LEGACY_EC_POINT)
const auto& k = EC_Scalar_Data_BN::checked_ref(scalar);
BOTAN_STATE_CHECK(m_base_mult != nullptr);
std::vector<BigInt> ws;
const auto pt = m_base_mult->mul(k.value(), rng, m_order, ws);

if(pt.is_zero()) {
Expand All @@ -240,7 +240,6 @@ std::unique_ptr<EC_Scalar_Data> EC_Group_Data::gk_x_mod_order(const EC_Scalar_Da
return std::make_unique<EC_Scalar_Data_BN>(shared_from_this(), mod_order(pt.get_affine_x()));
}
#else
BOTAN_UNUSED(ws);
throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
#endif
}
Expand Down Expand Up @@ -315,8 +314,7 @@ std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_hash_to_curve_nu(std::
}

std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_g_mul(const EC_Scalar_Data& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const {
RandomNumberGenerator& rng) const {
if(m_pcurve) {
const auto& k = EC_Scalar_Data_PC::checked_ref(scalar);
auto pt = m_pcurve->mul_by_g(k.value(), rng).to_affine();
Expand All @@ -327,10 +325,10 @@ std::unique_ptr<EC_AffinePoint_Data> EC_Group_Data::point_g_mul(const EC_Scalar_
const auto& bn = EC_Scalar_Data_BN::checked_ref(scalar);

BOTAN_STATE_CHECK(group->m_base_mult != nullptr);
std::vector<BigInt> ws;
auto pt = group->m_base_mult->mul(bn.value(), rng, m_order, ws);
return std::make_unique<EC_AffinePoint_Data_BN>(shared_from_this(), std::move(pt));
#else
BOTAN_UNUSED(ws);
throw Not_Implemented("Legacy EC interfaces disabled in this build configuration");
#endif
}
Expand Down
15 changes: 4 additions & 11 deletions src/lib/pubkey/ec_group/ec_inner_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,9 @@ class EC_AffinePoint_Data {
virtual void serialize_uncompressed_to(std::span<uint8_t> bytes) const = 0;

virtual std::unique_ptr<EC_AffinePoint_Data> mul(const EC_Scalar_Data& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const = 0;
RandomNumberGenerator& rng) const = 0;

virtual secure_vector<uint8_t> mul_x_only(const EC_Scalar_Data& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const = 0;
virtual secure_vector<uint8_t> mul_x_only(const EC_Scalar_Data& scalar, RandomNumberGenerator& rng) const = 0;

#if defined(BOTAN_HAS_LEGACY_EC_POINT)
virtual EC_Point to_legacy_point() const = 0;
Expand Down Expand Up @@ -244,9 +241,7 @@ class EC_Group_Data final : public std::enable_shared_from_this<EC_Group_Data> {

std::unique_ptr<EC_Scalar_Data> scalar_one() const;

std::unique_ptr<EC_Scalar_Data> gk_x_mod_order(const EC_Scalar_Data& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const;
std::unique_ptr<EC_Scalar_Data> gk_x_mod_order(const EC_Scalar_Data& scalar, RandomNumberGenerator& rng) const;

/// Deserialize a point
///
Expand All @@ -261,9 +256,7 @@ class EC_Group_Data final : public std::enable_shared_from_this<EC_Group_Data> {
std::span<const uint8_t> input,
std::span<const uint8_t> domain_sep) const;

std::unique_ptr<EC_AffinePoint_Data> point_g_mul(const EC_Scalar_Data& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const;
std::unique_ptr<EC_AffinePoint_Data> point_g_mul(const EC_Scalar_Data& scalar, RandomNumberGenerator& rng) const;

std::unique_ptr<EC_AffinePoint_Data> mul_px_qy(const EC_AffinePoint_Data& p,
const EC_Scalar_Data& x,
Expand Down
10 changes: 2 additions & 8 deletions src/lib/pubkey/ec_group/ec_inner_pc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,21 +118,15 @@ const std::shared_ptr<const EC_Group_Data>& EC_AffinePoint_Data_PC::group() cons
}

std::unique_ptr<EC_AffinePoint_Data> EC_AffinePoint_Data_PC::mul(const EC_Scalar_Data& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const {
BOTAN_UNUSED(ws);

RandomNumberGenerator& rng) const {
BOTAN_ARG_CHECK(scalar.group() == m_group, "Curve mismatch");
const auto& k = EC_Scalar_Data_PC::checked_ref(scalar).value();
auto pt = m_group->pcurve().mul(m_pt, k, rng).to_affine();
return std::make_unique<EC_AffinePoint_Data_PC>(m_group, std::move(pt));
}

secure_vector<uint8_t> EC_AffinePoint_Data_PC::mul_x_only(const EC_Scalar_Data& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const {
BOTAN_UNUSED(ws);

RandomNumberGenerator& rng) const {
BOTAN_ARG_CHECK(scalar.group() == m_group, "Curve mismatch");
const auto& k = EC_Scalar_Data_PC::checked_ref(scalar).value();
return m_group->pcurve().mul_x_only(m_pt, k, rng);
Expand Down
8 changes: 2 additions & 6 deletions src/lib/pubkey/ec_group/ec_inner_pc.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,9 @@ class EC_AffinePoint_Data_PC final : public EC_AffinePoint_Data {

void serialize_uncompressed_to(std::span<uint8_t> bytes) const override;

std::unique_ptr<EC_AffinePoint_Data> mul(const EC_Scalar_Data& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const override;
std::unique_ptr<EC_AffinePoint_Data> mul(const EC_Scalar_Data& scalar, RandomNumberGenerator& rng) const override;

secure_vector<uint8_t> mul_x_only(const EC_Scalar_Data& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const override;
secure_vector<uint8_t> mul_x_only(const EC_Scalar_Data& scalar, RandomNumberGenerator& rng) const override;

const PCurve::PrimeOrderCurve::AffinePoint& value() const { return m_pt; }

Expand Down
4 changes: 2 additions & 2 deletions src/lib/pubkey/ec_group/ec_scalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ BigInt EC_Scalar::to_bigint() const {
return BigInt::from_bytes(bytes);
}

EC_Scalar EC_Scalar::gk_x_mod_order(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws) {
EC_Scalar EC_Scalar::gk_x_mod_order(const EC_Scalar& scalar, RandomNumberGenerator& rng) {
const auto& group = scalar._inner().group();
return EC_Scalar(group->gk_x_mod_order(scalar.inner(), rng, ws));
return EC_Scalar(group->gk_x_mod_order(scalar.inner(), rng));
}

void EC_Scalar::serialize_to(std::span<uint8_t> bytes) const {
Expand Down
10 changes: 7 additions & 3 deletions src/lib/pubkey/ec_group/ec_scalar.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,14 @@ class BOTAN_UNSTABLE_API EC_Scalar final {
* Compute the elliptic curve scalar multiplication (g*k) where g is the
* standard base point on the curve. Then extract the x coordinate of
* the resulting point, and reduce it modulo the group order.
*
* Workspace argument is transitional
*/
static EC_Scalar gk_x_mod_order(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws);
static EC_Scalar gk_x_mod_order(const EC_Scalar& scalar, RandomNumberGenerator& rng);

BOTAN_DEPRECATED("Use version without workspace arg")
static EC_Scalar gk_x_mod_order(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws) {
BOTAN_UNUSED(ws);
return EC_Scalar::gk_x_mod_order(scalar, rng);
}

/**
* Return the byte size of this scalar
Expand Down
8 changes: 4 additions & 4 deletions src/lib/pubkey/ec_group/legacy_ec_point/ec_inner_bn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@ const std::shared_ptr<const EC_Group_Data>& EC_AffinePoint_Data_BN::group() cons
}

std::unique_ptr<EC_AffinePoint_Data> EC_AffinePoint_Data_BN::mul(const EC_Scalar_Data& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const {
RandomNumberGenerator& rng) const {
BOTAN_ARG_CHECK(scalar.group() == m_group, "Curve mismatch");
const auto& bn = EC_Scalar_Data_BN::checked_ref(scalar);

std::vector<BigInt> ws;
EC_Point_Var_Point_Precompute mul(m_pt, rng, ws);

// We pass order*cofactor here to "correctly" handle the case where the
Expand All @@ -114,11 +114,11 @@ std::unique_ptr<EC_AffinePoint_Data> EC_AffinePoint_Data_BN::mul(const EC_Scalar
}

secure_vector<uint8_t> EC_AffinePoint_Data_BN::mul_x_only(const EC_Scalar_Data& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const {
RandomNumberGenerator& rng) const {
BOTAN_ARG_CHECK(scalar.group() == m_group, "Curve mismatch");
const auto& bn = EC_Scalar_Data_BN::checked_ref(scalar);

std::vector<BigInt> ws;
EC_Point_Var_Point_Precompute mul(m_pt, rng, ws);

// We pass order*cofactor here to "correctly" handle the case where the
Expand Down
8 changes: 2 additions & 6 deletions src/lib/pubkey/ec_group/legacy_ec_point/ec_inner_bn.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,9 @@ class EC_AffinePoint_Data_BN final : public EC_AffinePoint_Data {

void serialize_uncompressed_to(std::span<uint8_t> bytes) const override;

std::unique_ptr<EC_AffinePoint_Data> mul(const EC_Scalar_Data& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const override;
std::unique_ptr<EC_AffinePoint_Data> mul(const EC_Scalar_Data& scalar, RandomNumberGenerator& rng) const override;

secure_vector<uint8_t> mul_x_only(const EC_Scalar_Data& scalar,
RandomNumberGenerator& rng,
std::vector<BigInt>& ws) const override;
secure_vector<uint8_t> mul_x_only(const EC_Scalar_Data& scalar, RandomNumberGenerator& rng) const override;

EC_Point to_legacy_point() const override { return m_pt; }

Expand Down
5 changes: 2 additions & 3 deletions src/lib/pubkey/ecc_key/ec_key_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,10 @@ EC_PrivateKey_Data::EC_PrivateKey_Data(EC_Group group, std::span<const uint8_t>
std::shared_ptr<EC_PublicKey_Data> EC_PrivateKey_Data::public_key(RandomNumberGenerator& rng,
bool with_modular_inverse) const {
auto public_point = [&] {
std::vector<BigInt> ws;
if(with_modular_inverse) {
return EC_AffinePoint::g_mul(m_scalar.invert(), rng, ws);
return EC_AffinePoint::g_mul(m_scalar.invert(), rng);
} else {
return EC_AffinePoint::g_mul(m_scalar, rng, ws);
return EC_AffinePoint::g_mul(m_scalar, rng);
}
};

Expand Down
Loading

0 comments on commit 8704987

Please sign in to comment.