Fix premature fopen() call in mbedtls_entropy_write_seed_file #3175

Signed-off-by: Victor Krasnoshchok <ct3da21164@protonmail.ch>
diff --git a/ChangeLog.d/bugfix_PR3616.txt b/ChangeLog.d/bugfix_PR3616.txt
new file mode 100644
index 0000000..47d1044
--- /dev/null
+++ b/ChangeLog.d/bugfix_PR3616.txt
@@ -0,0 +1,5 @@
+Bugfix
+   * Fix premature fopen() call in mbedtls_entropy_write_seed_file which may
+     lead to the seed file corruption in case if the path to the seed file is
+     equal to MBEDTLS_PLATFORM_STD_NV_SEED_FILE. Contributed by Victor
+     Krasnoshchok in #3616.
diff --git a/library/entropy.c b/library/entropy.c
index 666c556..22fa713 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -489,14 +489,20 @@
 int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path )
 {
     int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
-    FILE *f;
+    FILE *f = NULL;
     unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
 
-    if( ( f = fopen( path, "wb" ) ) == NULL )
-        return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
-
     if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
+    {
+        ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
         goto exit;
+    }
+
+    if( ( f = fopen( path, "wb" ) ) == NULL )
+    {
+        ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
+        goto exit;
+    }
 
     if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE )
     {
@@ -509,7 +515,9 @@
 exit:
     mbedtls_platform_zeroize( buf, sizeof( buf ) );
 
-    fclose( f );
+    if( f != NULL )
+        fclose( f );
+
     return( ret );
 }
 
diff --git a/tests/suites/test_suite_entropy.data b/tests/suites/test_suite_entropy.data
index 5cff399..3595c71 100644
--- a/tests/suites/test_suite_entropy.data
+++ b/tests/suites/test_suite_entropy.data
@@ -7,6 +7,9 @@
 Entropy write/update seed file
 entropy_seed_file:"no_such_dir/file":MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR
 
+Entropy write/update seed file: base NV seed file
+entropy_write_base_seed_file:0
+
 Entropy too many sources
 entropy_too_many_sources:
 
diff --git a/tests/suites/test_suite_entropy.function b/tests/suites/test_suite_entropy.function
index 889d3bc..c275257 100644
--- a/tests/suites/test_suite_entropy.function
+++ b/tests/suites/test_suite_entropy.function
@@ -140,6 +140,21 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
+void entropy_write_base_seed_file( int ret )
+{
+    mbedtls_entropy_context ctx;
+
+    mbedtls_entropy_init( &ctx );
+
+    TEST_ASSERT( mbedtls_entropy_write_seed_file( &ctx, MBEDTLS_PLATFORM_STD_NV_SEED_FILE ) == ret );
+    TEST_ASSERT( mbedtls_entropy_update_seed_file( &ctx, MBEDTLS_PLATFORM_STD_NV_SEED_FILE ) == ret );
+
+exit:
+    mbedtls_entropy_free( &ctx );
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void entropy_too_many_sources(  )
 {