Merge branch 'development'
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index d31555d..b36e27b 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -3,7 +3,7 @@
*
* \brief Consistency checks for configuration options
*
- * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -357,6 +357,38 @@
#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites"
#endif
+#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\
+ ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) )
+#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\
+ !defined(MBEDTLS_ENTROPY_NV_SEED)
+#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\
+ !defined(MBEDTLS_PLATFORM_NV_SEED_ALT)
+#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\
+ !defined(MBEDTLS_PLATFORM_NV_SEED_ALT)
+#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\
+ ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\
+ defined(MBEDTLS_PLATFORM_NV_SEED_ALT) )
+#error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\
+ ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\
+ defined(MBEDTLS_PLATFORM_NV_SEED_ALT) )
+#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously"
+#endif
+
#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \
!defined(MBEDTLS_OID_C) )
#error "MBEDTLS_RSA_C defined, but not all prerequisites"
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 0a8c056..8b6de1b 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -156,6 +156,7 @@
//#define MBEDTLS_PLATFORM_FPRINTF_ALT
//#define MBEDTLS_PLATFORM_PRINTF_ALT
//#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+//#define MBEDTLS_PLATFORM_NV_SEED_ALT
/**
* \def MBEDTLS_DEPRECATED_WARNING
@@ -800,6 +801,34 @@
//#define MBEDTLS_ENTROPY_FORCE_SHA256
/**
+ * \def MBEDTLS_ENTROPY_NV_SEED
+ *
+ * Enable the non-volatile (NV) seed file-based entropy source.
+ * (Also enables the NV seed read/write functions in the platform layer)
+ *
+ * This is crucial (if not required) on systems that do not have a
+ * cryptographic entropy source (in hardware or kernel) available.
+ *
+ * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C
+ *
+ * \note The read/write functions that are used by the entropy source are
+ * determined in the platform layer, and can be modified at runtime and/or
+ * compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used.
+ *
+ * \note If you use the default implementation functions that read a seedfile
+ * with regular fopen(), please make sure you make a seedfile with the
+ * proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at
+ * least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from
+ * and written to or you will get an entropy source error! The default
+ * implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE
+ * bytes from the file.
+ *
+ * \note The entropy collector will write to the seed file before entropy is
+ * given to an external source, to update it.
+ */
+//#define MBEDTLS_ENTROPY_NV_SEED
+
+/**
* \def MBEDTLS_MEMORY_DEBUG
*
* Enable debugging of buffer allocator memory issues. Automatically prints
@@ -2473,6 +2502,9 @@
//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */
//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */
//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
+//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */
/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */
/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */
@@ -2485,6 +2517,8 @@
//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */
/* Note: your snprintf must correclty zero-terminate the buffer! */
//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */
+//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */
+//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */
/* SSL Cache options */
//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */
diff --git a/include/mbedtls/entropy.h b/include/mbedtls/entropy.h
index 00de9a6..fed0494 100644
--- a/include/mbedtls/entropy.h
+++ b/include/mbedtls/entropy.h
@@ -3,7 +3,7 @@
*
* \brief Entropy accumulator implementation
*
- * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -134,6 +134,9 @@
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t mutex; /*!< mutex */
#endif
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+ int initial_entropy_run;
+#endif
}
mbedtls_entropy_context;
@@ -208,6 +211,18 @@
int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx,
const unsigned char *data, size_t len );
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+/**
+ * \brief Trigger an update of the seed file in NV by using the
+ * current entropy pool.
+ *
+ * \param ctx Entropy context
+ *
+ * \return 0 if successful
+ */
+int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx );
+#endif /* MBEDTLS_ENTROPY_NV_SEED */
+
#if defined(MBEDTLS_FS_IO)
/**
* \brief Write a seed file
diff --git a/include/mbedtls/entropy_poll.h b/include/mbedtls/entropy_poll.h
index dc11911..123f09c 100644
--- a/include/mbedtls/entropy_poll.h
+++ b/include/mbedtls/entropy_poll.h
@@ -3,7 +3,7 @@
*
* \brief Platform-specific and custom entropy polling functions
*
- * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -82,6 +82,16 @@
unsigned char *output, size_t len, size_t *olen );
#endif
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+/**
+ * \brief Entropy poll callback for a non-volatile seed file
+ *
+ * \note This must accept NULL as its first argument.
+ */
+int mbedtls_nv_seed_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen );
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/include/mbedtls/platform.h b/include/mbedtls/platform.h
index 039cb58..5fa01b5 100644
--- a/include/mbedtls/platform.h
+++ b/include/mbedtls/platform.h
@@ -3,7 +3,7 @@
*
* \brief mbed TLS Platform abstraction layer
*
- * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -76,12 +76,24 @@
#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE)
#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< Default exit value to use */
#endif
+#if defined(MBEDTLS_FS_IO)
+#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ)
+#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read
+#endif
+#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE)
+#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write
+#endif
+#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE)
+#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile"
+#endif
+#endif /* MBEDTLS_FS_IO */
#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR)
#include MBEDTLS_PLATFORM_STD_MEM_HDR
#endif
#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
+
/* \} name SECTION: Module settings */
/*
@@ -262,6 +274,47 @@
#endif /* MBEDTLS_PLATFORM_TIME_MACRO */
#endif /* MBEDTLS_PLATFORM_TIME_ALT */
+/*
+ * The function pointers for reading from and writing a seed file to
+ * Non-Volatile storage (NV) in a platform-independent way
+ *
+ * Only enabled when the NV seed entropy source is enabled
+ */
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO)
+/* Internal standard platform definitions */
+int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len );
+int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len );
+#endif
+
+#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT)
+extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len );
+extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len );
+
+/**
+ * \brief Set your own seed file writing/reading functions
+ *
+ * \param nv_seed_read_func the seed reading function implementation
+ * \param nv_seed_write_func the seed writing function implementation
+ *
+ * \return 0
+ */
+int mbedtls_platform_set_nv_seed(
+ int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ),
+ int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len )
+ );
+#else
+#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \
+ defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO)
+#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO
+#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO
+#else
+#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read
+#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write
+#endif
+#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */
+#endif /* MBEDTLS_ENTROPY_NV_SEED */
+
#ifdef __cplusplus
}
#endif
diff --git a/library/entropy.c b/library/entropy.c
index cdbd35c..dc2a00c 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -1,7 +1,7 @@
/*
* Entropy accumulator implementation
*
- * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -94,6 +94,11 @@
MBEDTLS_ENTROPY_MIN_HARDWARE,
MBEDTLS_ENTROPY_SOURCE_STRONG );
#endif
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+ mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL,
+ MBEDTLS_ENTROPY_BLOCK_SIZE,
+ MBEDTLS_ENTROPY_SOURCE_STRONG );
+#endif
#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
}
@@ -272,6 +277,18 @@
if( len > MBEDTLS_ENTROPY_BLOCK_SIZE )
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+ /* Update the NV entropy seed before generating any entropy for outside
+ * use.
+ */
+ if( ctx->initial_entropy_run == 0 )
+ {
+ ctx->initial_entropy_run = 1;
+ if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 )
+ return( ret );
+ }
+#endif
+
#if defined(MBEDTLS_THREADING_C)
if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
return( ret );
@@ -346,6 +363,27 @@
return( ret );
}
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx )
+{
+ int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
+ unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ];
+
+ /* Read new seed and write it to NV */
+ if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
+ return( ret );
+
+ if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 )
+ return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
+
+ /* Manually update the remaining stream with a separator value to diverge */
+ memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
+ mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
+
+ return( 0 );
+}
+#endif /* MBEDTLS_ENTROPY_NV_SEED */
+
#if defined(MBEDTLS_FS_IO)
int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path )
{
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
index e2f45c7..fcb7d8b 100644
--- a/library/entropy_poll.c
+++ b/library/entropy_poll.c
@@ -1,7 +1,7 @@
/*
* Platform-specific and custom entropy polling functions
*
- * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -37,6 +37,9 @@
#if defined(MBEDTLS_HAVEGE_C)
#include "mbedtls/havege.h"
#endif
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+#include "mbedtls/platform.h"
+#endif
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
@@ -222,4 +225,27 @@
}
#endif /* MBEDTLS_HAVEGE_C */
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+int mbedtls_nv_seed_poll( void *data,
+ unsigned char *output, size_t len, size_t *olen )
+{
+ unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
+ size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
+ ((void) data);
+
+ memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
+
+ if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 )
+ return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
+
+ if( len < use_len )
+ use_len = len;
+
+ memcpy( output, buf, use_len );
+ *olen = use_len;
+
+ return( 0 );
+}
+#endif /* MBEDTLS_ENTROPY_NV_SEED */
+
#endif /* MBEDTLS_ENTROPY_C */
diff --git a/library/platform.c b/library/platform.c
index 89a2bd6..68ca45d 100644
--- a/library/platform.c
+++ b/library/platform.c
@@ -1,7 +1,7 @@
/*
* Platform abstraction layer
*
- * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
+ * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -213,4 +213,91 @@
}
#endif /* MBEDTLS_PLATFORM_TIME_ALT */
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO)
+/* Default implementations for the platform independent seed functions use
+ * standard libc file functions to read from and write to a pre-defined filename
+ */
+int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len )
+{
+ FILE *file;
+ size_t n;
+
+ if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL )
+ return -1;
+
+ if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len )
+ {
+ fclose( file );
+ return -1;
+ }
+
+ fclose( file );
+ return( n );
+}
+
+int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len )
+{
+ FILE *file;
+ size_t n;
+
+ if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL )
+ return -1;
+
+ if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len )
+ {
+ fclose( file );
+ return -1;
+ }
+
+ fclose( file );
+ return( n );
+}
+#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
+
+#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT)
+#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static int platform_nv_seed_read_uninit( unsigned char *buf, size_t buf_len )
+{
+ ((void) buf);
+ ((void) buf_len);
+ return( -1 );
+}
+
+#define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit
+#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */
+
+#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE)
+/*
+ * Make dummy function to prevent NULL pointer dereferences
+ */
+static int platform_nv_seed_write_uninit( unsigned char *buf, size_t buf_len )
+{
+ ((void) buf);
+ ((void) buf_len);
+ return( -1 );
+}
+
+#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit
+#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */
+
+int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) =
+ MBEDTLS_PLATFORM_STD_NV_SEED_READ;
+int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) =
+ MBEDTLS_PLATFORM_STD_NV_SEED_WRITE;
+
+int mbedtls_platform_set_nv_seed(
+ int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ),
+ int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) )
+{
+ mbedtls_nv_seed_read = nv_seed_read_func;
+ mbedtls_nv_seed_write = nv_seed_write_func;
+ return( 0 );
+}
+#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */
+#endif /* MBEDTLS_ENTROPY_NV_SEED */
+
#endif /* MBEDTLS_PLATFORM_C */
diff --git a/library/version_features.c b/library/version_features.c
index b852ca8..a9b1c53 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -66,6 +66,9 @@
#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)
"MBEDTLS_PLATFORM_SNPRINTF_ALT",
#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
+#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT)
+ "MBEDTLS_PLATFORM_NV_SEED_ALT",
+#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */
#if defined(MBEDTLS_DEPRECATED_WARNING)
"MBEDTLS_DEPRECATED_WARNING",
#endif /* MBEDTLS_DEPRECATED_WARNING */
@@ -291,6 +294,9 @@
#if defined(MBEDTLS_ENTROPY_FORCE_SHA256)
"MBEDTLS_ENTROPY_FORCE_SHA256",
#endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+ "MBEDTLS_ENTROPY_NV_SEED",
+#endif /* MBEDTLS_ENTROPY_NV_SEED */
#if defined(MBEDTLS_MEMORY_DEBUG)
"MBEDTLS_MEMORY_DEBUG",
#endif /* MBEDTLS_MEMORY_DEBUG */
diff --git a/tests/suites/test_suite_entropy.data b/tests/suites/test_suite_entropy.data
index 833eef5..5ca99f8 100644
--- a/tests/suites/test_suite_entropy.data
+++ b/tests/suites/test_suite_entropy.data
@@ -1,3 +1,6 @@
+Create NV seed_file
+nv_seed_file_create:
+
Entropy write/update seed file
entropy_seed_file:"data_files/entropy_seed":0
@@ -37,5 +40,17 @@
Entropy thershold #4
entropy_threshold:1024:1:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
+Check NV seed standard IO
+entropy_nv_seed_std_io:
+
+Check NV seed manually #1
+entropy_nv_seed:"00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF"
+
+Check NV seed manually #2
+entropy_nv_seed:"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+
+Check NV seed manually #3
+entropy_nv_seed:"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+
Entropy self test
entropy_selftest:
diff --git a/tests/suites/test_suite_entropy.function b/tests/suites/test_suite_entropy.function
index 3b739cc..d1ef94b 100644
--- a/tests/suites/test_suite_entropy.function
+++ b/tests/suites/test_suite_entropy.function
@@ -1,5 +1,6 @@
/* BEGIN_HEADER */
#include "mbedtls/entropy.h"
+#include "mbedtls/entropy_poll.h"
/*
* Number of calls made to entropy_dummy_source()
@@ -33,6 +34,88 @@
return( 0 );
}
+
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+/*
+ * Ability to clear entropy sources to allow testing with just predefined
+ * entropy sources. This function or tests depending on it might break if there
+ * are internal changes to how entropy sources are registered.
+ *
+ * To be called immediately after mbedtls_entropy_init().
+ *
+ * Just resetting the counter. New sources will overwrite existing ones.
+ * This might break memory checks in the future if sources need 'free-ing' then
+ * as well.
+ */
+static void entropy_clear_sources( mbedtls_entropy_context *ctx )
+{
+ ctx->source_count = 0;
+}
+
+/*
+ * NV seed read/write functions that use a buffer instead of a file
+ */
+static unsigned char buffer_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
+
+static int buffer_nv_seed_read( unsigned char *buf, size_t buf_len )
+{
+ if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
+ return( -1 );
+
+ memcpy( buf, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
+ return( 0 );
+}
+
+static int buffer_nv_seed_write( unsigned char *buf, size_t buf_len )
+{
+ if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
+ return( -1 );
+
+ memcpy( buffer_seed, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
+ return( 0 );
+}
+
+/*
+ * NV seed read/write helpers that fill the base seedfile
+ */
+static int write_nv_seed( unsigned char *buf, size_t buf_len )
+{
+ FILE *f;
+
+ if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
+ return( -1 );
+
+ if( ( f = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL )
+ return( -1 );
+
+ if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) !=
+ MBEDTLS_ENTROPY_BLOCK_SIZE )
+ return( -1 );
+
+ fclose( f );
+
+ return( 0 );
+}
+
+static int read_nv_seed( unsigned char *buf, size_t buf_len )
+{
+ FILE *f;
+
+ if( buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE )
+ return( -1 );
+
+ if( ( f = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL )
+ return( -1 );
+
+ if( fread( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) !=
+ MBEDTLS_ENTROPY_BLOCK_SIZE )
+ return( -1 );
+
+ fclose( f );
+
+ return( 0 );
+}
+#endif /* MBEDTLS_ENTROPY_NV_SEED */
/* END_HEADER */
/* BEGIN_DEPENDENCIES
@@ -160,6 +243,10 @@
if( result >= 0 )
{
TEST_ASSERT( ret == 0 );
+#if defined(MBEDTLS_ENTROPY_NV_SEED)
+ // Two times as much calls due to the NV seed update
+ result *= 2;
+#endif
TEST_ASSERT( entropy_dummy_calls == (size_t) result );
}
else
@@ -172,6 +259,124 @@
}
/* END_CASE */
+/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
+void nv_seed_file_create()
+{
+ unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
+
+ memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
+
+ TEST_ASSERT( write_nv_seed( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO:MBEDTLS_PLATFORM_NV_SEED_ALT */
+void entropy_nv_seed_std_io()
+{
+ unsigned char io_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
+ unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
+
+ memset( io_seed, 1, MBEDTLS_ENTROPY_BLOCK_SIZE );
+ memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
+
+ mbedtls_platform_set_nv_seed( mbedtls_platform_std_nv_seed_read,
+ mbedtls_platform_std_nv_seed_write );
+
+ /* Check if platform NV read and write manipulate the same data */
+ TEST_ASSERT( write_nv_seed( io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
+ TEST_ASSERT( mbedtls_nv_seed_read( check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) ==
+ MBEDTLS_ENTROPY_BLOCK_SIZE );
+
+ TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
+
+ memset( check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
+
+ /* Check if platform NV write and raw read manipulate the same data */
+ TEST_ASSERT( mbedtls_nv_seed_write( io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) ==
+ MBEDTLS_ENTROPY_BLOCK_SIZE );
+ TEST_ASSERT( read_nv_seed( check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
+
+ TEST_ASSERT( memcmp( io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_PLATFORM_NV_SEED_ALT:MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
+void entropy_nv_seed( char *read_seed_str )
+{
+ mbedtls_sha512_context accumulator;
+ mbedtls_entropy_context ctx;
+
+ unsigned char header[2];
+ unsigned char entropy[MBEDTLS_ENTROPY_BLOCK_SIZE];
+ unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
+ unsigned char empty[MBEDTLS_ENTROPY_BLOCK_SIZE];
+ unsigned char read_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
+ unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
+ unsigned char check_entropy[MBEDTLS_ENTROPY_BLOCK_SIZE];
+
+ memset( entropy, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
+ memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
+ memset( buffer_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
+ memset( empty, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
+ memset( check_seed, 2, MBEDTLS_ENTROPY_BLOCK_SIZE );
+ memset( check_entropy, 3, MBEDTLS_ENTROPY_BLOCK_SIZE );
+
+ // Set the initial NV seed to read
+ unhexify( read_seed, read_seed_str );
+ memcpy( buffer_seed, read_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
+
+ // Make sure we read/write NV seed from our buffers
+ mbedtls_platform_set_nv_seed( buffer_nv_seed_read, buffer_nv_seed_write );
+
+ mbedtls_entropy_init( &ctx );
+ entropy_clear_sources( &ctx );
+
+ TEST_ASSERT( mbedtls_entropy_add_source( &ctx, mbedtls_nv_seed_poll, NULL,
+ MBEDTLS_ENTROPY_BLOCK_SIZE,
+ MBEDTLS_ENTROPY_SOURCE_STRONG ) == 0 );
+
+ // Do an entropy run
+ TEST_ASSERT( mbedtls_entropy_func( &ctx, entropy, sizeof( entropy ) ) == 0 );
+
+ // Determine what should have happened with manual entropy internal logic
+ // Only use the SHA-512 version to check
+
+ // Init accumulator
+ header[1] = MBEDTLS_ENTROPY_BLOCK_SIZE;
+ mbedtls_sha512_starts( &accumulator, 0 );
+
+ // First run for updating write_seed
+ header[0] = 0;
+ mbedtls_sha512_update( &accumulator, header, 2 );
+ mbedtls_sha512_update( &accumulator, read_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
+ mbedtls_sha512_finish( &accumulator, buf );
+
+ memset( &accumulator, 0, sizeof( mbedtls_sha512_context ) );
+ mbedtls_sha512_starts( &accumulator, 0 );
+ mbedtls_sha512_update( &accumulator, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
+
+ mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, check_seed, 0 );
+
+ // Second run for actual entropy (triggers mbedtls_entropy_update_nv_seed)
+ header[0] = MBEDTLS_ENTROPY_SOURCE_MANUAL;
+ mbedtls_sha512_update( &accumulator, header, 2 );
+ mbedtls_sha512_update( &accumulator, empty, MBEDTLS_ENTROPY_BLOCK_SIZE );
+
+ header[0] = 0;
+ mbedtls_sha512_update( &accumulator, header, 2 );
+ mbedtls_sha512_update( &accumulator, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE );
+ mbedtls_sha512_finish( &accumulator, buf );
+
+ mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, check_entropy, 0 );
+
+ // Check result of both NV file and entropy received with the manual calculations
+ TEST_ASSERT( memcmp( check_seed, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
+ TEST_ASSERT( memcmp( check_entropy, entropy, MBEDTLS_ENTROPY_BLOCK_SIZE ) == 0 );
+
+ mbedtls_entropy_free( &ctx );
+}
+/* END_CASE */
+
/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
void entropy_selftest( )
{