aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/pubkey/ec_group/ec_group.cpp
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-01-31 14:03:05 -0500
committerJack Lloyd <[email protected]>2018-01-31 14:03:05 -0500
commite5b9ee2345affb56307070298ded9c2d5e1914be (patch)
tree7311fb0a10a99ccaf8cb82eecdea26d9fbe3d458 /src/lib/pubkey/ec_group/ec_group.cpp
parent439d2ead033142365f092c7882bad31e4257ed09 (diff)
Use shared representation of EC_Group
Hide CurveGFp with an eye for eventual removal
Diffstat (limited to 'src/lib/pubkey/ec_group/ec_group.cpp')
-rw-r--r--src/lib/pubkey/ec_group/ec_group.cpp249
1 files changed, 193 insertions, 56 deletions
diff --git a/src/lib/pubkey/ec_group/ec_group.cpp b/src/lib/pubkey/ec_group/ec_group.cpp
index 6ae8c16d8..8a3ffa718 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,42 @@
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> lookup_EC_group_by_oid(const OID& oid);
-EC_Group::EC_Group(const std::string& str)
+std::shared_ptr<EC_Group_Data> BER_decode_EC_group(const uint8_t bits[], size_t len)
{
- if(str == "")
- return; // no initialization / uninitialized
-
- try
- {
- std::vector<uint8_t> ber =
- unlock(PEM_Code::decode_check_label(str, "EC PARAMETERS"));
-
- *this = EC_Group(ber);
- }
- catch(Decoding_Error) // hmm, not PEM?
- {
- *this = EC_Group(OIDS::lookup(str));
- }
- }
-
-EC_Group::EC_Group(const std::vector<uint8_t>& ber_data)
- {
- 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)
{
+ std::shared_ptr<EC_Group_Data> data = std::make_shared<EC_Group_Data>();
BigInt p, a, b;
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 +64,166 @@ 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(data->m_order)
+ .decode(data->m_cofactor)
.end_cons()
.verify_end();
- m_curve = CurveGFp(p, a, b);
- m_base_point = OS2ECP(sv_base_point, m_curve);
+ data->m_curve = CurveGFp(p, a, b);
+ data->m_base_point = Botan::OS2ECP(sv_base_point, data->m_curve);
+
+ data->m_p_bits = p.bits();
+ data->m_p_bytes = p.bytes();
+ return data;
}
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(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 CurveGFp& curve,
+ const PointGFp& base_point,
+ const BigInt& order,
+ const BigInt& cofactor)
+ {
+ m_data.reset(new EC_Group_Data);
+
+ m_data->m_curve = curve;
+ m_data->m_base_point = base_point;
+ m_data->m_order = order;
+ m_data->m_cofactor = cofactor;
+ m_data->m_p_bits = curve.get_p().bits();
+ m_data->m_p_bytes = curve.get_p().bytes();
+ }
+
+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, get_curve());
+ }
+
+PointGFp EC_Group::point(const BigInt& x, const BigInt& y) const
+ {
+ return PointGFp(get_curve(), x, y);
+ }
+
+PointGFp EC_Group::zero_point() const
+ {
+ return PointGFp(get_curve());
}
std::vector<uint8_t>
@@ -96,36 +232,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();
@@ -143,9 +280,9 @@ 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 +290,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;
}