mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 17 23:23:45 2019 +0000
Revision:
0:5b88d5760320
Child:
1:9db0e321a9f4
mbed-os5 only for TYBLE16

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:5b88d5760320 1 /*
kenjiArai 0:5b88d5760320 2 * HMAC_DRBG implementation (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 /*
kenjiArai 0:5b88d5760320 23 * The NIST SP 800-90A DRBGs are described in the following publication.
kenjiArai 0:5b88d5760320 24 * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
kenjiArai 0:5b88d5760320 25 * References below are based on rev. 1 (January 2012).
kenjiArai 0:5b88d5760320 26 */
kenjiArai 0:5b88d5760320 27
kenjiArai 0:5b88d5760320 28 #if !defined(MBEDTLS_CONFIG_FILE)
kenjiArai 0:5b88d5760320 29 #include "mbedtls/config.h"
kenjiArai 0:5b88d5760320 30 #else
kenjiArai 0:5b88d5760320 31 #include MBEDTLS_CONFIG_FILE
kenjiArai 0:5b88d5760320 32 #endif
kenjiArai 0:5b88d5760320 33
kenjiArai 0:5b88d5760320 34 #if defined(MBEDTLS_HMAC_DRBG_C)
kenjiArai 0:5b88d5760320 35
kenjiArai 0:5b88d5760320 36 #include "mbedtls/hmac_drbg.h"
kenjiArai 0:5b88d5760320 37 #include "mbedtls/platform_util.h"
kenjiArai 0:5b88d5760320 38
kenjiArai 0:5b88d5760320 39 #include <string.h>
kenjiArai 0:5b88d5760320 40
kenjiArai 0:5b88d5760320 41 #if defined(MBEDTLS_FS_IO)
kenjiArai 0:5b88d5760320 42 #include <stdio.h>
kenjiArai 0:5b88d5760320 43 #endif
kenjiArai 0:5b88d5760320 44
kenjiArai 0:5b88d5760320 45 #if defined(MBEDTLS_SELF_TEST)
kenjiArai 0:5b88d5760320 46 #if defined(MBEDTLS_PLATFORM_C)
kenjiArai 0:5b88d5760320 47 #include "mbedtls/platform.h"
kenjiArai 0:5b88d5760320 48 #else
kenjiArai 0:5b88d5760320 49 #include <stdio.h>
kenjiArai 0:5b88d5760320 50 #define mbedtls_printf printf
kenjiArai 0:5b88d5760320 51 #endif /* MBEDTLS_SELF_TEST */
kenjiArai 0:5b88d5760320 52 #endif /* MBEDTLS_PLATFORM_C */
kenjiArai 0:5b88d5760320 53
kenjiArai 0:5b88d5760320 54 /*
kenjiArai 0:5b88d5760320 55 * HMAC_DRBG context initialization
kenjiArai 0:5b88d5760320 56 */
kenjiArai 0:5b88d5760320 57 void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx )
kenjiArai 0:5b88d5760320 58 {
kenjiArai 0:5b88d5760320 59 memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) );
kenjiArai 0:5b88d5760320 60
kenjiArai 0:5b88d5760320 61 #if defined(MBEDTLS_THREADING_C)
kenjiArai 0:5b88d5760320 62 mbedtls_mutex_init( &ctx->mutex );
kenjiArai 0:5b88d5760320 63 #endif
kenjiArai 0:5b88d5760320 64 }
kenjiArai 0:5b88d5760320 65
kenjiArai 0:5b88d5760320 66 /*
kenjiArai 0:5b88d5760320 67 * HMAC_DRBG update, using optional additional data (10.1.2.2)
kenjiArai 0:5b88d5760320 68 */
kenjiArai 0:5b88d5760320 69 int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
kenjiArai 0:5b88d5760320 70 const unsigned char *additional,
kenjiArai 0:5b88d5760320 71 size_t add_len )
kenjiArai 0:5b88d5760320 72 {
kenjiArai 0:5b88d5760320 73 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
kenjiArai 0:5b88d5760320 74 unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1;
kenjiArai 0:5b88d5760320 75 unsigned char sep[1];
kenjiArai 0:5b88d5760320 76 unsigned char K[MBEDTLS_MD_MAX_SIZE];
kenjiArai 0:5b88d5760320 77 int ret;
kenjiArai 0:5b88d5760320 78
kenjiArai 0:5b88d5760320 79 for( sep[0] = 0; sep[0] < rounds; sep[0]++ )
kenjiArai 0:5b88d5760320 80 {
kenjiArai 0:5b88d5760320 81 /* Step 1 or 4 */
kenjiArai 0:5b88d5760320 82 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
kenjiArai 0:5b88d5760320 83 goto exit;
kenjiArai 0:5b88d5760320 84 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
kenjiArai 0:5b88d5760320 85 ctx->V, md_len ) ) != 0 )
kenjiArai 0:5b88d5760320 86 goto exit;
kenjiArai 0:5b88d5760320 87 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
kenjiArai 0:5b88d5760320 88 sep, 1 ) ) != 0 )
kenjiArai 0:5b88d5760320 89 goto exit;
kenjiArai 0:5b88d5760320 90 if( rounds == 2 )
kenjiArai 0:5b88d5760320 91 {
kenjiArai 0:5b88d5760320 92 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
kenjiArai 0:5b88d5760320 93 additional, add_len ) ) != 0 )
kenjiArai 0:5b88d5760320 94 goto exit;
kenjiArai 0:5b88d5760320 95 }
kenjiArai 0:5b88d5760320 96 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 )
kenjiArai 0:5b88d5760320 97 goto exit;
kenjiArai 0:5b88d5760320 98
kenjiArai 0:5b88d5760320 99 /* Step 2 or 5 */
kenjiArai 0:5b88d5760320 100 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 )
kenjiArai 0:5b88d5760320 101 goto exit;
kenjiArai 0:5b88d5760320 102 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
kenjiArai 0:5b88d5760320 103 ctx->V, md_len ) ) != 0 )
kenjiArai 0:5b88d5760320 104 goto exit;
kenjiArai 0:5b88d5760320 105 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
kenjiArai 0:5b88d5760320 106 goto exit;
kenjiArai 0:5b88d5760320 107 }
kenjiArai 0:5b88d5760320 108
kenjiArai 0:5b88d5760320 109 exit:
kenjiArai 0:5b88d5760320 110 mbedtls_platform_zeroize( K, sizeof( K ) );
kenjiArai 0:5b88d5760320 111 return( ret );
kenjiArai 0:5b88d5760320 112 }
kenjiArai 0:5b88d5760320 113
kenjiArai 0:5b88d5760320 114 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
kenjiArai 0:5b88d5760320 115 void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
kenjiArai 0:5b88d5760320 116 const unsigned char *additional,
kenjiArai 0:5b88d5760320 117 size_t add_len )
kenjiArai 0:5b88d5760320 118 {
kenjiArai 0:5b88d5760320 119 (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
kenjiArai 0:5b88d5760320 120 }
kenjiArai 0:5b88d5760320 121 #endif /* MBEDTLS_DEPRECATED_REMOVED */
kenjiArai 0:5b88d5760320 122
kenjiArai 0:5b88d5760320 123 /*
kenjiArai 0:5b88d5760320 124 * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
kenjiArai 0:5b88d5760320 125 */
kenjiArai 0:5b88d5760320 126 int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
kenjiArai 0:5b88d5760320 127 const mbedtls_md_info_t * md_info,
kenjiArai 0:5b88d5760320 128 const unsigned char *data, size_t data_len )
kenjiArai 0:5b88d5760320 129 {
kenjiArai 0:5b88d5760320 130 int ret;
kenjiArai 0:5b88d5760320 131
kenjiArai 0:5b88d5760320 132 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
kenjiArai 0:5b88d5760320 133 return( ret );
kenjiArai 0:5b88d5760320 134
kenjiArai 0:5b88d5760320 135 /*
kenjiArai 0:5b88d5760320 136 * Set initial working state.
kenjiArai 0:5b88d5760320 137 * Use the V memory location, which is currently all 0, to initialize the
kenjiArai 0:5b88d5760320 138 * MD context with an all-zero key. Then set V to its initial value.
kenjiArai 0:5b88d5760320 139 */
kenjiArai 0:5b88d5760320 140 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V,
kenjiArai 0:5b88d5760320 141 mbedtls_md_get_size( md_info ) ) ) != 0 )
kenjiArai 0:5b88d5760320 142 return( ret );
kenjiArai 0:5b88d5760320 143 memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) );
kenjiArai 0:5b88d5760320 144
kenjiArai 0:5b88d5760320 145 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 )
kenjiArai 0:5b88d5760320 146 return( ret );
kenjiArai 0:5b88d5760320 147
kenjiArai 0:5b88d5760320 148 return( 0 );
kenjiArai 0:5b88d5760320 149 }
kenjiArai 0:5b88d5760320 150
kenjiArai 0:5b88d5760320 151 /*
kenjiArai 0:5b88d5760320 152 * HMAC_DRBG reseeding: 10.1.2.4 (arabic) + 9.2 (Roman)
kenjiArai 0:5b88d5760320 153 */
kenjiArai 0:5b88d5760320 154 int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
kenjiArai 0:5b88d5760320 155 const unsigned char *additional, size_t len )
kenjiArai 0:5b88d5760320 156 {
kenjiArai 0:5b88d5760320 157 unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
kenjiArai 0:5b88d5760320 158 size_t seedlen;
kenjiArai 0:5b88d5760320 159 int ret;
kenjiArai 0:5b88d5760320 160
kenjiArai 0:5b88d5760320 161 /* III. Check input length */
kenjiArai 0:5b88d5760320 162 if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
kenjiArai 0:5b88d5760320 163 ctx->entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT )
kenjiArai 0:5b88d5760320 164 {
kenjiArai 0:5b88d5760320 165 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
kenjiArai 0:5b88d5760320 166 }
kenjiArai 0:5b88d5760320 167
kenjiArai 0:5b88d5760320 168 memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT );
kenjiArai 0:5b88d5760320 169
kenjiArai 0:5b88d5760320 170 /* IV. Gather entropy_len bytes of entropy for the seed */
kenjiArai 0:5b88d5760320 171 if( ( ret = ctx->f_entropy( ctx->p_entropy,
kenjiArai 0:5b88d5760320 172 seed, ctx->entropy_len ) ) != 0 )
kenjiArai 0:5b88d5760320 173 return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED );
kenjiArai 0:5b88d5760320 174
kenjiArai 0:5b88d5760320 175 seedlen = ctx->entropy_len;
kenjiArai 0:5b88d5760320 176
kenjiArai 0:5b88d5760320 177 /* 1. Concatenate entropy and additional data if any */
kenjiArai 0:5b88d5760320 178 if( additional != NULL && len != 0 )
kenjiArai 0:5b88d5760320 179 {
kenjiArai 0:5b88d5760320 180 memcpy( seed + seedlen, additional, len );
kenjiArai 0:5b88d5760320 181 seedlen += len;
kenjiArai 0:5b88d5760320 182 }
kenjiArai 0:5b88d5760320 183
kenjiArai 0:5b88d5760320 184 /* 2. Update state */
kenjiArai 0:5b88d5760320 185 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 )
kenjiArai 0:5b88d5760320 186 goto exit;
kenjiArai 0:5b88d5760320 187
kenjiArai 0:5b88d5760320 188 /* 3. Reset reseed_counter */
kenjiArai 0:5b88d5760320 189 ctx->reseed_counter = 1;
kenjiArai 0:5b88d5760320 190
kenjiArai 0:5b88d5760320 191 exit:
kenjiArai 0:5b88d5760320 192 /* 4. Done */
kenjiArai 0:5b88d5760320 193 mbedtls_platform_zeroize( seed, seedlen );
kenjiArai 0:5b88d5760320 194 return( ret );
kenjiArai 0:5b88d5760320 195 }
kenjiArai 0:5b88d5760320 196
kenjiArai 0:5b88d5760320 197 /*
kenjiArai 0:5b88d5760320 198 * HMAC_DRBG initialisation (10.1.2.3 + 9.1)
kenjiArai 0:5b88d5760320 199 */
kenjiArai 0:5b88d5760320 200 int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
kenjiArai 0:5b88d5760320 201 const mbedtls_md_info_t * md_info,
kenjiArai 0:5b88d5760320 202 int (*f_entropy)(void *, unsigned char *, size_t),
kenjiArai 0:5b88d5760320 203 void *p_entropy,
kenjiArai 0:5b88d5760320 204 const unsigned char *custom,
kenjiArai 0:5b88d5760320 205 size_t len )
kenjiArai 0:5b88d5760320 206 {
kenjiArai 0:5b88d5760320 207 int ret;
kenjiArai 0:5b88d5760320 208 size_t entropy_len, md_size;
kenjiArai 0:5b88d5760320 209
kenjiArai 0:5b88d5760320 210 if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 )
kenjiArai 0:5b88d5760320 211 return( ret );
kenjiArai 0:5b88d5760320 212
kenjiArai 0:5b88d5760320 213 md_size = mbedtls_md_get_size( md_info );
kenjiArai 0:5b88d5760320 214
kenjiArai 0:5b88d5760320 215 /*
kenjiArai 0:5b88d5760320 216 * Set initial working state.
kenjiArai 0:5b88d5760320 217 * Use the V memory location, which is currently all 0, to initialize the
kenjiArai 0:5b88d5760320 218 * MD context with an all-zero key. Then set V to its initial value.
kenjiArai 0:5b88d5760320 219 */
kenjiArai 0:5b88d5760320 220 if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 )
kenjiArai 0:5b88d5760320 221 return( ret );
kenjiArai 0:5b88d5760320 222 memset( ctx->V, 0x01, md_size );
kenjiArai 0:5b88d5760320 223
kenjiArai 0:5b88d5760320 224 ctx->f_entropy = f_entropy;
kenjiArai 0:5b88d5760320 225 ctx->p_entropy = p_entropy;
kenjiArai 0:5b88d5760320 226
kenjiArai 0:5b88d5760320 227 ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
kenjiArai 0:5b88d5760320 228
kenjiArai 0:5b88d5760320 229 /*
kenjiArai 0:5b88d5760320 230 * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
kenjiArai 0:5b88d5760320 231 * each hash function, then according to SP800-90A rev1 10.1 table 2,
kenjiArai 0:5b88d5760320 232 * min_entropy_len (in bits) is security_strength.
kenjiArai 0:5b88d5760320 233 *
kenjiArai 0:5b88d5760320 234 * (This also matches the sizes used in the NIST test vectors.)
kenjiArai 0:5b88d5760320 235 */
kenjiArai 0:5b88d5760320 236 entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
kenjiArai 0:5b88d5760320 237 md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
kenjiArai 0:5b88d5760320 238 32; /* better (256+) -> 256 bits */
kenjiArai 0:5b88d5760320 239
kenjiArai 0:5b88d5760320 240 /*
kenjiArai 0:5b88d5760320 241 * For initialisation, use more entropy to emulate a nonce
kenjiArai 0:5b88d5760320 242 * (Again, matches test vectors.)
kenjiArai 0:5b88d5760320 243 */
kenjiArai 0:5b88d5760320 244 ctx->entropy_len = entropy_len * 3 / 2;
kenjiArai 0:5b88d5760320 245
kenjiArai 0:5b88d5760320 246 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, custom, len ) ) != 0 )
kenjiArai 0:5b88d5760320 247 return( ret );
kenjiArai 0:5b88d5760320 248
kenjiArai 0:5b88d5760320 249 ctx->entropy_len = entropy_len;
kenjiArai 0:5b88d5760320 250
kenjiArai 0:5b88d5760320 251 return( 0 );
kenjiArai 0:5b88d5760320 252 }
kenjiArai 0:5b88d5760320 253
kenjiArai 0:5b88d5760320 254 /*
kenjiArai 0:5b88d5760320 255 * Set prediction resistance
kenjiArai 0:5b88d5760320 256 */
kenjiArai 0:5b88d5760320 257 void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
kenjiArai 0:5b88d5760320 258 int resistance )
kenjiArai 0:5b88d5760320 259 {
kenjiArai 0:5b88d5760320 260 ctx->prediction_resistance = resistance;
kenjiArai 0:5b88d5760320 261 }
kenjiArai 0:5b88d5760320 262
kenjiArai 0:5b88d5760320 263 /*
kenjiArai 0:5b88d5760320 264 * Set entropy length grabbed for reseeds
kenjiArai 0:5b88d5760320 265 */
kenjiArai 0:5b88d5760320 266 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len )
kenjiArai 0:5b88d5760320 267 {
kenjiArai 0:5b88d5760320 268 ctx->entropy_len = len;
kenjiArai 0:5b88d5760320 269 }
kenjiArai 0:5b88d5760320 270
kenjiArai 0:5b88d5760320 271 /*
kenjiArai 0:5b88d5760320 272 * Set reseed interval
kenjiArai 0:5b88d5760320 273 */
kenjiArai 0:5b88d5760320 274 void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval )
kenjiArai 0:5b88d5760320 275 {
kenjiArai 0:5b88d5760320 276 ctx->reseed_interval = interval;
kenjiArai 0:5b88d5760320 277 }
kenjiArai 0:5b88d5760320 278
kenjiArai 0:5b88d5760320 279 /*
kenjiArai 0:5b88d5760320 280 * HMAC_DRBG random function with optional additional data:
kenjiArai 0:5b88d5760320 281 * 10.1.2.5 (arabic) + 9.3 (Roman)
kenjiArai 0:5b88d5760320 282 */
kenjiArai 0:5b88d5760320 283 int mbedtls_hmac_drbg_random_with_add( void *p_rng,
kenjiArai 0:5b88d5760320 284 unsigned char *output, size_t out_len,
kenjiArai 0:5b88d5760320 285 const unsigned char *additional, size_t add_len )
kenjiArai 0:5b88d5760320 286 {
kenjiArai 0:5b88d5760320 287 int ret;
kenjiArai 0:5b88d5760320 288 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
kenjiArai 0:5b88d5760320 289 size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info );
kenjiArai 0:5b88d5760320 290 size_t left = out_len;
kenjiArai 0:5b88d5760320 291 unsigned char *out = output;
kenjiArai 0:5b88d5760320 292
kenjiArai 0:5b88d5760320 293 /* II. Check request length */
kenjiArai 0:5b88d5760320 294 if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST )
kenjiArai 0:5b88d5760320 295 return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG );
kenjiArai 0:5b88d5760320 296
kenjiArai 0:5b88d5760320 297 /* III. Check input length */
kenjiArai 0:5b88d5760320 298 if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT )
kenjiArai 0:5b88d5760320 299 return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG );
kenjiArai 0:5b88d5760320 300
kenjiArai 0:5b88d5760320 301 /* 1. (aka VII and IX) Check reseed counter and PR */
kenjiArai 0:5b88d5760320 302 if( ctx->f_entropy != NULL && /* For no-reseeding instances */
kenjiArai 0:5b88d5760320 303 ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
kenjiArai 0:5b88d5760320 304 ctx->reseed_counter > ctx->reseed_interval ) )
kenjiArai 0:5b88d5760320 305 {
kenjiArai 0:5b88d5760320 306 if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 )
kenjiArai 0:5b88d5760320 307 return( ret );
kenjiArai 0:5b88d5760320 308
kenjiArai 0:5b88d5760320 309 add_len = 0; /* VII.4 */
kenjiArai 0:5b88d5760320 310 }
kenjiArai 0:5b88d5760320 311
kenjiArai 0:5b88d5760320 312 /* 2. Use additional data if any */
kenjiArai 0:5b88d5760320 313 if( additional != NULL && add_len != 0 )
kenjiArai 0:5b88d5760320 314 {
kenjiArai 0:5b88d5760320 315 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
kenjiArai 0:5b88d5760320 316 additional, add_len ) ) != 0 )
kenjiArai 0:5b88d5760320 317 goto exit;
kenjiArai 0:5b88d5760320 318 }
kenjiArai 0:5b88d5760320 319
kenjiArai 0:5b88d5760320 320 /* 3, 4, 5. Generate bytes */
kenjiArai 0:5b88d5760320 321 while( left != 0 )
kenjiArai 0:5b88d5760320 322 {
kenjiArai 0:5b88d5760320 323 size_t use_len = left > md_len ? md_len : left;
kenjiArai 0:5b88d5760320 324
kenjiArai 0:5b88d5760320 325 if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 )
kenjiArai 0:5b88d5760320 326 goto exit;
kenjiArai 0:5b88d5760320 327 if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx,
kenjiArai 0:5b88d5760320 328 ctx->V, md_len ) ) != 0 )
kenjiArai 0:5b88d5760320 329 goto exit;
kenjiArai 0:5b88d5760320 330 if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 )
kenjiArai 0:5b88d5760320 331 goto exit;
kenjiArai 0:5b88d5760320 332
kenjiArai 0:5b88d5760320 333 memcpy( out, ctx->V, use_len );
kenjiArai 0:5b88d5760320 334 out += use_len;
kenjiArai 0:5b88d5760320 335 left -= use_len;
kenjiArai 0:5b88d5760320 336 }
kenjiArai 0:5b88d5760320 337
kenjiArai 0:5b88d5760320 338 /* 6. Update */
kenjiArai 0:5b88d5760320 339 if( ( ret = mbedtls_hmac_drbg_update_ret( ctx,
kenjiArai 0:5b88d5760320 340 additional, add_len ) ) != 0 )
kenjiArai 0:5b88d5760320 341 goto exit;
kenjiArai 0:5b88d5760320 342
kenjiArai 0:5b88d5760320 343 /* 7. Update reseed counter */
kenjiArai 0:5b88d5760320 344 ctx->reseed_counter++;
kenjiArai 0:5b88d5760320 345
kenjiArai 0:5b88d5760320 346 exit:
kenjiArai 0:5b88d5760320 347 /* 8. Done */
kenjiArai 0:5b88d5760320 348 return( ret );
kenjiArai 0:5b88d5760320 349 }
kenjiArai 0:5b88d5760320 350
kenjiArai 0:5b88d5760320 351 /*
kenjiArai 0:5b88d5760320 352 * HMAC_DRBG random function
kenjiArai 0:5b88d5760320 353 */
kenjiArai 0:5b88d5760320 354 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len )
kenjiArai 0:5b88d5760320 355 {
kenjiArai 0:5b88d5760320 356 int ret;
kenjiArai 0:5b88d5760320 357 mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
kenjiArai 0:5b88d5760320 358
kenjiArai 0:5b88d5760320 359 #if defined(MBEDTLS_THREADING_C)
kenjiArai 0:5b88d5760320 360 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
kenjiArai 0:5b88d5760320 361 return( ret );
kenjiArai 0:5b88d5760320 362 #endif
kenjiArai 0:5b88d5760320 363
kenjiArai 0:5b88d5760320 364 ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 );
kenjiArai 0:5b88d5760320 365
kenjiArai 0:5b88d5760320 366 #if defined(MBEDTLS_THREADING_C)
kenjiArai 0:5b88d5760320 367 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
kenjiArai 0:5b88d5760320 368 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
kenjiArai 0:5b88d5760320 369 #endif
kenjiArai 0:5b88d5760320 370
kenjiArai 0:5b88d5760320 371 return( ret );
kenjiArai 0:5b88d5760320 372 }
kenjiArai 0:5b88d5760320 373
kenjiArai 0:5b88d5760320 374 /*
kenjiArai 0:5b88d5760320 375 * Free an HMAC_DRBG context
kenjiArai 0:5b88d5760320 376 */
kenjiArai 0:5b88d5760320 377 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx )
kenjiArai 0:5b88d5760320 378 {
kenjiArai 0:5b88d5760320 379 if( ctx == NULL )
kenjiArai 0:5b88d5760320 380 return;
kenjiArai 0:5b88d5760320 381
kenjiArai 0:5b88d5760320 382 #if defined(MBEDTLS_THREADING_C)
kenjiArai 0:5b88d5760320 383 mbedtls_mutex_free( &ctx->mutex );
kenjiArai 0:5b88d5760320 384 #endif
kenjiArai 0:5b88d5760320 385 mbedtls_md_free( &ctx->md_ctx );
kenjiArai 0:5b88d5760320 386 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) );
kenjiArai 0:5b88d5760320 387 }
kenjiArai 0:5b88d5760320 388
kenjiArai 0:5b88d5760320 389 #if defined(MBEDTLS_FS_IO)
kenjiArai 0:5b88d5760320 390 int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
kenjiArai 0:5b88d5760320 391 {
kenjiArai 0:5b88d5760320 392 int ret;
kenjiArai 0:5b88d5760320 393 FILE *f;
kenjiArai 0:5b88d5760320 394 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
kenjiArai 0:5b88d5760320 395
kenjiArai 0:5b88d5760320 396 if( ( f = fopen( path, "wb" ) ) == NULL )
kenjiArai 0:5b88d5760320 397 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
kenjiArai 0:5b88d5760320 398
kenjiArai 0:5b88d5760320 399 if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 )
kenjiArai 0:5b88d5760320 400 goto exit;
kenjiArai 0:5b88d5760320 401
kenjiArai 0:5b88d5760320 402 if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) )
kenjiArai 0:5b88d5760320 403 {
kenjiArai 0:5b88d5760320 404 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
kenjiArai 0:5b88d5760320 405 goto exit;
kenjiArai 0:5b88d5760320 406 }
kenjiArai 0:5b88d5760320 407
kenjiArai 0:5b88d5760320 408 ret = 0;
kenjiArai 0:5b88d5760320 409
kenjiArai 0:5b88d5760320 410 exit:
kenjiArai 0:5b88d5760320 411 fclose( f );
kenjiArai 0:5b88d5760320 412 mbedtls_platform_zeroize( buf, sizeof( buf ) );
kenjiArai 0:5b88d5760320 413
kenjiArai 0:5b88d5760320 414 return( ret );
kenjiArai 0:5b88d5760320 415 }
kenjiArai 0:5b88d5760320 416
kenjiArai 0:5b88d5760320 417 int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path )
kenjiArai 0:5b88d5760320 418 {
kenjiArai 0:5b88d5760320 419 int ret = 0;
kenjiArai 0:5b88d5760320 420 FILE *f = NULL;
kenjiArai 0:5b88d5760320 421 size_t n;
kenjiArai 0:5b88d5760320 422 unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ];
kenjiArai 0:5b88d5760320 423 unsigned char c;
kenjiArai 0:5b88d5760320 424
kenjiArai 0:5b88d5760320 425 if( ( f = fopen( path, "rb" ) ) == NULL )
kenjiArai 0:5b88d5760320 426 return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR );
kenjiArai 0:5b88d5760320 427
kenjiArai 0:5b88d5760320 428 n = fread( buf, 1, sizeof( buf ), f );
kenjiArai 0:5b88d5760320 429 if( fread( &c, 1, 1, f ) != 0 )
kenjiArai 0:5b88d5760320 430 {
kenjiArai 0:5b88d5760320 431 ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
kenjiArai 0:5b88d5760320 432 goto exit;
kenjiArai 0:5b88d5760320 433 }
kenjiArai 0:5b88d5760320 434 if( n == 0 || ferror( f ) )
kenjiArai 0:5b88d5760320 435 {
kenjiArai 0:5b88d5760320 436 ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
kenjiArai 0:5b88d5760320 437 goto exit;
kenjiArai 0:5b88d5760320 438 }
kenjiArai 0:5b88d5760320 439 fclose( f );
kenjiArai 0:5b88d5760320 440 f = NULL;
kenjiArai 0:5b88d5760320 441
kenjiArai 0:5b88d5760320 442 ret = mbedtls_hmac_drbg_update_ret( ctx, buf, n );
kenjiArai 0:5b88d5760320 443
kenjiArai 0:5b88d5760320 444 exit:
kenjiArai 0:5b88d5760320 445 mbedtls_platform_zeroize( buf, sizeof( buf ) );
kenjiArai 0:5b88d5760320 446 if( f != NULL )
kenjiArai 0:5b88d5760320 447 fclose( f );
kenjiArai 0:5b88d5760320 448 if( ret != 0 )
kenjiArai 0:5b88d5760320 449 return( ret );
kenjiArai 0:5b88d5760320 450 return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) );
kenjiArai 0:5b88d5760320 451 }
kenjiArai 0:5b88d5760320 452 #endif /* MBEDTLS_FS_IO */
kenjiArai 0:5b88d5760320 453
kenjiArai 0:5b88d5760320 454
kenjiArai 0:5b88d5760320 455 #if defined(MBEDTLS_SELF_TEST)
kenjiArai 0:5b88d5760320 456
kenjiArai 0:5b88d5760320 457 #if !defined(MBEDTLS_SHA1_C)
kenjiArai 0:5b88d5760320 458 /* Dummy checkup routine */
kenjiArai 0:5b88d5760320 459 int mbedtls_hmac_drbg_self_test( int verbose )
kenjiArai 0:5b88d5760320 460 {
kenjiArai 0:5b88d5760320 461 (void) verbose;
kenjiArai 0:5b88d5760320 462 return( 0 );
kenjiArai 0:5b88d5760320 463 }
kenjiArai 0:5b88d5760320 464 #else
kenjiArai 0:5b88d5760320 465
kenjiArai 0:5b88d5760320 466 #define OUTPUT_LEN 80
kenjiArai 0:5b88d5760320 467
kenjiArai 0:5b88d5760320 468 /* From a NIST PR=true test vector */
kenjiArai 0:5b88d5760320 469 static const unsigned char entropy_pr[] = {
kenjiArai 0:5b88d5760320 470 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
kenjiArai 0:5b88d5760320 471 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
kenjiArai 0:5b88d5760320 472 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
kenjiArai 0:5b88d5760320 473 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
kenjiArai 0:5b88d5760320 474 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 };
kenjiArai 0:5b88d5760320 475 static const unsigned char result_pr[OUTPUT_LEN] = {
kenjiArai 0:5b88d5760320 476 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
kenjiArai 0:5b88d5760320 477 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
kenjiArai 0:5b88d5760320 478 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
kenjiArai 0:5b88d5760320 479 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
kenjiArai 0:5b88d5760320 480 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
kenjiArai 0:5b88d5760320 481 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
kenjiArai 0:5b88d5760320 482 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 };
kenjiArai 0:5b88d5760320 483
kenjiArai 0:5b88d5760320 484 /* From a NIST PR=false test vector */
kenjiArai 0:5b88d5760320 485 static const unsigned char entropy_nopr[] = {
kenjiArai 0:5b88d5760320 486 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
kenjiArai 0:5b88d5760320 487 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
kenjiArai 0:5b88d5760320 488 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
kenjiArai 0:5b88d5760320 489 0xe9, 0x9d, 0xfe, 0xdf };
kenjiArai 0:5b88d5760320 490 static const unsigned char result_nopr[OUTPUT_LEN] = {
kenjiArai 0:5b88d5760320 491 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
kenjiArai 0:5b88d5760320 492 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
kenjiArai 0:5b88d5760320 493 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
kenjiArai 0:5b88d5760320 494 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
kenjiArai 0:5b88d5760320 495 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
kenjiArai 0:5b88d5760320 496 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
kenjiArai 0:5b88d5760320 497 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 };
kenjiArai 0:5b88d5760320 498
kenjiArai 0:5b88d5760320 499 /* "Entropy" from buffer */
kenjiArai 0:5b88d5760320 500 static size_t test_offset;
kenjiArai 0:5b88d5760320 501 static int hmac_drbg_self_test_entropy( void *data,
kenjiArai 0:5b88d5760320 502 unsigned char *buf, size_t len )
kenjiArai 0:5b88d5760320 503 {
kenjiArai 0:5b88d5760320 504 const unsigned char *p = data;
kenjiArai 0:5b88d5760320 505 memcpy( buf, p + test_offset, len );
kenjiArai 0:5b88d5760320 506 test_offset += len;
kenjiArai 0:5b88d5760320 507 return( 0 );
kenjiArai 0:5b88d5760320 508 }
kenjiArai 0:5b88d5760320 509
kenjiArai 0:5b88d5760320 510 #define CHK( c ) if( (c) != 0 ) \
kenjiArai 0:5b88d5760320 511 { \
kenjiArai 0:5b88d5760320 512 if( verbose != 0 ) \
kenjiArai 0:5b88d5760320 513 mbedtls_printf( "failed\n" ); \
kenjiArai 0:5b88d5760320 514 return( 1 ); \
kenjiArai 0:5b88d5760320 515 }
kenjiArai 0:5b88d5760320 516
kenjiArai 0:5b88d5760320 517 /*
kenjiArai 0:5b88d5760320 518 * Checkup routine for HMAC_DRBG with SHA-1
kenjiArai 0:5b88d5760320 519 */
kenjiArai 0:5b88d5760320 520 int mbedtls_hmac_drbg_self_test( int verbose )
kenjiArai 0:5b88d5760320 521 {
kenjiArai 0:5b88d5760320 522 mbedtls_hmac_drbg_context ctx;
kenjiArai 0:5b88d5760320 523 unsigned char buf[OUTPUT_LEN];
kenjiArai 0:5b88d5760320 524 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 );
kenjiArai 0:5b88d5760320 525
kenjiArai 0:5b88d5760320 526 mbedtls_hmac_drbg_init( &ctx );
kenjiArai 0:5b88d5760320 527
kenjiArai 0:5b88d5760320 528 /*
kenjiArai 0:5b88d5760320 529 * PR = True
kenjiArai 0:5b88d5760320 530 */
kenjiArai 0:5b88d5760320 531 if( verbose != 0 )
kenjiArai 0:5b88d5760320 532 mbedtls_printf( " HMAC_DRBG (PR = True) : " );
kenjiArai 0:5b88d5760320 533
kenjiArai 0:5b88d5760320 534 test_offset = 0;
kenjiArai 0:5b88d5760320 535 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
kenjiArai 0:5b88d5760320 536 hmac_drbg_self_test_entropy, (void *) entropy_pr,
kenjiArai 0:5b88d5760320 537 NULL, 0 ) );
kenjiArai 0:5b88d5760320 538 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON );
kenjiArai 0:5b88d5760320 539 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
kenjiArai 0:5b88d5760320 540 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
kenjiArai 0:5b88d5760320 541 CHK( memcmp( buf, result_pr, OUTPUT_LEN ) );
kenjiArai 0:5b88d5760320 542 mbedtls_hmac_drbg_free( &ctx );
kenjiArai 0:5b88d5760320 543
kenjiArai 0:5b88d5760320 544 mbedtls_hmac_drbg_free( &ctx );
kenjiArai 0:5b88d5760320 545
kenjiArai 0:5b88d5760320 546 if( verbose != 0 )
kenjiArai 0:5b88d5760320 547 mbedtls_printf( "passed\n" );
kenjiArai 0:5b88d5760320 548
kenjiArai 0:5b88d5760320 549 /*
kenjiArai 0:5b88d5760320 550 * PR = False
kenjiArai 0:5b88d5760320 551 */
kenjiArai 0:5b88d5760320 552 if( verbose != 0 )
kenjiArai 0:5b88d5760320 553 mbedtls_printf( " HMAC_DRBG (PR = False) : " );
kenjiArai 0:5b88d5760320 554
kenjiArai 0:5b88d5760320 555 mbedtls_hmac_drbg_init( &ctx );
kenjiArai 0:5b88d5760320 556
kenjiArai 0:5b88d5760320 557 test_offset = 0;
kenjiArai 0:5b88d5760320 558 CHK( mbedtls_hmac_drbg_seed( &ctx, md_info,
kenjiArai 0:5b88d5760320 559 hmac_drbg_self_test_entropy, (void *) entropy_nopr,
kenjiArai 0:5b88d5760320 560 NULL, 0 ) );
kenjiArai 0:5b88d5760320 561 CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) );
kenjiArai 0:5b88d5760320 562 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
kenjiArai 0:5b88d5760320 563 CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) );
kenjiArai 0:5b88d5760320 564 CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) );
kenjiArai 0:5b88d5760320 565 mbedtls_hmac_drbg_free( &ctx );
kenjiArai 0:5b88d5760320 566
kenjiArai 0:5b88d5760320 567 mbedtls_hmac_drbg_free( &ctx );
kenjiArai 0:5b88d5760320 568
kenjiArai 0:5b88d5760320 569 if( verbose != 0 )
kenjiArai 0:5b88d5760320 570 mbedtls_printf( "passed\n" );
kenjiArai 0:5b88d5760320 571
kenjiArai 0:5b88d5760320 572 if( verbose != 0 )
kenjiArai 0:5b88d5760320 573 mbedtls_printf( "\n" );
kenjiArai 0:5b88d5760320 574
kenjiArai 0:5b88d5760320 575 return( 0 );
kenjiArai 0:5b88d5760320 576 }
kenjiArai 0:5b88d5760320 577 #endif /* MBEDTLS_SHA1_C */
kenjiArai 0:5b88d5760320 578 #endif /* MBEDTLS_SELF_TEST */
kenjiArai 0:5b88d5760320 579
kenjiArai 0:5b88d5760320 580 #endif /* MBEDTLS_HMAC_DRBG_C */