mirror of
				https://github.com/Mbed-TLS/mbedtls.git
				synced 2025-11-03 20:33:16 +03:00 
			
		
		
		
	Merge pull request #2894 from gilles-peskine-arm/drbg-set_entropy_len-2.16
Backport 2.16: Allow xxx_drbg_set_entropy_len before xxx_drbg_seed
This commit is contained in:
		@@ -6,6 +6,10 @@ 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()
 | 
			
		||||
 
 | 
			
		||||
@@ -214,11 +214,8 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
 | 
			
		||||
 *   with mbedtls_entropy_init() (which registers the platform's default
 | 
			
		||||
 *   entropy sources).
 | 
			
		||||
 *
 | 
			
		||||
 * \p f_entropy is always called with a buffer size equal to the entropy
 | 
			
		||||
 * length. The entropy length is initially #MBEDTLS_CTR_DRBG_ENTROPY_LEN
 | 
			
		||||
 * and this value is always used for the initial seeding. You can change
 | 
			
		||||
 * the entropy length for subsequent seeding by calling
 | 
			
		||||
 * mbedtls_ctr_drbg_set_entropy_len() after this function.
 | 
			
		||||
 * 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.
 | 
			
		||||
@@ -252,9 +249,18 @@ void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
 | 
			
		||||
#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.
 | 
			
		||||
 *                      \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
 | 
			
		||||
@@ -298,15 +304,10 @@ void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief               This function sets the amount of entropy grabbed on each
 | 
			
		||||
 *                      subsequent reseed.
 | 
			
		||||
 *                      seed or reseed.
 | 
			
		||||
 *
 | 
			
		||||
 * The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN.
 | 
			
		||||
 *
 | 
			
		||||
 * \note                mbedtls_ctr_drbg_seed() always sets the entropy length
 | 
			
		||||
 *                      to #MBEDTLS_CTR_DRBG_ENTROPY_LEN, so this function
 | 
			
		||||
 *                      only has an effect when it is called after
 | 
			
		||||
 *                      mbedtls_ctr_drbg_seed().
 | 
			
		||||
 *
 | 
			
		||||
 * \note                The security strength of CTR_DRBG is bounded by the
 | 
			
		||||
 *                      entropy length. Thus:
 | 
			
		||||
 *                      - When using AES-256
 | 
			
		||||
 
 | 
			
		||||
@@ -139,13 +139,11 @@ void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx );
 | 
			
		||||
 *                      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() afterwards.
 | 
			
		||||
 *                      mbedtls_hmac_drbg_set_entropy_len().
 | 
			
		||||
 *
 | 
			
		||||
 * \note                The entropy length for the initial seeding is
 | 
			
		||||
 *                      the security strength (converted from bits to bytes).
 | 
			
		||||
 *                      You can set a different entropy length for subsequent
 | 
			
		||||
 *                      seeding by calling mbedtls_hmac_drbg_set_entropy_len()
 | 
			
		||||
 *                      after this function.
 | 
			
		||||
 * \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
 | 
			
		||||
@@ -224,14 +222,9 @@ void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \brief               This function sets the amount of entropy grabbed on each
 | 
			
		||||
 *                      reseed.
 | 
			
		||||
 *                      seed or reseed.
 | 
			
		||||
 *
 | 
			
		||||
 * The default value is set by mbedtls_hmac_drbg_seed().
 | 
			
		||||
 *
 | 
			
		||||
 * \note                mbedtls_hmac_drbg_seed() always sets the entropy length
 | 
			
		||||
 *                      to the default value based on the chosen MD algorithm,
 | 
			
		||||
 *                      so this function only has an effect if it is called
 | 
			
		||||
 *                      after mbedtls_hmac_drbg_seed().
 | 
			
		||||
 * 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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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];
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
@@ -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 ) );
 | 
			
		||||
 
 | 
			
		||||
@@ -273,16 +273,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,
 | 
			
		||||
                                       1 /* add nonce */ ) ) != 0 )
 | 
			
		||||
@@ -303,7 +306,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 )
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -674,12 +674,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 );
 | 
			
		||||
 
 | 
			
		||||
@@ -44,11 +44,11 @@ static void ctr_drbg_validate_internal( int reseed_mode, data_t * nonce,
 | 
			
		||||
 | 
			
		||||
    /* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, <ignored>)
 | 
			
		||||
     * 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,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user