aboutsummaryrefslogtreecommitdiffstats
path: root/src/pubkey/ec_group/ec_group.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/pubkey/ec_group/ec_group.cpp')
-rw-r--r--src/pubkey/ec_group/ec_group.cpp137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/pubkey/ec_group/ec_group.cpp b/src/pubkey/ec_group/ec_group.cpp
new file mode 100644
index 000000000..fe4fae885
--- /dev/null
+++ b/src/pubkey/ec_group/ec_group.cpp
@@ -0,0 +1,137 @@
+/*
+* ECC Domain Parameters
+*
+* (C) 2007 Falko Strenzke, FlexSecure GmbH
+* 2008 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/ec_group.h>
+#include <botan/ber_dec.h>
+#include <botan/der_enc.h>
+#include <botan/libstate.h>
+#include <botan/oids.h>
+#include <botan/pem.h>
+
+namespace Botan {
+
+EC_Group::EC_Group(const OID& domain_oid)
+ {
+ std::string pem =
+ global_state().get("ec", OIDS::lookup(domain_oid));
+
+ if(pem == "")
+ throw Lookup_Error("No ECC domain data for " + domain_oid.as_string());
+
+ *this = EC_Group(pem);
+ oid = domain_oid.as_string();
+ }
+
+EC_Group::EC_Group(const std::string& str)
+ {
+ if(str == "")
+ return; // no initialization / uninitialized
+
+ try
+ {
+ DataSource_Memory input(str);
+
+ SecureVector<byte> ber =
+ PEM_Code::decode_check_label(input, "EC PARAMETERS");
+
+ *this = EC_Group(ber);
+ }
+ catch(Decoding_Error) // hmm, not PEM?
+ {
+ *this = EC_Group(OIDS::lookup(str));
+ }
+ }
+
+EC_Group::EC_Group(const MemoryRegion<byte>& ber_data)
+ {
+ BER_Decoder ber(ber_data);
+ BER_Object obj = ber.get_next_object();
+
+ if(obj.type_tag == NULL_TAG)
+ throw Decoding_Error("Cannot handle ImplicitCA ECDSA parameters");
+ else if(obj.type_tag == OBJECT_ID)
+ {
+ OID dom_par_oid;
+ BER_Decoder(ber_data).decode(dom_par_oid);
+ *this = EC_Group(dom_par_oid);
+ }
+ else if(obj.type_tag == SEQUENCE)
+ {
+ BigInt p, a, b;
+ SecureVector<byte> sv_base_point;
+
+ BER_Decoder(ber_data)
+ .start_cons(SEQUENCE)
+ .decode_and_check<size_t>(1, "Unknown ECC param version code")
+ .start_cons(SEQUENCE)
+ .decode_and_check(OID("1.2.840.10045.1.1"),
+ "Only prime ECC fields supported")
+ .decode(p)
+ .end_cons()
+ .start_cons(SEQUENCE)
+ .decode_octet_string_bigint(a)
+ .decode_octet_string_bigint(b)
+ .end_cons()
+ .decode(sv_base_point, OCTET_STRING)
+ .decode(order)
+ .decode(cofactor)
+ .end_cons()
+ .verify_end();
+
+ curve = CurveGFp(p, a, b);
+ base_point = OS2ECP(sv_base_point, curve);
+ }
+ else
+ throw Decoding_Error("Unexpected tag while decoding ECC domain params");
+ }
+
+SecureVector<byte>
+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");
+
+ const size_t p_bytes = curve.get_p().bytes();
+
+ return DER_Encoder()
+ .start_cons(SEQUENCE)
+ .encode(ecpVers1)
+ .start_cons(SEQUENCE)
+ .encode(curve_type)
+ .encode(curve.get_p())
+ .end_cons()
+ .start_cons(SEQUENCE)
+ .encode(BigInt::encode_1363(curve.get_a(), p_bytes),
+ OCTET_STRING)
+ .encode(BigInt::encode_1363(curve.get_b(), p_bytes),
+ OCTET_STRING)
+ .end_cons()
+ .encode(EC2OSP(base_point, PointGFp::UNCOMPRESSED), OCTET_STRING)
+ .encode(order)
+ .encode(cofactor)
+ .end_cons()
+ .get_contents();
+ }
+ else if(form == EC_DOMPAR_ENC_OID)
+ return DER_Encoder().encode(get_oid()).get_contents();
+ else if(form == EC_DOMPAR_ENC_IMPLICITCA)
+ return DER_Encoder().encode_null().get_contents();
+ else
+ throw Internal_Error("EC_Group::DER_encode: Unknown encoding");
+ }
+
+std::string EC_Group::PEM_encode() const
+ {
+ SecureVector<byte> der = DER_encode(EC_DOMPAR_ENC_EXPLICIT);
+ return PEM_Code::encode(der, "EC PARAMETERS");
+ }
+
+}