mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 31 06:02:27 2019 +0000
Revision:
1:9db0e321a9f4
Parent:
0:5b88d5760320
updated based on mbed-os5.15.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:5b88d5760320 1 /*
kenjiArai 0:5b88d5760320 2 * CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
kenjiArai 0:5b88d5760320 3 *
kenjiArai 0:5b88d5760320 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
kenjiArai 0:5b88d5760320 5 * SPDX-License-Identifier: Apache-2.0
kenjiArai 0:5b88d5760320 6 *
kenjiArai 0:5b88d5760320 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
kenjiArai 0:5b88d5760320 8 * not use this file except in compliance with the License.
kenjiArai 0:5b88d5760320 9 * You may obtain a copy of the License at
kenjiArai 0:5b88d5760320 10 *
kenjiArai 0:5b88d5760320 11 * http://www.apache.org/licenses/LICENSE-2.0
kenjiArai 0:5b88d5760320 12 *
kenjiArai 0:5b88d5760320 13 * Unless required by applicable law or agreed to in writing, software
kenjiArai 0:5b88d5760320 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
kenjiArai 0:5b88d5760320 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kenjiArai 0:5b88d5760320 16 * See the License for the specific language governing permissions and
kenjiArai 0:5b88d5760320 17 * limitations under the License.
kenjiArai 0:5b88d5760320 18 *
kenjiArai 0:5b88d5760320 19 * This file is part of mbed TLS (https://tls.mbed.org)
kenjiArai 0:5b88d5760320 20 */
kenjiArai 0:5b88d5760320 21 /*
kenjiArai 0:5b88d5760320 22 * The NIST SP 800-90 DRBGs are described in the following publication.
kenjiArai 0:5b88d5760320 23 *
kenjiArai 0:5b88d5760320 24 * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
kenjiArai 0:5b88d5760320 25 */
kenjiArai 0:5b88d5760320 26
kenjiArai 0:5b88d5760320 27 #if !defined(MBEDTLS_CONFIG_FILE)
kenjiArai 0:5b88d5760320 28 #include "mbedtls/config.h"
kenjiArai 0:5b88d5760320 29 #else
kenjiArai 0:5b88d5760320 30 #include MBEDTLS_CONFIG_FILE
kenjiArai 0:5b88d5760320 31 #endif
kenjiArai 0:5b88d5760320 32
kenjiArai 0:5b88d5760320 33 #if defined(MBEDTLS_CTR_DRBG_C)
kenjiArai 0:5b88d5760320 34
kenjiArai 0:5b88d5760320 35 #include "mbedtls/ctr_drbg.h"
kenjiArai 0:5b88d5760320 36 #include "mbedtls/platform_util.h"
kenjiArai 0:5b88d5760320 37
kenjiArai 0:5b88d5760320 38 #include <string.h>
kenjiArai 0:5b88d5760320 39
kenjiArai 0:5b88d5760320 40 #if defined(MBEDTLS_FS_IO)
kenjiArai 0:5b88d5760320 41 #include <stdio.h>
kenjiArai 0:5b88d5760320 42 #endif
kenjiArai 0:5b88d5760320 43
kenjiArai 0:5b88d5760320 44 #if defined(MBEDTLS_SELF_TEST)
kenjiArai 0:5b88d5760320 45 #if defined(MBEDTLS_PLATFORM_C)
kenjiArai 0:5b88d5760320 46 #include "mbedtls/platform.h"
kenjiArai 0:5b88d5760320 47 #else
kenjiArai 0:5b88d5760320 48 #include <stdio.h>
kenjiArai 0:5b88d5760320 49 #define mbedtls_printf printf
kenjiArai 0:5b88d5760320 50 #endif /* MBEDTLS_PLATFORM_C */
kenjiArai 0:5b88d5760320 51 #endif /* MBEDTLS_SELF_TEST */
kenjiArai 0:5b88d5760320 52
kenjiArai 0:5b88d5760320 53 /*
kenjiArai 0:5b88d5760320 54 * CTR_DRBG context initialization
kenjiArai 0:5b88d5760320 55 */
kenjiArai 0:5b88d5760320 56 void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx )
kenjiArai 0:5b88d5760320 57 {
kenjiArai 0:5b88d5760320 58 memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) );
kenjiArai 0:5b88d5760320 59
kenjiArai 0:5b88d5760320 60 #if defined(MBEDTLS_THREADING_C)
kenjiArai 0:5b88d5760320 61 mbedtls_mutex_init( &ctx->mutex );
kenjiArai 0:5b88d5760320 62 #endif
kenjiArai 0:5b88d5760320 63 }
kenjiArai 0:5b88d5760320 64
kenjiArai 0:5b88d5760320 65 /*
kenjiArai 0:5b88d5760320 66 * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow
kenjiArai 0:5b88d5760320 67 * NIST tests to succeed (which require known length fixed entropy)
kenjiArai 0:5b88d5760320 68 */
kenjiArai 0:5b88d5760320 69 /* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
kenjiArai 0:5b88d5760320 70 * mbedtls_ctr_drbg_seed_entropy_len(ctx, f_entropy, p_entropy,
kenjiArai 0:5b88d5760320 71 * custom, len, entropy_len)
kenjiArai 0:5b88d5760320 72 * implements
kenjiArai 0:5b88d5760320 73 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
kenjiArai 0:5b88d5760320 74 * security_strength) -> initial_working_state
kenjiArai 0:5b88d5760320 75 * with inputs
kenjiArai 0:5b88d5760320 76 * custom[:len] = nonce || personalization_string
kenjiArai 0:5b88d5760320 77 * where entropy_input comes from f_entropy for entropy_len bytes
kenjiArai 0:5b88d5760320 78 * and with outputs
kenjiArai 0:5b88d5760320 79 * ctx = initial_working_state
kenjiArai 0:5b88d5760320 80 */
kenjiArai 0:5b88d5760320 81 int mbedtls_ctr_drbg_seed_entropy_len(
kenjiArai 0:5b88d5760320 82 mbedtls_ctr_drbg_context *ctx,
kenjiArai 0:5b88d5760320 83 int (*f_entropy)(void *, unsigned char *, size_t),
kenjiArai 0:5b88d5760320 84 void *p_entropy,
kenjiArai 0:5b88d5760320 85 const unsigned char *custom,
kenjiArai 0:5b88d5760320 86 size_t len,
kenjiArai 0:5b88d5760320 87 size_t entropy_len )
kenjiArai 0:5b88d5760320 88 {
kenjiArai 0:5b88d5760320 89 int ret;
kenjiArai 0:5b88d5760320 90 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
kenjiArai 0:5b88d5760320 91
kenjiArai 0:5b88d5760320 92 memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE );
kenjiArai 0:5b88d5760320 93
kenjiArai 0:5b88d5760320 94 mbedtls_aes_init( &ctx->aes_ctx );
kenjiArai 0:5b88d5760320 95
kenjiArai 0:5b88d5760320 96 ctx->f_entropy = f_entropy;
kenjiArai 0:5b88d5760320 97 ctx->p_entropy = p_entropy;
kenjiArai 0:5b88d5760320 98
kenjiArai 0:5b88d5760320 99 ctx->entropy_len = entropy_len;
kenjiArai 0:5b88d5760320 100 ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
kenjiArai 0:5b88d5760320 101
kenjiArai 0:5b88d5760320 102 /*
kenjiArai 0:5b88d5760320 103 * Initialize with an empty key
kenjiArai 0:5b88d5760320 104 */
kenjiArai 0:5b88d5760320 105 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key,
kenjiArai 0:5b88d5760320 106 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
kenjiArai 0:5b88d5760320 107 {
kenjiArai 0:5b88d5760320 108 return( ret );
kenjiArai 0:5b88d5760320 109 }
kenjiArai 0:5b88d5760320 110
kenjiArai 0:5b88d5760320 111 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 )
kenjiArai 0:5b88d5760320 112 {
kenjiArai 0:5b88d5760320 113 return( ret );
kenjiArai 0:5b88d5760320 114 }
kenjiArai 0:5b88d5760320 115 return( 0 );
kenjiArai 0:5b88d5760320 116 }
kenjiArai 0:5b88d5760320 117
kenjiArai 0:5b88d5760320 118 int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
kenjiArai 0:5b88d5760320 119 int (*f_entropy)(void *, unsigned char *, size_t),
kenjiArai 0:5b88d5760320 120 void *p_entropy,
kenjiArai 0:5b88d5760320 121 const unsigned char *custom,
kenjiArai 0:5b88d5760320 122 size_t len )
kenjiArai 0:5b88d5760320 123 {
kenjiArai 0:5b88d5760320 124 return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy,
kenjiArai 0:5b88d5760320 125 custom, len,
kenjiArai 0:5b88d5760320 126 MBEDTLS_CTR_DRBG_ENTROPY_LEN ) );
kenjiArai 0:5b88d5760320 127 }
kenjiArai 0:5b88d5760320 128
kenjiArai 0:5b88d5760320 129 void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx )
kenjiArai 0:5b88d5760320 130 {
kenjiArai 0:5b88d5760320 131 if( ctx == NULL )
kenjiArai 0:5b88d5760320 132 return;
kenjiArai 0:5b88d5760320 133
kenjiArai 0:5b88d5760320 134 #if defined(MBEDTLS_THREADING_C)
kenjiArai 0:5b88d5760320 135 mbedtls_mutex_free( &ctx->mutex );
kenjiArai 0:5b88d5760320 136 #endif
kenjiArai 0:5b88d5760320 137 mbedtls_aes_free( &ctx->aes_ctx );
kenjiArai 0:5b88d5760320 138 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) );
kenjiArai 0:5b88d5760320 139 }
kenjiArai 0:5b88d5760320 140
kenjiArai 0:5b88d5760320 141 void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
kenjiArai 0:5b88d5760320 142 int resistance )
kenjiArai 0:5b88d5760320 143 {
kenjiArai 0:5b88d5760320 144 ctx->prediction_resistance = resistance;
kenjiArai 0:5b88d5760320 145 }
kenjiArai 0:5b88d5760320 146
kenjiArai 0:5b88d5760320 147 void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
kenjiArai 0:5b88d5760320 148 size_t len )
kenjiArai 0:5b88d5760320 149 {
kenjiArai 0:5b88d5760320 150 ctx->entropy_len = len;
kenjiArai 0:5b88d5760320 151 }
kenjiArai 0:5b88d5760320 152
kenjiArai 0:5b88d5760320 153 void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
kenjiArai 0:5b88d5760320 154 int interval )
kenjiArai 0:5b88d5760320 155 {
kenjiArai 0:5b88d5760320 156 ctx->reseed_interval = interval;
kenjiArai 0:5b88d5760320 157 }
kenjiArai 0:5b88d5760320 158
kenjiArai 0:5b88d5760320 159 static int block_cipher_df( unsigned char *output,
kenjiArai 0:5b88d5760320 160 const unsigned char *data, size_t data_len )
kenjiArai 0:5b88d5760320 161 {
kenjiArai 0:5b88d5760320 162 unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
kenjiArai 0:5b88d5760320 163 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16];
kenjiArai 0:5b88d5760320 164 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
kenjiArai 0:5b88d5760320 165 unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
kenjiArai 0:5b88d5760320 166 unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
kenjiArai 0:5b88d5760320 167 unsigned char *p, *iv;
kenjiArai 0:5b88d5760320 168 mbedtls_aes_context aes_ctx;
kenjiArai 0:5b88d5760320 169 int ret = 0;
kenjiArai 0:5b88d5760320 170
kenjiArai 0:5b88d5760320 171 int i, j;
kenjiArai 0:5b88d5760320 172 size_t buf_len, use_len;
kenjiArai 0:5b88d5760320 173
kenjiArai 0:5b88d5760320 174 if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
kenjiArai 0:5b88d5760320 175 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
kenjiArai 0:5b88d5760320 176
kenjiArai 0:5b88d5760320 177 memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
kenjiArai 0:5b88d5760320 178 MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 );
kenjiArai 0:5b88d5760320 179 mbedtls_aes_init( &aes_ctx );
kenjiArai 0:5b88d5760320 180
kenjiArai 0:5b88d5760320 181 /*
kenjiArai 0:5b88d5760320 182 * Construct IV (16 bytes) and S in buffer
kenjiArai 0:5b88d5760320 183 * IV = Counter (in 32-bits) padded to 16 with zeroes
kenjiArai 0:5b88d5760320 184 * S = Length input string (in 32-bits) || Length of output (in 32-bits) ||
kenjiArai 0:5b88d5760320 185 * data || 0x80
kenjiArai 0:5b88d5760320 186 * (Total is padded to a multiple of 16-bytes with zeroes)
kenjiArai 0:5b88d5760320 187 */
kenjiArai 0:5b88d5760320 188 p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE;
kenjiArai 0:5b88d5760320 189 *p++ = ( data_len >> 24 ) & 0xff;
kenjiArai 0:5b88d5760320 190 *p++ = ( data_len >> 16 ) & 0xff;
kenjiArai 0:5b88d5760320 191 *p++ = ( data_len >> 8 ) & 0xff;
kenjiArai 0:5b88d5760320 192 *p++ = ( data_len ) & 0xff;
kenjiArai 0:5b88d5760320 193 p += 3;
kenjiArai 0:5b88d5760320 194 *p++ = MBEDTLS_CTR_DRBG_SEEDLEN;
kenjiArai 0:5b88d5760320 195 memcpy( p, data, data_len );
kenjiArai 0:5b88d5760320 196 p[data_len] = 0x80;
kenjiArai 0:5b88d5760320 197
kenjiArai 0:5b88d5760320 198 buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1;
kenjiArai 0:5b88d5760320 199
kenjiArai 0:5b88d5760320 200 for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ )
kenjiArai 0:5b88d5760320 201 key[i] = i;
kenjiArai 0:5b88d5760320 202
kenjiArai 0:5b88d5760320 203 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key,
kenjiArai 0:5b88d5760320 204 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
kenjiArai 0:5b88d5760320 205 {
kenjiArai 0:5b88d5760320 206 goto exit;
kenjiArai 0:5b88d5760320 207 }
kenjiArai 0:5b88d5760320 208
kenjiArai 0:5b88d5760320 209 /*
kenjiArai 0:5b88d5760320 210 * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
kenjiArai 0:5b88d5760320 211 */
kenjiArai 0:5b88d5760320 212 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
kenjiArai 0:5b88d5760320 213 {
kenjiArai 0:5b88d5760320 214 p = buf;
kenjiArai 0:5b88d5760320 215 memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE );
kenjiArai 0:5b88d5760320 216 use_len = buf_len;
kenjiArai 0:5b88d5760320 217
kenjiArai 0:5b88d5760320 218 while( use_len > 0 )
kenjiArai 0:5b88d5760320 219 {
kenjiArai 0:5b88d5760320 220 for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ )
kenjiArai 0:5b88d5760320 221 chain[i] ^= p[i];
kenjiArai 0:5b88d5760320 222 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
kenjiArai 0:5b88d5760320 223 use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ?
kenjiArai 0:5b88d5760320 224 MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
kenjiArai 0:5b88d5760320 225
kenjiArai 0:5b88d5760320 226 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
kenjiArai 0:5b88d5760320 227 chain, chain ) ) != 0 )
kenjiArai 0:5b88d5760320 228 {
kenjiArai 0:5b88d5760320 229 goto exit;
kenjiArai 0:5b88d5760320 230 }
kenjiArai 0:5b88d5760320 231 }
kenjiArai 0:5b88d5760320 232
kenjiArai 0:5b88d5760320 233 memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE );
kenjiArai 0:5b88d5760320 234
kenjiArai 0:5b88d5760320 235 /*
kenjiArai 0:5b88d5760320 236 * Update IV
kenjiArai 0:5b88d5760320 237 */
kenjiArai 0:5b88d5760320 238 buf[3]++;
kenjiArai 0:5b88d5760320 239 }
kenjiArai 0:5b88d5760320 240
kenjiArai 0:5b88d5760320 241 /*
kenjiArai 0:5b88d5760320 242 * Do final encryption with reduced data
kenjiArai 0:5b88d5760320 243 */
kenjiArai 0:5b88d5760320 244 if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp,
kenjiArai 0:5b88d5760320 245 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
kenjiArai 0:5b88d5760320 246 {
kenjiArai 0:5b88d5760320 247 goto exit;
kenjiArai 0:5b88d5760320 248 }
kenjiArai 0:5b88d5760320 249 iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
kenjiArai 0:5b88d5760320 250 p = output;
kenjiArai 0:5b88d5760320 251
kenjiArai 0:5b88d5760320 252 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
kenjiArai 0:5b88d5760320 253 {
kenjiArai 0:5b88d5760320 254 if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT,
kenjiArai 0:5b88d5760320 255 iv, iv ) ) != 0 )
kenjiArai 0:5b88d5760320 256 {
kenjiArai 0:5b88d5760320 257 goto exit;
kenjiArai 0:5b88d5760320 258 }
kenjiArai 0:5b88d5760320 259 memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE );
kenjiArai 0:5b88d5760320 260 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
kenjiArai 0:5b88d5760320 261 }
kenjiArai 0:5b88d5760320 262 exit:
kenjiArai 0:5b88d5760320 263 mbedtls_aes_free( &aes_ctx );
kenjiArai 0:5b88d5760320 264 /*
kenjiArai 0:5b88d5760320 265 * tidy up the stack
kenjiArai 0:5b88d5760320 266 */
kenjiArai 0:5b88d5760320 267 mbedtls_platform_zeroize( buf, sizeof( buf ) );
kenjiArai 0:5b88d5760320 268 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
kenjiArai 0:5b88d5760320 269 mbedtls_platform_zeroize( key, sizeof( key ) );
kenjiArai 0:5b88d5760320 270 mbedtls_platform_zeroize( chain, sizeof( chain ) );
kenjiArai 0:5b88d5760320 271 if( 0 != ret )
kenjiArai 0:5b88d5760320 272 {
kenjiArai 0:5b88d5760320 273 /*
kenjiArai 0:5b88d5760320 274 * wipe partial seed from memory
kenjiArai 0:5b88d5760320 275 */
kenjiArai 0:5b88d5760320 276 mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN );
kenjiArai 0:5b88d5760320 277 }
kenjiArai 0:5b88d5760320 278
kenjiArai 0:5b88d5760320 279 return( ret );
kenjiArai 0:5b88d5760320 280 }
kenjiArai 0:5b88d5760320 281
kenjiArai 0:5b88d5760320 282 /* CTR_DRBG_Update (SP 800-90A &sect;10.2.1.2)
kenjiArai 0:5b88d5760320 283 * ctr_drbg_update_internal(ctx, provided_data)
kenjiArai 0:5b88d5760320 284 * implements
kenjiArai 0:5b88d5760320 285 * CTR_DRBG_Update(provided_data, Key, V)
kenjiArai 0:5b88d5760320 286 * with inputs and outputs
kenjiArai 0:5b88d5760320 287 * ctx->aes_ctx = Key
kenjiArai 0:5b88d5760320 288 * ctx->counter = V
kenjiArai 0:5b88d5760320 289 */
kenjiArai 0:5b88d5760320 290 static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx,
kenjiArai 0:5b88d5760320 291 const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] )
kenjiArai 0:5b88d5760320 292 {
kenjiArai 0:5b88d5760320 293 unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
kenjiArai 0:5b88d5760320 294 unsigned char *p = tmp;
kenjiArai 0:5b88d5760320 295 int i, j;
kenjiArai 0:5b88d5760320 296 int ret = 0;
kenjiArai 0:5b88d5760320 297
kenjiArai 0:5b88d5760320 298 memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
kenjiArai 0:5b88d5760320 299
kenjiArai 0:5b88d5760320 300 for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE )
kenjiArai 0:5b88d5760320 301 {
kenjiArai 0:5b88d5760320 302 /*
kenjiArai 0:5b88d5760320 303 * Increase counter
kenjiArai 0:5b88d5760320 304 */
kenjiArai 0:5b88d5760320 305 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
kenjiArai 0:5b88d5760320 306 if( ++ctx->counter[i - 1] != 0 )
kenjiArai 0:5b88d5760320 307 break;
kenjiArai 0:5b88d5760320 308
kenjiArai 0:5b88d5760320 309 /*
kenjiArai 0:5b88d5760320 310 * Crypt counter block
kenjiArai 0:5b88d5760320 311 */
kenjiArai 0:5b88d5760320 312 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
kenjiArai 0:5b88d5760320 313 ctx->counter, p ) ) != 0 )
kenjiArai 0:5b88d5760320 314 {
kenjiArai 0:5b88d5760320 315 goto exit;
kenjiArai 0:5b88d5760320 316 }
kenjiArai 0:5b88d5760320 317
kenjiArai 0:5b88d5760320 318 p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
kenjiArai 0:5b88d5760320 319 }
kenjiArai 0:5b88d5760320 320
kenjiArai 0:5b88d5760320 321 for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ )
kenjiArai 0:5b88d5760320 322 tmp[i] ^= data[i];
kenjiArai 0:5b88d5760320 323
kenjiArai 0:5b88d5760320 324 /*
kenjiArai 0:5b88d5760320 325 * Update key and counter
kenjiArai 0:5b88d5760320 326 */
kenjiArai 0:5b88d5760320 327 if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp,
kenjiArai 0:5b88d5760320 328 MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 )
kenjiArai 0:5b88d5760320 329 {
kenjiArai 0:5b88d5760320 330 goto exit;
kenjiArai 0:5b88d5760320 331 }
kenjiArai 0:5b88d5760320 332 memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
kenjiArai 0:5b88d5760320 333 MBEDTLS_CTR_DRBG_BLOCKSIZE );
kenjiArai 0:5b88d5760320 334
kenjiArai 0:5b88d5760320 335 exit:
kenjiArai 0:5b88d5760320 336 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
kenjiArai 0:5b88d5760320 337 return( ret );
kenjiArai 0:5b88d5760320 338 }
kenjiArai 0:5b88d5760320 339
kenjiArai 0:5b88d5760320 340 /* CTR_DRBG_Instantiate with derivation function (SP 800-90A &sect;10.2.1.3.2)
kenjiArai 0:5b88d5760320 341 * mbedtls_ctr_drbg_update(ctx, additional, add_len)
kenjiArai 0:5b88d5760320 342 * implements
kenjiArai 0:5b88d5760320 343 * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string,
kenjiArai 0:5b88d5760320 344 * security_strength) -> initial_working_state
kenjiArai 0:5b88d5760320 345 * with inputs
kenjiArai 0:5b88d5760320 346 * ctx->counter = all-bits-0
kenjiArai 0:5b88d5760320 347 * ctx->aes_ctx = context from all-bits-0 key
kenjiArai 0:5b88d5760320 348 * additional[:add_len] = entropy_input || nonce || personalization_string
kenjiArai 0:5b88d5760320 349 * and with outputs
kenjiArai 0:5b88d5760320 350 * ctx = initial_working_state
kenjiArai 0:5b88d5760320 351 */
kenjiArai 0:5b88d5760320 352 int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
kenjiArai 0:5b88d5760320 353 const unsigned char *additional,
kenjiArai 0:5b88d5760320 354 size_t add_len )
kenjiArai 0:5b88d5760320 355 {
kenjiArai 0:5b88d5760320 356 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
kenjiArai 0:5b88d5760320 357 int ret;
kenjiArai 0:5b88d5760320 358
kenjiArai 0:5b88d5760320 359 if( add_len == 0 )
kenjiArai 0:5b88d5760320 360 return( 0 );
kenjiArai 0:5b88d5760320 361
kenjiArai 0:5b88d5760320 362 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
kenjiArai 0:5b88d5760320 363 goto exit;
kenjiArai 0:5b88d5760320 364 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
kenjiArai 0:5b88d5760320 365 goto exit;
kenjiArai 0:5b88d5760320 366
kenjiArai 0:5b88d5760320 367 exit:
kenjiArai 0:5b88d5760320 368 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
kenjiArai 0:5b88d5760320 369 return( ret );
kenjiArai 0:5b88d5760320 370 }
kenjiArai 0:5b88d5760320 371
kenjiArai 0:5b88d5760320 372 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
kenjiArai 0:5b88d5760320 373 void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx,
kenjiArai 0:5b88d5760320 374 const unsigned char *additional,
kenjiArai 0:5b88d5760320 375 size_t add_len )
kenjiArai 0:5b88d5760320 376 {
kenjiArai 0:5b88d5760320 377 /* MAX_INPUT would be more logical here, but we have to match
kenjiArai 0:5b88d5760320 378 * block_cipher_df()'s limits since we can't propagate errors */
kenjiArai 0:5b88d5760320 379 if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT )
kenjiArai 0:5b88d5760320 380 add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT;
kenjiArai 0:5b88d5760320 381 (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len );
kenjiArai 0:5b88d5760320 382 }
kenjiArai 0:5b88d5760320 383 #endif /* MBEDTLS_DEPRECATED_REMOVED */
kenjiArai 0:5b88d5760320 384
kenjiArai 0:5b88d5760320 385 /* CTR_DRBG_Reseed with derivation function (SP 800-90A &sect;10.2.1.4.2)
kenjiArai 0:5b88d5760320 386 * mbedtls_ctr_drbg_reseed(ctx, additional, len)
kenjiArai 0:5b88d5760320 387 * implements
kenjiArai 0:5b88d5760320 388 * CTR_DRBG_Reseed(working_state, entropy_input, additional_input)
kenjiArai 0:5b88d5760320 389 * -> new_working_state
kenjiArai 0:5b88d5760320 390 * with inputs
kenjiArai 0:5b88d5760320 391 * ctx contains working_state
kenjiArai 0:5b88d5760320 392 * additional[:len] = additional_input
kenjiArai 0:5b88d5760320 393 * and entropy_input comes from calling ctx->f_entropy
kenjiArai 0:5b88d5760320 394 * and with output
kenjiArai 0:5b88d5760320 395 * ctx contains new_working_state
kenjiArai 0:5b88d5760320 396 */
kenjiArai 0:5b88d5760320 397 int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
kenjiArai 0:5b88d5760320 398 const unsigned char *additional, size_t len )
kenjiArai 0:5b88d5760320 399 {
kenjiArai 0:5b88d5760320 400 unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT];
kenjiArai 0:5b88d5760320 401 size_t seedlen = 0;
kenjiArai 0:5b88d5760320 402 int ret;
kenjiArai 0:5b88d5760320 403
kenjiArai 0:5b88d5760320 404 if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ||
kenjiArai 0:5b88d5760320 405 len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len )
kenjiArai 0:5b88d5760320 406 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
kenjiArai 0:5b88d5760320 407
kenjiArai 0:5b88d5760320 408 memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT );
kenjiArai 0:5b88d5760320 409
kenjiArai 0:5b88d5760320 410 /*
kenjiArai 0:5b88d5760320 411 * Gather entropy_len bytes of entropy to seed state
kenjiArai 0:5b88d5760320 412 */
kenjiArai 0:5b88d5760320 413 if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
kenjiArai 0:5b88d5760320 414 ctx->entropy_len ) )
kenjiArai 0:5b88d5760320 415 {
kenjiArai 0:5b88d5760320 416 return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED );
kenjiArai 0:5b88d5760320 417 }
kenjiArai 0:5b88d5760320 418
kenjiArai 0:5b88d5760320 419 seedlen += ctx->entropy_len;
kenjiArai 0:5b88d5760320 420
kenjiArai 0:5b88d5760320 421 /*
kenjiArai 0:5b88d5760320 422 * Add additional data
kenjiArai 0:5b88d5760320 423 */
kenjiArai 0:5b88d5760320 424 if( additional && len )
kenjiArai 0:5b88d5760320 425 {
kenjiArai 0:5b88d5760320 426 memcpy( seed + seedlen, additional, len );
kenjiArai 0:5b88d5760320 427 seedlen += len;
kenjiArai 0:5b88d5760320 428 }
kenjiArai 0:5b88d5760320 429
kenjiArai 0:5b88d5760320 430 /*
kenjiArai 0:5b88d5760320 431 * Reduce to 384 bits
kenjiArai 0:5b88d5760320 432 */
kenjiArai 0:5b88d5760320 433 if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 )
kenjiArai 0:5b88d5760320 434 goto exit;
kenjiArai 0:5b88d5760320 435
kenjiArai 0:5b88d5760320 436 /*
kenjiArai 0:5b88d5760320 437 * Update state
kenjiArai 0:5b88d5760320 438 */
kenjiArai 0:5b88d5760320 439 if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 )
kenjiArai 0:5b88d5760320 440 goto exit;
kenjiArai 0:5b88d5760320 441 ctx->reseed_counter = 1;
kenjiArai 0:5b88d5760320 442
kenjiArai 0:5b88d5760320 443 exit:
kenjiArai 0:5b88d5760320 444 mbedtls_platform_zeroize( seed, sizeof( seed ) );
kenjiArai 0:5b88d5760320 445 return( ret );
kenjiArai 0:5b88d5760320 446 }
kenjiArai 0:5b88d5760320 447
kenjiArai 0:5b88d5760320 448 /* CTR_DRBG_Generate with derivation function (SP 800-90A &sect;10.2.1.5.2)
kenjiArai 0:5b88d5760320 449 * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len)
kenjiArai 0:5b88d5760320 450 * implements
kenjiArai 0:5b88d5760320 451 * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len])
kenjiArai 0:5b88d5760320 452 * -> working_state_after_reseed
kenjiArai 0:5b88d5760320 453 * if required, then
kenjiArai 0:5b88d5760320 454 * CTR_DRBG_Generate(working_state_after_reseed,
kenjiArai 0:5b88d5760320 455 * requested_number_of_bits, additional_input)
kenjiArai 0:5b88d5760320 456 * -> status, returned_bits, new_working_state
kenjiArai 0:5b88d5760320 457 * with inputs
kenjiArai 0:5b88d5760320 458 * ctx contains working_state
kenjiArai 0:5b88d5760320 459 * requested_number_of_bits = 8 * output_len
kenjiArai 0:5b88d5760320 460 * additional[:add_len] = additional_input
kenjiArai 0:5b88d5760320 461 * and entropy_input comes from calling ctx->f_entropy
kenjiArai 0:5b88d5760320 462 * and with outputs
kenjiArai 0:5b88d5760320 463 * status = SUCCESS (this function does the reseed internally)
kenjiArai 0:5b88d5760320 464 * returned_bits = output[:output_len]
kenjiArai 0:5b88d5760320 465 * ctx contains new_working_state
kenjiArai 0:5b88d5760320 466 */
kenjiArai 0:5b88d5760320 467 int mbedtls_ctr_drbg_random_with_add( void *p_rng,
kenjiArai 0:5b88d5760320 468 unsigned char *output, size_t output_len,
kenjiArai 0:5b88d5760320 469 const unsigned char *additional, size_t add_len )
kenjiArai 0:5b88d5760320 470 {
kenjiArai 0:5b88d5760320 471 int ret = 0;
kenjiArai 0:5b88d5760320 472 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
kenjiArai 0:5b88d5760320 473 unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
kenjiArai 0:5b88d5760320 474 unsigned char *p = output;
kenjiArai 0:5b88d5760320 475 unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
kenjiArai 0:5b88d5760320 476 int i;
kenjiArai 0:5b88d5760320 477 size_t use_len;
kenjiArai 0:5b88d5760320 478
kenjiArai 0:5b88d5760320 479 if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST )
kenjiArai 0:5b88d5760320 480 return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG );
kenjiArai 0:5b88d5760320 481
kenjiArai 0:5b88d5760320 482 if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT )
kenjiArai 0:5b88d5760320 483 return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG );
kenjiArai 0:5b88d5760320 484
kenjiArai 0:5b88d5760320 485 memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN );
kenjiArai 0:5b88d5760320 486
kenjiArai 0:5b88d5760320 487 if( ctx->reseed_counter > ctx->reseed_interval ||
kenjiArai 0:5b88d5760320 488 ctx->prediction_resistance )
kenjiArai 0:5b88d5760320 489 {
kenjiArai 0:5b88d5760320 490 if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 )
kenjiArai 0:5b88d5760320 491 {
kenjiArai 0:5b88d5760320 492 return( ret );
kenjiArai 0:5b88d5760320 493 }
kenjiArai 0:5b88d5760320 494 add_len = 0;
kenjiArai 0:5b88d5760320 495 }
kenjiArai 0:5b88d5760320 496
kenjiArai 0:5b88d5760320 497 if( add_len > 0 )
kenjiArai 0:5b88d5760320 498 {
kenjiArai 0:5b88d5760320 499 if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 )
kenjiArai 0:5b88d5760320 500 goto exit;
kenjiArai 0:5b88d5760320 501 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
kenjiArai 0:5b88d5760320 502 goto exit;
kenjiArai 0:5b88d5760320 503 }
kenjiArai 0:5b88d5760320 504
kenjiArai 0:5b88d5760320 505 while( output_len > 0 )
kenjiArai 0:5b88d5760320 506 {
kenjiArai 0:5b88d5760320 507 /*
kenjiArai 0:5b88d5760320 508 * Increase counter
kenjiArai 0:5b88d5760320 509 */
kenjiArai 0:5b88d5760320 510 for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- )
kenjiArai 0:5b88d5760320 511 if( ++ctx->counter[i - 1] != 0 )
kenjiArai 0:5b88d5760320 512 break;
kenjiArai 0:5b88d5760320 513
kenjiArai 0:5b88d5760320 514 /*
kenjiArai 0:5b88d5760320 515 * Crypt counter block
kenjiArai 0:5b88d5760320 516 */
kenjiArai 0:5b88d5760320 517 if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
kenjiArai 0:5b88d5760320 518 ctx->counter, tmp ) ) != 0 )
kenjiArai 0:5b88d5760320 519 {
kenjiArai 0:5b88d5760320 520 goto exit;
kenjiArai 0:5b88d5760320 521 }
kenjiArai 0:5b88d5760320 522
kenjiArai 0:5b88d5760320 523 use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE )
kenjiArai 0:5b88d5760320 524 ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
kenjiArai 0:5b88d5760320 525 /*
kenjiArai 0:5b88d5760320 526 * Copy random block to destination
kenjiArai 0:5b88d5760320 527 */
kenjiArai 0:5b88d5760320 528 memcpy( p, tmp, use_len );
kenjiArai 0:5b88d5760320 529 p += use_len;
kenjiArai 0:5b88d5760320 530 output_len -= use_len;
kenjiArai 0:5b88d5760320 531 }
kenjiArai 0:5b88d5760320 532
kenjiArai 0:5b88d5760320 533 if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 )
kenjiArai 0:5b88d5760320 534 goto exit;
kenjiArai 0:5b88d5760320 535
kenjiArai 0:5b88d5760320 536 ctx->reseed_counter++;
kenjiArai 0:5b88d5760320 537
kenjiArai 0:5b88d5760320 538 exit:
kenjiArai 0:5b88d5760320 539 mbedtls_platform_zeroize( add_input, sizeof( add_input ) );
kenjiArai 0:5b88d5760320 540 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
kenjiArai 0:5b88d5760320 541 return( 0 );
kenjiArai 0:5b88d5760320 542 }
kenjiArai 0:5b88d5760320 543
kenjiArai 0:5b88d5760320 544 int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output,
kenjiArai 0:5b88d5760320 545 size_t output_len )
kenjiArai 0:5b88d5760320 546 {
kenjiArai 0:5b88d5760320 547 int ret;
kenjiArai 0:5b88d5760320 548 mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
kenjiArai 0:5b88d5760320 549
kenjiArai 0:5b88d5760320 550 #if defined(MBEDTLS_THREADING_C)
kenjiArai 0:5b88d5760320 551 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
kenjiArai 0:5b88d5760320 552 return( ret );
kenjiArai 0:5b88d5760320 553 #endif
kenjiArai 0:5b88d5760320 554
kenjiArai 0:5b88d5760320 555 ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 );
kenjiArai 0:5b88d5760320 556
kenjiArai 0:5b88d5760320 557 #if defined(MBEDTLS_THREADING_C)
kenjiArai 0:5b88d5760320 558 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
kenjiArai 0:5b88d5760320 559 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
kenjiArai 0:5b88d5760320 560 #endif
kenjiArai 0:5b88d5760320 561
kenjiArai 0:5b88d5760320 562 return( ret );
kenjiArai 0:5b88d5760320 563 }
kenjiArai 0:5b88d5760320 564
kenjiArai 0:5b88d5760320 565 #if defined(MBEDTLS_FS_IO)
kenjiArai 0:5b88d5760320 566 int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx,
kenjiArai 0:5b88d5760320 567 const char *path )
kenjiArai 0:5b88d5760320 568 {
kenjiArai 0:5b88d5760320 569 int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
kenjiArai 0:5b88d5760320 570 FILE *f;
kenjiArai 0:5b88d5760320 571 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
kenjiArai 0:5b88d5760320 572
kenjiArai 0:5b88d5760320 573 if( ( f = fopen( path, "wb" ) ) == NULL )
kenjiArai 0:5b88d5760320 574 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
kenjiArai 0:5b88d5760320 575
kenjiArai 0:5b88d5760320 576 if( ( ret = mbedtls_ctr_drbg_random( ctx, buf,
kenjiArai 0:5b88d5760320 577 MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 )
kenjiArai 0:5b88d5760320 578 goto exit;
kenjiArai 0:5b88d5760320 579
kenjiArai 0:5b88d5760320 580 if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) !=
kenjiArai 0:5b88d5760320 581 MBEDTLS_CTR_DRBG_MAX_INPUT )
kenjiArai 0:5b88d5760320 582 {
kenjiArai 0:5b88d5760320 583 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
kenjiArai 0:5b88d5760320 584 }
kenjiArai 0:5b88d5760320 585 else
kenjiArai 0:5b88d5760320 586 {
kenjiArai 0:5b88d5760320 587 ret = 0;
kenjiArai 0:5b88d5760320 588 }
kenjiArai 0:5b88d5760320 589
kenjiArai 0:5b88d5760320 590 exit:
kenjiArai 0:5b88d5760320 591 mbedtls_platform_zeroize( buf, sizeof( buf ) );
kenjiArai 0:5b88d5760320 592
kenjiArai 0:5b88d5760320 593 fclose( f );
kenjiArai 0:5b88d5760320 594 return( ret );
kenjiArai 0:5b88d5760320 595 }
kenjiArai 0:5b88d5760320 596
kenjiArai 0:5b88d5760320 597 int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx,
kenjiArai 0:5b88d5760320 598 const char *path )
kenjiArai 0:5b88d5760320 599 {
kenjiArai 0:5b88d5760320 600 int ret = 0;
kenjiArai 0:5b88d5760320 601 FILE *f = NULL;
kenjiArai 0:5b88d5760320 602 size_t n;
kenjiArai 0:5b88d5760320 603 unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ];
kenjiArai 0:5b88d5760320 604 unsigned char c;
kenjiArai 0:5b88d5760320 605
kenjiArai 0:5b88d5760320 606 if( ( f = fopen( path, "rb" ) ) == NULL )
kenjiArai 0:5b88d5760320 607 return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR );
kenjiArai 0:5b88d5760320 608
kenjiArai 0:5b88d5760320 609 n = fread( buf, 1, sizeof( buf ), f );
kenjiArai 0:5b88d5760320 610 if( fread( &c, 1, 1, f ) != 0 )
kenjiArai 0:5b88d5760320 611 {
kenjiArai 0:5b88d5760320 612 ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
kenjiArai 0:5b88d5760320 613 goto exit;
kenjiArai 0:5b88d5760320 614 }
kenjiArai 0:5b88d5760320 615 if( n == 0 || ferror( f ) )
kenjiArai 0:5b88d5760320 616 {
kenjiArai 0:5b88d5760320 617 ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR;
kenjiArai 0:5b88d5760320 618 goto exit;
kenjiArai 0:5b88d5760320 619 }
kenjiArai 0:5b88d5760320 620 fclose( f );
kenjiArai 0:5b88d5760320 621 f = NULL;
kenjiArai 0:5b88d5760320 622
kenjiArai 0:5b88d5760320 623 ret = mbedtls_ctr_drbg_update_ret( ctx, buf, n );
kenjiArai 0:5b88d5760320 624
kenjiArai 0:5b88d5760320 625 exit:
kenjiArai 0:5b88d5760320 626 mbedtls_platform_zeroize( buf, sizeof( buf ) );
kenjiArai 0:5b88d5760320 627 if( f != NULL )
kenjiArai 0:5b88d5760320 628 fclose( f );
kenjiArai 0:5b88d5760320 629 if( ret != 0 )
kenjiArai 0:5b88d5760320 630 return( ret );
kenjiArai 0:5b88d5760320 631 return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) );
kenjiArai 0:5b88d5760320 632 }
kenjiArai 0:5b88d5760320 633 #endif /* MBEDTLS_FS_IO */
kenjiArai 0:5b88d5760320 634
kenjiArai 0:5b88d5760320 635 #if defined(MBEDTLS_SELF_TEST)
kenjiArai 0:5b88d5760320 636
kenjiArai 0:5b88d5760320 637 static const unsigned char entropy_source_pr[96] =
kenjiArai 0:5b88d5760320 638 { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16,
kenjiArai 0:5b88d5760320 639 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02,
kenjiArai 0:5b88d5760320 640 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b,
kenjiArai 0:5b88d5760320 641 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb,
kenjiArai 0:5b88d5760320 642 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9,
kenjiArai 0:5b88d5760320 643 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95,
kenjiArai 0:5b88d5760320 644 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63,
kenjiArai 0:5b88d5760320 645 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3,
kenjiArai 0:5b88d5760320 646 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31,
kenjiArai 0:5b88d5760320 647 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4,
kenjiArai 0:5b88d5760320 648 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56,
kenjiArai 0:5b88d5760320 649 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 };
kenjiArai 0:5b88d5760320 650
kenjiArai 0:5b88d5760320 651 static const unsigned char entropy_source_nopr[64] =
kenjiArai 0:5b88d5760320 652 { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14,
kenjiArai 0:5b88d5760320 653 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe,
kenjiArai 0:5b88d5760320 654 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d,
kenjiArai 0:5b88d5760320 655 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20,
kenjiArai 0:5b88d5760320 656 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9,
kenjiArai 0:5b88d5760320 657 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46,
kenjiArai 0:5b88d5760320 658 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e,
kenjiArai 0:5b88d5760320 659 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e };
kenjiArai 0:5b88d5760320 660
kenjiArai 0:5b88d5760320 661 static const unsigned char nonce_pers_pr[16] =
kenjiArai 0:5b88d5760320 662 { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2,
kenjiArai 0:5b88d5760320 663 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c };
kenjiArai 0:5b88d5760320 664
kenjiArai 0:5b88d5760320 665 static const unsigned char nonce_pers_nopr[16] =
kenjiArai 0:5b88d5760320 666 { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5,
kenjiArai 0:5b88d5760320 667 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f };
kenjiArai 0:5b88d5760320 668
kenjiArai 0:5b88d5760320 669 static const unsigned char result_pr[16] =
kenjiArai 0:5b88d5760320 670 { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f,
kenjiArai 0:5b88d5760320 671 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 };
kenjiArai 0:5b88d5760320 672
kenjiArai 0:5b88d5760320 673 static const unsigned char result_nopr[16] =
kenjiArai 0:5b88d5760320 674 { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88,
kenjiArai 0:5b88d5760320 675 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f };
kenjiArai 0:5b88d5760320 676
kenjiArai 0:5b88d5760320 677 static size_t test_offset;
kenjiArai 0:5b88d5760320 678 static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
kenjiArai 0:5b88d5760320 679 size_t len )
kenjiArai 0:5b88d5760320 680 {
kenjiArai 0:5b88d5760320 681 const unsigned char *p = data;
kenjiArai 0:5b88d5760320 682 memcpy( buf, p + test_offset, len );
kenjiArai 0:5b88d5760320 683 test_offset += len;
kenjiArai 0:5b88d5760320 684 return( 0 );
kenjiArai 0:5b88d5760320 685 }
kenjiArai 0:5b88d5760320 686
kenjiArai 0:5b88d5760320 687 #define CHK( c ) if( (c) != 0 ) \
kenjiArai 0:5b88d5760320 688 { \
kenjiArai 0:5b88d5760320 689 if( verbose != 0 ) \
kenjiArai 0:5b88d5760320 690 mbedtls_printf( "failed\n" ); \
kenjiArai 0:5b88d5760320 691 return( 1 ); \
kenjiArai 0:5b88d5760320 692 }
kenjiArai 0:5b88d5760320 693
kenjiArai 0:5b88d5760320 694 /*
kenjiArai 0:5b88d5760320 695 * Checkup routine
kenjiArai 0:5b88d5760320 696 */
kenjiArai 0:5b88d5760320 697 int mbedtls_ctr_drbg_self_test( int verbose )
kenjiArai 0:5b88d5760320 698 {
kenjiArai 0:5b88d5760320 699 mbedtls_ctr_drbg_context ctx;
kenjiArai 0:5b88d5760320 700 unsigned char buf[16];
kenjiArai 0:5b88d5760320 701
kenjiArai 0:5b88d5760320 702 mbedtls_ctr_drbg_init( &ctx );
kenjiArai 0:5b88d5760320 703
kenjiArai 0:5b88d5760320 704 /*
kenjiArai 0:5b88d5760320 705 * Based on a NIST CTR_DRBG test vector (PR = True)
kenjiArai 0:5b88d5760320 706 */
kenjiArai 0:5b88d5760320 707 if( verbose != 0 )
kenjiArai 0:5b88d5760320 708 mbedtls_printf( " CTR_DRBG (PR = TRUE) : " );
kenjiArai 0:5b88d5760320 709
kenjiArai 0:5b88d5760320 710 test_offset = 0;
kenjiArai 0:5b88d5760320 711 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
kenjiArai 0:5b88d5760320 712 (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) );
kenjiArai 0:5b88d5760320 713 mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
kenjiArai 0:5b88d5760320 714 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
kenjiArai 0:5b88d5760320 715 CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
kenjiArai 0:5b88d5760320 716 CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) );
kenjiArai 0:5b88d5760320 717
kenjiArai 0:5b88d5760320 718 mbedtls_ctr_drbg_free( &ctx );
kenjiArai 0:5b88d5760320 719
kenjiArai 0:5b88d5760320 720 if( verbose != 0 )
kenjiArai 0:5b88d5760320 721 mbedtls_printf( "passed\n" );
kenjiArai 0:5b88d5760320 722
kenjiArai 0:5b88d5760320 723 /*
kenjiArai 0:5b88d5760320 724 * Based on a NIST CTR_DRBG test vector (PR = FALSE)
kenjiArai 0:5b88d5760320 725 */
kenjiArai 0:5b88d5760320 726 if( verbose != 0 )
kenjiArai 0:5b88d5760320 727 mbedtls_printf( " CTR_DRBG (PR = FALSE): " );
kenjiArai 0:5b88d5760320 728
kenjiArai 0:5b88d5760320 729 mbedtls_ctr_drbg_init( &ctx );
kenjiArai 0:5b88d5760320 730
kenjiArai 0:5b88d5760320 731 test_offset = 0;
kenjiArai 0:5b88d5760320 732 CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy,
kenjiArai 0:5b88d5760320 733 (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) );
kenjiArai 0:5b88d5760320 734 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
kenjiArai 0:5b88d5760320 735 CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
kenjiArai 0:5b88d5760320 736 CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) );
kenjiArai 0:5b88d5760320 737 CHK( memcmp( buf, result_nopr, 16 ) );
kenjiArai 0:5b88d5760320 738
kenjiArai 0:5b88d5760320 739 mbedtls_ctr_drbg_free( &ctx );
kenjiArai 0:5b88d5760320 740
kenjiArai 0:5b88d5760320 741 if( verbose != 0 )
kenjiArai 0:5b88d5760320 742 mbedtls_printf( "passed\n" );
kenjiArai 0:5b88d5760320 743
kenjiArai 0:5b88d5760320 744 if( verbose != 0 )
kenjiArai 0:5b88d5760320 745 mbedtls_printf( "\n" );
kenjiArai 0:5b88d5760320 746
kenjiArai 0:5b88d5760320 747 return( 0 );
kenjiArai 0:5b88d5760320 748 }
kenjiArai 0:5b88d5760320 749 #endif /* MBEDTLS_SELF_TEST */
kenjiArai 0:5b88d5760320 750
kenjiArai 0:5b88d5760320 751 #endif /* MBEDTLS_CTR_DRBG_C */