aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-02-01 13:20:40 -0500
committerJack Lloyd <[email protected]>2018-02-01 13:20:40 -0500
commite70879bf0f3c1705cd6d4f0b4cef1f5d990c5b51 (patch)
tree1b3c344250cd0def213afb0b58c5ed1f9dc5b0d8 /src
parent0c84944402d03436c6982b370ace2d519add9751 (diff)
parent5213f9a5ed5c39b28d5226183231cf1121c59235 (diff)
Merge GH #1435 Use shared_ptr representation for EC_Group
Diffstat (limited to 'src')
-rw-r--r--src/cli/pubkey.cpp6
-rw-r--r--src/cli/speed.cpp7
-rw-r--r--src/fuzzer/os2ecp.cpp2
-rw-r--r--src/lib/ffi/ffi_pkey_algs.cpp8
-rw-r--r--src/lib/prov/pkcs11/p11_ecc_key.cpp10
-rw-r--r--src/lib/pubkey/ec_group/ec_group.cpp311
-rw-r--r--src/lib/pubkey/ec_group/ec_group.h128
-rw-r--r--src/lib/pubkey/ecc_key/ecc_key.cpp19
-rw-r--r--src/lib/pubkey/ecc_key/info.txt1
-rw-r--r--src/lib/pubkey/ecdh/ecdh.cpp18
-rw-r--r--src/lib/pubkey/ecies/ecies.cpp13
-rw-r--r--src/lib/pubkey/gost_3410/gost_3410.cpp4
-rw-r--r--src/lib/pubkey/sm2/sm2.cpp6
-rw-r--r--src/lib/pubkey/sm2/sm2_enc.cpp6
-rw-r--r--src/lib/tls/tls_callbacks.cpp2
-rw-r--r--src/tests/test_ecdsa.cpp2
-rw-r--r--src/tests/test_ecies.cpp5
-rw-r--r--src/tests/test_gost_3410.cpp2
-rw-r--r--src/tests/test_sm2.cpp8
-rw-r--r--src/tests/unit_ecc.cpp140
-rw-r--r--src/tests/unit_ecdsa.cpp28
21 files changed, 480 insertions, 246 deletions
diff --git a/src/cli/pubkey.cpp b/src/cli/pubkey.cpp
index ffe1470dc..0e515d2ea 100644
--- a/src/cli/pubkey.cpp
+++ b/src/cli/pubkey.cpp
@@ -340,9 +340,9 @@ class EC_Group_Info final : public Command
}
else
{
- output() << "P = " << std::hex << group.get_curve().get_p() << "\n"
- << "A = " << std::hex << group.get_curve().get_a() << "\n"
- << "B = " << std::hex << group.get_curve().get_b() << "\n"
+ output() << "P = " << std::hex << group.get_p() << "\n"
+ << "A = " << std::hex << group.get_a() << "\n"
+ << "B = " << std::hex << group.get_b() << "\n"
<< "G = " << group.get_base_point().get_affine_x() << ","
<< group.get_base_point().get_affine_y() << "\n";
}
diff --git a/src/cli/speed.cpp b/src/cli/speed.cpp
index 04b8cc3ff..7dbc7922c 100644
--- a/src/cli/speed.cpp
+++ b/src/cli/speed.cpp
@@ -1215,7 +1215,7 @@ class Speed final : public Command
Timer mult_timer(group_name + " scalar mult");
Timer blinded_mult_timer(group_name + " blinded scalar mult");
- const Botan::BigInt scalar(rng(), group.get_curve().get_p().bits());
+ const Botan::BigInt scalar(rng(), group.get_p_bits());
const Botan::PointGFp& base_point = group.get_base_point();
Botan::Blinded_Point_Multiply scalar_mult(base_point, group.get_order(), 4);
@@ -1242,7 +1242,6 @@ class Speed final : public Command
for(std::string group_name : groups)
{
const Botan::EC_Group group(group_name);
- const Botan::CurveGFp& curve = group.get_curve();
while(uncmp_timer.under(runtime) && cmp_timer.under(runtime))
{
@@ -1251,8 +1250,8 @@ class Speed final : public Command
const Botan::secure_vector<uint8_t> os_cmp = Botan::EC2OSP(p, Botan::PointGFp::COMPRESSED);
const Botan::secure_vector<uint8_t> os_uncmp = Botan::EC2OSP(p, Botan::PointGFp::UNCOMPRESSED);
- uncmp_timer.run([&]() { OS2ECP(os_uncmp, curve); });
- cmp_timer.run([&]() { OS2ECP(os_cmp, curve); });
+ uncmp_timer.run([&]() { group.OS2ECP(os_uncmp); });
+ cmp_timer.run([&]() { group.OS2ECP(os_cmp); });
}
record_result(uncmp_timer);
diff --git a/src/fuzzer/os2ecp.cpp b/src/fuzzer/os2ecp.cpp
index dba6dbdfe..cb4a50b47 100644
--- a/src/fuzzer/os2ecp.cpp
+++ b/src/fuzzer/os2ecp.cpp
@@ -13,7 +13,7 @@ void check_os2ecp(const Botan::EC_Group& group, const uint8_t in[], size_t len)
{
try
{
- Botan::PointGFp point = Botan::OS2ECP(in, len, group.get_curve());
+ Botan::PointGFp point = group.OS2ECP(in, len);
}
catch(Botan::Exception& e) {}
}
diff --git a/src/lib/ffi/ffi_pkey_algs.cpp b/src/lib/ffi/ffi_pkey_algs.cpp
index a20d7de40..7091708a8 100644
--- a/src/lib/ffi/ffi_pkey_algs.cpp
+++ b/src/lib/ffi/ffi_pkey_algs.cpp
@@ -96,7 +96,7 @@ int pubkey_load_ec(std::unique_ptr<ECPublicKey_t>& key,
return BOTAN_FFI_ERROR_NULL_POINTER;
Botan::EC_Group grp(curve_name);
- Botan::PointGFp uncompressed_point(grp.get_curve(), public_x, public_y);
+ Botan::PointGFp uncompressed_point = grp.point(public_x, public_y);
key.reset(new ECPublicKey_t(grp, uncompressed_point));
return BOTAN_FFI_SUCCESS;
}
@@ -149,11 +149,11 @@ Botan::BigInt pubkey_get_field(const Botan::Public_Key& key,
else if(field == "base_y")
return ecc->domain().get_base_point().get_affine_y();
else if(field == "p")
- return ecc->domain().get_curve().get_p();
+ return ecc->domain().get_p();
else if(field == "a")
- return ecc->domain().get_curve().get_a();
+ return ecc->domain().get_a();
else if(field == "b")
- return ecc->domain().get_curve().get_b();
+ return ecc->domain().get_b();
else if(field == "cofactor")
return ecc->domain().get_cofactor();
else if(field == "order")
diff --git a/src/lib/prov/pkcs11/p11_ecc_key.cpp b/src/lib/prov/pkcs11/p11_ecc_key.cpp
index df55b9ffb..3a0fa6350 100644
--- a/src/lib/prov/pkcs11/p11_ecc_key.cpp
+++ b/src/lib/prov/pkcs11/p11_ecc_key.cpp
@@ -17,11 +17,11 @@ namespace Botan {
namespace PKCS11 {
namespace {
/// Converts a DER-encoded ANSI X9.62 ECPoint to PointGFp
-PointGFp decode_public_point(const secure_vector<uint8_t>& ec_point_data, const CurveGFp& curve)
+PointGFp decode_public_point(const secure_vector<uint8_t>& ec_point_data, const EC_Group& group)
{
secure_vector<uint8_t> ec_point;
BER_Decoder(ec_point_data).decode(ec_point, OCTET_STRING);
- return OS2ECP(ec_point, curve);
+ return group.OS2ECP(ec_point);
}
}
@@ -44,7 +44,7 @@ PKCS11_EC_PublicKey::PKCS11_EC_PublicKey(Session& session, ObjectHandle handle)
{
secure_vector<uint8_t> ec_parameters = get_attribute_value(AttributeType::EcParams);
m_domain_params = EC_Group(unlock(ec_parameters));
- m_public_key = decode_public_point(get_attribute_value(AttributeType::EcPoint), m_domain_params.get_curve());
+ m_public_key = decode_public_point(get_attribute_value(AttributeType::EcPoint), m_domain_params);
m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
}
@@ -55,7 +55,7 @@ PKCS11_EC_PublicKey::PKCS11_EC_PublicKey(Session& session, const EC_PublicKeyImp
secure_vector<uint8_t> ec_point;
BER_Decoder(props.ec_point()).decode(ec_point, OCTET_STRING);
- m_public_key = OS2ECP(ec_point, m_domain_params.get_curve());
+ m_public_key = m_domain_params.OS2ECP(ec_point);
m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
}
@@ -100,7 +100,7 @@ PKCS11_EC_PrivateKey::PKCS11_EC_PrivateKey(Session& session, const std::vector<u
this->reset_handle(priv_key_handle);
Object public_key(session, pub_key_handle);
- m_public_key = decode_public_point(public_key.get_attribute_value(AttributeType::EcPoint), m_domain_params.get_curve());
+ m_public_key = decode_public_point(public_key.get_attribute_value(AttributeType::EcPoint), m_domain_params);
}
size_t PKCS11_EC_PrivateKey::key_length() const
diff --git a/src/lib/pubkey/ec_group/ec_group.cpp b/src/lib/pubkey/ec_group/ec_group.cpp
index 6ae8c16d8..93747a166 100644
--- a/src/lib/pubkey/ec_group/ec_group.cpp
+++ b/src/lib/pubkey/ec_group/ec_group.cpp
@@ -2,7 +2,7 @@
* ECC Domain Parameters
*
* (C) 2007 Falko Strenzke, FlexSecure GmbH
-* 2008 Jack Lloyd
+* 2008,2018 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -16,56 +16,84 @@
namespace Botan {
-EC_Group::EC_Group(const OID& domain_oid)
+struct EC_Group_Data
{
- const std::string pem = PEM_for_named_group(OIDS::lookup(domain_oid));
+ CurveGFp m_curve;
+ PointGFp m_base_point;
+ BigInt m_order;
+ BigInt m_cofactor;
+ OID m_oid;
+ size_t m_p_bits, m_p_bytes;
+ };
- if(pem == "")
- {
- throw Lookup_Error("No ECC domain data for '" + domain_oid.as_string() + "'");
- }
+namespace {
- *this = EC_Group(pem);
- m_oid = domain_oid.as_string();
+std::shared_ptr<EC_Group_Data> new_EC_group_data(const BigInt& p,
+ const BigInt& a,
+ const BigInt& b,
+ const BigInt& g_x,
+ const BigInt& g_y,
+ const BigInt& order,
+ const BigInt& cofactor,
+ const OID& oid = OID())
+ {
+ std::shared_ptr<EC_Group_Data> data = std::make_shared<EC_Group_Data>();
+
+ data->m_curve = CurveGFp(p, a, b);
+ data->m_base_point = PointGFp(data->m_curve, g_x, g_y);
+ data->m_order = order;
+ data->m_cofactor = cofactor;
+ data->m_oid = oid;
+
+ data->m_p_bits = p.bits();
+ data->m_p_bytes = p.bytes();
+ return data;
}
-EC_Group::EC_Group(const std::string& str)
+std::shared_ptr<EC_Group_Data> new_EC_group_data(const BigInt& p,
+ const BigInt& a,
+ const BigInt& b,
+ const std::vector<uint8_t>& base_point,
+ const BigInt& order,
+ const BigInt& cofactor,
+ const OID& oid = OID())
{
- if(str == "")
- return; // no initialization / uninitialized
+ std::shared_ptr<EC_Group_Data> data = std::make_shared<EC_Group_Data>();
- try
- {
- std::vector<uint8_t> ber =
- unlock(PEM_Code::decode_check_label(str, "EC PARAMETERS"));
+ data->m_curve = CurveGFp(p, a, b);
+ data->m_base_point = Botan::OS2ECP(base_point, data->m_curve);
+ data->m_order = order;
+ data->m_cofactor = cofactor;
+ data->m_oid = oid;
- *this = EC_Group(ber);
- }
- catch(Decoding_Error) // hmm, not PEM?
- {
- *this = EC_Group(OIDS::lookup(str));
- }
+ data->m_p_bits = p.bits();
+ data->m_p_bytes = p.bytes();
+ return data;
}
-EC_Group::EC_Group(const std::vector<uint8_t>& ber_data)
+std::shared_ptr<EC_Group_Data> lookup_EC_group_by_oid(const OID& oid);
+
+std::shared_ptr<EC_Group_Data> BER_decode_EC_group(const uint8_t bits[], size_t len)
{
- BER_Decoder ber(ber_data);
+ BER_Decoder ber(bits, len);
BER_Object obj = ber.get_next_object();
if(obj.type() == NULL_TAG)
- throw Decoding_Error("Cannot handle ImplicitCA ECDSA parameters");
+ {
+ throw Decoding_Error("Cannot handle ImplicitCA ECC parameters");
+ }
else if(obj.type() == OBJECT_ID)
{
OID dom_par_oid;
- BER_Decoder(ber_data).decode(dom_par_oid);
- *this = EC_Group(dom_par_oid);
+ BER_Decoder(bits, len).decode(dom_par_oid);
+ return lookup_EC_group_by_oid(dom_par_oid);
}
else if(obj.type() == SEQUENCE)
{
- BigInt p, a, b;
+ BigInt p, a, b, order, cofactor;
std::vector<uint8_t> sv_base_point;
- BER_Decoder(ber_data)
+ BER_Decoder(bits, len)
.start_cons(SEQUENCE)
.decode_and_check<size_t>(1, "Unknown ECC param version code")
.start_cons(SEQUENCE)
@@ -78,16 +106,181 @@ EC_Group::EC_Group(const std::vector<uint8_t>& ber_data)
.decode_octet_string_bigint(b)
.end_cons()
.decode(sv_base_point, OCTET_STRING)
- .decode(m_order)
- .decode(m_cofactor)
+ .decode(order)
+ .decode(cofactor)
.end_cons()
.verify_end();
- m_curve = CurveGFp(p, a, b);
- m_base_point = OS2ECP(sv_base_point, m_curve);
+ return new_EC_group_data(p, a, b, sv_base_point, order, cofactor);
}
else
+ {
throw Decoding_Error("Unexpected tag while decoding ECC domain params");
+ }
+ }
+
+std::shared_ptr<EC_Group_Data> BER_decode_EC_group(const std::string& pem)
+ {
+ secure_vector<uint8_t> ber = PEM_Code::decode_check_label(pem, "EC PARAMETERS");
+ return BER_decode_EC_group(ber.data(), ber.size());
+ }
+
+std::shared_ptr<EC_Group_Data> lookup_EC_group_by_oid(const OID& oid)
+ {
+ if(oid.empty())
+ throw Invalid_Argument("lookup_EC_group_by_oid with empty oid");
+
+ const std::string oid_name = OIDS::oid2str(oid);
+ if(oid_name.empty())
+ throw Invalid_Argument("Unknown EC group OID " + oid.as_string());
+
+ const std::string pem = EC_Group::PEM_for_named_group(oid_name);
+ if(pem.empty())
+ throw Invalid_Argument("EC group OID (" + oid_name + ") is not known");
+ std::shared_ptr<EC_Group_Data> data = BER_decode_EC_group(pem);
+ data->m_oid = oid;
+ return data;
+ }
+
+}
+
+EC_Group::EC_Group()
+ {
+ }
+
+EC_Group::~EC_Group()
+ {
+ // shared_ptr possibly freed here
+ }
+
+EC_Group::EC_Group(const OID& domain_oid)
+ {
+ this->m_data = lookup_EC_group_by_oid(domain_oid);
+ }
+
+EC_Group::EC_Group(const std::string& str)
+ {
+ if(str == "")
+ return; // no initialization / uninitialized
+
+ try
+ {
+ OID oid = OIDS::lookup(str);
+ if(oid.empty() == false)
+ m_data = lookup_EC_group_by_oid(oid);
+ }
+ catch(Invalid_OID)
+ {
+ }
+
+ if(m_data == nullptr)
+ {
+ // OK try it as PEM ...
+ this->m_data = BER_decode_EC_group(str);
+ }
+ }
+
+EC_Group::EC_Group(const BigInt& p,
+ const BigInt& a,
+ const BigInt& b,
+ const BigInt& base_x,
+ const BigInt& base_y,
+ const BigInt& order,
+ const BigInt& cofactor,
+ const OID& oid)
+ {
+ m_data = new_EC_group_data(p, a, b, base_x, base_y, order, cofactor, oid);
+ }
+
+EC_Group::EC_Group(const CurveGFp& curve,
+ const PointGFp& base_point,
+ const BigInt& order,
+ const BigInt& cofactor)
+ {
+ m_data = new_EC_group_data(curve.get_p(),
+ curve.get_a(),
+ curve.get_b(),
+ base_point.get_affine_x(),
+ base_point.get_affine_y(),
+ order,
+ cofactor);
+ }
+
+EC_Group::EC_Group(const std::vector<uint8_t>& ber)
+ {
+ m_data = BER_decode_EC_group(ber.data(), ber.size());
+ }
+
+const EC_Group_Data& EC_Group::data() const
+ {
+ if(m_data == nullptr)
+ throw Invalid_State("EC_Group uninitialized");
+ return *m_data;
+ }
+
+const CurveGFp& EC_Group::get_curve() const
+ {
+ return data().m_curve;
+ }
+
+size_t EC_Group::get_p_bits() const
+ {
+ return data().m_p_bits;
+ }
+
+size_t EC_Group::get_p_bytes() const
+ {
+ return data().m_p_bytes;
+ }
+
+const BigInt& EC_Group::get_p() const
+ {
+ return data().m_curve.get_p();
+ }
+
+const BigInt& EC_Group::get_a() const
+ {
+ return data().m_curve.get_a();
+ }
+
+const BigInt& EC_Group::get_b() const
+ {
+ return data().m_curve.get_b();
+ }
+
+const PointGFp& EC_Group::get_base_point() const
+ {
+ return data().m_base_point;
+ }
+
+const BigInt& EC_Group::get_order() const
+ {
+ return data().m_order;
+ }
+
+const BigInt& EC_Group::get_cofactor() const
+ {
+ return data().m_cofactor;
+ }
+
+const OID& EC_Group::get_curve_oid() const
+ {
+ return data().m_oid;
+ }
+
+PointGFp EC_Group::OS2ECP(const uint8_t bits[], size_t len) const
+ {
+ return Botan::OS2ECP(bits, len, data().m_curve);
+ }
+
+PointGFp EC_Group::point(const BigInt& x, const BigInt& y) const
+ {
+ return PointGFp(data().m_curve, x, y);
+ }
+
+PointGFp EC_Group::zero_point() const
+ {
+ return PointGFp(data().m_curve);
}
std::vector<uint8_t>
@@ -96,36 +289,37 @@ EC_Group::DER_encode(EC_Group_Encoding form) const
if(form == EC_DOMPAR_ENC_EXPLICIT)
{
const size_t ecpVers1 = 1;
- OID curve_type("1.2.840.10045.1.1");
+ OID curve_type("1.2.840.10045.1.1"); // prime field
- const size_t p_bytes = m_curve.get_p().bytes();
+ const size_t p_bytes = get_p_bytes();
return DER_Encoder()
.start_cons(SEQUENCE)
.encode(ecpVers1)
.start_cons(SEQUENCE)
.encode(curve_type)
- .encode(m_curve.get_p())
+ .encode(get_p())
.end_cons()
.start_cons(SEQUENCE)
- .encode(BigInt::encode_1363(m_curve.get_a(), p_bytes),
+ .encode(BigInt::encode_1363(get_a(), p_bytes),
OCTET_STRING)
- .encode(BigInt::encode_1363(m_curve.get_b(), p_bytes),
+ .encode(BigInt::encode_1363(get_b(), p_bytes),
OCTET_STRING)
.end_cons()
- .encode(EC2OSP(m_base_point, PointGFp::UNCOMPRESSED), OCTET_STRING)
- .encode(m_order)
- .encode(m_cofactor)
+ .encode(EC2OSP(get_base_point(), PointGFp::UNCOMPRESSED), OCTET_STRING)
+ .encode(get_order())
+ .encode(get_cofactor())
.end_cons()
.get_contents_unlocked();
}
else if(form == EC_DOMPAR_ENC_OID)
{
- if(get_oid().empty())
+ const OID oid = get_curve_oid();
+ if(oid.empty())
{
throw Encoding_Error("Cannot encode EC_Group as OID because OID not set");
}
- return DER_Encoder().encode(OID(get_oid())).get_contents_unlocked();
+ return DER_Encoder().encode(oid).get_contents_unlocked();
}
else if(form == EC_DOMPAR_ENC_IMPLICITCA)
return DER_Encoder().encode_null().get_contents_unlocked();
@@ -139,13 +333,28 @@ std::string EC_Group::PEM_encode() const
return PEM_Code::encode(der, "EC PARAMETERS");
}
+bool EC_Group::operator==(const EC_Group& other) const
+ {
+ if(m_data == other.m_data)
+ return true; // same shared rep
+
+ /*
+ * No point comparing order/cofactor as they are uniquely determined
+ * by the curve equation (p,a,b) and the base point.
+ */
+ return (get_p() == other.get_p() &&
+ get_a() == other.get_a() &&
+ get_b() == other.get_b() &&
+ get_base_point() == other.get_base_point());
+ }
+
bool EC_Group::verify_group(RandomNumberGenerator& rng,
bool) const
{
//compute the discriminant
- Modular_Reducer p(m_curve.get_p());
- BigInt discriminant = p.multiply(4, m_curve.get_a());
- discriminant += p.multiply(27, m_curve.get_b());
+ Modular_Reducer p(get_p());
+ BigInt discriminant = p.multiply(4, get_a());
+ discriminant += p.multiply(27, get_b());
discriminant = p.reduce(discriminant);
//check the discriminant
if(discriminant == 0)
@@ -153,26 +362,26 @@ bool EC_Group::verify_group(RandomNumberGenerator& rng,
return false;
}
//check for valid cofactor
- if(m_cofactor < 1)
+ if(get_cofactor() < 1)
{
return false;
}
//check if the base point is on the curve
- if(!m_base_point.on_the_curve())
+ if(!get_base_point().on_the_curve())
{
return false;
}
- if((m_base_point * m_cofactor).is_zero())
+ if((get_base_point() * get_cofactor()).is_zero())
{
return false;
}
//check if order is prime
- if(!is_prime(m_order, rng, 128))
+ if(!is_prime(get_order(), rng, 128))
{
return false;
}
//check if order of the base point is correct
- if(!(m_base_point * m_order).is_zero())
+ if(!(get_base_point() * get_order()).is_zero())
{
return false;
}
diff --git a/src/lib/pubkey/ec_group/ec_group.h b/src/lib/pubkey/ec_group/ec_group.h
index 18ffed12c..0e6b57b5a 100644
--- a/src/lib/pubkey/ec_group/ec_group.h
+++ b/src/lib/pubkey/ec_group/ec_group.h
@@ -13,6 +13,7 @@
#include <botan/point_gfp.h>
#include <botan/curve_gfp.h>
#include <botan/asn1_oid.h>
+#include <memory>
#include <set>
namespace Botan {
@@ -26,6 +27,8 @@ enum EC_Group_Encoding {
EC_DOMPAR_ENC_OID = 2
};
+struct EC_Group_Data;
+
/**
* Class representing an elliptic curve
*/
@@ -40,16 +43,31 @@ class BOTAN_PUBLIC_API(2,0) EC_Group final
* @param order the order of the base point
* @param cofactor the cofactor
*/
+ BOTAN_DEPRECATED("Use version taking all BigInts")
EC_Group(const CurveGFp& curve,
const PointGFp& base_point,
const BigInt& order,
- const BigInt& cofactor) :
- m_curve(curve),
- m_base_point(base_point),
- m_order(order),
- m_cofactor(cofactor),
- m_oid("")
- {}
+ const BigInt& cofactor);
+
+ /**
+ * Construct Domain paramers from specified parameters
+ * @param p the elliptic curve p
+ * @param a the elliptic curve a param
+ * @param b the elliptic curve b param
+ * @param base_x the x coordinate of the base point
+ * @param base_y the y coordinate of the base point
+ * @param order the order of the base point
+ * @param cofactor the cofactor
+ * @param oid an optional OID used to identify this curve
+ */
+ EC_Group(const BigInt& p,
+ const BigInt& a,
+ const BigInt& b,
+ const BigInt& base_x,
+ const BigInt& base_y,
+ const BigInt& order,
+ const BigInt& cofactor,
+ const OID& oid = OID());
/**
* Decode a BER encoded ECC domain parameter set
@@ -68,7 +86,14 @@ class BOTAN_PUBLIC_API(2,0) EC_Group final
* from an OID name (eg "secp256r1", or "1.2.840.10045.3.1.7")
* @param pem_or_oid PEM-encoded data, or an OID
*/
- EC_Group(const std::string& pem_or_oid = "");
+ explicit EC_Group(const std::string& pem_or_oid);
+
+ /**
+ * Create an uninitialized EC_Group
+ */
+ EC_Group();
+
+ ~EC_Group();
/**
* Create the DER encoding of this domain
@@ -87,48 +112,91 @@ class BOTAN_PUBLIC_API(2,0) EC_Group final
* Return domain parameter curve
* @result domain parameter curve
*/
- const CurveGFp& get_curve() const { return m_curve; }
+ BOTAN_DEPRECATED("Avoid CurveGFp") const CurveGFp& get_curve() const;
+
+ /**
+ * Return the size of p in bits (same as get_p().bits())
+ */
+ size_t get_p_bits() const;
+
+ /**
+ * Return the size of p in bits (same as get_p().bytes())
+ */
+ size_t get_p_bytes() const;
+
+ /**
+ * Return the prime modulus of the field
+ */
+ const BigInt& get_p() const;
+
+ /**
+ * Return the a parameter of the elliptic curve equation
+ */
+ const BigInt& get_a() const;
+
+ /**
+ * Return the b parameter of the elliptic curve equation
+ */
+ const BigInt& get_b() const;
/**
* Return group base point
* @result base point
*/
- const PointGFp& get_base_point() const { return m_base_point; }
+ const PointGFp& get_base_point() const;
/**
* Return the order of the base point
* @result order of the base point
*/
- const BigInt& get_order() const { return m_order; }
+ const BigInt& get_order() const;
+
+ /**
+ * Return the OID of these domain parameters
+ * @result the OID as a string
+ */
+ std::string BOTAN_DEPRECATED("Use get_curve_oid") get_oid() const { return get_curve_oid().as_string(); }
+
+ /**
+ * Return the OID of these domain parameters
+ * @result the OID
+ */
+ const OID& get_curve_oid() const;
/**
* Return the cofactor
* @result the cofactor
*/
- const BigInt& get_cofactor() const { return m_cofactor; }
+ const BigInt& get_cofactor() const;
- bool initialized() const { return !m_base_point.is_zero(); }
+ /**
+ * Return a point on this curve with the affine values x, y
+ */
+ PointGFp point(const BigInt& x, const BigInt& y) const;
/**
- * Return the OID of these domain parameters
- * @result the OID
+ * Return the zero (or infinite) point on this curve
*/
- std::string get_oid() const { return m_oid; }
-
+ PointGFp zero_point() const;
+
+ PointGFp OS2ECP(const uint8_t bits[], size_t len) const;
+
+ template<typename Alloc>
+ PointGFp OS2ECP(const std::vector<uint8_t, Alloc>& vec) const
+ {
+ return this->OS2ECP(vec.data(), vec.size());
+ }
+
+ bool initialized() const { return (m_data != nullptr); }
+
/**
* Verify EC_Group domain
* @returns true if group is valid. false otherwise
*/
bool verify_group(RandomNumberGenerator& rng,
- bool strong = false) const;
-
- bool operator==(const EC_Group& other) const
- {
- return ((get_curve() == other.get_curve()) &&
- (get_base_point() == other.get_base_point()) &&
- (get_order() == other.get_order()) &&
- (get_cofactor() == other.get_cofactor()));
- }
+ bool strong = false) const;
+
+ bool operator==(const EC_Group& other) const;
/**
* Return PEM representation of named EC group
@@ -140,11 +208,11 @@ class BOTAN_PUBLIC_API(2,0) EC_Group final
*/
static const std::set<std::string>& known_named_groups();
+ static void add_named_group(const std::string& name, const OID& oid, const EC_Group& group);
+
private:
- CurveGFp m_curve;
- PointGFp m_base_point;
- BigInt m_order, m_cofactor;
- std::string m_oid;
+ const EC_Group_Data& data() const;
+ std::shared_ptr<EC_Group_Data> m_data;
};
inline bool operator!=(const EC_Group& lhs,
diff --git a/src/lib/pubkey/ecc_key/ecc_key.cpp b/src/lib/pubkey/ecc_key/ecc_key.cpp
index 34062c362..17b6e6484 100644
--- a/src/lib/pubkey/ecc_key/ecc_key.cpp
+++ b/src/lib/pubkey/ecc_key/ecc_key.cpp
@@ -19,7 +19,7 @@ namespace Botan {
size_t EC_PublicKey::key_length() const
{
- return domain().get_curve().get_p().bits();
+ return domain().get_p_bits();
}
size_t EC_PublicKey::estimated_strength() const
@@ -31,20 +31,23 @@ EC_PublicKey::EC_PublicKey(const EC_Group& dom_par,
const PointGFp& pub_point) :
m_domain_params(dom_par), m_public_key(pub_point)
{
- if (!dom_par.get_oid().empty())
+ if (!dom_par.get_curve_oid().empty())
m_domain_encoding = EC_DOMPAR_ENC_OID;
else
m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
+
+#if 0
if(domain().get_curve() != public_point().get_curve())
throw Invalid_Argument("EC_PublicKey: curve mismatch in constructor");
+#endif
}
EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id,
const std::vector<uint8_t>& key_bits) :
m_domain_params{EC_Group(alg_id.get_parameters())},
- m_public_key{OS2ECP(key_bits, domain().get_curve())}
+ m_public_key{domain().OS2ECP(key_bits)}
{
- if (!domain().get_oid().empty())
+ if (!domain().get_curve_oid().empty())
m_domain_encoding = EC_DOMPAR_ENC_OID;
else
m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
@@ -101,7 +104,7 @@ void EC_PublicKey::set_parameter_encoding(EC_Group_Encoding form)
form != EC_DOMPAR_ENC_OID)
throw Invalid_Argument("Invalid encoding form for EC-key object specified");
- if((form == EC_DOMPAR_ENC_OID) && (m_domain_params.get_oid() == ""))
+ if((form == EC_DOMPAR_ENC_OID) && (m_domain_params.get_curve_oid().empty()))
throw Invalid_Argument("Invalid encoding form OID specified for "
"EC-key object whose corresponding domain "
"parameters are without oid");
@@ -126,7 +129,7 @@ EC_PrivateKey::EC_PrivateKey(RandomNumberGenerator& rng,
bool with_modular_inverse)
{
m_domain_params = ec_group;
- if (!ec_group.get_oid().empty())
+ if (!ec_group.get_curve_oid().empty())
m_domain_encoding = EC_DOMPAR_ENC_OID;
else
m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
@@ -165,7 +168,7 @@ EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id,
m_domain_params = EC_Group(alg_id.get_parameters());
m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
- if (!domain().get_oid().empty())
+ if (!domain().get_curve_oid().empty())
m_domain_encoding = EC_DOMPAR_ENC_OID;
else
m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT;
@@ -191,7 +194,7 @@ EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id,
}
else
{
- m_public_key = OS2ECP(public_key_bits, domain().get_curve());
+ m_public_key = domain().OS2ECP(public_key_bits);
// OS2ECP verifies that the point is on the curve
}
}
diff --git a/src/lib/pubkey/ecc_key/info.txt b/src/lib/pubkey/ecc_key/info.txt
index ac345a089..f46c9bb54 100644
--- a/src/lib/pubkey/ecc_key/info.txt
+++ b/src/lib/pubkey/ecc_key/info.txt
@@ -5,7 +5,6 @@ ECC_PUBLIC_KEY_CRYPTO -> 20131128
<requires>
asn1
bigint
-ec_gfp
ec_group
numbertheory
</requires>
diff --git a/src/lib/pubkey/ecdh/ecdh.cpp b/src/lib/pubkey/ecdh/ecdh.cpp
index c05f22d1b..1850696e1 100644
--- a/src/lib/pubkey/ecdh/ecdh.cpp
+++ b/src/lib/pubkey/ecdh/ecdh.cpp
@@ -28,27 +28,23 @@ class ECDH_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF
ECDH_KA_Operation(const ECDH_PrivateKey& key, const std::string& kdf, RandomNumberGenerator& rng) :
PK_Ops::Key_Agreement_with_KDF(kdf),
- m_curve(key.domain().get_curve()),
- m_cofactor(key.domain().get_cofactor()),
- m_order(key.domain().get_order()),
+ m_domain(key.domain()),
m_rng(rng)
{
- m_l_times_priv = inverse_mod(m_cofactor, m_order) * key.private_value();
+ m_l_times_priv = inverse_mod(m_domain.get_cofactor(), m_domain.get_order()) * key.private_value();
}
secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override
{
- PointGFp point = OS2ECP(w, w_len, m_curve);
- PointGFp S = m_cofactor * point;
- Blinded_Point_Multiply blinder(S, m_order);
+ PointGFp point = m_domain.OS2ECP(w, w_len);
+ PointGFp S = m_domain.get_cofactor() * point;
+ Blinded_Point_Multiply blinder(S, m_domain.get_order());
S = blinder.blinded_multiply(m_l_times_priv, m_rng);
BOTAN_ASSERT(S.on_the_curve(), "ECDH agreed value was on the curve");
- return BigInt::encode_1363(S.get_affine_x(), m_curve.get_p().bytes());
+ return BigInt::encode_1363(S.get_affine_x(), m_domain.get_p_bytes());
}
private:
- const CurveGFp& m_curve;
- const BigInt& m_cofactor;
- const BigInt& m_order;
+ const EC_Group& m_domain;
BigInt m_l_times_priv;
RandomNumberGenerator& m_rng;
diff --git a/src/lib/pubkey/ecies/ecies.cpp b/src/lib/pubkey/ecies/ecies.cpp
index e2d574dcf..cd09b4c52 100644
--- a/src/lib/pubkey/ecies/ecies.cpp
+++ b/src/lib/pubkey/ecies/ecies.cpp
@@ -66,12 +66,11 @@ 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 CurveGFp& curve = m_key.domain().get_curve();
- PointGFp point = OS2ECP(w, w_len, curve);
+ PointGFp point = m_key.domain().OS2ECP(w, w_len);
Blinded_Point_Multiply blinder(point, m_key.domain().get_order());
PointGFp S = blinder.blinded_multiply(m_key.private_value(), m_rng);
BOTAN_ASSERT(S.on_the_curve(), "ECDH agreed value was on the curve");
- return BigInt::encode_1363(S.get_affine_x(), curve.get_p().bytes());
+ return BigInt::encode_1363(S.get_affine_x(), m_key.domain().get_p_bytes());
}
private:
@@ -241,7 +240,7 @@ ECIES_Encryptor::ECIES_Encryptor(const PK_Key_Agreement_Key& private_key,
{
// ISO 18033: step d
// convert only if necessary; m_eph_public_key_bin has been initialized with the uncompressed format
- m_eph_public_key_bin = unlock(EC2OSP(OS2ECP(m_eph_public_key_bin, m_params.domain().get_curve()),
+ m_eph_public_key_bin = unlock(EC2OSP(m_params.domain().OS2ECP(m_eph_public_key_bin),
static_cast<uint8_t>(ecies_params.compression_type())));
}
}
@@ -311,7 +310,7 @@ ECIES_Decryptor::ECIES_Decryptor(const PK_Key_Agreement_Key& key,
// ISO 18033: "If v > 1 and CheckMode = 0, then we must have gcd(u, v) = 1." (v = index, u= order)
if(!ecies_params.check_mode())
{
- Botan::BigInt cofactor = m_params.domain().get_cofactor();
+ const Botan::BigInt& cofactor = m_params.domain().get_cofactor();
if(cofactor > 1 && Botan::gcd(cofactor, m_params.domain().get_order()) != 1)
{
throw Invalid_Argument("ECIES: gcd of cofactor and order must be 1 if check_mode is 0");
@@ -324,7 +323,7 @@ ECIES_Decryptor::ECIES_Decryptor(const PK_Key_Agreement_Key& key,
*/
secure_vector<uint8_t> ECIES_Decryptor::do_decrypt(uint8_t& valid_mask, const uint8_t in[], size_t in_len) const
{
- size_t point_size = m_params.domain().get_curve().get_p().bytes();
+ size_t point_size = m_params.domain().get_p_bytes();
if(m_params.compression_type() != PointGFp::COMPRESSED)
{
point_size *= 2; // uncompressed and hybrid contains x AND y
@@ -345,7 +344,7 @@ secure_vector<uint8_t> ECIES_Decryptor::do_decrypt(uint8_t& valid_mask, const ui
const std::vector<uint8_t> mac_data(in + in_len - mac->output_length(), in + in_len);
// ISO 18033: step a
- PointGFp other_public_key = OS2ECP(other_public_key_bin, m_params.domain().get_curve());
+ PointGFp other_public_key = m_params.domain().OS2ECP(other_public_key_bin);
// ISO 18033: step b
if(m_params.check_mode() && !other_public_key.on_the_curve())
diff --git a/src/lib/pubkey/gost_3410/gost_3410.cpp b/src/lib/pubkey/gost_3410/gost_3410.cpp
index acd127a2d..f005a349b 100644
--- a/src/lib/pubkey/gost_3410/gost_3410.cpp
+++ b/src/lib/pubkey/gost_3410/gost_3410.cpp
@@ -41,7 +41,7 @@ AlgorithmIdentifier GOST_3410_PublicKey::algorithm_identifier() const
{
std::vector<uint8_t> params =
DER_Encoder().start_cons(SEQUENCE)
- .encode(OID(domain().get_oid()))
+ .encode(domain().get_curve_oid())
.end_cons()
.get_contents_unlocked();
@@ -73,7 +73,7 @@ GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id,
BigInt x(bits.data(), part_size);
BigInt y(&bits[part_size], part_size);
- m_public_key = PointGFp(domain().get_curve(), x, y);
+ m_public_key = domain().point(x, y);
BOTAN_ASSERT(m_public_key.on_the_curve(),
"Loaded GOST 34.10 public key is on the curve");
diff --git a/src/lib/pubkey/sm2/sm2.cpp b/src/lib/pubkey/sm2/sm2.cpp
index 28f455ba3..652985ec9 100644
--- a/src/lib/pubkey/sm2/sm2.cpp
+++ b/src/lib/pubkey/sm2/sm2.cpp
@@ -54,10 +54,10 @@ std::vector<uint8_t> sm2_compute_za(HashFunction& hash,
hash.update(get_byte(1, uid_len));
hash.update(user_id);
- const size_t p_bytes = domain.get_curve().get_p().bytes();
+ const size_t p_bytes = domain.get_p_bytes();
- hash.update(BigInt::encode_1363(domain.get_curve().get_a(), p_bytes));
- hash.update(BigInt::encode_1363(domain.get_curve().get_b(), p_bytes));
+ hash.update(BigInt::encode_1363(domain.get_a(), p_bytes));
+ hash.update(BigInt::encode_1363(domain.get_b(), p_bytes));
hash.update(BigInt::encode_1363(domain.get_base_point().get_affine_x(), p_bytes));
hash.update(BigInt::encode_1363(domain.get_base_point().get_affine_y(), p_bytes));
hash.update(BigInt::encode_1363(pubkey.get_affine_x(), p_bytes));
diff --git a/src/lib/pubkey/sm2/sm2_enc.cpp b/src/lib/pubkey/sm2/sm2_enc.cpp
index b697daf1e..9ba278060 100644
--- a/src/lib/pubkey/sm2/sm2_enc.cpp
+++ b/src/lib/pubkey/sm2/sm2_enc.cpp
@@ -46,7 +46,7 @@ class SM2_Encryption_Operation final : public PK_Ops::Encryption
{
public:
SM2_Encryption_Operation(const SM2_Encryption_PublicKey& key, const std::string& kdf_hash) :
- m_p_bytes(key.domain().get_curve().get_p().bytes()),
+ m_p_bytes(key.domain().get_p_bytes()),
m_order(key.domain().get_order()),
m_base_point(key.domain().get_base_point(), m_order),
m_public_point(key.public_point(), m_order),
@@ -135,7 +135,7 @@ class SM2_Decryption_Operation final : public PK_Ops::Decryption
size_t ciphertext_len) override
{
const BigInt& cofactor = m_key.domain().get_cofactor();
- const size_t p_bytes = m_key.domain().get_curve().get_p().bytes();
+ const size_t p_bytes = m_key.domain().get_p_bytes();
valid_mask = 0x00;
@@ -160,7 +160,7 @@ class SM2_Decryption_Operation final : public PK_Ops::Decryption
.end_cons()
.verify_end();
- const PointGFp C1(m_key.domain().get_curve(), x1, y1);
+ const PointGFp C1 = m_key.domain().point(x1, y1);
if(!C1.on_the_curve())
return secure_vector<uint8_t>();
diff --git a/src/lib/tls/tls_callbacks.cpp b/src/lib/tls/tls_callbacks.cpp
index 7a64291c8..b3b1b79bb 100644
--- a/src/lib/tls/tls_callbacks.cpp
+++ b/src/lib/tls/tls_callbacks.cpp
@@ -164,7 +164,7 @@ std::pair<secure_vector<uint8_t>, std::vector<uint8_t>> TLS::Callbacks::tls_ecdh
else
{
EC_Group group(OIDS::lookup(curve_name));
- ECDH_PublicKey peer_key(group, OS2ECP(peer_public_value, group.get_curve()));
+ ECDH_PublicKey peer_key(group, group.OS2ECP(peer_public_value));
policy.check_peer_key_acceptable(peer_key);
ECDH_PrivateKey priv_key(rng, group);
PK_Key_Agreement ka(priv_key, rng, "Raw");
diff --git a/src/tests/test_ecdsa.cpp b/src/tests/test_ecdsa.cpp
index 36ca72942..2105250cb 100644
--- a/src/tests/test_ecdsa.cpp
+++ b/src/tests/test_ecdsa.cpp
@@ -104,7 +104,7 @@ class ECDSA_Invalid_Key_Tests final : public Text_Based_Test
try
{
- public_point.reset(new Botan::PointGFp(group.get_curve(), x, y));
+ public_point.reset(new Botan::PointGFp(group.point(x, y)));
}
catch(Botan::Invalid_Argument&)
{
diff --git a/src/tests/test_ecies.cpp b/src/tests/test_ecies.cpp
index 5c5af0a41..2ce931bae 100644
--- a/src/tests/test_ecies.cpp
+++ b/src/tests/test_ecies.cpp
@@ -127,12 +127,11 @@ class ECIES_ISO_Tests final : public Text_Based_Test
const std::vector<uint8_t> c0 = get_req_bin(vars, "C0"); // expected encoded (ephemeral) public key
const std::vector<uint8_t> k = get_req_bin(vars, "K"); // expected derived secret
- const Botan::CurveGFp curve(p, a, b);
- const Botan::EC_Group domain(curve, Botan::PointGFp(curve, gx, gy), mu, nu);
+ const Botan::EC_Group domain(p, a, b, gx, gy, mu, nu);
// keys of bob
const Botan::ECDH_PrivateKey other_private_key(Test::rng(), domain, x);
- const Botan::PointGFp other_public_key_point(curve, hx, hy);
+ const Botan::PointGFp other_public_key_point = domain.point(hx, hy);
const Botan::ECDH_PublicKey other_public_key(domain, other_public_key_point);
// (ephemeral) keys of alice
diff --git a/src/tests/test_gost_3410.cpp b/src/tests/test_gost_3410.cpp
index a1443a7ae..fe9e91f58 100644
--- a/src/tests/test_gost_3410.cpp
+++ b/src/tests/test_gost_3410.cpp
@@ -30,7 +30,7 @@ class GOST_3410_2001_Verification_Tests final : public PK_Signature_Verification
{
const std::string group_id = get_req_str(vars, "Group");
Botan::EC_Group group(Botan::OIDS::lookup(group_id));
- const Botan::PointGFp public_point = Botan::OS2ECP(get_req_bin(vars, "Pubkey"), group.get_curve());
+ const Botan::PointGFp public_point = group.OS2ECP(get_req_bin(vars, "Pubkey"));
std::unique_ptr<Botan::Public_Key> key(new Botan::GOST_3410_PublicKey(group, public_point));
return key;
diff --git a/src/tests/test_sm2.cpp b/src/tests/test_sm2.cpp
index 16b82b792..c4ddf6ddf 100644
--- a/src/tests/test_sm2.cpp
+++ b/src/tests/test_sm2.cpp
@@ -51,9 +51,7 @@ class SM2_Signature_KAT_Tests final : public PK_Signature_Generation_Test
const BigInt cofactor = get_req_bn(vars, "Cofactor");
const BigInt x = get_req_bn(vars, "x");
- Botan::CurveGFp curve(p, a, b);
- Botan::PointGFp base_point(curve, xG, yG);
- Botan::EC_Group domain(curve, base_point, order, cofactor);
+ Botan::EC_Group domain(p, a, b, xG, yG, order, cofactor);
Botan::Null_RNG null_rng;
std::unique_ptr<Botan::Private_Key> key(new Botan::SM2_Signature_PrivateKey(null_rng, domain, x));
@@ -97,9 +95,7 @@ class SM2_Encryption_KAT_Tests final : public PK_Encryption_Decryption_Test
const BigInt cofactor = get_req_bn(vars, "Cofactor");
const BigInt x = get_req_bn(vars, "x");
- Botan::CurveGFp curve(p, a, b);
- Botan::PointGFp base_point(curve, xG, yG);
- Botan::EC_Group domain(curve, base_point, order, cofactor);
+ Botan::EC_Group domain(p, a, b, xG, yG, order, cofactor);
Botan::Null_RNG null_rng;
std::unique_ptr<Botan::Private_Key> key(new Botan::SM2_Encryption_PrivateKey(null_rng, domain, x));
diff --git a/src/tests/unit_ecc.cpp b/src/tests/unit_ecc.cpp
index b9355e6f0..8d8cdb538 100644
--- a/src/tests/unit_ecc.cpp
+++ b/src/tests/unit_ecc.cpp
@@ -17,7 +17,6 @@
#include <botan/point_gfp.h>
#include <botan/ec_group.h>
#include <botan/reducer.h>
- #include <botan/oids.h>
#include <botan/hex.h>
#include <botan/data_src.h>
#include <botan/x509_key.h>
@@ -83,9 +82,9 @@ Botan::BigInt test_integer(Botan::RandomNumberGenerator& rng, size_t bits, BigIn
}
Botan::PointGFp create_random_point(Botan::RandomNumberGenerator& rng,
- const Botan::CurveGFp& curve)
+ const Botan::EC_Group& group)
{
- const Botan::BigInt& p = curve.get_p();
+ const Botan::BigInt& p = group.get_p();
Botan::Modular_Reducer mod_p(p);
@@ -93,14 +92,14 @@ Botan::PointGFp create_random_point(Botan::RandomNumberGenerator& rng,
{
const Botan::BigInt x = Botan::BigInt::random_integer(rng, 1, p);
const Botan::BigInt x3 = mod_p.multiply(x, mod_p.square(x));
- const Botan::BigInt ax = mod_p.multiply(curve.get_a(), x);
- const Botan::BigInt y = mod_p.reduce(x3 + ax + curve.get_b());
+ const Botan::BigInt ax = mod_p.multiply(group.get_a(), x);
+ const Botan::BigInt y = mod_p.reduce(x3 + ax + group.get_b());
const Botan::BigInt sqrt_y = ressol(y, p);
if(sqrt_y > 1)
{
BOTAN_ASSERT_EQUAL(mod_p.square(sqrt_y), y, "Square root is correct");
- Botan::PointGFp point(curve, x, sqrt_y);
+ Botan::PointGFp point = group.point(x, sqrt_y);
return point;
}
}
@@ -276,7 +275,9 @@ Test::Result test_groups()
for(auto const& group_name : named_groups)
{
const Botan::EC_Group group(group_name);
- result.confirm("EC_Group is known", !group.get_oid().empty());
+ result.confirm("EC_Group is known", !group.get_curve_oid().empty());
+ result.test_eq("EC_Group has correct bit size", group.get_p().bits(), group.get_p_bits());
+ result.test_eq("EC_Group has byte size", group.get_p().bytes(), group.get_p_bytes());
}
return result;
}
@@ -289,11 +290,10 @@ Test::Result test_coordinates()
const Botan::BigInt exp_affine_y("1373093393927139016463695321221277758035357890939");
// precalculation
- const Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1"));
- const Botan::CurveGFp& curve = secp160r1.get_curve();
+ const Botan::EC_Group secp160r1("secp160r1");
const Botan::PointGFp& p_G = secp160r1.get_base_point();
- const Botan::PointGFp point_exp(curve, exp_affine_x, exp_affine_y);
+ const Botan::PointGFp point_exp = secp160r1.point(exp_affine_x, exp_affine_y);
result.confirm("Point is on the curve", point_exp.on_the_curve());
const Botan::PointGFp p1 = p_G * 2;
@@ -319,7 +319,7 @@ Test::Result test_point_transformation()
Test::Result result("ECC Unit");
// get a valid point
- Botan::EC_Group dom_pars(Botan::OID("1.3.132.0.8"));
+ Botan::EC_Group dom_pars("secp160r1");
Botan::PointGFp p = dom_pars.get_base_point() * Test::rng().next_nonzero_byte();
// get a copy
@@ -337,7 +337,7 @@ Test::Result test_point_mult()
{
Test::Result result("ECC Unit");
- Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1"));
+ Botan::EC_Group secp160r1("secp160r1");
const Botan::PointGFp& p_G = secp160r1.get_base_point();
Botan::BigInt d_U("0xaa374ffc3ce144e6b073307972cb6d57b2a4e982");
@@ -352,7 +352,7 @@ Test::Result test_point_negative()
{
Test::Result result("ECC Unit");
- Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1"));
+ Botan::EC_Group secp160r1("secp160r1");
const Botan::PointGFp& p_G = secp160r1.get_base_point();
const Botan::PointGFp p1 = p_G * 2;
@@ -371,12 +371,10 @@ Test::Result test_zeropoint()
{
Test::Result result("ECC Unit");
- Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1"));
- const Botan::CurveGFp& curve = secp160r1.get_curve();
+ Botan::EC_Group secp160r1("secp160r1");
- Botan::PointGFp p1(curve,
- Botan::BigInt("16984103820118642236896513183038186009872590470"),
- Botan::BigInt("1373093393927139016463695321221277758035357890939"));
+ Botan::PointGFp p1 = secp160r1.point(Botan::BigInt("16984103820118642236896513183038186009872590470"),
+ Botan::BigInt("1373093393927139016463695321221277758035357890939"));
result.confirm("point is on the curve", p1.on_the_curve());
@@ -391,20 +389,19 @@ Test::Result test_zeropoint_enc_dec()
{
Test::Result result("ECC Unit");
- Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1"));
- const Botan::CurveGFp& curve = secp160r1.get_curve();
+ Botan::EC_Group secp160r1("secp160r1");
- Botan::PointGFp p(curve);
+ Botan::PointGFp p = secp160r1.zero_point();
result.confirm("zero point is zero", p.is_zero());
std::vector<uint8_t> sv_p = unlock(EC2OSP(p, Botan::PointGFp::UNCOMPRESSED));
- result.test_eq("encoded/decode rt works", OS2ECP(sv_p, curve), p);
+ result.test_eq("encoded/decode rt works", secp160r1.OS2ECP(sv_p), p);
sv_p = unlock(EC2OSP(p, Botan::PointGFp::COMPRESSED));
- result.test_eq("encoded/decode compressed rt works", OS2ECP(sv_p, curve), p);
+ result.test_eq("encoded/decode compressed rt works", secp160r1.OS2ECP(sv_p), p);
sv_p = unlock(EC2OSP(p, Botan::PointGFp::HYBRID));
- result.test_eq("encoded/decode hybrid rt works", OS2ECP(sv_p, curve), p);
+ result.test_eq("encoded/decode hybrid rt works", secp160r1.OS2ECP(sv_p), p);
return result;
}
@@ -412,17 +409,15 @@ Test::Result test_calc_with_zeropoint()
{
Test::Result result("ECC Unit");
- Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1"));
- const Botan::CurveGFp& curve = secp160r1.get_curve();
+ Botan::EC_Group secp160r1("secp160r1");
- Botan::PointGFp p(curve,
- Botan::BigInt("16984103820118642236896513183038186009872590470"),
- Botan::BigInt("1373093393927139016463695321221277758035357890939"));
+ Botan::PointGFp p = secp160r1.point(Botan::BigInt("16984103820118642236896513183038186009872590470"),
+ Botan::BigInt("1373093393927139016463695321221277758035357890939"));
result.confirm("point is on the curve", p.on_the_curve());
result.confirm("point is not zero", !p.is_zero());
- Botan::PointGFp zero(curve);
+ Botan::PointGFp zero = secp160r1.zero_point();
result.confirm("zero point is zero", zero.is_zero());
Botan::PointGFp res = p + zero;
@@ -441,8 +436,7 @@ Test::Result test_add_point()
Test::Result result("ECC Unit");
// precalculation
- Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1"));
- const Botan::CurveGFp& curve = secp160r1.get_curve();
+ Botan::EC_Group secp160r1("secp160r1");
const Botan::PointGFp& p_G = secp160r1.get_base_point();
Botan::PointGFp p0 = p_G;
@@ -450,9 +444,8 @@ Test::Result test_add_point()
p1 += p0;
- Botan::PointGFp expected(curve,
- Botan::BigInt("704859595002530890444080436569091156047721708633"),
- Botan::BigInt("1147993098458695153857594941635310323215433166682"));
+ Botan::PointGFp expected = secp160r1.point(Botan::BigInt("704859595002530890444080436569091156047721708633"),
+ Botan::BigInt("1147993098458695153857594941635310323215433166682"));
result.test_eq("point addition", p1, expected);
return result;
@@ -462,8 +455,7 @@ Test::Result test_sub_point()
{
Test::Result result("ECC Unit");
- Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1"));
- const Botan::CurveGFp& curve = secp160r1.get_curve();
+ Botan::EC_Group secp160r1("secp160r1");
const Botan::PointGFp& p_G = secp160r1.get_base_point();
Botan::PointGFp p0 = p_G;
@@ -471,9 +463,8 @@ Test::Result test_sub_point()
p1 -= p0;
- Botan::PointGFp expected(curve,
- Botan::BigInt("425826231723888350446541592701409065913635568770"),
- Botan::BigInt("203520114162904107873991457957346892027982641970"));
+ Botan::PointGFp expected = secp160r1.point(Botan::BigInt("425826231723888350446541592701409065913635568770"),
+ Botan::BigInt("203520114162904107873991457957346892027982641970"));
result.test_eq("point subtraction", p1, expected);
return result;
@@ -483,8 +474,7 @@ Test::Result test_mult_point()
{
Test::Result result("ECC Unit");
- Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1"));
- const Botan::CurveGFp& curve = secp160r1.get_curve();
+ Botan::EC_Group secp160r1("secp160r1");
const Botan::PointGFp& p_G = secp160r1.get_base_point();
Botan::PointGFp p0 = p_G;
@@ -494,7 +484,7 @@ Test::Result test_mult_point()
const Botan::BigInt exp_mult_x(std::string("967697346845926834906555988570157345422864716250"));
const Botan::BigInt exp_mult_y(std::string("512319768365374654866290830075237814703869061656"));
- Botan::PointGFp expected(curve, exp_mult_x, exp_mult_y);
+ Botan::PointGFp expected = secp160r1.point(exp_mult_x, exp_mult_y);
result.test_eq("point mult", p1, expected);
return result;
@@ -505,8 +495,7 @@ Test::Result test_basic_operations()
Test::Result result("ECC Unit");
// precalculation
- Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1"));
- const Botan::CurveGFp& curve = secp160r1.get_curve();
+ Botan::EC_Group secp160r1("secp160r1");
const Botan::PointGFp& p_G = secp160r1.get_base_point();
const Botan::PointGFp p0 = p_G;
@@ -516,16 +505,14 @@ Test::Result test_basic_operations()
result.test_eq("p1 affine y", p1.get_affine_y(), Botan::BigInt("1373093393927139016463695321221277758035357890939"));
const Botan::PointGFp simplePlus = p1 + p0;
- const Botan::PointGFp exp_simplePlus(curve,
- Botan::BigInt("704859595002530890444080436569091156047721708633"),
- Botan::BigInt("1147993098458695153857594941635310323215433166682"));
+ const Botan::PointGFp exp_simplePlus = secp160r1.point(Botan::BigInt("704859595002530890444080436569091156047721708633"),
+ Botan::BigInt("1147993098458695153857594941635310323215433166682"));
result.test_eq("point addition", simplePlus, exp_simplePlus);
const Botan::PointGFp simpleMinus = p1 - p0;
- const Botan::PointGFp exp_simpleMinus(curve,
- Botan::BigInt("425826231723888350446541592701409065913635568770"),
- Botan::BigInt("203520114162904107873991457957346892027982641970"));
+ const Botan::PointGFp exp_simpleMinus= secp160r1.point(Botan::BigInt("425826231723888350446541592701409065913635568770"),
+ Botan::BigInt("203520114162904107873991457957346892027982641970"));
result.test_eq("point subtraction", simpleMinus, exp_simpleMinus);
@@ -544,12 +531,11 @@ Test::Result test_enc_dec_compressed_160()
Test::Result result("ECC Unit");
// Test for compressed conversion (02/03) 160bit
- Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1"));
- const Botan::CurveGFp& curve = secp160r1.get_curve();
+ Botan::EC_Group secp160r1("secp160r1");
const std::vector<uint8_t> G_comp = Botan::hex_decode("024A96B5688EF573284664698968C38BB913CBFC82");
- const Botan::PointGFp p = Botan::OS2ECP(G_comp, curve);
+ const Botan::PointGFp p = secp160r1.OS2ECP(G_comp);
std::vector<uint8_t> sv_result = unlock(Botan::EC2OSP(p, Botan::PointGFp::COMPRESSED));
@@ -692,11 +678,11 @@ Test::Result test_gfp_store_restore()
Test::Result result("ECC Unit");
// generate point
- Botan::EC_Group dom_pars(Botan::OID("1.3.132.0.8"));
+ Botan::EC_Group dom_pars("secp160r1");
Botan::PointGFp p = dom_pars.get_base_point();
std::vector<uint8_t> sv_mes = unlock(EC2OSP(p, Botan::PointGFp::COMPRESSED));
- Botan::PointGFp new_p = Botan::OS2ECP(sv_mes, dom_pars.get_curve());
+ Botan::PointGFp new_p = dom_pars.OS2ECP(sv_mes);
result.test_eq("original and restored points are same", p, new_p);
return result;
@@ -732,12 +718,10 @@ Test::Result test_more_zeropoint()
// by Falko
- Botan::EC_Group secp160r1(Botan::OIDS::lookup("secp160r1"));
- const Botan::CurveGFp& curve = secp160r1.get_curve();
+ Botan::EC_Group secp160r1("secp160r1");
- Botan::PointGFp p1(curve,
- Botan::BigInt("16984103820118642236896513183038186009872590470"),
- Botan::BigInt("1373093393927139016463695321221277758035357890939"));
+ Botan::PointGFp p1 = secp160r1.point(Botan::BigInt("16984103820118642236896513183038186009872590470"),
+ Botan::BigInt("1373093393927139016463695321221277758035357890939"));
result.confirm("point is on the curve", p1.on_the_curve());
Botan::PointGFp minus_p1 = -p1;
@@ -747,12 +731,12 @@ Test::Result test_more_zeropoint()
result.confirm("point is zero", shouldBeZero.is_zero());
Botan::BigInt y1 = p1.get_affine_y();
- y1 = curve.get_p() - y1;
+ y1 = secp160r1.get_p() - y1;
result.test_eq("minus point x", minus_p1.get_affine_x(), p1.get_affine_x());
result.test_eq("minus point y", minus_p1.get_affine_y(), y1);
- Botan::PointGFp zero(curve);
+ Botan::PointGFp zero = secp160r1.zero_point();
result.confirm("zero point is on the curve", zero.on_the_curve());
result.test_eq("addition of zero does nothing", p1, p1 + zero);
@@ -764,7 +748,7 @@ Test::Result test_mult_by_order()
Test::Result result("ECC Unit");
// generate point
- Botan::EC_Group dom_pars(Botan::OID("1.3.132.0.8"));
+ Botan::EC_Group dom_pars("secp160r1");
Botan::PointGFp p = dom_pars.get_base_point();
Botan::PointGFp shouldBeZero = p * dom_pars.get_order();
@@ -776,10 +760,10 @@ Test::Result test_point_swap()
{
Test::Result result("ECC Unit");
- Botan::EC_Group dom_pars(Botan::OID("1.3.132.0.8"));
+ Botan::EC_Group dom_pars("secp160r1");
- Botan::PointGFp a(create_random_point(Test::rng(), dom_pars.get_curve()));
- Botan::PointGFp b(create_random_point(Test::rng(), dom_pars.get_curve()));
+ Botan::PointGFp a(create_random_point(Test::rng(), dom_pars));
+ Botan::PointGFp b(create_random_point(Test::rng(), dom_pars));
b *= Botan::BigInt(Test::rng(), 20);
Botan::PointGFp c(a);
@@ -800,12 +784,12 @@ Test::Result test_mult_sec_mass()
{
Test::Result result("ECC Unit");
- Botan::EC_Group dom_pars(Botan::OID("1.3.132.0.8"));
+ Botan::EC_Group dom_pars("secp160r1");
for(int i = 0; i < 50; i++)
{
try
{
- Botan::PointGFp a(create_random_point(Test::rng(), dom_pars.get_curve()));
+ Botan::PointGFp a(create_random_point(Test::rng(), dom_pars));
Botan::BigInt scal(Botan::BigInt(Test::rng(), 40));
Botan::PointGFp b = a * scal;
Botan::PointGFp c(a);
@@ -822,23 +806,6 @@ Test::Result test_mult_sec_mass()
return result;
}
-Test::Result test_curve_cp_ctor()
- {
- Test::Result result("ECC Unit");
-
- try
- {
- Botan::EC_Group dom_pars(Botan::OID("1.3.132.0.8"));
- Botan::CurveGFp curve(dom_pars.get_curve());
- }
- catch(std::exception& e)
- {
- result.test_failure("curve_cp_ctor", e.what());
- }
-
- return result;
- }
-
class ECC_Unit_Tests final : public Test
{
public:
@@ -869,7 +836,6 @@ class ECC_Unit_Tests final : public Test
results.push_back(test_mult_by_order());
results.push_back(test_point_swap());
results.push_back(test_mult_sec_mass());
- results.push_back(test_curve_cp_ctor());
return results;
}
diff --git a/src/tests/unit_ecdsa.cpp b/src/tests/unit_ecdsa.cpp
index 5d137bacf..081b686e6 100644
--- a/src/tests/unit_ecdsa.cpp
+++ b/src/tests/unit_ecdsa.cpp
@@ -233,20 +233,20 @@ Test::Result test_unusual_curve()
Test::Result result("ECDSA Unit");
//calc a curve which is not in the registry
- const std::string G_secp_comp =
- "04081523d03d4f12cd02879dea4bf6a4f3a7df26ed888f10c5b2235a1274c386a2f218300dee6ed217841164533bcdc903f07a096f9fbf4ee95bac098a111f296f5830fe5c35b3e344d5df3a2256985f64fbe6d0edcc4c61d18bef681dd399df3d0194c5a4315e012e0245ecea56365baa9e8be1f7";
- const Botan::BigInt
- bi_p_secp("2117607112719756483104013348936480976596328609518055062007450442679169492999007105354629105748524349829824407773719892437896937279095106809");
- const Botan::BigInt
- bi_a_secp("0x0a377dede6b523333d36c78e9b0eaa3bf48ce93041f6d4fc34014d08f6833807498deedd4290101c5866e8dfb589485d13357b9e78c2d7fbe9fe");
- const Botan::BigInt
- bi_b_secp("0x0a9acf8c8ba617777e248509bcb4717d4db346202bf9e352cd5633731dd92a51b72a4dc3b3d17c823fcc8fbda4da08f25dea89046087342595a7");
- Botan::BigInt bi_order_g("0x0e1a16196e6000000000bc7f1618d867b15bb86474418f");
- Botan::CurveGFp curve(bi_p_secp, bi_a_secp, bi_b_secp);
- Botan::PointGFp p_G = Botan::OS2ECP(Botan::hex_decode(G_secp_comp), curve);
-
- Botan::EC_Group dom_params(curve, p_G, bi_order_g, Botan::BigInt(1));
- if(!result.confirm("point is on curve", p_G.on_the_curve()))
+ const Botan::BigInt p("2117607112719756483104013348936480976596328609518055062007450442679169492999007105354629105748524349829824407773719892437896937279095106809");
+ const Botan::BigInt a("0x0a377dede6b523333d36c78e9b0eaa3bf48ce93041f6d4fc34014d08f6833807498deedd4290101c5866e8dfb589485d13357b9e78c2d7fbe9fe");
+ const Botan::BigInt b("0x0a9acf8c8ba617777e248509bcb4717d4db346202bf9e352cd5633731dd92a51b72a4dc3b3d17c823fcc8fbda4da08f25dea89046087342595a7");
+ const Botan::BigInt order_g("0x0e1a16196e6000000000bc7f1618d867b15bb86474418f");
+ const Botan::BigInt cofactor = 1;
+
+ const BigInt Gx("1503931002566715881584977704503341991763310127581173321974500299341775226206001860606586625324214456299149080935147329869147994265934715820");
+ const BigInt Gy("1774988776970033741491814582357926984496972046739476148938345272681378523636129776486407268230155403536112014267092770854858769258781598199");
+
+ Botan::EC_Group dom_params(p, a, b, Gx, Gy, order_g, cofactor);
+
+ Botan::PointGFp p_G = dom_params.point(Gx, Gy);
+
+ if(!result.confirm("G is on curve", p_G.on_the_curve()))
{
return result;
}