From 5e769522359e3b07167f9d1696c971cd5d19fc6e Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Tue, 20 Nov 2018 21:59:56 +0100 Subject: [PATCH] Add a facility to configure entropy sources Add a function to configure entropy sources. For testing only. Use it to test that the library initialization fails properly if there is no entropy source. --- library/psa_crypto.c | 25 ++++- library/psa_crypto_invasive.h | 79 ++++++++++++++++ tests/suites/test_suite_psa_crypto_init.data | 6 ++ .../test_suite_psa_crypto_init.function | 93 +++++++++++++++++++ 4 files changed, 200 insertions(+), 3 deletions(-) create mode 100644 library/psa_crypto_invasive.h diff --git a/library/psa_crypto.c b/library/psa_crypto.c index 4c0ac1213..f4c87d3e2 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -43,6 +43,7 @@ #include "psa/crypto.h" +#include "psa_crypto_invasive.h" /* Include internal declarations that are useful for implementing persistently * stored keys. */ #include "psa_crypto_storage.h" @@ -155,6 +156,8 @@ enum rng_state typedef struct { + void (* entropy_init )( mbedtls_entropy_context *ctx ); + void (* entropy_free )( mbedtls_entropy_context *ctx ); mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; key_slot_t key_slots[PSA_KEY_SLOT_COUNT]; @@ -4437,6 +4440,17 @@ psa_status_t psa_generate_key( psa_key_slot_t key, /* Module setup */ /****************************************************************/ +psa_status_t mbedtls_psa_crypto_configure_entropy_sources( + void (* entropy_init )( mbedtls_entropy_context *ctx ), + void (* entropy_free )( mbedtls_entropy_context *ctx ) ) +{ + if( global_data.rng_state != RNG_NOT_INITIALIZED ) + return( PSA_ERROR_BAD_STATE ); + global_data.entropy_init = entropy_init; + global_data.entropy_free = entropy_free; + return( PSA_SUCCESS ); +} + void mbedtls_psa_crypto_free( void ) { psa_key_slot_t key; @@ -4457,7 +4471,7 @@ void mbedtls_psa_crypto_free( void ) if( global_data.rng_state != RNG_NOT_INITIALIZED ) { mbedtls_ctr_drbg_free( &global_data.ctr_drbg ); - mbedtls_entropy_free( &global_data.entropy ); + global_data.entropy_free( &global_data.entropy ); } /* Wipe all remaining data, including configuration. * In particular, this sets all state indicator to the value @@ -4474,10 +4488,15 @@ psa_status_t psa_crypto_init( void ) if( global_data.initialized != 0 ) return( PSA_SUCCESS ); - mbedtls_zeroize( &global_data, sizeof( global_data ) ); + /* Set default configuration if + * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */ + if( global_data.entropy_init == NULL ) + global_data.entropy_init = mbedtls_entropy_init; + if( global_data.entropy_free == NULL ) + global_data.entropy_free = mbedtls_entropy_free; /* Initialize the random generator. */ - mbedtls_entropy_init( &global_data.entropy ); + global_data.entropy_init( &global_data.entropy ); mbedtls_ctr_drbg_init( &global_data.ctr_drbg ); global_data.rng_state = RNG_INITIALIZED; ret = mbedtls_ctr_drbg_seed( &global_data.ctr_drbg, diff --git a/library/psa_crypto_invasive.h b/library/psa_crypto_invasive.h new file mode 100644 index 000000000..642652a47 --- /dev/null +++ b/library/psa_crypto_invasive.h @@ -0,0 +1,79 @@ +/** + * \file psa_crypto_invasive.h + * + * \brief PSA cryptography module: invasive interfaces for test only. + * + * The interfaces in this file are intended for testing purposes only. + * They MUST NOT be made available to clients over IPC in integrations + * with isolation, and they SHOULD NOT be made available in library + * integrations except when building the library for testing. + */ +/* + * Copyright (C) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_INVASIVE_H +#define PSA_CRYPTO_INVASIVE_H + +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#else +#include "mbedtls/config.h" +#endif + +#include "psa/crypto.h" + +#include "mbedtls/entropy.h" + +/** \brief Configure entropy sources. + * + * This function may only be called before a call to psa_crypto_init(), + * or after a call to mbedtls_psa_crypto_free() and before any + * subsequent call to psa_crypto_init(). + * + * This function is only intended for test purposes. The functionality + * it provides is also useful for system integrators, but + * system integrators should configure entropy drivers instead of + * breaking through to the Mbed TLS API. + * + * \param entropy_init Function to initialize the entropy context + * and set up the desired entropy sources. + * It is called by psa_crypto_init(). + * By default this is mbedtls_entropy_init(). + * This function cannot report failures directly. + * To indicate a failure, set the entropy context + * to a state where mbedtls_entropy_func() will + * return an error. + * \param entropy_free Function to free the entropy context + * and associated resources. + * It is called by mbedtls_psa_crypto_free(). + * By default this is mbedtls_entropy_free(). + * + * \retval PSA_SUCCESS + * Success. + * \retval PSA_ERROR_NOT_PERMITTED + * The caller does not have the permission to configure + * entropy sources. + * \retval PSA_ERROR_BAD_STATE + * The library has already been initialized. + */ +psa_status_t mbedtls_psa_crypto_configure_entropy_sources( + void (* entropy_init )( mbedtls_entropy_context *ctx ), + void (* entropy_free )( mbedtls_entropy_context *ctx ) ); + +#endif /* PSA_CRYPTO_INVASIVE_H */ diff --git a/tests/suites/test_suite_psa_crypto_init.data b/tests/suites/test_suite_psa_crypto_init.data index e44111814..8ce044dc6 100644 --- a/tests/suites/test_suite_psa_crypto_init.data +++ b/tests/suites/test_suite_psa_crypto_init.data @@ -18,3 +18,9 @@ validate_module_init_generate_random:1 No key slot access after deinit validate_module_init_key_based:1 + +Custom entropy sources: all standard +custom_entropy_sources:0x0000ffff:PSA_SUCCESS + +Custom entropy sources: none +custom_entropy_sources:0:PSA_ERROR_INSUFFICIENT_ENTROPY diff --git a/tests/suites/test_suite_psa_crypto_init.function b/tests/suites/test_suite_psa_crypto_init.function index 7cb10c0a1..0957969d5 100644 --- a/tests/suites/test_suite_psa_crypto_init.function +++ b/tests/suites/test_suite_psa_crypto_init.function @@ -6,6 +6,73 @@ #endif #include "psa/crypto.h" +/* Some tests in this module configure entropy sources. */ +#include "psa_crypto_invasive.h" + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" + +#define ENTROPY_SOURCE_PLATFORM 0x00000001 +#define ENTROPY_SOURCE_TIMING 0x00000002 +#define ENTROPY_SOURCE_HAVEGE 0x00000004 +#define ENTROPY_SOURCE_HARDWARE 0x00000008 +#define ENTROPY_SOURCE_NV_SEED 0x00000010 +static uint32_t custom_entropy_sources_mask; + +/* This is a modified version of mbedtls_entropy_init() from entropy.c + * which chooses entropy sources dynamically. */ +static void custom_entropy_init( mbedtls_entropy_context *ctx ) +{ + ctx->source_count = 0; + memset( ctx->source, 0, sizeof( ctx->source ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + ctx->accumulator_started = 0; +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_init( &ctx->accumulator ); +#else + mbedtls_sha256_init( &ctx->accumulator ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_init( &ctx->havege_data ); +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + if( custom_entropy_sources_mask & ENTROPY_SOURCE_PLATFORM ) + mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, + MBEDTLS_ENTROPY_MIN_PLATFORM, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_TIMING_C) + if( custom_entropy_sources_mask & ENTROPY_SOURCE_TIMING ) + mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDCLOCK, + MBEDTLS_ENTROPY_SOURCE_WEAK ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + if( custom_entropy_sources_mask & ENTROPY_SOURCE_HAVEGE ) + mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data, + MBEDTLS_ENTROPY_MIN_HAVEGE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + if( custom_entropy_sources_mask & ENTROPY_SOURCE_HARDWARE ) + mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDWARE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + if( custom_entropy_sources_mask & ENTROPY_SOURCE_NV_SEED ) + mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, + MBEDTLS_ENTROPY_BLOCK_SIZE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); + ctx->initial_entropy_run = 0; +#endif +} + /* END_HEADER */ /* BEGIN_DEPENDENCIES @@ -75,3 +142,29 @@ void validate_module_init_key_based( int count ) TEST_ASSERT( status == PSA_ERROR_BAD_STATE ); } /* END_CASE */ + +/* BEGIN_CASE */ +void custom_entropy_sources( int sources_arg, int expected_init_status_arg ) +{ + psa_status_t expected_init_status = expected_init_status_arg; + int inited = 0; + uint8_t random[10] = { 0 }; + + custom_entropy_sources_mask = sources_arg; + TEST_ASSERT( mbedtls_psa_crypto_configure_entropy_sources( + custom_entropy_init, mbedtls_entropy_free ) == + PSA_SUCCESS ); + + TEST_ASSERT( psa_crypto_init( ) == expected_init_status ); + if( expected_init_status != PSA_SUCCESS ) + goto exit; + inited = 1; + + TEST_ASSERT( psa_generate_random( random, sizeof( random ) ) == + PSA_SUCCESS ); + +exit: + if( inited ) + mbedtls_psa_crypto_free( ); +} +/* END_CASE */