diff options
Diffstat (limited to 'crypto/evp/e_aes.c')
-rw-r--r-- | crypto/evp/e_aes.c | 72 |
1 files changed, 70 insertions, 2 deletions
diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c index 68322e1982..e60d736b9c 100644 --- a/crypto/evp/e_aes.c +++ b/crypto/evp/e_aes.c @@ -59,6 +59,12 @@ typedef struct { const unsigned char iv[16]); } EVP_AES_XTS_CTX; +#ifdef FIPS_MODE +static const int allow_insecure_decrypt = 0; +#else +static const int allow_insecure_decrypt = 1; +#endif + typedef struct { union { double align; @@ -383,10 +389,27 @@ static int aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); + if (!iv && !key) return 1; if (key) { + /* The key is two half length keys in reality */ + const int bytes = EVP_CIPHER_CTX_key_length(ctx) / 2; + const int bits = bytes * 8; + + /* + * Verify that the two keys are different. + * + * This addresses Rogaway's vulnerability. + * See comment in aes_xts_init_key() below. + */ + if ((!allow_insecure_decrypt || enc) + && CRYPTO_memcmp(key, key + bytes, bytes) == 0) { + EVPerr(EVP_F_AESNI_XTS_INIT_KEY, EVP_R_XTS_DUPLICATED_KEYS); + return 0; + } + /* key_len is two AES keys */ if (enc) { aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4, @@ -787,11 +810,27 @@ static int aes_t4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); + if (!iv && !key) return 1; if (key) { - int bits = EVP_CIPHER_CTX_key_length(ctx) * 4; + /* The key is two half length keys in reality */ + const int bytes = EVP_CIPHER_CTX_key_length(ctx) / 2; + const int bits = bytes * 8; + + /* + * Verify that the two keys are different. + * + * This addresses Rogaway's vulnerability. + * See comment in aes_xts_init_key() below. + */ + if ((!allow_insecure_decrypt || enc) + && CRYPTO_memcmp(key, key + bytes, bytes) == 0) { + EVPerr(EVP_F_AES_T4_XTS_INIT_KEY, EVP_R_XTS_DUPLICATED_KEYS); + return 0; + } + xctx->stream = NULL; /* key_len is two AES keys */ if (enc) { @@ -3284,10 +3323,12 @@ BLOCK_CIPHER_custom(NID_aes, 128, 1, 12, gcm, GCM, static int aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) { - EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,c); + EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX, c); + if (type == EVP_CTRL_COPY) { EVP_CIPHER_CTX *out = ptr; EVP_AES_XTS_CTX *xctx_out = EVP_C_DATA(EVP_AES_XTS_CTX,out); + if (xctx->xts.key1) { if (xctx->xts.key1 != &xctx->ks1) return 0; @@ -3311,11 +3352,38 @@ static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); + if (!iv && !key) return 1; if (key) do { + /* The key is two half length keys in reality */ + const int bytes = EVP_CIPHER_CTX_key_length(ctx) / 2; + const int bits = bytes * 8; + + /* + * Verify that the two keys are different. + * + * This addresses the vulnerability described in Rogaway's + * September 2004 paper: + * + * "Efficient Instantiations of Tweakable Blockciphers and + * Refinements to Modes OCB and PMAC". + * (http://web.cs.ucdavis.edu/~rogaway/papers/offsets.pdf) + * + * FIPS 140-2 IG A.9 XTS-AES Key Generation Requirements states + * that: + * "The check for Key_1 != Key_2 shall be done at any place + * BEFORE using the keys in the XTS-AES algorithm to process + * data with them." + */ + if ((!allow_insecure_decrypt || enc) + && CRYPTO_memcmp(key, key + bytes, bytes) == 0) { + EVPerr(EVP_F_AES_XTS_INIT_KEY, EVP_R_XTS_DUPLICATED_KEYS); + return 0; + } + #ifdef AES_XTS_ASM xctx->stream = enc ? AES_xts_encrypt : AES_xts_decrypt; #else |