commit 6cb9c2cf77cc8375f89cc8d625d0b60e292d8160 Author: Nick Mathewson nickm@torproject.org Date: Fri Sep 16 11:21:33 2016 -0400
Add support for AES256 and AES192
(This will be used by prop224) --- src/common/aes.c | 2 +- src/common/crypto.c | 39 +++++++++++++++++++++++-------- src/common/crypto.h | 4 ++++ src/test/test_crypto.c | 62 ++++++++++++++++++++++++++++++++++++++------------ 4 files changed, 82 insertions(+), 25 deletions(-)
diff --git a/src/common/aes.c b/src/common/aes.c index 7131ce1..cb8fb68 100644 --- a/src/common/aes.c +++ b/src/common/aes.c @@ -48,7 +48,7 @@ ENABLE_GCC_WARNING(redundant-decls)
/* We have five strategies for implementing AES counter mode. * - * Best with x86 and x86_64: Use EVP_aes_ctr128() and EVP_EncryptUpdate(). + * Best with x86 and x86_64: Use EVP_aes_*_ctr() and EVP_EncryptUpdate(). * This is possible with OpenSSL 1.0.1, where the counter-mode implementation * can use bit-sliced or vectorized AES or AESNI as appropriate. * diff --git a/src/common/crypto.c b/src/common/crypto.c index fb77340..72c1c45 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -542,29 +542,48 @@ crypto_pk_free(crypto_pk_t *env) }
/** Allocate and return a new symmetric cipher using the provided key and iv. - * The key is CIPHER_KEY_LEN bytes; the IV is CIPHER_IV_LEN bytes. Both - * must be provided. - */ + * The key is <b>bits</b> bits long; the IV is CIPHER_IV_LEN bytes. Both + * must be provided. Key length must be 128, 192, or 256 */ crypto_cipher_t * -crypto_cipher_new_with_iv(const char *key, const char *iv) +crypto_cipher_new_with_iv_and_bits(const uint8_t *key, + const uint8_t *iv, + int bits) { - crypto_cipher_t *env; tor_assert(key); tor_assert(iv);
- env = aes_new_cipher((const uint8_t*)key, (const uint8_t*)iv, 128); + return aes_new_cipher((const uint8_t*)key, (const uint8_t*)iv, bits); +}
- return env; +/** Allocate and return a new symmetric cipher using the provided key and iv. + * The key is CIPHER_KEY_LEN bytes; the IV is CIPHER_IV_LEN bytes. Both + * must be provided. + */ +crypto_cipher_t * +crypto_cipher_new_with_iv(const char *key, const char *iv) +{ + return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)iv, + 128); }
/** Return a new crypto_cipher_t with the provided <b>key</b> and an IV of all - * zero bytes. */ + * zero bytes and key length <b>bits</b>. Key length must be 128, 192, or + * 256. */ crypto_cipher_t * -crypto_cipher_new(const char *key) +crypto_cipher_new_with_bits(const char *key, int bits) { char zeroiv[CIPHER_IV_LEN]; memset(zeroiv, 0, sizeof(zeroiv)); - return crypto_cipher_new_with_iv(key, zeroiv); + return crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)zeroiv, + bits); +} + +/** Return a new crypto_cipher_t with the provided <b>key</b> (of + * CIPHER_KEY_LEN bytes) and an IV of all zero bytes. */ +crypto_cipher_t * +crypto_cipher_new(const char *key) +{ + return crypto_cipher_new_with_bits(key, 128); }
/** Free a symmetric cipher. diff --git a/src/common/crypto.h b/src/common/crypto.h index e60cf34..116e0a6 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -138,7 +138,11 @@ void crypto_pk_free(crypto_pk_t *env);
void crypto_set_tls_dh_prime(void); crypto_cipher_t *crypto_cipher_new(const char *key); +crypto_cipher_t *crypto_cipher_new_with_bits(const char *key, int bits); crypto_cipher_t *crypto_cipher_new_with_iv(const char *key, const char *iv); +crypto_cipher_t *crypto_cipher_new_with_iv_and_bits(const uint8_t *key, + const uint8_t *iv, + int bits); void crypto_cipher_free(crypto_cipher_t *env);
/* public key crypto */ diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 6586c06..64a46f7 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -363,9 +363,9 @@ test_crypto_rng_engine(void *arg) ; }
-/** Run unit tests for our AES functionality */ +/** Run unit tests for our AES128 functionality */ static void -test_crypto_aes(void *arg) +test_crypto_aes128(void *arg) { char *data1 = NULL, *data2 = NULL, *data3 = NULL; crypto_cipher_t *env1 = NULL, *env2 = NULL; @@ -514,32 +514,61 @@ test_crypto_aes(void *arg) static void test_crypto_aes_ctr_testvec(void *arg) { - (void)arg; + const char *bitstr = arg; char *mem_op_hex_tmp=NULL; + crypto_cipher_t *c=NULL;
/* from NIST SP800-38a, section F.5 */ - const char key16[] = "2b7e151628aed2a6abf7158809cf4f3c"; const char ctr16[] = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"; const char plaintext16[] = "6bc1bee22e409f96e93d7e117393172a" "ae2d8a571e03ac9c9eb76fac45af8e51" "30c81c46a35ce411e5fbc1191a0a52ef" "f69f2445df4f9b17ad2b417be66c3710"; - const char ciphertext16[] = - "874d6191b620e3261bef6864990db6ce" - "9806f66b7970fdff8617187bb9fffdff" - "5ae4df3edbd5d35e5b4f09020db03eab" - "1e031dda2fbe03d1792170a0f3009cee"; + const char *ciphertext16; + const char *key16; + int bits; + + if (!strcmp(bitstr, "128")) { + ciphertext16 = /* section F.5.1 */ + "874d6191b620e3261bef6864990db6ce" + "9806f66b7970fdff8617187bb9fffdff" + "5ae4df3edbd5d35e5b4f09020db03eab" + "1e031dda2fbe03d1792170a0f3009cee"; + key16 = "2b7e151628aed2a6abf7158809cf4f3c"; + bits = 128; + } else if (!strcmp(bitstr, "192")) { + ciphertext16 = /* section F.5.3 */ + "1abc932417521ca24f2b0459fe7e6e0b" + "090339ec0aa6faefd5ccc2c6f4ce8e94" + "1e36b26bd1ebc670d1bd1d665620abf7" + "4f78a7f6d29809585a97daec58c6b050"; + key16 = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; + bits = 192; + } else if (!strcmp(bitstr, "256")) { + ciphertext16 = /* section F.5.5 */ + "601ec313775789a5b7a7f504bbf3d228" + "f443e3ca4d62b59aca84e990cacaf5c5" + "2b0930daa23de94ce87017ba2d84988d" + "dfc9c58db67aada613c2dd08457941a6"; + key16 = + "603deb1015ca71be2b73aef0857d7781" + "1f352c073b6108d72d9810a30914dff4"; + bits = 256; + } else { + tt_abort_msg("AES doesn't support this number of bits."); + }
- char key[16]; + char key[32]; char iv[16]; char plaintext[16*4]; + memset(key, 0xf9, sizeof(key)); /* poison extra bytes */ base16_decode(key, sizeof(key), key16, strlen(key16)); base16_decode(iv, sizeof(iv), ctr16, strlen(ctr16)); base16_decode(plaintext, sizeof(plaintext), plaintext16, strlen(plaintext16));
- crypto_cipher_t *c = crypto_cipher_new_with_iv(key, iv); + c = crypto_cipher_new_with_iv_and_bits((uint8_t*)key, (uint8_t*)iv, bits); crypto_cipher_crypt_inplace(c, plaintext, sizeof(plaintext)); test_memeq_hex(plaintext, ciphertext16);
@@ -2873,9 +2902,14 @@ struct testcase_t crypto_tests[] = { { "rng_strongest_broken", test_crypto_rng_strongest, TT_FORK, &passthrough_setup, (void*)"broken" }, { "openssl_version", test_crypto_openssl_version, TT_FORK, NULL, NULL }, - { "aes_AES", test_crypto_aes, TT_FORK, &passthrough_setup, (void*)"aes" }, - { "aes_EVP", test_crypto_aes, TT_FORK, &passthrough_setup, (void*)"evp" }, - { "aes_ctr_testvec", test_crypto_aes_ctr_testvec, 0, NULL, NULL }, + { "aes_AES", test_crypto_aes128, TT_FORK, &passthrough_setup, (void*)"aes" }, + { "aes_EVP", test_crypto_aes128, TT_FORK, &passthrough_setup, (void*)"evp" }, + { "aes128_ctr_testvec", test_crypto_aes_ctr_testvec, 0, + &passthrough_setup, (void*)"128" }, + { "aes192_ctr_testvec", test_crypto_aes_ctr_testvec, 0, + &passthrough_setup, (void*)"192" }, + { "aes256_ctr_testvec", test_crypto_aes_ctr_testvec, 0, + &passthrough_setup, (void*)"256" }, CRYPTO_LEGACY(sha), CRYPTO_LEGACY(pk), { "pk_fingerprints", test_crypto_pk_fingerprints, TT_FORK, NULL, NULL },