diff options
-rw-r--r-- | src/pbe/get_pbe.cpp | 81 | ||||
-rw-r--r-- | src/pbe/pbes2/pbes2.cpp | 148 | ||||
-rw-r--r-- | src/pbe/pbes2/pbes2.h | 14 |
3 files changed, 129 insertions, 114 deletions
diff --git a/src/pbe/get_pbe.cpp b/src/pbe/get_pbe.cpp index d5960f283..7e76b7943 100644 --- a/src/pbe/get_pbe.cpp +++ b/src/pbe/get_pbe.cpp @@ -19,21 +19,26 @@ namespace Botan { -namespace { - -PBE* make_pbe_pkcs15(const std::string& cipher, - const std::string& digest, - Cipher_Dir direction) +/************************************************* +* Get an encryption PBE, set new parameters * +*************************************************/ +PBE* get_pbe(const std::string& algo_spec) { + SCAN_Name request(algo_spec); + + const std::string pbe = request.algo_name(); + const std::string digest = 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-PKCS5 v1.5: Invalid cipher spec " + cipher); + throw Invalid_Argument("PBE: Invalid cipher spec " + cipher); const std::string cipher_algo = global_state().deref_alias(cipher_spec[0]); const std::string cipher_mode = cipher_spec[1]; if(cipher_mode != "CBC") - throw Invalid_Argument("PBE-PKCS5 v1.5: Invalid cipher " + cipher); + throw Invalid_Argument("PBE: Invalid cipher mode " + cipher); Algorithm_Factory& af = global_state().algorithm_factory(); @@ -45,39 +50,23 @@ PBE* make_pbe_pkcs15(const std::string& cipher, if(!hash_function) throw Algorithm_Not_Found(digest); - return new PBE_PKCS5v15(block_cipher->clone(), - hash_function->clone(), - direction); - - } - -} - -/************************************************* -* Get an encryption PBE, set new parameters * -*************************************************/ -PBE* get_pbe(const std::string& pbe_name) - { - SCAN_Name request(pbe_name); - if(request.arg_count() != 2) - throw Invalid_Algorithm_Name(pbe_name); - - const std::string pbe = request.algo_name(); - const std::string digest = request.arg(0); - const std::string cipher = request.arg(1); + throw Invalid_Algorithm_Name(algo_spec); #if defined(BOTAN_HAS_PBE_PKCS_V15) if(pbe == "PBE-PKCS5v15") - return make_pbe_pkcs15(cipher, digest, ENCRYPTION); + return new PBE_PKCS5v15(block_cipher->clone(), + hash_function->clone(), + ENCRYPTION); #endif #if defined(BOTAN_HAS_PBE_PKCS_V20) if(pbe == "PBE-PKCS5v20") - return new PBE_PKCS5v20(digest, cipher); + return new PBE_PKCS5v20(block_cipher->clone(), + hash_function->clone()); #endif - throw Algorithm_Not_Found(pbe_name); + throw Algorithm_Not_Found(algo_spec); } /************************************************* @@ -87,23 +76,47 @@ PBE* get_pbe(const OID& pbe_oid, DataSource& params) { SCAN_Name request(OIDS::lookup(pbe_oid)); + const std::string pbe = request.algo_name(); + #if defined(BOTAN_HAS_PBE_PKCS_V15) - if(request.algo_name() == "PBE-PKCS5v15") + if(pbe == "PBE-PKCS5v15") { if(request.arg_count() != 2) - throw Invalid_Algorithm_Name(pbe_oid.as_string()); + throw Invalid_Algorithm_Name(request.as_string()); const std::string digest = request.arg(0); const std::string cipher = request.arg(1); - PBE* pbe = make_pbe_pkcs15(cipher, digest, DECRYPTION); + 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 = global_state().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.make_block_cipher(cipher_algo); + if(!block_cipher) + throw Algorithm_Not_Found(cipher_algo); + + const HashFunction* hash_function = af.make_hash_function(digest); + if(!hash_function) + throw Algorithm_Not_Found(digest); + + PBE* pbe = new PBE_PKCS5v15(block_cipher->clone(), + hash_function->clone(), + DECRYPTION); pbe->decode_params(params); return pbe; } #endif #if defined(BOTAN_HAS_PBE_PKCS_V20) - if(request.algo_name() == "PBE-PKCS5v20") + if(pbe == "PBE-PKCS5v20") return new PBE_PKCS5v20(params); #endif diff --git a/src/pbe/pbes2/pbes2.cpp b/src/pbe/pbes2/pbes2.cpp index e4e4585fe..25be6f98a 100644 --- a/src/pbe/pbes2/pbes2.cpp +++ b/src/pbe/pbes2/pbes2.cpp @@ -1,12 +1,13 @@ -/************************************************* -* PKCS #5 PBES2 Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ +/** +* PKCS #5 PBES2 Source File +* (C) 1999-2008 Jack Lloyd +*/ #include <botan/pbes2.h> #include <botan/pbkdf2.h> #include <botan/hmac.h> -#include <botan/lookup.h> +#include <botan/cbc.h> +#include <botan/algo_factory.h> #include <botan/libstate.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> @@ -18,9 +19,9 @@ namespace Botan { -/************************************************* -* Encrypt some bytes using PBES2 * -*************************************************/ +/** +* Encrypt some bytes using PBES2 +*/ void PBE_PKCS5v20::write(const byte input[], u32bit length) { while(length) @@ -32,20 +33,28 @@ void PBE_PKCS5v20::write(const byte input[], u32bit length) } } -/************************************************* -* Start encrypting with PBES2 * -*************************************************/ +/** +* Start encrypting with PBES2 +*/ void PBE_PKCS5v20::start_msg() { - pipe.append(get_cipher(cipher, key, iv, direction)); + if(direction == ENCRYPTION) + pipe.append(new CBC_Encryption(block_cipher->clone(), + new PKCS7_Padding, + key, iv)); + else + pipe.append(new CBC_Decryption(block_cipher->clone(), + new PKCS7_Padding, + key, iv)); + pipe.start_msg(); if(pipe.message_count() > 1) pipe.set_default_msg(pipe.default_msg() + 1); } -/************************************************* -* Finish encrypting with PBES2 * -*************************************************/ +/** +* Finish encrypting with PBES2 +*/ void PBE_PKCS5v20::end_msg() { pipe.end_msg(); @@ -53,9 +62,9 @@ void PBE_PKCS5v20::end_msg() pipe.reset(); } -/************************************************* -* Flush the pipe * -*************************************************/ +/** +* Flush the pipe +*/ void PBE_PKCS5v20::flush_pipe(bool safe_to_skip) { if(safe_to_skip && pipe.remaining() < 64) @@ -69,36 +78,36 @@ void PBE_PKCS5v20::flush_pipe(bool safe_to_skip) } } -/************************************************* -* Set the passphrase to use * -*************************************************/ +/** +* Set the passphrase to use +*/ void PBE_PKCS5v20::set_key(const std::string& passphrase) { - PKCS5_PBKDF2 pbkdf(new HMAC(get_hash(digest))); + PKCS5_PBKDF2 pbkdf(new HMAC(hash_function->clone())); pbkdf.set_iterations(iterations); pbkdf.change_salt(salt, salt.size()); key = pbkdf.derive_key(key_length, passphrase).bits_of(); } -/************************************************* -* Create a new set of PBES2 parameters * -*************************************************/ +/** +* Create a new set of PBES2 parameters +*/ void PBE_PKCS5v20::new_params(RandomNumberGenerator& rng) { iterations = 2048; - key_length = max_keylength_of(cipher_algo); + key_length = block_cipher->MAXIMUM_KEYLENGTH; salt.create(8); rng.randomize(salt, salt.size()); - iv.create(block_size_of(cipher_algo)); + iv.create(block_cipher->BLOCK_SIZE); rng.randomize(iv, iv.size()); } -/************************************************* -* Encode PKCS#5 PBES2 parameters * -*************************************************/ +/** +* Encode PKCS#5 PBES2 parameters +*/ MemoryVector<byte> PBE_PKCS5v20::encode_params() const { return DER_Encoder() @@ -115,7 +124,7 @@ MemoryVector<byte> PBE_PKCS5v20::encode_params() const ) ) .encode( - AlgorithmIdentifier(cipher, + AlgorithmIdentifier(block_cipher->name() + "/CBC", DER_Encoder() .encode(iv, OCTET_STRING) .get_contents() @@ -125,9 +134,9 @@ MemoryVector<byte> PBE_PKCS5v20::encode_params() const .get_contents(); } -/************************************************* -* Decode PKCS#5 PBES2 parameters * -*************************************************/ +/** +* Decode PKCS#5 PBES2 parameters +*/ void PBE_PKCS5v20::decode_params(DataSource& source) { AlgorithmIdentifier kdf_algo, enc_algo; @@ -141,8 +150,6 @@ void PBE_PKCS5v20::decode_params(DataSource& source) if(kdf_algo.oid == OIDS::lookup("PKCS5.PBKDF2")) { - digest = "SHA-160"; - BER_Decoder(kdf_algo.parameters) .start_cons(SEQUENCE) .decode(salt, OCTET_STRING) @@ -155,37 +162,41 @@ void PBE_PKCS5v20::decode_params(DataSource& source) throw Decoding_Error("PBE-PKCS5 v2.0: Unknown KDF algorithm " + kdf_algo.oid.as_string()); - cipher = OIDS::lookup(enc_algo.oid); + 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); - cipher_algo = global_state().deref_alias(cipher_spec[0]); - if(!known_cipher(cipher_algo) || cipher_spec[1] != "CBC") + 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(SCAN_Name("SHA-160")); + if(key_length == 0) - key_length = max_keylength_of(cipher_algo); + key_length = block_cipher->MAXIMUM_KEYLENGTH; if(salt.size() < 8) throw Decoding_Error("PBE-PKCS5 v2.0: Encoded salt is too small"); } -/************************************************* -* Return an OID for PBES2 * -*************************************************/ +/** +* Return an OID for PBES2 +*/ OID PBE_PKCS5v20::get_oid() const { return OIDS::lookup("PBE-PKCS5v20"); } -/************************************************* -* Check if this is a known PBES2 cipher * -*************************************************/ -bool PBE_PKCS5v20::known_cipher(const std::string& algo) const +/** +* Check if this is a known PBES2 cipher +*/ +bool PBE_PKCS5v20::known_cipher(const std::string& algo) { if(algo == "AES-128" || algo == "AES-192" || algo == "AES-256") return true; @@ -194,39 +205,26 @@ bool PBE_PKCS5v20::known_cipher(const std::string& algo) const return false; } -/************************************************* -* PKCS#5 v2.0 PBE Constructor * -*************************************************/ -PBE_PKCS5v20::PBE_PKCS5v20(const std::string& d_algo, - const std::string& c_algo) : - direction(ENCRYPTION), - digest(global_state().deref_alias(d_algo)), - cipher(c_algo) +/** +* PKCS#5 v2.0 PBE Constructor +*/ +PBE_PKCS5v20::PBE_PKCS5v20(BlockCipher* cipher, + HashFunction* digest) : + direction(ENCRYPTION), block_cipher(cipher), hash_function(digest) { - std::vector<std::string> cipher_spec = split_on(cipher, '/'); - if(cipher_spec.size() != 2) - throw Invalid_Argument("PBE-PKCS5 v2.0: Invalid cipher spec " + cipher); - cipher_algo = global_state().deref_alias(cipher_spec[0]); - const std::string cipher_mode = cipher_spec[1]; - - if(!have_block_cipher(cipher_algo)) - throw Algorithm_Not_Found(cipher_algo); - if(!have_hash(digest)) - throw Algorithm_Not_Found(digest); - - if(!known_cipher(cipher_algo)) - throw Invalid_Argument("PBE-PKCS5 v2.0: Invalid cipher " + cipher); - if(cipher_mode != "CBC") - throw Invalid_Argument("PBE-PKCS5 v2.0: Invalid cipher " + cipher); - if(digest != "SHA-160") - throw Invalid_Argument("PBE-PKCS5 v2.0: Invalid digest " + digest); + if(!known_cipher(block_cipher->name())) + throw Invalid_Argument("PBE-PKCS5 v2.0: Invalid cipher " + cipher->name()); + if(hash_function->name() != "SHA-160") + throw Invalid_Argument("PBE-PKCS5 v2.0: Invalid digest " + digest->name()); } -/************************************************* -* PKCS#5 v2.0 PBE Constructor * -*************************************************/ +/** +* PKCS#5 v2.0 PBE Constructor +*/ PBE_PKCS5v20::PBE_PKCS5v20(DataSource& params) : direction(DECRYPTION) { + hash_function = 0; + block_cipher = 0; decode_params(params); } diff --git a/src/pbe/pbes2/pbes2.h b/src/pbe/pbes2/pbes2.h index 6a859f814..984d5ad4a 100644 --- a/src/pbe/pbes2/pbes2.h +++ b/src/pbe/pbes2/pbes2.h @@ -7,7 +7,8 @@ #define BOTAN_PBE_PKCS_v20_H__ #include <botan/pbe.h> -#include <botan/sym_algo.h> +#include <botan/block_cipher.h> +#include <botan/hash.h> #include <botan/pipe.h> namespace Botan { @@ -18,11 +19,14 @@ namespace Botan { class BOTAN_DLL PBE_PKCS5v20 : public PBE { public: + static bool known_cipher(const std::string&); + void write(const byte[], u32bit); void start_msg(); void end_msg(); + PBE_PKCS5v20(DataSource&); - PBE_PKCS5v20(const std::string&, const std::string&); + PBE_PKCS5v20(BlockCipher*, HashFunction*); private: void set_key(const std::string&); void new_params(RandomNumberGenerator& rng); @@ -31,10 +35,10 @@ class BOTAN_DLL PBE_PKCS5v20 : public PBE OID get_oid() const; void flush_pipe(bool); - bool known_cipher(const std::string&) const; - const Cipher_Dir direction; - std::string digest, cipher, cipher_algo; + Cipher_Dir direction; + BlockCipher* block_cipher; + HashFunction* hash_function; SecureVector<byte> salt, key, iv; u32bit iterations, key_length; Pipe pipe; |