diff --git a/ChangeLog b/ChangeLog index 6ba9a5a3a..2e9bf1137 100644 --- a/ChangeLog +++ b/ChangeLog @@ -63,16 +63,64 @@ Changes * Reduce RAM consumption during session renegotiation by not storing the peer CRT chain and session ticket twice. -= mbed TLS 2.16.x branch released xxxx-xx-xx += mbed TLS 2.16.X branch released XXXX-XX-XX + +Security + * Fix potential memory overread when performing an ECDSA signature + operation. The overread only happens with cryptographically low + probability (of the order of 2^-n where n is the bitsize of the curve) + unless the RNG is broken, and could result in information disclosure or + denial of service (application crash or extra resource consumption). + Found by Auke Zeilstra and Peter Schwabe, using static analysis. + * To avoid a side channel vulnerability when parsing an RSA private key, + read all the CRT parameters from the DER structure rather than + reconstructing them. Found by Alejandro Cabrera Aldaya and Billy Bob + Brumley. Reported and fix contributed by Jack Lloyd. + ARMmbed/mbed-crypto#352 + +Bugfix + * Fix an unchecked call to mbedtls_md() in the x509write module. + += mbed TLS 2.16.4 branch released 2020-01-15 + +Security + * Fix side channel vulnerability in ECDSA. Our bignum implementation is not + constant time/constant trace, so side channel attacks can retrieve the + blinded value, factor it (as it is smaller than RSA keys and not guaranteed + to have only large prime factors), and then, by brute force, recover the + key. Reported by Alejandro Cabrera Aldaya and Billy Brumley. + * Zeroize local variables in mbedtls_internal_aes_encrypt() and + mbedtls_internal_aes_decrypt() before exiting the function. The value of + these variables can be used to recover the last round key. To follow best + practice and to limit the impact of buffer overread vulnerabilities (like + Heartbleed) we need to zeroize them before exiting the function. + Issue reported by Tuba Yavuz, Farhaan Fowze, Ken (Yihang) Bai, + Grant Hernandez, and Kevin Butler (University of Florida) and + Dave Tian (Purdue University). + * Fix side channel vulnerability in ECDSA key generation. Obtaining precise + timings on the comparison in the key generation enabled the attacker to + learn leading bits of the ephemeral key used during ECDSA signatures and to + recover the private key. Reported by Jeremy Dubeuf. + * Catch failure of AES functions in mbedtls_ctr_drbg_random(). Uncaught + failures could happen with alternative implementations of AES. Bug + reported and fix proposed by Johan Uppman Bruce and Christoffer Lauri, + Sectra. Bugfix * Remove redundant line for getting the bitlen of a bignum, since the variable holding the returned value is overwritten a line after. Found by irwir in #2377. + * Support mbedtls_hmac_drbg_set_entropy_len() and + mbedtls_ctr_drbg_set_entropy_len() before the DRBG is seeded. Before, + the initial seeding always reset the entropy length to the compile-time + default. Changes * Add unit tests for AES-GCM when called through mbedtls_cipher_auth_xxx() from the cipher abstraction layer. Fixes #2198. + * Clarify how the interface of the CTR_DRBG and HMAC modules relates to + NIST SP 800-90A. In particular CTR_DRBG requires an explicit nonce + to achieve a 256-bit strength if MBEDTLS_ENTROPY_FORCE_SHA256 is set. = mbed TLS 2.16.3 branch released 2019-09-06 diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h index a6126f3be..de43cdfb5 100644 --- a/doxygen/input/doc_mainpage.h +++ b/doxygen/input/doc_mainpage.h @@ -24,7 +24,7 @@ */ /** - * @mainpage mbed TLS v2.16.3 source code documentation + * @mainpage mbed TLS v2.16.4 source code documentation * * This documentation describes the internal structure of mbed TLS. It was * automatically generated from specially formatted comment blocks in diff --git a/doxygen/mbedtls.doxyfile b/doxygen/mbedtls.doxyfile index 3fcc034e1..574552080 100644 --- a/doxygen/mbedtls.doxyfile +++ b/doxygen/mbedtls.doxyfile @@ -28,7 +28,7 @@ DOXYFILE_ENCODING = UTF-8 # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. -PROJECT_NAME = "mbed TLS v2.16.3" +PROJECT_NAME = "mbed TLS v2.16.4" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or diff --git a/include/mbedtls/bignum.h b/include/mbedtls/bignum.h index 1c8607264..22b373113 100644 --- a/include/mbedtls/bignum.h +++ b/include/mbedtls/bignum.h @@ -184,7 +184,7 @@ extern "C" { */ typedef struct mbedtls_mpi { - int s; /*!< integer sign */ + int s; /*!< Sign: -1 if the mpi is negative, 1 otherwise */ size_t n; /*!< total # of limbs */ mbedtls_mpi_uint *p; /*!< pointer to limbs */ } @@ -559,6 +559,24 @@ int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); */ int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); +/** + * \brief Check if an MPI is less than the other in constant time. + * + * \param X The left-hand MPI. This must point to an initialized MPI + * with the same allocated length as Y. + * \param Y The right-hand MPI. This must point to an initialized MPI + * with the same allocated length as X. + * \param ret The result of the comparison: + * \c 1 if \p X is less than \p Y. + * \c 0 if \p X is greater than or equal to \p Y. + * + * \return 0 on success. + * \return MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the allocated length of + * the two input MPIs is not the same. + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, + unsigned *ret ); + /** * \brief Compare an MPI with an integer. * diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 347a8fa81..4ee592062 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -747,6 +747,13 @@ #define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN #define MBEDTLS_CIPHER_PADDING_ZEROS +/** \def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + * + * Uncomment this macro to use a 128-bit key in the CTR_DRBG module. + * By default, CTR_DRBG uses a 256-bit key. + */ +//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + /** * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES * @@ -2516,7 +2523,11 @@ * * Enable the CTR_DRBG AES-based random generator. * The CTR_DRBG generator uses AES-256 by default. - * To use AES-128 instead, enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY below. + * To use AES-128 instead, enable \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above. + * + * \note To achieve a 256-bit security strength with CTR_DRBG, + * you must use AES-256 *and* use sufficient entropy. + * See ctr_drbg.h for more details. * * Module: library/ctr_drbg.c * Caller: @@ -3434,7 +3445,6 @@ //#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ //#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ //#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ -//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY /**< Use 128-bit key for CTR_DRBG - may reduce security (see ctr_drbg.h) */ /* HMAC_DRBG options */ //#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ diff --git a/include/mbedtls/ctr_drbg.h b/include/mbedtls/ctr_drbg.h index cc3df7b11..e0b5ed9c9 100644 --- a/include/mbedtls/ctr_drbg.h +++ b/include/mbedtls/ctr_drbg.h @@ -1,7 +1,8 @@ /** * \file ctr_drbg.h * - * \brief This file contains CTR_DRBG definitions and functions. + * \brief This file contains definitions and functions for the + * CTR_DRBG pseudorandom generator. * * CTR_DRBG is a standardized way of building a PRNG from a block-cipher * in counter mode operation, as defined in NIST SP 800-90A: @@ -9,13 +10,35 @@ * Bit Generators. * * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128 - * as the underlying block cipher. + * (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time) + * as the underlying block cipher, with a derivation function. + * The initial seeding grabs #MBEDTLS_CTR_DRBG_ENTROPY_LEN bytes of entropy. + * See the documentation of mbedtls_ctr_drbg_seed() for more details. * - * \warning Using 128-bit keys for CTR_DRBG limits the security of generated - * keys and operations that use random values generated to 128-bit security. + * Based on NIST SP 800-90A §10.2.1 table 3 and NIST SP 800-57 part 1 table 2, + * here are the security strengths achieved in typical configuration: + * - 256 bits under the default configuration of the library, with AES-256 + * and with #MBEDTLS_CTR_DRBG_ENTROPY_LEN set to 48 or more. + * - 256 bits if AES-256 is used, #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set + * to 32 or more, and the DRBG is initialized with an explicit + * nonce in the \c custom parameter to mbedtls_ctr_drbg_seed(). + * - 128 bits if AES-256 is used but #MBEDTLS_CTR_DRBG_ENTROPY_LEN is + * between 24 and 47 and the DRBG is not initialized with an explicit + * nonce (see mbedtls_ctr_drbg_seed()). + * - 128 bits if AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled) + * and #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set to 24 or more (which is + * always the case unless it is explicitly set to a different value + * in config.h). + * + * Note that the value of #MBEDTLS_CTR_DRBG_ENTROPY_LEN defaults to: + * - \c 48 if the module \c MBEDTLS_SHA512_C is enabled and the symbol + * \c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled at compile time. + * This is the default configuration of the library. + * - \c 32 if the module \c MBEDTLS_SHA512_C is disabled at compile time. + * - \c 32 if \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled at compile time. */ /* - * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright (C) 2006-2019, Arm Limited (or its affiliates), All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -56,9 +79,19 @@ #define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) -#define MBEDTLS_CTR_DRBG_KEYSIZE 16 /**< The key size used by the cipher (compile-time choice: 128 bits). */ +#define MBEDTLS_CTR_DRBG_KEYSIZE 16 +/**< The key size in bytes used by the cipher. + * + * Compile-time choice: 16 bytes (128 bits) + * because #MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled. + */ #else -#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher (compile-time choice: 256 bits). */ +#define MBEDTLS_CTR_DRBG_KEYSIZE 32 +/**< The key size in bytes used by the cipher. + * + * Compile-time choice: 32 bytes (256 bits) + * because \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled. + */ #endif #define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */ @@ -73,21 +106,31 @@ * \{ */ +/** \def MBEDTLS_CTR_DRBG_ENTROPY_LEN + * + * \brief The amount of entropy used per seed by default, in bytes. + */ #if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) #if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +/** This is 48 bytes because the entropy module uses SHA-512 + * (\c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled). + */ #define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 -/**< The amount of entropy used per seed by default: - * + +#else /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ + +/** This is 32 bytes because the entropy module uses SHA-256 + * (the SHA512 module is disabled or + * \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled). */ -#else +#if !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +/** \warning To achieve a 256-bit security strength, you must pass a nonce + * to mbedtls_ctr_drbg_seed(). + */ +#endif /* !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) */ #define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 -/**< Amount of entropy used per seed by default: - * - */ -#endif -#endif +#endif /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ +#endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */ #if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) #define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 @@ -106,7 +149,7 @@ #if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) #define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 -/**< The maximum size of seed or reseed buffer. */ +/**< The maximum size of seed or reseed buffer in bytes. */ #endif /* \} name SECTION: Module settings */ @@ -164,17 +207,68 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); * \brief This function seeds and sets up the CTR_DRBG * entropy source for future reseeds. * - * \note Personalization data can be provided in addition to the more generic - * entropy source, to make this instantiation as unique as possible. + * A typical choice for the \p f_entropy and \p p_entropy parameters is + * to use the entropy module: + * - \p f_entropy is mbedtls_entropy_func(); + * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized + * with mbedtls_entropy_init() (which registers the platform's default + * entropy sources). * + * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default. + * You can override it by calling mbedtls_ctr_drbg_set_entropy_len(). + * + * You can provide a personalization string in addition to the + * entropy source, to make this instantiation as unique as possible. + * + * \note The _seed_material_ value passed to the derivation + * function in the CTR_DRBG Instantiate Process + * described in NIST SP 800-90A §10.2.1.3.2 + * is the concatenation of the string obtained from + * calling \p f_entropy and the \p custom string. + * The origin of the nonce depends on the value of + * the entropy length relative to the security strength. + * - If the entropy length is at least 1.5 times the + * security strength then the nonce is taken from the + * string obtained with \p f_entropy. + * - If the entropy length is less than the security + * strength, then the nonce is taken from \p custom. + * In this case, for compliance with SP 800-90A, + * you must pass a unique value of \p custom at + * each invocation. See SP 800-90A §8.6.7 for more + * details. + */ +#if MBEDTLS_CTR_DRBG_ENTROPY_LEN < MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 +/** \warning When #MBEDTLS_CTR_DRBG_ENTROPY_LEN is less than + * #MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2, to achieve the + * maximum security strength permitted by CTR_DRBG, + * you must pass a value of \p custom that is a nonce: + * this value must never be repeated in subsequent + * runs of the same application or on a different + * device. + */ +#endif +/** * \param ctx The CTR_DRBG context to seed. + * It must have been initialized with + * mbedtls_ctr_drbg_init(). + * After a successful call to mbedtls_ctr_drbg_seed(), + * you may not call mbedtls_ctr_drbg_seed() again on + * the same context unless you call + * mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init() + * again first. * \param f_entropy The entropy callback, taking as arguments the * \p p_entropy context, the buffer to fill, and the - length of the buffer. - * \param p_entropy The entropy context. - * \param custom Personalization data, that is device-specific - identifiers. Can be NULL. - * \param len The length of the personalization data. + * length of the buffer. + * \p f_entropy is always called with a buffer size + * equal to the entropy length. + * \param p_entropy The entropy context to pass to \p f_entropy. + * \param custom The personalization string. + * This can be \c NULL, in which case the personalization + * string is empty regardless of the value of \p len. + * \param len The length of the personalization string. + * This must be at most + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + * - #MBEDTLS_CTR_DRBG_ENTROPY_LEN. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. @@ -197,7 +291,8 @@ void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); * The default value is off. * * \note If enabled, entropy is gathered at the beginning of - * every call to mbedtls_ctr_drbg_random_with_add(). + * every call to mbedtls_ctr_drbg_random_with_add() + * or mbedtls_ctr_drbg_random(). * Only use this if your entropy source has sufficient * throughput. * @@ -209,18 +304,37 @@ void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, /** * \brief This function sets the amount of entropy grabbed on each - * seed or reseed. The default value is - * #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * seed or reseed. + * + * The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \note The security strength of CTR_DRBG is bounded by the + * entropy length. Thus: + * - When using AES-256 + * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled, + * which is the default), + * \p len must be at least 32 (in bytes) + * to achieve a 256-bit strength. + * - When using AES-128 + * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled) + * \p len must be at least 16 (in bytes) + * to achieve a 128-bit strength. * * \param ctx The CTR_DRBG context. - * \param len The amount of entropy to grab. + * \param len The amount of entropy to grab, in bytes. + * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. */ void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len ); /** * \brief This function sets the reseed interval. - * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL. + * + * The reseed interval is the number of calls to mbedtls_ctr_drbg_random() + * or mbedtls_ctr_drbg_random_with_add() after which the entropy function + * is called again. + * + * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL. * * \param ctx The CTR_DRBG context. * \param interval The reseed interval. @@ -233,8 +347,12 @@ void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, * extracts data from the entropy source. * * \param ctx The CTR_DRBG context. - * \param additional Additional data to add to the state. Can be NULL. + * \param additional Additional data to add to the state. Can be \c NULL. * \param len The length of the additional data. + * This must be less than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len + * where \c entropy_len is the entropy length + * configured for the context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. @@ -246,7 +364,8 @@ int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, * \brief This function updates the state of the CTR_DRBG context. * * \param ctx The CTR_DRBG context. - * \param additional The data to update the state with. + * \param additional The data to update the state with. This must not be + * \c NULL unless \p add_len is \c 0. * \param add_len Length of \p additional in bytes. This must be at * most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. * @@ -264,14 +383,23 @@ int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, * \brief This function updates a CTR_DRBG instance with additional * data and uses it to generate random data. * - * \note The function automatically reseeds if the reseed counter is exceeded. + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. * * \param p_rng The CTR_DRBG context. This must be a pointer to a * #mbedtls_ctr_drbg_context structure. * \param output The buffer to fill. - * \param output_len The length of the buffer. - * \param additional Additional data to update. Can be NULL. - * \param add_len The length of the additional data. + * \param output_len The length of the buffer in bytes. + * \param additional Additional data to update. Can be \c NULL, in which + * case the additional data is empty regardless of + * the value of \p add_len. + * \param add_len The length of the additional data + * if \p additional is not \c NULL. + * This must be less than #MBEDTLS_CTR_DRBG_MAX_INPUT + * and less than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len + * where \c entropy_len is the entropy length + * configured for the context. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or @@ -284,12 +412,14 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng, /** * \brief This function uses CTR_DRBG to generate random data. * - * \note The function automatically reseeds if the reseed counter is exceeded. + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * * * \param p_rng The CTR_DRBG context. This must be a pointer to a * #mbedtls_ctr_drbg_context structure. * \param output The buffer to fill. - * \param output_len The length of the buffer. + * \param output_len The length of the buffer in bytes. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or @@ -336,7 +466,7 @@ MBEDTLS_DEPRECATED void mbedtls_ctr_drbg_update( * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. - * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on reseed * failure. */ int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); @@ -350,8 +480,10 @@ int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char * * \return \c 0 on success. * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. - * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or - * #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG on failure. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on + * reseed failure. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if the existing + * seed file is too large. */ int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); #endif /* MBEDTLS_FS_IO */ diff --git a/include/mbedtls/hmac_drbg.h b/include/mbedtls/hmac_drbg.h index f38337aa7..eec05e471 100644 --- a/include/mbedtls/hmac_drbg.h +++ b/include/mbedtls/hmac_drbg.h @@ -1,10 +1,14 @@ /** * \file hmac_drbg.h * - * \brief HMAC_DRBG (NIST SP 800-90A) + * \brief The HMAC_DRBG pseudorandom generator. + * + * This module implements the HMAC_DRBG pseudorandom generator described + * in NIST SP 800-90A: Recommendation for Random Number Generation Using + * Deterministic Random Bit Generators. */ /* - * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2006-2019, ARM Limited, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -104,38 +108,72 @@ typedef struct mbedtls_hmac_drbg_context } mbedtls_hmac_drbg_context; /** - * \brief HMAC_DRBG context initialization - * Makes the context ready for mbedtls_hmac_drbg_seed(), - * mbedtls_hmac_drbg_seed_buf() or - * mbedtls_hmac_drbg_free(). + * \brief HMAC_DRBG context initialization. * - * \param ctx HMAC_DRBG context to be initialized + * This function makes the context ready for mbedtls_hmac_drbg_seed(), + * mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free(). + * + * \param ctx HMAC_DRBG context to be initialized. */ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); /** - * \brief HMAC_DRBG initial seeding - * Seed and setup entropy source for future reseeds. + * \brief HMAC_DRBG initial seeding. * - * \param ctx HMAC_DRBG context to be seeded - * \param md_info MD algorithm to use for HMAC_DRBG - * \param f_entropy Entropy callback (p_entropy, buffer to fill, buffer - * length) - * \param p_entropy Entropy context - * \param custom Personalization data (Device specific identifiers) - * (Can be NULL) - * \param len Length of personalization data + * Set the initial seed and set up the entropy source for future reseeds. * - * \note The "security strength" as defined by NIST is set to: - * 128 bits if md_alg is SHA-1, - * 192 bits if md_alg is SHA-224, - * 256 bits if md_alg is SHA-256 or higher. + * A typical choice for the \p f_entropy and \p p_entropy parameters is + * to use the entropy module: + * - \p f_entropy is mbedtls_entropy_func(); + * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized + * with mbedtls_entropy_init() (which registers the platform's default + * entropy sources). + * + * You can provide a personalization string in addition to the + * entropy source, to make this instantiation as unique as possible. + * + * \note By default, the security strength as defined by NIST is: + * - 128 bits if \p md_info is SHA-1; + * - 192 bits if \p md_info is SHA-224; + * - 256 bits if \p md_info is SHA-256, SHA-384 or SHA-512. * Note that SHA-256 is just as efficient as SHA-224. + * The security strength can be reduced if a smaller + * entropy length is set with + * mbedtls_hmac_drbg_set_entropy_len(). * - * \return 0 if successful, or - * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or - * MBEDTLS_ERR_MD_ALLOC_FAILED, or - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED. + * \note The default entropy length is the security strength + * (converted from bits to bytes). You can override + * it by calling mbedtls_hmac_drbg_set_entropy_len(). + * + * \note During the initial seeding, this function calls + * the entropy source to obtain a nonce + * whose length is half the entropy length. + * + * \param ctx HMAC_DRBG context to be seeded. + * \param md_info MD algorithm to use for HMAC_DRBG. + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + * length of the buffer. + * \p f_entropy is always called with a length that is + * less than or equal to the entropy length. + * \param p_entropy The entropy context to pass to \p f_entropy. + * \param custom The personalization string. + * This can be \c NULL, in which case the personalization + * string is empty regardless of the value of \p len. + * \param len The length of the personalization string. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT + * and also at most + * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len * 3 / 2 + * where \p entropy_len is the entropy length + * described above. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is + * invalid. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough + * memory to allocate context data. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if the call to \p f_entropy failed. */ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, mbedtls_md_handle_t md_info, @@ -146,100 +184,134 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, /** * \brief Initilisation of simpified HMAC_DRBG (never reseeds). - * (For use with deterministic ECDSA.) * - * \param ctx HMAC_DRBG context to be initialised - * \param md_info MD algorithm to use for HMAC_DRBG - * \param data Concatenation of entropy string and additional data - * \param data_len Length of data in bytes + * This function is meant for use in algorithms that need a pseudorandom + * input such as deterministic ECDSA. * - * \return 0 if successful, or - * MBEDTLS_ERR_MD_BAD_INPUT_DATA, or - * MBEDTLS_ERR_MD_ALLOC_FAILED. + * \param ctx HMAC_DRBG context to be initialised. + * \param md_info MD algorithm to use for HMAC_DRBG. + * \param data Concatenation of the initial entropy string and + * the additional data. + * \param data_len Length of \p data in bytes. + * + * \return \c 0 if successful. or + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is + * invalid. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough + * memory to allocate context data. */ int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, mbedtls_md_handle_t md_info, const unsigned char *data, size_t data_len ); /** - * \brief Enable / disable prediction resistance (Default: Off) + * \brief This function turns prediction resistance on or off. + * The default value is off. * - * Note: If enabled, entropy is used for ctx->entropy_len before each call! - * Only use this if you have ample supply of good entropy! + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_hmac_drbg_random_with_add() + * or mbedtls_hmac_drbg_random(). + * Only use this if your entropy source has sufficient + * throughput. * - * \param ctx HMAC_DRBG context - * \param resistance MBEDTLS_HMAC_DRBG_PR_ON or MBEDTLS_HMAC_DRBG_PR_OFF + * \param ctx The HMAC_DRBG context. + * \param resistance #MBEDTLS_HMAC_DRBG_PR_ON or #MBEDTLS_HMAC_DRBG_PR_OFF. */ void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, int resistance ); /** - * \brief Set the amount of entropy grabbed on each reseed - * (Default: given by the security strength, which - * depends on the hash used, see \c mbedtls_hmac_drbg_init() ) + * \brief This function sets the amount of entropy grabbed on each + * seed or reseed. * - * \param ctx HMAC_DRBG context - * \param len Amount of entropy to grab, in bytes + * See the documentation of mbedtls_hmac_drbg_seed() for the default value. + * + * \param ctx The HMAC_DRBG context. + * \param len The amount of entropy to grab, in bytes. */ void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len ); /** - * \brief Set the reseed interval - * (Default: MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) + * \brief Set the reseed interval. * - * \param ctx HMAC_DRBG context - * \param interval Reseed interval + * The reseed interval is the number of calls to mbedtls_hmac_drbg_random() + * or mbedtls_hmac_drbg_random_with_add() after which the entropy function + * is called again. + * + * The default value is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL. + * + * \param ctx The HMAC_DRBG context. + * \param interval The reseed interval. */ void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval ); /** - * \brief HMAC_DRBG update state + * \brief This function updates the state of the HMAC_DRBG context. * - * \param ctx HMAC_DRBG context - * \param additional Additional data to update state with, or NULL - * \param add_len Length of additional data, or 0 + * \param ctx The HMAC_DRBG context. + * \param additional The data to update the state with. + * If this is \c NULL, there is no additional data. + * \param add_len Length of \p additional in bytes. + * Unused if \p additional is \c NULL. * * \return \c 0 on success, or an error from the underlying * hash calculation or * MBEDTLS_ERR_PLATFORM_FAULT_DETECTED. - * - * \note Additional data is optional, pass NULL and 0 as second - * third argument if no additional data is being used. */ int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t add_len ); /** - * \brief HMAC_DRBG reseeding (extracts data from entropy source) + * \brief This function reseeds the HMAC_DRBG context, that is + * extracts data from the entropy source. * - * \param ctx HMAC_DRBG context - * \param additional Additional data to add to state (Can be NULL) - * \param len Length of additional data + * \param ctx The HMAC_DRBG context. + * \param additional Additional data to add to the state. + * If this is \c NULL, there is no additional data + * and \p len should be \c 0. + * \param len The length of the additional data. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT + * and also at most + * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len + * where \p entropy_len is the entropy length + * (see mbedtls_hmac_drbg_set_entropy_len()). * - * \return 0 if successful, or - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy function failed. */ int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, const unsigned char *additional, size_t len ); /** - * \brief HMAC_DRBG generate random with additional update input + * \brief This function updates an HMAC_DRBG instance with additional + * data and uses it to generate random data. * - * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. * - * \param p_rng HMAC_DRBG context - * \param output Buffer to fill - * \param output_len Length of the buffer - * \param additional Additional data to update with (can be NULL) - * \param add_len Length of additional data (can be 0) + * \param p_rng The HMAC_DRBG context. This must be a pointer to a + * #mbedtls_hmac_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * \param additional Additional data to update with. + * If this is \c NULL, there is no additional data + * and \p add_len should be \c 0. + * \param add_len The length of the additional data. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT. * - * \return 0 if successful, or - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or - * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or - * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG, or - * MBEDTLS_ERR_PLATFORM_FAULT_DETECTED. + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy source failed. + * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if + * \p output_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if + * \p add_len > #MBEDTLS_HMAC_DRBG_MAX_INPUT. + * \return #MBEDTLS_ERR_PLATFORM_FAULT_DETECTED if + * a logical fault is detected. */ int mbedtls_hmac_drbg_random_with_add( void *p_rng, unsigned char *output, size_t output_len, @@ -247,26 +319,31 @@ int mbedtls_hmac_drbg_random_with_add( void *p_rng, size_t add_len ); /** - * \brief HMAC_DRBG generate random + * \brief This function uses HMAC_DRBG to generate random data. * - * Note: Automatically reseeds if reseed_counter is reached or PR is enabled. + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. * - * \param p_rng HMAC_DRBG context - * \param output Buffer to fill - * \param out_len Length of the buffer + * \param p_rng The HMAC_DRBG context. This must be a pointer to a + * #mbedtls_hmac_drbg_context structure. + * \param output The buffer to fill. + * \param out_len The length of the buffer in bytes. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. * - * \return 0 if successful, or - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or - * MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG, - * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG, or - * MBEDTLS_ERR_PLATFORM_FAULT_DETECTED. + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy source failed. + * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if + * \p out_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * \return #MBEDTLS_ERR_PLATFORM_FAULT_DETECTED if + * a logical fault is detected. */ int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); /** * \brief Free an HMAC_DRBG context * - * \param ctx HMAC_DRBG context to free. + * \param ctx The HMAC_DRBG context to free. */ void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); @@ -277,17 +354,16 @@ void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); #define MBEDTLS_DEPRECATED #endif /** - * \brief HMAC_DRBG update state + * \brief This function updates the state of the HMAC_DRBG context. * * \deprecated Superseded by mbedtls_hmac_drbg_update_ret() * in 2.16.0. * - * \param ctx HMAC_DRBG context - * \param additional Additional data to update state with, or NULL - * \param add_len Length of additional data, or 0 - * - * \note Additional data is optional, pass NULL and 0 as second - * third argument if no additional data is being used. + * \param ctx The HMAC_DRBG context. + * \param additional The data to update the state with. + * If this is \c NULL, there is no additional data. + * \param add_len Length of \p additional in bytes. + * Unused if \p additional is \c NULL. */ MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, @@ -297,26 +373,31 @@ MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update( #if defined(MBEDTLS_FS_IO) /** - * \brief Write a seed file + * \brief This function writes a seed file. * - * \param ctx HMAC_DRBG context - * \param path Name of the file + * \param ctx The HMAC_DRBG context. + * \param path The name of the file. * - * \return 0 if successful, 1 on file error, or - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * \return \c 0 on success. + * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on reseed + * failure. */ int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); /** - * \brief Read and update a seed file. Seed is added to this - * instance + * \brief This function reads and updates a seed file. The seed + * is added to this instance. * - * \param ctx HMAC_DRBG context - * \param path Name of the file + * \param ctx The HMAC_DRBG context. + * \param path The name of the file. * - * \return 0 if successful, 1 on file error, - * MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or - * MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG + * \return \c 0 on success. + * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on + * reseed failure. + * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if the existing + * seed file is too large. */ int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); #endif /* MBEDTLS_FS_IO */ @@ -324,9 +405,10 @@ int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const ch #if defined(MBEDTLS_SELF_TEST) /** - * \brief Checkup routine + * \brief The HMAC_DRBG Checkup routine. * - * \return 0 if successful, or 1 if the test failed + * \return \c 0 if successful. + * \return \c 1 if the test failed. */ int mbedtls_hmac_drbg_self_test( int verbose ); #endif diff --git a/include/mbedtls/version.h b/include/mbedtls/version.h index b4eef71e5..aeffb1669 100644 --- a/include/mbedtls/version.h +++ b/include/mbedtls/version.h @@ -40,16 +40,16 @@ */ #define MBEDTLS_VERSION_MAJOR 2 #define MBEDTLS_VERSION_MINOR 16 -#define MBEDTLS_VERSION_PATCH 3 +#define MBEDTLS_VERSION_PATCH 4 /** * The single version number has the following structure: * MMNNPP00 * Major version | Minor version | Patch version */ -#define MBEDTLS_VERSION_NUMBER 0x02100300 -#define MBEDTLS_VERSION_STRING "2.16.3" -#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.3" +#define MBEDTLS_VERSION_NUMBER 0x02100400 +#define MBEDTLS_VERSION_STRING "2.16.4" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.16.4" #if defined(MBEDTLS_VERSION_C) diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 0156856db..d5e34eb1b 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -162,15 +162,15 @@ endif(USE_STATIC_MBEDTLS_LIBRARY) if(USE_SHARED_MBEDTLS_LIBRARY) add_library(mbedcrypto SHARED ${src_crypto}) - set_target_properties(mbedcrypto PROPERTIES VERSION 2.16.3 SOVERSION 3) + set_target_properties(mbedcrypto PROPERTIES VERSION 2.16.4 SOVERSION 3) target_link_libraries(mbedcrypto ${libs}) add_library(mbedx509 SHARED ${src_x509}) - set_target_properties(mbedx509 PROPERTIES VERSION 2.16.3 SOVERSION 0) + set_target_properties(mbedx509 PROPERTIES VERSION 2.16.4 SOVERSION 0) target_link_libraries(mbedx509 ${libs} mbedcrypto) add_library(mbedtls SHARED ${src_tls}) - set_target_properties(mbedtls PROPERTIES VERSION 2.16.3 SOVERSION 12) + set_target_properties(mbedtls PROPERTIES VERSION 2.16.4 SOVERSION 12) target_link_libraries(mbedtls ${libs} mbedx509) install(TARGETS mbedtls mbedx509 mbedcrypto diff --git a/library/aes.c b/library/aes.c index 9098d4795..57469873f 100644 --- a/library/aes.c +++ b/library/aes.c @@ -1246,6 +1246,18 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, PUT_UINT32_LE( X2, output, 8 ); PUT_UINT32_LE( X3, output, 12 ); + mbedtls_platform_zeroize( &X0, sizeof( X0 ) ); + mbedtls_platform_zeroize( &X1, sizeof( X1 ) ); + mbedtls_platform_zeroize( &X2, sizeof( X2 ) ); + mbedtls_platform_zeroize( &X3, sizeof( X3 ) ); + + mbedtls_platform_zeroize( &Y0, sizeof( Y0 ) ); + mbedtls_platform_zeroize( &Y1, sizeof( Y1 ) ); + mbedtls_platform_zeroize( &Y2, sizeof( Y2 ) ); + mbedtls_platform_zeroize( &Y3, sizeof( Y3 ) ); + + mbedtls_platform_zeroize( &RK, sizeof( RK ) ); + return( 0 ); } #endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ @@ -1513,6 +1525,18 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, PUT_UINT32_LE( X2, output, 8 ); PUT_UINT32_LE( X3, output, 12 ); + mbedtls_platform_zeroize( &X0, sizeof( X0 ) ); + mbedtls_platform_zeroize( &X1, sizeof( X1 ) ); + mbedtls_platform_zeroize( &X2, sizeof( X2 ) ); + mbedtls_platform_zeroize( &X3, sizeof( X3 ) ); + + mbedtls_platform_zeroize( &Y0, sizeof( Y0 ) ); + mbedtls_platform_zeroize( &Y1, sizeof( Y1 ) ); + mbedtls_platform_zeroize( &Y2, sizeof( Y2 ) ); + mbedtls_platform_zeroize( &Y3, sizeof( Y3 ) ); + + mbedtls_platform_zeroize( &RK, sizeof( RK ) ); + return( 0 ); } #endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ diff --git a/library/bignum.c b/library/bignum.c index 842b38b8c..00df10d98 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -157,9 +157,10 @@ int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); - /* Actually resize up in this case */ + /* Actually resize up if there are currently fewer than nblimbs limbs. */ if( X->n <= nblimbs ) return( mbedtls_mpi_grow( X, nblimbs ) ); + /* After this point, then X->n > nblimbs and in particular X->n > 0. */ for( i = X->n - 1; i > 0; i-- ) if( X->p[i] != 0 ) @@ -198,7 +199,7 @@ int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) if( X == Y ) return( 0 ); - if( Y->p == NULL ) + if( Y->n == 0 ) { mbedtls_mpi_free( X ); return( 0 ); @@ -1071,6 +1072,107 @@ int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) return( 0 ); } +/** Decide if an integer is less than the other, without branches. + * + * \param x First integer. + * \param y Second integer. + * + * \return 1 if \p x is less than \p y, 0 otherwise + */ +static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x, + const mbedtls_mpi_uint y ) +{ + mbedtls_mpi_uint ret; + mbedtls_mpi_uint cond; + + /* + * Check if the most significant bits (MSB) of the operands are different. + */ + cond = ( x ^ y ); + /* + * If the MSB are the same then the difference x-y will be negative (and + * have its MSB set to 1 during conversion to unsigned) if and only if x> ( biL - 1 ); + + return (unsigned) ret; +} + +/* + * Compare signed values in constant time + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, + unsigned *ret ) +{ + size_t i; + /* The value of any of these variables is either 0 or 1 at all times. */ + unsigned cond, done, X_is_negative, Y_is_negative; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + MPI_VALIDATE_RET( ret != NULL ); + + if( X->n != Y->n ) + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + + /* + * Set sign_N to 1 if N >= 0, 0 if N < 0. + * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. + */ + X_is_negative = ( X->s & 2 ) >> 1; + Y_is_negative = ( Y->s & 2 ) >> 1; + + /* + * If the signs are different, then the positive operand is the bigger. + * That is if X is negative (X_is_negative == 1), then X < Y is true and it + * is false if X is positive (X_is_negative == 0). + */ + cond = ( X_is_negative ^ Y_is_negative ); + *ret = cond & X_is_negative; + + /* + * This is a constant-time function. We might have the result, but we still + * need to go through the loop. Record if we have the result already. + */ + done = cond; + + for( i = X->n; i > 0; i-- ) + { + /* + * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both + * X and Y are negative. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] ); + *ret |= cond & ( 1 - done ) & X_is_negative; + done |= cond; + + /* + * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both + * X and Y are positive. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] ); + *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative ); + done |= cond; + } + + return( 0 ); +} + /* * Compare signed values */ diff --git a/library/cipher.c b/library/cipher.c index 20af25609..7164741b1 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -361,6 +361,10 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i *olen = 0; block_size = mbedtls_cipher_get_block_size( ctx ); + if ( 0 == block_size ) + { + return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); + } if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) { @@ -396,11 +400,6 @@ 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 % block_size ) ) { @@ -459,11 +458,6 @@ int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *i */ if( 0 != ilen ) { - if( 0 == block_size ) - { - return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); - } - /* Encryption: only cache partial blocks * Decryption w/ padding: always keep at least one whole block * Decryption w/o padding: only cache partial blocks diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c index 069303fdc..1c71288c3 100644 --- a/library/ctr_drbg.c +++ b/library/ctr_drbg.c @@ -62,68 +62,6 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) #endif } -/* - * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow - * NIST tests to succeed (which require known length fixed entropy) - */ -/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) - * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy, - * custom, len, entropy_len) - * implements - * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, - * security_strength) -> initial_working_state - * with inputs - * custom[:len] = nonce || personalization_string - * where entropy_input comes from f_entropy for entropy_len bytes - * and with outputs - * ctx = initial_working_state - */ -int mbedtls_ctr_drbg_seed_entropy_len( - mbedtls_ctr_drbg_context *ctx, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len, - size_t entropy_len ) -{ - int ret; - unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; - - mbedtls_platform_memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); - - mbedtls_aes_init( &ctx->aes_ctx ); - - ctx->f_entropy = f_entropy; - ctx->p_entropy = p_entropy; - - ctx->entropy_len = entropy_len; - ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; - - /* - * Initialize with an empty key - */ - if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) - { - return( ret ); - } - - if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) - { - return( ret ); - } - return( 0 ); -} - -int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, - int (*f_entropy)(void *, unsigned char *, size_t), - void *p_entropy, - const unsigned char *custom, - size_t len ) -{ - return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len, - MBEDTLS_CTR_DRBG_ENTROPY_LEN ) ); -} - void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) { if( ctx == NULL ) @@ -427,6 +365,63 @@ exit: return( ret ); } +/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) + * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len) + * implements + * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, + * security_strength) -> initial_working_state + * with inputs + * custom[:len] = nonce || personalization_string + * where entropy_input comes from f_entropy for ctx->entropy_len bytes + * and with outputs + * ctx = initial_working_state + */ +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + int ret; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + + memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); + + mbedtls_aes_init( &ctx->aes_ctx ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + if( ctx->entropy_len == 0 ) + ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; + + /* + * Initialize with an empty key + */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +/* Backward compatibility wrapper */ +int mbedtls_ctr_drbg_seed_entropy_len( + mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), void *p_entropy, + const unsigned char *custom, size_t len, + size_t entropy_len ) +{ + mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len ); + return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) ); +} + /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) * implements @@ -517,7 +512,7 @@ int mbedtls_ctr_drbg_random_with_add( void *p_rng, exit: mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); - return( 0 ); + return( ret ); } int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) @@ -678,8 +673,11 @@ int mbedtls_ctr_drbg_self_test( int verbose ) mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); test_offset = 0; - CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, - (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) ); + mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); + CHK( mbedtls_ctr_drbg_seed( &ctx, + ctr_drbg_self_test_entropy, + (void *) entropy_source_pr, + nonce_pers_pr, 16 ) ); mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); @@ -699,8 +697,11 @@ int mbedtls_ctr_drbg_self_test( int verbose ) mbedtls_ctr_drbg_init( &ctx ); test_offset = 0; - CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, - (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) ); + mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); + CHK( mbedtls_ctr_drbg_seed( &ctx, + ctr_drbg_self_test_entropy, + (void *) entropy_source_nopr, + nonce_pers_nopr, 16 ) ); CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); diff --git a/library/ecdsa.c b/library/ecdsa.c index a9734f6f6..6cfaa08fe 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -297,7 +297,7 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, *p_sign_tries = 0; do { - if( *p_sign_tries++ > 10 ) + if( (*p_sign_tries)++ > 10 ) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; @@ -310,7 +310,7 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, *p_key_tries = 0; do { - if( *p_key_tries++ > 10 ) + if( (*p_key_tries)++ > 10 ) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; @@ -363,6 +363,7 @@ modn: MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pk, pk, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); diff --git a/library/ecp.c b/library/ecp.c index 5c2e0f1bd..661112bb7 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -2724,6 +2724,7 @@ int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, { /* SEC1 3.2.1: Generate d such that 1 <= n < N */ int count = 0; + unsigned cmp = 0; /* * Match the procedure given in RFC 6979 (deterministic ECDSA): @@ -2748,9 +2749,14 @@ int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, */ if( ++count > 30 ) return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + + ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp ); + if( ret != 0 ) + { + goto cleanup; + } } - while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || - mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ); + while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 ); } #endif /* ECP_SHORTWEIERSTRASS */ diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c index 82703b0a3..dd895be42 100644 --- a/library/hmac_drbg.c +++ b/library/hmac_drbg.c @@ -320,16 +320,19 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; - /* - * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by - * each hash function, then according to SP800-90A rev1 10.1 table 2, - * min_entropy_len (in bits) is security_strength. - * - * (This also matches the sizes used in the NIST test vectors.) - */ - ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ - md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ - 32; /* better (256+) -> 256 bits */ + if( ctx->entropy_len == 0 ) + { + /* + * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by + * each hash function, then according to SP800-90A rev1 10.1 table 2, + * min_entropy_len (in bits) is security_strength. + * + * (This also matches the sizes used in the NIST test vectors.) + */ + ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ + md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ + 32; /* better (256+) -> 256 bits */ + } if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, HMAC_NONCE_YES ) ) != 0 ) { @@ -349,7 +352,7 @@ void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx } /* - * Set entropy length grabbed for reseeds + * Set entropy length grabbed for seeding */ void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len ) { diff --git a/library/pkparse.c b/library/pkparse.c index 3f202259f..de455528a 100644 --- a/library/pkparse.c +++ b/library/pkparse.c @@ -843,14 +843,40 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, goto cleanup; p += len; - /* Complete the RSA private key */ - if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 ) - goto cleanup; +#if !defined(MBEDTLS_RSA_NO_CRT) + /* + * The RSA CRT parameters DP, DQ and QP are nominally redundant, in + * that they can be easily recomputed from D, P and Q. However by + * parsing them from the PKCS1 structure it is possible to avoid + * recalculating them which both reduces the overhead of loading + * RSA private keys into memory and also avoids side channels which + * can arise when computing those values, since all of D, P, and Q + * are secret. See https://eprint.iacr.org/2020/055 for a + * description of one such attack. + */ - /* Check optional parameters */ + /* Import DP */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DP ) ) != 0) + goto cleanup; + + /* Import DQ */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->DQ ) ) != 0) + goto cleanup; + + /* Import QP */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &rsa->QP ) ) != 0) + goto cleanup; + +#else + /* Verify existance of the CRT params */ if( ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 || ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 || ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ) + goto cleanup; +#endif + + /* Complete the RSA private key */ + if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 ) goto cleanup; if( p != end ) diff --git a/library/rsa.c b/library/rsa.c index cde07e380..3f480a318 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -249,6 +249,9 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) { int ret = 0; int have_N, have_P, have_Q, have_D, have_E; +#if !defined(MBEDTLS_RSA_NO_CRT) + int have_DP, have_DQ, have_QP; +#endif int n_missing, pq_missing, d_missing, is_pub, is_priv; RSA_VALIDATE_RET( ctx != NULL ); @@ -259,6 +262,12 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 ); have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 ); +#if !defined(MBEDTLS_RSA_NO_CRT) + have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 ); + have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 ); + have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 ); +#endif + /* * Check whether provided parameters are enough * to deduce all others. The following incomplete @@ -324,7 +333,7 @@ int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) */ #if !defined(MBEDTLS_RSA_NO_CRT) - if( is_priv ) + if( is_priv && ! ( have_DP && have_DQ && have_QP ) ) { ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, &ctx->DP, &ctx->DQ, &ctx->QP ); diff --git a/library/version_features.c b/library/version_features.c index 6882830b0..d60758ce5 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -306,6 +306,9 @@ static const char *features[] = { #if defined(MBEDTLS_CIPHER_PADDING_ZEROS) "MBEDTLS_CIPHER_PADDING_ZEROS", #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) + "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY", +#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ #if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) "MBEDTLS_ENABLE_WEAK_CIPHERSUITES", #endif /* MBEDTLS_ENABLE_WEAK_CIPHERSUITES */ diff --git a/library/x509write_csr.c b/library/x509write_csr.c index 623db76f5..5a5bc6e8d 100644 --- a/library/x509write_csr.c +++ b/library/x509write_csr.c @@ -227,7 +227,9 @@ int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, s /* * Prepare signature */ - mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); + ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); + if( ret != 0 ) + return( ret ); if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, f_rng, p_rng ) ) != 0 ) diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c index 315065be4..8093c0d7f 100644 --- a/programs/ssl/query_config.c +++ b/programs/ssl/query_config.c @@ -858,6 +858,14 @@ int query_config( const char *config ) } #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) + if( strcmp( "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_CTR_DRBG_USE_128_BIT_KEY ); + return( 0 ); + } +#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ + #if defined(MBEDTLS_ENABLE_WEAK_CIPHERSUITES) if( strcmp( "MBEDTLS_ENABLE_WEAK_CIPHERSUITES", config ) == 0 ) { @@ -2266,14 +2274,6 @@ int query_config( const char *config ) } #endif /* MBEDTLS_CTR_DRBG_MAX_SEED_INPUT */ -#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) - if( strcmp( "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY", config ) == 0 ) - { - MACRO_EXPANSION_TO_STR( MBEDTLS_CTR_DRBG_USE_128_BIT_KEY ); - return( 0 ); - } -#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ - #if defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) if( strcmp( "MBEDTLS_HMAC_DRBG_RESEED_INTERVAL", config ) == 0 ) { diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c index 9c6aafb4f..71bee4737 100644 --- a/programs/test/benchmark.c +++ b/programs/test/benchmark.c @@ -686,12 +686,13 @@ int main( int argc, char *argv[] ) mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ctr_drbg_init( &ctr_drbg ); - if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 ) mbedtls_exit(1); TIME_AND_TSC( "CTR_DRBG (NOPR)", mbedtls_ctr_drbg_random( &ctr_drbg, buf, BUFSIZE ) ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_ctr_drbg_init( &ctr_drbg ); if( mbedtls_ctr_drbg_seed( &ctr_drbg, myrand, NULL, NULL, 0 ) != 0 ) mbedtls_exit(1); mbedtls_ctr_drbg_set_prediction_resistance( &ctr_drbg, MBEDTLS_CTR_DRBG_PR_ON ); diff --git a/programs/test/selftest.c b/programs/test/selftest.c index 82f08fa1b..4a8ed6843 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -66,6 +66,8 @@ #else #include #include +#define mbedtls_calloc calloc +#define mbedtls_free free #define mbedtls_printf printf #define mbedtls_snprintf snprintf #define mbedtls_exit exit @@ -78,6 +80,86 @@ #endif +#if defined MBEDTLS_SELF_TEST +/* Sanity check for malloc. This is not expected to fail, and is rather + * intended to display potentially useful information about the platform, + * in particular the behavior of malloc(0). */ +static int calloc_self_test( int verbose ) +{ + int failures = 0; + void *empty1 = mbedtls_calloc( 0, 1 ); + void *empty2 = mbedtls_calloc( 0, 1 ); + void *buffer1 = mbedtls_calloc( 1, 1 ); + void *buffer2 = mbedtls_calloc( 1, 1 ); + uintptr_t old_buffer1; + + if( empty1 == NULL && empty2 == NULL ) + { + if( verbose ) + mbedtls_printf( " CALLOC(0): passed (NULL)\n" ); + } + else if( empty1 == NULL || empty2 == NULL ) + { + if( verbose ) + mbedtls_printf( " CALLOC(0): failed (mix of NULL and non-NULL)\n" ); + ++failures; + } + else if( empty1 == empty2 ) + { + if( verbose ) + mbedtls_printf( " CALLOC(0): passed (same non-null)\n" ); + } + else + { + if( verbose ) + mbedtls_printf( " CALLOC(0): passed (distinct non-null)\n" ); + } + + if( buffer1 == NULL || buffer2 == NULL ) + { + if( verbose ) + mbedtls_printf( " CALLOC(1): failed (NULL)\n" ); + ++failures; + } + else if( buffer1 == buffer2 ) + { + if( verbose ) + mbedtls_printf( " CALLOC(1): failed (same buffer twice)\n" ); + ++failures; + } + else + { + if( verbose ) + mbedtls_printf( " CALLOC(1): passed\n" ); + } + + old_buffer1 = (uintptr_t) buffer1; + mbedtls_free( buffer1 ); + buffer1 = mbedtls_calloc( 1, 1 ); + if( buffer1 == NULL ) + { + if( verbose ) + mbedtls_printf( " CALLOC(1 again): failed (NULL)\n" ); + ++failures; + } + else + { + if( verbose ) + mbedtls_printf( " CALLOC(1 again): passed (%s address)\n", + (uintptr_t) old_buffer1 == (uintptr_t) buffer1 ? + "same" : "different" ); + } + + if( verbose ) + mbedtls_printf( "\n" ); + mbedtls_free( empty1 ); + mbedtls_free( empty2 ); + mbedtls_free( buffer1 ); + mbedtls_free( buffer2 ); + return( failures ); +} +#endif /* MBEDTLS_SELF_TEST */ + static int test_snprintf( size_t n, const char ref_buf[10], int ref_ret ) { int ret; @@ -174,6 +256,7 @@ typedef struct const selftest_t selftests[] = { + {"calloc", calloc_self_test}, #if defined(MBEDTLS_MD2_C) {"md2", mbedtls_md2_self_test}, #endif diff --git a/scripts/config.pl b/scripts/config.pl index 2519623cd..89182020a 100755 --- a/scripts/config.pl +++ b/scripts/config.pl @@ -100,6 +100,7 @@ MBEDTLS_TEST_NULL_ENTROPY MBEDTLS_DEPRECATED_REMOVED MBEDTLS_HAVE_SSE2 MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +MBEDTLS_CTR_DRBG_USE_128_BIT_KEY MBEDTLS_ECP_DP_M221_ENABLED MBEDTLS_ECP_DP_M383_ENABLED MBEDTLS_ECP_DP_M511_ENABLED diff --git a/tests/configs/config-wrapper-malloc-0-null.h b/tests/configs/config-wrapper-malloc-0-null.h new file mode 100644 index 000000000..ed74eda63 --- /dev/null +++ b/tests/configs/config-wrapper-malloc-0-null.h @@ -0,0 +1,39 @@ +/* config.h wrapper that forces calloc(0) to return NULL. + * Used for testing. + */ +/* + * Copyright (C) 2019, 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 MBEDTLS_CONFIG_H +/* Don't #define MBEDTLS_CONFIG_H, let config.h do it. */ + +#include "mbedtls/config.h" + +#include +static inline void *custom_calloc( size_t nmemb, size_t size ) +{ + if( nmemb == 0 || size == 0 ) + return( NULL ); + return( calloc( nmemb, size ) ); +} + +#define MBEDTLS_PLATFORM_MEMORY +#define MBEDTLS_PLATFORM_STD_CALLOC custom_calloc + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index bd7e98f6c..ae2e11283 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -137,6 +137,9 @@ pre_initialize_variables () { export MAKEFLAGS="-j" fi + # CFLAGS and LDFLAGS for Asan builds that don't use CMake + ASAN_CFLAGS='-Werror -Wall -Wextra -fsanitize=address,undefined -fno-sanitize-recover=all' + # Gather the list of available components. These are the functions # defined in this script whose name starts with "component_". # Parse the script with sed, because in sh there is no way to list @@ -1106,8 +1109,8 @@ component_test_no_platform () { scripts/config.pl unset MBEDTLS_FS_IO # Note, _DEFAULT_SOURCE needs to be defined for platforms using glibc version >2.19, # to re-enable platform integration features otherwise disabled in C99 builds - make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -std=c99 -pedantic -O0 -D_DEFAULT_SOURCE' lib programs - make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O0' test + make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -std=c99 -pedantic -Os -D_DEFAULT_SOURCE' lib programs + make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -Os' test } component_build_no_std_function () { @@ -1116,21 +1119,21 @@ component_build_no_std_function () { scripts/config.pl full scripts/config.pl set MBEDTLS_PLATFORM_NO_STD_FUNCTIONS scripts/config.pl unset MBEDTLS_ENTROPY_NV_SEED - make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O0' + make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -Os' } component_build_no_ssl_srv () { msg "build: full config except ssl_srv.c, make, gcc" # ~ 30s scripts/config.pl full scripts/config.pl unset MBEDTLS_SSL_SRV_C - make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O0' + make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O1' } component_build_no_ssl_cli () { msg "build: full config except ssl_cli.c, make, gcc" # ~ 30s scripts/config.pl full scripts/config.pl unset MBEDTLS_SSL_CLI_C - make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O0' + make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O1' } component_build_no_sockets () { @@ -1140,7 +1143,7 @@ component_build_no_sockets () { scripts/config.pl full scripts/config.pl unset MBEDTLS_NET_C # getaddrinfo() undeclared, etc. scripts/config.pl set MBEDTLS_NO_PLATFORM_ENTROPY # uses syscall() on GNU/Linux - make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O0 -std=c99 -pedantic' lib + make CC=gcc PTHREAD=1 CFLAGS='-Werror -Wall -Wextra -O1 -std=c99 -pedantic' lib } component_test_memory_buffer_allocator_backtrace () { @@ -1284,6 +1287,21 @@ component_test_platform_calloc_macro () { make test } +component_test_malloc_0_null () { + msg "build: malloc(0) returns NULL (ASan+UBSan build)" + scripts/config.pl full + scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C + make CC=gcc CFLAGS="'-DMBEDTLS_CONFIG_FILE=\"$PWD/tests/configs/config-wrapper-malloc-0-null.h\"' -O -Werror -Wall -Wextra -fsanitize=address,undefined" LDFLAGS='-fsanitize=address,undefined' + + msg "test: malloc(0) returns NULL (ASan+UBSan build)" + make test + + msg "selftest: malloc(0) returns NULL (ASan+UBSan build)" + # Just the calloc selftest. "make test" ran the others as part of the + # test suites. + if_build_succeeded programs/test/selftest calloc +} + component_test_aes_fewer_tables () { msg "build: default config with AES_FEWER_TABLES enabled" scripts/config.pl set MBEDTLS_AES_FEWER_TABLES @@ -1357,6 +1375,30 @@ component_test_cmake_shared () { make test } +test_build_opt () { + info=$1 cc=$2; shift 2 + for opt in "$@"; do + msg "build/test: $cc $opt, $info" # ~ 30s + make CC="$cc" CFLAGS="$opt -Wall -Wextra -Werror" + # We're confident enough in compilers to not run _all_ the tests, + # but at least run the unit tests. In particular, runs with + # optimizations use inline assembly whereas runs with -O0 + # skip inline assembly. + make test # ~30s + make clean + done +} + +component_test_clang_opt () { + scripts/config.pl full + test_build_opt 'full config' clang -O0 -Os -O2 +} + +component_test_gcc_opt () { + scripts/config.pl full + test_build_opt 'full config' gcc -O0 -Os -O2 +} + component_build_mbedtls_config_file () { msg "build: make with MBEDTLS_CONFIG_FILE" # ~40s # Use the full config so as to catch a maximum of places where @@ -1372,7 +1414,7 @@ component_test_m32_o0 () { # Build once with -O0, to compile out the i386 specific inline assembly msg "build: i386, make, gcc -O0 (ASan build)" # ~ 30s scripts/config.pl full - make CC=gcc PTHREAD=1 CFLAGS='-O0 -Werror -Wall -Wextra -m32 -fsanitize=address' LDFLAGS='-m32' + make CC=gcc PTHREAD=1 CFLAGS="$ASAN_CFLAGS -m32 -O0" LDFLAGS="-m32 $ASAN_CFLAGS" msg "test: i386, make, gcc -O0 (ASan build)" make test @@ -1388,7 +1430,7 @@ component_test_m32_o1 () { # Build again with -O1, to compile in the i386 specific inline assembly msg "build: i386, make, gcc -O1 (ASan build)" # ~ 30s scripts/config.pl full - make CC=gcc PTHREAD=1 CFLAGS='-O1 -Werror -Wall -Wextra -m32 -fsanitize=address' LDFLAGS='-m32' + make CC=gcc PTHREAD=1 CFLAGS="$ASAN_CFLAGS -m32 -O1" LDFLAGS="-m32 $ASAN_CFLAGS" msg "test: i386, make, gcc -O1 (ASan build)" make test diff --git a/tests/scripts/run-test-suites.pl b/tests/scripts/run-test-suites.pl index 1c9dc1dfc..d06badd23 100755 --- a/tests/scripts/run-test-suites.pl +++ b/tests/scripts/run-test-suites.pl @@ -93,7 +93,7 @@ for my $suite (@suites) $suite_cases_failed = () = $result =~ /.. FAILED/g; $suite_cases_skipped = () = $result =~ /.. ----/g; - if( $result =~ /PASSED/ ) { + if( $? == 0 ) { print "PASS\n"; if( $verbose > 2 ) { pad_print_center( 72, '-', "Begin $suite" ); diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 00ed39150..67cf50233 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -1162,6 +1162,18 @@ run_test "Default (compression enabled)" \ -S "error" \ -C "error" +requires_config_enabled MBEDTLS_ZLIB_SUPPORT +run_test "Default (compression enabled)" \ + "$P_SRV debug_level=3" \ + "$P_CLI debug_level=3" \ + 0 \ + -s "Allocating compression buffer" \ + -c "Allocating compression buffer" \ + -s "Record expansion is unknown (compression)" \ + -c "Record expansion is unknown (compression)" \ + -S "error" \ + -C "error" + # Test current time in ServerHello requires_config_enabled MBEDTLS_HAVE_TIME run_test "ServerHello contains gmt_unix_time" \ @@ -5380,15 +5392,8 @@ run_test "Per-version suites: TLS 1.2" \ # Test for ClientHello without extensions requires_gnutls -run_test "ClientHello without extensions, SHA-1 allowed" \ - "$P_SRV debug_level=3 key_file=data_files/server2.key crt_file=data_files/server2.crt" \ - "$G_CLI --priority=NORMAL:%NO_EXTENSIONS:%DISABLE_SAFE_RENEGOTIATION localhost" \ - 0 \ - -s "dumping 'client hello extensions' (0 bytes)" - -requires_gnutls -run_test "ClientHello without extensions, SHA-1 forbidden in certificates on server" \ - "$P_SRV debug_level=3 key_file=data_files/server2.key crt_file=data_files/server2.crt allow_sha1=0" \ +run_test "ClientHello without extensions" \ + "$P_SRV debug_level=3" \ "$G_CLI --priority=NORMAL:%NO_EXTENSIONS:%DISABLE_SAFE_RENEGOTIATION localhost" \ 0 \ -s "dumping 'client hello extensions' (0 bytes)" diff --git a/tests/suites/test_suite_ctr_drbg.function b/tests/suites/test_suite_ctr_drbg.function index 4a97826f6..01050d92d 100644 --- a/tests/suites/test_suite_ctr_drbg.function +++ b/tests/suites/test_suite_ctr_drbg.function @@ -44,11 +44,11 @@ static void ctr_drbg_validate_internal( int reseed_mode, data_t * nonce, /* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, ) * where nonce||perso = nonce[nonce->len] */ - TEST_ASSERT( mbedtls_ctr_drbg_seed_entropy_len( + mbedtls_ctr_drbg_set_entropy_len( &ctx, entropy_chunk_len ); + TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctx, mbedtls_test_entropy_func, entropy->x, - nonce->x, nonce->len, - entropy_chunk_len ) == 0 ); + nonce->x, nonce->len ) == 0 ); if( reseed_mode == RESEED_ALWAYS ) mbedtls_ctr_drbg_set_prediction_resistance( &ctx, diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function index 4f3143f5b..9e82bb5d2 100644 --- a/tests/suites/test_suite_ecdsa.function +++ b/tests/suites/test_suite_ecdsa.function @@ -527,7 +527,9 @@ void ecdsa_write_restart( int id, char *d_str, int md_alg, TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE ); hlen = mbedtls_md_get_size( md_info ); - mbedtls_md( md_info, (const unsigned char *) msg, strlen( msg ), hash ); + TEST_ASSERT( mbedtls_md( md_info, + (const unsigned char *) msg, strlen( msg ), + hash ) == 0 ); mbedtls_ecp_set_max_ops( max_ops ); diff --git a/tests/suites/test_suite_memory_buffer_alloc.data b/tests/suites/test_suite_memory_buffer_alloc.data index d59f1135a..d780fd41b 100644 --- a/tests/suites/test_suite_memory_buffer_alloc.data +++ b/tests/suites/test_suite_memory_buffer_alloc.data @@ -16,8 +16,8 @@ memory_buffer_alloc_free_alloc:100:64:100:100:0:0:0:1:200:0 Memory buffer alloc - Out of Memory test memory_buffer_alloc_oom_test: -Memory buffer small buffer -memory_buffer_small_buffer: +Memory buffer: heap too small (header verification should fail) +memory_buffer_heap_too_small: -Memory buffer underalloc +Memory buffer: attempt to allocate SIZE_MAX memory_buffer_underalloc: diff --git a/tests/suites/test_suite_memory_buffer_alloc.function b/tests/suites/test_suite_memory_buffer_alloc.function index bc034367a..cc884c28e 100644 --- a/tests/suites/test_suite_memory_buffer_alloc.function +++ b/tests/suites/test_suite_memory_buffer_alloc.function @@ -29,7 +29,7 @@ void mbedtls_memory_buffer_alloc_self_test( ) } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */ +/* BEGIN_CASE */ void memory_buffer_alloc_free_alloc( int a_bytes, int b_bytes, int c_bytes, int d_bytes, int free_a, int free_b, int free_c, int free_d, int e_bytes, @@ -39,8 +39,11 @@ void memory_buffer_alloc_free_alloc( int a_bytes, int b_bytes, int c_bytes, unsigned char *ptr_a = NULL, *ptr_b = NULL, *ptr_c = NULL, *ptr_d = NULL, *ptr_e = NULL, *ptr_f = NULL; +#if defined(MBEDTLS_MEMORY_DEBUG) size_t reported_blocks; - size_t allocated_bytes = 0, reported_bytes; + size_t reported_bytes; +#endif + size_t allocated_bytes = 0; mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); @@ -78,8 +81,10 @@ void memory_buffer_alloc_free_alloc( int a_bytes, int b_bytes, int c_bytes, allocated_bytes += d_bytes * sizeof(char); } +#if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks ); TEST_ASSERT( reported_bytes == allocated_bytes ); +#endif if( free_a ) { @@ -117,8 +122,10 @@ void memory_buffer_alloc_free_alloc( int a_bytes, int b_bytes, int c_bytes, allocated_bytes -= d_bytes * sizeof(char); } +#if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks ); TEST_ASSERT( reported_bytes == allocated_bytes ); +#endif if( e_bytes > 0 ) { @@ -178,8 +185,10 @@ void memory_buffer_alloc_free_alloc( int a_bytes, int b_bytes, int c_bytes, ptr_f = NULL; } +#if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks ); TEST_ASSERT( reported_bytes == 0 ); +#endif TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 ); @@ -188,12 +197,14 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */ +/* BEGIN_CASE */ void memory_buffer_alloc_oom_test( ) { unsigned char buf[1024]; unsigned char *ptr_a = NULL, *ptr_b = NULL, *ptr_c = NULL; +#if defined(MBEDTLS_MEMORY_DEBUG) size_t reported_blocks, reported_bytes; +#endif (void)ptr_c; @@ -210,8 +221,10 @@ void memory_buffer_alloc_oom_test( ) ptr_c = mbedtls_calloc( 431, sizeof(char) ); TEST_ASSERT( ptr_c == NULL ); +#if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks ); TEST_ASSERT( reported_bytes >= 864 && reported_bytes <= sizeof(buf) ); +#endif mbedtls_free( ptr_a ); ptr_a = NULL; @@ -221,8 +234,10 @@ void memory_buffer_alloc_oom_test( ) ptr_b = NULL; TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 ); +#if defined(MBEDTLS_MEMORY_DEBUG) mbedtls_memory_buffer_alloc_cur_get( &reported_bytes, &reported_blocks ); TEST_ASSERT( reported_bytes == 0 ); +#endif TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() == 0 ); @@ -231,17 +246,20 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */ -void memory_buffer_small_buffer( ) +/* BEGIN_CASE */ +void memory_buffer_heap_too_small( ) { unsigned char buf[1]; mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); + /* With MBEDTLS_MEMORY_DEBUG enabled, this prints a message + * "FATAL: verification of first header failed". + */ TEST_ASSERT( mbedtls_memory_buffer_alloc_verify() != 0 ); } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_MEMORY_DEBUG */ +/* BEGIN_CASE */ void memory_buffer_underalloc( ) { unsigned char buf[100]; diff --git a/tests/suites/test_suite_mpi.data b/tests/suites/test_suite_mpi.data index 425e93ad2..00926ff97 100644 --- a/tests/suites/test_suite_mpi.data +++ b/tests/suites/test_suite_mpi.data @@ -163,6 +163,93 @@ mbedtls_mpi_cmp_mpi:10:"2":10:"-3":1 Base test mbedtls_mpi_cmp_mpi (Mixed values) #6 mbedtls_mpi_cmp_mpi:10:"-2":10:"31231231289798":-1 +Base test mbedtls_mpi_lt_mpi_ct #1 +mbedtls_mpi_lt_mpi_ct:1:"2B5":1:"2B5":0:0 + +Base test mbedtls_mpi_lt_mpi_ct #2 +mbedtls_mpi_lt_mpi_ct:1:"2B5":1:"2B4":0:0 + +Base test mbedtls_mpi_lt_mpi_ct #3 +mbedtls_mpi_lt_mpi_ct:1:"2B5":1:"2B6":1:0 + +Base test mbedtls_mpi_lt_mpi_ct (Negative values) #1 +mbedtls_mpi_lt_mpi_ct:1:"-2":1:"-2":0:0 + +Base test mbedtls_mpi_lt_mpi_ct (Negative values) #2 +mbedtls_mpi_lt_mpi_ct:1:"-2":1:"-3":0:0 + +Base test mbedtls_mpi_lt_mpi_ct (Negative values) #3 +mbedtls_mpi_lt_mpi_ct:1:"-2":1:"-1":1:0 + +Base test mbedtls_mpi_lt_mpi_ct (Mixed values) #1 +mbedtls_mpi_lt_mpi_ct:1:"-3":1:"2":1:0 + +Base test mbedtls_mpi_lt_mpi_ct (Mixed values) #2 +mbedtls_mpi_lt_mpi_ct:1:"2":1:"-3":0:0 + +Base test mbedtls_mpi_lt_mpi_ct (Mixed values) #3 +mbedtls_mpi_lt_mpi_ct:2:"-2":2:"1C67967269C6":1:0 + +Base test mbedtls_mpi_lt_mpi_ct (X is longer in storage) +mbedtls_mpi_lt_mpi_ct:3:"2B5":2:"2B5":0:MBEDTLS_ERR_MPI_BAD_INPUT_DATA + +Base test mbedtls_mpi_lt_mpi_ct (Y is longer in storage) +mbedtls_mpi_lt_mpi_ct:3:"2B5":4:"2B5":0:MBEDTLS_ERR_MPI_BAD_INPUT_DATA + +Base test mbedtls_mpi_lt_mpi_ct (corner case - 64 bit) #1 +mbedtls_mpi_lt_mpi_ct:2:"7FFFFFFFFFFFFFFF":2:"FF":0:0 + +Base test mbedtls_mpi_lt_mpi_ct (corner case - 64 bit) #2 +mbedtls_mpi_lt_mpi_ct:2:"8000000000000000":2:"7FFFFFFFFFFFFFFF":0:0 + +Base test mbedtls_mpi_lt_mpi_ct (corner case - 64 bit) #3 +mbedtls_mpi_lt_mpi_ct:2:"8000000000000000":2:"1":0:0 + +Base test mbedtls_mpi_lt_mpi_ct (corner case - 64 bit) #4 +mbedtls_mpi_lt_mpi_ct:2:"8000000000000000":2:"0":0:0 + +Base test mbedtls_mpi_lt_mpi_ct (corner case - 64 bit) #5 +mbedtls_mpi_lt_mpi_ct:2:"FFFFFFFFFFFFFFFF":2:"FF":0:0 + +Base test mbedtls_mpi_lt_mpi_ct (corner case - 32 bit) #1 +mbedtls_mpi_lt_mpi_ct:1:"7FFFFFFF":1:"FF":0:0 + +Base test mbedtls_mpi_lt_mpi_ct (corner case - 32 bit) #2 +mbedtls_mpi_lt_mpi_ct:1:"80000000":1:"7FFFFFFF":0:0 + +Base test mbedtls_mpi_lt_mpi_ct (corner case - 32 bit) #3 +mbedtls_mpi_lt_mpi_ct:1:"80000000":1:"1":0:0 + +Base test mbedtls_mpi_lt_mpi_ct (corner case - 32 bit) #4 +mbedtls_mpi_lt_mpi_ct:1:"80000000":1:"0":0:0 + +Base test mbedtls_mpi_lt_mpi_ct (corner case - 32 bit) #5 +mbedtls_mpi_lt_mpi_ct:1:"FFFFFFFF":1:"FF":0:0 + +Multi-limb mbedtls_mpi_lt_mpi_ct (XY, equal MS limbs) +mbedtls_mpi_lt_mpi_ct:2:"-EEFFFFFFFFFFFFFFF1":2:"-EEFFFFFFFFFFFFFFFF":0:0 + +Multi-limb mbedtls_mpi_lt_mpi_ct (X=Y) +mbedtls_mpi_lt_mpi_ct:2:"EEFFFFFFFFFFFFFFFF":2:"EEFFFFFFFFFFFFFFFF":0:0 + +Multi-limb mbedtls_mpi_lt_mpi_ct (X=-Y) +mbedtls_mpi_lt_mpi_ct:2:"-EEFFFFFFFFFFFFFFFF":2:"EEFFFFFFFFFFFFFFFF":1:0 + +Multi-limb mbedtls_mpi_lt_mpi_ct (Alternating limbs) #1 +mbedtls_mpi_lt_mpi_ct:2:"11FFFFFFFFFFFFFFFF":2:"FF1111111111111111":1:0 + +Multi-limb mbedtls_mpi_lt_mpi_ct (Alternating limbs) #2 +mbedtls_mpi_lt_mpi_ct:2:"FF1111111111111111":2:"11FFFFFFFFFFFFFFFF":0:0 + +Multi-limb mbedtls_mpi_lt_mpi_ct (Alternating limbs) #3 +mbedtls_mpi_lt_mpi_ct:2:"-11FFFFFFFFFFFFFFFF":2:"-FF1111111111111111":0:0 + +Multi-limb mbedtls_mpi_lt_mpi_ct (Alternating limbs) #4 +mbedtls_mpi_lt_mpi_ct:2:"-FF1111111111111111":2:"-11FFFFFFFFFFFFFFFF":1:0 + Base test mbedtls_mpi_cmp_abs #1 mbedtls_mpi_cmp_abs:10:"693":10:"693":0 @@ -193,37 +280,106 @@ mbedtls_mpi_cmp_abs:10:"2":10:"-3":-1 Base test mbedtls_mpi_cmp_abs (Mix values) #3 mbedtls_mpi_cmp_abs:10:"-2":10:"1":1 -Base test mbedtls_mpi_copy #1 -mbedtls_mpi_copy:0:1500 +Copy zero (1 limb) to positive (1 limb) +mbedtls_mpi_copy_sint:0:1500 -Base test mpi_copy_self #1 +Copy zero (1 limb) to negative (1 limb) +mbedtls_mpi_copy_sint:0:-1500 + +Copy positive (1 limb) to zero (1 limb) +mbedtls_mpi_copy_sint:1500:0 + +Copy negative (1 limb) to zero (1 limb) +mbedtls_mpi_copy_sint:-1500:0 + +Copy positive (1 limb) to negative (1 limb) +mbedtls_mpi_copy_sint:1500:-42 + +Copy negative (1 limb) to positive (1 limb) +mbedtls_mpi_copy_sint:-42:1500 + +Copy zero (null) to zero (null) +mbedtls_mpi_copy_binary:"":"" + +Copy zero (null) to positive (1 limb) +mbedtls_mpi_copy_binary:"":"1234" + +Copy positive (1 limb) to zero (null) +mbedtls_mpi_copy_binary:"1234":"" + +Copy positive to larger +mbedtls_mpi_copy_binary:"bead":"ca5cadedb01dfaceacc01ade" + +Copy positive to smaller +mbedtls_mpi_copy_binary:"ca5cadedb01dfaceacc01ade":"bead" + +Copy self: positive (1 limb) mpi_copy_self:14 -Base test mbedtls_mpi_swap #1 -mbedtls_mpi_swap:0:1500 +Copy self: zero (1 limb) +mpi_copy_self:0 -Test mbedtls_mpi_shrink #1 +Swap zero (1 limb) with positive (1 limb) +mbedtls_mpi_swap_sint:0:1500 + +Swap zero (1 limb) with negative (1 limb) +mbedtls_mpi_swap_sint:0:-1500 + +Swap positive (1 limb) with zero (1 limb) +mbedtls_mpi_swap_sint:1500:0 + +Swap negative (1 limb) with zero (1 limb) +mbedtls_mpi_swap_sint:-1500:0 + +Swap positive (1 limb) with negative (1 limb) +mbedtls_mpi_swap_sint:1500:-42 + +Swap negative (1 limb) with positive (1 limb) +mbedtls_mpi_swap_sint:-42:1500 + +Swap zero (null) with zero (null) +mbedtls_mpi_swap_binary:"":"" + +Swap zero (null) with positive (1 limb) +mbedtls_mpi_swap_binary:"":"1234" + +Swap positive (1 limb) with zero (null) +mbedtls_mpi_swap_binary:"1234":"" + +Swap positive with larger +mbedtls_mpi_swap_binary:"bead":"ca5cadedb01dfaceacc01ade" + +Swap positive with smaller +mbedtls_mpi_swap_binary:"ca5cadedb01dfaceacc01ade":"bead" + +Swap self: 1 limb +mpi_swap_self:"face" + +Swap self: null +mpi_swap_self:"" + +Shrink 2 limbs in a buffer of size 2 to 4 mbedtls_mpi_shrink:2:2:4:4 -Test mbedtls_mpi_shrink #2 +Shrink 2 limbs in a buffer of size 4 to 4 mbedtls_mpi_shrink:4:2:4:4 -Test mbedtls_mpi_shrink #3 +Shrink 2 limbs in a buffer of size 8 to 4 mbedtls_mpi_shrink:8:2:4:4 -Test mbedtls_mpi_shrink #4 +Shrink 4 limbs in a buffer of size 8 to 4 mbedtls_mpi_shrink:8:4:4:4 -Test mbedtls_mpi_shrink #5 +Shrink 6 limbs in a buffer of size 8 to 4 yielding 6 mbedtls_mpi_shrink:8:6:4:6 -Test mbedtls_mpi_shrink #6 +Shrink 2 limbs in a buffer of size 4 to 0 yielding 2 mbedtls_mpi_shrink:4:2:0:2 -Test mbedtls_mpi_shrink #7 +Shrink 1 limbs in a buffer of size 4 to 0 yielding 1 mbedtls_mpi_shrink:4:1:0:1 -Test mbedtls_mpi_shrink #8 +Shrink 0 limbs in a buffer of size 4 to 0 yielding 1 mbedtls_mpi_shrink:4:0:0:1 Test mbedtls_mpi_safe_cond_assign #1 diff --git a/tests/suites/test_suite_mpi.function b/tests/suites/test_suite_mpi.function index f982385e1..f2702f12b 100644 --- a/tests/suites/test_suite_mpi.function +++ b/tests/suites/test_suite_mpi.function @@ -537,6 +537,31 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void mbedtls_mpi_lt_mpi_ct( int size_X, char * input_X, + int size_Y, char * input_Y, + int input_ret, int input_err ) +{ + unsigned ret; + unsigned input_uret = input_ret; + mbedtls_mpi X, Y; + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); + + TEST_ASSERT( mbedtls_mpi_read_string( &X, 16, input_X ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_string( &Y, 16, input_Y ) == 0 ); + + TEST_ASSERT( mbedtls_mpi_grow( &X, size_X ) == 0 ); + TEST_ASSERT( mbedtls_mpi_grow( &Y, size_Y ) == 0 ); + + TEST_ASSERT( mbedtls_mpi_lt_mpi_ct( &X, &Y, &ret ) == input_err ); + if( input_err == 0 ) + TEST_ASSERT( ret == input_uret ); + +exit: + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); +} +/* END_CASE */ + /* BEGIN_CASE */ void mbedtls_mpi_cmp_abs( int radix_X, char * input_X, int radix_Y, char * input_Y, int input_A ) @@ -554,22 +579,40 @@ exit: /* END_CASE */ /* BEGIN_CASE */ -void mbedtls_mpi_copy( int input_X, int input_A ) +void mbedtls_mpi_copy_sint( int input_X, int input_Y ) { - mbedtls_mpi X, Y, A; - mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &A ); + mbedtls_mpi X, Y; + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); TEST_ASSERT( mbedtls_mpi_lset( &X, input_X ) == 0 ); - TEST_ASSERT( mbedtls_mpi_lset( &Y, input_A ) == 0 ); - TEST_ASSERT( mbedtls_mpi_lset( &A, input_A ) == 0 ); - TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y ) != 0 ); - TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &A ) == 0 ); + TEST_ASSERT( mbedtls_mpi_lset( &Y, input_Y ) == 0 ); + TEST_ASSERT( mbedtls_mpi_copy( &Y, &X ) == 0 ); - TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y ) == 0 ); - TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &A ) != 0 ); + TEST_ASSERT( mbedtls_mpi_cmp_int( &X, input_X ) == 0 ); + TEST_ASSERT( mbedtls_mpi_cmp_int( &Y, input_X ) == 0 ); exit: - mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &A ); + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void mbedtls_mpi_copy_binary( data_t *input_X, data_t *input_Y ) +{ + mbedtls_mpi X, Y, X0; + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &X0 ); + + TEST_ASSERT( mbedtls_mpi_read_binary( &X, input_X->x, input_X->len ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_binary( &Y, input_Y->x, input_Y->len ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_binary( &X0, input_X->x, input_X->len ) == 0 ); + TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &X0 ) == 0 ); + + TEST_ASSERT( mbedtls_mpi_copy( &Y, &X ) == 0 ); + TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &X0 ) == 0 ); + TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &X0 ) == 0 ); + +exit: + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &X0 ); } /* END_CASE */ @@ -661,22 +704,61 @@ exit: /* END_CASE */ /* BEGIN_CASE */ -void mbedtls_mpi_swap( int input_X, int input_Y ) +void mbedtls_mpi_swap_sint( int input_X, int input_Y ) { - mbedtls_mpi X, Y, A; - mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &A ); + mbedtls_mpi X, Y; + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); TEST_ASSERT( mbedtls_mpi_lset( &X, input_X ) == 0 ); TEST_ASSERT( mbedtls_mpi_lset( &Y, input_Y ) == 0 ); - TEST_ASSERT( mbedtls_mpi_lset( &A, input_X ) == 0 ); - TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y ) != 0 ); - TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &A ) == 0 ); + TEST_ASSERT( mbedtls_mpi_cmp_int( &X, input_X ) == 0 ); + TEST_ASSERT( mbedtls_mpi_cmp_int( &Y, input_Y ) == 0 ); + mbedtls_mpi_swap( &X, &Y ); - TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y ) != 0 ); - TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &A ) == 0 ); + TEST_ASSERT( mbedtls_mpi_cmp_int( &X, input_Y ) == 0 ); + TEST_ASSERT( mbedtls_mpi_cmp_int( &Y, input_X ) == 0 ); exit: - mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &A ); + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void mbedtls_mpi_swap_binary( data_t *input_X, data_t *input_Y ) +{ + mbedtls_mpi X, Y, X0, Y0; + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); + mbedtls_mpi_init( &X0 ); mbedtls_mpi_init( &Y0 ); + + TEST_ASSERT( mbedtls_mpi_read_binary( &X, input_X->x, input_X->len ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_binary( &Y, input_Y->x, input_Y->len ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_binary( &X0, input_X->x, input_X->len ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_binary( &Y0, input_Y->x, input_Y->len ) == 0 ); + + mbedtls_mpi_swap( &X, &Y ); + TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &Y0 ) == 0 ); + TEST_ASSERT( mbedtls_mpi_cmp_mpi( &Y, &X0 ) == 0 ); + +exit: + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); + mbedtls_mpi_free( &X0 ); mbedtls_mpi_free( &Y0 ); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void mpi_swap_self( data_t *input_X ) +{ + mbedtls_mpi X, X0; + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &X0 ); + + TEST_ASSERT( mbedtls_mpi_read_binary( &X, input_X->x, input_X->len ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_binary( &X0, input_X->x, input_X->len ) == 0 ); + + mbedtls_mpi_swap( &X, &X ); + TEST_ASSERT( mbedtls_mpi_cmp_mpi( &X, &X0 ) == 0 ); + +exit: + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &X0 ); } /* END_CASE */ diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function index 61bf95c0c..9153862c1 100644 --- a/tests/suites/test_suite_pk.function +++ b/tests/suites/test_suite_pk.function @@ -735,7 +735,9 @@ void pk_sign_verify_restart( int pk_type, int grp_id, char *d_str, TEST_ASSERT( md_info != MBEDTLS_MD_INVALID_HANDLE ); hlen = mbedtls_md_get_size( md_info ); - mbedtls_md( md_info, (const unsigned char *) msg, strlen( msg ), hash ); + TEST_ASSERT( mbedtls_md( md_info, + (const unsigned char *) msg, strlen( msg ), + hash ) == 0 ); mbedtls_ecp_set_max_ops( max_ops ); diff --git a/tests/suites/test_suite_version.data b/tests/suites/test_suite_version.data index c3189c82c..f7dd90cd9 100644 --- a/tests/suites/test_suite_version.data +++ b/tests/suites/test_suite_version.data @@ -1,8 +1,8 @@ Check compiletime library version -check_compiletime_version:"2.16.3" +check_compiletime_version:"2.16.4" Check runtime library version -check_runtime_version:"2.16.3" +check_runtime_version:"2.16.4" Check for MBEDTLS_VERSION_C check_feature:"MBEDTLS_VERSION_C":0