diff options
Diffstat (limited to 'old/botan/src/pbe')
-rw-r--r-- | old/botan/src/pbe/get_pbe.cpp | 130 | ||||
-rw-r--r-- | old/botan/src/pbe/get_pbe.h | 33 | ||||
-rw-r--r-- | old/botan/src/pbe/info.txt | 16 | ||||
-rw-r--r-- | old/botan/src/pbe/pbes1/info.txt | 19 | ||||
-rw-r--r-- | old/botan/src/pbe/pbes1/pbes1.cpp | 184 | ||||
-rw-r--r-- | old/botan/src/pbe/pbes1/pbes1.h | 53 | ||||
-rw-r--r-- | old/botan/src/pbe/pbes2/info.txt | 23 | ||||
-rw-r--r-- | old/botan/src/pbe/pbes2/pbes2.cpp | 239 | ||||
-rw-r--r-- | old/botan/src/pbe/pbes2/pbes2.h | 53 |
9 files changed, 750 insertions, 0 deletions
diff --git a/old/botan/src/pbe/get_pbe.cpp b/old/botan/src/pbe/get_pbe.cpp new file mode 100644 index 0000000..3217101 --- /dev/null +++ b/old/botan/src/pbe/get_pbe.cpp @@ -0,0 +1,130 @@ +/* +* 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_V15) + #include <botan/pbes1.h> +#endif + +#if defined(BOTAN_HAS_PBE_PKCS_V20) + #include <botan/pbes2.h> +#endif + +namespace Botan { + +/* +* 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(); + 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 = 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.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_V15) + if(pbe == "PBE-PKCS5v15") + 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(block_cipher->clone(), + hash_function->clone()); +#endif + + throw Algorithm_Not_Found(algo_spec); + } + +/* +* Get a decryption PBE, decode parameters +*/ +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(pbe == "PBE-PKCS5v15") + { + if(request.arg_count() != 2) + throw Invalid_Algorithm_Name(request.as_string()); + + 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 = 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.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); + + 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(pbe == "PBE-PKCS5v20") + return new PBE_PKCS5v20(params); +#endif + + throw Algorithm_Not_Found(pbe_oid.as_string()); + } + +} diff --git a/old/botan/src/pbe/get_pbe.h b/old/botan/src/pbe/get_pbe.h new file mode 100644 index 0000000..04eda66 --- /dev/null +++ b/old/botan/src/pbe/get_pbe.h @@ -0,0 +1,33 @@ +/* +* 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 <string> + +namespace Botan { + +/** +* Factory function for PBEs. +* @param algo_spec the name of the PBE algorithm to retrieve +* @return a pointer to a PBE with randomly created parameters +*/ +BOTAN_DLL PBE* get_pbe(const std::string&); + +/** +* Factory function for PBEs. +* @param pbe_oid the oid of the desired PBE +* @param params a DataSource providing the DER encoded parameters to use +* @return a pointer to the PBE with the specified parameters +*/ +BOTAN_DLL PBE* get_pbe(const OID&, DataSource&); + +} + +#endif diff --git a/old/botan/src/pbe/info.txt b/old/botan/src/pbe/info.txt new file mode 100644 index 0000000..c4210b2 --- /dev/null +++ b/old/botan/src/pbe/info.txt @@ -0,0 +1,16 @@ +realname "PBE Base" + +load_on dep + +define PASSWORD_BASED_ENCRYPTION + +<add> +get_pbe.cpp +get_pbe.h +</add> + +<requires> +filters +libstate +oid_lookup +</requires> diff --git a/old/botan/src/pbe/pbes1/info.txt b/old/botan/src/pbe/pbes1/info.txt new file mode 100644 index 0000000..70c6bae --- /dev/null +++ b/old/botan/src/pbe/pbes1/info.txt @@ -0,0 +1,19 @@ +realname "PKCS5 v1.5 PBE" + +define PBE_PKCS_V15 + +load_on auto + +<add> +pbes1.cpp +pbes1.h +</add> + +<requires> +asn1 +block +cbc +filters +hash +pbkdf1 +</requires> diff --git a/old/botan/src/pbe/pbes1/pbes1.cpp b/old/botan/src/pbe/pbes1/pbes1.cpp new file mode 100644 index 0000000..21bd330 --- /dev/null +++ b/old/botan/src/pbe/pbes1/pbes1.cpp @@ -0,0 +1,184 @@ +/* +* PKCS #5 PBES1 +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/pbes1.h> +#include <botan/pbkdf1.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> +#include <botan/cbc.h> +#include <algorithm> + +namespace Botan { + +/* +* Encrypt some bytes using PBES1 +*/ +void PBE_PKCS5v15::write(const byte input[], u32bit length) + { + while(length) + { + u32bit put = std::min(DEFAULT_BUFFERSIZE, length); + pipe.write(input, length); + flush_pipe(true); + length -= put; + } + } + +/* +* Start encrypting with PBES1 +*/ +void PBE_PKCS5v15::start_msg() + { + 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 PBES1 +*/ +void PBE_PKCS5v15::end_msg() + { + pipe.end_msg(); + flush_pipe(false); + pipe.reset(); + } + +/* +* Flush the pipe +*/ +void PBE_PKCS5v15::flush_pipe(bool safe_to_skip) + { + if(safe_to_skip && pipe.remaining() < 64) + return; + + SecureVector<byte> buffer(DEFAULT_BUFFERSIZE); + while(pipe.remaining()) + { + u32bit got = pipe.read(buffer, buffer.size()); + send(buffer, got); + } + } + +/* +* Set the passphrase to use +*/ +void PBE_PKCS5v15::set_key(const std::string& passphrase) + { + PKCS5_PBKDF1 pbkdf(hash_function->clone()); + + pbkdf.set_iterations(iterations); + pbkdf.change_salt(salt, salt.size()); + SymmetricKey key_and_iv = pbkdf.derive_key(16, passphrase); + + key.set(key_and_iv.begin(), 8); + iv.set(key_and_iv.begin() + 8, 8); + } + +/* +* Create a new set of PBES1 parameters +*/ +void PBE_PKCS5v15::new_params(RandomNumberGenerator& rng) + { + iterations = 2048; + salt.create(8); + rng.randomize(salt, salt.size()); + } + +/* +* Encode PKCS#5 PBES1 parameters +*/ +MemoryVector<byte> PBE_PKCS5v15::encode_params() const + { + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(salt, OCTET_STRING) + .encode(iterations) + .end_cons() + .get_contents(); + } + +/* +* Decode PKCS#5 PBES1 parameters +*/ +void PBE_PKCS5v15::decode_params(DataSource& source) + { + BER_Decoder(source) + .start_cons(SEQUENCE) + .decode(salt, OCTET_STRING) + .decode(iterations) + .verify_end() + .end_cons(); + + if(salt.size() != 8) + throw Decoding_Error("PBES1: Encoded salt is not 8 octets"); + } + +/* +* Return an OID for this PBES1 type +*/ +OID PBE_PKCS5v15::get_oid() const + { + const OID base_pbes1_oid("1.2.840.113549.1.5"); + + const std::string cipher = block_cipher->name(); + const std::string digest = hash_function->name(); + + if(cipher == "DES" && digest == "MD2") + return (base_pbes1_oid + 1); + else if(cipher == "DES" && digest == "MD5") + return (base_pbes1_oid + 3); + else if(cipher == "DES" && digest == "SHA-160") + return (base_pbes1_oid + 10); + else if(cipher == "RC2" && digest == "MD2") + return (base_pbes1_oid + 4); + else if(cipher == "RC2" && digest == "MD5") + return (base_pbes1_oid + 6); + else if(cipher == "RC2" && digest == "SHA-160") + return (base_pbes1_oid + 11); + else + throw Internal_Error("PBE-PKCS5 v1.5: get_oid() has run out of options"); + } + +/* +* PKCS#5 v1.5 PBE Constructor +*/ +PBE_PKCS5v15::PBE_PKCS5v15(BlockCipher* cipher, + HashFunction* hash, + Cipher_Dir dir) : + direction(dir), block_cipher(cipher), hash_function(hash) + { + if(cipher->name() != "DES" && cipher->name() != "RC2") + { + throw Invalid_Argument("PBE_PKCS5v1.5: Unknown cipher " + + cipher->name()); + } + + if(hash->name() != "MD2" && hash->name() != "MD5" && + hash->name() != "SHA-160") + { + throw Invalid_Argument("PBE_PKCS5v1.5: Unknown hash " + + hash->name()); + } + } + +PBE_PKCS5v15::~PBE_PKCS5v15() + { + delete block_cipher; + delete hash_function; + } + +} diff --git a/old/botan/src/pbe/pbes1/pbes1.h b/old/botan/src/pbe/pbes1/pbes1.h new file mode 100644 index 0000000..2e1855d --- /dev/null +++ b/old/botan/src/pbe/pbes1/pbes1.h @@ -0,0 +1,53 @@ +/* +* PKCS #5 v1.5 PBE +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_PBE_PKCS_V15_H__ +#define BOTAN_PBE_PKCS_V15_H__ + +#include <botan/pbe.h> +#include <botan/block_cipher.h> +#include <botan/hash.h> +#include <botan/pipe.h> + +namespace Botan { + +/* +* PKCS#5 v1.5 PBE +*/ +class BOTAN_DLL PBE_PKCS5v15 : public PBE + { + public: + void write(const byte[], u32bit); + void start_msg(); + void end_msg(); + + PBE_PKCS5v15(BlockCipher* cipher, + HashFunction* hash, + Cipher_Dir); + + ~PBE_PKCS5v15(); + private: + void set_key(const std::string&); + void new_params(RandomNumberGenerator& rng); + MemoryVector<byte> encode_params() const; + void decode_params(DataSource&); + OID get_oid() const; + + void flush_pipe(bool); + + Cipher_Dir direction; + BlockCipher* block_cipher; + HashFunction* hash_function; + + SecureVector<byte> salt, key, iv; + u32bit iterations; + Pipe pipe; + }; + +} + +#endif diff --git a/old/botan/src/pbe/pbes2/info.txt b/old/botan/src/pbe/pbes2/info.txt new file mode 100644 index 0000000..cd37b1e --- /dev/null +++ b/old/botan/src/pbe/pbes2/info.txt @@ -0,0 +1,23 @@ +realname "PKCS5 v2.0 PBE" + +define PBE_PKCS_V20 + +load_on auto + +<add> +pbes2.cpp +pbes2.h +</add> + +<requires> +algo_factory +asn1 +block +cbc +filters +hash +hmac +libstate +oid_lookup +pbkdf2 +</requires> diff --git a/old/botan/src/pbe/pbes2/pbes2.cpp b/old/botan/src/pbe/pbes2/pbes2.cpp new file mode 100644 index 0000000..b7e2589 --- /dev/null +++ b/old/botan/src/pbe/pbes2/pbes2.cpp @@ -0,0 +1,239 @@ +/** +* 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/hmac.h> +#include <botan/cbc.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/asn1_obj.h> +#include <botan/oids.h> +#include <algorithm> +#include <memory> + +namespace Botan { + +/** +* Encrypt some bytes using PBES2 +*/ +void PBE_PKCS5v20::write(const byte input[], u32bit length) + { + while(length) + { + u32bit put = std::min(DEFAULT_BUFFERSIZE, length); + pipe.write(input, length); + flush_pipe(true); + length -= put; + } + } + +/** +* Start encrypting with PBES2 +*/ +void PBE_PKCS5v20::start_msg() + { + 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 +*/ +void PBE_PKCS5v20::end_msg() + { + pipe.end_msg(); + flush_pipe(false); + pipe.reset(); + } + +/** +* Flush the pipe +*/ +void PBE_PKCS5v20::flush_pipe(bool safe_to_skip) + { + if(safe_to_skip && pipe.remaining() < 64) + return; + + SecureVector<byte> buffer(DEFAULT_BUFFERSIZE); + while(pipe.remaining()) + { + u32bit got = pipe.read(buffer, buffer.size()); + send(buffer, got); + } + } + +/** +* Set the passphrase to use +*/ +void PBE_PKCS5v20::set_key(const std::string& passphrase) + { + 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 +*/ +void PBE_PKCS5v20::new_params(RandomNumberGenerator& rng) + { + iterations = 2048; + key_length = block_cipher->MAXIMUM_KEYLENGTH; + + salt.create(8); + rng.randomize(salt, salt.size()); + + iv.create(block_cipher->BLOCK_SIZE); + rng.randomize(iv, iv.size()); + } + +/** +* 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(); + } + +/** +* Decode PKCS#5 PBES2 parameters +*/ +void PBE_PKCS5v20::decode_params(DataSource& source) + { + AlgorithmIdentifier kdf_algo, enc_algo; + + BER_Decoder(source) + .start_cons(SEQUENCE) + .decode(kdf_algo) + .decode(enc_algo) + .verify_end() + .end_cons(); + + if(kdf_algo.oid == OIDS::lookup("PKCS5.PBKDF2")) + { + BER_Decoder(kdf_algo.parameters) + .start_cons(SEQUENCE) + .decode(salt, OCTET_STRING) + .decode(iterations) + .decode_optional(key_length, INTEGER, UNIVERSAL) + .verify_end() + .end_cons(); + } + else + throw Decoding_Error("PBE-PKCS5 v2.0: Unknown KDF algorithm " + + kdf_algo.oid.as_string()); + + 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(!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("SHA-160"); + + if(key_length == 0) + 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 +*/ +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) + { + if(algo == "AES-128" || algo == "AES-192" || algo == "AES-256") + return true; + if(algo == "DES" || algo == "TripleDES") + return true; + return false; + } + +/** +* PKCS#5 v2.0 PBE Constructor +*/ +PBE_PKCS5v20::PBE_PKCS5v20(BlockCipher* cipher, + HashFunction* digest) : + direction(ENCRYPTION), block_cipher(cipher), hash_function(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 +*/ +PBE_PKCS5v20::PBE_PKCS5v20(DataSource& params) : direction(DECRYPTION) + { + hash_function = 0; + block_cipher = 0; + decode_params(params); + } + +PBE_PKCS5v20::~PBE_PKCS5v20() + { + delete hash_function; + delete block_cipher; + } + +} diff --git a/old/botan/src/pbe/pbes2/pbes2.h b/old/botan/src/pbe/pbes2/pbes2.h new file mode 100644 index 0000000..fc460a2 --- /dev/null +++ b/old/botan/src/pbe/pbes2/pbes2.h @@ -0,0 +1,53 @@ +/* +* 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/hash.h> +#include <botan/pipe.h> + +namespace Botan { + +/* +* PKCS#5 v2.0 PBE +*/ +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(BlockCipher*, HashFunction*); + + ~PBE_PKCS5v20(); + private: + void set_key(const std::string&); + void new_params(RandomNumberGenerator& rng); + MemoryVector<byte> encode_params() const; + void decode_params(DataSource&); + OID get_oid() const; + + void flush_pipe(bool); + + Cipher_Dir direction; + BlockCipher* block_cipher; + HashFunction* hash_function; + SecureVector<byte> salt, key, iv; + u32bit iterations, key_length; + Pipe pipe; + }; + +} + +#endif |