aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2014-11-19 12:45:07 +0000
committerlloyd <[email protected]>2014-11-19 12:45:07 +0000
commit840fc0e4dfcb9578b9b1bfd3da0b8fd8a1fa8534 (patch)
tree8d907b91cfb796bf1357f276b017724ad2354964
parent80858693243f3774c2b3cd9084fb5aaafc542b06 (diff)
Cleanup PBES2 and add GCM support
-rw-r--r--doc/relnotes/1_11_10.rst6
-rw-r--r--src/lib/asn1/oid_lookup/default.cpp5
-rw-r--r--src/lib/constructs/pbes2/info.txt (renamed from src/lib/pbe/pbes2/info.txt)4
-rw-r--r--src/lib/constructs/pbes2/pbes2.cpp189
-rw-r--r--src/lib/constructs/pbes2/pbes2.h50
-rw-r--r--src/lib/pbe/get_pbe.cpp89
-rw-r--r--src/lib/pbe/get_pbe.h44
-rw-r--r--src/lib/pbe/info.txt7
-rw-r--r--src/lib/pbe/pbe.h39
-rw-r--r--src/lib/pbe/pbes2/pbes2.cpp202
-rw-r--r--src/lib/pbe/pbes2/pbes2.h68
-rw-r--r--src/lib/pubkey/info.txt2
-rw-r--r--src/lib/pubkey/pkcs8.cpp36
13 files changed, 273 insertions, 468 deletions
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/pbe/pbes2/info.txt b/src/lib/constructs/pbes2/info.txt
index ba7d77774..e1f260966 100644
--- a/src/lib/pbe/pbes2/info.txt
+++ b/src/lib/constructs/pbes2/info.txt
@@ -1,14 +1,12 @@
-define PBE_PKCS_V20 20131128
+define PKCS5_PBES2 20141119
<requires>
algo_factory
asn1
block
cbc
-filters
hash
hmac
-libstate
oid_lookup
pbkdf2
</requires>
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 <botan/pbes2.h>
+#include <botan/pbkdf2.h>
+#include <botan/der_enc.h>
+#include <botan/ber_dec.h>
+#include <botan/parsing.h>
+#include <botan/alg_id.h>
+#include <botan/oids.h>
+#include <botan/rng.h>
+#include <botan/cbc.h>
+#include <algorithm>
+
+#if defined(BOTAN_HAS_AEAD_GCM)
+ #include <botan/gcm.h>
+#endif
+
+namespace Botan {
+
+namespace {
+
+/*
+* Encode PKCS#5 PBES2 parameters
+*/
+std::vector<byte> encode_pbes2_params(const std::string& cipher,
+ const std::string& prf,
+ const secure_vector<byte>& salt,
+ const secure_vector<byte>& 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<AlgorithmIdentifier, std::vector<byte>>
+pbes2_encrypt(const secure_vector<byte>& 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<std::string> cipher_spec = split_on(cipher, '/');
+ if(cipher_spec.size() != 2)
+ throw Decoding_Error("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher);
+
+ const secure_vector<byte> salt = rng.random_vec(12);
+
+ std::unique_ptr<Keyed_Transform> 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<byte> 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<byte> 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<byte>
+pbes2_decrypt(const secure_vector<byte>& key_bits,
+ const std::string& passphrase,
+ const std::vector<byte>& 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<byte> 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<std::string> 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<byte> 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<Keyed_Transform> 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<byte> 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 <botan/secmem.h>
+#include <botan/transform.h>
+#include <botan/alg_id.h>
+#include <botan/algo_factory.h>
+#include <chrono>
+
+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<AlgorithmIdentifier, std::vector<byte>>
+BOTAN_DLL pbes2_encrypt(const secure_vector<byte>& 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<byte>
+BOTAN_DLL pbes2_decrypt(const secure_vector<byte>& key_bits,
+ const std::string& passphrase,
+ const std::vector<byte>& 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 <botan/get_pbe.h>
-#include <botan/oids.h>
-#include <botan/scan_name.h>
-#include <botan/parsing.h>
-#include <botan/libstate.h>
-
-#if defined(BOTAN_HAS_PBE_PKCS_V20)
- #include <botan/pbes2.h>
- #include <botan/hmac.h>
-#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<std::string> 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<byte>& 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 <botan/pbe.h>
-#include <vector>
-#include <string>
-#include <chrono>
-
-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<byte>& 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
-
-<requires>
-filters
-libstate
-oid_lookup
-</requires>
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 <botan/asn1_oid.h>
-#include <botan/data_src.h>
-#include <botan/filter.h>
-#include <botan/rng.h>
-
-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<byte> 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/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 <botan/pbes2.h>
-#include <botan/pbkdf2.h>
-#include <botan/algo_factory.h>
-#include <botan/libstate.h>
-#include <botan/der_enc.h>
-#include <botan/ber_dec.h>
-#include <botan/parsing.h>
-#include <botan/alg_id.h>
-#include <botan/oids.h>
-#include <botan/lookup.h>
-#include <algorithm>
-
-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<byte> 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<byte> 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<byte>& 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<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")
- 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 <botan/pbe.h>
-#include <botan/block_cipher.h>
-#include <botan/mac.h>
-#include <botan/pipe.h>
-#include <chrono>
-
-namespace Botan {
-
-/**
-* PKCS #5 v2.0 PBE
-*/
-class BOTAN_DLL PBE_PKCS5v20 : public PBE
- {
- public:
- OID get_oid() const;
-
- std::vector<byte> 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<byte>& 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<BlockCipher> m_block_cipher;
- std::unique_ptr<MessageAuthenticationCode> m_prf;
- secure_vector<byte> 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 <botan/pkcs8.h>
-#include <botan/get_pbe.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>
#include <botan/alg_id.h>
#include <botan/oids.h>
#include <botan/pem.h>
+#include <botan/pbes2.h>
+#include <botan/libstate.h>
+#include <botan/scan_name.h>
#include <botan/internal/pk_algs.h>
namespace Botan {
@@ -94,10 +96,11 @@ secure_vector<byte> 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<byte> 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> 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<AlgorithmIdentifier, std::vector<byte>> 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();
}