Merge pull request #3553 from AndrzejKurek/crc-calculation-base

Validate AES keys after each use checking CRC 
diff --git a/configs/baremetal.h b/configs/baremetal.h
index c93f53a..71bf463 100644
--- a/configs/baremetal.h
+++ b/configs/baremetal.h
@@ -137,6 +137,8 @@
 
 #define MBEDTLS_OID_C
 #define MBEDTLS_PLATFORM_C
+#define MBEDTLS_CRC_C
+#define MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY
 
 /* I/O buffer configuration */
 #define MBEDTLS_SSL_MAX_CONTENT_LEN             2048
diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h
index cb7d726..5fb020f 100644
--- a/include/mbedtls/aes.h
+++ b/include/mbedtls/aes.h
@@ -90,6 +90,9 @@
 #if defined(MBEDTLS_AES_SCA_COUNTERMEASURES)
     uint32_t frk[8];            /*!< Fake AES round keys. */
 #endif
+#if defined(MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY)
+    uint16_t crc;               /*!< CRC-16 of the set key */
+#endif
 #if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) && !defined(MBEDTLS_PADLOCK_C)
     uint32_t buf[44];           /*!< Unaligned data buffer */
 #else /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 7239557..974bf7b 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -986,6 +986,10 @@
 #error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously"
 #endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */
 
+#if defined(MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY) && ( !defined(MBEDTLS_CRC_C) )
+#error "MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY defined, but not MBEDTLS_CRC_C"
+#endif
+
 /*
  * Avoid warning from -pedantic. This is a convenient place for this
  * workaround since this is included by every single file before the
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 9b88597..db38e81 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -2729,6 +2729,29 @@
 #define MBEDTLS_ERROR_C
 
 /**
+ * \def MBEDTLS_CRC_C
+ *
+ * Enable the CRC calculating module
+ *
+ * Module:  library/crc.c
+ *
+ * This module enables mbedtls_crc_update().
+ */
+//#define MBEDTLS_CRC_C
+
+/**
+ * \def MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY
+ *
+ * Enable validation of AES keys by checking their CRC
+ * during every encryption/decryption.
+ *
+ * Module:  library/aes.c
+ *
+ * Requires: MBEDTLS_CRC_C
+ */
+//#define MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY
+
+/**
  * \def MBEDTLS_GCM_C
  *
  * Enable the Galois/Counter Mode (GCM) for AES.
diff --git a/include/mbedtls/crc.h b/include/mbedtls/crc.h
new file mode 100644
index 0000000..0131666
--- /dev/null
+++ b/include/mbedtls/crc.h
@@ -0,0 +1,47 @@
+/*
+ *  CRC-16/ARC implementation, generated using pycrc v0.9.2, https://pycrc.org.
+ *
+ *  Used options: --model=crc-16 --algorithm=tbl --generate=h --std=C89 --table-idx-width 4
+ *
+ *  Copyright (C) 2006-2020, 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.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#ifndef MBEDTLS_CRC_H
+#define MBEDTLS_CRC_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Update the crc value with new data.
+ *
+ * \param[in] crc      The current crc value.
+ * \param[in] data     Pointer to a buffer of \a data_len bytes.
+ * \param[in] data_len Number of bytes in the \a data buffer.
+ * \return             The updated crc value.
+ */
+uint16_t mbedtls_crc_update( uint16_t crc, const void *data, size_t data_len );
+
+#ifdef __cplusplus
+}
+#endif
+#endif      /* MBEDTLS_CRC_H */
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index b59d318..9e0724f 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -20,6 +20,7 @@
     cipher.c
     cipher_wrap.c
     cmac.c
+    crc.c
     ctr_drbg.c
     des.c
     dhm.c
diff --git a/library/Makefile b/library/Makefile
index 96a9d60..7e16bd8 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -83,9 +83,9 @@
 		base64.o	bignum.o	blowfish.o	\
 		camellia.o	ccm.o		chacha20.o	\
 		chachapoly.o	cipher.o	cipher_wrap.o	\
-		cmac.o		ctr_drbg.o	des.o		\
-		dhm.o		ecdh.o		ecdsa.o		\
-		ecjpake.o	ecp.o				\
+		cmac.o		crc.o		ctr_drbg.o	\
+		des.o		dhm.o		ecdh.o		\
+		ecdsa.o		ecjpake.o	ecp.o		\
 		ecp_curves.o	entropy.o	entropy_poll.o	\
 		error.o		gcm.o		havege.o	\
 		hkdf.o						\
@@ -101,6 +101,7 @@
 		threading.o	timing.o	version.o	\
 		version_features.o		xtea.o
 
+
 OBJS_X509=	certs.o		pkcs11.o	x509.o
 
 OBJS_TLS=	debug.o		net_sockets.o		\
diff --git a/library/aes.c b/library/aes.c
index e7a888f..d6a6b00 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -45,6 +45,10 @@
 #include "mbedtls/aesni.h"
 #endif
 
+#if defined(MBEDTLS_CRC_C) && defined(MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY)
+#include "mbedtls/crc.h"
+#endif
+
 #if defined(MBEDTLS_SELF_TEST)
 #if defined(MBEDTLS_PLATFORM_C)
 #include "mbedtls/platform.h"
@@ -703,6 +707,7 @@
 
     AES_VALIDATE_RET( ctx != NULL );
     AES_VALIDATE_RET( key != NULL );
+    (void) ret;
 
     switch( keybits )
     {
@@ -821,8 +826,6 @@
 #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
     }
 
-    ret = 0;
-
     /* Validate execution path */
     if( ( flow_ctrl == keybits >> 5 ) && ( ( ctx->nr == 10 && i == 10 )
 #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
@@ -831,7 +834,10 @@
 #endif
     ) )
     {
-        return ret;
+#if defined(MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY)
+        ctx->crc = mbedtls_crc_update( 0, ctx->rk, keybits >> 3 );
+#endif
+        return 0;
     }
 
     mbedtls_platform_memset( RK, 0, ( keybits >> 5 ) * 4 );
@@ -926,6 +932,9 @@
     }
     else if( ( i == 0 ) && ( j == 4 ) )
     {
+#if defined(MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY)
+        ctx->crc = mbedtls_crc_update( 0, ctx->rk, keybits >> 3 );
+#endif
         return( ret );
     }
     else
@@ -1088,6 +1097,21 @@
     // reserve based on max rounds + dummy rounds + 2 (for initial key addition)
     uint8_t round_ctrl_table[( 14 + AES_SCA_CM_ROUNDS + 2 )];
 
+#if defined(MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY)
+    unsigned key_bytes = 0;
+    uint16_t check_crc = 0;
+    switch( ctx->nr )
+    {
+        case 10: key_bytes = 16; break;
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
+        case 12: key_bytes = 24; break;
+        case 14: key_bytes = 32; break;
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
+        default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
+    }
+    check_crc = mbedtls_crc_update( 0, ctx->rk, key_bytes );
+#endif
+
     aes_data_real.rk_ptr = ctx->rk;
     aes_data_fake.rk_ptr = ctx->frk;
 
@@ -1182,9 +1206,20 @@
         flow_control++;
     } while( ( i = ( i + 1 ) % 4 ) != offset );
 
-    if( flow_control == tindex + dummy_rounds + 8 )
+    /* Double negation is used to silence an "extraneous parentheses" warning */
+    if( ! ( flow_control != tindex + dummy_rounds + 8 )
+#if defined(MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY)
+         && check_crc == ctx->crc
+#endif
+      )
     {
-        return 0;
+#if defined(MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY)
+        mbedtls_platform_random_delay();
+        if( mbedtls_crc_update( 0, ctx->rk, key_bytes ) == ctx->crc )
+#endif
+        {
+            return 0;
+        }
     }
 
     // Clear the output in case of a FI
@@ -1369,6 +1404,21 @@
     // reserve based on max rounds + dummy rounds + 2 (for initial key addition)
     uint8_t round_ctrl_table[( 14 + AES_SCA_CM_ROUNDS + 2 )];
 
+#if defined(MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY)
+    unsigned key_bytes = 0;
+    uint16_t check_crc = 0;
+    switch( ctx->nr )
+    {
+        case 10: key_bytes = 16; break;
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
+        case 12: key_bytes = 24; break;
+        case 14: key_bytes = 32; break;
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
+        default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
+    }
+    check_crc = mbedtls_crc_update( 0, ctx->rk, key_bytes );
+#endif
+
     aes_data_real.rk_ptr = ctx->rk;
     aes_data_fake.rk_ptr = ctx->frk;
 
@@ -1463,9 +1513,20 @@
         flow_control++;
     } while( ( i = ( i + 1 ) % 4 ) != offset );
 
-    if( flow_control == tindex + dummy_rounds + 8 )
+    /* Double negation is used to silence an "extraneous parentheses" warning */
+    if( ! ( flow_control != tindex + dummy_rounds + 8 )
+#if defined(MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY)
+         && check_crc == ctx->crc
+#endif
+      )
     {
-        return 0;
+#if defined(MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY)
+        mbedtls_platform_random_delay();
+        if( mbedtls_crc_update( 0, ctx->rk, key_bytes ) == ctx->crc )
+#endif
+        {
+            return 0;
+        }
     }
 
     // Clear the output in case of a FI
diff --git a/library/crc.c b/library/crc.c
new file mode 100644
index 0000000..9e21f25
--- /dev/null
+++ b/library/crc.c
@@ -0,0 +1,55 @@
+/*
+ *  CRC-16/ARC implementation, generated using pycrc v0.9.2, https://pycrc.org,
+ *  with further FI countermeasures added manually.
+ *
+ *  Used options: --model=crc-16 --algorithm=tbl --generate=c --std=C89 --table-idx-width 4
+ *
+ *  Copyright (C) 2006-2020, 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.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+#if !defined(MBEDTLS_CONFIG_FILE)
+#include "mbedtls/config.h"
+#else
+#include MBEDTLS_CONFIG_FILE
+#endif
+
+#if defined(MBEDTLS_CRC_C)
+
+#include "mbedtls/crc.h"
+
+static const uint32_t crc_table[16] = {
+    0x0000, 0xcc01, 0xd801, 0x1400, 0xf001, 0x3c00, 0x2800, 0xe401,
+    0xa001, 0x6c00, 0x7800, 0xb401, 0x5000, 0x9c01, 0x8801, 0x4400
+};
+
+uint16_t mbedtls_crc_update( uint16_t crc, const void *data, size_t data_len )
+{
+    const unsigned char *d = (const unsigned char *)data;
+    unsigned int tbl_idx;
+
+    while ( data_len -- ) {
+        tbl_idx = crc ^ *d;
+        crc = crc_table[tbl_idx & 0x0f] ^ ( crc >> 4 );
+        tbl_idx = crc ^ ( *d >> 4 );
+        crc = crc_table[tbl_idx & 0x0f] ^ ( crc >> 4 );
+        d ++;
+    }
+    return crc;
+}
+
+#endif /* MBEDTLS_CRC_C */
diff --git a/library/version_features.c b/library/version_features.c
index 38a7cee..84cb8a6 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -684,6 +684,12 @@
 #if defined(MBEDTLS_ERROR_C)
     "MBEDTLS_ERROR_C",
 #endif /* MBEDTLS_ERROR_C */
+#if defined(MBEDTLS_CRC_C)
+    "MBEDTLS_CRC_C",
+#endif /* MBEDTLS_CRC_C */
+#if defined(MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY)
+    "MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY",
+#endif /* MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY */
 #if defined(MBEDTLS_GCM_C)
     "MBEDTLS_GCM_C",
 #endif /* MBEDTLS_GCM_C */
diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c
index 8db6d22..af77ed5 100644
--- a/programs/ssl/query_config.c
+++ b/programs/ssl/query_config.c
@@ -1866,6 +1866,22 @@
     }
 #endif /* MBEDTLS_ERROR_C */
 
+#if defined(MBEDTLS_CRC_C)
+    if( strcmp( "MBEDTLS_CRC_C", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_CRC_C );
+        return( 0 );
+    }
+#endif /* MBEDTLS_CRC_C */
+
+#if defined(MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY)
+    if( strcmp( "MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY );
+        return( 0 );
+    }
+#endif /* MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY */
+
 #if defined(MBEDTLS_GCM_C)
     if( strcmp( "MBEDTLS_GCM_C", config ) == 0 )
     {
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 2ea77e7..1a00ca0 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -67,6 +67,7 @@
 endif(MSVC)
 
 add_test_suite(aes aes.ecb)
+add_test_suite(aes aes.ecb.crc)
 add_test_suite(aes aes.cbc)
 add_test_suite(aes aes.cfb)
 add_test_suite(aes aes.ofb)
@@ -94,6 +95,7 @@
 add_test_suite(cipher cipher.null)
 add_test_suite(cipher cipher.padding)
 add_test_suite(cmac)
+add_test_suite(crc)
 add_test_suite(ctr_drbg)
 add_test_suite(debug)
 add_test_suite(des)
diff --git a/tests/suites/test_suite_aes.ecb.crc.data b/tests/suites/test_suite_aes.ecb.crc.data
new file mode 100644
index 0000000..cd42620
--- /dev/null
+++ b/tests/suites/test_suite_aes.ecb.crc.data
@@ -0,0 +1,46 @@
+AES-128-ECB Encrypt NIST KAT #1 good CRC
+aes_encrypt_ecb_crc:"00000000000000000000000000000000":"f34481ec3cc627bacd5dc3fb08f273e6":"0336763e966d92595a567cc9ce537f5e":0:0:1
+
+AES-128-ECB Encrypt NIST KAT #1 bad CRC
+aes_encrypt_ecb_crc:"00000000000000000000000000000000":"f34481ec3cc627bacd5dc3fb08f273e6":"00000000000000000000000000000000":42:MBEDTLS_ERR_PLATFORM_FAULT_DETECTED:0
+
+AES-128-ECB Decrypt NIST KAT #1 good CRC
+depends_on:!MBEDTLS_AES_ONLY_ENCRYPT
+aes_decrypt_ecb_crc:"00000000000000000000000000000000":"db4f1aa530967d6732ce4715eb0ee24b":"ff000000000000000000000000000000":614:0:1
+
+AES-128-ECB Decrypt NIST KAT #1 bad CRC
+depends_on:!MBEDTLS_AES_ONLY_ENCRYPT
+aes_decrypt_ecb_crc:"00000000000000000000000000000000":"db4f1aa530967d6732ce4715eb0ee24b":"00000000000000000000000000000000":42:MBEDTLS_ERR_PLATFORM_FAULT_DETECTED:0
+
+AES-192-ECB Encrypt NIST KAT #1 good CRC
+depends_on:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
+aes_encrypt_ecb_crc:"000000000000000000000000000000000000000000000000":"fffffffffffffffffffff80000000000":"156f07767a85a4312321f63968338a01":0:0:1
+
+AES-192-ECB Encrypt NIST KAT #1 bad CRC
+depends_on:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
+aes_encrypt_ecb_crc:"000000000000000000000000000000000000000000000000":"fffffffffffffffffffff80000000000":"00000000000000000000000000000000":42:MBEDTLS_ERR_PLATFORM_FAULT_DETECTED:0
+
+AES-192-ECB Decrypt NIST KAT #1 good CRC
+depends_on:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:!MBEDTLS_AES_ONLY_ENCRYPT
+aes_decrypt_ecb_crc:"fffffffffffffffffffffffffffffffff000000000000000":"bb2852c891c5947d2ed44032c421b85f":"00000000000000000000000000000000":31004:0:1
+
+AES-192-ECB Decrypt NIST KAT #1 bad CRC
+depends_on:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:!MBEDTLS_AES_ONLY_ENCRYPT
+aes_decrypt_ecb_crc:"fffffffffffffffffffffffffffffffff000000000000000":"bb2852c891c5947d2ed44032c421b85f":"00000000000000000000000000000000":42:MBEDTLS_ERR_PLATFORM_FAULT_DETECTED:0
+
+AES-256-ECB Encrypt NIST KAT #1 good CRC
+depends_on:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
+aes_encrypt_ecb_crc:"c1cc358b449909a19436cfbb3f852ef8bcb5ed12ac7058325f56e6099aab1a1c":"00000000000000000000000000000000":"352065272169abf9856843927d0674fd":61384:0:1
+
+AES-256-ECB Encrypt NIST KAT #1 bad CRC
+depends_on:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
+aes_encrypt_ecb_crc:"c1cc358b449909a19436cfbb3f852ef8bcb5ed12ac7058325f56e6099aab1a1c":"00000000000000000000000000000000":"00000000000000000000000000000000":42:MBEDTLS_ERR_PLATFORM_FAULT_DETECTED:0
+
+AES-256-ECB Decrypt NIST KAT #1 good CRC
+depends_on:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:!MBEDTLS_AES_ONLY_ENCRYPT
+aes_decrypt_ecb_crc:"fffffffffffffffffffffffffffffffffffffffffffffff00000000000000000":"edf61ae362e882ddc0167474a7a77f3a":"00000000000000000000000000000000":32504:0:1
+
+AES-256-ECB Decrypt NIST KAT #1 bad CRC
+depends_on:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:!MBEDTLS_AES_ONLY_ENCRYPT
+aes_decrypt_ecb_crc:"fffffffffffffffffffffffffffffffffffffffffffffff00000000000000000":"edf61ae362e882ddc0167474a7a77f3a":"00000000000000000000000000000000":42:MBEDTLS_ERR_PLATFORM_FAULT_DETECTED:0
+
diff --git a/tests/suites/test_suite_aes.function b/tests/suites/test_suite_aes.function
index da8c1e9..2a2f9cb 100644
--- a/tests/suites/test_suite_aes.function
+++ b/tests/suites/test_suite_aes.function
@@ -1,5 +1,6 @@
 /* BEGIN_HEADER */
 #include "mbedtls/aes.h"
+#include "mbedtls/platform.h"
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -369,6 +370,60 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY:MBEDTLS_AES_SCA_COUNTERMEASURES:!MBEDTLS_AES_SETKEY_ENC_ALT:!MBEDTLS_AESNI_C */
+void aes_encrypt_ecb_crc( data_t * key_str, data_t * src_str,
+                          data_t * hex_dst_string, unsigned int crc, int crypt_result, int check_crc )
+{
+    unsigned char output[100];
+    mbedtls_aes_context ctx;
+
+    memset(output, 0x00, 100);
+
+    mbedtls_aes_init( &ctx );
+
+    TEST_ASSERT( mbedtls_aes_setkey_enc( &ctx, key_str->x, key_str->len * 8 ) == 0 );
+
+    if( check_crc )
+        TEST_ASSERT( ctx.crc == crc );
+    else
+        ctx.crc = crc;
+
+    TEST_ASSERT( mbedtls_aes_crypt_ecb( &ctx, MBEDTLS_AES_ENCRYPT, src_str->x, output ) == crypt_result );
+
+    TEST_ASSERT( hexcmp( output, hex_dst_string->x, 16, hex_dst_string->len ) == 0 );
+
+exit:
+    mbedtls_aes_free( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY:MBEDTLS_AES_SCA_COUNTERMEASURES:!MBEDTLS_AES_SETKEY_ENC_ALT:!MBEDTLS_AESNI_C */
+void aes_decrypt_ecb_crc( data_t * key_str, data_t * src_str,
+                          data_t * hex_dst_string, unsigned int crc, int crypt_result, int check_crc )
+{
+    unsigned char output[100];
+    mbedtls_aes_context ctx;
+
+    memset(output, 0x00, 100);
+
+    mbedtls_aes_init( &ctx );
+
+    TEST_ASSERT( mbedtls_aes_setkey_dec( &ctx, key_str->x, key_str->len * 8 ) == 0 );
+
+    if( check_crc )
+        TEST_ASSERT( ctx.crc == crc );
+    else
+        ctx.crc = crc;
+
+    TEST_ASSERT( mbedtls_aes_crypt_ecb( &ctx, MBEDTLS_AES_DECRYPT, src_str->x, output ) == crypt_result );
+
+    TEST_ASSERT( hexcmp( output, hex_dst_string->x, 16, hex_dst_string->len ) == 0 );
+
+exit:
+    mbedtls_aes_free( &ctx );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:MBEDTLS_CHECK_PARAMS:!MBEDTLS_PARAM_FAILED_ALT */
 void aes_check_params( )
 {
diff --git a/tests/suites/test_suite_crc.data b/tests/suites/test_suite_crc.data
new file mode 100644
index 0000000..aa4c686
--- /dev/null
+++ b/tests/suites/test_suite_crc.data
@@ -0,0 +1,44 @@
+CRC-16 1 byte of 0x00
+compute_crc:"00":0
+
+CRC-16 8 bytes of 0x00
+compute_crc:"0000000000000000":0
+
+CRC-16 16 bytes of 0x00
+compute_crc:"00000000000000000000000000000000":0
+
+CRC-16 32 bytes of 0x00
+compute_crc:"0000000000000000000000000000000000000000000000000000000000000000":0
+
+CRC-16 1 byte of 0xFF
+compute_crc:"FF":16448
+
+CRC-16 8 bytes of 0xFF
+compute_crc:"FFFFFFFFFFFFFFFF":33857
+
+CRC-16 16 bytes of 0xFF
+compute_crc:"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF":28736
+
+CRC-16 32 bytes of 0xFF
+compute_crc:"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF":41985
+
+CRC-16 1 byte of 0x01
+compute_crc:"01":49345
+
+CRC-16 8 bytes incrementing
+compute_crc:"0123456789abcdef":62374
+
+CRC-16 16 bytes incrementing
+compute_crc:"0123456789abcdef0123456789abcdef":44783
+
+CRC-16 32 bytes incrementing
+compute_crc:"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef":44749
+
+CRC-16 64 bytes incrementing
+compute_crc:"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef":53063
+
+CRC-16 ascii 1 to 9 incrementing
+compute_crc:"313233343536373839":47933
+
+CRC-16 512 bytes of random data
+compute_crc:"66870a93e17d4a5dd6ef84476dff6e2aa7d2ebd391cf4c54affff479a98a81360909f32eafbea98f4a3e4737de4c588d11c356860333ad7f4c334fb7dfce77cb04fafb50991f9b2e7957312a1b9dbcbebaf03f4eb9443938279f9b6c01e2b8c6022ee58f5840c7e86962830ca088174dc1b9912b64bde42877343c0b979b8ea376e4bf994a7ff6c629d5ba936958cc9f55db1c98151b16f7d918ff84f85b45e3ee49e7d166baac4dec81a174b3e496446a92c00d0859c2402f0110964effbdae9a6a3243530996029f4a428f1626837e55d32660cf6a2d4263c9fe23841d01b9410a9530bf9b1561fa83f6c42447d310bc991352ee9863b83b890b5aa0ea0bbf":49505
diff --git a/tests/suites/test_suite_crc.function b/tests/suites/test_suite_crc.function
new file mode 100644
index 0000000..8d09958
--- /dev/null
+++ b/tests/suites/test_suite_crc.function
@@ -0,0 +1,26 @@
+/* BEGIN_HEADER */
+#include "mbedtls/crc.h"
+/* END_HEADER */
+
+/* BEGIN_DEPENDENCIES
+ * depends_on:MBEDTLS_CRC_C
+ * END_DEPENDENCIES
+ */
+
+/* BEGIN_CASE */
+void compute_crc( data_t *input, unsigned int crc )
+{
+    uint16_t result = mbedtls_crc_update( 0, input->x, input->len );
+    uint32_t len = input->len;
+    TEST_ASSERT( crc == result );
+
+    result = 0;
+    while( len > 0 )
+    {
+        uint8_t cur_len = ( len > 8 ? 8 : len );
+        result = mbedtls_crc_update( result, &input->x[ input->len - len ], cur_len );
+        len -= cur_len;
+    }
+    TEST_ASSERT( crc == result );
+}
+/* END_CASE */
diff --git a/visualc/VS2010/mbedTLS.vcxproj b/visualc/VS2010/mbedTLS.vcxproj
index 0e57881..4139879 100644
--- a/visualc/VS2010/mbedTLS.vcxproj
+++ b/visualc/VS2010/mbedTLS.vcxproj
@@ -166,6 +166,7 @@
     <ClInclude Include="..\..\include\mbedtls\cmac.h" />

     <ClInclude Include="..\..\include\mbedtls\compat-1.3.h" />

     <ClInclude Include="..\..\include\mbedtls\config.h" />

+    <ClInclude Include="..\..\include\mbedtls\crc.h" />

     <ClInclude Include="..\..\include\mbedtls\ctr_drbg.h" />

     <ClInclude Include="..\..\include\mbedtls\debug.h" />

     <ClInclude Include="..\..\include\mbedtls\des.h" />

@@ -243,6 +244,7 @@
     <ClCompile Include="..\..\library\cipher.c" />

     <ClCompile Include="..\..\library\cipher_wrap.c" />

     <ClCompile Include="..\..\library\cmac.c" />

+    <ClCompile Include="..\..\library\crc.c" />

     <ClCompile Include="..\..\library\ctr_drbg.c" />

     <ClCompile Include="..\..\library\debug.c" />

     <ClCompile Include="..\..\library\des.c" />