1817466cbSJens Wiklander /* 2817466cbSJens Wiklander * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) 3817466cbSJens Wiklander * 47901324dSJerome Forissier * Copyright The Mbed TLS Contributors 57901324dSJerome Forissier * SPDX-License-Identifier: Apache-2.0 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 /* 203d3b0591SJens Wiklander * The NIST SP 800-90 DRBGs are described in the following publication. 21817466cbSJens Wiklander * 22817466cbSJens Wiklander * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf 23817466cbSJens Wiklander */ 24817466cbSJens Wiklander 257901324dSJerome Forissier #include "common.h" 26817466cbSJens Wiklander 27817466cbSJens Wiklander #if defined(MBEDTLS_CTR_DRBG_C) 28817466cbSJens Wiklander 29817466cbSJens Wiklander #include "mbedtls/ctr_drbg.h" 303d3b0591SJens Wiklander #include "mbedtls/platform_util.h" 3111fa71b9SJerome Forissier #include "mbedtls/error.h" 32817466cbSJens Wiklander 33817466cbSJens Wiklander #include <string.h> 34817466cbSJens Wiklander 35817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) 36817466cbSJens Wiklander #include <stdio.h> 37817466cbSJens Wiklander #endif 38817466cbSJens Wiklander 39817466cbSJens Wiklander #include "mbedtls/platform.h" 40817466cbSJens Wiklander 41817466cbSJens Wiklander /* 42817466cbSJens Wiklander * CTR_DRBG context initialization 43817466cbSJens Wiklander */ 44817466cbSJens Wiklander void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx) 45817466cbSJens Wiklander { 46817466cbSJens Wiklander memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context)); 47*32b31808SJens Wiklander mbedtls_aes_init(&ctx->aes_ctx); 4811fa71b9SJerome Forissier /* Indicate that the entropy nonce length is not set explicitly. 4911fa71b9SJerome Forissier * See mbedtls_ctr_drbg_set_nonce_len(). */ 5011fa71b9SJerome Forissier ctx->reseed_counter = -1; 51817466cbSJens Wiklander 527901324dSJerome Forissier ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; 53817466cbSJens Wiklander } 54817466cbSJens Wiklander 557901324dSJerome Forissier /* 567901324dSJerome Forissier * This function resets CTR_DRBG context to the state immediately 577901324dSJerome Forissier * after initial call of mbedtls_ctr_drbg_init(). 587901324dSJerome Forissier */ 59817466cbSJens Wiklander void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx) 60817466cbSJens Wiklander { 61*32b31808SJens Wiklander if (ctx == NULL) { 62817466cbSJens Wiklander return; 63*32b31808SJens Wiklander } 64817466cbSJens Wiklander 65817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 667901324dSJerome Forissier /* The mutex is initialized iff f_entropy is set. */ 67*32b31808SJens Wiklander if (ctx->f_entropy != NULL) { 68817466cbSJens Wiklander mbedtls_mutex_free(&ctx->mutex); 69*32b31808SJens Wiklander } 70817466cbSJens Wiklander #endif 71817466cbSJens Wiklander mbedtls_aes_free(&ctx->aes_ctx); 723d3b0591SJens Wiklander mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context)); 737901324dSJerome Forissier ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; 747901324dSJerome Forissier ctx->reseed_counter = -1; 75817466cbSJens Wiklander } 76817466cbSJens Wiklander 7711fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx, 7811fa71b9SJerome Forissier int resistance) 79817466cbSJens Wiklander { 80817466cbSJens Wiklander ctx->prediction_resistance = resistance; 81817466cbSJens Wiklander } 82817466cbSJens Wiklander 8311fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx, 8411fa71b9SJerome Forissier size_t len) 85817466cbSJens Wiklander { 86817466cbSJens Wiklander ctx->entropy_len = len; 87817466cbSJens Wiklander } 88817466cbSJens Wiklander 8911fa71b9SJerome Forissier int mbedtls_ctr_drbg_set_nonce_len(mbedtls_ctr_drbg_context *ctx, 9011fa71b9SJerome Forissier size_t len) 9111fa71b9SJerome Forissier { 9211fa71b9SJerome Forissier /* If mbedtls_ctr_drbg_seed() has already been called, it's 9311fa71b9SJerome Forissier * too late. Return the error code that's closest to making sense. */ 94*32b31808SJens Wiklander if (ctx->f_entropy != NULL) { 95*32b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; 96*32b31808SJens Wiklander } 9711fa71b9SJerome Forissier 98*32b31808SJens Wiklander if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { 99*32b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 100*32b31808SJens Wiklander } 101*32b31808SJens Wiklander 10211fa71b9SJerome Forissier /* This shouldn't be an issue because 10311fa71b9SJerome Forissier * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible 10411fa71b9SJerome Forissier * configuration, but make sure anyway. */ 105*32b31808SJens Wiklander if (len > INT_MAX) { 106*32b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 107*32b31808SJens Wiklander } 10811fa71b9SJerome Forissier 10911fa71b9SJerome Forissier /* For backward compatibility with Mbed TLS <= 2.19, store the 11011fa71b9SJerome Forissier * entropy nonce length in a field that already exists, but isn't 11111fa71b9SJerome Forissier * used until after the initial seeding. */ 11211fa71b9SJerome Forissier /* Due to the capping of len above, the value fits in an int. */ 11311fa71b9SJerome Forissier ctx->reseed_counter = (int) len; 114*32b31808SJens Wiklander return 0; 11511fa71b9SJerome Forissier } 11611fa71b9SJerome Forissier 11711fa71b9SJerome Forissier void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx, 11811fa71b9SJerome Forissier int interval) 119817466cbSJens Wiklander { 120817466cbSJens Wiklander ctx->reseed_interval = interval; 121817466cbSJens Wiklander } 122817466cbSJens Wiklander 123817466cbSJens Wiklander static int block_cipher_df(unsigned char *output, 124817466cbSJens Wiklander const unsigned char *data, size_t data_len) 125817466cbSJens Wiklander { 12611fa71b9SJerome Forissier unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 12711fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; 128817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; 129817466cbSJens Wiklander unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; 130817466cbSJens Wiklander unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; 131817466cbSJens Wiklander unsigned char *p, *iv; 132817466cbSJens Wiklander mbedtls_aes_context aes_ctx; 1333d3b0591SJens Wiklander int ret = 0; 134817466cbSJens Wiklander 135817466cbSJens Wiklander int i, j; 136817466cbSJens Wiklander size_t buf_len, use_len; 137817466cbSJens Wiklander 138*32b31808SJens Wiklander if (data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { 139*32b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 140*32b31808SJens Wiklander } 141817466cbSJens Wiklander 14211fa71b9SJerome Forissier memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 14311fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE + 16); 144817466cbSJens Wiklander mbedtls_aes_init(&aes_ctx); 145817466cbSJens Wiklander 146817466cbSJens Wiklander /* 147817466cbSJens Wiklander * Construct IV (16 bytes) and S in buffer 148817466cbSJens Wiklander * IV = Counter (in 32-bits) padded to 16 with zeroes 149817466cbSJens Wiklander * S = Length input string (in 32-bits) || Length of output (in 32-bits) || 150817466cbSJens Wiklander * data || 0x80 151817466cbSJens Wiklander * (Total is padded to a multiple of 16-bytes with zeroes) 152817466cbSJens Wiklander */ 153817466cbSJens Wiklander p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; 154039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(data_len, p, 0); 155039e02dfSJerome Forissier p += 4 + 3; 156817466cbSJens Wiklander *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; 157817466cbSJens Wiklander memcpy(p, data, data_len); 158817466cbSJens Wiklander p[data_len] = 0x80; 159817466cbSJens Wiklander 160817466cbSJens Wiklander buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; 161817466cbSJens Wiklander 162*32b31808SJens Wiklander for (i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++) { 163817466cbSJens Wiklander key[i] = i; 164*32b31808SJens Wiklander } 165817466cbSJens Wiklander 16611fa71b9SJerome Forissier if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key, 167*32b31808SJens Wiklander MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { 1683d3b0591SJens Wiklander goto exit; 1693d3b0591SJens Wiklander } 170817466cbSJens Wiklander 171817466cbSJens Wiklander /* 172817466cbSJens Wiklander * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data 173817466cbSJens Wiklander */ 174*32b31808SJens Wiklander for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { 175817466cbSJens Wiklander p = buf; 176817466cbSJens Wiklander memset(chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE); 177817466cbSJens Wiklander use_len = buf_len; 178817466cbSJens Wiklander 179*32b31808SJens Wiklander while (use_len > 0) { 180*32b31808SJens Wiklander mbedtls_xor(chain, chain, p, MBEDTLS_CTR_DRBG_BLOCKSIZE); 181817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 182817466cbSJens Wiklander use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ? 183817466cbSJens Wiklander MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; 184817466cbSJens Wiklander 18511fa71b9SJerome Forissier if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, 186*32b31808SJens Wiklander chain, chain)) != 0) { 1873d3b0591SJens Wiklander goto exit; 1883d3b0591SJens Wiklander } 189817466cbSJens Wiklander } 190817466cbSJens Wiklander 191817466cbSJens Wiklander memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE); 192817466cbSJens Wiklander 193817466cbSJens Wiklander /* 194817466cbSJens Wiklander * Update IV 195817466cbSJens Wiklander */ 196817466cbSJens Wiklander buf[3]++; 197817466cbSJens Wiklander } 198817466cbSJens Wiklander 199817466cbSJens Wiklander /* 200817466cbSJens Wiklander * Do final encryption with reduced data 201817466cbSJens Wiklander */ 20211fa71b9SJerome Forissier if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp, 203*32b31808SJens Wiklander MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { 2043d3b0591SJens Wiklander goto exit; 2053d3b0591SJens Wiklander } 206817466cbSJens Wiklander iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; 207817466cbSJens Wiklander p = output; 208817466cbSJens Wiklander 209*32b31808SJens Wiklander for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { 21011fa71b9SJerome Forissier if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, 211*32b31808SJens Wiklander iv, iv)) != 0) { 2123d3b0591SJens Wiklander goto exit; 2133d3b0591SJens Wiklander } 214817466cbSJens Wiklander memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE); 215817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 216817466cbSJens Wiklander } 2173d3b0591SJens Wiklander exit: 218817466cbSJens Wiklander mbedtls_aes_free(&aes_ctx); 2193d3b0591SJens Wiklander /* 2203d3b0591SJens Wiklander * tidy up the stack 2213d3b0591SJens Wiklander */ 2223d3b0591SJens Wiklander mbedtls_platform_zeroize(buf, sizeof(buf)); 2233d3b0591SJens Wiklander mbedtls_platform_zeroize(tmp, sizeof(tmp)); 2243d3b0591SJens Wiklander mbedtls_platform_zeroize(key, sizeof(key)); 2253d3b0591SJens Wiklander mbedtls_platform_zeroize(chain, sizeof(chain)); 226*32b31808SJens Wiklander if (0 != ret) { 2273d3b0591SJens Wiklander /* 2283d3b0591SJens Wiklander * wipe partial seed from memory 2293d3b0591SJens Wiklander */ 2303d3b0591SJens Wiklander mbedtls_platform_zeroize(output, MBEDTLS_CTR_DRBG_SEEDLEN); 231817466cbSJens Wiklander } 232817466cbSJens Wiklander 233*32b31808SJens Wiklander return ret; 2343d3b0591SJens Wiklander } 2353d3b0591SJens Wiklander 2363d3b0591SJens Wiklander /* CTR_DRBG_Update (SP 800-90A §10.2.1.2) 2373d3b0591SJens Wiklander * ctr_drbg_update_internal(ctx, provided_data) 2383d3b0591SJens Wiklander * implements 2393d3b0591SJens Wiklander * CTR_DRBG_Update(provided_data, Key, V) 2403d3b0591SJens Wiklander * with inputs and outputs 2413d3b0591SJens Wiklander * ctx->aes_ctx = Key 2423d3b0591SJens Wiklander * ctx->counter = V 2433d3b0591SJens Wiklander */ 244817466cbSJens Wiklander static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx, 245817466cbSJens Wiklander const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN]) 246817466cbSJens Wiklander { 247817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; 248817466cbSJens Wiklander unsigned char *p = tmp; 249817466cbSJens Wiklander int i, j; 2503d3b0591SJens Wiklander int ret = 0; 251817466cbSJens Wiklander 252817466cbSJens Wiklander memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN); 253817466cbSJens Wiklander 254*32b31808SJens Wiklander for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) { 255817466cbSJens Wiklander /* 256817466cbSJens Wiklander * Increase counter 257817466cbSJens Wiklander */ 258*32b31808SJens Wiklander for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) { 259*32b31808SJens Wiklander if (++ctx->counter[i - 1] != 0) { 260817466cbSJens Wiklander break; 261*32b31808SJens Wiklander } 262*32b31808SJens Wiklander } 263817466cbSJens Wiklander 264817466cbSJens Wiklander /* 265817466cbSJens Wiklander * Crypt counter block 266817466cbSJens Wiklander */ 26711fa71b9SJerome Forissier if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, 268*32b31808SJens Wiklander ctx->counter, p)) != 0) { 2693d3b0591SJens Wiklander goto exit; 27011fa71b9SJerome Forissier } 271817466cbSJens Wiklander 272817466cbSJens Wiklander p += MBEDTLS_CTR_DRBG_BLOCKSIZE; 273817466cbSJens Wiklander } 274817466cbSJens Wiklander 275*32b31808SJens Wiklander for (i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++) { 276817466cbSJens Wiklander tmp[i] ^= data[i]; 277*32b31808SJens Wiklander } 278817466cbSJens Wiklander 279817466cbSJens Wiklander /* 280817466cbSJens Wiklander * Update key and counter 281817466cbSJens Wiklander */ 28211fa71b9SJerome Forissier if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp, 283*32b31808SJens Wiklander MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { 2843d3b0591SJens Wiklander goto exit; 28511fa71b9SJerome Forissier } 28611fa71b9SJerome Forissier memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, 28711fa71b9SJerome Forissier MBEDTLS_CTR_DRBG_BLOCKSIZE); 288817466cbSJens Wiklander 2893d3b0591SJens Wiklander exit: 2903d3b0591SJens Wiklander mbedtls_platform_zeroize(tmp, sizeof(tmp)); 291*32b31808SJens Wiklander return ret; 292817466cbSJens Wiklander } 293817466cbSJens Wiklander 2943d3b0591SJens Wiklander /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 2953d3b0591SJens Wiklander * mbedtls_ctr_drbg_update(ctx, additional, add_len) 2963d3b0591SJens Wiklander * implements 2973d3b0591SJens Wiklander * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 2983d3b0591SJens Wiklander * security_strength) -> initial_working_state 2993d3b0591SJens Wiklander * with inputs 3003d3b0591SJens Wiklander * ctx->counter = all-bits-0 3013d3b0591SJens Wiklander * ctx->aes_ctx = context from all-bits-0 key 3023d3b0591SJens Wiklander * additional[:add_len] = entropy_input || nonce || personalization_string 3033d3b0591SJens Wiklander * and with outputs 3043d3b0591SJens Wiklander * ctx = initial_working_state 3053d3b0591SJens Wiklander */ 306*32b31808SJens Wiklander int mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx, 3073d3b0591SJens Wiklander const unsigned char *additional, 3083d3b0591SJens Wiklander size_t add_len) 309817466cbSJens Wiklander { 310817466cbSJens Wiklander unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 31111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 312817466cbSJens Wiklander 313*32b31808SJens Wiklander if (add_len == 0) { 314*32b31808SJens Wiklander return 0; 315*32b31808SJens Wiklander } 3163d3b0591SJens Wiklander 317*32b31808SJens Wiklander if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) { 3183d3b0591SJens Wiklander goto exit; 319*32b31808SJens Wiklander } 320*32b31808SJens Wiklander if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) { 3213d3b0591SJens Wiklander goto exit; 322*32b31808SJens Wiklander } 3233d3b0591SJens Wiklander 3243d3b0591SJens Wiklander exit: 3253d3b0591SJens Wiklander mbedtls_platform_zeroize(add_input, sizeof(add_input)); 326*32b31808SJens Wiklander return ret; 3273d3b0591SJens Wiklander } 3283d3b0591SJens Wiklander 3293d3b0591SJens Wiklander /* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) 33011fa71b9SJerome Forissier * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len) 3313d3b0591SJens Wiklander * implements 3323d3b0591SJens Wiklander * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) 3333d3b0591SJens Wiklander * -> new_working_state 3343d3b0591SJens Wiklander * with inputs 3353d3b0591SJens Wiklander * ctx contains working_state 3363d3b0591SJens Wiklander * additional[:len] = additional_input 3373d3b0591SJens Wiklander * and entropy_input comes from calling ctx->f_entropy 33811fa71b9SJerome Forissier * for (ctx->entropy_len + nonce_len) bytes 3393d3b0591SJens Wiklander * and with output 3403d3b0591SJens Wiklander * ctx contains new_working_state 3413d3b0591SJens Wiklander */ 34211fa71b9SJerome Forissier static int mbedtls_ctr_drbg_reseed_internal(mbedtls_ctr_drbg_context *ctx, 34311fa71b9SJerome Forissier const unsigned char *additional, 34411fa71b9SJerome Forissier size_t len, 34511fa71b9SJerome Forissier size_t nonce_len) 346817466cbSJens Wiklander { 347817466cbSJens Wiklander unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; 348817466cbSJens Wiklander size_t seedlen = 0; 34911fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 350817466cbSJens Wiklander 351*32b31808SJens Wiklander if (ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) { 352*32b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 353*32b31808SJens Wiklander } 354*32b31808SJens Wiklander if (nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len) { 355*32b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 356*32b31808SJens Wiklander } 357*32b31808SJens Wiklander if (len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len) { 358*32b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 359*32b31808SJens Wiklander } 360817466cbSJens Wiklander 361817466cbSJens Wiklander memset(seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT); 362817466cbSJens Wiklander 36311fa71b9SJerome Forissier /* Gather entropy_len bytes of entropy to seed state. */ 364*32b31808SJens Wiklander if (0 != ctx->f_entropy(ctx->p_entropy, seed, ctx->entropy_len)) { 365*32b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; 366817466cbSJens Wiklander } 367817466cbSJens Wiklander seedlen += ctx->entropy_len; 368817466cbSJens Wiklander 36911fa71b9SJerome Forissier /* Gather entropy for a nonce if requested. */ 370*32b31808SJens Wiklander if (nonce_len != 0) { 371*32b31808SJens Wiklander if (0 != ctx->f_entropy(ctx->p_entropy, seed + seedlen, nonce_len)) { 372*32b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; 37311fa71b9SJerome Forissier } 37411fa71b9SJerome Forissier seedlen += nonce_len; 37511fa71b9SJerome Forissier } 37611fa71b9SJerome Forissier 37711fa71b9SJerome Forissier /* Add additional data if provided. */ 378*32b31808SJens Wiklander if (additional != NULL && len != 0) { 379817466cbSJens Wiklander memcpy(seed + seedlen, additional, len); 380817466cbSJens Wiklander seedlen += len; 381817466cbSJens Wiklander } 382817466cbSJens Wiklander 38311fa71b9SJerome Forissier /* Reduce to 384 bits. */ 384*32b31808SJens Wiklander if ((ret = block_cipher_df(seed, seed, seedlen)) != 0) { 3853d3b0591SJens Wiklander goto exit; 386*32b31808SJens Wiklander } 387817466cbSJens Wiklander 38811fa71b9SJerome Forissier /* Update state. */ 389*32b31808SJens Wiklander if ((ret = ctr_drbg_update_internal(ctx, seed)) != 0) { 3903d3b0591SJens Wiklander goto exit; 391*32b31808SJens Wiklander } 392817466cbSJens Wiklander ctx->reseed_counter = 1; 393817466cbSJens Wiklander 3943d3b0591SJens Wiklander exit: 3953d3b0591SJens Wiklander mbedtls_platform_zeroize(seed, sizeof(seed)); 396*32b31808SJens Wiklander return ret; 397817466cbSJens Wiklander } 398817466cbSJens Wiklander 39911fa71b9SJerome Forissier int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx, 40011fa71b9SJerome Forissier const unsigned char *additional, size_t len) 40111fa71b9SJerome Forissier { 402*32b31808SJens Wiklander return mbedtls_ctr_drbg_reseed_internal(ctx, additional, len, 0); 40311fa71b9SJerome Forissier } 40411fa71b9SJerome Forissier 40511fa71b9SJerome Forissier /* Return a "good" nonce length for CTR_DRBG. The chosen nonce length 40611fa71b9SJerome Forissier * is sufficient to achieve the maximum security strength given the key 40711fa71b9SJerome Forissier * size and entropy length. If there is enough entropy in the initial 40811fa71b9SJerome Forissier * call to the entropy function to serve as both the entropy input and 40911fa71b9SJerome Forissier * the nonce, don't make a second call to get a nonce. */ 41011fa71b9SJerome Forissier static size_t good_nonce_len(size_t entropy_len) 41111fa71b9SJerome Forissier { 412*32b31808SJens Wiklander if (entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2) { 413*32b31808SJens Wiklander return 0; 414*32b31808SJens Wiklander } else { 415*32b31808SJens Wiklander return (entropy_len + 1) / 2; 416*32b31808SJens Wiklander } 41711fa71b9SJerome Forissier } 41811fa71b9SJerome Forissier 4195b25c76aSJerome Forissier /* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) 4205b25c76aSJerome Forissier * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len) 4215b25c76aSJerome Forissier * implements 4225b25c76aSJerome Forissier * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, 4235b25c76aSJerome Forissier * security_strength) -> initial_working_state 4245b25c76aSJerome Forissier * with inputs 4255b25c76aSJerome Forissier * custom[:len] = nonce || personalization_string 4265b25c76aSJerome Forissier * where entropy_input comes from f_entropy for ctx->entropy_len bytes 4275b25c76aSJerome Forissier * and with outputs 4285b25c76aSJerome Forissier * ctx = initial_working_state 4295b25c76aSJerome Forissier */ 4305b25c76aSJerome Forissier int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx, 4315b25c76aSJerome Forissier int (*f_entropy)(void *, unsigned char *, size_t), 4325b25c76aSJerome Forissier void *p_entropy, 4335b25c76aSJerome Forissier const unsigned char *custom, 4345b25c76aSJerome Forissier size_t len) 4355b25c76aSJerome Forissier { 43611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 4375b25c76aSJerome Forissier unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; 43811fa71b9SJerome Forissier size_t nonce_len; 4395b25c76aSJerome Forissier 4405b25c76aSJerome Forissier memset(key, 0, MBEDTLS_CTR_DRBG_KEYSIZE); 4415b25c76aSJerome Forissier 4427901324dSJerome Forissier /* The mutex is initialized iff f_entropy is set. */ 4437901324dSJerome Forissier #if defined(MBEDTLS_THREADING_C) 4447901324dSJerome Forissier mbedtls_mutex_init(&ctx->mutex); 4457901324dSJerome Forissier #endif 4467901324dSJerome Forissier 4475b25c76aSJerome Forissier ctx->f_entropy = f_entropy; 4485b25c76aSJerome Forissier ctx->p_entropy = p_entropy; 4495b25c76aSJerome Forissier 450*32b31808SJens Wiklander if (ctx->entropy_len == 0) { 4515b25c76aSJerome Forissier ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; 452*32b31808SJens Wiklander } 45311fa71b9SJerome Forissier /* ctx->reseed_counter contains the desired amount of entropy to 45411fa71b9SJerome Forissier * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()). 45511fa71b9SJerome Forissier * If it's -1, indicating that the entropy nonce length was not set 45611fa71b9SJerome Forissier * explicitly, use a sufficiently large nonce for security. */ 45711fa71b9SJerome Forissier nonce_len = (ctx->reseed_counter >= 0 ? 45811fa71b9SJerome Forissier (size_t) ctx->reseed_counter : 45911fa71b9SJerome Forissier good_nonce_len(ctx->entropy_len)); 46011fa71b9SJerome Forissier 46111fa71b9SJerome Forissier /* Initialize with an empty key. */ 46211fa71b9SJerome Forissier if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key, 463*32b31808SJens Wiklander MBEDTLS_CTR_DRBG_KEYBITS)) != 0) { 464*32b31808SJens Wiklander return ret; 4655b25c76aSJerome Forissier } 4665b25c76aSJerome Forissier 46711fa71b9SJerome Forissier /* Do the initial seeding. */ 46811fa71b9SJerome Forissier if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len, 469*32b31808SJens Wiklander nonce_len)) != 0) { 470*32b31808SJens Wiklander return ret; 4715b25c76aSJerome Forissier } 472*32b31808SJens Wiklander return 0; 4735b25c76aSJerome Forissier } 4745b25c76aSJerome Forissier 4753d3b0591SJens Wiklander /* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) 4763d3b0591SJens Wiklander * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) 4773d3b0591SJens Wiklander * implements 4783d3b0591SJens Wiklander * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) 4793d3b0591SJens Wiklander * -> working_state_after_reseed 4803d3b0591SJens Wiklander * if required, then 4813d3b0591SJens Wiklander * CTR_DRBG_Generate(working_state_after_reseed, 4823d3b0591SJens Wiklander * requested_number_of_bits, additional_input) 4833d3b0591SJens Wiklander * -> status, returned_bits, new_working_state 4843d3b0591SJens Wiklander * with inputs 4853d3b0591SJens Wiklander * ctx contains working_state 4863d3b0591SJens Wiklander * requested_number_of_bits = 8 * output_len 4873d3b0591SJens Wiklander * additional[:add_len] = additional_input 4883d3b0591SJens Wiklander * and entropy_input comes from calling ctx->f_entropy 4893d3b0591SJens Wiklander * and with outputs 4903d3b0591SJens Wiklander * status = SUCCESS (this function does the reseed internally) 4913d3b0591SJens Wiklander * returned_bits = output[:output_len] 4923d3b0591SJens Wiklander * ctx contains new_working_state 4933d3b0591SJens Wiklander */ 494817466cbSJens Wiklander int mbedtls_ctr_drbg_random_with_add(void *p_rng, 495817466cbSJens Wiklander unsigned char *output, size_t output_len, 496817466cbSJens Wiklander const unsigned char *additional, size_t add_len) 497817466cbSJens Wiklander { 498817466cbSJens Wiklander int ret = 0; 499817466cbSJens Wiklander mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 500817466cbSJens Wiklander unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; 501817466cbSJens Wiklander unsigned char *p = output; 502817466cbSJens Wiklander unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; 503817466cbSJens Wiklander int i; 504817466cbSJens Wiklander size_t use_len; 505817466cbSJens Wiklander 506*32b31808SJens Wiklander if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) { 507*32b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG; 508*32b31808SJens Wiklander } 509817466cbSJens Wiklander 510*32b31808SJens Wiklander if (add_len > MBEDTLS_CTR_DRBG_MAX_INPUT) { 511*32b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 512*32b31808SJens Wiklander } 513817466cbSJens Wiklander 514817466cbSJens Wiklander memset(add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN); 515817466cbSJens Wiklander 516817466cbSJens Wiklander if (ctx->reseed_counter > ctx->reseed_interval || 517*32b31808SJens Wiklander ctx->prediction_resistance) { 518*32b31808SJens Wiklander if ((ret = mbedtls_ctr_drbg_reseed(ctx, additional, add_len)) != 0) { 519*32b31808SJens Wiklander return ret; 5203d3b0591SJens Wiklander } 521817466cbSJens Wiklander add_len = 0; 522817466cbSJens Wiklander } 523817466cbSJens Wiklander 524*32b31808SJens Wiklander if (add_len > 0) { 525*32b31808SJens Wiklander if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) { 5263d3b0591SJens Wiklander goto exit; 527817466cbSJens Wiklander } 528*32b31808SJens Wiklander if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) { 529*32b31808SJens Wiklander goto exit; 530*32b31808SJens Wiklander } 531*32b31808SJens Wiklander } 532817466cbSJens Wiklander 533*32b31808SJens Wiklander while (output_len > 0) { 534817466cbSJens Wiklander /* 535817466cbSJens Wiklander * Increase counter 536817466cbSJens Wiklander */ 537*32b31808SJens Wiklander for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) { 538*32b31808SJens Wiklander if (++ctx->counter[i - 1] != 0) { 539817466cbSJens Wiklander break; 540*32b31808SJens Wiklander } 541*32b31808SJens Wiklander } 542817466cbSJens Wiklander 543817466cbSJens Wiklander /* 544817466cbSJens Wiklander * Crypt counter block 545817466cbSJens Wiklander */ 54611fa71b9SJerome Forissier if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, 547*32b31808SJens Wiklander ctx->counter, tmp)) != 0) { 5483d3b0591SJens Wiklander goto exit; 54911fa71b9SJerome Forissier } 550817466cbSJens Wiklander 55111fa71b9SJerome Forissier use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE) 55211fa71b9SJerome Forissier ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len; 553817466cbSJens Wiklander /* 554817466cbSJens Wiklander * Copy random block to destination 555817466cbSJens Wiklander */ 556817466cbSJens Wiklander memcpy(p, tmp, use_len); 557817466cbSJens Wiklander p += use_len; 558817466cbSJens Wiklander output_len -= use_len; 559817466cbSJens Wiklander } 560817466cbSJens Wiklander 561*32b31808SJens Wiklander if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) { 5623d3b0591SJens Wiklander goto exit; 563*32b31808SJens Wiklander } 564817466cbSJens Wiklander 565817466cbSJens Wiklander ctx->reseed_counter++; 566817466cbSJens Wiklander 5673d3b0591SJens Wiklander exit: 5683d3b0591SJens Wiklander mbedtls_platform_zeroize(add_input, sizeof(add_input)); 5693d3b0591SJens Wiklander mbedtls_platform_zeroize(tmp, sizeof(tmp)); 570*32b31808SJens Wiklander return ret; 571817466cbSJens Wiklander } 572817466cbSJens Wiklander 57311fa71b9SJerome Forissier int mbedtls_ctr_drbg_random(void *p_rng, unsigned char *output, 57411fa71b9SJerome Forissier size_t output_len) 575817466cbSJens Wiklander { 57611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 577817466cbSJens Wiklander mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; 578817466cbSJens Wiklander 579817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 580*32b31808SJens Wiklander if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) { 581*32b31808SJens Wiklander return ret; 582*32b31808SJens Wiklander } 583817466cbSJens Wiklander #endif 584817466cbSJens Wiklander 585817466cbSJens Wiklander ret = mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, NULL, 0); 586817466cbSJens Wiklander 587817466cbSJens Wiklander #if defined(MBEDTLS_THREADING_C) 588*32b31808SJens Wiklander if (mbedtls_mutex_unlock(&ctx->mutex) != 0) { 589*32b31808SJens Wiklander return MBEDTLS_ERR_THREADING_MUTEX_ERROR; 590*32b31808SJens Wiklander } 591817466cbSJens Wiklander #endif 592817466cbSJens Wiklander 593*32b31808SJens Wiklander return ret; 594817466cbSJens Wiklander } 595817466cbSJens Wiklander 596817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) 59711fa71b9SJerome Forissier int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx, 59811fa71b9SJerome Forissier const char *path) 599817466cbSJens Wiklander { 600817466cbSJens Wiklander int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 601817466cbSJens Wiklander FILE *f; 602817466cbSJens Wiklander unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT]; 603817466cbSJens Wiklander 604*32b31808SJens Wiklander if ((f = fopen(path, "wb")) == NULL) { 605*32b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 606*32b31808SJens Wiklander } 607*32b31808SJens Wiklander 608*32b31808SJens Wiklander /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ 609*32b31808SJens Wiklander mbedtls_setbuf(f, NULL); 610817466cbSJens Wiklander 61111fa71b9SJerome Forissier if ((ret = mbedtls_ctr_drbg_random(ctx, buf, 612*32b31808SJens Wiklander MBEDTLS_CTR_DRBG_MAX_INPUT)) != 0) { 613817466cbSJens Wiklander goto exit; 614*32b31808SJens Wiklander } 615817466cbSJens Wiklander 61611fa71b9SJerome Forissier if (fwrite(buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f) != 617*32b31808SJens Wiklander MBEDTLS_CTR_DRBG_MAX_INPUT) { 618817466cbSJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 619*32b31808SJens Wiklander } else { 620817466cbSJens Wiklander ret = 0; 62111fa71b9SJerome Forissier } 622817466cbSJens Wiklander 623817466cbSJens Wiklander exit: 6243d3b0591SJens Wiklander mbedtls_platform_zeroize(buf, sizeof(buf)); 6253d3b0591SJens Wiklander 626817466cbSJens Wiklander fclose(f); 627*32b31808SJens Wiklander return ret; 628817466cbSJens Wiklander } 629817466cbSJens Wiklander 63011fa71b9SJerome Forissier int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx, 63111fa71b9SJerome Forissier const char *path) 632817466cbSJens Wiklander { 6333d3b0591SJens Wiklander int ret = 0; 6343d3b0591SJens Wiklander FILE *f = NULL; 635817466cbSJens Wiklander size_t n; 636817466cbSJens Wiklander unsigned char buf[MBEDTLS_CTR_DRBG_MAX_INPUT]; 6373d3b0591SJens Wiklander unsigned char c; 638817466cbSJens Wiklander 639*32b31808SJens Wiklander if ((f = fopen(path, "rb")) == NULL) { 640*32b31808SJens Wiklander return MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 641*32b31808SJens Wiklander } 642*32b31808SJens Wiklander 643*32b31808SJens Wiklander /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */ 644*32b31808SJens Wiklander mbedtls_setbuf(f, NULL); 645817466cbSJens Wiklander 6463d3b0591SJens Wiklander n = fread(buf, 1, sizeof(buf), f); 647*32b31808SJens Wiklander if (fread(&c, 1, 1, f) != 0) { 6483d3b0591SJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; 6493d3b0591SJens Wiklander goto exit; 650817466cbSJens Wiklander } 651*32b31808SJens Wiklander if (n == 0 || ferror(f)) { 6523d3b0591SJens Wiklander ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; 6533d3b0591SJens Wiklander goto exit; 654817466cbSJens Wiklander } 655817466cbSJens Wiklander fclose(f); 6563d3b0591SJens Wiklander f = NULL; 657817466cbSJens Wiklander 658*32b31808SJens Wiklander ret = mbedtls_ctr_drbg_update(ctx, buf, n); 659817466cbSJens Wiklander 6603d3b0591SJens Wiklander exit: 6613d3b0591SJens Wiklander mbedtls_platform_zeroize(buf, sizeof(buf)); 662*32b31808SJens Wiklander if (f != NULL) { 6633d3b0591SJens Wiklander fclose(f); 664*32b31808SJens Wiklander } 665*32b31808SJens Wiklander if (ret != 0) { 666*32b31808SJens Wiklander return ret; 667*32b31808SJens Wiklander } 668*32b31808SJens Wiklander return mbedtls_ctr_drbg_write_seed_file(ctx, path); 669817466cbSJens Wiklander } 670817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */ 671817466cbSJens Wiklander 672817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST) 673817466cbSJens Wiklander 6747901324dSJerome Forissier /* The CTR_DRBG NIST test vectors used here are available at 6757901324dSJerome Forissier * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip 6767901324dSJerome Forissier * 6777901324dSJerome Forissier * The parameters used to derive the test data are: 6787901324dSJerome Forissier * 6797901324dSJerome Forissier * [AES-128 use df] 6807901324dSJerome Forissier * [PredictionResistance = True/False] 6817901324dSJerome Forissier * [EntropyInputLen = 128] 6827901324dSJerome Forissier * [NonceLen = 64] 6837901324dSJerome Forissier * [PersonalizationStringLen = 128] 6847901324dSJerome Forissier * [AdditionalInputLen = 0] 6857901324dSJerome Forissier * [ReturnedBitsLen = 512] 6867901324dSJerome Forissier * 6877901324dSJerome Forissier * [AES-256 use df] 6887901324dSJerome Forissier * [PredictionResistance = True/False] 6897901324dSJerome Forissier * [EntropyInputLen = 256] 6907901324dSJerome Forissier * [NonceLen = 128] 6917901324dSJerome Forissier * [PersonalizationStringLen = 256] 6927901324dSJerome Forissier * [AdditionalInputLen = 0] 6937901324dSJerome Forissier * [ReturnedBitsLen = 512] 6947901324dSJerome Forissier * 6957901324dSJerome Forissier */ 696817466cbSJens Wiklander 69711fa71b9SJerome Forissier #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) 6987901324dSJerome Forissier static const unsigned char entropy_source_pr[] = 6997901324dSJerome Forissier { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb, 7007901324dSJerome Forissier 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92, 7017901324dSJerome Forissier 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8, 7027901324dSJerome Forissier 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20, 7037901324dSJerome Forissier 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0, 7047901324dSJerome Forissier 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad, 7057901324dSJerome Forissier 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 }; 70611fa71b9SJerome Forissier 7077901324dSJerome Forissier static const unsigned char entropy_source_nopr[] = 7087901324dSJerome Forissier { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45, 7097901324dSJerome Forissier 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9, 7107901324dSJerome Forissier 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20, 7117901324dSJerome Forissier 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f, 7127901324dSJerome Forissier 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c }; 7137901324dSJerome Forissier 7147901324dSJerome Forissier static const unsigned char pers_pr[] = 7157901324dSJerome Forissier { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a, 7167901324dSJerome Forissier 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad }; 7177901324dSJerome Forissier 7187901324dSJerome Forissier static const unsigned char pers_nopr[] = 7197901324dSJerome Forissier { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c, 7207901324dSJerome Forissier 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f }; 7217901324dSJerome Forissier 7227901324dSJerome Forissier static const unsigned char result_pr[] = 7237901324dSJerome Forissier { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66, 7247901324dSJerome Forissier 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff, 7257901324dSJerome Forissier 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10, 7267901324dSJerome Forissier 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30, 7277901324dSJerome Forissier 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4, 7287901324dSJerome Forissier 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc, 7297901324dSJerome Forissier 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06, 7307901324dSJerome Forissier 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf }; 7317901324dSJerome Forissier 7327901324dSJerome Forissier static const unsigned char result_nopr[] = 7337901324dSJerome Forissier { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13, 7347901324dSJerome Forissier 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0, 7357901324dSJerome Forissier 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf, 7367901324dSJerome Forissier 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2, 7377901324dSJerome Forissier 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7, 7387901324dSJerome Forissier 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2, 7397901324dSJerome Forissier 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02, 7407901324dSJerome Forissier 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 }; 74111fa71b9SJerome Forissier #else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ 742817466cbSJens Wiklander 7437901324dSJerome Forissier static const unsigned char entropy_source_pr[] = 7447901324dSJerome Forissier { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49, 7457901324dSJerome Forissier 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a, 7467901324dSJerome Forissier 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85, 7477901324dSJerome Forissier 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e, 7487901324dSJerome Forissier 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15, 7497901324dSJerome Forissier 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45, 7507901324dSJerome Forissier 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8, 7517901324dSJerome Forissier 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c, 7527901324dSJerome Forissier 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3, 7537901324dSJerome Forissier 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce, 7547901324dSJerome Forissier 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e, 7557901324dSJerome Forissier 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76, 7567901324dSJerome Forissier 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77, 7577901324dSJerome Forissier 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe }; 7587901324dSJerome Forissier 7597901324dSJerome Forissier static const unsigned char entropy_source_nopr[] = 7607901324dSJerome Forissier { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d, 7617901324dSJerome Forissier 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0, 7627901324dSJerome Forissier 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73, 7637901324dSJerome Forissier 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c, 7647901324dSJerome Forissier 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2, 7657901324dSJerome Forissier 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1, 7667901324dSJerome Forissier 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a, 7677901324dSJerome Forissier 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb, 7687901324dSJerome Forissier 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a, 7697901324dSJerome Forissier 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 }; 7707901324dSJerome Forissier 7717901324dSJerome Forissier static const unsigned char pers_pr[] = 7727901324dSJerome Forissier { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33, 7737901324dSJerome Forissier 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e, 7747901324dSJerome Forissier 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0, 7757901324dSJerome Forissier 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 }; 7767901324dSJerome Forissier 7777901324dSJerome Forissier static const unsigned char pers_nopr[] = 7787901324dSJerome Forissier { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29, 7797901324dSJerome Forissier 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf, 7807901324dSJerome Forissier 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb, 7817901324dSJerome Forissier 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b }; 7827901324dSJerome Forissier 7837901324dSJerome Forissier static const unsigned char result_pr[] = 7847901324dSJerome Forissier { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85, 7857901324dSJerome Forissier 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d, 7867901324dSJerome Forissier 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62, 7877901324dSJerome Forissier 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d, 7887901324dSJerome Forissier 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb, 7897901324dSJerome Forissier 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39, 7907901324dSJerome Forissier 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40, 7917901324dSJerome Forissier 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 }; 7927901324dSJerome Forissier 7937901324dSJerome Forissier static const unsigned char result_nopr[] = 7947901324dSJerome Forissier { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad, 7957901324dSJerome Forissier 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3, 7967901324dSJerome Forissier 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b, 7977901324dSJerome Forissier 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14, 7987901324dSJerome Forissier 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54, 7997901324dSJerome Forissier 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30, 8007901324dSJerome Forissier 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a, 8017901324dSJerome Forissier 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 }; 80211fa71b9SJerome Forissier #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ 803817466cbSJens Wiklander 804817466cbSJens Wiklander static size_t test_offset; 805817466cbSJens Wiklander static int ctr_drbg_self_test_entropy(void *data, unsigned char *buf, 806817466cbSJens Wiklander size_t len) 807817466cbSJens Wiklander { 808817466cbSJens Wiklander const unsigned char *p = data; 809817466cbSJens Wiklander memcpy(buf, p + test_offset, len); 810817466cbSJens Wiklander test_offset += len; 811*32b31808SJens Wiklander return 0; 812817466cbSJens Wiklander } 813817466cbSJens Wiklander 814817466cbSJens Wiklander #define CHK(c) if ((c) != 0) \ 815817466cbSJens Wiklander { \ 816817466cbSJens Wiklander if (verbose != 0) \ 817817466cbSJens Wiklander mbedtls_printf("failed\n"); \ 818*32b31808SJens Wiklander return 1; \ 819817466cbSJens Wiklander } 820817466cbSJens Wiklander 821039e02dfSJerome Forissier #define SELF_TEST_OUTPUT_DISCARD_LENGTH 64 8227901324dSJerome Forissier 823817466cbSJens Wiklander /* 824817466cbSJens Wiklander * Checkup routine 825817466cbSJens Wiklander */ 826817466cbSJens Wiklander int mbedtls_ctr_drbg_self_test(int verbose) 827817466cbSJens Wiklander { 828817466cbSJens Wiklander mbedtls_ctr_drbg_context ctx; 8297901324dSJerome Forissier unsigned char buf[sizeof(result_pr)]; 830817466cbSJens Wiklander 831817466cbSJens Wiklander mbedtls_ctr_drbg_init(&ctx); 832817466cbSJens Wiklander 833817466cbSJens Wiklander /* 834817466cbSJens Wiklander * Based on a NIST CTR_DRBG test vector (PR = True) 835817466cbSJens Wiklander */ 836*32b31808SJens Wiklander if (verbose != 0) { 837817466cbSJens Wiklander mbedtls_printf(" CTR_DRBG (PR = TRUE) : "); 838*32b31808SJens Wiklander } 839817466cbSJens Wiklander 840817466cbSJens Wiklander test_offset = 0; 8417901324dSJerome Forissier mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE); 8427901324dSJerome Forissier mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2); 8435b25c76aSJerome Forissier CHK(mbedtls_ctr_drbg_seed(&ctx, 8445b25c76aSJerome Forissier ctr_drbg_self_test_entropy, 8455b25c76aSJerome Forissier (void *) entropy_source_pr, 8467901324dSJerome Forissier pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE)); 847817466cbSJens Wiklander mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON); 848039e02dfSJerome Forissier CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH)); 8497901324dSJerome Forissier CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_pr))); 8507901324dSJerome Forissier CHK(memcmp(buf, result_pr, sizeof(result_pr))); 851817466cbSJens Wiklander 852817466cbSJens Wiklander mbedtls_ctr_drbg_free(&ctx); 853817466cbSJens Wiklander 854*32b31808SJens Wiklander if (verbose != 0) { 855817466cbSJens Wiklander mbedtls_printf("passed\n"); 856*32b31808SJens Wiklander } 857817466cbSJens Wiklander 858817466cbSJens Wiklander /* 859817466cbSJens Wiklander * Based on a NIST CTR_DRBG test vector (PR = FALSE) 860817466cbSJens Wiklander */ 861*32b31808SJens Wiklander if (verbose != 0) { 862817466cbSJens Wiklander mbedtls_printf(" CTR_DRBG (PR = FALSE): "); 863*32b31808SJens Wiklander } 864817466cbSJens Wiklander 865817466cbSJens Wiklander mbedtls_ctr_drbg_init(&ctx); 866817466cbSJens Wiklander 867817466cbSJens Wiklander test_offset = 0; 8687901324dSJerome Forissier mbedtls_ctr_drbg_set_entropy_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE); 8697901324dSJerome Forissier mbedtls_ctr_drbg_set_nonce_len(&ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2); 8705b25c76aSJerome Forissier CHK(mbedtls_ctr_drbg_seed(&ctx, 8715b25c76aSJerome Forissier ctr_drbg_self_test_entropy, 8725b25c76aSJerome Forissier (void *) entropy_source_nopr, 8737901324dSJerome Forissier pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE)); 874817466cbSJens Wiklander CHK(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0)); 875039e02dfSJerome Forissier CHK(mbedtls_ctr_drbg_random(&ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH)); 8767901324dSJerome Forissier CHK(mbedtls_ctr_drbg_random(&ctx, buf, sizeof(result_nopr))); 8777901324dSJerome Forissier CHK(memcmp(buf, result_nopr, sizeof(result_nopr))); 878817466cbSJens Wiklander 879817466cbSJens Wiklander mbedtls_ctr_drbg_free(&ctx); 880817466cbSJens Wiklander 881*32b31808SJens Wiklander if (verbose != 0) { 882817466cbSJens Wiklander mbedtls_printf("passed\n"); 883*32b31808SJens Wiklander } 884817466cbSJens Wiklander 885*32b31808SJens Wiklander if (verbose != 0) { 886817466cbSJens Wiklander mbedtls_printf("\n"); 887*32b31808SJens Wiklander } 888817466cbSJens Wiklander 889*32b31808SJens Wiklander return 0; 890817466cbSJens Wiklander } 891817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */ 892817466cbSJens Wiklander 893817466cbSJens Wiklander #endif /* MBEDTLS_CTR_DRBG_C */ 894