mbedTLS CVE fix
[platform/upstream/iotivity.git] / extlibs / mbedtls / mbedtls / library / sha512.c
index 724522a..10d4ad1 100644 (file)
@@ -114,7 +114,7 @@ void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
 /*
  * SHA-512 context setup
  */
-void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 )
+int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 )
 {
     ctx->total[0] = 0;
     ctx->total[1] = 0;
@@ -145,6 +145,14 @@ void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 )
     }
 
     ctx->is384 = is384;
+
+    return( 0 );
+}
+
+void mbedtls_sha512_starts( mbedtls_sha512_context *ctx,
+                            int is384 )
+{
+    mbedtls_sha512_starts_ret( ctx, is384 );
 }
 
 #if !defined(MBEDTLS_SHA512_PROCESS_ALT)
@@ -196,7 +204,8 @@ static const uint64_t K[80] =
     UL64(0x5FCB6FAB3AD6FAEC),  UL64(0x6C44198C4A475817)
 };
 
-void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] )
+int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx,
+                                     const unsigned char data[128] )
 {
     int i;
     uint64_t temp1, temp2, W[80];
@@ -263,20 +272,30 @@ void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char da
     ctx->state[5] += F;
     ctx->state[6] += G;
     ctx->state[7] += H;
+
+    return( 0 );
+}
+
+void mbedtls_sha512_process( mbedtls_sha512_context *ctx,
+                             const unsigned char data[128] )
+{
+    mbedtls_internal_sha512_process( ctx, data );
 }
 #endif /* !MBEDTLS_SHA512_PROCESS_ALT */
 
 /*
  * SHA-512 process buffer
  */
-void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input,
-                    size_t ilen )
+int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx,
+                               const unsigned char *input,
+                               size_t ilen )
 {
+    int ret;
     size_t fill;
     unsigned int left;
 
     if( ilen == 0 )
-        return;
+        return( 0 );
 
     left = (unsigned int) (ctx->total[0] & 0x7F);
     fill = 128 - left;
@@ -289,7 +308,10 @@ void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *in
     if( left && ilen >= fill )
     {
         memcpy( (void *) (ctx->buffer + left), input, fill );
-        mbedtls_sha512_process( ctx, ctx->buffer );
+
+        if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
+            return( ret );
+
         input += fill;
         ilen  -= fill;
         left = 0;
@@ -297,49 +319,75 @@ void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *in
 
     while( ilen >= 128 )
     {
-        mbedtls_sha512_process( ctx, input );
+        if( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 )
+            return( ret );
+
         input += 128;
         ilen  -= 128;
     }
 
     if( ilen > 0 )
         memcpy( (void *) (ctx->buffer + left), input, ilen );
+
+    return( 0 );
 }
 
-static const unsigned char sha512_padding[128] =
+void mbedtls_sha512_update( mbedtls_sha512_context *ctx,
+                            const unsigned char *input,
+                            size_t ilen )
 {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
+    mbedtls_sha512_update_ret( ctx, input, ilen );
+}
 
 /*
  * SHA-512 final digest
  */
-void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] )
+int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx,
+                               unsigned char output[64] )
 {
-    size_t last, padn;
+    int ret;
+    unsigned used;
     uint64_t high, low;
-    unsigned char msglen[16];
 
+    /*
+     * Add padding: 0x80 then 0x00 until 16 bytes remain for the length
+     */
+    used = ctx->total[0] & 0x7F;
+
+    ctx->buffer[used++] = 0x80;
+
+    if( used <= 112 )
+    {
+        /* Enough room for padding + length in current block */
+        memset( ctx->buffer + used, 0, 112 - used );
+    }
+    else
+    {
+        /* We'll need an extra block */
+        memset( ctx->buffer + used, 0, 128 - used );
+
+        if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
+            return( ret );
+
+        memset( ctx->buffer, 0, 112 );
+    }
+
+    /*
+     * Add message length
+     */
     high = ( ctx->total[0] >> 61 )
          | ( ctx->total[1] <<  3 );
     low  = ( ctx->total[0] <<  3 );
 
-    PUT_UINT64_BE( high, msglen, 0 );
-    PUT_UINT64_BE( low,  msglen, 8 );
-
-    last = (size_t)( ctx->total[0] & 0x7F );
-    padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
+    PUT_UINT64_BE( high, ctx->buffer, 112 );
+    PUT_UINT64_BE( low,  ctx->buffer, 120 );
 
-    mbedtls_sha512_update( ctx, sha512_padding, padn );
-    mbedtls_sha512_update( ctx, msglen, 16 );
+    if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
+        return( ret );
 
+    /*
+     * 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 );
@@ -352,6 +400,14 @@ void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64
         PUT_UINT64_BE( ctx->state[6], output, 48 );
         PUT_UINT64_BE( ctx->state[7], output, 56 );
     }
+
+    return( 0 );
+}
+
+void mbedtls_sha512_finish( mbedtls_sha512_context *ctx,
+                            unsigned char output[64] )
+{
+    mbedtls_sha512_finish_ret( ctx, output );
 }
 
 #endif /* !MBEDTLS_SHA512_ALT */
@@ -359,16 +415,37 @@ void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64
 /*
  * output = SHA-512( input buffer )
  */
-void mbedtls_sha512( const unsigned char *input, size_t ilen,
-             unsigned char output[64], int is384 )
+int mbedtls_sha512_ret( const unsigned char *input,
+                    size_t ilen,
+                    unsigned char output[64],
+                    int is384 )
 {
+    int ret;
     mbedtls_sha512_context ctx;
 
     mbedtls_sha512_init( &ctx );
-    mbedtls_sha512_starts( &ctx, is384 );
-    mbedtls_sha512_update( &ctx, input, ilen );
-    mbedtls_sha512_finish( &ctx, output );
+
+    if( ( ret = mbedtls_sha512_starts_ret( &ctx, is384 ) ) != 0 )
+        goto exit;
+
+    if( ( ret = mbedtls_sha512_update_ret( &ctx, input, ilen ) ) != 0 )
+        goto exit;
+
+    if( ( ret = mbedtls_sha512_finish_ret( &ctx, output ) ) != 0 )
+        goto exit;
+
+exit:
     mbedtls_sha512_free( &ctx );
+
+    return( ret );
+}
+
+void mbedtls_sha512( const unsigned char *input,
+                     size_t ilen,
+                     unsigned char output[64],
+                     int is384 )
+{
+    mbedtls_sha512_ret( input, ilen, output, is384 );
 }
 
 #if defined(MBEDTLS_SELF_TEST)
@@ -384,7 +461,7 @@ static const unsigned char sha512_test_buf[3][113] =
     { "" }
 };
 
-static const int sha512_test_buflen[3] =
+static const size_t sha512_test_buflen[3] =
 {
     3, 112, 1000
 };
@@ -471,28 +548,35 @@ int mbedtls_sha512_self_test( int verbose )
         if( verbose != 0 )
             mbedtls_printf( "  SHA-%d test #%d: ", 512 - k * 128, j + 1 );
 
-        mbedtls_sha512_starts( &ctx, k );
+        if( ( ret = mbedtls_sha512_starts_ret( &ctx, k ) ) != 0 )
+            goto fail;
 
         if( j == 2 )
         {
             memset( buf, 'a', buflen = 1000 );
 
             for( j = 0; j < 1000; j++ )
-                mbedtls_sha512_update( &ctx, buf, buflen );
+            {
+                ret = mbedtls_sha512_update_ret( &ctx, buf, buflen );
+                if( ret != 0 )
+                    goto fail;
+            }
         }
         else
-            mbedtls_sha512_update( &ctx, sha512_test_buf[j],
-                                 sha512_test_buflen[j] );
+        {
+            ret = mbedtls_sha512_update_ret( &ctx, sha512_test_buf[j],
+                                             sha512_test_buflen[j] );
+            if( ret != 0 )
+                goto fail;
+        }
 
-        mbedtls_sha512_finish( &ctx, sha512sum );
+        if( ( ret = mbedtls_sha512_finish_ret( &ctx, sha512sum ) ) != 0 )
+            goto fail;
 
         if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 )
         {
-            if( verbose != 0 )
-                mbedtls_printf( "failed\n" );
-
             ret = 1;
-            goto exit;
+            goto fail;
         }
 
         if( verbose != 0 )
@@ -502,6 +586,12 @@ int mbedtls_sha512_self_test( int verbose )
     if( verbose != 0 )
         mbedtls_printf( "\n" );
 
+    goto exit;
+
+fail:
+    if( verbose != 0 )
+        mbedtls_printf( "failed\n" );
+
 exit:
     mbedtls_sha512_free( &ctx );
     mbedtls_free( buf );