diff options
-rw-r--r-- | src/constructs/cryptobox/cryptobox.h | 25 | ||||
-rw-r--r-- | src/constructs/cryptobox/raw_key.cpp | 134 | ||||
-rw-r--r-- | src/tls/tls_session.cpp | 105 |
3 files changed, 163 insertions, 101 deletions
diff --git a/src/constructs/cryptobox/cryptobox.h b/src/constructs/cryptobox/cryptobox.h index ce1bb9ab0..e70492d37 100644 --- a/src/constructs/cryptobox/cryptobox.h +++ b/src/constructs/cryptobox/cryptobox.h @@ -10,6 +10,7 @@ #include <string> #include <botan/rng.h> +#include <botan/symkey.h> namespace Botan { @@ -29,6 +30,7 @@ BOTAN_DLL std::string encrypt(const byte input[], size_t input_len, const std::string& passphrase, RandomNumberGenerator& rng); + /** * Decrypt a message encrypted with CryptoBox::encrypt * @param input the input data @@ -46,6 +48,29 @@ BOTAN_DLL std::string decrypt(const byte input[], size_t input_len, BOTAN_DLL std::string decrypt(const std::string& input, const std::string& passphrase); +/** +* Encrypt a message using a shared key +* @param input the input data +* @param input_len the length of input in bytes +* @param key the key used to encrypt the message +* @param rng a ref to a random number generator, such as AutoSeeded_RNG +*/ +BOTAN_DLL std::vector<byte> +encrypt(const byte input[], size_t input_len, + const SymmetricKey& key, + RandomNumberGenerator& rng); + +/** +* Encrypt a message using a shared key +* @param input the input data +* @param input_len the length of input in bytes +* @param key the key used to encrypt the message +* @param rng a ref to a random number generator, such as AutoSeeded_RNG +*/ +BOTAN_DLL secure_vector<byte> +decrypt(const byte input[], size_t input_len, + const SymmetricKey& key); + } } diff --git a/src/constructs/cryptobox/raw_key.cpp b/src/constructs/cryptobox/raw_key.cpp new file mode 100644 index 000000000..9fc912c0c --- /dev/null +++ b/src/constructs/cryptobox/raw_key.cpp @@ -0,0 +1,134 @@ +/* +* Cryptobox Message Routines +* (C) 2013 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/cryptobox.h> +#include <botan/pipe.h> +#include <botan/lookup.h> +#include <botan/loadstor.h> +#include <memory> + +namespace Botan { + +namespace CryptoBox { + +namespace { + +const u32bit CRYPTOBOX_MAGIC = 0x571B0E4F; +const std::string CRYPTOBOX_CIPHER = "AES-256/CBC"; +const std::string CRYPTOBOX_MAC = "HMAC(SHA-256)"; +const std::string CRYPTOBOX_KDF = "KDF2(SHA-256)"; + +const size_t MAGIC_LENGTH = 4; +const size_t KEY_KDF_SALT_LENGTH = 10; +const size_t MAC_KEY_LENGTH = 32; +const size_t CIPHER_KEY_LENGTH = 32; +const size_t CIPHER_IV_LENGTH = 16; +const size_t MAC_OUTPUT_LENGTH = 32; + +} + +std::vector<byte> encrypt(const byte input[], size_t input_len, + const SymmetricKey& master_key, + RandomNumberGenerator& rng) + { + std::unique_ptr<KDF> kdf(get_kdf(CRYPTOBOX_KDF)); + + const secure_vector<byte> cipher_key_salt = + rng.random_vec(KEY_KDF_SALT_LENGTH); + + const secure_vector<byte> mac_key_salt = + rng.random_vec(KEY_KDF_SALT_LENGTH); + + SymmetricKey cipher_key = + kdf->derive_key(CIPHER_KEY_LENGTH, + master_key.bits_of(), + cipher_key_salt); + + SymmetricKey mac_key = + kdf->derive_key(MAC_KEY_LENGTH, + master_key.bits_of(), + mac_key_salt); + + InitializationVector cipher_iv(rng, 16); + + std::unique_ptr<MessageAuthenticationCode> mac(get_mac(CRYPTOBOX_MAC)); + mac->set_key(mac_key); + + Pipe pipe(get_cipher(CRYPTOBOX_CIPHER, cipher_key, cipher_iv, ENCRYPTION)); + pipe.process_msg(input, input_len); + secure_vector<byte> ctext = pipe.read_all(0); + + std::vector<byte> out(MAGIC_LENGTH); + store_be(CRYPTOBOX_MAGIC, &out[0]); + out += cipher_key_salt; + out += mac_key_salt; + out += cipher_iv.bits_of(); + out += ctext; + + mac->update(out); + + out += mac->final(); + return out; + } + +secure_vector<byte> decrypt(const byte input[], size_t input_len, + const SymmetricKey& master_key) + { + const size_t MIN_CTEXT_SIZE = 16; // due to using CBC with padding + + const size_t MIN_POSSIBLE_LENGTH = + MAGIC_LENGTH + + 2 * KEY_KDF_SALT_LENGTH + + CIPHER_IV_LENGTH + + MIN_CTEXT_SIZE + + MAC_OUTPUT_LENGTH; + + if(input_len < MIN_POSSIBLE_LENGTH) + throw Decoding_Error("Encrypted input too short to be valid"); + + if(load_be<u32bit>(input, 0) != CRYPTOBOX_MAGIC) + throw Decoding_Error("Unknown header value in cryptobox"); + + std::unique_ptr<KDF> kdf(get_kdf(CRYPTOBOX_KDF)); + + const byte* cipher_key_salt = &input[MAGIC_LENGTH]; + + const byte* mac_key_salt = &input[MAGIC_LENGTH + KEY_KDF_SALT_LENGTH]; + + SymmetricKey mac_key = kdf->derive_key(MAC_KEY_LENGTH, + master_key.bits_of(), + mac_key_salt, + KEY_KDF_SALT_LENGTH); + + std::unique_ptr<MessageAuthenticationCode> mac(get_mac(CRYPTOBOX_MAC)); + mac->set_key(mac_key); + + mac->update(&input[0], input_len - MAC_OUTPUT_LENGTH); + secure_vector<byte> computed_mac = mac->final(); + + if(!same_mem(&input[input_len - MAC_OUTPUT_LENGTH], &computed_mac[0], computed_mac.size())) + throw Decoding_Error("MAC verification failed"); + + SymmetricKey cipher_key = + kdf->derive_key(CIPHER_KEY_LENGTH, + master_key.bits_of(), + cipher_key_salt, KEY_KDF_SALT_LENGTH); + + InitializationVector cipher_iv(&input[MAGIC_LENGTH+2*KEY_KDF_SALT_LENGTH], + CIPHER_IV_LENGTH); + + const size_t CTEXT_OFFSET = MAGIC_LENGTH + 2 * KEY_KDF_SALT_LENGTH + CIPHER_IV_LENGTH; + + Pipe pipe(get_cipher(CRYPTOBOX_CIPHER, cipher_key, cipher_iv, DECRYPTION)); + pipe.process_msg(&input[CTEXT_OFFSET], + input_len - (MAC_OUTPUT_LENGTH + CTEXT_OFFSET)); + return pipe.read_all(); + } + +} + +} diff --git a/src/tls/tls_session.cpp b/src/tls/tls_session.cpp index 85cb6d69e..9d869116c 100644 --- a/src/tls/tls_session.cpp +++ b/src/tls/tls_session.cpp @@ -10,8 +10,7 @@ #include <botan/ber_dec.h> #include <botan/asn1_str.h> #include <botan/pem.h> -#include <botan/lookup.h> -#include <botan/loadstor.h> +#include <botan/cryptobox.h> #include <memory> namespace Botan { @@ -147,64 +146,13 @@ std::chrono::seconds Session::session_age() const std::chrono::system_clock::now() - m_start_time); } -namespace { - -const u32bit SESSION_CRYPTO_MAGIC = 0x571B0E4F; -const std::string SESSION_CRYPTO_CIPHER = "AES-256/CBC"; -const std::string SESSION_CRYPTO_MAC = "HMAC(SHA-256)"; -const std::string SESSION_CRYPTO_KDF = "KDF2(SHA-256)"; - -const size_t MAGIC_LENGTH = 4; -const size_t KEY_KDF_SALT_LENGTH = 10; -const size_t MAC_KEY_LENGTH = 32; -const size_t CIPHER_KEY_LENGTH = 32; -const size_t CIPHER_IV_LENGTH = 16; -const size_t MAC_OUTPUT_LENGTH = 32; - -} - std::vector<byte> Session::encrypt(const SymmetricKey& master_key, RandomNumberGenerator& rng) const { - std::unique_ptr<KDF> kdf(get_kdf(SESSION_CRYPTO_KDF)); - - const secure_vector<byte> cipher_key_salt = - rng.random_vec(KEY_KDF_SALT_LENGTH); - - const secure_vector<byte> mac_key_salt = - rng.random_vec(KEY_KDF_SALT_LENGTH); - - SymmetricKey cipher_key = - kdf->derive_key(CIPHER_KEY_LENGTH, - master_key.bits_of(), - cipher_key_salt); - - SymmetricKey mac_key = - kdf->derive_key(MAC_KEY_LENGTH, - master_key.bits_of(), - mac_key_salt); - - InitializationVector cipher_iv(rng, 16); - - std::unique_ptr<MessageAuthenticationCode> mac(get_mac(SESSION_CRYPTO_MAC)); - mac->set_key(mac_key); - - Pipe pipe(get_cipher(SESSION_CRYPTO_CIPHER, cipher_key, cipher_iv, ENCRYPTION)); - pipe.process_msg(this->DER_encode()); - secure_vector<byte> ctext = pipe.read_all(0); - - std::vector<byte> out(MAGIC_LENGTH); - store_be(SESSION_CRYPTO_MAGIC, &out[0]); - out += cipher_key_salt; - out += mac_key_salt; - out += cipher_iv.bits_of(); - out += ctext; - - mac->update(out); + const auto der = this->DER_encode(); - out += mac->final(); - return out; + return CryptoBox::encrypt(&der[0], der.size(), master_key, rng); } Session Session::decrypt(const byte buf[], size_t buf_len, @@ -212,52 +160,7 @@ Session Session::decrypt(const byte buf[], size_t buf_len, { try { - const size_t MIN_CTEXT_SIZE = 4 * 16; // due to 48 byte master secret - - if(buf_len < (MAGIC_LENGTH + - 2 * KEY_KDF_SALT_LENGTH + - CIPHER_IV_LENGTH + - MIN_CTEXT_SIZE + - MAC_OUTPUT_LENGTH)) - throw Decoding_Error("Encrypted TLS session too short to be valid"); - - if(load_be<u32bit>(buf, 0) != SESSION_CRYPTO_MAGIC) - throw Decoding_Error("Unknown header value in encrypted session"); - - std::unique_ptr<KDF> kdf(get_kdf(SESSION_CRYPTO_KDF)); - - const byte* cipher_key_salt = &buf[MAGIC_LENGTH]; - - const byte* mac_key_salt = &buf[MAGIC_LENGTH + KEY_KDF_SALT_LENGTH]; - - SymmetricKey mac_key = - kdf->derive_key(MAC_KEY_LENGTH, - master_key.bits_of(), - mac_key_salt, KEY_KDF_SALT_LENGTH); - - std::unique_ptr<MessageAuthenticationCode> mac(get_mac(SESSION_CRYPTO_MAC)); - mac->set_key(mac_key); - - mac->update(&buf[0], buf_len - MAC_OUTPUT_LENGTH); - secure_vector<byte> computed_mac = mac->final(); - - if(!same_mem(&buf[buf_len - MAC_OUTPUT_LENGTH], &computed_mac[0], computed_mac.size())) - throw Decoding_Error("MAC verification failed for encrypted session"); - - SymmetricKey cipher_key = - kdf->derive_key(CIPHER_KEY_LENGTH, - master_key.bits_of(), - cipher_key_salt, KEY_KDF_SALT_LENGTH); - - InitializationVector cipher_iv(&buf[MAGIC_LENGTH+2*KEY_KDF_SALT_LENGTH], - CIPHER_IV_LENGTH); - - const size_t CTEXT_OFFSET = MAGIC_LENGTH + 2 * KEY_KDF_SALT_LENGTH + CIPHER_IV_LENGTH; - - Pipe pipe(get_cipher(SESSION_CRYPTO_CIPHER, cipher_key, cipher_iv, DECRYPTION)); - pipe.process_msg(&buf[CTEXT_OFFSET], - buf_len - (MAC_OUTPUT_LENGTH + CTEXT_OFFSET)); - secure_vector<byte> ber = pipe.read_all(); + const auto ber = CryptoBox::decrypt(buf, buf_len, master_key); return Session(&ber[0], ber.size()); } |