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"); }
Response::Response(const uint8_t response_bits[], size_t response_bits_len) : m_response_bits(response_bits, response_bits + response_bits_len) { m_dummy_response_status = Certificate_Status_Code::OCSP_RESPONSE_INVALID; BER_Decoder response_outer = BER_Decoder(m_response_bits).start_cons(SEQUENCE); size_t resp_status = 0; response_outer.decode(resp_status, ENUMERATED, UNIVERSAL); if(resp_status != 0) throw Exception("OCSP response status " + std::to_string(resp_status)); if(response_outer.more_items()) { BER_Decoder response_bytes = response_outer.start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC).start_cons(SEQUENCE); response_bytes.decode_and_check(OID("1.3.6.1.5.5.7.48.1.1"), "Unknown response type in OCSP response"); BER_Decoder basicresponse = BER_Decoder(response_bytes.get_next_octet_string()).start_cons(SEQUENCE); basicresponse.start_cons(SEQUENCE) .raw_bytes(m_tbs_bits) .end_cons() .decode(m_sig_algo) .decode(m_signature, BIT_STRING); decode_optional_list(basicresponse, ASN1_Tag(0), m_certs); size_t responsedata_version = 0; Extensions extensions; BER_Decoder(m_tbs_bits) .decode_optional(responsedata_version, ASN1_Tag(0), ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) .decode_optional(m_signer_name, ASN1_Tag(1), ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) .decode_optional_string(m_key_hash, OCTET_STRING, 2, ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) .decode(m_produced_at) .decode_list(m_responses) .decode_optional(extensions, ASN1_Tag(1), ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)); } response_outer.end_cons(); }
void EAC1_1_ADO::decode_info(DataSource& source, SecureVector<byte> & res_tbs_bits, ECDSA_Signature & res_sig) { SecureVector<byte> concat_sig; SecureVector<byte> cert_inner_bits; ASN1_Car car; BER_Decoder(source) .start_cons(ASN1_Tag(7)) .start_cons(ASN1_Tag(33)) .raw_bytes(cert_inner_bits) .end_cons() .decode(car) .decode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) .end_cons(); SecureVector<byte> enc_cert = DER_Encoder() .start_cons(ASN1_Tag(33), APPLICATION) .raw_bytes(cert_inner_bits) .end_cons() .get_contents(); res_tbs_bits = enc_cert; res_tbs_bits += DER_Encoder().encode(car).get_contents(); res_sig = decode_concatenation(concat_sig); }
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 } }
DL_Scheme_PublicKey::DL_Scheme_PublicKey(const AlgorithmIdentifier& alg_id, const std::vector<uint8_t>& key_bits, DL_Group::Format format) : m_group(alg_id.get_parameters(), format) { BER_Decoder(key_bits).decode(m_y); }
/* * Decode PKCS#5 PBES2 parameters */ void PBE_PKCS5v20::decode_params(DataSource& source) { AlgorithmIdentifier kdf_algo, enc_algo; BER_Decoder(source) .start_cons(SEQUENCE) .decode(kdf_algo) .decode(enc_algo) .verify_end() .end_cons(); if(kdf_algo.oid == OIDS::lookup("PKCS5.PBKDF2")) { BER_Decoder(kdf_algo.parameters) .start_cons(SEQUENCE) .decode(salt, OCTET_STRING) .decode(iterations) .decode_optional(key_length, INTEGER, UNIVERSAL) .verify_end() .end_cons(); } else throw Decoding_Error("PBE-PKCS5 v2.0: Unknown KDF algorithm " + kdf_algo.oid.as_string()); Algorithm_Factory& af = global_state().algorithm_factory(); std::string cipher = OIDS::lookup(enc_algo.oid); std::vector<std::string> cipher_spec = split_on(cipher, '/'); if(cipher_spec.size() != 2) throw Decoding_Error("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher); if(!known_cipher(cipher_spec[0]) || cipher_spec[1] != "CBC") throw Decoding_Error("PBE-PKCS5 v2.0: Don't know param format for " + cipher); BER_Decoder(enc_algo.parameters).decode(iv, OCTET_STRING).verify_end(); block_cipher = af.make_block_cipher(cipher_spec[0]); hash_function = af.make_hash_function("SHA-160"); if(key_length == 0) key_length = block_cipher->maximum_keylength(); if(salt.size() < 8) throw Decoding_Error("PBE-PKCS5 v2.0: Encoded salt is too small"); }
DL_Scheme_PrivateKey::DL_Scheme_PrivateKey(const AlgorithmIdentifier& alg_id, const secure_vector<uint8_t>& key_bits, DL_Group::Format format) { m_group.BER_decode(alg_id.get_parameters(), format); BER_Decoder(key_bits).decode(m_x); }
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 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"); }
Curve25519_PublicKey::Curve25519_PublicKey(const AlgorithmIdentifier&, const secure_vector<byte>& key_bits) { BER_Decoder(key_bits) .start_cons(SEQUENCE) .decode(m_public, OCTET_STRING) .verify_end() .end_cons(); size_check(m_public.size(), "public key"); }
Ed25519_PrivateKey::Ed25519_PrivateKey(const AlgorithmIdentifier&, const secure_vector<uint8_t>& key_bits) { secure_vector<uint8_t> bits; BER_Decoder(key_bits).decode(bits, OCTET_STRING).discard_remaining(); if(bits.size() != 32) throw Decoding_Error("Invalid size for Ed25519 private key"); m_public.resize(32); m_private.resize(64); ed25519_gen_keypair(m_public.data(), m_private.data(), bits.data()); }
/* * Extract a public key and return it */ Public_Key* load_key(DataSource& source) { try { AlgorithmIdentifier alg_id; secure_vector<byte> key_bits; if(ASN1::maybe_BER(source) && !PEM_Code::matches(source)) { BER_Decoder(source) .start_cons(SEQUENCE) .decode(alg_id) .decode(key_bits, BIT_STRING) .verify_end() .end_cons(); } else { DataSource_Memory ber( PEM_Code::decode_check_label(source, "PUBLIC KEY") ); BER_Decoder(ber) .start_cons(SEQUENCE) .decode(alg_id) .decode(key_bits, BIT_STRING) .verify_end() .end_cons(); } if(key_bits.empty()) throw Decoding_Error("X.509 public key decoding failed"); return make_public_key(alg_id, key_bits); } catch(Decoding_Error& e) { throw Decoding_Error("X.509 public key decoding failed: " + std::string(e.what())); } }
std::vector<byte> CertID::extract_key_bitstr(const X509_Certificate& cert) const { const auto key_bits = cert.subject_public_key_bits(); AlgorithmIdentifier public_key_algid; std::vector<byte> public_key_bitstr; BER_Decoder(key_bits) .decode(public_key_algid) .decode(public_key_bitstr, BIT_STRING); return public_key_bitstr; }
secure_vector<uint8_t> pbes2_decrypt(const secure_vector<uint8_t>& key_bits, const std::string& passphrase, const std::vector<uint8_t>& params) { AlgorithmIdentifier kdf_algo, enc_algo; BER_Decoder(params) .start_cons(SEQUENCE) .decode(kdf_algo) .decode(enc_algo) .end_cons(); const std::string cipher = OIDS::lookup(enc_algo.get_oid()); const std::vector<std::string> cipher_spec = split_on(cipher, '/'); if(cipher_spec.size() != 2) throw Decoding_Error("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher); if(!known_pbes_cipher_mode(cipher_spec[1])) throw Decoding_Error("PBE-PKCS5 v2.0: Don't know param format for " + cipher); secure_vector<uint8_t> iv; BER_Decoder(enc_algo.get_parameters()).decode(iv, OCTET_STRING).verify_end(); std::unique_ptr<Cipher_Mode> dec = Cipher_Mode::create(cipher, DECRYPTION); if(!dec) throw Decoding_Error("PBE-PKCS5 cannot decrypt no cipher " + cipher); dec->set_key(derive_key(passphrase, kdf_algo, dec->key_spec().maximum_keylength())); dec->start(iv); secure_vector<uint8_t> buf = key_bits; dec->finish(buf); return buf; }
Curve25519_PrivateKey::Curve25519_PrivateKey(const AlgorithmIdentifier&, const secure_vector<byte>& key_bits, RandomNumberGenerator& rng) { BER_Decoder(key_bits) .start_cons(SEQUENCE) .decode(m_public, OCTET_STRING) .decode(m_private, OCTET_STRING) .verify_end() .end_cons(); size_check(m_public.size(), "public key"); size_check(m_private.size(), "private key"); load_check(rng); }
void key_bits(const MemoryRegion<byte>& bits) { u32bit version; SecureVector<byte> octstr_secret; BER_Decoder(bits) .start_cons(SEQUENCE) .decode(version) .decode(octstr_secret, OCTET_STRING) .verify_end() .end_cons(); key->m_private_value = BigInt::decode(octstr_secret, octstr_secret.size()); if(version != 1) throw Decoding_Error("Wrong PKCS #1 key format version for EC key"); key->PKCS8_load_hook(); }
IF_Scheme_PrivateKey::IF_Scheme_PrivateKey(RandomNumberGenerator& rng, const AlgorithmIdentifier&, const secure_vector<byte>& key_bits) { BER_Decoder(key_bits) .start_cons(SEQUENCE) .decode_and_check<size_t>(0, "Unknown PKCS #1 key format version") .decode(m_n) .decode(m_e) .decode(m_d) .decode(m_p) .decode(m_q) .decode(m_d1) .decode(m_d2) .decode(m_c) .end_cons(); load_check(rng); }
void EAC1_1_ADO::force_decode() { SecureVector<byte> inner_cert; BER_Decoder(tbs_bits) .start_cons(ASN1_Tag(33)) .raw_bytes(inner_cert) .end_cons() .decode(m_car) .verify_end(); SecureVector<byte> req_bits = DER_Encoder() .start_cons(ASN1_Tag(33), APPLICATION) .raw_bytes(inner_cert) .end_cons() .get_contents(); DataSource_Memory req_source(req_bits); m_req = EAC1_1_Req(req_source); sig_algo = m_req.sig_algo; }
Response::Response(const Certificate_Store& trusted_roots, const std::vector<byte>& response_bits) { BER_Decoder response_outer = BER_Decoder(response_bits).start_cons(SEQUENCE); size_t resp_status = 0; response_outer.decode(resp_status, ENUMERATED, UNIVERSAL); if(resp_status != 0) throw std::runtime_error("OCSP response status " + std::to_string(resp_status)); if(response_outer.more_items()) { BER_Decoder response_bytes = response_outer.start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC).start_cons(SEQUENCE); response_bytes.decode_and_check(OID("1.3.6.1.5.5.7.48.1.1"), "Unknown response type in OCSP response"); BER_Decoder basicresponse = BER_Decoder(response_bytes.get_next_octet_string()).start_cons(SEQUENCE); std::vector<byte> tbs_bits; AlgorithmIdentifier sig_algo; std::vector<byte> signature; std::vector<X509_Certificate> certs; basicresponse.start_cons(SEQUENCE) .raw_bytes(tbs_bits) .end_cons() .decode(sig_algo) .decode(signature, BIT_STRING); decode_optional_list(basicresponse, ASN1_Tag(0), certs); size_t responsedata_version = 0; X509_DN name; std::vector<byte> key_hash; X509_Time produced_at; Extensions extensions; BER_Decoder(tbs_bits) .decode_optional(responsedata_version, ASN1_Tag(0), ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) .decode_optional(name, ASN1_Tag(1), ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) .decode_optional_string(key_hash, OCTET_STRING, 2, ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) .decode(produced_at) .decode_list(m_responses) .decode_optional(extensions, ASN1_Tag(1), ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)); if(certs.empty()) { if(auto cert = trusted_roots.find_cert(name, std::vector<byte>())) certs.push_back(*cert); else throw std::runtime_error("Could not find certificate that signed OCSP response"); } check_signature(tbs_bits, sig_algo, signature, trusted_roots, certs); } response_outer.end_cons(); }
secure_vector<uint8_t> pbes2_decrypt(const secure_vector<uint8_t>& key_bits, const std::string& passphrase, const std::vector<uint8_t>& params) { AlgorithmIdentifier kdf_algo, enc_algo; BER_Decoder(params) .start_cons(SEQUENCE) .decode(kdf_algo) .decode(enc_algo) .end_cons(); AlgorithmIdentifier prf_algo; if(kdf_algo.oid != OIDS::lookup("PKCS5.PBKDF2")) throw Decoding_Error("PBE-PKCS5 v2.0: Unknown KDF algorithm " + kdf_algo.oid.as_string()); secure_vector<uint8_t> salt; size_t iterations = 0, key_length = 0; BER_Decoder(kdf_algo.parameters) .start_cons(SEQUENCE) .decode(salt, OCTET_STRING) .decode(iterations) .decode_optional(key_length, INTEGER, UNIVERSAL) .decode_optional(prf_algo, SEQUENCE, CONSTRUCTED, AlgorithmIdentifier("HMAC(SHA-160)", AlgorithmIdentifier::USE_NULL_PARAM)) .end_cons(); const std::string cipher = OIDS::lookup(enc_algo.oid); const std::vector<std::string> cipher_spec = split_on(cipher, '/'); if(cipher_spec.size() != 2) throw Decoding_Error("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher); if(cipher_spec[1] != "CBC" && cipher_spec[1] != "GCM") throw Decoding_Error("PBE-PKCS5 v2.0: Don't know param format for " + cipher); if(salt.size() < 8) throw Decoding_Error("PBE-PKCS5 v2.0: Encoded salt is too small"); secure_vector<uint8_t> iv; BER_Decoder(enc_algo.parameters).decode(iv, OCTET_STRING).verify_end(); const std::string prf = OIDS::lookup(prf_algo.oid); std::unique_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(" + prf + ")")); std::unique_ptr<Cipher_Mode> dec(get_cipher_mode(cipher, DECRYPTION)); if(!dec) throw Decoding_Error("PBE-PKCS5 cannot decrypt no cipher " + cipher); if(key_length == 0) key_length = dec->key_spec().maximum_keylength(); dec->set_key(pbkdf->pbkdf_iterations(key_length, passphrase, salt.data(), salt.size(), iterations)); dec->start(iv); secure_vector<uint8_t> buf = key_bits; dec->finish(buf); return buf; }