Merge remote-tracking branch 'upstream-restricted/pr/387' into mbedtls-1.3-restricted
diff --git a/ChangeLog b/ChangeLog
index 55e4e7f..1a85af2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,6 +11,8 @@
    * Fix unsafe bounds check in ssl_parse_client_psk_identity() when adding
      64kB to the address of the SSL buffer wraps around.
    * Tighten should-be-constant-time memcmp against compiler optimizations.
+   * Ensure that buffers are cleared after use if they contain sensitive data.
+     Changes were introduced in multiple places in the library.
 
 Bugfix
    * Fix memory leak in ssl_set_hostname() when called multiple times.
diff --git a/library/bignum.c b/library/bignum.c
index 4829d91..e4a8dec 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -1880,6 +1880,8 @@
     MPI_CHK( mpi_read_binary( X, buf, size ) );
 
 cleanup:
+    polarssl_zeroize( buf, sizeof( buf ) );
+
     return( ret );
 }
 
diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c
index 7b315e8..f66064f 100644
--- a/library/ctr_drbg.c
+++ b/library/ctr_drbg.c
@@ -402,20 +402,20 @@
         goto exit;
 
     if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT )
-    {
         ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
-        goto exit;
-    }
-
-    ret = 0;
+    else
+        ret = 0;
 
 exit:
+    polarssl_zeroize( buf, sizeof( buf ) );
+
     fclose( f );
     return( ret );
 }
 
 int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path )
 {
+    int ret = 0;
     FILE *f;
     size_t n;
     unsigned char buf[ CTR_DRBG_MAX_INPUT ];
@@ -434,14 +434,16 @@
     }
 
     if( fread( buf, 1, n, f ) != n )
-    {
-        fclose( f );
-        return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR );
-    }
+        ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR;
+    else
+        ctr_drbg_update( ctx, buf, n );
 
     fclose( f );
 
-    ctr_drbg_update( ctx, buf, n );
+    polarssl_zeroize( buf, sizeof( buf ) );
+
+    if( ret != 0 )
+        return( ret );
 
     return( ctr_drbg_write_seed_file( ctx, path ) );
 }
diff --git a/library/dhm.c b/library/dhm.c
index 48fba2a..582eec7 100644
--- a/library/dhm.c
+++ b/library/dhm.c
@@ -532,7 +532,10 @@
     if( fread( *buf, 1, *n, f ) != *n )
     {
         fclose( f );
+
+        polarssl_zeroize( *buf, *n + 1 );
         polarssl_free( *buf );
+
         return( POLARSSL_ERR_DHM_FILE_IO_ERROR );
     }
 
diff --git a/library/entropy.c b/library/entropy.c
index c6f44df..2cd4ce1 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -166,6 +166,8 @@
     sha256_update( &ctx->accumulator, p, use_len );
 #endif
 
+    polarssl_zeroize( tmp, sizeof( tmp ) );
+
     return( 0 );
 }
 
@@ -194,13 +196,11 @@
  */
 static int entropy_gather_internal( entropy_context *ctx )
 {
-    int ret, i;
+    int ret = POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED;
+    int i;
     unsigned char buf[ENTROPY_MAX_GATHER];
     size_t olen;
 
-    if( ctx->source_count == 0 )
-        return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED );
-
     /*
      * Run through our entropy sources
      */
@@ -210,7 +210,7 @@
         if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
                         buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 )
         {
-            return( ret );
+            goto cleanup;
         }
 
         /*
@@ -223,7 +223,10 @@
         }
     }
 
-    return( 0 );
+cleanup:
+    polarssl_zeroize( buf, sizeof( buf ) );
+
+    return( ret );
 }
 
 /*
@@ -324,6 +327,8 @@
     ret = 0;
 
 exit:
+    polarssl_zeroize( buf, sizeof( buf ) );
+
 #if defined(POLARSSL_THREADING_C)
     if( polarssl_mutex_unlock( &ctx->mutex ) != 0 )
         return( POLARSSL_ERR_THREADING_MUTEX_ERROR );
@@ -354,12 +359,15 @@
     ret = 0;
 
 exit:
+    polarssl_zeroize( buf, sizeof( buf ) );
+
     fclose( f );
     return( ret );
 }
 
 int entropy_update_seed_file( entropy_context *ctx, const char *path )
 {
+    int ret = 0;
     FILE *f;
     size_t n;
     unsigned char buf[ ENTROPY_MAX_SEED_SIZE ];
@@ -375,14 +383,16 @@
         n = ENTROPY_MAX_SEED_SIZE;
 
     if( fread( buf, 1, n, f ) != n )
-    {
-        fclose( f );
-        return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR );
-    }
+        ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR;
+    else
+        ret = entropy_update_manual( ctx, buf, n );
 
     fclose( f );
 
-    entropy_update_manual( ctx, buf, n );
+    polarssl_zeroize( buf, sizeof( buf ) );
+
+    if( ret != 0 )
+        return( ret );
 
     return( entropy_write_seed_file( ctx, path ) );
 }
diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c
index c7904d0..eece389 100644
--- a/library/hmac_drbg.c
+++ b/library/hmac_drbg.c
@@ -342,11 +342,14 @@
 
 exit:
     fclose( f );
+    polarssl_zeroize( buf, sizeof( buf ) );
+
     return( ret );
 }
 
 int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path )
 {
+    int ret = 0;
     FILE *f;
     size_t n;
     unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ];
@@ -365,14 +368,16 @@
     }
 
     if( fread( buf, 1, n, f ) != n )
-    {
-        fclose( f );
-        return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR );
-    }
+        ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR;
+    else
+        hmac_drbg_update( ctx, buf, n );
 
     fclose( f );
 
-    hmac_drbg_update( ctx, buf, n );
+    polarssl_zeroize( buf, sizeof( buf ) );
+
+    if( ret != 0 )
+        return( ret );
 
     return( hmac_drbg_write_seed_file( ctx, path ) );
 }
diff --git a/library/md2.c b/library/md2.c
index 2ac7eba..2d6123f 100644
--- a/library/md2.c
+++ b/library/md2.c
@@ -217,6 +217,7 @@
  */
 int md2_file( const char *path, unsigned char output[16] )
 {
+    int ret = 0;
     FILE *f;
     size_t n;
     md2_context ctx;
@@ -231,17 +232,16 @@
     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
         md2_update( &ctx, buf, n );
 
-    md2_finish( &ctx, output );
-    md2_free( &ctx );
-
     if( ferror( f ) != 0 )
-    {
-        fclose( f );
-        return( POLARSSL_ERR_MD2_FILE_IO_ERROR );
-    }
+        ret = POLARSSL_ERR_MD2_FILE_IO_ERROR;
+    else
+        md2_finish( &ctx, output );
 
+    md2_free( &ctx );
+    polarssl_zeroize( buf, sizeof( buf ) );
     fclose( f );
-    return( 0 );
+
+    return( ret );
 }
 #endif /* POLARSSL_FS_IO */
 
diff --git a/library/md4.c b/library/md4.c
index 8754d2f..9c4a9b8 100644
--- a/library/md4.c
+++ b/library/md4.c
@@ -313,6 +313,7 @@
  */
 int md4_file( const char *path, unsigned char output[16] )
 {
+    int ret = 0;
     FILE *f;
     size_t n;
     md4_context ctx;
@@ -327,17 +328,16 @@
     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
         md4_update( &ctx, buf, n );
 
-    md4_finish( &ctx, output );
-    md4_free( &ctx );
-
     if( ferror( f ) != 0 )
-    {
-        fclose( f );
-        return( POLARSSL_ERR_MD4_FILE_IO_ERROR );
-    }
+        ret = POLARSSL_ERR_MD4_FILE_IO_ERROR;
+    else
+        md4_finish( &ctx, output );
 
+    md4_free( &ctx );
+    polarssl_zeroize( buf, sizeof( buf ) );
     fclose( f );
-    return( 0 );
+
+    return( ret );
 }
 #endif /* POLARSSL_FS_IO */
 
diff --git a/library/md5.c b/library/md5.c
index 8c7ed1f..4a0f251 100644
--- a/library/md5.c
+++ b/library/md5.c
@@ -330,6 +330,7 @@
  */
 int md5_file( const char *path, unsigned char output[16] )
 {
+    int ret = 0;
     FILE *f;
     size_t n;
     md5_context ctx;
@@ -344,17 +345,16 @@
     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
         md5_update( &ctx, buf, n );
 
-    md5_finish( &ctx, output );
-    md5_free( &ctx );
-
     if( ferror( f ) != 0 )
-    {
-        fclose( f );
-        return( POLARSSL_ERR_MD5_FILE_IO_ERROR );
-    }
+        ret = POLARSSL_ERR_MD5_FILE_IO_ERROR;
+    else
+        md5_finish( &ctx, output );
 
+    md5_free( &ctx );
+    polarssl_zeroize( buf, sizeof( buf ) );
     fclose( f );
-    return( 0 );
+
+    return( ret );
 }
 #endif /* POLARSSL_FS_IO */
 
diff --git a/library/pem.c b/library/pem.c
index b2c16c2..789a92d 100644
--- a/library/pem.c
+++ b/library/pem.c
@@ -333,6 +333,7 @@
 
     if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 )
     {
+        polarssl_zeroize( buf, len );
         polarssl_free( buf );
         return( POLARSSL_ERR_PEM_INVALID_DATA + ret );
     }
@@ -343,6 +344,7 @@
     ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) )
         if( pwd == NULL )
         {
+            polarssl_zeroize( buf, len );
             polarssl_free( buf );
             return( POLARSSL_ERR_PEM_PASSWORD_REQUIRED );
         }
@@ -371,10 +373,12 @@
          */
         if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 )
         {
+            polarssl_zeroize( buf, len );
             polarssl_free( buf );
             return( POLARSSL_ERR_PEM_PASSWORD_MISMATCH );
         }
 #else
+        polarssl_zeroize( buf, len );
         polarssl_free( buf );
         return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE );
 #endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC &&
diff --git a/library/pkparse.c b/library/pkparse.c
index 6fb0dd5..0c8fb83 100644
--- a/library/pkparse.c
+++ b/library/pkparse.c
@@ -98,7 +98,10 @@
     if( fread( *buf, 1, *n, f ) != *n )
     {
         fclose( f );
+
+        polarssl_zeroize( *buf, *n );
         polarssl_free( *buf );
+
         return( POLARSSL_ERR_PK_FILE_IO_ERROR );
     }
 
diff --git a/library/ripemd160.c b/library/ripemd160.c
index 2c196f4..7b5d02e 100644
--- a/library/ripemd160.c
+++ b/library/ripemd160.c
@@ -388,6 +388,7 @@
  */
 int ripemd160_file( const char *path, unsigned char output[20] )
 {
+    int ret = 0;
     FILE *f;
     size_t n;
     ripemd160_context ctx;
@@ -402,17 +403,16 @@
     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
         ripemd160_update( &ctx, buf, n );
 
-    ripemd160_finish( &ctx, output );
-    ripemd160_free( &ctx );
-
     if( ferror( f ) != 0 )
-    {
-        fclose( f );
-        return( POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR );
-    }
+        ret = POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR;
+    else
+        ripemd160_finish( &ctx, output );
 
+    ripemd160_free( &ctx );
+    polarssl_zeroize( buf, sizeof( buf ) );
     fclose( f );
-    return( 0 );
+
+    return( ret );
 }
 #endif /* POLARSSL_FS_IO */
 
diff --git a/library/sha1.c b/library/sha1.c
index 44de872..a5a235b 100644
--- a/library/sha1.c
+++ b/library/sha1.c
@@ -363,6 +363,7 @@
  */
 int sha1_file( const char *path, unsigned char output[20] )
 {
+    int ret = 0;
     FILE *f;
     size_t n;
     sha1_context ctx;
@@ -377,17 +378,16 @@
     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
         sha1_update( &ctx, buf, n );
 
-    sha1_finish( &ctx, output );
-    sha1_free( &ctx );
-
     if( ferror( f ) != 0 )
-    {
-        fclose( f );
-        return( POLARSSL_ERR_SHA1_FILE_IO_ERROR );
-    }
+        ret = POLARSSL_ERR_SHA1_FILE_IO_ERROR;
+    else
+        sha1_finish( &ctx, output );
 
+    sha1_free( &ctx );
+    polarssl_zeroize( buf, sizeof( buf ) );
     fclose( f );
-    return( 0 );
+
+    return( ret );
 }
 #endif /* POLARSSL_FS_IO */
 
diff --git a/library/sha256.c b/library/sha256.c
index 674fdf2..caae79f 100644
--- a/library/sha256.c
+++ b/library/sha256.c
@@ -366,6 +366,7 @@
  */
 int sha256_file( const char *path, unsigned char output[32], int is224 )
 {
+    int ret = 0;
     FILE *f;
     size_t n;
     sha256_context ctx;
@@ -380,17 +381,16 @@
     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
         sha256_update( &ctx, buf, n );
 
-    sha256_finish( &ctx, output );
-    sha256_free( &ctx );
-
     if( ferror( f ) != 0 )
-    {
-        fclose( f );
-        return( POLARSSL_ERR_SHA256_FILE_IO_ERROR );
-    }
+        ret = POLARSSL_ERR_SHA256_FILE_IO_ERROR;
+    else
+        sha256_finish( &ctx, output );
 
+    sha256_free( &ctx );
+    polarssl_zeroize( buf, sizeof( buf ) );
     fclose( f );
-    return( 0 );
+
+    return( ret );
 }
 #endif /* POLARSSL_FS_IO */
 
diff --git a/library/sha512.c b/library/sha512.c
index bd607e0..5e51f7f 100644
--- a/library/sha512.c
+++ b/library/sha512.c
@@ -370,6 +370,7 @@
  */
 int sha512_file( const char *path, unsigned char output[64], int is384 )
 {
+    int ret = 0;
     FILE *f;
     size_t n;
     sha512_context ctx;
@@ -384,17 +385,16 @@
     while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 )
         sha512_update( &ctx, buf, n );
 
-    sha512_finish( &ctx, output );
-    sha512_free( &ctx );
-
     if( ferror( f ) != 0 )
-    {
-        fclose( f );
-        return( POLARSSL_ERR_SHA512_FILE_IO_ERROR );
-    }
+        ret = POLARSSL_ERR_SHA512_FILE_IO_ERROR;
+    else
+        sha512_finish( &ctx, output );
 
+    sha512_free( &ctx );
+    polarssl_zeroize( buf, sizeof( buf ) );
     fclose( f );
-    return( 0 );
+
+    return( ret );
 }
 #endif /* POLARSSL_FS_IO */
 
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 54867da..eaf50be 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -4140,12 +4140,19 @@
         return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
     }
 
-    if( ssl->psk != NULL || ssl->psk_identity != NULL )
+    if( ssl->psk != NULL )
     {
+        polarssl_zeroize( ssl->psk, ssl->psk_len );
+
         polarssl_free( ssl->psk );
-        polarssl_free( ssl->psk_identity );
         ssl->psk = NULL;
+        ssl->psk_len = 0;
+    }
+    if( ssl->psk_identity != NULL )
+    {
+        polarssl_free( ssl->psk_identity );
         ssl->psk_identity = NULL;
+        ssl->psk_identity_len = 0;
     }
 
     if( ( ssl->psk = polarssl_malloc( psk_len ) ) == NULL ||