Import mbedtls-2.16.0
Imports mbedTLS 2.16.0 from https://github.com/ARMmbed/mbedtls.git
commit fb1972db23da ("Merge pull request #544 from ARMmbed/version-2.16")
(tag mbedtls-2.16.0).
Certain files will never be needed and are thus removed (reducing number
of lines to almost 50%):
rm -f circle.yml CMakeLists.txt DartConfiguration.tcl Makefile
rm -f .gitignore .travis.yml .pylint
rm -f include/.gitignore include/CMakeLists.txt library/.gitignore
rm -f library/CMakeLists.txt library/Makefile
rm -rf .git .github doxygen configs programs scripts tests visualc yotta
This is a complete overwrite of previous code so earlier changes in the
branch import/mbedtls-2.6.1 will be added on top of this commit to bring
the changes forward.
Acked-by: Jerome Forissier <jerome.forissier@linaro.org>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
diff --git a/lib/libmbedtls/mbedtls/library/aes.c b/lib/libmbedtls/mbedtls/library/aes.c
index 2373082..0543cd7 100644
--- a/lib/libmbedtls/mbedtls/library/aes.c
+++ b/lib/libmbedtls/mbedtls/library/aes.c
@@ -1,8 +1,8 @@
-// SPDX-License-Identifier: Apache-2.0
/*
* FIPS-197 compliant AES implementation
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
@@ -36,6 +36,8 @@
#include <string.h>
#include "mbedtls/aes.h"
+#include "mbedtls/platform.h"
+#include "mbedtls/platform_util.h"
#if defined(MBEDTLS_PADLOCK_C)
#include "mbedtls/padlock.h"
#endif
@@ -54,10 +56,11 @@
#if !defined(MBEDTLS_AES_ALT)
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_zeroize( void *v, size_t n ) {
- volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
-}
+/* Parameter validation macros based on platform_util.h */
+#define AES_VALIDATE_RET( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_AES_BAD_INPUT_DATA )
+#define AES_VALIDATE( cond ) \
+ MBEDTLS_INTERNAL_VALIDATE( cond )
/*
* 32-bit integer manipulation macros (little endian)
@@ -201,6 +204,8 @@
static const uint32_t FT0[256] = { FT };
#undef V
+#if !defined(MBEDTLS_AES_FEWER_TABLES)
+
#define V(a,b,c,d) 0x##b##c##d##a
static const uint32_t FT1[256] = { FT };
#undef V
@@ -213,6 +218,8 @@
static const uint32_t FT3[256] = { FT };
#undef V
+#endif /* !MBEDTLS_AES_FEWER_TABLES */
+
#undef FT
/*
@@ -328,6 +335,8 @@
static const uint32_t RT0[256] = { RT };
#undef V
+#if !defined(MBEDTLS_AES_FEWER_TABLES)
+
#define V(a,b,c,d) 0x##b##c##d##a
static const uint32_t RT1[256] = { RT };
#undef V
@@ -340,6 +349,8 @@
static const uint32_t RT3[256] = { RT };
#undef V
+#endif /* !MBEDTLS_AES_FEWER_TABLES */
+
#undef RT
/*
@@ -359,18 +370,22 @@
*/
static unsigned char FSb[256];
static uint32_t FT0[256];
+#if !defined(MBEDTLS_AES_FEWER_TABLES)
static uint32_t FT1[256];
static uint32_t FT2[256];
static uint32_t FT3[256];
+#endif /* !MBEDTLS_AES_FEWER_TABLES */
/*
* Reverse S-box & tables
*/
static unsigned char RSb[256];
static uint32_t RT0[256];
+#if !defined(MBEDTLS_AES_FEWER_TABLES)
static uint32_t RT1[256];
static uint32_t RT2[256];
static uint32_t RT3[256];
+#endif /* !MBEDTLS_AES_FEWER_TABLES */
/*
* Round constants
@@ -445,9 +460,11 @@
( (uint32_t) x << 16 ) ^
( (uint32_t) z << 24 );
+#if !defined(MBEDTLS_AES_FEWER_TABLES)
FT1[i] = ROTL8( FT0[i] );
FT2[i] = ROTL8( FT1[i] );
FT3[i] = ROTL8( FT2[i] );
+#endif /* !MBEDTLS_AES_FEWER_TABLES */
x = RSb[i];
@@ -456,16 +473,52 @@
( (uint32_t) MUL( 0x0D, x ) << 16 ) ^
( (uint32_t) MUL( 0x0B, x ) << 24 );
+#if !defined(MBEDTLS_AES_FEWER_TABLES)
RT1[i] = ROTL8( RT0[i] );
RT2[i] = ROTL8( RT1[i] );
RT3[i] = ROTL8( RT2[i] );
+#endif /* !MBEDTLS_AES_FEWER_TABLES */
}
}
+#undef ROTL8
+
#endif /* MBEDTLS_AES_ROM_TABLES */
+#if defined(MBEDTLS_AES_FEWER_TABLES)
+
+#define ROTL8(x) ( (uint32_t)( ( x ) << 8 ) + (uint32_t)( ( x ) >> 24 ) )
+#define ROTL16(x) ( (uint32_t)( ( x ) << 16 ) + (uint32_t)( ( x ) >> 16 ) )
+#define ROTL24(x) ( (uint32_t)( ( x ) << 24 ) + (uint32_t)( ( x ) >> 8 ) )
+
+#define AES_RT0(idx) RT0[idx]
+#define AES_RT1(idx) ROTL8( RT0[idx] )
+#define AES_RT2(idx) ROTL16( RT0[idx] )
+#define AES_RT3(idx) ROTL24( RT0[idx] )
+
+#define AES_FT0(idx) FT0[idx]
+#define AES_FT1(idx) ROTL8( FT0[idx] )
+#define AES_FT2(idx) ROTL16( FT0[idx] )
+#define AES_FT3(idx) ROTL24( FT0[idx] )
+
+#else /* MBEDTLS_AES_FEWER_TABLES */
+
+#define AES_RT0(idx) RT0[idx]
+#define AES_RT1(idx) RT1[idx]
+#define AES_RT2(idx) RT2[idx]
+#define AES_RT3(idx) RT3[idx]
+
+#define AES_FT0(idx) FT0[idx]
+#define AES_FT1(idx) FT1[idx]
+#define AES_FT2(idx) FT2[idx]
+#define AES_FT3(idx) FT3[idx]
+
+#endif /* MBEDTLS_AES_FEWER_TABLES */
+
void mbedtls_aes_init( mbedtls_aes_context *ctx )
{
+ AES_VALIDATE( ctx != NULL );
+
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
}
@@ -474,9 +527,28 @@
if( ctx == NULL )
return;
- mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) );
+ mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) );
}
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx )
+{
+ AES_VALIDATE( ctx != NULL );
+
+ mbedtls_aes_init( &ctx->crypt );
+ mbedtls_aes_init( &ctx->tweak );
+}
+
+void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx )
+{
+ if( ctx == NULL )
+ return;
+
+ mbedtls_aes_free( &ctx->crypt );
+ mbedtls_aes_free( &ctx->tweak );
+}
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
/*
* AES key schedule (encryption)
*/
@@ -487,14 +559,8 @@
unsigned int i;
uint32_t *RK;
-#if !defined(MBEDTLS_AES_ROM_TABLES)
- if( aes_init_done == 0 )
- {
- aes_gen_tables();
- aes_init_done = 1;
-
- }
-#endif
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( key != NULL );
switch( keybits )
{
@@ -504,6 +570,14 @@
default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
}
+#if !defined(MBEDTLS_AES_ROM_TABLES)
+ if( aes_init_done == 0 )
+ {
+ aes_gen_tables();
+ aes_init_done = 1;
+ }
+#endif
+
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16)
if( aes_padlock_ace == -1 )
aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE );
@@ -603,6 +677,9 @@
uint32_t *RK;
uint32_t *SK;
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( key != NULL );
+
mbedtls_aes_init( &cty );
#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16)
@@ -641,10 +718,10 @@
{
for( j = 0; j < 4; j++, SK++ )
{
- *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^
- RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^
- RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
- RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
+ *RK++ = AES_RT0( FSb[ ( *SK ) & 0xFF ] ) ^
+ AES_RT1( FSb[ ( *SK >> 8 ) & 0xFF ] ) ^
+ AES_RT2( FSb[ ( *SK >> 16 ) & 0xFF ] ) ^
+ AES_RT3( FSb[ ( *SK >> 24 ) & 0xFF ] );
}
}
@@ -658,52 +735,130 @@
return( ret );
}
-#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */
-#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
-{ \
- X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \
- FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
- FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
- FT3[ ( Y3 >> 24 ) & 0xFF ]; \
- \
- X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \
- FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
- FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
- FT3[ ( Y0 >> 24 ) & 0xFF ]; \
- \
- X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \
- FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
- FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
- FT3[ ( Y1 >> 24 ) & 0xFF ]; \
- \
- X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \
- FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
- FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
- FT3[ ( Y2 >> 24 ) & 0xFF ]; \
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+static int mbedtls_aes_xts_decode_keys( const unsigned char *key,
+ unsigned int keybits,
+ const unsigned char **key1,
+ unsigned int *key1bits,
+ const unsigned char **key2,
+ unsigned int *key2bits )
+{
+ const unsigned int half_keybits = keybits / 2;
+ const unsigned int half_keybytes = half_keybits / 8;
+
+ switch( keybits )
+ {
+ case 256: break;
+ case 512: break;
+ default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
+ }
+
+ *key1bits = half_keybits;
+ *key2bits = half_keybits;
+ *key1 = &key[0];
+ *key2 = &key[half_keybytes];
+
+ return 0;
}
-#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
-{ \
- X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \
- RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
- RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
- RT3[ ( Y1 >> 24 ) & 0xFF ]; \
- \
- X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \
- RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
- RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
- RT3[ ( Y2 >> 24 ) & 0xFF ]; \
- \
- X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \
- RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
- RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
- RT3[ ( Y3 >> 24 ) & 0xFF ]; \
- \
- X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \
- RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
- RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
- RT3[ ( Y0 >> 24 ) & 0xFF ]; \
+int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
+ const unsigned char *key,
+ unsigned int keybits)
+{
+ int ret;
+ const unsigned char *key1, *key2;
+ unsigned int key1bits, key2bits;
+
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( key != NULL );
+
+ ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
+ &key2, &key2bits );
+ if( ret != 0 )
+ return( ret );
+
+ /* Set the tweak key. Always set tweak key for the encryption mode. */
+ ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits );
+ if( ret != 0 )
+ return( ret );
+
+ /* Set crypt key for encryption. */
+ return mbedtls_aes_setkey_enc( &ctx->crypt, key1, key1bits );
+}
+
+int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
+ const unsigned char *key,
+ unsigned int keybits)
+{
+ int ret;
+ const unsigned char *key1, *key2;
+ unsigned int key1bits, key2bits;
+
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( key != NULL );
+
+ ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
+ &key2, &key2bits );
+ if( ret != 0 )
+ return( ret );
+
+ /* Set the tweak key. Always set tweak key for encryption. */
+ ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits );
+ if( ret != 0 )
+ return( ret );
+
+ /* Set crypt key for decryption. */
+ return mbedtls_aes_setkey_dec( &ctx->crypt, key1, key1bits );
+}
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
+#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */
+
+#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
+{ \
+ X0 = *RK++ ^ AES_FT0( ( Y0 ) & 0xFF ) ^ \
+ AES_FT1( ( Y1 >> 8 ) & 0xFF ) ^ \
+ AES_FT2( ( Y2 >> 16 ) & 0xFF ) ^ \
+ AES_FT3( ( Y3 >> 24 ) & 0xFF ); \
+ \
+ X1 = *RK++ ^ AES_FT0( ( Y1 ) & 0xFF ) ^ \
+ AES_FT1( ( Y2 >> 8 ) & 0xFF ) ^ \
+ AES_FT2( ( Y3 >> 16 ) & 0xFF ) ^ \
+ AES_FT3( ( Y0 >> 24 ) & 0xFF ); \
+ \
+ X2 = *RK++ ^ AES_FT0( ( Y2 ) & 0xFF ) ^ \
+ AES_FT1( ( Y3 >> 8 ) & 0xFF ) ^ \
+ AES_FT2( ( Y0 >> 16 ) & 0xFF ) ^ \
+ AES_FT3( ( Y1 >> 24 ) & 0xFF ); \
+ \
+ X3 = *RK++ ^ AES_FT0( ( Y3 ) & 0xFF ) ^ \
+ AES_FT1( ( Y0 >> 8 ) & 0xFF ) ^ \
+ AES_FT2( ( Y1 >> 16 ) & 0xFF ) ^ \
+ AES_FT3( ( Y2 >> 24 ) & 0xFF ); \
+}
+
+#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
+{ \
+ X0 = *RK++ ^ AES_RT0( ( Y0 ) & 0xFF ) ^ \
+ AES_RT1( ( Y3 >> 8 ) & 0xFF ) ^ \
+ AES_RT2( ( Y2 >> 16 ) & 0xFF ) ^ \
+ AES_RT3( ( Y1 >> 24 ) & 0xFF ); \
+ \
+ X1 = *RK++ ^ AES_RT0( ( Y1 ) & 0xFF ) ^ \
+ AES_RT1( ( Y0 >> 8 ) & 0xFF ) ^ \
+ AES_RT2( ( Y3 >> 16 ) & 0xFF ) ^ \
+ AES_RT3( ( Y2 >> 24 ) & 0xFF ); \
+ \
+ X2 = *RK++ ^ AES_RT0( ( Y2 ) & 0xFF ) ^ \
+ AES_RT1( ( Y1 >> 8 ) & 0xFF ) ^ \
+ AES_RT2( ( Y0 >> 16 ) & 0xFF ) ^ \
+ AES_RT3( ( Y3 >> 24 ) & 0xFF ); \
+ \
+ X3 = *RK++ ^ AES_RT0( ( Y3 ) & 0xFF ) ^ \
+ AES_RT1( ( Y2 >> 8 ) & 0xFF ) ^ \
+ AES_RT2( ( Y1 >> 16 ) & 0xFF ) ^ \
+ AES_RT3( ( Y0 >> 24 ) & 0xFF ); \
}
/*
@@ -765,12 +920,14 @@
}
#endif /* !MBEDTLS_AES_ENCRYPT_ALT */
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
mbedtls_internal_aes_encrypt( ctx, input, output );
}
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
/*
* AES-ECB block decryption
@@ -831,21 +988,29 @@
}
#endif /* !MBEDTLS_AES_DECRYPT_ALT */
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] )
{
mbedtls_internal_aes_decrypt( ctx, input, output );
}
+#endif /* !MBEDTLS_DEPRECATED_REMOVED */
/*
* AES-ECB block encryption/decryption
*/
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
- int mode,
- const unsigned char input[16],
- unsigned char output[16] )
+ int mode,
+ const unsigned char input[16],
+ unsigned char output[16] )
{
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( input != NULL );
+ AES_VALIDATE_RET( output != NULL );
+ AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
+ mode == MBEDTLS_AES_DECRYPT );
+
#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64)
if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) )
return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) );
@@ -883,6 +1048,13 @@
int i;
unsigned char temp[16];
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
+ mode == MBEDTLS_AES_DECRYPT );
+ AES_VALIDATE_RET( iv != NULL );
+ AES_VALIDATE_RET( input != NULL );
+ AES_VALIDATE_RET( output != NULL );
+
if( length % 16 )
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
@@ -935,6 +1107,172 @@
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+
+/* Endianess with 64 bits values */
+#ifndef GET_UINT64_LE
+#define GET_UINT64_LE(n,b,i) \
+{ \
+ (n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \
+ | ( (uint64_t) (b)[(i) + 6] << 48 ) \
+ | ( (uint64_t) (b)[(i) + 5] << 40 ) \
+ | ( (uint64_t) (b)[(i) + 4] << 32 ) \
+ | ( (uint64_t) (b)[(i) + 3] << 24 ) \
+ | ( (uint64_t) (b)[(i) + 2] << 16 ) \
+ | ( (uint64_t) (b)[(i) + 1] << 8 ) \
+ | ( (uint64_t) (b)[(i) ] ); \
+}
+#endif
+
+#ifndef PUT_UINT64_LE
+#define PUT_UINT64_LE(n,b,i) \
+{ \
+ (b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \
+ (b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \
+ (b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \
+ (b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) ] = (unsigned char) ( (n) ); \
+}
+#endif
+
+typedef unsigned char mbedtls_be128[16];
+
+/*
+ * GF(2^128) multiplication function
+ *
+ * This function multiplies a field element by x in the polynomial field
+ * representation. It uses 64-bit word operations to gain speed but compensates
+ * for machine endianess and hence works correctly on both big and little
+ * endian machines.
+ */
+static void mbedtls_gf128mul_x_ble( unsigned char r[16],
+ const unsigned char x[16] )
+{
+ uint64_t a, b, ra, rb;
+
+ GET_UINT64_LE( a, x, 0 );
+ GET_UINT64_LE( b, x, 8 );
+
+ ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) );
+ rb = ( a >> 63 ) | ( b << 1 );
+
+ PUT_UINT64_LE( ra, r, 0 );
+ PUT_UINT64_LE( rb, r, 8 );
+}
+
+/*
+ * AES-XTS buffer encryption/decryption
+ */
+int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
+ int mode,
+ size_t length,
+ const unsigned char data_unit[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret;
+ size_t blocks = length / 16;
+ size_t leftover = length % 16;
+ unsigned char tweak[16];
+ unsigned char prev_tweak[16];
+ unsigned char tmp[16];
+
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
+ mode == MBEDTLS_AES_DECRYPT );
+ AES_VALIDATE_RET( data_unit != NULL );
+ AES_VALIDATE_RET( input != NULL );
+ AES_VALIDATE_RET( output != NULL );
+
+ /* Data units must be at least 16 bytes long. */
+ if( length < 16 )
+ return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
+
+ /* NIST SP 800-38E disallows data units larger than 2**20 blocks. */
+ if( length > ( 1 << 20 ) * 16 )
+ return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
+
+ /* Compute the tweak. */
+ ret = mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT,
+ data_unit, tweak );
+ if( ret != 0 )
+ return( ret );
+
+ while( blocks-- )
+ {
+ size_t i;
+
+ if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 )
+ {
+ /* We are on the last block in a decrypt operation that has
+ * leftover bytes, so we need to use the next tweak for this block,
+ * and this tweak for the lefover bytes. Save the current tweak for
+ * the leftovers and then update the current tweak for use on this,
+ * the last full block. */
+ memcpy( prev_tweak, tweak, sizeof( tweak ) );
+ mbedtls_gf128mul_x_ble( tweak, tweak );
+ }
+
+ for( i = 0; i < 16; i++ )
+ tmp[i] = input[i] ^ tweak[i];
+
+ ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
+ if( ret != 0 )
+ return( ret );
+
+ for( i = 0; i < 16; i++ )
+ output[i] = tmp[i] ^ tweak[i];
+
+ /* Update the tweak for the next block. */
+ mbedtls_gf128mul_x_ble( tweak, tweak );
+
+ output += 16;
+ input += 16;
+ }
+
+ if( leftover )
+ {
+ /* If we are on the leftover bytes in a decrypt operation, we need to
+ * use the previous tweak for these bytes (as saved in prev_tweak). */
+ unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak;
+
+ /* We are now on the final part of the data unit, which doesn't divide
+ * evenly by 16. It's time for ciphertext stealing. */
+ size_t i;
+ unsigned char *prev_output = output - 16;
+
+ /* Copy ciphertext bytes from the previous block to our output for each
+ * byte of cyphertext we won't steal. At the same time, copy the
+ * remainder of the input for this final round (since the loop bounds
+ * are the same). */
+ for( i = 0; i < leftover; i++ )
+ {
+ output[i] = prev_output[i];
+ tmp[i] = input[i] ^ t[i];
+ }
+
+ /* Copy ciphertext bytes from the previous block for input in this
+ * round. */
+ for( ; i < 16; i++ )
+ tmp[i] = prev_output[i] ^ t[i];
+
+ ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
+ if( ret != 0 )
+ return ret;
+
+ /* Write the result back to the previous block, overriding the previous
+ * output we copied. */
+ for( i = 0; i < 16; i++ )
+ prev_output[i] = tmp[i] ^ t[i];
+ }
+
+ return( 0 );
+}
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/*
* AES-CFB128 buffer encryption/decryption
@@ -948,7 +1286,20 @@
unsigned char *output )
{
int c;
- size_t n = *iv_off;
+ size_t n;
+
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
+ mode == MBEDTLS_AES_DECRYPT );
+ AES_VALIDATE_RET( iv_off != NULL );
+ AES_VALIDATE_RET( iv != NULL );
+ AES_VALIDATE_RET( input != NULL );
+ AES_VALIDATE_RET( output != NULL );
+
+ n = *iv_off;
+
+ if( n > 15 )
+ return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
if( mode == MBEDTLS_AES_DECRYPT )
{
@@ -986,15 +1337,21 @@
* AES-CFB8 buffer encryption/decryption
*/
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
- int mode,
- size_t length,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output )
+ int mode,
+ size_t length,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
{
unsigned char c;
unsigned char ov[17];
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT ||
+ mode == MBEDTLS_AES_DECRYPT );
+ AES_VALIDATE_RET( iv != NULL );
+ AES_VALIDATE_RET( input != NULL );
+ AES_VALIDATE_RET( output != NULL );
while( length-- )
{
memcpy( ov, iv, 16 );
@@ -1013,7 +1370,52 @@
return( 0 );
}
-#endif /*MBEDTLS_CIPHER_MODE_CFB */
+#endif /* MBEDTLS_CIPHER_MODE_CFB */
+
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+/*
+ * AES-OFB (Output Feedback Mode) buffer encryption/decryption
+ */
+int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
+ size_t length,
+ size_t *iv_off,
+ unsigned char iv[16],
+ const unsigned char *input,
+ unsigned char *output )
+{
+ int ret = 0;
+ size_t n;
+
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( iv_off != NULL );
+ AES_VALIDATE_RET( iv != NULL );
+ AES_VALIDATE_RET( input != NULL );
+ AES_VALIDATE_RET( output != NULL );
+
+ n = *iv_off;
+
+ if( n > 15 )
+ return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
+
+ while( length-- )
+ {
+ if( n == 0 )
+ {
+ ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
+ if( ret != 0 )
+ goto exit;
+ }
+ *output++ = *input++ ^ iv[n];
+
+ n = ( n + 1 ) & 0x0F;
+ }
+
+ *iv_off = n;
+
+exit:
+ return( ret );
+}
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/*
@@ -1028,7 +1430,19 @@
unsigned char *output )
{
int c, i;
- size_t n = *nc_off;
+ size_t n;
+
+ AES_VALIDATE_RET( ctx != NULL );
+ AES_VALIDATE_RET( nc_off != NULL );
+ AES_VALIDATE_RET( nonce_counter != NULL );
+ AES_VALIDATE_RET( stream_block != NULL );
+ AES_VALIDATE_RET( input != NULL );
+ AES_VALIDATE_RET( output != NULL );
+
+ n = *nc_off;
+
+ if ( n > 0x0F )
+ return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
while( length-- )
{
@@ -1167,6 +1581,72 @@
};
#endif /* MBEDTLS_CIPHER_MODE_CFB */
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+/*
+ * AES-OFB test vectors from:
+ *
+ * https://csrc.nist.gov/publications/detail/sp/800-38a/final
+ */
+static const unsigned char aes_test_ofb_key[3][32] =
+{
+ { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
+ 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
+ { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
+ 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
+ 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
+ { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+ 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+ 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+ 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+};
+
+static const unsigned char aes_test_ofb_iv[16] =
+{
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
+};
+
+static const unsigned char aes_test_ofb_pt[64] =
+{
+ 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96,
+ 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A,
+ 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C,
+ 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51,
+ 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11,
+ 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF,
+ 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17,
+ 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
+};
+
+static const unsigned char aes_test_ofb_ct[3][64] =
+{
+ { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
+ 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
+ 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03,
+ 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25,
+ 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6,
+ 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc,
+ 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78,
+ 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e },
+ { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
+ 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
+ 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c,
+ 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01,
+ 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f,
+ 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2,
+ 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e,
+ 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a },
+ { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B,
+ 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60,
+ 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a,
+ 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d,
+ 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed,
+ 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08,
+ 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8,
+ 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 }
+};
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/*
* AES-CTR test vectors from:
@@ -1230,25 +1710,98 @@
{ 16, 32, 36 };
#endif /* MBEDTLS_CIPHER_MODE_CTR */
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+/*
+ * AES-XTS test vectors from:
+ *
+ * IEEE P1619/D16 Annex B
+ * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf
+ * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf)
+ */
+static const unsigned char aes_test_xts_key[][32] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+ { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
+ 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
+ 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 },
+};
+
+static const unsigned char aes_test_xts_pt32[][32] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+ { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
+ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 },
+};
+
+static const unsigned char aes_test_xts_ct32[][32] =
+{
+ { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
+ 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
+ 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
+ 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e },
+ { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
+ 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
+ 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
+ 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 },
+ { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,
+ 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,
+ 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,
+ 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 },
+};
+
+static const unsigned char aes_test_xts_data_unit[][16] =
+{
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+};
+
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
/*
* Checkup routine
*/
int mbedtls_aes_self_test( int verbose )
{
- int ret = 0, i, j, u, v;
+ int ret = 0, i, j, u, mode;
+ unsigned int keybits;
unsigned char key[32];
unsigned char buf[64];
+ const unsigned char *aes_tests;
#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)
unsigned char iv[16];
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
unsigned char prv[16];
#endif
-#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB)
+#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \
+ defined(MBEDTLS_CIPHER_MODE_OFB)
size_t offset;
#endif
-#if defined(MBEDTLS_CIPHER_MODE_CTR)
+#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS)
int len;
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
unsigned char nonce_counter[16];
unsigned char stream_block[16];
#endif
@@ -1263,45 +1816,52 @@
for( i = 0; i < 6; i++ )
{
u = i >> 1;
- v = i & 1;
+ keybits = 128 + u * 64;
+ mode = i & 1;
if( verbose != 0 )
- mbedtls_printf( " AES-ECB-%3d (%s): ", 128 + u * 64,
- ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+ mbedtls_printf( " AES-ECB-%3d (%s): ", keybits,
+ ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memset( buf, 0, 16 );
- if( v == MBEDTLS_AES_DECRYPT )
+ if( mode == MBEDTLS_AES_DECRYPT )
{
- mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 );
-
- for( j = 0; j < 10000; j++ )
- mbedtls_aes_crypt_ecb( &ctx, v, buf, buf );
-
- if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- ret = 1;
- goto exit;
- }
+ ret = mbedtls_aes_setkey_dec( &ctx, key, keybits );
+ aes_tests = aes_test_ecb_dec[u];
}
else
{
- mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 );
+ ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
+ aes_tests = aes_test_ecb_enc[u];
+ }
- for( j = 0; j < 10000; j++ )
- mbedtls_aes_crypt_ecb( &ctx, v, buf, buf );
+ /*
+ * AES-192 is an optional feature that may be unavailable when
+ * there is an alternative underlying implementation i.e. when
+ * MBEDTLS_AES_ALT is defined.
+ */
+ if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
+ {
+ mbedtls_printf( "skipped\n" );
+ continue;
+ }
+ else if( ret != 0 )
+ {
+ goto exit;
+ }
- if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- ret = 1;
+ for( j = 0; j < 10000; j++ )
+ {
+ ret = mbedtls_aes_crypt_ecb( &ctx, mode, buf, buf );
+ if( ret != 0 )
goto exit;
- }
+ }
+
+ if( memcmp( buf, aes_tests, 16 ) != 0 )
+ {
+ ret = 1;
+ goto exit;
}
if( verbose != 0 )
@@ -1318,55 +1878,64 @@
for( i = 0; i < 6; i++ )
{
u = i >> 1;
- v = i & 1;
+ keybits = 128 + u * 64;
+ mode = i & 1;
if( verbose != 0 )
- mbedtls_printf( " AES-CBC-%3d (%s): ", 128 + u * 64,
- ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+ mbedtls_printf( " AES-CBC-%3d (%s): ", keybits,
+ ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memset( iv , 0, 16 );
memset( prv, 0, 16 );
memset( buf, 0, 16 );
- if( v == MBEDTLS_AES_DECRYPT )
+ if( mode == MBEDTLS_AES_DECRYPT )
{
- mbedtls_aes_setkey_dec( &ctx, key, 128 + u * 64 );
-
- for( j = 0; j < 10000; j++ )
- mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
-
- if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- ret = 1;
- goto exit;
- }
+ ret = mbedtls_aes_setkey_dec( &ctx, key, keybits );
+ aes_tests = aes_test_cbc_dec[u];
}
else
{
- mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 );
+ ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
+ aes_tests = aes_test_cbc_enc[u];
+ }
- for( j = 0; j < 10000; j++ )
+ /*
+ * AES-192 is an optional feature that may be unavailable when
+ * there is an alternative underlying implementation i.e. when
+ * MBEDTLS_AES_ALT is defined.
+ */
+ if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
+ {
+ mbedtls_printf( "skipped\n" );
+ continue;
+ }
+ else if( ret != 0 )
+ {
+ goto exit;
+ }
+
+ for( j = 0; j < 10000; j++ )
+ {
+ if( mode == MBEDTLS_AES_ENCRYPT )
{
unsigned char tmp[16];
- mbedtls_aes_crypt_cbc( &ctx, v, 16, iv, buf, buf );
-
memcpy( tmp, prv, 16 );
memcpy( prv, buf, 16 );
memcpy( buf, tmp, 16 );
}
- if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- ret = 1;
+ ret = mbedtls_aes_crypt_cbc( &ctx, mode, 16, iv, buf, buf );
+ if( ret != 0 )
goto exit;
- }
+
+ }
+
+ if( memcmp( buf, aes_tests, 16 ) != 0 )
+ {
+ ret = 1;
+ goto exit;
}
if( verbose != 0 )
@@ -1384,45 +1953,52 @@
for( i = 0; i < 6; i++ )
{
u = i >> 1;
- v = i & 1;
+ keybits = 128 + u * 64;
+ mode = i & 1;
if( verbose != 0 )
- mbedtls_printf( " AES-CFB128-%3d (%s): ", 128 + u * 64,
- ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+ mbedtls_printf( " AES-CFB128-%3d (%s): ", keybits,
+ ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memcpy( iv, aes_test_cfb128_iv, 16 );
- memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 );
+ memcpy( key, aes_test_cfb128_key[u], keybits / 8 );
offset = 0;
- mbedtls_aes_setkey_enc( &ctx, key, 128 + u * 64 );
+ ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
+ /*
+ * AES-192 is an optional feature that may be unavailable when
+ * there is an alternative underlying implementation i.e. when
+ * MBEDTLS_AES_ALT is defined.
+ */
+ if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
+ {
+ mbedtls_printf( "skipped\n" );
+ continue;
+ }
+ else if( ret != 0 )
+ {
+ goto exit;
+ }
- if( v == MBEDTLS_AES_DECRYPT )
+ if( mode == MBEDTLS_AES_DECRYPT )
{
memcpy( buf, aes_test_cfb128_ct[u], 64 );
- mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
-
- if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- ret = 1;
- goto exit;
- }
+ aes_tests = aes_test_cfb128_pt;
}
else
{
memcpy( buf, aes_test_cfb128_pt, 64 );
- mbedtls_aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf );
+ aes_tests = aes_test_cfb128_ct[u];
+ }
- if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
+ ret = mbedtls_aes_crypt_cfb128( &ctx, mode, 64, &offset, iv, buf, buf );
+ if( ret != 0 )
+ goto exit;
- ret = 1;
- goto exit;
- }
+ if( memcmp( buf, aes_tests, 64 ) != 0 )
+ {
+ ret = 1;
+ goto exit;
}
if( verbose != 0 )
@@ -1433,6 +2009,69 @@
mbedtls_printf( "\n" );
#endif /* MBEDTLS_CIPHER_MODE_CFB */
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+ /*
+ * OFB mode
+ */
+ for( i = 0; i < 6; i++ )
+ {
+ u = i >> 1;
+ keybits = 128 + u * 64;
+ mode = i & 1;
+
+ if( verbose != 0 )
+ mbedtls_printf( " AES-OFB-%3d (%s): ", keybits,
+ ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+ memcpy( iv, aes_test_ofb_iv, 16 );
+ memcpy( key, aes_test_ofb_key[u], keybits / 8 );
+
+ offset = 0;
+ ret = mbedtls_aes_setkey_enc( &ctx, key, keybits );
+ /*
+ * AES-192 is an optional feature that may be unavailable when
+ * there is an alternative underlying implementation i.e. when
+ * MBEDTLS_AES_ALT is defined.
+ */
+ if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 )
+ {
+ mbedtls_printf( "skipped\n" );
+ continue;
+ }
+ else if( ret != 0 )
+ {
+ goto exit;
+ }
+
+ if( mode == MBEDTLS_AES_DECRYPT )
+ {
+ memcpy( buf, aes_test_ofb_ct[u], 64 );
+ aes_tests = aes_test_ofb_pt;
+ }
+ else
+ {
+ memcpy( buf, aes_test_ofb_pt, 64 );
+ aes_tests = aes_test_ofb_ct[u];
+ }
+
+ ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf );
+ if( ret != 0 )
+ goto exit;
+
+ if( memcmp( buf, aes_tests, 64 ) != 0 )
+ {
+ ret = 1;
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( "\n" );
+#endif /* MBEDTLS_CIPHER_MODE_OFB */
+
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/*
* CTR mode
@@ -1440,51 +2079,41 @@
for( i = 0; i < 6; i++ )
{
u = i >> 1;
- v = i & 1;
+ mode = i & 1;
if( verbose != 0 )
mbedtls_printf( " AES-CTR-128 (%s): ",
- ( v == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+ ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 );
memcpy( key, aes_test_ctr_key[u], 16 );
offset = 0;
- mbedtls_aes_setkey_enc( &ctx, key, 128 );
+ if( ( ret = mbedtls_aes_setkey_enc( &ctx, key, 128 ) ) != 0 )
+ goto exit;
- if( v == MBEDTLS_AES_DECRYPT )
+ len = aes_test_ctr_len[u];
+
+ if( mode == MBEDTLS_AES_DECRYPT )
{
- len = aes_test_ctr_len[u];
memcpy( buf, aes_test_ctr_ct[u], len );
-
- mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
- buf, buf );
-
- if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- ret = 1;
- goto exit;
- }
+ aes_tests = aes_test_ctr_pt[u];
}
else
{
- len = aes_test_ctr_len[u];
memcpy( buf, aes_test_ctr_pt[u], len );
+ aes_tests = aes_test_ctr_ct[u];
+ }
- mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block,
- buf, buf );
+ ret = mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter,
+ stream_block, buf, buf );
+ if( ret != 0 )
+ goto exit;
- if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 )
- {
- if( verbose != 0 )
- mbedtls_printf( "failed\n" );
-
- ret = 1;
- goto exit;
- }
+ if( memcmp( buf, aes_tests, len ) != 0 )
+ {
+ ret = 1;
+ goto exit;
}
if( verbose != 0 )
@@ -1495,9 +2124,79 @@
mbedtls_printf( "\n" );
#endif /* MBEDTLS_CIPHER_MODE_CTR */
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+ {
+ static const int num_tests =
+ sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key);
+ mbedtls_aes_xts_context ctx_xts;
+
+ /*
+ * XTS mode
+ */
+ mbedtls_aes_xts_init( &ctx_xts );
+
+ for( i = 0; i < num_tests << 1; i++ )
+ {
+ const unsigned char *data_unit;
+ u = i >> 1;
+ mode = i & 1;
+
+ if( verbose != 0 )
+ mbedtls_printf( " AES-XTS-128 (%s): ",
+ ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" );
+
+ memset( key, 0, sizeof( key ) );
+ memcpy( key, aes_test_xts_key[u], 32 );
+ data_unit = aes_test_xts_data_unit[u];
+
+ len = sizeof( *aes_test_xts_ct32 );
+
+ if( mode == MBEDTLS_AES_DECRYPT )
+ {
+ ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 );
+ if( ret != 0)
+ goto exit;
+ memcpy( buf, aes_test_xts_ct32[u], len );
+ aes_tests = aes_test_xts_pt32[u];
+ }
+ else
+ {
+ ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 );
+ if( ret != 0)
+ goto exit;
+ memcpy( buf, aes_test_xts_pt32[u], len );
+ aes_tests = aes_test_xts_ct32[u];
+ }
+
+
+ ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit,
+ buf, buf );
+ if( ret != 0 )
+ goto exit;
+
+ if( memcmp( buf, aes_tests, len ) != 0 )
+ {
+ ret = 1;
+ goto exit;
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( "passed\n" );
+ }
+
+ if( verbose != 0 )
+ mbedtls_printf( "\n" );
+
+ mbedtls_aes_xts_free( &ctx_xts );
+ }
+#endif /* MBEDTLS_CIPHER_MODE_XTS */
+
ret = 0;
exit:
+ if( ret != 0 && verbose != 0 )
+ mbedtls_printf( "failed\n" );
+
mbedtls_aes_free( &ctx );
return( ret );