diff --git a/configs/config-thread.h b/configs/config-thread.h index 453b17f0a..3193a0404 100644 --- a/configs/config-thread.h +++ b/configs/config-thread.h @@ -85,10 +85,6 @@ /* Save ROM and a few bytes of RAM by specifying our own ciphersuite list */ #define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 -#if defined(TARGET_LIKE_MBED) -#include "mbedtls/target_config.h" -#endif - #include "mbedtls/check_config.h" #endif /* MBEDTLS_CONFIG_H */ diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index d31555df7..a95af6ca4 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 @@ -130,6 +130,16 @@ #error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" #endif +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \ + defined(MBEDTLS_HAVEGE_C) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" +#endif + #if defined(MBEDTLS_GCM_C) && ( \ !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) ) #error "MBEDTLS_GCM_C defined, but not all prerequisites" @@ -357,6 +367,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/cipher.h b/include/mbedtls/cipher.h index 70000f5e6..c9675544a 100644 --- a/include/mbedtls/cipher.h +++ b/include/mbedtls/cipher.h @@ -57,6 +57,7 @@ #define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ #define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ #define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ +#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid, eg because it was free()ed. */ #define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length */ #define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length */ diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 0efee0454..1aa86bf1b 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 @@ -278,6 +279,23 @@ //#define MBEDTLS_AES_ENCRYPT_ALT //#define MBEDTLS_AES_DECRYPT_ALT +/** + * \def MBEDTLS_TEST_NULL_ENTROPY + * + * Enables testing and use of mbed TLS without any configured entropy sources. + * This permits use of the library on platforms before an entropy source has + * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the + * MBEDTLS_ENTROPY_NV_SEED switches). + * + * WARNING! This switch MUST be disabled in production builds, and is suitable + * only for development. + * Enabling the switch negates any security provided by the library. + * + * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + */ +//#define MBEDTLS_TEST_NULL_ENTROPY + /** * \def MBEDTLS_ENTROPY_HARDWARE_ALT * @@ -799,6 +817,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 * @@ -2473,6 +2519,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 +2534,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 */ @@ -2513,11 +2564,7 @@ /* X509 options */ //#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ -/* \} name SECTION: Module configuration options */ - -#if defined(TARGET_LIKE_MBED) -#include "mbedtls/target_config.h" -#endif +/* \} name SECTION: Customisation configuration options */ /* * Allow user to override any previous default. diff --git a/include/mbedtls/entropy.h b/include/mbedtls/entropy.h index 00de9a6e5..fed0494ed 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 @@ typedef struct #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_func( void *data, unsigned char *output, size_t len ); 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 dc1191134..430e8651c 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 @@ -43,6 +43,14 @@ extern "C" { #define MBEDTLS_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedtls_timing_hardclock() */ #define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ +/** + * \brief Entropy poll callback that provides 0 entropy. + */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) /** * \brief Platform-specific entropy poll callback @@ -82,6 +90,16 @@ int mbedtls_hardware_poll( void *data, 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 fc3672cbe..caf8f2527 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 @@ extern "C" { #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 */ /* @@ -264,6 +276,47 @@ int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* time #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/base64.c b/library/base64.c index 3432e5fcd..5cb12cba7 100644 --- a/library/base64.c +++ b/library/base64.c @@ -97,7 +97,7 @@ int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, n *= 4; - if( dlen < n + 1 ) + if( ( dlen < n + 1 ) || ( NULL == dst ) ) { *olen = n + 1; return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); diff --git a/library/camellia.c b/library/camellia.c index d50513fd0..ac6f96a83 100644 --- a/library/camellia.c +++ b/library/camellia.c @@ -963,38 +963,38 @@ int mbedtls_camellia_self_test( int verbose ) mbedtls_printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); - memcpy( src, camellia_test_cbc_iv, 16 ); - memcpy( dst, camellia_test_cbc_iv, 16 ); - memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u ); - - if( v == MBEDTLS_CAMELLIA_DECRYPT ) { - mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); - } else { - mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); - } - - for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) { + memcpy( src, camellia_test_cbc_iv, 16 ); + memcpy( dst, camellia_test_cbc_iv, 16 ); + memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u ); if( v == MBEDTLS_CAMELLIA_DECRYPT ) { - memcpy( iv , src, 16 ); - memcpy( src, camellia_test_cbc_cipher[u][i], 16 ); - memcpy( dst, camellia_test_cbc_plain[i], 16 ); - } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ - memcpy( iv , dst, 16 ); - memcpy( src, camellia_test_cbc_plain[i], 16 ); - memcpy( dst, camellia_test_cbc_cipher[u][i], 16 ); + mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + } else { + mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); } - mbedtls_camellia_crypt_cbc( &ctx, v, 16, iv, src, buf ); + for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) { - if( memcmp( buf, dst, 16 ) != 0 ) - { - if( verbose != 0 ) - mbedtls_printf( "failed\n" ); + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + memcpy( iv , src, 16 ); + memcpy( src, camellia_test_cbc_cipher[u][i], 16 ); + memcpy( dst, camellia_test_cbc_plain[i], 16 ); + } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + memcpy( iv , dst, 16 ); + memcpy( src, camellia_test_cbc_plain[i], 16 ); + memcpy( dst, camellia_test_cbc_cipher[u][i], 16 ); + } - return( 1 ); + mbedtls_camellia_crypt_cbc( &ctx, v, 16, iv, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } } - } if( verbose != 0 ) mbedtls_printf( "passed\n" ); diff --git a/library/cipher.c b/library/cipher.c index 0dc51520f..bbe40eb39 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -252,6 +252,7 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i size_t ilen, unsigned char *output, size_t *olen ) { int ret; + size_t block_size = 0; if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) { @@ -259,10 +260,11 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i } *olen = 0; + block_size = mbedtls_cipher_get_block_size( ctx ); if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) { - if( ilen != mbedtls_cipher_get_block_size( ctx ) ) + if( ilen != block_size ) return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); *olen = ilen; @@ -285,8 +287,13 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i } #endif + if ( 0 == block_size ) + { + return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + } + if( input == output && - ( ctx->unprocessed_len != 0 || ilen % mbedtls_cipher_get_block_size( ctx ) ) ) + ( ctx->unprocessed_len != 0 || ilen % block_size ) ) { return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); } @@ -300,9 +307,9 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i * If there is not enough data for a full block, cache it. */ if( ( ctx->operation == MBEDTLS_DECRYPT && - ilen + ctx->unprocessed_len <= mbedtls_cipher_get_block_size( ctx ) ) || + ilen + ctx->unprocessed_len <= block_size ) || ( ctx->operation == MBEDTLS_ENCRYPT && - ilen + ctx->unprocessed_len < mbedtls_cipher_get_block_size( ctx ) ) ) + ilen + ctx->unprocessed_len < block_size ) ) { memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, ilen ); @@ -314,22 +321,22 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i /* * Process cached data first */ - if( ctx->unprocessed_len != 0 ) + if( 0 != ctx->unprocessed_len ) { - copy_len = mbedtls_cipher_get_block_size( ctx ) - ctx->unprocessed_len; + copy_len = block_size - ctx->unprocessed_len; memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, copy_len ); if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, - ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, + ctx->operation, block_size, ctx->iv, ctx->unprocessed_data, output ) ) ) { return( ret ); } - *olen += mbedtls_cipher_get_block_size( ctx ); - output += mbedtls_cipher_get_block_size( ctx ); + *olen += block_size; + output += block_size; ctx->unprocessed_len = 0; input += copy_len; @@ -341,9 +348,14 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i */ if( 0 != ilen ) { - copy_len = ilen % mbedtls_cipher_get_block_size( ctx ); + if( 0 == block_size ) + { + return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + } + + copy_len = ilen % block_size; if( copy_len == 0 && ctx->operation == MBEDTLS_DECRYPT ) - copy_len = mbedtls_cipher_get_block_size( ctx ); + copy_len = block_size; memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), copy_len ); diff --git a/library/debug.c b/library/debug.c index a032478da..a9cd814be 100644 --- a/library/debug.c +++ b/library/debug.c @@ -86,7 +86,7 @@ void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, char str[DEBUG_BUF_SIZE]; int ret; - if( ssl->conf == NULL || ssl->conf->f_dbg == NULL || level > debug_threshold ) + if( NULL == ssl || NULL == ssl->conf || NULL == ssl->conf->f_dbg || level > debug_threshold ) return; va_start( argp, format ); diff --git a/library/ecp.c b/library/ecp.c index 19bb4882e..f51f2251e 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1827,7 +1827,9 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, /* [M225] page 5 */ size_t b; - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); + } while( mbedtls_mpi_bitlen( d ) == 0); /* Make sure the most significant bit is nbits */ b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */ diff --git a/library/entropy.c b/library/entropy.c index cdbd35c34..282640f2d 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 @@ -27,6 +27,12 @@ #if defined(MBEDTLS_ENTROPY_C) +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +#warning "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! ****" +#warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES ****" +#warning "**** NOT SUITABLE FOR PRODUCTION ****" +#endif + #include "mbedtls/entropy.h" #include "mbedtls/entropy_poll.h" @@ -73,6 +79,11 @@ void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) mbedtls_havege_init( &ctx->havege_data ); #endif +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, + 1, MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif + #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, @@ -94,6 +105,11 @@ void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) 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 +288,18 @@ int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) 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 +374,27 @@ exit: 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 e2f45c78a..a116e605d 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) @@ -188,6 +191,23 @@ int mbedtls_platform_entropy_poll( void *data, #endif /* _WIN32 && !EFIX64 && !EFI32 */ #endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + ((void) data); + ((void) output); + *olen = 0; + + if( len < sizeof(unsigned char) ) + return( 0 ); + + *olen = sizeof(unsigned char); + + return( 0 ); +} +#endif + #if defined(MBEDTLS_TIMING_C) int mbedtls_hardclock_poll( void *data, unsigned char *output, size_t len, size_t *olen ) @@ -222,4 +242,27 @@ int mbedtls_havege_poll( void *data, } #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/error.c b/library/error.c index 4718b514d..4bd15bfee 100644 --- a/library/error.c +++ b/library/error.c @@ -183,6 +183,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" ); if( use_ret == -(MBEDTLS_ERR_CIPHER_AUTH_FAILED) ) mbedtls_snprintf( buf, buflen, "CIPHER - Authentication failed (for AEAD modes)" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT) ) + mbedtls_snprintf( buf, buflen, "CIPHER - The context is invalid, eg because it was free()ed" ); #endif /* MBEDTLS_CIPHER_C */ #if defined(MBEDTLS_DHM_C) diff --git a/library/platform.c b/library/platform.c index 89a2bd65d..68ca45d10 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 @@ int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* time } #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/ssl_tls.c b/library/ssl_tls.c index 9208ec9c8..80a908d9c 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -5773,7 +5773,7 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, { mbedtls_ecjpake_role role; - if( ssl->handshake == NULL && ssl->conf == NULL ) + if( ssl->handshake == NULL || ssl->conf == NULL ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) diff --git a/library/version_features.c b/library/version_features.c index b852ca81a..5d20ba019 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -66,6 +66,9 @@ static const char *features[] = { #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 */ @@ -156,6 +159,9 @@ static const char *features[] = { #if defined(MBEDTLS_AES_DECRYPT_ALT) "MBEDTLS_AES_DECRYPT_ALT", #endif /* MBEDTLS_AES_DECRYPT_ALT */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + "MBEDTLS_TEST_NULL_ENTROPY", +#endif /* MBEDTLS_TEST_NULL_ENTROPY */ #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) "MBEDTLS_ENTROPY_HARDWARE_ALT", #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ @@ -291,6 +297,9 @@ static const char *features[] = { #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/library/x509_crt.c b/library/x509_crt.c index c3adf7c86..af6c2a4a5 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -970,7 +970,9 @@ int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *bu int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ) { int success = 0, first_error = 0, total_failed = 0; +#if defined(MBEDTLS_PEM_PARSE_C) int buf_format = MBEDTLS_X509_FORMAT_DER; +#endif /* * Check for valid input @@ -988,10 +990,12 @@ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, s { buf_format = MBEDTLS_X509_FORMAT_PEM; } -#endif if( buf_format == MBEDTLS_X509_FORMAT_DER ) return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#else + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#endif #if defined(MBEDTLS_PEM_PARSE_C) if( buf_format == MBEDTLS_X509_FORMAT_PEM ) @@ -1064,7 +1068,6 @@ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, s success = 1; } } -#endif /* MBEDTLS_PEM_PARSE_C */ if( success ) return( total_failed ); @@ -1072,6 +1075,7 @@ int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, s return( first_error ); else return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ); +#endif /* MBEDTLS_PEM_PARSE_C */ } #if defined(MBEDTLS_FS_IO) @@ -1353,6 +1357,14 @@ int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, p = buf; n = size; + if( NULL == crt ) + { + ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); + } + ret = mbedtls_snprintf( p, n, "%scert. version : %d\n", prefix, crt->version ); MBEDTLS_X509_SAFE_SNPRINTF; diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c index 102144eca..a14d20c10 100644 --- a/programs/aes/crypt_and_hash.c +++ b/programs/aes/crypt_and_hash.c @@ -184,7 +184,12 @@ int main( int argc, char *argv[] ) mbedtls_fprintf( stderr, "Message Digest '%s' not found\n", argv[5] ); goto exit; } - mbedtls_md_setup( &md_ctx, md_info, 1 ); + + if( mbedtls_md_setup( &md_ctx, md_info, 1 ) != 0 ) + { + mbedtls_fprintf( stderr, "mbedtls_md_setup failed\n" ); + goto exit; + } /* * Read the secret key and clean the command line. @@ -399,6 +404,15 @@ int main( int argc, char *argv[] ) goto exit; } + if( mbedtls_cipher_get_block_size( &cipher_ctx ) == 0 ) + { + mbedtls_fprintf( stderr, "Invalid cipher block size: 0. \n" ); + goto exit; + } + + /* + * Check the file size. + */ if( ( ( filesize - mbedtls_md_get_size( md_info ) ) % mbedtls_cipher_get_block_size( &cipher_ctx ) ) != 0 ) { diff --git a/programs/pkey/dh_client.c b/programs/pkey/dh_client.c index 230bf4d7c..8ebf34a77 100644 --- a/programs/pkey/dh_client.c +++ b/programs/pkey/dh_client.c @@ -125,6 +125,7 @@ int main( void ) ( ret = mbedtls_mpi_read_file( &rsa.E, 16, f ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n", ret ); + fclose( f ); goto exit; } diff --git a/programs/pkey/dh_genprime.c b/programs/pkey/dh_genprime.c index d30c73bf7..072fe138f 100644 --- a/programs/pkey/dh_genprime.c +++ b/programs/pkey/dh_genprime.c @@ -172,6 +172,7 @@ int main( int argc, char **argv ) ( ret = mbedtls_mpi_write_file( "G = ", &G, 16, fout ) != 0 ) ) { mbedtls_printf( " failed\n ! mbedtls_mpi_write_file returned %d\n\n", ret ); + fclose( fout ); goto exit; } diff --git a/programs/pkey/dh_server.c b/programs/pkey/dh_server.c index cb156f79b..7eef845df 100644 --- a/programs/pkey/dh_server.c +++ b/programs/pkey/dh_server.c @@ -132,6 +132,7 @@ int main( void ) ( ret = mbedtls_mpi_read_file( &rsa.QP, 16, f ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n", ret ); + fclose( f ); goto exit; } @@ -157,6 +158,7 @@ int main( void ) mbedtls_mpi_read_file( &dhm.G, 16, f ) != 0 ) { mbedtls_printf( " failed\n ! Invalid DH parameter file\n\n" ); + fclose( f ); goto exit; } diff --git a/programs/pkey/pk_sign.c b/programs/pkey/pk_sign.c index 322e8aff0..daf08a905 100644 --- a/programs/pkey/pk_sign.c +++ b/programs/pkey/pk_sign.c @@ -142,6 +142,7 @@ int main( int argc, char *argv[] ) if( fwrite( buf, 1, olen, f ) != olen ) { mbedtls_printf( "failed\n ! fwrite failed\n\n" ); + fclose( f ); goto exit; } diff --git a/programs/pkey/rsa_decrypt.c b/programs/pkey/rsa_decrypt.c index 57c672094..1cc013dbd 100644 --- a/programs/pkey/rsa_decrypt.c +++ b/programs/pkey/rsa_decrypt.c @@ -125,6 +125,7 @@ int main( int argc, char *argv[] ) exit_val = MBEDTLS_EXIT_FAILURE; mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n", return_val ); + fclose( f ); goto exit; } diff --git a/programs/pkey/rsa_encrypt.c b/programs/pkey/rsa_encrypt.c index e78e27309..b9cb18765 100644 --- a/programs/pkey/rsa_encrypt.c +++ b/programs/pkey/rsa_encrypt.c @@ -118,6 +118,7 @@ int main( int argc, char *argv[] ) exit_val = MBEDTLS_EXIT_FAILURE; mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n", return_val ); + fclose( f ); goto exit; } diff --git a/programs/pkey/rsa_sign.c b/programs/pkey/rsa_sign.c index 27f356632..affbf7afc 100644 --- a/programs/pkey/rsa_sign.c +++ b/programs/pkey/rsa_sign.c @@ -97,6 +97,7 @@ int main( int argc, char *argv[] ) ( ret = mbedtls_mpi_read_file( &rsa.QP, 16, f ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n", ret ); + fclose( f ); goto exit; } diff --git a/programs/pkey/rsa_sign_pss.c b/programs/pkey/rsa_sign_pss.c index c045a04c1..7b6f14dd8 100644 --- a/programs/pkey/rsa_sign_pss.c +++ b/programs/pkey/rsa_sign_pss.c @@ -153,6 +153,7 @@ int main( int argc, char *argv[] ) if( fwrite( buf, 1, olen, f ) != olen ) { mbedtls_printf( "failed\n ! fwrite failed\n\n" ); + fclose( f ); goto exit; } diff --git a/programs/pkey/rsa_verify.c b/programs/pkey/rsa_verify.c index a22b55521..1f827aa07 100644 --- a/programs/pkey/rsa_verify.c +++ b/programs/pkey/rsa_verify.c @@ -89,6 +89,7 @@ int main( int argc, char *argv[] ) ( ret = mbedtls_mpi_read_file( &rsa.E, 16, f ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n", ret ); + fclose( f ); goto exit; } diff --git a/programs/test/selftest.c b/programs/test/selftest.c index e57a78e5a..00aa5c6c4 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -397,6 +397,7 @@ int main( int argc, char *argv[] ) if( suites_failed > 0) mbedtls_exit( MBEDTLS_EXIT_FAILURE ); + /* return() is here to prevent compiler warnings */ return( MBEDTLS_EXIT_SUCCESS ); } diff --git a/scripts/config.pl b/scripts/config.pl index a6dcfe7d7..84ec38ed7 100755 --- a/scripts/config.pl +++ b/scripts/config.pl @@ -18,6 +18,7 @@ # # Things that shouldn't be enabled with "full". # +# MBEDTLS_TEST_NULL_ENTROPY # MBEDTLS_DEPRECATED_REMOVED # MBEDTLS_HAVE_SSE2 # MBEDTLS_PLATFORM_NO_STD_FUNCTIONS @@ -69,6 +70,7 @@ Options EOU my @excluded = qw( +MBEDTLS_TEST_NULL_ENTROPY MBEDTLS_DEPRECATED_REMOVED MBEDTLS_HAVE_SSE2 MBEDTLS_PLATFORM_NO_STD_FUNCTIONS diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index c3b708f03..469827e11 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -266,6 +266,22 @@ scripts/config.pl unset MBEDTLS_NET_C # getaddrinfo() undeclared, etc. scripts/config.pl set MBEDTLS_NO_PLATFORM_ENTROPY # uses syscall() on GNU/Linux CC=gcc CFLAGS='-Werror -O0 -std=c99 -pedantic' make lib +msg "build: default config with MBEDTLS_TEST_NULL_ENTROPY (ASan build)" +cleanup +cp "$CONFIG_H" "$CONFIG_BAK" +scripts/config.pl set MBEDTLS_TEST_NULL_ENTROPY +scripts/config.pl set MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +scripts/config.pl set MBEDTLS_ENTROPY_C +scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED +scripts/config.pl unset MBEDTLS_ENTROPY_HARDWARE_ALT +scripts/config.pl unset MBEDTLS_HAVEGE_C +CC=gcc cmake -D CMAKE_C_FLAGS:String="-fsanitize=address -fno-common -O3" . +make + +msg "test: MBEDTLS_TEST_NULL_ENTROPY - main suites and selftest (ASan build)" +make test +programs/test/selftest + if uname -a | grep -F Linux >/dev/null; then msg "build/test: make shared" # ~ 40s cleanup diff --git a/tests/scripts/basic-build-test.sh b/tests/scripts/basic-build-test.sh index 010c0c67f..9fab39637 100755 --- a/tests/scripts/basic-build-test.sh +++ b/tests/scripts/basic-build-test.sh @@ -36,10 +36,13 @@ if [ -d library -a -d include -a -d tests ]; then :; else exit 1 fi +CONFIG_H='include/mbedtls/config.h' +CONFIG_BAK="$CONFIG_H.bak" # Step 1 - Make and instrumented build for code coverage export CFLAGS=' --coverage -g3 -O0 ' make clean +cp "$CONFIG_H" "$CONFIG_BAK" scripts/config.pl full scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE make -j @@ -204,3 +207,9 @@ rm compat-test-$TEST_OUTPUT rm cov-$TEST_OUTPUT cd .. + +make clean + +if [ -f "$CONFIG_BAK" ]; then + mv "$CONFIG_BAK" "$CONFIG_H" +fi diff --git a/tests/suites/test_suite_entropy.data b/tests/suites/test_suite_entropy.data index 833eef565..5ca99f85c 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_threshold:16:0:MBEDTLS_ERR_ENTROPY_SOURCE_FAILED 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 3b739cce9..d1ef94b6e 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 @@ static int entropy_dummy_source( void *data, unsigned char *output, 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 @@ void entropy_threshold( int threshold, int chunk_size, int result ) 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 @@ exit: } /* 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( ) {