GOST_3410_PublicKey::GOST_3410_PublicKey(const AlgorithmIdentifier& alg_id, const secure_vector<byte>& key_bits) { OID ecc_param_id; // The parameters also includes hash and cipher OIDs BER_Decoder(alg_id.parameters).start_cons(SEQUENCE).decode(ecc_param_id); domain_params = EC_Group(ecc_param_id); secure_vector<byte> bits; BER_Decoder(key_bits).decode(bits, OCTET_STRING); const size_t part_size = bits.size() / 2; // Keys are stored in little endian format (WTF) for(size_t i = 0; i != part_size / 2; ++i) { std::swap(bits[i], bits[part_size-1-i]); std::swap(bits[part_size+i], bits[2*part_size-1-i]); } BigInt x(bits.data(), part_size); BigInt y(&bits[part_size], part_size); public_key = PointGFp(domain().get_curve(), x, y); BOTAN_ASSERT(public_key.on_the_curve(), "Loaded GOST 34.10 public key is on the curve"); }
EC_PrivateKey::EC_PrivateKey(const AlgorithmIdentifier& alg_id, const secure_vector<byte>& key_bits) { m_domain_params = EC_Group(alg_id.parameters); m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT; OID key_parameters; secure_vector<byte> public_key_bits; BER_Decoder(key_bits) .start_cons(SEQUENCE) .decode_and_check<size_t>(1, "Unknown version code for ECC key") .decode_octet_string_bigint(m_private_key) .decode_optional(key_parameters, ASN1_Tag(0), PRIVATE) .decode_optional_string(public_key_bits, BIT_STRING, 1, PRIVATE) .end_cons(); if(!key_parameters.empty() && key_parameters != alg_id.oid) throw Decoding_Error("EC_PrivateKey - inner and outer OIDs did not match"); if(public_key_bits.empty()) { m_public_key = domain().get_base_point() * m_private_key; BOTAN_ASSERT(m_public_key.on_the_curve(), "Public point derived from loaded key was on the curve"); } else { m_public_key = OS2ECP(public_key_bits, domain().get_curve()); // OS2ECP verifies that the point is on the curve } }
PKCS11_EC_PublicKey::PKCS11_EC_PublicKey(Session& session, ObjectHandle handle) : Object(session, 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_domain_encoding = EC_DOMPAR_ENC_EXPLICIT; }
EC_Group::EC_Group(const std::string& str) { 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_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id, const std::vector<uint8_t>& key_bits) : m_domain_params{EC_Group(alg_id.parameters)}, m_public_key{OS2ECP(key_bits, domain().get_curve())} { if (!domain().get_oid().empty()) m_domain_encoding = EC_DOMPAR_ENC_OID; else m_domain_encoding = EC_DOMPAR_ENC_EXPLICIT; }
PKCS11_EC_PublicKey::PKCS11_EC_PublicKey(Session& session, const EC_PublicKeyImportProperties& props) : Object(session, props) { m_domain_params = EC_Group(props.ec_params()); 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_domain_encoding = EC_DOMPAR_ENC_EXPLICIT; }
EC_Group::EC_Group(const OID& domain_oid) { const std::string pem = PEM_for_named_group(OIDS::lookup(domain_oid)); if(pem == "") throw Lookup_Error("No ECC domain data for " + domain_oid.as_string()); *this = EC_Group(pem); m_oid = domain_oid.as_string(); }
EC_Group::EC_Group(const std::vector<uint8_t>& 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; std::vector<uint8_t> 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(m_order) .decode(m_cofactor) .end_cons() .verify_end(); m_curve = CurveGFp(p, a, b); m_base_point = OS2ECP(sv_base_point, m_curve); } else throw Decoding_Error("Unexpected tag while decoding ECC domain params"); }
PKCS11_EC_PrivateKey::PKCS11_EC_PrivateKey(Session& session, const std::vector<uint8_t>& ec_params, const EC_PrivateKeyGenerationProperties& props) : Object(session) { m_domain_params = EC_Group(ec_params); EC_PublicKeyGenerationProperties pub_key_props(ec_params); pub_key_props.set_verify(true); pub_key_props.set_private(false); pub_key_props.set_token(false); // don't create a persistent public key object ObjectHandle pub_key_handle = CK_INVALID_HANDLE; ObjectHandle priv_key_handle = CK_INVALID_HANDLE; Mechanism mechanism = { CKM_EC_KEY_PAIR_GEN, nullptr, 0 }; session.module()->C_GenerateKeyPair(session.handle(), &mechanism, pub_key_props.data(), pub_key_props.count(), props.data(), props.count(), &pub_key_handle, &priv_key_handle); 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()); }
EC_PublicKey::EC_PublicKey(const AlgorithmIdentifier& alg_id, const secure_vector<byte>& key_bits) : m_domain_params{EC_Group(alg_id.parameters)}, m_public_key{OS2ECP(key_bits, domain().get_curve())}, m_domain_encoding{EC_DOMPAR_ENC_EXPLICIT} {}
PKCS11_EC_PrivateKey::PKCS11_EC_PrivateKey(Session& session, const EC_PrivateKeyImportProperties& props) : Object(session, props) { m_domain_params = EC_Group(props.ec_params()); }
PKCS11_EC_PrivateKey::PKCS11_EC_PrivateKey(Session& session, ObjectHandle handle) : Object(session, handle), m_domain_params(), m_public_key() { secure_vector<uint8_t> ec_parameters = get_attribute_value(AttributeType::EcParams); m_domain_params = EC_Group(unlock(ec_parameters)); }