diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h index e48981ab9d..652281c7e5 100644 --- a/include/mbedtls/aes.h +++ b/include/mbedtls/aes.h @@ -213,6 +213,30 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, unsigned char *output ); #endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CIPHER_MODE_XEX) +/** + * \brief AES-XEX buffer encryption/decryption + * Length should be a multiple of the block size (16 bytes) + * + * \param crypt_ctx AES context for encrypting data + * \param tweak_ctx AES context for xor-ing with data + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH + */ +int mbedtls_aes_crypt_xex( mbedtls_aes_context *crypt_ctx, + mbedtls_aes_context *tweak_ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_XEX */ + #if defined(MBEDTLS_CIPHER_MODE_CFB) /** * \brief This function performs an AES-CFB128 encryption or decryption diff --git a/library/aes.c b/library/aes.c index e27e40a86b..766aa21a79 100644 --- a/library/aes.c +++ b/library/aes.c @@ -44,6 +44,10 @@ #include "mbedtls/aesni.h" #endif +#if defined(MBEDTLS_CIPHER_MODE_XEX) +#include "mbedtls/gf128mul.h" +#endif + #if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" @@ -983,6 +987,55 @@ int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, } #endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CIPHER_MODE_XEX) +/* + * AES-XEX buffer encryption/decryption + */ +int mbedtls_aes_crypt_xex( mbedtls_aes_context *crypt_ctx, + mbedtls_aes_context *tweak_ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char t_buf[16]; + unsigned char scratch[16]; + + if( length % 16 ) + return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ); + + + mbedtls_aes_crypt_ecb( tweak_ctx, MBEDTLS_AES_ENCRYPT, iv, t_buf ); + + goto first; + + do + { + gf128mul_x_ble( t_buf, t_buf ); + +first: + /* PP <- T xor P */ + for( i = 0; i < 16; i++ ) + scratch[i] = (unsigned char)( input[i] ^ t_buf[i] ); + + /* CC <- E(Key2,PP) */ + mbedtls_aes_crypt_ecb( crypt_ctx, mode, scratch, output ); + + /* C <- T xor CC */ + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ t_buf[i] ); + + input += 16; + output += 16; + length -= 16; + } while( length > 0 ); + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_XEX */ + #if defined(MBEDTLS_CIPHER_MODE_CFB) /* * AES-CFB128 buffer encryption/decryption