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; }
/* * 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(); }
bool Certificate_Store_In_SQL::insert_key(const X509_Certificate& cert, const Private_Key& key) { insert_cert(cert); if(find_key(cert)) return false; auto pkcs8 = PKCS8::BER_encode(key, m_rng, m_password); auto fpr = key.fingerprint("SHA-256"); auto stmt1 = m_database->new_statement( "INSERT OR REPLACE INTO " + m_prefix + "keys ( fingerprint, key ) VALUES ( ?1, ?2 )"); stmt1->bind(1,fpr); stmt1->bind(2,pkcs8.data(),pkcs8.size()); stmt1->spin(); auto stmt2 = m_database->new_statement( "UPDATE " + m_prefix + "certificates SET priv_fingerprint = ?1 WHERE fingerprint == ?2"); stmt2->bind(1,fpr); stmt2->bind(2,cert.fingerprint("SHA-256")); stmt2->spin(); return true; }
/* * 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 }
/* * BER encode a PKCS #8 private key, encrypted */ std::vector<uint8_t> BER_encode(const Private_Key& key, RandomNumberGenerator& rng, const std::string& pass, std::chrono::milliseconds msec, const std::string& pbe_algo) { #if defined(BOTAN_HAS_PKCS5_PBES2) const auto pbe_params = choose_pbe_params(pbe_algo, key.algo_name()); const std::pair<AlgorithmIdentifier, std::vector<uint8_t>> pbe_info = pbes2_encrypt_msec(PKCS8::BER_encode(key), pass, msec, nullptr, pbe_params.first, pbe_params.second, rng); std::vector<uint8_t> output; DER_Encoder der(output); der.start_cons(SEQUENCE) .encode(pbe_info.first) .encode(pbe_info.second, OCTET_STRING) .end_cons(); return output; #else BOTAN_UNUSED(key, rng, pass, msec, pbe_algo); throw Encoding_Error("PKCS8::BER_encode cannot encrypt because PBES2 was disabled in build"); #endif }
void Certificate_Store_In_SQL::remove_key(const Private_Key& key) { auto fpr = key.fingerprint("SHA-256"); auto stmt = m_database->new_statement("DELETE FROM " + m_prefix + "keys WHERE fingerprint == ?1"); stmt->bind(1,fpr); stmt->spin(); }
/* * Choose a signing format for the key */ std::unique_ptr<PK_Signer> X509_Object::choose_sig_format(AlgorithmIdentifier& sig_algo, const Private_Key& key, RandomNumberGenerator& rng, const std::string& hash_fn, const std::string& padding_algo) { const Signature_Format format = (key.message_parts() > 1) ? DER_SEQUENCE : IEEE_1363; const std::string emsa = choose_sig_algo(sig_algo, key, hash_fn, padding_algo); return std::unique_ptr<PK_Signer>(new PK_Signer(key, rng, emsa, format)); }
std::vector<std::shared_ptr<const X509_Certificate>> Certificate_Store_In_SQL::find_certs_for_key(const Private_Key& key) const { auto fpr = key.fingerprint("SHA-256"); auto stmt = m_database->new_statement("SELECT certificate FROM " + m_prefix + "certificates WHERE priv_fingerprint == ?1"); stmt->bind(1,fpr); std::vector<std::shared_ptr<const X509_Certificate>> certs; while(stmt->step()) { auto blob = stmt->get_blob(0); certs.push_back(std::make_shared<X509_Certificate>( std::vector<uint8_t>(blob.first,blob.first + blob.second))); } return certs; }
/* * 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(); }
std::pair<std::string, Signature_Format> Handshake_State::choose_sig_format(const Private_Key& key, std::string& hash_algo_out, std::string& sig_algo_out, bool for_client_auth, const Policy& policy) const { const std::string sig_algo = key.algo_name(); const std::string hash_algo = choose_hash(sig_algo, this->version(), policy, for_client_auth, client_hello(), cert_req()); if(this->version().supports_negotiable_signature_algorithms()) { hash_algo_out = hash_algo; sig_algo_out = sig_algo; } if(sig_algo == "RSA") { const std::string padding = "EMSA3(" + hash_algo + ")"; return std::make_pair(padding, IEEE_1363); } else if(sig_algo == "DSA" || sig_algo == "ECDSA") { const std::string padding = "EMSA1(" + hash_algo + ")"; return std::make_pair(padding, DER_SEQUENCE); } throw Invalid_Argument(sig_algo + " is invalid/unknown for TLS signatures"); }
/* * BER encode a PKCS #8 private key, unencrypted */ secure_vector<uint8_t> BER_encode(const Private_Key& key) { // keeping around for compat return key.private_key_info(); }