1c6672fdcSEdison Ai // SPDX-License-Identifier: Apache-2.0 2817466cbSJens Wiklander /* 3817466cbSJens Wiklander * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) 4817466cbSJens Wiklander * 5817466cbSJens Wiklander * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 6817466cbSJens Wiklander * 7817466cbSJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 8817466cbSJens Wiklander * not use this file except in compliance with the License. 9817466cbSJens Wiklander * You may obtain a copy of the License at 10817466cbSJens Wiklander * 11817466cbSJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 12817466cbSJens Wiklander * 13817466cbSJens Wiklander * Unless required by applicable law or agreed to in writing, software 14817466cbSJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15817466cbSJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16817466cbSJens Wiklander * See the License for the specific language governing permissions and 17817466cbSJens Wiklander * limitations under the License. 18817466cbSJens Wiklander * 19817466cbSJens Wiklander * This file is part of mbed TLS (https://tls.mbed.org) 20817466cbSJens Wiklander */ 21817466cbSJens Wiklander /* 223d3b0591SJens Wiklander * The NIST SP 800-90 DRBGs are described in the following publication. 23817466cbSJens Wiklander * 24817466cbSJens Wiklander * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf 25817466cbSJens Wiklander */ 26817466cbSJens Wiklander 27817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE) 28817466cbSJens Wiklander #include "mbedtls/config.h" 29817466cbSJens Wiklander #else 30817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE 31817466cbSJens Wiklander #endif 32817466cbSJens Wiklander 33817466cbSJens Wiklander #if defined(MBEDTLS_CTR_DRBG_C) 34817466cbSJens Wiklander 35817466cbSJens Wiklander #include "mbedtls/ctr_drbg.h" 363d3b0591SJens Wiklander #include "mbedtls/platform_util.h" 37*11fa71b9SJerome Forissier #include "mbedtls/error.h" 38817466cbSJens Wiklander 39817466cbSJens Wiklander #include <string.h> 40817466cbSJens Wiklander 41817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) 42817466cbSJens Wiklander #include <stdio.h> 43817466cbSJens Wiklander #endif 44817466cbSJens Wiklander 45817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) 46817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C) 47817466cbSJens Wiklander #include "mbedtls/platform.h" 48817466cbSJens Wiklander #else 49817466cbSJens Wiklander #include <stdio.h> 50817466cbSJens Wiklander #define mbedtls_printf printf 51817466cbSJens Wiklander #endif /* MBEDTLS_PLATFORM_C */ 52817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 53817466cbSJens Wiklander 54817466cbSJens Wiklander /* 55817466cbSJens Wiklander * CTR_DRBG context initialization 56817466cbSJens Wiklander */ 57817466cbSJens Wiklander void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) 58817466cbSJens Wiklander { 59817466cbSJens Wiklander memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); 60*11fa71b9SJerome Forissier /* Indicate that the entropy nonce length is not set explicitly. 61*11fa71b9SJerome Forissier * See mbedtls_ctr_drbg_set_nonce_len(). */ 62*11fa71b9SJerome Forissier ctx->reseed_counter = -1; 63817466cbSJens Wiklander 64817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 65817466cbSJens Wiklander mbedtls_mutex_init( &ctx->mutex ); 66817466cbSJens Wiklander #endif 67817466cbSJens Wiklander } 68817466cbSJens Wiklander 69817466cbSJens Wiklander void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) 70817466cbSJens Wiklander { 71817466cbSJens Wiklander if( ctx == NULL ) 72817466cbSJens Wiklander return; 73817466cbSJens Wiklander 74817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 75817466cbSJens Wiklander mbedtls_mutex_free( &ctx->mutex ); 76817466cbSJens Wiklander #endif 77817466cbSJens Wiklander mbedtls_aes_free( &ctx->aes_ctx ); 783d3b0591SJens Wiklander mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); 79817466cbSJens Wiklander } 80817466cbSJens Wiklander 81*11fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, 82*11fa71b9SJerome Forissier int resistance ) 83817466cbSJens Wiklander { 84817466cbSJens Wiklander ctx->prediction_resistance = resistance; 85817466cbSJens Wiklander } 86817466cbSJens Wiklander 87*11fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, 88*11fa71b9SJerome Forissier size_t len ) 89817466cbSJens Wiklander { 90817466cbSJens Wiklander ctx->entropy_len = len; 91817466cbSJens Wiklander } 92817466cbSJens Wiklander 93*11fa71b9SJerome Forissier int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx, 94*11fa71b9SJerome Forissier size_t len ) 95*11fa71b9SJerome Forissier { 96*11fa71b9SJerome Forissier /* If mbedtls_ctr_drbg_seed() has already been called, it's 97*11fa71b9SJerome Forissier * too late. Return the error code that's closest to making sense. */ 98*11fa71b9SJerome Forissier if( ctx->f_entropy != NULL ) 99*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); 100*11fa71b9SJerome Forissier 101*11fa71b9SJerome Forissier if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) 102*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 103*11fa71b9SJerome Forissier #if SIZE_MAX > INT_MAX 104*11fa71b9SJerome Forissier /* This shouldn't be an issue because 105*11fa71b9SJerome Forissier * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible 106*11fa71b9SJerome Forissier * configuration, but make sure anyway. */ 107*11fa71b9SJerome Forissier if( len > INT_MAX ) 108*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 109*11fa71b9SJerome Forissier #endif 110*11fa71b9SJerome Forissier 111*11fa71b9SJerome Forissier /* For backward compatibility with Mbed TLS <= 2.19, store the 112*11fa71b9SJerome Forissier * entropy nonce length in a field that already exists, but isn't 113*11fa71b9SJerome Forissier * used until after the initial seeding. */ 114*11fa71b9SJerome Forissier /* Due to the capping of len above, the value fits in an int. */ 115*11fa71b9SJerome Forissier ctx->reseed_counter = (int) len; 116*11fa71b9SJerome Forissier return( 0 ); 117*11fa71b9SJerome Forissier } 118*11fa71b9SJerome Forissier 119*11fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, 120*11fa71b9SJerome Forissier int interval ) 121817466cbSJens Wiklander { 122817466cbSJens Wiklander ctx->reseed_interval = interval; 123817466cbSJens Wiklander } 124817466cbSJens Wiklander 125817466cbSJens Wiklander static int block_cipher_df( unsigned char *output, 126817466cbSJens Wiklander const unsigned char *data, size_t data_len ) 127817466cbSJens Wiklander { 128*11fa71b9SJerome Forissier unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 129*11fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; 130817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; 131817466cbSJens Wiklander unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; 132817466cbSJens Wiklander unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; 133817466cbSJens Wiklander unsigned char *p, *iv; 134817466cbSJens Wiklander mbedtls_aes_context aes_ctx; 1353d3b0591SJens Wiklander int ret = 0; 136817466cbSJens Wiklander 137817466cbSJens Wiklander int i, j; 138817466cbSJens Wiklander size_t buf_len, use_len; 139817466cbSJens Wiklander 140817466cbSJens Wiklander if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) 141817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 142817466cbSJens Wiklander 143*11fa71b9SJerome Forissier memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 144*11fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 ); 145817466cbSJens Wiklander mbedtls_aes_init( &aes_ctx ); 146817466cbSJens Wiklander 147817466cbSJens Wiklander /* 148817466cbSJens Wiklander * Construct IV (16 bytes) and S in buffer 149817466cbSJens Wiklander * IV = Counter (in 32-bits) padded to 16 with zeroes 150817466cbSJens Wiklander * S = Length input string (in 32-bits) || Length of output (in 32-bits) || 151817466cbSJens Wiklander * data || 0x80 152817466cbSJens Wiklander * (Total is padded to a multiple of 16-bytes with zeroes) 153817466cbSJens Wiklander */ 154817466cbSJens Wiklander p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; 155817466cbSJens Wiklander *p++ = ( data_len >> 24 ) & 0xff; 156817466cbSJens Wiklander *p++ = ( data_len >> 16 ) & 0xff; 157817466cbSJens Wiklander *p++ = ( data_len >> 8 ) & 0xff; 158817466cbSJens Wiklander *p++ = ( data_len ) & 0xff; 159817466cbSJens Wiklander p += 3; 160817466cbSJens Wiklander *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; 161817466cbSJens Wiklander memcpy( p, data, data_len ); 162817466cbSJens Wiklander p[data_len] = 0x80; 163817466cbSJens Wiklander 164817466cbSJens Wiklander buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; 165817466cbSJens Wiklander 166817466cbSJens Wiklander for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) 167817466cbSJens Wiklander key[i] = i; 168817466cbSJens Wiklander 169*11fa71b9SJerome Forissier if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, 170*11fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 1713d3b0591SJens Wiklander { 1723d3b0591SJens Wiklander goto exit; 1733d3b0591SJens Wiklander } 174817466cbSJens Wiklander 175817466cbSJens Wiklander /* 176817466cbSJens Wiklander * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data 177817466cbSJens Wiklander */ 178817466cbSJens Wiklander for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) 179817466cbSJens Wiklander { 180817466cbSJens Wiklander p = buf; 181817466cbSJens Wiklander memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 182817466cbSJens Wiklander use_len = buf_len; 183817466cbSJens Wiklander 184817466cbSJens Wiklander while( use_len > 0 ) 185817466cbSJens Wiklander { 186817466cbSJens Wiklander for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) 187817466cbSJens Wiklander chain[i] ^= p[i]; 188817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 189817466cbSJens Wiklander use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? 190817466cbSJens Wiklander MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; 191817466cbSJens Wiklander 192*11fa71b9SJerome Forissier if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, 193*11fa71b9SJerome Forissier chain, chain ) ) != 0 ) 1943d3b0591SJens Wiklander { 1953d3b0591SJens Wiklander goto exit; 1963d3b0591SJens Wiklander } 197817466cbSJens Wiklander } 198817466cbSJens Wiklander 199817466cbSJens Wiklander memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 200817466cbSJens Wiklander 201817466cbSJens Wiklander /* 202817466cbSJens Wiklander * Update IV 203817466cbSJens Wiklander */ 204817466cbSJens Wiklander buf[3]++; 205817466cbSJens Wiklander } 206817466cbSJens Wiklander 207817466cbSJens Wiklander /* 208817466cbSJens Wiklander * Do final encryption with reduced data 209817466cbSJens Wiklander */ 210*11fa71b9SJerome Forissier if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, 211*11fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 2123d3b0591SJens Wiklander { 2133d3b0591SJens Wiklander goto exit; 2143d3b0591SJens Wiklander } 215817466cbSJens Wiklander iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; 216817466cbSJens Wiklander p = output; 217817466cbSJens Wiklander 218817466cbSJens Wiklander for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) 219817466cbSJens Wiklander { 220*11fa71b9SJerome Forissier if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, 221*11fa71b9SJerome Forissier iv, iv ) ) != 0 ) 2223d3b0591SJens Wiklander { 2233d3b0591SJens Wiklander goto exit; 2243d3b0591SJens Wiklander } 225817466cbSJens Wiklander memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); 226817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 227817466cbSJens Wiklander } 2283d3b0591SJens Wiklander exit: 229817466cbSJens Wiklander mbedtls_aes_free( &aes_ctx ); 2303d3b0591SJens Wiklander /* 2313d3b0591SJens Wiklander * tidy up the stack 2323d3b0591SJens Wiklander */ 2333d3b0591SJens Wiklander mbedtls_platform_zeroize( buf, sizeof( buf ) ); 2343d3b0591SJens Wiklander mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 2353d3b0591SJens Wiklander mbedtls_platform_zeroize( key, sizeof( key ) ); 2363d3b0591SJens Wiklander mbedtls_platform_zeroize( chain, sizeof( chain ) ); 2373d3b0591SJens Wiklander if( 0 != ret ) 2383d3b0591SJens Wiklander { 2393d3b0591SJens Wiklander /* 2403d3b0591SJens Wiklander * wipe partial seed from memory 2413d3b0591SJens Wiklander */ 2423d3b0591SJens Wiklander mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); 243817466cbSJens Wiklander } 244817466cbSJens Wiklander 2453d3b0591SJens Wiklander return( ret ); 2463d3b0591SJens Wiklander } 2473d3b0591SJens Wiklander 2483d3b0591SJens Wiklander /* CTR_DRBG_Update (SP 800-90A §10.2.1.2) 2493d3b0591SJens Wiklander * ctr_drbg_update_internal(ctx, provided_data) 2503d3b0591SJens Wiklander * implements 2513d3b0591SJens Wiklander * CTR_DRBG_Update(provided_data, Key, V) 2523d3b0591SJens Wiklander * with inputs and outputs 2533d3b0591SJens Wiklander * ctx->aes_ctx = Key 2543d3b0591SJens Wiklander * ctx->counter = V 2553d3b0591SJens Wiklander */ 256817466cbSJens Wiklander static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, 257817466cbSJens Wiklander const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) 258817466cbSJens Wiklander { 259817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; 260817466cbSJens Wiklander unsigned char *p = tmp; 261817466cbSJens Wiklander int i, j; 2623d3b0591SJens Wiklander int ret = 0; 263817466cbSJens Wiklander 264817466cbSJens Wiklander memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); 265817466cbSJens Wiklander 266817466cbSJens Wiklander for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) 267817466cbSJens Wiklander { 268817466cbSJens Wiklander /* 269817466cbSJens Wiklander * Increase counter 270817466cbSJens Wiklander */ 271817466cbSJens Wiklander for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) 272817466cbSJens Wiklander if( ++ctx->counter[i - 1] != 0 ) 273817466cbSJens Wiklander break; 274817466cbSJens Wiklander 275817466cbSJens Wiklander /* 276817466cbSJens Wiklander * Crypt counter block 277817466cbSJens Wiklander */ 278*11fa71b9SJerome Forissier if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, 279*11fa71b9SJerome Forissier ctx->counter, p ) ) != 0 ) 280*11fa71b9SJerome Forissier { 2813d3b0591SJens Wiklander goto exit; 282*11fa71b9SJerome Forissier } 283817466cbSJens Wiklander 284817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 285817466cbSJens Wiklander } 286817466cbSJens Wiklander 287817466cbSJens Wiklander for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) 288817466cbSJens Wiklander tmp[i] ^= data[i]; 289817466cbSJens Wiklander 290817466cbSJens Wiklander /* 291817466cbSJens Wiklander * Update key and counter 292817466cbSJens Wiklander */ 293*11fa71b9SJerome Forissier if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, 294*11fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 295*11fa71b9SJerome Forissier { 2963d3b0591SJens Wiklander goto exit; 297*11fa71b9SJerome Forissier } 298*11fa71b9SJerome Forissier memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, 299*11fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE ); 300817466cbSJens Wiklander 3013d3b0591SJens Wiklander exit: 3023d3b0591SJens Wiklander mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 3033d3b0591SJens Wiklander return( ret ); 304817466cbSJens Wiklander } 305817466cbSJens Wiklander 3063d3b0591SJens Wiklander /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 3073d3b0591SJens Wiklander * mbedtls_ctr_drbg_update(ctx, additional, add_len) 3083d3b0591SJens Wiklander * implements 3093d3b0591SJens Wiklander * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 3103d3b0591SJens Wiklander * security_strength) -> initial_working_state 3113d3b0591SJens Wiklander * with inputs 3123d3b0591SJens Wiklander * ctx->counter = all-bits-0 3133d3b0591SJens Wiklander * ctx->aes_ctx = context from all-bits-0 key 3143d3b0591SJens Wiklander * additional[:add_len] = entropy_input || nonce || personalization_string 3153d3b0591SJens Wiklander * and with outputs 3163d3b0591SJens Wiklander * ctx = initial_working_state 3173d3b0591SJens Wiklander */ 3183d3b0591SJens Wiklander int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, 3193d3b0591SJens Wiklander const unsigned char *additional, 3203d3b0591SJens Wiklander size_t add_len ) 321817466cbSJens Wiklander { 322817466cbSJens Wiklander unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 323*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 324817466cbSJens Wiklander 3253d3b0591SJens Wiklander if( add_len == 0 ) 3263d3b0591SJens Wiklander return( 0 ); 3273d3b0591SJens Wiklander 3283d3b0591SJens Wiklander if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) 3293d3b0591SJens Wiklander goto exit; 3303d3b0591SJens Wiklander if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) 3313d3b0591SJens Wiklander goto exit; 3323d3b0591SJens Wiklander 3333d3b0591SJens Wiklander exit: 3343d3b0591SJens Wiklander mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); 3353d3b0591SJens Wiklander return( ret ); 3363d3b0591SJens Wiklander } 3373d3b0591SJens Wiklander 3383d3b0591SJens Wiklander #if !defined(MBEDTLS_DEPRECATED_REMOVED) 3393d3b0591SJens Wiklander void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, 3403d3b0591SJens Wiklander const unsigned char *additional, 3413d3b0591SJens Wiklander size_t add_len ) 342817466cbSJens Wiklander { 343817466cbSJens Wiklander /* MAX_INPUT would be more logical here, but we have to match 344817466cbSJens Wiklander * block_cipher_df()'s limits since we can't propagate errors */ 345817466cbSJens Wiklander if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) 346817466cbSJens Wiklander add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; 3473d3b0591SJens Wiklander (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len ); 348817466cbSJens Wiklander } 3493d3b0591SJens Wiklander #endif /* MBEDTLS_DEPRECATED_REMOVED */ 350817466cbSJens Wiklander 3513d3b0591SJens Wiklander /* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) 352*11fa71b9SJerome Forissier * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len) 3533d3b0591SJens Wiklander * implements 3543d3b0591SJens Wiklander * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) 3553d3b0591SJens Wiklander * -> new_working_state 3563d3b0591SJens Wiklander * with inputs 3573d3b0591SJens Wiklander * ctx contains working_state 3583d3b0591SJens Wiklander * additional[:len] = additional_input 3593d3b0591SJens Wiklander * and entropy_input comes from calling ctx->f_entropy 360*11fa71b9SJerome Forissier * for (ctx->entropy_len + nonce_len) bytes 3613d3b0591SJens Wiklander * and with output 3623d3b0591SJens Wiklander * ctx contains new_working_state 3633d3b0591SJens Wiklander */ 364*11fa71b9SJerome Forissier static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx, 365*11fa71b9SJerome Forissier const unsigned char *additional, 366*11fa71b9SJerome Forissier size_t len, 367*11fa71b9SJerome Forissier size_t nonce_len ) 368817466cbSJens Wiklander { 369817466cbSJens Wiklander unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; 370817466cbSJens Wiklander size_t seedlen = 0; 371*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 372817466cbSJens Wiklander 373*11fa71b9SJerome Forissier if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) 374*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 375*11fa71b9SJerome Forissier if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) 376*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 377*11fa71b9SJerome Forissier if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len ) 378817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 379817466cbSJens Wiklander 380817466cbSJens Wiklander memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); 381817466cbSJens Wiklander 382*11fa71b9SJerome Forissier /* Gather entropy_len bytes of entropy to seed state. */ 383*11fa71b9SJerome Forissier if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) ) 384817466cbSJens Wiklander { 385817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); 386817466cbSJens Wiklander } 387817466cbSJens Wiklander seedlen += ctx->entropy_len; 388817466cbSJens Wiklander 389*11fa71b9SJerome Forissier /* Gather entropy for a nonce if requested. */ 390*11fa71b9SJerome Forissier if( nonce_len != 0 ) 391*11fa71b9SJerome Forissier { 392*11fa71b9SJerome Forissier if( 0 != ctx->f_entropy( ctx->p_entropy, seed, nonce_len ) ) 393*11fa71b9SJerome Forissier { 394*11fa71b9SJerome Forissier return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); 395*11fa71b9SJerome Forissier } 396*11fa71b9SJerome Forissier seedlen += nonce_len; 397*11fa71b9SJerome Forissier } 398*11fa71b9SJerome Forissier 399*11fa71b9SJerome Forissier /* Add additional data if provided. */ 400*11fa71b9SJerome Forissier if( additional != NULL && len != 0 ) 401817466cbSJens Wiklander { 402817466cbSJens Wiklander memcpy( seed + seedlen, additional, len ); 403817466cbSJens Wiklander seedlen += len; 404817466cbSJens Wiklander } 405817466cbSJens Wiklander 406*11fa71b9SJerome Forissier /* Reduce to 384 bits. */ 4073d3b0591SJens Wiklander if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) 4083d3b0591SJens Wiklander goto exit; 409817466cbSJens Wiklander 410*11fa71b9SJerome Forissier /* Update state. */ 4113d3b0591SJens Wiklander if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) 4123d3b0591SJens Wiklander goto exit; 413817466cbSJens Wiklander ctx->reseed_counter = 1; 414817466cbSJens Wiklander 4153d3b0591SJens Wiklander exit: 4163d3b0591SJens Wiklander mbedtls_platform_zeroize( seed, sizeof( seed ) ); 4173d3b0591SJens Wiklander return( ret ); 418817466cbSJens Wiklander } 419817466cbSJens Wiklander 420*11fa71b9SJerome Forissier int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, 421*11fa71b9SJerome Forissier const unsigned char *additional, size_t len ) 422*11fa71b9SJerome Forissier { 423*11fa71b9SJerome Forissier return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) ); 424*11fa71b9SJerome Forissier } 425*11fa71b9SJerome Forissier 426*11fa71b9SJerome Forissier /* Return a "good" nonce length for CTR_DRBG. The chosen nonce length 427*11fa71b9SJerome Forissier * is sufficient to achieve the maximum security strength given the key 428*11fa71b9SJerome Forissier * size and entropy length. If there is enough entropy in the initial 429*11fa71b9SJerome Forissier * call to the entropy function to serve as both the entropy input and 430*11fa71b9SJerome Forissier * the nonce, don't make a second call to get a nonce. */ 431*11fa71b9SJerome Forissier static size_t good_nonce_len( size_t entropy_len ) 432*11fa71b9SJerome Forissier { 433*11fa71b9SJerome Forissier if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 ) 434*11fa71b9SJerome Forissier return( 0 ); 435*11fa71b9SJerome Forissier else 436*11fa71b9SJerome Forissier return( ( entropy_len + 1 ) / 2 ); 437*11fa71b9SJerome Forissier } 438*11fa71b9SJerome Forissier 4395b25c76aSJerome Forissier /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 4405b25c76aSJerome Forissier * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len) 4415b25c76aSJerome Forissier * implements 4425b25c76aSJerome Forissier * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 4435b25c76aSJerome Forissier * security_strength) -> initial_working_state 4445b25c76aSJerome Forissier * with inputs 4455b25c76aSJerome Forissier * custom[:len] = nonce || personalization_string 4465b25c76aSJerome Forissier * where entropy_input comes from f_entropy for ctx->entropy_len bytes 4475b25c76aSJerome Forissier * and with outputs 4485b25c76aSJerome Forissier * ctx = initial_working_state 4495b25c76aSJerome Forissier */ 4505b25c76aSJerome Forissier int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, 4515b25c76aSJerome Forissier int (*f_entropy)(void *, unsigned char *, size_t), 4525b25c76aSJerome Forissier void *p_entropy, 4535b25c76aSJerome Forissier const unsigned char *custom, 4545b25c76aSJerome Forissier size_t len ) 4555b25c76aSJerome Forissier { 456*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 4575b25c76aSJerome Forissier unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; 458*11fa71b9SJerome Forissier size_t nonce_len; 4595b25c76aSJerome Forissier 4605b25c76aSJerome Forissier memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); 4615b25c76aSJerome Forissier 4625b25c76aSJerome Forissier mbedtls_aes_init( &ctx->aes_ctx ); 4635b25c76aSJerome Forissier 4645b25c76aSJerome Forissier ctx->f_entropy = f_entropy; 4655b25c76aSJerome Forissier ctx->p_entropy = p_entropy; 4665b25c76aSJerome Forissier 4675b25c76aSJerome Forissier if( ctx->entropy_len == 0 ) 4685b25c76aSJerome Forissier ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; 469*11fa71b9SJerome Forissier /* ctx->reseed_counter contains the desired amount of entropy to 470*11fa71b9SJerome Forissier * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()). 471*11fa71b9SJerome Forissier * If it's -1, indicating that the entropy nonce length was not set 472*11fa71b9SJerome Forissier * explicitly, use a sufficiently large nonce for security. */ 473*11fa71b9SJerome Forissier nonce_len = ( ctx->reseed_counter >= 0 ? 474*11fa71b9SJerome Forissier (size_t) ctx->reseed_counter : 475*11fa71b9SJerome Forissier good_nonce_len( ctx->entropy_len ) ); 476*11fa71b9SJerome Forissier 4775b25c76aSJerome Forissier ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; 4785b25c76aSJerome Forissier 479*11fa71b9SJerome Forissier /* Initialize with an empty key. */ 480*11fa71b9SJerome Forissier if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, 481*11fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) 4825b25c76aSJerome Forissier { 4835b25c76aSJerome Forissier return( ret ); 4845b25c76aSJerome Forissier } 4855b25c76aSJerome Forissier 486*11fa71b9SJerome Forissier /* Do the initial seeding. */ 487*11fa71b9SJerome Forissier if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len, 488*11fa71b9SJerome Forissier nonce_len ) ) != 0 ) 4895b25c76aSJerome Forissier { 4905b25c76aSJerome Forissier return( ret ); 4915b25c76aSJerome Forissier } 4925b25c76aSJerome Forissier return( 0 ); 4935b25c76aSJerome Forissier } 4945b25c76aSJerome Forissier 4953d3b0591SJens Wiklander /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) 4963d3b0591SJens Wiklander * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) 4973d3b0591SJens Wiklander * implements 4983d3b0591SJens Wiklander * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) 4993d3b0591SJens Wiklander * -> working_state_after_reseed 5003d3b0591SJens Wiklander * if required, then 5013d3b0591SJens Wiklander * CTR_DRBG_Generate(working_state_after_reseed, 5023d3b0591SJens Wiklander * requested_number_of_bits, additional_input) 5033d3b0591SJens Wiklander * -> status, returned_bits, new_working_state 5043d3b0591SJens Wiklander * with inputs 5053d3b0591SJens Wiklander * ctx contains working_state 5063d3b0591SJens Wiklander * requested_number_of_bits = 8 * output_len 5073d3b0591SJens Wiklander * additional[:add_len] = additional_input 5083d3b0591SJens Wiklander * and entropy_input comes from calling ctx->f_entropy 5093d3b0591SJens Wiklander * and with outputs 5103d3b0591SJens Wiklander * status = SUCCESS (this function does the reseed internally) 5113d3b0591SJens Wiklander * returned_bits = output[:output_len] 5123d3b0591SJens Wiklander * ctx contains new_working_state 5133d3b0591SJens Wiklander */ 514817466cbSJens Wiklander int mbedtls_ctr_drbg_random_with_add( void *p_rng, 515817466cbSJens Wiklander unsigned char *output, size_t output_len, 516817466cbSJens Wiklander const unsigned char *additional, size_t add_len ) 517817466cbSJens Wiklander { 518817466cbSJens Wiklander int ret = 0; 519817466cbSJens Wiklander mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 520817466cbSJens Wiklander unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 521817466cbSJens Wiklander unsigned char *p = output; 522817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; 523817466cbSJens Wiklander int i; 524817466cbSJens Wiklander size_t use_len; 525817466cbSJens Wiklander 526817466cbSJens Wiklander if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST ) 527817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ); 528817466cbSJens Wiklander 529817466cbSJens Wiklander if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT ) 530817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); 531817466cbSJens Wiklander 532817466cbSJens Wiklander memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); 533817466cbSJens Wiklander 534817466cbSJens Wiklander if( ctx->reseed_counter > ctx->reseed_interval || 535817466cbSJens Wiklander ctx->prediction_resistance ) 536817466cbSJens Wiklander { 537817466cbSJens Wiklander if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) 5383d3b0591SJens Wiklander { 539817466cbSJens Wiklander return( ret ); 5403d3b0591SJens Wiklander } 541817466cbSJens Wiklander add_len = 0; 542817466cbSJens Wiklander } 543817466cbSJens Wiklander 544817466cbSJens Wiklander if( add_len > 0 ) 545817466cbSJens Wiklander { 5463d3b0591SJens Wiklander if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) 5473d3b0591SJens Wiklander goto exit; 5483d3b0591SJens Wiklander if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) 5493d3b0591SJens Wiklander goto exit; 550817466cbSJens Wiklander } 551817466cbSJens Wiklander 552817466cbSJens Wiklander while( output_len > 0 ) 553817466cbSJens Wiklander { 554817466cbSJens Wiklander /* 555817466cbSJens Wiklander * Increase counter 556817466cbSJens Wiklander */ 557817466cbSJens Wiklander for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) 558817466cbSJens Wiklander if( ++ctx->counter[i - 1] != 0 ) 559817466cbSJens Wiklander break; 560817466cbSJens Wiklander 561817466cbSJens Wiklander /* 562817466cbSJens Wiklander * Crypt counter block 563817466cbSJens Wiklander */ 564*11fa71b9SJerome Forissier if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, 565*11fa71b9SJerome Forissier ctx->counter, tmp ) ) != 0 ) 566*11fa71b9SJerome Forissier { 5673d3b0591SJens Wiklander goto exit; 568*11fa71b9SJerome Forissier } 569817466cbSJens Wiklander 570*11fa71b9SJerome Forissier use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) 571*11fa71b9SJerome Forissier ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len; 572817466cbSJens Wiklander /* 573817466cbSJens Wiklander * Copy random block to destination 574817466cbSJens Wiklander */ 575817466cbSJens Wiklander memcpy( p, tmp, use_len ); 576817466cbSJens Wiklander p += use_len; 577817466cbSJens Wiklander output_len -= use_len; 578817466cbSJens Wiklander } 579817466cbSJens Wiklander 5803d3b0591SJens Wiklander if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) 5813d3b0591SJens Wiklander goto exit; 582817466cbSJens Wiklander 583817466cbSJens Wiklander ctx->reseed_counter++; 584817466cbSJens Wiklander 5853d3b0591SJens Wiklander exit: 5863d3b0591SJens Wiklander mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); 5873d3b0591SJens Wiklander mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); 5885b25c76aSJerome Forissier return( ret ); 589817466cbSJens Wiklander } 590817466cbSJens Wiklander 591*11fa71b9SJerome Forissier int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, 592*11fa71b9SJerome Forissier size_t output_len ) 593817466cbSJens Wiklander { 594*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 595817466cbSJens Wiklander mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 596817466cbSJens Wiklander 597817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 598817466cbSJens Wiklander if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) 599817466cbSJens Wiklander return( ret ); 600817466cbSJens Wiklander #endif 601817466cbSJens Wiklander 602817466cbSJens Wiklander ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 ); 603817466cbSJens Wiklander 604817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 605817466cbSJens Wiklander if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) 606817466cbSJens Wiklander return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); 607817466cbSJens Wiklander #endif 608817466cbSJens Wiklander 609817466cbSJens Wiklander return( ret ); 610817466cbSJens Wiklander } 611817466cbSJens Wiklander 612817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) 613*11fa71b9SJerome Forissier int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, 614*11fa71b9SJerome Forissier const char *path ) 615817466cbSJens Wiklander { 616817466cbSJens Wiklander int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 617817466cbSJens Wiklander FILE *f; 618817466cbSJens Wiklander unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; 619817466cbSJens Wiklander 620817466cbSJens Wiklander if( ( f = fopen( path, "wb" ) ) == NULL ) 621817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); 622817466cbSJens Wiklander 623*11fa71b9SJerome Forissier if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, 624*11fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 ) 625817466cbSJens Wiklander goto exit; 626817466cbSJens Wiklander 627*11fa71b9SJerome Forissier if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != 628*11fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_MAX_INPUT ) 629*11fa71b9SJerome Forissier { 630817466cbSJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 631*11fa71b9SJerome Forissier } 6323d3b0591SJens Wiklander else 633*11fa71b9SJerome Forissier { 634817466cbSJens Wiklander ret = 0; 635*11fa71b9SJerome Forissier } 636817466cbSJens Wiklander 637817466cbSJens Wiklander exit: 6383d3b0591SJens Wiklander mbedtls_platform_zeroize( buf, sizeof( buf ) ); 6393d3b0591SJens Wiklander 640817466cbSJens Wiklander fclose( f ); 641817466cbSJens Wiklander return( ret ); 642817466cbSJens Wiklander } 643817466cbSJens Wiklander 644*11fa71b9SJerome Forissier int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, 645*11fa71b9SJerome Forissier const char *path ) 646817466cbSJens Wiklander { 6473d3b0591SJens Wiklander int ret = 0; 6483d3b0591SJens Wiklander FILE *f = NULL; 649817466cbSJens Wiklander size_t n; 650817466cbSJens Wiklander unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; 6513d3b0591SJens Wiklander unsigned char c; 652817466cbSJens Wiklander 653817466cbSJens Wiklander if( ( f = fopen( path, "rb" ) ) == NULL ) 654817466cbSJens Wiklander return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); 655817466cbSJens Wiklander 6563d3b0591SJens Wiklander n = fread( buf, 1, sizeof( buf ), f ); 6573d3b0591SJens Wiklander if( fread( &c, 1, 1, f ) != 0 ) 658817466cbSJens Wiklander { 6593d3b0591SJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 6603d3b0591SJens Wiklander goto exit; 661817466cbSJens Wiklander } 6623d3b0591SJens Wiklander if( n == 0 || ferror( f ) ) 663817466cbSJens Wiklander { 6643d3b0591SJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 6653d3b0591SJens Wiklander goto exit; 666817466cbSJens Wiklander } 667817466cbSJens Wiklander fclose( f ); 6683d3b0591SJens Wiklander f = NULL; 669817466cbSJens Wiklander 6703d3b0591SJens Wiklander ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n ); 671817466cbSJens Wiklander 6723d3b0591SJens Wiklander exit: 6733d3b0591SJens Wiklander mbedtls_platform_zeroize( buf, sizeof( buf ) ); 6743d3b0591SJens Wiklander if( f != NULL ) 6753d3b0591SJens Wiklander fclose( f ); 6763d3b0591SJens Wiklander if( ret != 0 ) 6773d3b0591SJens Wiklander return( ret ); 678817466cbSJens Wiklander return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); 679817466cbSJens Wiklander } 680817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */ 681817466cbSJens Wiklander 682817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) 683817466cbSJens Wiklander 684817466cbSJens Wiklander static const unsigned char entropy_source_pr[96] = 685817466cbSJens Wiklander { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16, 686817466cbSJens Wiklander 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02, 687817466cbSJens Wiklander 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b, 688817466cbSJens Wiklander 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb, 689817466cbSJens Wiklander 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9, 690817466cbSJens Wiklander 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95, 691817466cbSJens Wiklander 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63, 692817466cbSJens Wiklander 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3, 693817466cbSJens Wiklander 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31, 694817466cbSJens Wiklander 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4, 695817466cbSJens Wiklander 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56, 696817466cbSJens Wiklander 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 }; 697817466cbSJens Wiklander 698817466cbSJens Wiklander static const unsigned char entropy_source_nopr[64] = 699817466cbSJens Wiklander { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14, 700817466cbSJens Wiklander 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe, 701817466cbSJens Wiklander 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d, 702817466cbSJens Wiklander 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20, 703817466cbSJens Wiklander 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9, 704817466cbSJens Wiklander 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46, 705817466cbSJens Wiklander 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e, 706817466cbSJens Wiklander 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e }; 707817466cbSJens Wiklander 708817466cbSJens Wiklander static const unsigned char nonce_pers_pr[16] = 709817466cbSJens Wiklander { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2, 710817466cbSJens Wiklander 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c }; 711817466cbSJens Wiklander 712817466cbSJens Wiklander static const unsigned char nonce_pers_nopr[16] = 713817466cbSJens Wiklander { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5, 714817466cbSJens Wiklander 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f }; 715817466cbSJens Wiklander 716*11fa71b9SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) 717*11fa71b9SJerome Forissier static const unsigned char result_pr[16] = 718*11fa71b9SJerome Forissier { 0x95, 0x3c, 0xa5, 0xbd, 0x44, 0x1, 0x34, 0xb7, 719*11fa71b9SJerome Forissier 0x13, 0x58, 0x3e, 0x6a, 0x6c, 0x7e, 0x88, 0x8a }; 720*11fa71b9SJerome Forissier 721*11fa71b9SJerome Forissier static const unsigned char result_nopr[16] = 722*11fa71b9SJerome Forissier { 0x6c, 0x25, 0x27, 0x95, 0xa3, 0x62, 0xd6, 0xdb, 723*11fa71b9SJerome Forissier 0x90, 0xfd, 0x69, 0xb5, 0x42, 0x9, 0x4b, 0x84 }; 724*11fa71b9SJerome Forissier #else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ 725817466cbSJens Wiklander static const unsigned char result_pr[16] = 726817466cbSJens Wiklander { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f, 727817466cbSJens Wiklander 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 }; 728817466cbSJens Wiklander 729817466cbSJens Wiklander static const unsigned char result_nopr[16] = 730817466cbSJens Wiklander { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88, 731817466cbSJens Wiklander 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f }; 732*11fa71b9SJerome Forissier #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ 733817466cbSJens Wiklander 734817466cbSJens Wiklander static size_t test_offset; 735817466cbSJens Wiklander static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, 736817466cbSJens Wiklander size_t len ) 737817466cbSJens Wiklander { 738817466cbSJens Wiklander const unsigned char *p = data; 739817466cbSJens Wiklander memcpy( buf, p + test_offset, len ); 740817466cbSJens Wiklander test_offset += len; 741817466cbSJens Wiklander return( 0 ); 742817466cbSJens Wiklander } 743817466cbSJens Wiklander 744817466cbSJens Wiklander #define CHK( c ) if( (c) != 0 ) \ 745817466cbSJens Wiklander { \ 746817466cbSJens Wiklander if( verbose != 0 ) \ 747817466cbSJens Wiklander mbedtls_printf( "failed\n" ); \ 748817466cbSJens Wiklander return( 1 ); \ 749817466cbSJens Wiklander } 750817466cbSJens Wiklander 751817466cbSJens Wiklander /* 752817466cbSJens Wiklander * Checkup routine 753817466cbSJens Wiklander */ 754817466cbSJens Wiklander int mbedtls_ctr_drbg_self_test( int verbose ) 755817466cbSJens Wiklander { 756817466cbSJens Wiklander mbedtls_ctr_drbg_context ctx; 757817466cbSJens Wiklander unsigned char buf[16]; 758817466cbSJens Wiklander 759817466cbSJens Wiklander mbedtls_ctr_drbg_init( &ctx ); 760817466cbSJens Wiklander 761817466cbSJens Wiklander /* 762817466cbSJens Wiklander * Based on a NIST CTR_DRBG test vector (PR = True) 763817466cbSJens Wiklander */ 764817466cbSJens Wiklander if( verbose != 0 ) 765817466cbSJens Wiklander mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); 766817466cbSJens Wiklander 767817466cbSJens Wiklander test_offset = 0; 7685b25c76aSJerome Forissier mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); 769*11fa71b9SJerome Forissier mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 ); 7705b25c76aSJerome Forissier CHK( mbedtls_ctr_drbg_seed( &ctx, 7715b25c76aSJerome Forissier ctr_drbg_self_test_entropy, 7725b25c76aSJerome Forissier (void *) entropy_source_pr, 7735b25c76aSJerome Forissier nonce_pers_pr, 16 ) ); 774817466cbSJens Wiklander mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); 775817466cbSJens Wiklander CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); 776817466cbSJens Wiklander CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); 777817466cbSJens Wiklander CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); 778817466cbSJens Wiklander 779817466cbSJens Wiklander mbedtls_ctr_drbg_free( &ctx ); 780817466cbSJens Wiklander 781817466cbSJens Wiklander if( verbose != 0 ) 782817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 783817466cbSJens Wiklander 784817466cbSJens Wiklander /* 785817466cbSJens Wiklander * Based on a NIST CTR_DRBG test vector (PR = FALSE) 786817466cbSJens Wiklander */ 787817466cbSJens Wiklander if( verbose != 0 ) 788817466cbSJens Wiklander mbedtls_printf( " CTR_DRBG (PR = FALSE): " ); 789817466cbSJens Wiklander 790817466cbSJens Wiklander mbedtls_ctr_drbg_init( &ctx ); 791817466cbSJens Wiklander 792817466cbSJens Wiklander test_offset = 0; 7935b25c76aSJerome Forissier mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); 794*11fa71b9SJerome Forissier mbedtls_ctr_drbg_set_nonce_len( &ctx, 0 ); 7955b25c76aSJerome Forissier CHK( mbedtls_ctr_drbg_seed( &ctx, 7965b25c76aSJerome Forissier ctr_drbg_self_test_entropy, 7975b25c76aSJerome Forissier (void *) entropy_source_nopr, 7985b25c76aSJerome Forissier nonce_pers_nopr, 16 ) ); 799817466cbSJens Wiklander CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); 800817466cbSJens Wiklander CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); 801817466cbSJens Wiklander CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); 802817466cbSJens Wiklander CHK( memcmp( buf, result_nopr, 16 ) ); 803817466cbSJens Wiklander 804817466cbSJens Wiklander mbedtls_ctr_drbg_free( &ctx ); 805817466cbSJens Wiklander 806817466cbSJens Wiklander if( verbose != 0 ) 807817466cbSJens Wiklander mbedtls_printf( "passed\n" ); 808817466cbSJens Wiklander 809817466cbSJens Wiklander if( verbose != 0 ) 810817466cbSJens Wiklander mbedtls_printf( "\n" ); 811817466cbSJens Wiklander 812817466cbSJens Wiklander return( 0 ); 813817466cbSJens Wiklander } 814817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 815817466cbSJens Wiklander 816817466cbSJens Wiklander #endif /* MBEDTLS_CTR_DRBG_C */ 817