From 840fc0e4dfcb9578b9b1bfd3da0b8fd8a1fa8534 Mon Sep 17 00:00:00 2001 From: lloyd Date: Wed, 19 Nov 2014 12:45:07 +0000 Subject: Cleanup PBES2 and add GCM support --- doc/relnotes/1_11_10.rst | 6 ++ src/lib/asn1/oid_lookup/default.cpp | 5 + src/lib/constructs/pbes2/info.txt | 12 +++ src/lib/constructs/pbes2/pbes2.cpp | 189 +++++++++++++++++++++++++++++++++ src/lib/constructs/pbes2/pbes2.h | 50 +++++++++ src/lib/pbe/get_pbe.cpp | 89 ---------------- src/lib/pbe/get_pbe.h | 44 -------- src/lib/pbe/info.txt | 7 -- src/lib/pbe/pbe.h | 39 ------- src/lib/pbe/pbes2/info.txt | 14 --- src/lib/pbe/pbes2/pbes2.cpp | 202 ------------------------------------ src/lib/pbe/pbes2/pbes2.h | 68 ------------ src/lib/pubkey/info.txt | 2 +- src/lib/pubkey/pkcs8.cpp | 36 ++++--- 14 files changed, 284 insertions(+), 479 deletions(-) create mode 100644 src/lib/constructs/pbes2/info.txt create mode 100644 src/lib/constructs/pbes2/pbes2.cpp create mode 100644 src/lib/constructs/pbes2/pbes2.h delete mode 100644 src/lib/pbe/get_pbe.cpp delete mode 100644 src/lib/pbe/get_pbe.h delete mode 100644 src/lib/pbe/info.txt delete mode 100644 src/lib/pbe/pbe.h delete mode 100644 src/lib/pbe/pbes2/info.txt delete mode 100644 src/lib/pbe/pbes2/pbes2.cpp delete mode 100644 src/lib/pbe/pbes2/pbes2.h diff --git a/doc/relnotes/1_11_10.rst b/doc/relnotes/1_11_10.rst index 58631e6f0..fd34b5c99 100644 --- a/doc/relnotes/1_11_10.rst +++ b/doc/relnotes/1_11_10.rst @@ -38,6 +38,12 @@ Version 1.11.10, Not Yet Released user to directly specify the maximum false negative probability they are willing to accept. +* PKCS #8 private keys can now be encrypted using GCM mode instead of + unauthenticated CBC. The default remains CBC for compatability. + +* The default PKCS #8 encryption scheme has changed to use PBKDF2 with + SHA-256 instead of SHA-1 + * Fix decoding indefinite length BER constructs that contain a context sensitive tag of zero. Github pull 26 from Janusz Chorko. diff --git a/src/lib/asn1/oid_lookup/default.cpp b/src/lib/asn1/oid_lookup/default.cpp index 95a700f18..490b621fd 100644 --- a/src/lib/asn1/oid_lookup/default.cpp +++ b/src/lib/asn1/oid_lookup/default.cpp @@ -49,6 +49,11 @@ void set_defaults() OIDS::add_oidstr("2.16.840.1.101.3.4.1.42", "AES-256/CBC"); OIDS::add_oidstr("1.2.410.200004.1.4", "SEED/CBC"); // RFC 4010 OIDS::add_oidstr("1.3.6.1.4.1.25258.3.1", "Serpent/CBC"); + OIDS::add_oidstr("1.3.6.1.4.1.25258.3.2", "Threefish-512/CBC"); + + OIDS::add_oidstr("2.16.840.1.101.3.4.1.6", "AES-128/GCM"); + OIDS::add_oidstr("2.16.840.1.101.3.4.1.26", "AES-192/GCM"); + OIDS::add_oidstr("2.16.840.1.101.3.4.1.46", "AES-256/GCM"); /* Hash Functions */ OIDS::add_oidstr("1.2.840.113549.2.5", "MD5"); diff --git a/src/lib/constructs/pbes2/info.txt b/src/lib/constructs/pbes2/info.txt new file mode 100644 index 000000000..e1f260966 --- /dev/null +++ b/src/lib/constructs/pbes2/info.txt @@ -0,0 +1,12 @@ +define PKCS5_PBES2 20141119 + + +algo_factory +asn1 +block +cbc +hash +hmac +oid_lookup +pbkdf2 + diff --git a/src/lib/constructs/pbes2/pbes2.cpp b/src/lib/constructs/pbes2/pbes2.cpp new file mode 100644 index 000000000..afce0fce1 --- /dev/null +++ b/src/lib/constructs/pbes2/pbes2.cpp @@ -0,0 +1,189 @@ +/* +* PKCS #5 PBES2 +* (C) 1999-2008,2014 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(BOTAN_HAS_AEAD_GCM) + #include +#endif + +namespace Botan { + +namespace { + +/* +* Encode PKCS#5 PBES2 parameters +*/ +std::vector encode_pbes2_params(const std::string& cipher, + const std::string& prf, + const secure_vector& salt, + const secure_vector& iv, + size_t iterations, + size_t key_length) + { + return DER_Encoder() + .start_cons(SEQUENCE) + .encode( + AlgorithmIdentifier("PKCS5.PBKDF2", + DER_Encoder() + .start_cons(SEQUENCE) + .encode(salt, OCTET_STRING) + .encode(iterations) + .encode(key_length) + .encode_if( + prf != "HMAC(SHA-160)", + AlgorithmIdentifier(prf, AlgorithmIdentifier::USE_NULL_PARAM)) + .end_cons() + .get_contents_unlocked() + ) + ) + .encode( + AlgorithmIdentifier(cipher, + DER_Encoder().encode(iv, OCTET_STRING).get_contents_unlocked() + ) + ) + .end_cons() + .get_contents_unlocked(); + } + +} + +/* +* PKCS#5 v2.0 PBE Constructor +*/ +std::pair> +pbes2_encrypt(const secure_vector& key_bits, + const std::string& passphrase, + std::chrono::milliseconds msec, + const std::string& cipher, + const std::string& digest, + RandomNumberGenerator& rng, + Algorithm_Factory& af) + { + const std::string prf = "HMAC(" + digest + ")"; + + const std::vector cipher_spec = split_on(cipher, '/'); + if(cipher_spec.size() != 2) + throw Decoding_Error("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher); + + const secure_vector salt = rng.random_vec(12); + + std::unique_ptr enc; + + if(cipher_spec[1] == "CBC") + enc.reset(new CBC_Encryption(af.make_block_cipher(cipher_spec[0]), new PKCS7_Padding)); +#if defined(BOTAN_HAS_AEAD_GCM) + else if(cipher_spec[1] == "GCM") + enc.reset(new GCM_Encryption(af.make_block_cipher(cipher_spec[0]))); +#endif + else + throw Decoding_Error("PBE-PKCS5 v2.0: Don't know param format for " + cipher); + + PKCS5_PBKDF2 pbkdf(af.make_mac(prf)); + + const size_t key_length = enc->key_spec().maximum_keylength(); + size_t iterations = 0; + + secure_vector iv = rng.random_vec(enc->default_nonce_length()); + + enc->set_key(pbkdf.derive_key(key_length, passphrase, &salt[0], salt.size(), + msec, iterations).bits_of()); + + enc->start(iv); + secure_vector buf = key_bits; + enc->finish(buf); + + AlgorithmIdentifier id( + OIDS::lookup("PBE-PKCS5v20"), + encode_pbes2_params(cipher, prf, salt, iv, iterations, key_length)); + + return std::make_pair(id, unlock(buf)); + } + +secure_vector +pbes2_decrypt(const secure_vector& key_bits, + const std::string& passphrase, + const std::vector& params, + Algorithm_Factory& af) + { + AlgorithmIdentifier kdf_algo, enc_algo; + + BER_Decoder(params) + .start_cons(SEQUENCE) + .decode(kdf_algo) + .decode(enc_algo) + .verify_end() + .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 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)) + .verify_end() + .end_cons(); + + const std::string cipher = OIDS::lookup(enc_algo.oid); + const std::vector cipher_spec = split_on(cipher, '/'); + if(cipher_spec.size() != 2) + throw Decoding_Error("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher); + + if(salt.size() < 8) + throw Decoding_Error("PBE-PKCS5 v2.0: Encoded salt is too small"); + + secure_vector iv; + BER_Decoder(enc_algo.parameters).decode(iv, OCTET_STRING).verify_end(); + + PKCS5_PBKDF2 pbkdf(af.make_mac(OIDS::lookup(prf_algo.oid))); + + std::unique_ptr dec; + + if(cipher_spec[1] == "CBC") + dec.reset(new CBC_Decryption(af.make_block_cipher(cipher_spec[0]), new PKCS7_Padding)); +#if defined(BOTAN_HAS_AEAD_GCM) + else if(cipher_spec[1] == "GCM") + dec.reset(new GCM_Decryption(af.make_block_cipher(cipher_spec[0]))); +#endif + else + throw Decoding_Error("PBE-PKCS5 v2.0: Don't know param format for " + cipher); + + if(key_length == 0) + key_length = dec->key_spec().maximum_keylength(); + + dec->set_key(pbkdf.derive_key(key_length, passphrase, &salt[0], salt.size(), + iterations).bits_of()); + + dec->start(iv); + + secure_vector buf = key_bits; + dec->finish(buf); + + return buf; + } + +} diff --git a/src/lib/constructs/pbes2/pbes2.h b/src/lib/constructs/pbes2/pbes2.h new file mode 100644 index 000000000..ac88f6adb --- /dev/null +++ b/src/lib/constructs/pbes2/pbes2.h @@ -0,0 +1,50 @@ +/* +* PKCS #5 v2.0 PBE +* (C) 1999-2007,2014 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_PBE_PKCS_v20_H__ +#define BOTAN_PBE_PKCS_v20_H__ + +#include +#include +#include +#include +#include + +namespace Botan { + +/** +* Encrypt with PBES2 from PKCS #5 v2.0 +* @param passphrase the passphrase to use for encryption +* @param msec how many milliseconds to run PBKDF2 +* @param cipher specifies the block cipher to use to encrypt +* @param digest specifies the PRF to use with PBKDF2 (eg "HMAC(SHA-1)") +* @param rng a random number generator +*/ +std::pair> +BOTAN_DLL pbes2_encrypt(const secure_vector& key_bits, + const std::string& passphrase, + std::chrono::milliseconds msec, + const std::string& cipher, + const std::string& digest, + RandomNumberGenerator& rng, + Algorithm_Factory& af); + +/** +* Decrypt a PKCS #5 v2.0 encrypted stream +* @param key_bits the input +* @param passphrase the passphrase to use for decryption +* @param params the PBES2 parameters +*/ +secure_vector +BOTAN_DLL pbes2_decrypt(const secure_vector& key_bits, + const std::string& passphrase, + const std::vector& params, + Algorithm_Factory& af); + +} + +#endif diff --git a/src/lib/pbe/get_pbe.cpp b/src/lib/pbe/get_pbe.cpp deleted file mode 100644 index 5cb5ccc88..000000000 --- a/src/lib/pbe/get_pbe.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* -* PBE Retrieval -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include -#include -#include -#include -#include - -#if defined(BOTAN_HAS_PBE_PKCS_V20) - #include - #include -#endif - -namespace Botan { - -/* -* Get an encryption PBE, set new parameters -*/ -PBE* get_pbe(const std::string& algo_spec, - const std::string& passphrase, - std::chrono::milliseconds msec, - RandomNumberGenerator& rng) - { - SCAN_Name request(algo_spec); - - const std::string pbe = request.algo_name(); - std::string digest_name = request.arg(0); - const std::string cipher = request.arg(1); - - std::vector cipher_spec = split_on(cipher, '/'); - if(cipher_spec.size() != 2) - throw Invalid_Argument("PBE: Invalid cipher spec " + cipher); - - const std::string cipher_algo = SCAN_Name::deref_alias(cipher_spec[0]); - const std::string cipher_mode = cipher_spec[1]; - - if(cipher_mode != "CBC") - throw Invalid_Argument("PBE: Invalid cipher mode " + cipher); - - Algorithm_Factory& af = global_state().algorithm_factory(); - - const BlockCipher* block_cipher = af.prototype_block_cipher(cipher_algo); - if(!block_cipher) - throw Algorithm_Not_Found(cipher_algo); - - const HashFunction* hash_function = af.prototype_hash_function(digest_name); - if(!hash_function) - throw Algorithm_Not_Found(digest_name); - - if(request.arg_count() != 2) - throw Invalid_Algorithm_Name(algo_spec); - -#if defined(BOTAN_HAS_PBE_PKCS_V20) - if(pbe == "PBE-PKCS5v20") - return new PBE_PKCS5v20(block_cipher->clone(), - new HMAC(hash_function->clone()), - passphrase, - msec, - rng); -#endif - - throw Algorithm_Not_Found(algo_spec); - } - -/* -* Get a decryption PBE, decode parameters -*/ -PBE* get_pbe(const OID& pbe_oid, - const std::vector& params, - const std::string& passphrase) - { - SCAN_Name request(OIDS::lookup(pbe_oid)); - - const std::string pbe = request.algo_name(); - -#if defined(BOTAN_HAS_PBE_PKCS_V20) - if(pbe == "PBE-PKCS5v20") - return new PBE_PKCS5v20(params, passphrase); -#endif - - throw Algorithm_Not_Found(pbe_oid.as_string()); - } - -} diff --git a/src/lib/pbe/get_pbe.h b/src/lib/pbe/get_pbe.h deleted file mode 100644 index df87c0547..000000000 --- a/src/lib/pbe/get_pbe.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -* PBE Lookup -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_LOOKUP_PBE_H__ -#define BOTAN_LOOKUP_PBE_H__ - -#include -#include -#include -#include - -namespace Botan { - -/** -* Factory function for PBEs. -* @param algo_spec the name of the PBE algorithm to retrieve -* @param passphrase the passphrase to use for encryption -* @param msec how many milliseconds to run the PBKDF -* @param rng a random number generator -* @return pointer to a PBE with randomly created parameters -*/ -BOTAN_DLL PBE* get_pbe(const std::string& algo_spec, - const std::string& passphrase, - std::chrono::milliseconds msec, - RandomNumberGenerator& rng); - -/** -* Factory function for PBEs. -* @param pbe_oid the oid of the desired PBE -* @param params a DataSource providing the DER encoded parameters to use -* @param passphrase the passphrase to use for decryption -* @return pointer to the PBE with the specified parameters -*/ -BOTAN_DLL PBE* get_pbe(const OID& pbe_oid, - const std::vector& params, - const std::string& passphrase); - -} - -#endif diff --git a/src/lib/pbe/info.txt b/src/lib/pbe/info.txt deleted file mode 100644 index 0436c4efd..000000000 --- a/src/lib/pbe/info.txt +++ /dev/null @@ -1,7 +0,0 @@ -define PASSWORD_BASED_ENCRYPTION 20131128 - - -filters -libstate -oid_lookup - diff --git a/src/lib/pbe/pbe.h b/src/lib/pbe/pbe.h deleted file mode 100644 index 45c98e2c8..000000000 --- a/src/lib/pbe/pbe.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -* PBE -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_PBE_BASE_H__ -#define BOTAN_PBE_BASE_H__ - -#include -#include -#include -#include - -namespace Botan { - -/** -* Password Based Encryption (PBE) Filter. -*/ -class BOTAN_DLL PBE : public Filter - { - public: - /** - * DER encode the params (the number of iterations and the salt value) - * @return encoded params - */ - virtual std::vector encode_params() const = 0; - - /** - * Get this PBE's OID. - * @return object identifier - */ - virtual OID get_oid() const = 0; - }; - -} - -#endif diff --git a/src/lib/pbe/pbes2/info.txt b/src/lib/pbe/pbes2/info.txt deleted file mode 100644 index ba7d77774..000000000 --- a/src/lib/pbe/pbes2/info.txt +++ /dev/null @@ -1,14 +0,0 @@ -define PBE_PKCS_V20 20131128 - - -algo_factory -asn1 -block -cbc -filters -hash -hmac -libstate -oid_lookup -pbkdf2 - diff --git a/src/lib/pbe/pbes2/pbes2.cpp b/src/lib/pbe/pbes2/pbes2.cpp deleted file mode 100644 index 131905374..000000000 --- a/src/lib/pbe/pbes2/pbes2.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* -* PKCS #5 PBES2 -* (C) 1999-2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Botan { - -/* -* Encrypt some bytes using PBES2 -*/ -void PBE_PKCS5v20::write(const byte input[], size_t length) - { - m_pipe.write(input, length); - flush_pipe(true); - } - -/* -* Start encrypting with PBES2 -*/ -void PBE_PKCS5v20::start_msg() - { - m_pipe.append(get_cipher(m_block_cipher->name() + "/CBC/PKCS7", - m_key, m_iv, m_direction)); - - m_pipe.start_msg(); - if(m_pipe.message_count() > 1) - m_pipe.set_default_msg(m_pipe.default_msg() + 1); - } - -/* -* Finish encrypting with PBES2 -*/ -void PBE_PKCS5v20::end_msg() - { - m_pipe.end_msg(); - flush_pipe(false); - m_pipe.reset(); - } - -/* -* Flush the pipe -*/ -void PBE_PKCS5v20::flush_pipe(bool safe_to_skip) - { - if(safe_to_skip && m_pipe.remaining() < 64) - return; - - secure_vector buffer(DEFAULT_BUFFERSIZE); - while(m_pipe.remaining()) - { - const size_t got = m_pipe.read(&buffer[0], buffer.size()); - send(buffer, got); - } - } - -/* -* Encode PKCS#5 PBES2 parameters -*/ -std::vector PBE_PKCS5v20::encode_params() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode( - AlgorithmIdentifier("PKCS5.PBKDF2", - DER_Encoder() - .start_cons(SEQUENCE) - .encode(m_salt, OCTET_STRING) - .encode(m_iterations) - .encode(m_key_length) - .encode_if( - m_prf->name() != "HMAC(SHA-160)", - AlgorithmIdentifier(m_prf->name(), - AlgorithmIdentifier::USE_NULL_PARAM)) - .end_cons() - .get_contents_unlocked() - ) - ) - .encode( - AlgorithmIdentifier(m_block_cipher->name() + "/CBC", - DER_Encoder().encode(m_iv, OCTET_STRING).get_contents_unlocked() - ) - ) - .end_cons() - .get_contents_unlocked(); - } - -/* -* Return an OID for PBES2 -*/ -OID PBE_PKCS5v20::get_oid() const - { - return OIDS::lookup("PBE-PKCS5v20"); - } - -std::string PBE_PKCS5v20::name() const - { - return "PBE-PKCS5v20(" + m_block_cipher->name() + "," + - m_prf->name() + ")"; - } - -/* -* PKCS#5 v2.0 PBE Constructor -*/ -PBE_PKCS5v20::PBE_PKCS5v20(BlockCipher* cipher, - MessageAuthenticationCode* mac, - const std::string& passphrase, - std::chrono::milliseconds msec, - RandomNumberGenerator& rng) : - m_direction(ENCRYPTION), - m_block_cipher(cipher), - m_prf(mac), - m_salt(rng.random_vec(12)), - m_iv(rng.random_vec(m_block_cipher->block_size())), - m_iterations(0), - m_key_length(m_block_cipher->maximum_keylength()) - { - PKCS5_PBKDF2 pbkdf(m_prf->clone()); - - m_key = pbkdf.derive_key(m_key_length, passphrase, - &m_salt[0], m_salt.size(), - msec, m_iterations).bits_of(); - } - -/* -* PKCS#5 v2.0 PBE Constructor -*/ -PBE_PKCS5v20::PBE_PKCS5v20(const std::vector& params, - const std::string& passphrase) : - m_direction(DECRYPTION), - m_block_cipher(nullptr), - m_prf(nullptr) - { - AlgorithmIdentifier kdf_algo, enc_algo; - - BER_Decoder(params) - .start_cons(SEQUENCE) - .decode(kdf_algo) - .decode(enc_algo) - .verify_end() - .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()); - - BER_Decoder(kdf_algo.parameters) - .start_cons(SEQUENCE) - .decode(m_salt, OCTET_STRING) - .decode(m_iterations) - .decode_optional(m_key_length, INTEGER, UNIVERSAL) - .decode_optional(prf_algo, SEQUENCE, CONSTRUCTED, - AlgorithmIdentifier("HMAC(SHA-160)", - AlgorithmIdentifier::USE_NULL_PARAM)) - .verify_end() - .end_cons(); - - Algorithm_Factory& af = global_state().algorithm_factory(); - - std::string cipher = OIDS::lookup(enc_algo.oid); - std::vector 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") - throw Decoding_Error("PBE-PKCS5 v2.0: Don't know param format for " + - cipher); - - BER_Decoder(enc_algo.parameters).decode(m_iv, OCTET_STRING).verify_end(); - - m_block_cipher.reset(af.make_block_cipher(cipher_spec[0])); - m_prf.reset(af.make_mac(OIDS::lookup(prf_algo.oid))); - - if(m_key_length == 0) - m_key_length = m_block_cipher->maximum_keylength(); - - if(m_salt.size() < 8) - throw Decoding_Error("PBE-PKCS5 v2.0: Encoded salt is too small"); - - PKCS5_PBKDF2 pbkdf(m_prf->clone()); - - m_key = pbkdf.derive_key(m_key_length, passphrase, - &m_salt[0], m_salt.size(), - m_iterations).bits_of(); - } - -} diff --git a/src/lib/pbe/pbes2/pbes2.h b/src/lib/pbe/pbes2/pbes2.h deleted file mode 100644 index 623373b40..000000000 --- a/src/lib/pbe/pbes2/pbes2.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -* PKCS #5 v2.0 PBE -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_PBE_PKCS_v20_H__ -#define BOTAN_PBE_PKCS_v20_H__ - -#include -#include -#include -#include -#include - -namespace Botan { - -/** -* PKCS #5 v2.0 PBE -*/ -class BOTAN_DLL PBE_PKCS5v20 : public PBE - { - public: - OID get_oid() const; - - std::vector encode_params() const; - - std::string name() const; - - void write(const byte buf[], size_t buf_len); - void start_msg(); - void end_msg(); - - /** - * Load a PKCS #5 v2.0 encrypted stream - * @param params the PBES2 parameters - * @param passphrase the passphrase to use for decryption - */ - PBE_PKCS5v20(const std::vector& params, - const std::string& passphrase); - - /** - * @param cipher the block cipher to use - * @param mac the MAC to use - * @param passphrase the passphrase to use for encryption - * @param msec how many milliseconds to run the PBKDF - * @param rng a random number generator - */ - PBE_PKCS5v20(BlockCipher* cipher, - MessageAuthenticationCode* mac, - const std::string& passphrase, - std::chrono::milliseconds msec, - RandomNumberGenerator& rng); - private: - void flush_pipe(bool); - - Cipher_Dir m_direction; - std::unique_ptr m_block_cipher; - std::unique_ptr m_prf; - secure_vector m_salt, m_key, m_iv; - size_t m_iterations, m_key_length; - Pipe m_pipe; - }; - -} - -#endif diff --git a/src/lib/pubkey/info.txt b/src/lib/pubkey/info.txt index 27a332b5c..760f9c5cc 100644 --- a/src/lib/pubkey/info.txt +++ b/src/lib/pubkey/info.txt @@ -33,7 +33,7 @@ filters kdf libstate oid_lookup -pbe +pbes2 pem pk_pad rng diff --git a/src/lib/pubkey/pkcs8.cpp b/src/lib/pubkey/pkcs8.cpp index 7d4c9d802..24a5bb21f 100644 --- a/src/lib/pubkey/pkcs8.cpp +++ b/src/lib/pubkey/pkcs8.cpp @@ -6,12 +6,14 @@ */ #include -#include #include #include #include #include #include +#include +#include +#include #include namespace Botan { @@ -94,10 +96,11 @@ secure_vector PKCS8_decode( if(pass.first == false) break; - Pipe decryptor(get_pbe(pbe_alg_id.oid, pbe_alg_id.parameters, pass.second)); + if(OIDS::lookup(pbe_alg_id.oid) != "PBE-PKCS5v20") + throw std::runtime_error("Unknown PBE type " + pbe_alg_id.oid.as_string()); - decryptor.process_msg(key_data); - key = decryptor.read_all(); + key = pbes2_decrypt(key_data, pass.second, pbe_alg_id.parameters, + global_state().algorithm_factory()); } BER_Decoder(key) @@ -156,23 +159,26 @@ std::vector BER_encode(const Private_Key& key, std::chrono::milliseconds msec, const std::string& pbe_algo) { - const std::string DEFAULT_PBE = "PBE-PKCS5v20(SHA-1,AES-256/CBC)"; + const std::string DEFAULT_PBE = "PBE-PKCS5v20(SHA-256,AES-256/CBC)"; - std::unique_ptr pbe( - get_pbe(((pbe_algo != "") ? pbe_algo : DEFAULT_PBE), - pass, - msec, - rng)); + SCAN_Name request(pbe_algo.empty() ? DEFAULT_PBE : pbe_algo); - AlgorithmIdentifier pbe_algid(pbe->get_oid(), pbe->encode_params()); + const std::string pbe = request.algo_name(); - Pipe key_encrytor(pbe.release()); - key_encrytor.process_msg(PKCS8::BER_encode(key)); + if(pbe != "PBE-PKCS5v20") + throw std::runtime_error("Unsupported PBE " + pbe); + + const std::string digest = request.arg(0); + const std::string cipher = request.arg(1); + + const std::pair> pbe_info = + pbes2_encrypt(PKCS8::BER_encode(key), pass, msec, cipher, digest, rng, + global_state().algorithm_factory()); return DER_Encoder() .start_cons(SEQUENCE) - .encode(pbe_algid) - .encode(key_encrytor.read_all(), OCTET_STRING) + .encode(pbe_info.first) + .encode(pbe_info.second, OCTET_STRING) .end_cons() .get_contents_unlocked(); } -- cgit v1.2.3