diff options
author | Jack Lloyd <[email protected]> | 2018-01-31 14:03:05 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2018-01-31 14:03:05 -0500 |
commit | e5b9ee2345affb56307070298ded9c2d5e1914be (patch) | |
tree | 7311fb0a10a99ccaf8cb82eecdea26d9fbe3d458 /src/lib/pubkey/ec_group/ec_group.cpp | |
parent | 439d2ead033142365f092c7882bad31e4257ed09 (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.cpp | 249 |
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; } |