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); }
/* * Encode PKCS#5 PBES2 parameters */ MemoryVector<byte> PBE_PKCS5v20::encode_params() const { return DER_Encoder() .start_cons(SEQUENCE) .encode( AlgorithmIdentifier("PKCS5.PBKDF2", DER_Encoder() .start_cons(SEQUENCE) .encode(salt, OCTET_STRING) .encode(iterations) .encode(key_length) .end_cons() .get_contents() ) ) .encode( AlgorithmIdentifier(block_cipher->name() + "/CBC", DER_Encoder() .encode(iv, OCTET_STRING) .get_contents() ) ) .end_cons() .get_contents(); }
/* * BER encode a PKCS #8 private key, encrypted */ std::vector<uint8_t> BER_encode_encrypted_pbkdf_msec(const Private_Key& key, RandomNumberGenerator& rng, const std::string& pass, std::chrono::milliseconds pbkdf_msec, size_t* pbkdf_iterations, const std::string& cipher, const std::string& pbkdf_hash) { #if defined(BOTAN_HAS_PKCS5_PBES2) const std::pair<AlgorithmIdentifier, std::vector<uint8_t>> pbe_info = pbes2_encrypt_msec(key.private_key_info(), pass, pbkdf_msec, pbkdf_iterations, cipher.empty() ? "AES-256/CBC" : cipher, pbkdf_hash.empty() ? "SHA-256" : pbkdf_hash, rng); std::vector<uint8_t> output; DER_Encoder(output) .start_cons(SEQUENCE) .encode(pbe_info.first) .encode(pbe_info.second, OCTET_STRING) .end_cons(); return output; #else BOTAN_UNUSED(key, rng, pass, pbkdf_msec, pbkdf_iterations, cipher, pbkdf_hash); throw Encoding_Error("BER_encode_encrypted_pbkdf_msec cannot encrypt because PBES2 disabled in build"); #endif }
bool Certificate_Store_In_SQL::insert_cert(const X509_Certificate& cert) { if(find_cert(cert.subject_dn(),cert.subject_key_id())) return false; DER_Encoder enc; auto stmt = m_database->new_statement("INSERT OR REPLACE INTO " + m_prefix + "certificates (\ fingerprint, \ subject_dn, \ key_id, \ priv_fingerprint, \ certificate \ ) VALUES ( ?1, ?2, ?3, ?4, ?5 )"); stmt->bind(1,cert.fingerprint("SHA-256")); cert.subject_dn().encode_into(enc); stmt->bind(2,enc.get_contents_unlocked()); stmt->bind(3,cert.subject_key_id()); stmt->bind(4,std::vector<uint8_t>()); enc = DER_Encoder(); cert.encode_into(enc); stmt->bind(5,enc.get_contents_unlocked()); stmt->spin(); return true; }
AlgorithmIdentifier PSSR::config_for_x509(const Private_Key& key, const std::string& cert_hash_name) const { if(cert_hash_name != m_hash->name()) throw Invalid_Argument("Hash function from opts and hash_fn argument" " need to be identical"); // check that the signature algorithm and the padding scheme fit if(!sig_algo_and_pad_ok(key.algo_name(), "EMSA4")) { throw Invalid_Argument("Encoding scheme with canonical name EMSA4" " not supported for signature algorithm " + key.algo_name()); } AlgorithmIdentifier sig_algo; // hardcoded as RSA is the only valid algorithm for EMSA4 at the moment sig_algo.oid = OIDS::lookup( "RSA/EMSA4" ); const AlgorithmIdentifier hash_id(cert_hash_name, AlgorithmIdentifier::USE_NULL_PARAM); const AlgorithmIdentifier mgf_id("MGF1", hash_id.BER_encode()); DER_Encoder(sig_algo.parameters) .start_cons(SEQUENCE) .start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC).encode(hash_id).end_cons() .start_cons(ASN1_Tag(1), CONTEXT_SPECIFIC).encode(mgf_id).end_cons() .start_cons(ASN1_Tag(2), CONTEXT_SPECIFIC).encode(m_SALT_SIZE).end_cons() .start_cons(ASN1_Tag(3), CONTEXT_SPECIFIC).encode(size_t(1)).end_cons() // trailer field .end_cons(); return sig_algo; }
/* * Put some arbitrary bytes into a SEQUENCE */ std::vector<uint8_t> put_in_sequence(const std::vector<uint8_t>& contents) { return DER_Encoder() .start_cons(SEQUENCE) .raw_bytes(contents) .end_cons() .get_contents_unlocked(); }
std::vector<byte> Curve25519_PublicKey::x509_subject_public_key() const { return DER_Encoder() .start_cons(SEQUENCE) .encode(m_public, OCTET_STRING) .end_cons() .get_contents_unlocked(); }
std::vector<byte> BER_encode(const Public_Key& key) { return DER_Encoder() .start_cons(SEQUENCE) .encode(key.algorithm_identifier()) .encode(key.x509_subject_public_key(), BIT_STRING) .end_cons() .get_contents_unlocked(); }
secure_vector<byte> Curve25519_PrivateKey::pkcs8_private_key() const { return DER_Encoder() .start_cons(SEQUENCE) .encode(m_public, OCTET_STRING) .encode(m_private, OCTET_STRING) .end_cons() .get_contents(); }
/* * Create a CRL */ X509_CRL X509_CA::make_crl(const std::vector<CRL_Entry>& revoked, u32bit crl_number, u32bit next_update, RandomNumberGenerator& rng) const { const size_t X509_CRL_VERSION = 2; if(next_update == 0) next_update = timespec_to_u32bit("7d"); // Totally stupid: ties encoding logic to the return of std::time!! auto current_time = std::chrono::system_clock::now(); auto expire_time = current_time + std::chrono::seconds(next_update); Extensions extensions; extensions.add( new Cert_Extension::Authority_Key_ID(m_cert.subject_key_id())); extensions.add(new Cert_Extension::CRL_Number(crl_number)); // clang-format off const std::vector<byte> crl = X509_Object::make_signed( m_signer, rng, m_ca_sig_algo, DER_Encoder().start_cons(SEQUENCE) .encode(X509_CRL_VERSION-1) .encode(m_ca_sig_algo) .encode(m_cert.issuer_dn()) .encode(X509_Time(current_time)) .encode(X509_Time(expire_time)) .encode_if(revoked.size() > 0, DER_Encoder() .start_cons(SEQUENCE) .encode_list(revoked) .end_cons() ) .start_explicit(0) .start_cons(SEQUENCE) .encode(extensions) .end_cons() .end_explicit() .end_cons() .get_contents()); // clang-format on return X509_CRL(crl); }
secure_vector<byte> EC_PrivateKey::pkcs8_private_key() const { return DER_Encoder() .start_cons(SEQUENCE) .encode(static_cast<size_t>(1)) .encode(BigInt::encode_1363(m_private_key, m_private_key.bytes()), OCTET_STRING) .end_cons() .get_contents(); }
AlgorithmIdentifier GOST_3410_PublicKey::algorithm_identifier() const { std::vector<byte> params = DER_Encoder().start_cons(SEQUENCE) .encode(OID(domain().get_oid())) .end_cons() .get_contents_unlocked(); return AlgorithmIdentifier(get_oid(), params); }
/* * BER encode a PKCS #8 private key, unencrypted */ secure_vector<byte> BER_encode(const Private_Key& key) { const size_t PKCS8_VERSION = 0; return DER_Encoder() .start_cons(SEQUENCE) .encode(PKCS8_VERSION) .encode(key.pkcs8_algorithm_identifier()) .encode(key.pkcs8_private_key(), OCTET_STRING) .end_cons() .get_contents(); }
MemoryVector<byte> EAC1_1_ADO::make_signed(PK_Signer& signer, const MemoryRegion<byte>& tbs_bits, RandomNumberGenerator& rng) { SecureVector<byte> concat_sig = signer.sign_message(tbs_bits, rng); return DER_Encoder() .start_cons(ASN1_Tag(7), APPLICATION) .raw_bytes(tbs_bits) .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) .end_cons() .get_contents(); }
/* * DER encode the parameters */ std::vector<byte> DL_Group::DER_encode(Format format) const { init_check(); if((m_q == 0) && (format != PKCS_3)) throw Encoding_Error("The ANSI DL parameter formats require a subgroup"); if(format == ANSI_X9_57) { return DER_Encoder() .start_cons(SEQUENCE) .encode(m_p) .encode(m_q) .encode(m_g) .end_cons() .get_contents_unlocked(); } else if(format == ANSI_X9_42) { return DER_Encoder() .start_cons(SEQUENCE) .encode(m_p) .encode(m_g) .encode(m_q) .end_cons() .get_contents_unlocked(); } else if(format == PKCS_3) { return DER_Encoder() .start_cons(SEQUENCE) .encode(m_p) .encode(m_g) .end_cons() .get_contents_unlocked(); } throw Invalid_Argument("Unknown DL_Group encoding " + std::to_string(format)); }
MemoryVector<byte> key_bits() const { key->affirm_init(); SecureVector<byte> octstr_secret = BigInt::encode_1363(key->m_private_value, key->m_private_value.bytes()); return DER_Encoder() .start_cons(SEQUENCE) .encode(BigInt(1)) .encode(octstr_secret, OCTET_STRING) .end_cons() .get_contents(); }
/* * Apply the X.509 SIGNED macro */ std::vector<uint8_t> X509_Object::make_signed(PK_Signer* signer, RandomNumberGenerator& rng, const AlgorithmIdentifier& algo, const secure_vector<uint8_t>& tbs_bits) { return DER_Encoder() .start_cons(SEQUENCE) .raw_bytes(tbs_bits) .encode(algo) .encode(signer->sign_message(tbs_bits, rng), BIT_STRING) .end_cons() .get_contents_unlocked(); }
std::vector<uint8_t> 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 = m_curve.get_p().bytes(); return DER_Encoder() .start_cons(SEQUENCE) .encode(ecpVers1) .start_cons(SEQUENCE) .encode(curve_type) .encode(m_curve.get_p()) .end_cons() .start_cons(SEQUENCE) .encode(BigInt::encode_1363(m_curve.get_a(), p_bytes), OCTET_STRING) .encode(BigInt::encode_1363(m_curve.get_b(), p_bytes), OCTET_STRING) .end_cons() .encode(EC2OSP(m_base_point, PointGFp::UNCOMPRESSED), OCTET_STRING) .encode(m_order) .encode(m_cofactor) .end_cons() .get_contents_unlocked(); } else if(form == EC_DOMPAR_ENC_OID) return DER_Encoder().encode(OID(get_oid())).get_contents_unlocked(); else if(form == EC_DOMPAR_ENC_IMPLICITCA) return DER_Encoder().encode_null().get_contents_unlocked(); else throw Internal_Error("EC_Group::DER_encode: Unknown encoding"); }
void EAC1_1_ADO::encode(Pipe& out, X509_Encoding encoding) const { if(encoding == PEM) throw Invalid_Argument("EAC1_1_ADO::encode() cannot PEM encode an EAC object"); SecureVector<byte> concat_sig( EAC1_1_obj<EAC1_1_ADO>::m_sig.get_concatenation()); out.write(DER_Encoder() .start_cons(ASN1_Tag(7), APPLICATION) .raw_bytes(tbs_bits) .encode(concat_sig, OCTET_STRING, ASN1_Tag(55), APPLICATION) .end_cons() .get_contents()); }
secure_vector<byte> IF_Scheme_PrivateKey::pkcs8_private_key() const { return DER_Encoder() .start_cons(SEQUENCE) .encode(static_cast<size_t>(0)) .encode(m_n) .encode(m_e) .encode(m_d) .encode(m_p) .encode(m_q) .encode(m_d1) .encode(m_d2) .encode(m_c) .end_cons() .get_contents(); }
/* * Apply the X.509 SIGNED macro */ std::vector<uint8_t> X509_Object::make_signed(PK_Signer* signer, RandomNumberGenerator& rng, const AlgorithmIdentifier& algo, const secure_vector<uint8_t>& tbs_bits) { const std::vector<uint8_t> signature = signer->sign_message(tbs_bits, rng); std::vector<uint8_t> output; DER_Encoder(output) .start_cons(SEQUENCE) .raw_bytes(tbs_bits) .encode(algo) .encode(signature, BIT_STRING) .end_cons(); return output; }
/* * Create a new certificate */ X509_Certificate X509_CA::make_cert(PK_Signer* signer, RandomNumberGenerator& rng, const AlgorithmIdentifier& sig_algo, const std::vector<byte>& pub_key, const X509_Time& not_before, const X509_Time& not_after, const X509_DN& issuer_dn, const X509_DN& subject_dn, const Extensions& extensions) { const size_t X509_CERT_VERSION = 3; const size_t SERIAL_BITS = 128; BigInt serial_no(rng, SERIAL_BITS); // clang-format off return X509_Certificate(X509_Object::make_signed( signer, rng, sig_algo, DER_Encoder().start_cons(SEQUENCE) .start_explicit(0) .encode(X509_CERT_VERSION-1) .end_explicit() .encode(serial_no) .encode(sig_algo) .encode(issuer_dn) .start_cons(SEQUENCE) .encode(not_before) .encode(not_after) .end_cons() .encode(subject_dn) .raw_bytes(pub_key) .start_explicit(3) .start_cons(SEQUENCE) .encode(extensions) .end_cons() .end_explicit() .end_cons() .get_contents() ));; // clang-format on }
std::vector<byte> Request::BER_encode() const { CertID certid(m_issuer, m_subject); return DER_Encoder().start_cons(SEQUENCE) .start_cons(SEQUENCE) .start_explicit(0) .encode(static_cast<size_t>(0)) // version # .end_explicit() .start_cons(SEQUENCE) .start_cons(SEQUENCE) .encode(certid) .end_cons() .end_cons() .end_cons() .end_cons().get_contents_unlocked(); }
std::vector<uint8_t> Request::BER_encode() const { std::vector<uint8_t> output; DER_Encoder(output).start_cons(SEQUENCE) .start_cons(SEQUENCE) .start_explicit(0) .encode(static_cast<size_t>(0)) // version # .end_explicit() .start_cons(SEQUENCE) .start_cons(SEQUENCE) .encode(m_certid) .end_cons() .end_cons() .end_cons() .end_cons(); return output; }
/* * BER encode a PKCS #8 private key, encrypted */ std::vector<byte> BER_encode(const Private_Key& key, RandomNumberGenerator& rng, const std::string& pass, std::chrono::milliseconds msec, const std::string& pbe_algo) { const auto pbe_params = choose_pbe_params(pbe_algo, key.algo_name()); const std::pair<AlgorithmIdentifier, std::vector<byte>> pbe_info = pbes2_encrypt(PKCS8::BER_encode(key), pass, msec, pbe_params.first, pbe_params.second, rng); return DER_Encoder() .start_cons(SEQUENCE) .encode(pbe_info.first) .encode(pbe_info.second, OCTET_STRING) .end_cons() .get_contents_unlocked(); }
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; }
std::vector<byte> GOST_3410_PublicKey::x509_subject_public_key() const { const BigInt x = public_point().get_affine_x(); const BigInt y = public_point().get_affine_y(); size_t part_size = std::max(x.bytes(), y.bytes()); std::vector<byte> bits(2*part_size); x.binary_encode(&bits[part_size - x.bytes()]); y.binary_encode(&bits[2*part_size - y.bytes()]); // 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]); } return DER_Encoder().encode(bits, OCTET_STRING).get_contents_unlocked(); }
EAC1_1_CVC EAC1_1_CVC_CA::make_cert(std::auto_ptr<PK_Signer> signer, MemoryRegion<byte> const& public_key, ASN1_Car const& car, ASN1_Chr const& chr, byte holder_auth_templ, ASN1_Ced ced, ASN1_Cex cex, RandomNumberGenerator& rng) { OID chat_oid(OIDS::lookup("CertificateHolderAuthorizationTemplate")); MemoryVector<byte> enc_chat_val; enc_chat_val.append(holder_auth_templ); MemoryVector<byte> enc_cpi; enc_cpi.append(0x00); MemoryVector<byte> tbs = DER_Encoder() .encode(enc_cpi, OCTET_STRING, ASN1_Tag(41), APPLICATION) // cpi .encode(car) .raw_bytes(public_key) .encode(chr) .start_cons(ASN1_Tag(76), APPLICATION) .encode(chat_oid) .encode(enc_chat_val, OCTET_STRING, ASN1_Tag(19), APPLICATION) .end_cons() .encode(ced) .encode(cex) .get_contents(); MemoryVector<byte> signed_cert = EAC1_1_CVC::make_signed(signer, EAC1_1_CVC::build_cert_body(tbs), rng); SharedPointer<DataSource> source(new DataSource_Memory(signed_cert)); return EAC1_1_CVC(source); }
secure_vector<uint8_t> Ed25519_PrivateKey::private_key_bits() const { secure_vector<uint8_t> bits(&m_private[0], &m_private[32]); return DER_Encoder().encode(bits, OCTET_STRING).get_contents(); }
/* * Create a PKCS #10 certificate request */ PKCS10_Request create_cert_req(const X509_Cert_Options& opts, const Private_Key& key, const std::string& hash_fn, RandomNumberGenerator& rng) { AlgorithmIdentifier sig_algo; X509_DN subject_dn; AlternativeName subject_alt; opts.sanity_check(); std::vector<byte> pub_key = X509::BER_encode(key); std::unique_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo)); load_info(opts, subject_dn, subject_alt); const size_t PKCS10_VERSION = 0; Extensions extensions; extensions.add( new Cert_Extension::Basic_Constraints(opts.is_CA, opts.path_limit)); extensions.add( new Cert_Extension::Key_Usage( opts.is_CA ? Key_Constraints(KEY_CERT_SIGN | CRL_SIGN) : find_constraints(key, opts.constraints) ) ); extensions.add( new Cert_Extension::Extended_Key_Usage(opts.ex_constraints)); extensions.add( new Cert_Extension::Subject_Alternative_Name(subject_alt)); DER_Encoder tbs_req; tbs_req.start_cons(SEQUENCE) .encode(PKCS10_VERSION) .encode(subject_dn) .raw_bytes(pub_key) .start_explicit(0); if(opts.challenge != "") { ASN1_String challenge(opts.challenge, DIRECTORY_STRING); tbs_req.encode( Attribute("PKCS9.ChallengePassword", DER_Encoder().encode(challenge).get_contents_unlocked() ) ); } tbs_req.encode( Attribute("PKCS9.ExtensionRequest", DER_Encoder() .start_cons(SEQUENCE) .encode(extensions) .end_cons() .get_contents_unlocked() ) ) .end_explicit() .end_cons(); const std::vector<byte> req = X509_Object::make_signed(signer.get(), rng, sig_algo, tbs_req.get_contents()); return PKCS10_Request(req); }