Implement AES-XEX mode
XEX mode, known as "xor-encrypt-xor", is the simple case of the XTS
mode, known as "XEX with ciphertext stealing". When the buffers to be
encrypted/decrypted have a length divisible by the length of a standard
AES block (16), XTS is exactly like XEX.
diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h
index e48981a..652281c 100644
--- a/include/mbedtls/aes.h
+++ b/include/mbedtls/aes.h
@@ -213,6 +213,30 @@
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 e27e40a..766aa21 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 @@
}
#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