Merge pull request #3516 from AndrzejKurek/fi-pkparse-changes

FI-related pkparse.c fixes
diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h
index 4e0f989..7d16074 100644
--- a/include/mbedtls/platform_util.h
+++ b/include/mbedtls/platform_util.h
@@ -232,6 +232,18 @@
 int mbedtls_platform_memcmp( const void *buf1, const void *buf2, size_t num );
 
 /**
+ * \brief       RNG-function for getting a random 32-bit integer.
+ *
+ *
+ * \note        Currently the function is dependent of hardware providing an
+ *              rng with MBEDTLS_ENTROPY_HARDWARE_ALT. By default, 0 is
+ *              returned.
+ *
+ * \return      The generated random number.
+ */
+uint32_t mbedtls_platform_random_uint32( void );
+
+/**
  * \brief       RNG-function for getting a random in given range.
  *
  *              This function is meant to provide a global RNG to be used
diff --git a/include/mbedtls/sha256.h b/include/mbedtls/sha256.h
index 6ef2245..42aa988 100644
--- a/include/mbedtls/sha256.h
+++ b/include/mbedtls/sha256.h
@@ -118,7 +118,7 @@
  *                 and have a hash operation started.
  * \param input    The buffer holding the data. This must be a readable
  *                 buffer of length \p ilen Bytes.
- * \param ilen     The length of the input data in Bytes.
+ * \param ilen     The length of the input data in Bytes. At most UINT32_MAX.
  *
  * \return         \c 0 on success.
  * \return         A negative error code on failure.
diff --git a/include/tinycrypt/ecc.h b/include/tinycrypt/ecc.h
index 57aa508..4c20729 100644
--- a/include/tinycrypt/ecc.h
+++ b/include/tinycrypt/ecc.h
@@ -85,7 +85,7 @@
 /* Return values for functions, chosen with large Hamming distances between
  * them (especially to SUCESS) to mitigate the impact of fault injection
  * attacks flipping a low number of bits. */
-#define UECC_SUCCESS            0
+#define UECC_SUCCESS            0x00FFAAAA
 #define UECC_FAILURE            0x75555555
 #define UECC_FAULT_DETECTED     0x7aaaaaaa
 
diff --git a/library/aes.c b/library/aes.c
index f6c4fc3..e9e7544 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -552,7 +552,7 @@
     int i = 0, j, is_even_pos, dummy_rounds, num;
 
     mbedtls_platform_memset( tbl, 0, tbl_len );
-    // get random from 0x0fff (each f will be used separately)
+    // get random from 0x0fff
     num = mbedtls_platform_random_in_range( 0x1000 );
 
     // Randomize execution order of initial round key addition
@@ -570,7 +570,7 @@
     tbl_len = tbl_len - (AES_SCA_CM_ROUNDS - dummy_rounds);
 
     // randomize positions for the dummy rounds
-    num = ( num & 0x000f ) % ( dummy_rounds + 1 );
+    num = ( num & 0x0fff ) % ( dummy_rounds + 1 );
 
     // add dummy rounds after initial round key addition (if needed)
     for ( ; i < num + 2; i++ )
@@ -725,7 +725,9 @@
         return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) );
 #endif
 
-    mbedtls_platform_memset( RK, 0, ( keybits >> 5 ) * 4 );
+    /* Three least significant bits are truncated from keybits, which is
+     * expected to be a multiple of 8. */
+    mbedtls_platform_memset( RK, 0, keybits >> 3 );
     offset = mbedtls_platform_random_in_range( keybits >> 5 );
 
     for( j = offset; j < ( keybits >> 5 ); j++ )
@@ -1089,7 +1091,7 @@
     do
     {
         GET_UINT32_LE( aes_data_real.xy_values[i], input,  ( i * 4 ) );
-        aes_data_fake.xy_values[i] = mbedtls_platform_random_in_range( 0xffffffff );
+        aes_data_fake.xy_values[i] = mbedtls_platform_random_uint32();
         flow_control++;
     } while( ( i = ( i + 1 ) % 4 ) != offset );
 
diff --git a/library/pk.c b/library/pk.c
index b92eb14..fea7576 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -548,6 +548,7 @@
     return( (size_t) ( NUM_ECC_BYTES * 8 ) );
 }
 
+/* This function compares public keys of two keypairs */
 static int uecc_eckey_check_pair( const void *pub, const void *prv )
 {
     const mbedtls_uecc_keypair *uecc_pub =
@@ -621,13 +622,12 @@
 static int asn1_write_mpibuf( unsigned char **p, unsigned char *start,
                               size_t n_len )
 {
-    size_t len = 0;
+    size_t len = n_len;
     int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
 
-    if( (size_t)( *p - start ) < n_len )
+    if( (size_t)( *p - start ) < len )
         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
 
-    len = n_len;
     *p -= len;
     ret = mbedtls_platform_memmove( *p, start, len );
     if( ret != 0 )
@@ -659,6 +659,10 @@
         len += 1;
     }
 
+    /* Ensure that there is still space for len and ASN1_INTEGER */
+    if( ( *p - start ) < 2 )
+        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
     /* The ASN.1 length encoding is just a single Byte containing the length,
      * as we assume that the total buffer length is smaller than 128 Bytes. */
     *--(*p) = len;
@@ -674,7 +678,7 @@
  *
  * [in/out] sig: the signature pre- and post-transcoding
  * [in/out] sig_len: signature length pre- and post-transcoding
- * [int] buf_len: the available size the in/out buffer
+ * [in] buf_len: the available size the in/out buffer
  *
  * Warning: buf_len must be smaller than 128 Bytes.
  */
@@ -689,6 +693,9 @@
     MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig + rs_len, rs_len ) );
     MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig, rs_len ) );
 
+    if( p - sig < 2 )
+        return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
+
     /* The ASN.1 length encoding is just a single Byte containing the length,
      * as we assume that the total buffer length is smaller than 128 Bytes. */
     *--p = len;
diff --git a/library/platform_util.c b/library/platform_util.c
index de2fa2b..fc6eb5a 100644
--- a/library/platform_util.c
+++ b/library/platform_util.c
@@ -172,6 +172,20 @@
     return( (int) diff | (int) ( flow_counter ^ num ) );
 }
 
+uint32_t mbedtls_platform_random_uint32( )
+{
+#if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
+    return 0;
+#else
+    uint32_t result = 0;
+    size_t olen = 0;
+
+    mbedtls_hardware_poll( NULL, (unsigned char *) &result, sizeof( result ),
+                           &olen );
+    return( result );
+#endif
+}
+
 uint32_t mbedtls_platform_random_in_range( size_t num )
 {
 #if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
diff --git a/library/sha256.c b/library/sha256.c
index 493e88e..5214591 100644
--- a/library/sha256.c
+++ b/library/sha256.c
@@ -35,6 +35,7 @@
 #include "mbedtls/sha256.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/platform.h"
+#include <stdint.h>
 
 #include <string.h>
 
@@ -188,7 +189,7 @@
 {
     uint32_t temp1, temp2, W[64];
     uint32_t A[8];
-    uint32_t flow_ctrl = 0;
+    volatile uint32_t flow_ctrl = 0;
     unsigned int i;
 
     SHA256_VALIDATE_RET( ctx != NULL );
@@ -214,11 +215,6 @@
         }
     }
 
-    if( flow_ctrl != 16 )
-    {
-        return MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
-    }
-
     for( i = 0; i < 64; i++ )
     {
         if( i >= 16 )
@@ -317,19 +313,22 @@
     SHA256_VALIDATE_RET( ctx != NULL );
     SHA256_VALIDATE_RET( ilen == 0 || input != NULL );
 
-    if( ilen == 0 )
+    /* ilen_dup is used instead of ilen, to have it volatile for FI protection */
+    if( ilen_dup == 0 )
         return( 0 );
 
+    if( ilen_dup > UINT32_MAX )
+        return( MBEDTLS_ERR_SHA256_BAD_INPUT_DATA );
+
     left = ctx->total[0] & 0x3F;
     fill = 64 - left;
 
-    ctx->total[0] += (uint32_t) ilen;
-    ctx->total[0] &= 0xFFFFFFFF;
+    ctx->total[0] += (uint32_t) ilen_dup;
 
-    if( ctx->total[0] < (uint32_t) ilen )
+    if( ctx->total[0] < (uint32_t) ilen_dup )
         ctx->total[1]++;
 
-    if( left && ilen >= fill )
+    if( left && ilen_dup >= fill )
     {
         mbedtls_platform_memcpy( (void *) (ctx->buffer + left), input, fill );
 
@@ -337,27 +336,27 @@
             return( ret );
 
         input += fill;
-        ilen  -= fill;
+        ilen_dup  -= fill;
         left = 0;
     }
 
-    while( ilen >= 64 )
+    while( ilen_dup >= 64 )
     {
         if( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 )
             return( ret );
 
         input += 64;
-        ilen  -= 64;
+        ilen_dup  -= 64;
     }
 
-    if( ilen > 0 )
-        mbedtls_platform_memcpy( (void *) (ctx->buffer + left), input, ilen );
+    if( ilen_dup > 0 )
+        mbedtls_platform_memcpy( (void *) (ctx->buffer + left), input, ilen_dup );
 
-    /* Re-check ilen to protect from a FI attack */
-    if( ilen < 64 )
+    /* Re-check ilen_dup to protect from a FI attack */
+    if( ilen_dup < 64 )
     {
         /* Re-check that the calculated offsets are correct */
-        ilen_change = ilen_dup - ilen;
+        ilen_change = ilen - ilen_dup;
         if( ( input_dup + ilen_change ) == input )
         {
             return( 0 );
@@ -387,7 +386,7 @@
     uint32_t used;
     uint32_t high, low;
     uint32_t offset = 0;
-    uint32_t flow_ctrl = 0;
+    volatile uint32_t flow_ctrl = 0;
 
     SHA256_VALIDATE_RET( ctx != NULL );
     SHA256_VALIDATE_RET( (unsigned char *)output != NULL );
diff --git a/library/x509.c b/library/x509.c
index 093a315..65f2ec6 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -176,7 +176,7 @@
         return( MBEDTLS_ERR_X509_INVALID_ALG +
                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
 
-    p = (unsigned char *) alg->p;
+    p = alg->p;
     end = p + alg->len;
 
     if( p >= end )