Merge pull request #240 from Ko-/development

Enable 64-bit bignum limbs and add optimized multiplication for Aarch64
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 95ab1f2..3c1430c 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -1007,6 +1007,16 @@
 //#define MBEDTLS_SHA256_SMALLER
 
 /**
+ * \def MBEDTLS_SHA512_SMALLER
+ *
+ * Enable an implementation of SHA-512 that has lower ROM footprint but also
+ * lower performance.
+ *
+ * Uncomment to enable the smaller implementation of SHA512.
+ */
+//#define MBEDTLS_SHA512_SMALLER
+
+/**
  * \def MBEDTLS_THREADING_ALT
  *
  * Provide your own alternate threading implementation.
diff --git a/library/bignum.c b/library/bignum.c
index 30757df..5f5df78 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -2426,7 +2426,8 @@
             }
 
             if (count++ > 30) {
-                return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
+                ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
+                goto cleanup;
             }
 
         } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ||
diff --git a/library/sha512.c b/library/sha512.c
index bdd20b2..2e2b797 100644
--- a/library/sha512.c
+++ b/library/sha512.c
@@ -92,6 +92,15 @@
 }
 #endif /* PUT_UINT64_BE */
 
+#if defined(MBEDTLS_SHA512_SMALLER)
+static void sha512_put_uint64_be( uint64_t n, unsigned char *b, uint8_t i )
+{
+    PUT_UINT64_BE(n, b, i);
+}
+#else
+#define sha512_put_uint64_be    PUT_UINT64_BE
+#endif /* MBEDTLS_SHA512_SMALLER */
+
 void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
 {
     SHA512_VALIDATE( ctx != NULL );
@@ -219,7 +228,7 @@
 {
     int i;
     uint64_t temp1, temp2, W[80];
-    uint64_t A, B, C, D, E, F, G, H;
+    uint64_t A[8];
 
     SHA512_VALIDATE_RET( ctx != NULL );
     SHA512_VALIDATE_RET( (const unsigned char *)data != NULL );
@@ -244,6 +253,28 @@
         (d) += temp1; (h) = temp1 + temp2;                      \
     } while( 0 )
 
+    for( i = 0; i < 8; i++ )
+        A[i] = ctx->state[i];
+
+#if defined(MBEDTLS_SHA512_SMALLER)
+    for( i = 0; i < 80; i++ )
+    {
+        if( i < 16 )
+        {
+            GET_UINT64_BE( W[i], data, i << 3 );
+        }
+        else
+        {
+            W[i] = S1(W[i -  2]) + W[i -  7] +
+                   S0(W[i - 15]) + W[i - 16];
+        }
+
+        P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] );
+
+        temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3];
+        A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1;
+    }
+#else /* MBEDTLS_SHA512_SMALLER */
     for( i = 0; i < 16; i++ )
     {
         GET_UINT64_BE( W[i], data, i << 3 );
@@ -255,37 +286,23 @@
                S0(W[i - 15]) + W[i - 16];
     }
 
-    A = ctx->state[0];
-    B = ctx->state[1];
-    C = ctx->state[2];
-    D = ctx->state[3];
-    E = ctx->state[4];
-    F = ctx->state[5];
-    G = ctx->state[6];
-    H = ctx->state[7];
     i = 0;
-
     do
     {
-        P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
-        P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
-        P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
-        P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
-        P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
-        P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
-        P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
-        P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
+        P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); i++;
+        P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i], K[i] ); i++;
+        P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i], K[i] ); i++;
+        P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i], K[i] ); i++;
+        P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i], K[i] ); i++;
+        P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i], K[i] ); i++;
+        P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i], K[i] ); i++;
+        P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i], K[i] ); i++;
     }
     while( i < 80 );
+#endif /* MBEDTLS_SHA512_SMALLER */
 
-    ctx->state[0] += A;
-    ctx->state[1] += B;
-    ctx->state[2] += C;
-    ctx->state[3] += D;
-    ctx->state[4] += E;
-    ctx->state[5] += F;
-    ctx->state[6] += G;
-    ctx->state[7] += H;
+    for( i = 0; i < 8; i++ )
+        ctx->state[i] += A[i];
 
     return( 0 );
 }
@@ -403,8 +420,8 @@
          | ( ctx->total[1] <<  3 );
     low  = ( ctx->total[0] <<  3 );
 
-    PUT_UINT64_BE( high, ctx->buffer, 112 );
-    PUT_UINT64_BE( low,  ctx->buffer, 120 );
+    sha512_put_uint64_be( high, ctx->buffer, 112 );
+    sha512_put_uint64_be( low,  ctx->buffer, 120 );
 
     if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
         return( ret );
@@ -412,17 +429,17 @@
     /*
      * Output final state
      */
-    PUT_UINT64_BE( ctx->state[0], output,  0 );
-    PUT_UINT64_BE( ctx->state[1], output,  8 );
-    PUT_UINT64_BE( ctx->state[2], output, 16 );
-    PUT_UINT64_BE( ctx->state[3], output, 24 );
-    PUT_UINT64_BE( ctx->state[4], output, 32 );
-    PUT_UINT64_BE( ctx->state[5], output, 40 );
+    sha512_put_uint64_be( ctx->state[0], output,  0 );
+    sha512_put_uint64_be( ctx->state[1], output,  8 );
+    sha512_put_uint64_be( ctx->state[2], output, 16 );
+    sha512_put_uint64_be( ctx->state[3], output, 24 );
+    sha512_put_uint64_be( ctx->state[4], output, 32 );
+    sha512_put_uint64_be( ctx->state[5], output, 40 );
 
     if( ctx->is384 == 0 )
     {
-        PUT_UINT64_BE( ctx->state[6], output, 48 );
-        PUT_UINT64_BE( ctx->state[7], output, 56 );
+        sha512_put_uint64_be( ctx->state[6], output, 48 );
+        sha512_put_uint64_be( ctx->state[7], output, 56 );
     }
 
     return( 0 );
diff --git a/library/version_features.c b/library/version_features.c
index cd75cc0..5404d79 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -408,6 +408,9 @@
 #if defined(MBEDTLS_SHA256_SMALLER)
     "MBEDTLS_SHA256_SMALLER",
 #endif /* MBEDTLS_SHA256_SMALLER */
+#if defined(MBEDTLS_SHA512_SMALLER)
+    "MBEDTLS_SHA512_SMALLER",
+#endif /* MBEDTLS_SHA512_SMALLER */
 #if defined(MBEDTLS_THREADING_ALT)
     "MBEDTLS_THREADING_ALT",
 #endif /* MBEDTLS_THREADING_ALT */
diff --git a/programs/test/query_config.c b/programs/test/query_config.c
index 4f28009..da3dfb0 100644
--- a/programs/test/query_config.c
+++ b/programs/test/query_config.c
@@ -1116,6 +1116,14 @@
     }
 #endif /* MBEDTLS_SHA256_SMALLER */
 
+#if defined(MBEDTLS_SHA512_SMALLER)
+    if( strcmp( "MBEDTLS_SHA512_SMALLER", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SHA512_SMALLER );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SHA512_SMALLER */
+
 #if defined(MBEDTLS_THREADING_ALT)
     if( strcmp( "MBEDTLS_THREADING_ALT", config ) == 0 )
     {
diff --git a/tests/suites/test_suite_cipher.aes.data b/tests/suites/test_suite_cipher.aes.data
index c42fc79..6293408 100644
--- a/tests/suites/test_suite_cipher.aes.data
+++ b/tests/suites/test_suite_cipher.aes.data
@@ -1,6 +1,10 @@
-Decrypt empty buffer
+AES-128 CBC - Decrypt empty buffer
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
-dec_empty_buf:MBEDTLS_CIPHER_AES_128_CBC
+dec_empty_buf:MBEDTLS_CIPHER_AES_128_CBC:0:0
+
+AES-128 XTS - Decrypt empty buffer
+depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_XTS
+dec_empty_buf:MBEDTLS_CIPHER_AES_128_XTS:MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH:0
 
 AES-128 CBC - Encrypt and decrypt 0 bytes with PKCS7 padding
 depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
diff --git a/tests/suites/test_suite_cipher.arc4.data b/tests/suites/test_suite_cipher.arc4.data
index 6e69b81..adeed83 100644
--- a/tests/suites/test_suite_cipher.arc4.data
+++ b/tests/suites/test_suite_cipher.arc4.data
@@ -1,3 +1,7 @@
+ARC4 Decrypt empty buffer
+depends_on:MBEDTLS_ARC4_C
+dec_empty_buf:MBEDTLS_CIPHER_ARC4_128:0:0
+
 ARC4 Encrypt and decrypt 0 bytes
 depends_on:MBEDTLS_ARC4_C
 enc_dec_buf:MBEDTLS_CIPHER_ARC4_128:"ARC4-128":128:0:-1
diff --git a/tests/suites/test_suite_cipher.aria.data b/tests/suites/test_suite_cipher.aria.data
new file mode 100644
index 0000000..2c50a21
--- /dev/null
+++ b/tests/suites/test_suite_cipher.aria.data
@@ -0,0 +1,3 @@
+Aria CBC Decrypt empty buffer
+depends_on:MBEDTLS_ARIA_C:MBEDTLS_CIPHER_MODE_CBC
+dec_empty_buf:MBEDTLS_CIPHER_ARIA_128_CBC:0:0
diff --git a/tests/suites/test_suite_cipher.blowfish.data b/tests/suites/test_suite_cipher.blowfish.data
index b94bc47..bbb3934 100644
--- a/tests/suites/test_suite_cipher.blowfish.data
+++ b/tests/suites/test_suite_cipher.blowfish.data
@@ -1,3 +1,7 @@
+BLOWFISH CBC Decrypt empty buffer
+depends_on:MBEDTLS_BLOWFISH_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
+dec_empty_buf:MBEDTLS_CIPHER_BLOWFISH_CBC:0:0
+
 BLOWFISH Encrypt and decrypt 0 bytes
 depends_on:MBEDTLS_BLOWFISH_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
 enc_dec_buf:MBEDTLS_CIPHER_BLOWFISH_CBC:"BLOWFISH-CBC":128:0:-1
diff --git a/tests/suites/test_suite_cipher.camellia.data b/tests/suites/test_suite_cipher.camellia.data
index e6342da..8fbbbe9 100644
--- a/tests/suites/test_suite_cipher.camellia.data
+++ b/tests/suites/test_suite_cipher.camellia.data
@@ -1,3 +1,7 @@
+CAMELLIA CBC Decrypt empty buffer
+depends_on:MBEDTLS_CAMELLIA_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
+dec_empty_buf:MBEDTLS_CIPHER_CAMELLIA_128_CBC:0:0
+
 CAMELLIA Encrypt and decrypt 0 bytes
 depends_on:MBEDTLS_CAMELLIA_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
 enc_dec_buf:MBEDTLS_CIPHER_CAMELLIA_128_CBC:"CAMELLIA-128-CBC":128:0:-1
diff --git a/tests/suites/test_suite_cipher.chachapoly.data b/tests/suites/test_suite_cipher.chachapoly.data
index ccd0dfb..8c246ad 100644
--- a/tests/suites/test_suite_cipher.chachapoly.data
+++ b/tests/suites/test_suite_cipher.chachapoly.data
@@ -1,6 +1,6 @@
 Decrypt empty buffer
 depends_on:MBEDTLS_CHACHAPOLY_C
-dec_empty_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305
+dec_empty_buf:MBEDTLS_CIPHER_CHACHA20_POLY1305:0:0
 
 ChaCha20+Poly1305 Encrypt and decrypt 0 bytes
 depends_on:MBEDTLS_CHACHAPOLY_C
diff --git a/tests/suites/test_suite_cipher.des.data b/tests/suites/test_suite_cipher.des.data
index ba9020e..c272a3e 100644
--- a/tests/suites/test_suite_cipher.des.data
+++ b/tests/suites/test_suite_cipher.des.data
@@ -1,3 +1,15 @@
+DES CBC Decrypt empty buffer
+depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
+dec_empty_buf:MBEDTLS_CIPHER_DES_CBC:0:0
+
+DES EDE CBC Decrypt empty buffer
+depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
+dec_empty_buf:MBEDTLS_CIPHER_DES_EDE_CBC:0:0
+
+DES EDE3 CBC Decrypt empty buffer
+depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
+dec_empty_buf:MBEDTLS_CIPHER_DES_EDE3_CBC:0:0
+
 DES Encrypt and decrypt 0 bytes
 depends_on:MBEDTLS_DES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7
 enc_dec_buf:MBEDTLS_CIPHER_DES_CBC:"DES-CBC":64:0:-1
diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function
index f6367f1..8405f69 100644
--- a/tests/suites/test_suite_cipher.function
+++ b/tests/suites/test_suite_cipher.function
@@ -1,6 +1,10 @@
 /* BEGIN_HEADER */
 #include "mbedtls/cipher.h"
 
+#if defined(MBEDTLS_AES_C)
+#include "mbedtls/aes.h"
+#endif
+
 #if defined(MBEDTLS_GCM_C)
 #include "mbedtls/gcm.h"
 #endif
@@ -715,7 +719,9 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
-void dec_empty_buf( int cipher )
+void dec_empty_buf( int cipher,
+                    int expected_update_ret,
+                    int expected_finish_ret )
 {
     unsigned char key[32];
     unsigned char iv[16];
@@ -728,8 +734,6 @@
 
     size_t outlen = 0;
 
-    int expected_ret;
-
     memset( key, 0, 32 );
     memset( iv , 0, 16 );
 
@@ -758,25 +762,24 @@
 #endif
 
     /* decode 0-byte string */
-    TEST_ASSERT( 0 == mbedtls_cipher_update( &ctx_dec, encbuf, 0, decbuf, &outlen ) );
+    TEST_ASSERT( expected_update_ret ==
+                 mbedtls_cipher_update( &ctx_dec, encbuf, 0, decbuf, &outlen ) );
     TEST_ASSERT( 0 == outlen );
 
-    if ( cipher_info->mode == MBEDTLS_MODE_CBC ||
-         cipher_info->mode == MBEDTLS_MODE_ECB )
-    {
-        /* CBC and ECB ciphers need a full block of input. */
-        expected_ret = MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;
-    }
-    else
+    if ( expected_finish_ret == 0 &&
+         ( cipher_info->mode == MBEDTLS_MODE_CBC ||
+           cipher_info->mode == MBEDTLS_MODE_ECB ) )
     {
         /* Non-CBC and non-ECB ciphers are OK with decrypting empty buffers and
          * return success, not MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED, when
-         * decrypting an empty buffer. */
-        expected_ret = 0;
+         * decrypting an empty buffer.
+         * On the other hand, CBC and ECB ciphers need a full block of input.
+         */
+        expected_finish_ret = MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;
     }
 
-    TEST_ASSERT( expected_ret == mbedtls_cipher_finish(
-                                    &ctx_dec, decbuf + outlen, &outlen ) );
+    TEST_ASSERT( expected_finish_ret == mbedtls_cipher_finish(
+                                        &ctx_dec, decbuf + outlen, &outlen ) );
     TEST_ASSERT( 0 == outlen );
 
 exit:
diff --git a/tests/suites/test_suite_cipher.gcm.data b/tests/suites/test_suite_cipher.gcm.data
index 03d08ce..83889de 100644
--- a/tests/suites/test_suite_cipher.gcm.data
+++ b/tests/suites/test_suite_cipher.gcm.data
@@ -1,3 +1,11 @@
+CAMELLIA GCM Decrypt empty buffer
+depends_on:MBEDTLS_CAMELLIA_C:MBEDTLS_GCM_C
+dec_empty_buf:MBEDTLS_CIPHER_CAMELLIA_128_GCM:0:0
+
+Aria GCM Decrypt empty buffer
+depends_on:MBEDTLS_ARIA_C:MBEDTLS_GCM_C
+dec_empty_buf:MBEDTLS_CIPHER_ARIA_128_GCM:0:0
+
 AES 128 GCM Encrypt and decrypt 0 bytes
 depends_on:MBEDTLS_AES_C:MBEDTLS_GCM_C
 enc_dec_buf:MBEDTLS_CIPHER_AES_128_GCM:"AES-128-GCM":128:0:-1
diff --git a/tests/suites/test_suite_cipher.nist_kw.data b/tests/suites/test_suite_cipher.nist_kw.data
index 59ef931..8201891 100644
--- a/tests/suites/test_suite_cipher.nist_kw.data
+++ b/tests/suites/test_suite_cipher.nist_kw.data
@@ -1,3 +1,11 @@
+KW AES-128 wrap  - Decrypt empty buffer
+depends_on:MBEDTLS_AES_C:MBEDTLS_NIST_KW_C
+dec_empty_buf:MBEDTLS_CIPHER_AES_128_KW:MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE:MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE
+
+KWP AES-128 wrap  - Decrypt empty buffer
+depends_on:MBEDTLS_AES_C:MBEDTLS_NIST_KW_C
+dec_empty_buf:MBEDTLS_CIPHER_AES_128_KWP:MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE:MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE
+
 KW AES-128 wrap rfc 3394
 depends_on:MBEDTLS_AES_C:MBEDTLS_NIST_KW_C
 auth_crypt_tv:MBEDTLS_CIPHER_AES_128_KW:"000102030405060708090A0B0C0D0E0F":"":"":"1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5":"":"":"00112233445566778899AABBCCDDEEFF":0
@@ -268,4 +276,3 @@
 KWP AES-256 wrap CAVS 17.4 FAIL COUNT 4 CLEN 32
 depends_on:MBEDTLS_AES_C:MBEDTLS_NIST_KW_C
 auth_crypt_tv:MBEDTLS_CIPHER_AES_256_KWP:"c32cb3e1e41a4b9f4de79989957866f5dd48dba38c22a6ebb80e14c84bdd9534":"":"":"c29b05c2619a58ecc1d239e7a34273cd":"":"FAIL":"":0
-