/* * ECC Domain Parameters * * (C) 2007 Falko Strenzke, FlexSecure GmbH * 2008 Jack Lloyd * * Distributed under the terms of the Botan license */ #include #include #include #include #include #include namespace Botan { EC_Domain_Params::EC_Domain_Params(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_Domain_Params(pem); oid = domain_oid.as_string(); } EC_Domain_Params::EC_Domain_Params(const std::string& pem) { if(pem == "") return; // no initialization / uninitialized try { DataSource_Memory input(pem); SecureVector ber = PEM_Code::decode_check_label(input, "EC PARAMETERS"); *this = EC_Domain_Params(ber); } catch(Decoding_Error) // hmm, not PEM? { *this = EC_Domain_Params(OID(pem)); } } EC_Domain_Params::EC_Domain_Params(const MemoryRegion& 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_Domain_Params(dom_par_oid); } else if(obj.type_tag == SEQUENCE) { BigInt p, a, b; SecureVector sv_base_point; BER_Decoder(ber_data) .start_cons(SEQUENCE) .decode_and_check(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 EC_Domain_Params::DER_encode(EC_Domain_Params_Encoding form) const { if(form == EC_DOMPAR_ENC_EXPLICIT) { const u32bit 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_Domain_Params::DER_encode: Unknown encoding"); } std::string EC_Domain_Params::PEM_encode() const { SecureVector der = DER_encode(EC_DOMPAR_ENC_EXPLICIT); return PEM_Code::encode(der, "EC PARAMETERS"); } }