Skip to content

Commit

Permalink
Some EC_Group usage cleanups
Browse files Browse the repository at this point in the history
This hides all symbols of CurveGFp and CurveGFp_Repr (which were
already marked as BOTAN_UNSTABLE_API and intentionally undocumented)
and makes them accessible only to a few specific friends.

For EC_Point deprecate a number of functions only needed for internal
use. Also add a couple of functions to simplify a future bridge
between our current APIs and pcurves.

In EC_Group likewise begin some cleanup and deprecation.
  • Loading branch information
randombit committed May 2, 2024
1 parent 4af65b1 commit abe0e42
Show file tree
Hide file tree
Showing 50 changed files with 505 additions and 448 deletions.
59 changes: 15 additions & 44 deletions doc/api_ref/ecc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ during common operations.
Initialize an elliptic curve group from the relevant parameters. This
is used for example to create custom (application-specific) curves.

.. warning::

Currently a cofactor > 1 is accepted. In the future only prime order
subgroups will be allowed.

.. warning::

Currently primes of any size may be provided. In the
future the prime will be allowed to be at most 521 bits.

.. cpp:function:: EC_Group(const std::vector<uint8_t>& ber_encoding)

Initialize an ``EC_Group`` by decoding a DER encoded parameter block.
Expand All @@ -52,14 +62,6 @@ during common operations.
Return the PEM encoding of this group (base64 of DER encoding plus
header/trailer).

.. cpp:function:: bool a_is_minus_3() const

Return true if the ``a`` parameter is congruent to -3 mod p.

.. cpp:function:: bool a_is_zero() const

Return true if the ``a`` parameter is congruent to 0 mod p.

.. cpp:function:: size_t get_p_bits() const

Return size of the prime in bits.
Expand Down Expand Up @@ -108,6 +110,11 @@ during common operations.

Return the cofactor of the curve. In most cases this will be 1.

.. warning::

In a future release all support for elliptic curves group with
a cofactor > 1 will be removed.

.. cpp:function:: BigInt mod_order(const BigInt& x) const

Reduce argument ``x`` modulo the curve order.
Expand Down Expand Up @@ -246,39 +253,3 @@ during common operations.
.. cpp:function:: bool operator==(const EC_Point& other) const

Point equality. This compares the affine representations.

.. cpp:function:: void add(const EC_Point& other, std::vector<BigInt>& workspace)

Point addition, taking a workspace.

.. cpp:function:: void add_affine(const EC_Point& other, std::vector<BigInt>& workspace)

Mixed (Jacobian+affine) addition, taking a workspace.

.. warning::

This function assumes that ``other`` is affine, if this is
not correct the result will be invalid.

.. cpp:function:: void mult2(std::vector<BigInt>& workspace)

Point doubling.

.. cpp:function:: void mult2i(size_t i, std::vector<BigInt>& workspace)

Repeated point doubling.

.. cpp:function:: EC_Point plus(const EC_Point& other, std::vector<BigInt>& workspace) const

Point addition, returning the result.

.. cpp:function:: EC_Point double_of(std::vector<BigInt>& workspace) const

Point doubling, returning the result.

.. cpp:function:: EC_Point zero() const

Return the point at infinity



5 changes: 5 additions & 0 deletions doc/deprecated.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ in a future major release.
format is quite obscure and seemingly rarely implemented. Support
for this encoding will be removed in a future release.

- Currently `EC_Point` offers a wide variety of functionality almost
all of which was intended only for internal implementation. In a
future release, the only operations available for EC_Points will be
to extract the byte encoding of their affine x and y coordinates.

- Currently it is possible to create an EC_Group with cofactor > 1.
None of the builtin groups have composite order, and in the future
it will be impossible to create composite order EC_Groups.
Expand Down
2 changes: 1 addition & 1 deletion src/cli/pubkey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ class EC_Group_Info final : public Command {
}

void go() override {
Botan::EC_Group ec_group(get_arg("name"));
const auto ec_group = Botan::EC_Group::from_name(get_arg("name"));

if(flag_set("pem")) {
output() << ec_group.PEM_encode();
Expand Down
41 changes: 5 additions & 36 deletions src/cli/speed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -712,8 +712,6 @@ class Speed final : public Command {
#if defined(BOTAN_HAS_ECC_GROUP)
else if(algo == "ecc_mult") {
bench_ecc_mult(ecc_groups, msec);
} else if(algo == "ecc_ops") {
bench_ecc_ops(ecc_groups, msec);
} else if(algo == "ecc_init") {
bench_ecc_init(ecc_groups, msec);
} else if(algo == "os2ecp") {
Expand Down Expand Up @@ -1074,42 +1072,13 @@ class Speed final : public Command {
}

#if defined(BOTAN_HAS_ECC_GROUP)
void bench_ecc_ops(const std::vector<std::string>& groups, const std::chrono::milliseconds runtime) {
for(const std::string& group_name : groups) {
const Botan::EC_Group ec_group(group_name);

auto add_timer = make_timer(group_name + " add");
auto addf_timer = make_timer(group_name + " addf");
auto dbl_timer = make_timer(group_name + " dbl");

const Botan::EC_Point& base_point = ec_group.get_base_point();

// create a non-affine point
const auto random_k = Botan::BigInt::from_u64(0x4E6F537465707E);
Botan::EC_Point non_affine_pt = ec_group.get_base_point() * random_k;
Botan::EC_Point pt = ec_group.get_base_point();

std::vector<Botan::BigInt> ws(Botan::EC_Point::WORKSPACE_SIZE);

while(add_timer->under(runtime) && addf_timer->under(runtime) && dbl_timer->under(runtime)) {
dbl_timer->run([&]() { pt.mult2(ws); });
add_timer->run([&]() { pt.add(non_affine_pt, ws); });
addf_timer->run([&]() { pt.add_affine(base_point, ws); });
}

record_result(dbl_timer);
record_result(add_timer);
record_result(addf_timer);
}
}

void bench_ecc_init(const std::vector<std::string>& groups, const std::chrono::milliseconds runtime) {
for(std::string group_name : groups) {
auto timer = make_timer(group_name + " initialization");

while(timer->under(runtime)) {
Botan::EC_Group::clear_registered_curve_data();
timer->run([&]() { Botan::EC_Group group(group_name); });
timer->run([&]() { Botan::EC_Group::from_name(group_name); });
}

record_result(timer);
Expand All @@ -1118,7 +1087,7 @@ class Speed final : public Command {

void bench_ecc_mult(const std::vector<std::string>& groups, const std::chrono::milliseconds runtime) {
for(const std::string& group_name : groups) {
const Botan::EC_Group ec_group(group_name);
const auto ec_group = Botan::EC_Group::from_name(group_name);

auto mult_timer = make_timer(group_name + " Montgomery ladder");
auto blinded_mult_timer = make_timer(group_name + " blinded comb");
Expand Down Expand Up @@ -1155,7 +1124,7 @@ class Speed final : public Command {
auto uncmp_timer = make_timer("OS2ECP uncompressed " + group_name);
auto cmp_timer = make_timer("OS2ECP compressed " + group_name);

const Botan::EC_Group ec_group(group_name);
const auto ec_group = Botan::EC_Group::from_name(group_name);

while(uncmp_timer->under(runtime) && cmp_timer->under(runtime)) {
const Botan::BigInt k(rng(), 256);
Expand All @@ -1180,7 +1149,7 @@ class Speed final : public Command {
auto h2c_ro_timer = make_timer(group_name + "-RO", "", "hash to curve");
auto h2c_nu_timer = make_timer(group_name + "-NU", "", "hash to curve");

const Botan::EC_Group group(group_name);
const auto group = Botan::EC_Group::from_name(group_name);

while(h2c_ro_timer->under(runtime)) {
std::vector<uint8_t> input(32);
Expand Down Expand Up @@ -1793,7 +1762,7 @@ class Speed final : public Command {
const std::string& /*unused*/,
std::chrono::milliseconds msec) {
for(const std::string& group_name : groups) {
Botan::EC_Group group(group_name);
const auto group = Botan::EC_Group::from_name(group_name);
auto recovery_timer = make_timer("ECDSA recovery " + group_name);

while(recovery_timer->under(msec)) {
Expand Down
6 changes: 4 additions & 2 deletions src/cli/timing_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,9 @@ class ECDSA_Timing_Test final : public Timing_Test {
};

ECDSA_Timing_Test::ECDSA_Timing_Test(const std::string& ecgroup) :
m_group(ecgroup), m_privkey(timing_test_rng(), m_group), m_x(m_privkey.private_value()) {
m_group(Botan::EC_Group::from_name(ecgroup)),
m_privkey(timing_test_rng(), m_group),
m_x(m_privkey.private_value()) {
m_b = m_group.random_scalar(timing_test_rng());
m_b_inv = m_group.inverse_mod_order(m_b);
}
Expand Down Expand Up @@ -296,7 +298,7 @@ ticks ECDSA_Timing_Test::measure_critical_function(const std::vector<uint8_t>& i

class ECC_Mul_Timing_Test final : public Timing_Test {
public:
explicit ECC_Mul_Timing_Test(const std::string& ecgroup) : m_group(ecgroup) {}
explicit ECC_Mul_Timing_Test(const std::string& ecgroup) : m_group(Botan::EC_Group::from_name(ecgroup)) {}

ticks measure_critical_function(const std::vector<uint8_t>& input) override;

Expand Down
2 changes: 1 addition & 1 deletion src/examples/ecdh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ int main() {
Botan::AutoSeeded_RNG rng;

// ec domain and KDF
Botan::EC_Group domain("secp521r1");
const auto domain = Botan::EC_Group::from_name("secp521r1");
const std::string kdf = "KDF2(SHA-256)";

// the two parties generate ECDH keys
Expand Down
3 changes: 2 additions & 1 deletion src/examples/ecdsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
int main() {
Botan::AutoSeeded_RNG rng;
// Generate ECDSA keypair
Botan::ECDSA_PrivateKey key(rng, Botan::EC_Group("secp521r1"));
const auto group = Botan::EC_Group::from_name("secp521r1");
Botan::ECDSA_PrivateKey key(rng, group);

const std::string message("This is a tasty burger!");

Expand Down
6 changes: 3 additions & 3 deletions src/examples/pkcs11_ecdh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ int main() {
Botan::AutoSeeded_RNG rng;

// create private key in software
Botan::ECDH_PrivateKey priv_key_sw(rng, Botan::EC_Group("secp256r1"));
Botan::ECDH_PrivateKey priv_key_sw(rng, Botan::EC_Group::from_name("secp256r1"));
priv_key_sw.set_parameter_encoding(Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID);

// set import properties
Expand Down Expand Up @@ -81,13 +81,13 @@ int main() {

Botan::PKCS11::PKCS11_ECDH_PrivateKey priv_key2(
session,
Botan::EC_Group("secp256r1").DER_encode(Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID),
Botan::EC_Group::from_name("secp256r1").DER_encode(Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID),
priv_generate_props);

/************ generate ECDH key pair *************/

Botan::PKCS11::EC_PublicKeyGenerationProperties pub_generate_props(
Botan::EC_Group("secp256r1").DER_encode(Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID));
Botan::EC_Group::from_name("secp256r1").DER_encode(Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID));

pub_generate_props.set_label(label + "_PUB_KEY");
pub_generate_props.set_token(true);
Expand Down
6 changes: 3 additions & 3 deletions src/examples/pkcs11_ecdsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ int main() {
// create private key in software
Botan::AutoSeeded_RNG rng;

Botan::ECDSA_PrivateKey priv_key_sw(rng, Botan::EC_Group("secp256r1"));
Botan::ECDSA_PrivateKey priv_key_sw(rng, Botan::EC_Group::from_name("secp256r1"));
priv_key_sw.set_parameter_encoding(Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID);

// set the private key import properties
Expand Down Expand Up @@ -78,13 +78,13 @@ int main() {

Botan::PKCS11::PKCS11_ECDSA_PrivateKey pk(
session,
Botan::EC_Group("secp256r1").DER_encode(Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID),
Botan::EC_Group::from_name("secp256r1").DER_encode(Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID),
priv_generate_props);

/************ generate PKCS#11 ECDSA key pair *************/

Botan::PKCS11::EC_PublicKeyGenerationProperties pub_generate_props(
Botan::EC_Group("secp256r1").DER_encode(Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID));
Botan::EC_Group::from_name("secp256r1").DER_encode(Botan::EC_Group_Encoding::EC_DOMPAR_ENC_OID));

pub_generate_props.set_label("BOTAN_TEST_ECDSA_PUB_KEY");
pub_generate_props.set_token(true);
Expand Down
6 changes: 4 additions & 2 deletions src/examples/tls_custom_curves_client.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#define BOTAN_NO_DEPRECATED_WARNINGS

#include <botan/auto_rng.h>
#include <botan/certstor.h>
#include <botan/ecdh.h>
Expand Down Expand Up @@ -34,7 +36,7 @@ class Callbacks : public Botan::TLS::Callbacks {
if(std::holds_alternative<Botan::TLS::Group_Params>(group) &&
std::get<Botan::TLS::Group_Params>(group) == Botan::TLS::Group_Params(0xFE00)) {
// generate a private key of my custom curve
const Botan::EC_Group ec_group("testcurve1102");
const auto ec_group = Botan::EC_Group::from_name("testcurve1102");
return std::make_unique<Botan::ECDH_PrivateKey>(rng, ec_group);
} else {
// no custom curve used: up-call the default implementation
Expand All @@ -51,7 +53,7 @@ class Callbacks : public Botan::TLS::Callbacks {
if(std::holds_alternative<Botan::TLS::Group_Params>(group) &&
std::get<Botan::TLS::Group_Params>(group) == Botan::TLS::Group_Params(0xFE00)) {
// perform a key agreement on my custom curve
const Botan::EC_Group ec_group("testcurve1102");
const auto ec_group = Botan::EC_Group::from_name("testcurve1102");
Botan::ECDH_PublicKey peer_key(ec_group, ec_group.OS2ECP(public_value));
Botan::PK_Key_Agreement ka(private_key, rng, "Raw");
return ka.derive_key(0, peer_key.public_value()).bits_of();
Expand Down
4 changes: 2 additions & 2 deletions src/lib/ffi/ffi_pkey_algs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ int privkey_load_ec(std::unique_ptr<ECPrivateKey_t>& key, const Botan::BigInt& s
}

Botan::Null_RNG null_rng;
Botan::EC_Group grp(curve_name);
const auto grp = Botan::EC_Group::from_name(curve_name);
key.reset(new ECPrivateKey_t(null_rng, grp, scalar));
return BOTAN_FFI_SUCCESS;
}
Expand All @@ -102,7 +102,7 @@ int pubkey_load_ec(std::unique_ptr<ECPublicKey_t>& key,
return BOTAN_FFI_ERROR_NULL_POINTER;
}

Botan::EC_Group grp(curve_name);
const auto grp = Botan::EC_Group::from_name(curve_name);
Botan::EC_Point uncompressed_point = grp.point(public_x, public_y);
key.reset(new ECPublicKey_t(grp, uncompressed_point));
return BOTAN_FFI_SUCCESS;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/prov/pkcs11/p11_ecc_key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ PKCS11_EC_PrivateKey::PKCS11_EC_PrivateKey(Session& session,
}

size_t PKCS11_EC_PrivateKey::key_length() const {
return m_domain_params.get_order().bits();
return m_domain_params.get_order_bits();
}

std::vector<uint8_t> PKCS11_EC_PrivateKey::public_key_bits() const {
Expand Down
8 changes: 3 additions & 5 deletions src/lib/prov/pkcs11/p11_ecdsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class PKCS11_ECDSA_Signature_Operation final : public PK_Ops::Signature {
PKCS11_ECDSA_Signature_Operation(const PKCS11_ECDSA_PrivateKey& key, std::string_view hash) :
PK_Ops::Signature(),
m_key(key),
m_order(key.domain().get_order()),
m_order_bytes(key.domain().get_order_bytes()),
m_mechanism(MechanismWrapper::create_ecdsa_mechanism(hash)),
m_hash(hash) {}

Expand Down Expand Up @@ -92,15 +92,15 @@ class PKCS11_ECDSA_Signature_Operation final : public PK_Ops::Signature {
return signature;
}

size_t signature_length() const override { return 2 * m_order.bytes(); }
size_t signature_length() const override { return 2 * m_order_bytes; }

AlgorithmIdentifier algorithm_identifier() const override;

std::string hash_function() const override { return m_hash; }

private:
const PKCS11_ECDSA_PrivateKey m_key;
const BigInt m_order;
const size_t m_order_bytes;
MechanismWrapper m_mechanism;
const std::string m_hash;
secure_vector<uint8_t> m_first_message;
Expand All @@ -118,7 +118,6 @@ class PKCS11_ECDSA_Verification_Operation final : public PK_Ops::Verification {
PKCS11_ECDSA_Verification_Operation(const PKCS11_ECDSA_PublicKey& key, std::string_view hash) :
PK_Ops::Verification(),
m_key(key),
m_order(key.domain().get_order()),
m_mechanism(MechanismWrapper::create_ecdsa_mechanism(hash)),
m_hash(hash) {}

Expand Down Expand Up @@ -166,7 +165,6 @@ class PKCS11_ECDSA_Verification_Operation final : public PK_Ops::Verification {

private:
const PKCS11_ECDSA_PublicKey m_key;
const BigInt m_order;
MechanismWrapper m_mechanism;
const std::string m_hash;
secure_vector<uint8_t> m_first_message;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/prov/pkcs11/p11_ecdsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class BOTAN_PUBLIC_API(2, 0) PKCS11_ECDSA_PrivateKey final : public PKCS11_EC_Pr

size_t message_parts() const override { return 2; }

size_t message_part_size() const override { return domain().get_order().bytes(); }
size_t message_part_size() const override { return domain().get_order_bytes(); }

/// @return the exported ECDSA private key
ECDSA_PrivateKey export_key() const;
Expand Down

0 comments on commit abe0e42

Please sign in to comment.