aboutsummaryrefslogtreecommitdiffstats
path: root/src/constructs
diff options
context:
space:
mode:
authorlloyd <[email protected]>2013-03-04 22:46:01 +0000
committerlloyd <[email protected]>2013-03-04 22:46:01 +0000
commita85e80776608ceaf7bef92abbe987927f83fcc99 (patch)
tree1dbd038188a3f8278262d7cb14803bfa4f6498e4 /src/constructs
parent30315e4234b6e0f970b9c343b0d27e67d5979ac7 (diff)
Pull the code doing TLS session crypto out to cryptobox for general
use and call it.
Diffstat (limited to 'src/constructs')
-rw-r--r--src/constructs/cryptobox/cryptobox.h25
-rw-r--r--src/constructs/cryptobox/raw_key.cpp134
2 files changed, 159 insertions, 0 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();
+ }
+
+}
+
+}