diff options
author | lloyd <[email protected]> | 2011-03-08 22:18:37 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2011-03-08 22:18:37 +0000 |
commit | e8ae96510f3d87e3b142df81b51c3b15e30e77f9 (patch) | |
tree | 4f61ddba33a8e06b85ba2edc1b74d1a02e7c4739 /src/constructs | |
parent | 5f4aafe005d1031b955718fbb94d6beec3e6ea48 (diff) | |
parent | 41da07c02a36add833965be5ddc60ef1cf089beb (diff) |
propagate from branch 'net.randombit.botan' (head dd068808e5bf87c982765a8bcc314996053a5bdd)
to branch 'net.randombit.botan.c++0x' (head 34696d52a8148d64f7021b3e193fc56f051b9dd2)
Diffstat (limited to 'src/constructs')
-rw-r--r-- | src/constructs/aont/package.cpp | 8 | ||||
-rw-r--r-- | src/constructs/passhash/info.txt | 9 | ||||
-rw-r--r-- | src/constructs/passhash/passhash9.cpp | 148 | ||||
-rw-r--r-- | src/constructs/passhash/passhash9.h | 51 | ||||
-rw-r--r-- | src/constructs/rfc3394/info.txt | 1 | ||||
-rw-r--r-- | src/constructs/rfc3394/rfc3394.cpp | 122 | ||||
-rw-r--r-- | src/constructs/rfc3394/rfc3394.h | 45 |
7 files changed, 172 insertions, 212 deletions
diff --git a/src/constructs/aont/package.cpp b/src/constructs/aont/package.cpp index 4d92a789c..4d46f6b61 100644 --- a/src/constructs/aont/package.cpp +++ b/src/constructs/aont/package.cpp @@ -46,13 +46,13 @@ void aont_package(RandomNumberGenerator& rng, clear_mem(final_block, BLOCK_SIZE); // XOR the hash blocks into the final block - for(u32bit i = 0; i != blocks; ++i) + for(size_t i = 0; i != blocks; ++i) { const size_t left = std::min<size_t>(BLOCK_SIZE, input_len - BLOCK_SIZE * i); zeroise(buf); - copy_mem(&buf[0], output + BLOCK_SIZE * i, left); + copy_mem(&buf[0], output + (BLOCK_SIZE * i), left); for(size_t j = 0; j != sizeof(i); ++j) buf[BLOCK_SIZE - 1 - j] ^= get_byte(sizeof(i)-1-j, i); @@ -94,13 +94,13 @@ void aont_unpackage(BlockCipher* cipher, const size_t blocks = ((input_len - 1) / BLOCK_SIZE); // XOR the blocks into the package key bits - for(u32bit i = 0; i != blocks; ++i) + for(size_t i = 0; i != blocks; ++i) { const size_t left = std::min<size_t>(BLOCK_SIZE, input_len - BLOCK_SIZE * (i+1)); zeroise(buf); - copy_mem(&buf[0], input + BLOCK_SIZE * i, left); + copy_mem(&buf[0], input + (BLOCK_SIZE * i), left); for(size_t j = 0; j != sizeof(i); ++j) buf[BLOCK_SIZE - 1 - j] ^= get_byte(sizeof(i)-1-j, i); diff --git a/src/constructs/passhash/info.txt b/src/constructs/passhash/info.txt deleted file mode 100644 index f96809f29..000000000 --- a/src/constructs/passhash/info.txt +++ /dev/null @@ -1,9 +0,0 @@ -define PASSHASH9 - -<requires> -libstate -pbkdf2 -rng -base64 -</requires> - diff --git a/src/constructs/passhash/passhash9.cpp b/src/constructs/passhash/passhash9.cpp deleted file mode 100644 index 367583a0a..000000000 --- a/src/constructs/passhash/passhash9.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* -* Passhash9 Password Hashing -* (C) 2010 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/passhash9.h> -#include <botan/loadstor.h> -#include <botan/libstate.h> -#include <botan/pbkdf2.h> -#include <botan/b64_filt.h> -#include <botan/pipe.h> - -namespace Botan { - -namespace { - -const std::string MAGIC_PREFIX = "$9$"; - -const size_t WORKFACTOR_BYTES = 2; -const size_t ALGID_BYTES = 1; -const size_t SALT_BYTES = 12; // 96 bits of salt -const size_t PASSHASH9_PBKDF_OUTPUT_LEN = 24; // 192 bits output - -const byte PASSHASH9_DEFAULT_ALGO = 0; // HMAC(SHA-1) - -const size_t WORK_FACTOR_SCALE = 10000; - -MessageAuthenticationCode* get_pbkdf_prf(byte alg_id) - { - Algorithm_Factory& af = global_state().algorithm_factory(); - - try - { - if(alg_id == 0) - return af.make_mac("HMAC(SHA-1)"); - else if(alg_id == 1) - return af.make_mac("HMAC(SHA-256)"); - else if(alg_id == 2) - return af.make_mac("CMAC(Blowfish)"); - } - catch(Algorithm_Not_Found) {} - - return 0; - } - -} - -std::string generate_passhash9(const std::string& pass, - RandomNumberGenerator& rng, - u16bit work_factor) - { - return generate_passhash9(pass, PASSHASH9_DEFAULT_ALGO, rng, work_factor); - } - -std::string generate_passhash9(const std::string& pass, - byte alg_id, - RandomNumberGenerator& rng, - u16bit work_factor) - { - MessageAuthenticationCode* prf = get_pbkdf_prf(alg_id); - - if(!prf) - throw Invalid_Argument("Passhash9: Algorithm id " + - std::to_string(alg_id) + - " is not defined"); - - PKCS5_PBKDF2 kdf(prf); // takes ownership of pointer - - SecureVector<byte> salt(SALT_BYTES); - rng.randomize(&salt[0], salt.size()); - - const size_t kdf_iterations = WORK_FACTOR_SCALE * work_factor; - - SecureVector<byte> pbkdf2_output = - kdf.derive_key(PASSHASH9_PBKDF_OUTPUT_LEN, - pass, - &salt[0], salt.size(), - kdf_iterations).bits_of(); - - Pipe pipe(new Base64_Encoder); - pipe.start_msg(); - pipe.write(alg_id); - pipe.write(get_byte(0, work_factor)); - pipe.write(get_byte(1, work_factor)); - pipe.write(salt); - pipe.write(pbkdf2_output); - pipe.end_msg(); - - return MAGIC_PREFIX + pipe.read_all_as_string(); - } - -bool check_passhash9(const std::string& pass, const std::string& hash) - { - const size_t BINARY_LENGTH = - ALGID_BYTES + - WORKFACTOR_BYTES + - PASSHASH9_PBKDF_OUTPUT_LEN + - SALT_BYTES; - - const size_t BASE64_LENGTH = - MAGIC_PREFIX.size() + (BINARY_LENGTH * 8) / 6; - - if(hash.size() != BASE64_LENGTH) - return false; - - for(size_t i = 0; i != MAGIC_PREFIX.size(); ++i) - if(hash[i] != MAGIC_PREFIX[i]) - return false; - - Pipe pipe(new Base64_Decoder); - pipe.start_msg(); - pipe.write(hash.c_str() + MAGIC_PREFIX.size()); - pipe.end_msg(); - - SecureVector<byte> bin = pipe.read_all(); - - if(bin.size() != BINARY_LENGTH) - return false; - - byte alg_id = bin[0]; - - const size_t kdf_iterations = - WORK_FACTOR_SCALE * load_be<u16bit>(&bin[ALGID_BYTES], 0); - - if(kdf_iterations == 0) - return false; - - MessageAuthenticationCode* pbkdf_prf = get_pbkdf_prf(alg_id); - - if(pbkdf_prf == 0) - return false; // unknown algorithm, reject - - PKCS5_PBKDF2 kdf(pbkdf_prf); // takes ownership of pointer - - SecureVector<byte> cmp = kdf.derive_key( - PASSHASH9_PBKDF_OUTPUT_LEN, - pass, - &bin[ALGID_BYTES + WORKFACTOR_BYTES], SALT_BYTES, - kdf_iterations).bits_of(); - - return same_mem(&cmp[0], - &bin[ALGID_BYTES + WORKFACTOR_BYTES + SALT_BYTES], - PASSHASH9_PBKDF_OUTPUT_LEN); - } - -} diff --git a/src/constructs/passhash/passhash9.h b/src/constructs/passhash/passhash9.h deleted file mode 100644 index 92cc391dc..000000000 --- a/src/constructs/passhash/passhash9.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -* Passhash9 Password Hashing -* (C) 2010 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_PASSHASH9_H__ -#define BOTAN_PASSHASH9_H__ - -#include <botan/rng.h> - -namespace Botan { - -/** -* Create a password hash using PBKDF2 -* @param password the password -* @param rng a random number generator -* @param work_factor how much work to do to slow down guessing attacks -*/ -std::string BOTAN_DLL generate_passhash9(const std::string& password, - RandomNumberGenerator& rng, - u16bit work_factor = 10); - -/** -* Create a password hash using PBKDF2 -* @param password the password -* @param alg_id specifies which PRF to use with PBKDF2 -* 0 is HMAC(SHA-1) -* 1 is HMAC(SHA-256) -* 2 is CMAC(Blowfish) -* all other values are currently undefined -* @param rng a random number generator -* @param work_factor how much work to do to slow down guessing attacks -*/ -std::string BOTAN_DLL generate_passhash9(const std::string& password, - byte alg_id, - RandomNumberGenerator& rng, - u16bit work_factor = 10); - -/** -* Check a previously created password hash -* @param password the password to check against -* @param hash the stored hash to check against -*/ -bool BOTAN_DLL check_passhash9(const std::string& password, - const std::string& hash); - -} - -#endif diff --git a/src/constructs/rfc3394/info.txt b/src/constructs/rfc3394/info.txt new file mode 100644 index 000000000..496f3e138 --- /dev/null +++ b/src/constructs/rfc3394/info.txt @@ -0,0 +1 @@ +define RFC3394_KEYWRAP diff --git a/src/constructs/rfc3394/rfc3394.cpp b/src/constructs/rfc3394/rfc3394.cpp new file mode 100644 index 000000000..b000873fd --- /dev/null +++ b/src/constructs/rfc3394/rfc3394.cpp @@ -0,0 +1,122 @@ +/* +* AES Key Wrap (RFC 3394) +* (C) 2011 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/rfc3394.h> +#include <botan/algo_factory.h> +#include <botan/block_cipher.h> +#include <botan/loadstor.h> +#include <botan/exceptn.h> +#include <botan/internal/xor_buf.h> +#include <memory> + +namespace Botan { + +namespace { + +BlockCipher* make_aes(size_t keylength, + Algorithm_Factory& af) + { + if(keylength == 16) + return af.make_block_cipher("AES-128"); + else if(keylength == 24) + return af.make_block_cipher("AES-192"); + else if(keylength == 32) + return af.make_block_cipher("AES-256"); + else + throw std::invalid_argument("Bad KEK length for NIST keywrap"); + } + +} + +SecureVector<byte> rfc3394_keywrap(const MemoryRegion<byte>& key, + const SymmetricKey& kek, + Algorithm_Factory& af) + { + if(key.size() % 8 != 0) + throw std::invalid_argument("Bad input key size for NIST key wrap"); + + std::auto_ptr<BlockCipher> aes(make_aes(kek.length(), af)); + aes->set_key(kek); + + const size_t n = key.size() / 8; + + SecureVector<byte> R((n + 1) * 8); + SecureVector<byte> A(16); + + for(size_t i = 0; i != 8; ++i) + A[i] = 0xA6; + + copy_mem(&R[8], key.begin(), key.size()); + + for(size_t j = 0; j <= 5; ++j) + { + for(size_t i = 1; i <= n; ++i) + { + const u32bit t = (n * j) + i; + + copy_mem(&A[8], &R[8*i], 8); + + aes->encrypt(&A[0]); + copy_mem(&R[8*i], &A[8], 8); + + byte t_buf[4] = { 0 }; + store_be(t, t_buf); + xor_buf(&A[4], &t_buf[0], 4); + } + } + + copy_mem(&R[0], &A[0], 8); + + return R; + } + +SecureVector<byte> rfc3394_keyunwrap(const MemoryRegion<byte>& key, + const SymmetricKey& kek, + Algorithm_Factory& af) + { + if(key.size() < 16 || key.size() % 8 != 0) + throw std::invalid_argument("Bad input key size for NIST key unwrap"); + + std::auto_ptr<BlockCipher> aes(make_aes(kek.length(), af)); + aes->set_key(kek); + + const size_t n = (key.size() - 8) / 8; + + SecureVector<byte> R(n * 8); + SecureVector<byte> A(16); + + for(size_t i = 0; i != 8; ++i) + A[i] = key[i]; + + copy_mem(&R[0], key.begin() + 8, key.size() - 8); + + for(size_t j = 0; j <= 5; ++j) + { + for(size_t i = n; i != 0; --i) + { + const u32bit t = (5 - j) * n + i; + + byte t_buf[4] = { 0 }; + store_be(t, t_buf); + + xor_buf(&A[4], &t_buf[0], 4); + + copy_mem(&A[8], &R[8*(i-1)], 8); + + aes->decrypt(&A[0]); + + copy_mem(&R[8*(i-1)], &A[8], 8); + } + } + + if(load_be<u64bit>(&A[0], 0) != 0xA6A6A6A6A6A6A6A6) + throw Integrity_Failure("NIST key unwrap failed"); + + return R; + } + +} diff --git a/src/constructs/rfc3394/rfc3394.h b/src/constructs/rfc3394/rfc3394.h new file mode 100644 index 000000000..645586ee2 --- /dev/null +++ b/src/constructs/rfc3394/rfc3394.h @@ -0,0 +1,45 @@ +/* +* AES Key Wrap (RFC 3394) +* (C) 2011 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_AES_KEY_WRAP_H__ +#define BOTAN_AES_KEY_WRAP_H__ + +#include <botan/symkey.h> + +namespace Botan { + +class Algorithm_Factory; + +/** +* Encrypt a key under a key encryption key using the algorithm +* described in RFC 3394 +* +* @param key the plaintext key to encrypt +* @param kek the key encryption key +* @param af an algorithm factory +* @return key encrypted under kek +*/ +SecureVector<byte> BOTAN_DLL rfc3394_keywrap(const MemoryRegion<byte>& key, + const SymmetricKey& kek, + Algorithm_Factory& af); + +/** +* Decrypt a key under a key encryption key using the algorithm +* described in RFC 3394 +* +* @param key the encrypted key to decrypt +* @param kek the key encryption key +* @param af an algorithm factory +* @return key decrypted under kek +*/ +SecureVector<byte> BOTAN_DLL rfc3394_keyunwrap(const MemoryRegion<byte>& key, + const SymmetricKey& kek, + Algorithm_Factory& af); + +} + +#endif |