RTC auf true

Committer:
kevman
Date:
Wed Nov 28 15:10:15 2018 +0000
Revision:
0:38ceb79fef03
RTC modified

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kevman 0:38ceb79fef03 1 /*
kevman 0:38ceb79fef03 2 * Entropy accumulator implementation
kevman 0:38ceb79fef03 3 *
kevman 0:38ceb79fef03 4 * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
kevman 0:38ceb79fef03 5 * SPDX-License-Identifier: Apache-2.0
kevman 0:38ceb79fef03 6 *
kevman 0:38ceb79fef03 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
kevman 0:38ceb79fef03 8 * not use this file except in compliance with the License.
kevman 0:38ceb79fef03 9 * You may obtain a copy of the License at
kevman 0:38ceb79fef03 10 *
kevman 0:38ceb79fef03 11 * http://www.apache.org/licenses/LICENSE-2.0
kevman 0:38ceb79fef03 12 *
kevman 0:38ceb79fef03 13 * Unless required by applicable law or agreed to in writing, software
kevman 0:38ceb79fef03 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
kevman 0:38ceb79fef03 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kevman 0:38ceb79fef03 16 * See the License for the specific language governing permissions and
kevman 0:38ceb79fef03 17 * limitations under the License.
kevman 0:38ceb79fef03 18 *
kevman 0:38ceb79fef03 19 * This file is part of mbed TLS (https://tls.mbed.org)
kevman 0:38ceb79fef03 20 */
kevman 0:38ceb79fef03 21
kevman 0:38ceb79fef03 22 #if !defined(MBEDTLS_CONFIG_FILE)
kevman 0:38ceb79fef03 23 #include "mbedtls/config.h"
kevman 0:38ceb79fef03 24 #else
kevman 0:38ceb79fef03 25 #include MBEDTLS_CONFIG_FILE
kevman 0:38ceb79fef03 26 #endif
kevman 0:38ceb79fef03 27
kevman 0:38ceb79fef03 28 #if defined(MBEDTLS_ENTROPY_C)
kevman 0:38ceb79fef03 29
kevman 0:38ceb79fef03 30 #if defined(MBEDTLS_TEST_NULL_ENTROPY)
kevman 0:38ceb79fef03 31 #warning "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! "
kevman 0:38ceb79fef03 32 #warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES "
kevman 0:38ceb79fef03 33 #warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE "
kevman 0:38ceb79fef03 34 #endif
kevman 0:38ceb79fef03 35
kevman 0:38ceb79fef03 36 #include "mbedtls/entropy.h"
kevman 0:38ceb79fef03 37 #include "mbedtls/entropy_poll.h"
kevman 0:38ceb79fef03 38 #include "mbedtls/platform_util.h"
kevman 0:38ceb79fef03 39
kevman 0:38ceb79fef03 40 #include <string.h>
kevman 0:38ceb79fef03 41
kevman 0:38ceb79fef03 42 #if defined(MBEDTLS_FS_IO)
kevman 0:38ceb79fef03 43 #include <stdio.h>
kevman 0:38ceb79fef03 44 #endif
kevman 0:38ceb79fef03 45
kevman 0:38ceb79fef03 46 #if defined(MBEDTLS_ENTROPY_NV_SEED)
kevman 0:38ceb79fef03 47 #include "mbedtls/platform.h"
kevman 0:38ceb79fef03 48 #endif
kevman 0:38ceb79fef03 49
kevman 0:38ceb79fef03 50 #if defined(MBEDTLS_SELF_TEST)
kevman 0:38ceb79fef03 51 #if defined(MBEDTLS_PLATFORM_C)
kevman 0:38ceb79fef03 52 #include "mbedtls/platform.h"
kevman 0:38ceb79fef03 53 #else
kevman 0:38ceb79fef03 54 #include <stdio.h>
kevman 0:38ceb79fef03 55 #define mbedtls_printf printf
kevman 0:38ceb79fef03 56 #endif /* MBEDTLS_PLATFORM_C */
kevman 0:38ceb79fef03 57 #endif /* MBEDTLS_SELF_TEST */
kevman 0:38ceb79fef03 58
kevman 0:38ceb79fef03 59 #if defined(MBEDTLS_HAVEGE_C)
kevman 0:38ceb79fef03 60 #include "mbedtls/havege.h"
kevman 0:38ceb79fef03 61 #endif
kevman 0:38ceb79fef03 62
kevman 0:38ceb79fef03 63 #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
kevman 0:38ceb79fef03 64
kevman 0:38ceb79fef03 65 void mbedtls_entropy_init( mbedtls_entropy_context *ctx )
kevman 0:38ceb79fef03 66 {
kevman 0:38ceb79fef03 67 ctx->source_count = 0;
kevman 0:38ceb79fef03 68 memset( ctx->source, 0, sizeof( ctx->source ) );
kevman 0:38ceb79fef03 69
kevman 0:38ceb79fef03 70 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 71 mbedtls_mutex_init( &ctx->mutex );
kevman 0:38ceb79fef03 72 #endif
kevman 0:38ceb79fef03 73
kevman 0:38ceb79fef03 74 ctx->accumulator_started = 0;
kevman 0:38ceb79fef03 75 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
kevman 0:38ceb79fef03 76 mbedtls_sha512_init( &ctx->accumulator );
kevman 0:38ceb79fef03 77 #else
kevman 0:38ceb79fef03 78 mbedtls_sha256_init( &ctx->accumulator );
kevman 0:38ceb79fef03 79 #endif
kevman 0:38ceb79fef03 80 #if defined(MBEDTLS_HAVEGE_C)
kevman 0:38ceb79fef03 81 mbedtls_havege_init( &ctx->havege_data );
kevman 0:38ceb79fef03 82 #endif
kevman 0:38ceb79fef03 83
kevman 0:38ceb79fef03 84 /* Reminder: Update ENTROPY_HAVE_STRONG in the test files
kevman 0:38ceb79fef03 85 * when adding more strong entropy sources here. */
kevman 0:38ceb79fef03 86
kevman 0:38ceb79fef03 87 #if defined(MBEDTLS_TEST_NULL_ENTROPY)
kevman 0:38ceb79fef03 88 mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL,
kevman 0:38ceb79fef03 89 1, MBEDTLS_ENTROPY_SOURCE_STRONG );
kevman 0:38ceb79fef03 90 #endif
kevman 0:38ceb79fef03 91
kevman 0:38ceb79fef03 92 #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
kevman 0:38ceb79fef03 93 #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
kevman 0:38ceb79fef03 94 mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL,
kevman 0:38ceb79fef03 95 MBEDTLS_ENTROPY_MIN_PLATFORM,
kevman 0:38ceb79fef03 96 MBEDTLS_ENTROPY_SOURCE_STRONG );
kevman 0:38ceb79fef03 97 #endif
kevman 0:38ceb79fef03 98 #if defined(MBEDTLS_TIMING_C)
kevman 0:38ceb79fef03 99 mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL,
kevman 0:38ceb79fef03 100 MBEDTLS_ENTROPY_MIN_HARDCLOCK,
kevman 0:38ceb79fef03 101 MBEDTLS_ENTROPY_SOURCE_WEAK );
kevman 0:38ceb79fef03 102 #endif
kevman 0:38ceb79fef03 103 #if defined(MBEDTLS_HAVEGE_C)
kevman 0:38ceb79fef03 104 mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data,
kevman 0:38ceb79fef03 105 MBEDTLS_ENTROPY_MIN_HAVEGE,
kevman 0:38ceb79fef03 106 MBEDTLS_ENTROPY_SOURCE_STRONG );
kevman 0:38ceb79fef03 107 #endif
kevman 0:38ceb79fef03 108 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
kevman 0:38ceb79fef03 109 mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL,
kevman 0:38ceb79fef03 110 MBEDTLS_ENTROPY_MIN_HARDWARE,
kevman 0:38ceb79fef03 111 MBEDTLS_ENTROPY_SOURCE_STRONG );
kevman 0:38ceb79fef03 112 #endif
kevman 0:38ceb79fef03 113 #if defined(MBEDTLS_ENTROPY_NV_SEED)
kevman 0:38ceb79fef03 114 mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL,
kevman 0:38ceb79fef03 115 MBEDTLS_ENTROPY_BLOCK_SIZE,
kevman 0:38ceb79fef03 116 MBEDTLS_ENTROPY_SOURCE_STRONG );
kevman 0:38ceb79fef03 117 ctx->initial_entropy_run = 0;
kevman 0:38ceb79fef03 118 #endif
kevman 0:38ceb79fef03 119 #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
kevman 0:38ceb79fef03 120 }
kevman 0:38ceb79fef03 121
kevman 0:38ceb79fef03 122 void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
kevman 0:38ceb79fef03 123 {
kevman 0:38ceb79fef03 124 #if defined(MBEDTLS_HAVEGE_C)
kevman 0:38ceb79fef03 125 mbedtls_havege_free( &ctx->havege_data );
kevman 0:38ceb79fef03 126 #endif
kevman 0:38ceb79fef03 127 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 128 mbedtls_mutex_free( &ctx->mutex );
kevman 0:38ceb79fef03 129 #endif
kevman 0:38ceb79fef03 130 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
kevman 0:38ceb79fef03 131 mbedtls_sha512_free( &ctx->accumulator );
kevman 0:38ceb79fef03 132 #else
kevman 0:38ceb79fef03 133 mbedtls_sha256_free( &ctx->accumulator );
kevman 0:38ceb79fef03 134 #endif
kevman 0:38ceb79fef03 135 #if defined(MBEDTLS_ENTROPY_NV_SEED)
kevman 0:38ceb79fef03 136 ctx->initial_entropy_run = 0;
kevman 0:38ceb79fef03 137 #endif
kevman 0:38ceb79fef03 138 ctx->source_count = 0;
kevman 0:38ceb79fef03 139 mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) );
kevman 0:38ceb79fef03 140 ctx->accumulator_started = 0;
kevman 0:38ceb79fef03 141 }
kevman 0:38ceb79fef03 142
kevman 0:38ceb79fef03 143 int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx,
kevman 0:38ceb79fef03 144 mbedtls_entropy_f_source_ptr f_source, void *p_source,
kevman 0:38ceb79fef03 145 size_t threshold, int strong )
kevman 0:38ceb79fef03 146 {
kevman 0:38ceb79fef03 147 int idx, ret = 0;
kevman 0:38ceb79fef03 148
kevman 0:38ceb79fef03 149 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 150 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
kevman 0:38ceb79fef03 151 return( ret );
kevman 0:38ceb79fef03 152 #endif
kevman 0:38ceb79fef03 153
kevman 0:38ceb79fef03 154 idx = ctx->source_count;
kevman 0:38ceb79fef03 155 if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES )
kevman 0:38ceb79fef03 156 {
kevman 0:38ceb79fef03 157 ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES;
kevman 0:38ceb79fef03 158 goto exit;
kevman 0:38ceb79fef03 159 }
kevman 0:38ceb79fef03 160
kevman 0:38ceb79fef03 161 ctx->source[idx].f_source = f_source;
kevman 0:38ceb79fef03 162 ctx->source[idx].p_source = p_source;
kevman 0:38ceb79fef03 163 ctx->source[idx].threshold = threshold;
kevman 0:38ceb79fef03 164 ctx->source[idx].strong = strong;
kevman 0:38ceb79fef03 165
kevman 0:38ceb79fef03 166 ctx->source_count++;
kevman 0:38ceb79fef03 167
kevman 0:38ceb79fef03 168 exit:
kevman 0:38ceb79fef03 169 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 170 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
kevman 0:38ceb79fef03 171 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
kevman 0:38ceb79fef03 172 #endif
kevman 0:38ceb79fef03 173
kevman 0:38ceb79fef03 174 return( ret );
kevman 0:38ceb79fef03 175 }
kevman 0:38ceb79fef03 176
kevman 0:38ceb79fef03 177 /*
kevman 0:38ceb79fef03 178 * Entropy accumulator update
kevman 0:38ceb79fef03 179 */
kevman 0:38ceb79fef03 180 static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id,
kevman 0:38ceb79fef03 181 const unsigned char *data, size_t len )
kevman 0:38ceb79fef03 182 {
kevman 0:38ceb79fef03 183 unsigned char header[2];
kevman 0:38ceb79fef03 184 unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE];
kevman 0:38ceb79fef03 185 size_t use_len = len;
kevman 0:38ceb79fef03 186 const unsigned char *p = data;
kevman 0:38ceb79fef03 187 int ret = 0;
kevman 0:38ceb79fef03 188
kevman 0:38ceb79fef03 189 if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE )
kevman 0:38ceb79fef03 190 {
kevman 0:38ceb79fef03 191 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
kevman 0:38ceb79fef03 192 if( ( ret = mbedtls_sha512_ret( data, len, tmp, 0 ) ) != 0 )
kevman 0:38ceb79fef03 193 goto cleanup;
kevman 0:38ceb79fef03 194 #else
kevman 0:38ceb79fef03 195 if( ( ret = mbedtls_sha256_ret( data, len, tmp, 0 ) ) != 0 )
kevman 0:38ceb79fef03 196 goto cleanup;
kevman 0:38ceb79fef03 197 #endif
kevman 0:38ceb79fef03 198 p = tmp;
kevman 0:38ceb79fef03 199 use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
kevman 0:38ceb79fef03 200 }
kevman 0:38ceb79fef03 201
kevman 0:38ceb79fef03 202 header[0] = source_id;
kevman 0:38ceb79fef03 203 header[1] = use_len & 0xFF;
kevman 0:38ceb79fef03 204
kevman 0:38ceb79fef03 205 /*
kevman 0:38ceb79fef03 206 * Start the accumulator if this has not already happened. Note that
kevman 0:38ceb79fef03 207 * it is sufficient to start the accumulator here only because all calls to
kevman 0:38ceb79fef03 208 * gather entropy eventually execute this code.
kevman 0:38ceb79fef03 209 */
kevman 0:38ceb79fef03 210 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
kevman 0:38ceb79fef03 211 if( ctx->accumulator_started == 0 &&
kevman 0:38ceb79fef03 212 ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
kevman 0:38ceb79fef03 213 goto cleanup;
kevman 0:38ceb79fef03 214 else
kevman 0:38ceb79fef03 215 ctx->accumulator_started = 1;
kevman 0:38ceb79fef03 216 if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 )
kevman 0:38ceb79fef03 217 goto cleanup;
kevman 0:38ceb79fef03 218 ret = mbedtls_sha512_update_ret( &ctx->accumulator, p, use_len );
kevman 0:38ceb79fef03 219 #else
kevman 0:38ceb79fef03 220 if( ctx->accumulator_started == 0 &&
kevman 0:38ceb79fef03 221 ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
kevman 0:38ceb79fef03 222 goto cleanup;
kevman 0:38ceb79fef03 223 else
kevman 0:38ceb79fef03 224 ctx->accumulator_started = 1;
kevman 0:38ceb79fef03 225 if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 )
kevman 0:38ceb79fef03 226 goto cleanup;
kevman 0:38ceb79fef03 227 ret = mbedtls_sha256_update_ret( &ctx->accumulator, p, use_len );
kevman 0:38ceb79fef03 228 #endif
kevman 0:38ceb79fef03 229
kevman 0:38ceb79fef03 230 cleanup:
kevman 0:38ceb79fef03 231 mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
kevman 0:38ceb79fef03 232
kevman 0:38ceb79fef03 233 return( ret );
kevman 0:38ceb79fef03 234 }
kevman 0:38ceb79fef03 235
kevman 0:38ceb79fef03 236 int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx,
kevman 0:38ceb79fef03 237 const unsigned char *data, size_t len )
kevman 0:38ceb79fef03 238 {
kevman 0:38ceb79fef03 239 int ret;
kevman 0:38ceb79fef03 240
kevman 0:38ceb79fef03 241 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 242 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
kevman 0:38ceb79fef03 243 return( ret );
kevman 0:38ceb79fef03 244 #endif
kevman 0:38ceb79fef03 245
kevman 0:38ceb79fef03 246 ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len );
kevman 0:38ceb79fef03 247
kevman 0:38ceb79fef03 248 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 249 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
kevman 0:38ceb79fef03 250 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
kevman 0:38ceb79fef03 251 #endif
kevman 0:38ceb79fef03 252
kevman 0:38ceb79fef03 253 return( ret );
kevman 0:38ceb79fef03 254 }
kevman 0:38ceb79fef03 255
kevman 0:38ceb79fef03 256 /*
kevman 0:38ceb79fef03 257 * Run through the different sources to add entropy to our accumulator
kevman 0:38ceb79fef03 258 */
kevman 0:38ceb79fef03 259 static int entropy_gather_internal( mbedtls_entropy_context *ctx )
kevman 0:38ceb79fef03 260 {
kevman 0:38ceb79fef03 261 int ret, i, have_one_strong = 0;
kevman 0:38ceb79fef03 262 unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER];
kevman 0:38ceb79fef03 263 size_t olen;
kevman 0:38ceb79fef03 264
kevman 0:38ceb79fef03 265 if( ctx->source_count == 0 )
kevman 0:38ceb79fef03 266 return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED );
kevman 0:38ceb79fef03 267
kevman 0:38ceb79fef03 268 /*
kevman 0:38ceb79fef03 269 * Run through our entropy sources
kevman 0:38ceb79fef03 270 */
kevman 0:38ceb79fef03 271 for( i = 0; i < ctx->source_count; i++ )
kevman 0:38ceb79fef03 272 {
kevman 0:38ceb79fef03 273 if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG )
kevman 0:38ceb79fef03 274 have_one_strong = 1;
kevman 0:38ceb79fef03 275
kevman 0:38ceb79fef03 276 olen = 0;
kevman 0:38ceb79fef03 277 if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
kevman 0:38ceb79fef03 278 buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 )
kevman 0:38ceb79fef03 279 {
kevman 0:38ceb79fef03 280 goto cleanup;
kevman 0:38ceb79fef03 281 }
kevman 0:38ceb79fef03 282
kevman 0:38ceb79fef03 283 /*
kevman 0:38ceb79fef03 284 * Add if we actually gathered something
kevman 0:38ceb79fef03 285 */
kevman 0:38ceb79fef03 286 if( olen > 0 )
kevman 0:38ceb79fef03 287 {
kevman 0:38ceb79fef03 288 if( ( ret = entropy_update( ctx, (unsigned char) i,
kevman 0:38ceb79fef03 289 buf, olen ) ) != 0 )
kevman 0:38ceb79fef03 290 return( ret );
kevman 0:38ceb79fef03 291 ctx->source[i].size += olen;
kevman 0:38ceb79fef03 292 }
kevman 0:38ceb79fef03 293 }
kevman 0:38ceb79fef03 294
kevman 0:38ceb79fef03 295 if( have_one_strong == 0 )
kevman 0:38ceb79fef03 296 ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE;
kevman 0:38ceb79fef03 297
kevman 0:38ceb79fef03 298 cleanup:
kevman 0:38ceb79fef03 299 mbedtls_platform_zeroize( buf, sizeof( buf ) );
kevman 0:38ceb79fef03 300
kevman 0:38ceb79fef03 301 return( ret );
kevman 0:38ceb79fef03 302 }
kevman 0:38ceb79fef03 303
kevman 0:38ceb79fef03 304 /*
kevman 0:38ceb79fef03 305 * Thread-safe wrapper for entropy_gather_internal()
kevman 0:38ceb79fef03 306 */
kevman 0:38ceb79fef03 307 int mbedtls_entropy_gather( mbedtls_entropy_context *ctx )
kevman 0:38ceb79fef03 308 {
kevman 0:38ceb79fef03 309 int ret;
kevman 0:38ceb79fef03 310
kevman 0:38ceb79fef03 311 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 312 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
kevman 0:38ceb79fef03 313 return( ret );
kevman 0:38ceb79fef03 314 #endif
kevman 0:38ceb79fef03 315
kevman 0:38ceb79fef03 316 ret = entropy_gather_internal( ctx );
kevman 0:38ceb79fef03 317
kevman 0:38ceb79fef03 318 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 319 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
kevman 0:38ceb79fef03 320 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
kevman 0:38ceb79fef03 321 #endif
kevman 0:38ceb79fef03 322
kevman 0:38ceb79fef03 323 return( ret );
kevman 0:38ceb79fef03 324 }
kevman 0:38ceb79fef03 325
kevman 0:38ceb79fef03 326 int mbedtls_entropy_func( void *data, unsigned char *output, size_t len )
kevman 0:38ceb79fef03 327 {
kevman 0:38ceb79fef03 328 int ret, count = 0, i, done;
kevman 0:38ceb79fef03 329 mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;
kevman 0:38ceb79fef03 330 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
kevman 0:38ceb79fef03 331
kevman 0:38ceb79fef03 332 if( len > MBEDTLS_ENTROPY_BLOCK_SIZE )
kevman 0:38ceb79fef03 333 return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
kevman 0:38ceb79fef03 334
kevman 0:38ceb79fef03 335 #if defined(MBEDTLS_ENTROPY_NV_SEED)
kevman 0:38ceb79fef03 336 /* Update the NV entropy seed before generating any entropy for outside
kevman 0:38ceb79fef03 337 * use.
kevman 0:38ceb79fef03 338 */
kevman 0:38ceb79fef03 339 if( ctx->initial_entropy_run == 0 )
kevman 0:38ceb79fef03 340 {
kevman 0:38ceb79fef03 341 ctx->initial_entropy_run = 1;
kevman 0:38ceb79fef03 342 if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 )
kevman 0:38ceb79fef03 343 return( ret );
kevman 0:38ceb79fef03 344 }
kevman 0:38ceb79fef03 345 #endif
kevman 0:38ceb79fef03 346
kevman 0:38ceb79fef03 347 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 348 if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
kevman 0:38ceb79fef03 349 return( ret );
kevman 0:38ceb79fef03 350 #endif
kevman 0:38ceb79fef03 351
kevman 0:38ceb79fef03 352 /*
kevman 0:38ceb79fef03 353 * Always gather extra entropy before a call
kevman 0:38ceb79fef03 354 */
kevman 0:38ceb79fef03 355 do
kevman 0:38ceb79fef03 356 {
kevman 0:38ceb79fef03 357 if( count++ > ENTROPY_MAX_LOOP )
kevman 0:38ceb79fef03 358 {
kevman 0:38ceb79fef03 359 ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
kevman 0:38ceb79fef03 360 goto exit;
kevman 0:38ceb79fef03 361 }
kevman 0:38ceb79fef03 362
kevman 0:38ceb79fef03 363 if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
kevman 0:38ceb79fef03 364 goto exit;
kevman 0:38ceb79fef03 365
kevman 0:38ceb79fef03 366 done = 1;
kevman 0:38ceb79fef03 367 for( i = 0; i < ctx->source_count; i++ )
kevman 0:38ceb79fef03 368 if( ctx->source[i].size < ctx->source[i].threshold )
kevman 0:38ceb79fef03 369 done = 0;
kevman 0:38ceb79fef03 370 }
kevman 0:38ceb79fef03 371 while( ! done );
kevman 0:38ceb79fef03 372
kevman 0:38ceb79fef03 373 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
kevman 0:38ceb79fef03 374
kevman 0:38ceb79fef03 375 #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
kevman 0:38ceb79fef03 376 /*
kevman 0:38ceb79fef03 377 * Note that at this stage it is assumed that the accumulator was started
kevman 0:38ceb79fef03 378 * in a previous call to entropy_update(). If this is not guaranteed, the
kevman 0:38ceb79fef03 379 * code below will fail.
kevman 0:38ceb79fef03 380 */
kevman 0:38ceb79fef03 381 if( ( ret = mbedtls_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 )
kevman 0:38ceb79fef03 382 goto exit;
kevman 0:38ceb79fef03 383
kevman 0:38ceb79fef03 384 /*
kevman 0:38ceb79fef03 385 * Reset accumulator and counters and recycle existing entropy
kevman 0:38ceb79fef03 386 */
kevman 0:38ceb79fef03 387 mbedtls_sha512_free( &ctx->accumulator );
kevman 0:38ceb79fef03 388 mbedtls_sha512_init( &ctx->accumulator );
kevman 0:38ceb79fef03 389 if( ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
kevman 0:38ceb79fef03 390 goto exit;
kevman 0:38ceb79fef03 391 if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, buf,
kevman 0:38ceb79fef03 392 MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
kevman 0:38ceb79fef03 393 goto exit;
kevman 0:38ceb79fef03 394
kevman 0:38ceb79fef03 395 /*
kevman 0:38ceb79fef03 396 * Perform second SHA-512 on entropy
kevman 0:38ceb79fef03 397 */
kevman 0:38ceb79fef03 398 if( ( ret = mbedtls_sha512_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
kevman 0:38ceb79fef03 399 buf, 0 ) ) != 0 )
kevman 0:38ceb79fef03 400 goto exit;
kevman 0:38ceb79fef03 401 #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
kevman 0:38ceb79fef03 402 if( ( ret = mbedtls_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 )
kevman 0:38ceb79fef03 403 goto exit;
kevman 0:38ceb79fef03 404
kevman 0:38ceb79fef03 405 /*
kevman 0:38ceb79fef03 406 * Reset accumulator and counters and recycle existing entropy
kevman 0:38ceb79fef03 407 */
kevman 0:38ceb79fef03 408 mbedtls_sha256_free( &ctx->accumulator );
kevman 0:38ceb79fef03 409 mbedtls_sha256_init( &ctx->accumulator );
kevman 0:38ceb79fef03 410 if( ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
kevman 0:38ceb79fef03 411 goto exit;
kevman 0:38ceb79fef03 412 if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, buf,
kevman 0:38ceb79fef03 413 MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
kevman 0:38ceb79fef03 414 goto exit;
kevman 0:38ceb79fef03 415
kevman 0:38ceb79fef03 416 /*
kevman 0:38ceb79fef03 417 * Perform second SHA-256 on entropy
kevman 0:38ceb79fef03 418 */
kevman 0:38ceb79fef03 419 if( ( ret = mbedtls_sha256_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
kevman 0:38ceb79fef03 420 buf, 0 ) ) != 0 )
kevman 0:38ceb79fef03 421 goto exit;
kevman 0:38ceb79fef03 422 #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
kevman 0:38ceb79fef03 423
kevman 0:38ceb79fef03 424 for( i = 0; i < ctx->source_count; i++ )
kevman 0:38ceb79fef03 425 ctx->source[i].size = 0;
kevman 0:38ceb79fef03 426
kevman 0:38ceb79fef03 427 memcpy( output, buf, len );
kevman 0:38ceb79fef03 428
kevman 0:38ceb79fef03 429 ret = 0;
kevman 0:38ceb79fef03 430
kevman 0:38ceb79fef03 431 exit:
kevman 0:38ceb79fef03 432 mbedtls_platform_zeroize( buf, sizeof( buf ) );
kevman 0:38ceb79fef03 433
kevman 0:38ceb79fef03 434 #if defined(MBEDTLS_THREADING_C)
kevman 0:38ceb79fef03 435 if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
kevman 0:38ceb79fef03 436 return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
kevman 0:38ceb79fef03 437 #endif
kevman 0:38ceb79fef03 438
kevman 0:38ceb79fef03 439 return( ret );
kevman 0:38ceb79fef03 440 }
kevman 0:38ceb79fef03 441
kevman 0:38ceb79fef03 442 #if defined(MBEDTLS_ENTROPY_NV_SEED)
kevman 0:38ceb79fef03 443 int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx )
kevman 0:38ceb79fef03 444 {
kevman 0:38ceb79fef03 445 int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
kevman 0:38ceb79fef03 446 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
kevman 0:38ceb79fef03 447
kevman 0:38ceb79fef03 448 /* Read new seed and write it to NV */
kevman 0:38ceb79fef03 449 if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
kevman 0:38ceb79fef03 450 return( ret );
kevman 0:38ceb79fef03 451
kevman 0:38ceb79fef03 452 if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 )
kevman 0:38ceb79fef03 453 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
kevman 0:38ceb79fef03 454
kevman 0:38ceb79fef03 455 /* Manually update the remaining stream with a separator value to diverge */
kevman 0:38ceb79fef03 456 memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
kevman 0:38ceb79fef03 457 ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
kevman 0:38ceb79fef03 458
kevman 0:38ceb79fef03 459 return( ret );
kevman 0:38ceb79fef03 460 }
kevman 0:38ceb79fef03 461 #endif /* MBEDTLS_ENTROPY_NV_SEED */
kevman 0:38ceb79fef03 462
kevman 0:38ceb79fef03 463 #if defined(MBEDTLS_FS_IO)
kevman 0:38ceb79fef03 464 int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path )
kevman 0:38ceb79fef03 465 {
kevman 0:38ceb79fef03 466 int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
kevman 0:38ceb79fef03 467 FILE *f;
kevman 0:38ceb79fef03 468 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
kevman 0:38ceb79fef03 469
kevman 0:38ceb79fef03 470 if( ( f = fopen( path, "wb" ) ) == NULL )
kevman 0:38ceb79fef03 471 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
kevman 0:38ceb79fef03 472
kevman 0:38ceb79fef03 473 if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
kevman 0:38ceb79fef03 474 goto exit;
kevman 0:38ceb79fef03 475
kevman 0:38ceb79fef03 476 if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE )
kevman 0:38ceb79fef03 477 {
kevman 0:38ceb79fef03 478 ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
kevman 0:38ceb79fef03 479 goto exit;
kevman 0:38ceb79fef03 480 }
kevman 0:38ceb79fef03 481
kevman 0:38ceb79fef03 482 ret = 0;
kevman 0:38ceb79fef03 483
kevman 0:38ceb79fef03 484 exit:
kevman 0:38ceb79fef03 485 mbedtls_platform_zeroize( buf, sizeof( buf ) );
kevman 0:38ceb79fef03 486
kevman 0:38ceb79fef03 487 fclose( f );
kevman 0:38ceb79fef03 488 return( ret );
kevman 0:38ceb79fef03 489 }
kevman 0:38ceb79fef03 490
kevman 0:38ceb79fef03 491 int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path )
kevman 0:38ceb79fef03 492 {
kevman 0:38ceb79fef03 493 int ret = 0;
kevman 0:38ceb79fef03 494 FILE *f;
kevman 0:38ceb79fef03 495 size_t n;
kevman 0:38ceb79fef03 496 unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ];
kevman 0:38ceb79fef03 497
kevman 0:38ceb79fef03 498 if( ( f = fopen( path, "rb" ) ) == NULL )
kevman 0:38ceb79fef03 499 return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
kevman 0:38ceb79fef03 500
kevman 0:38ceb79fef03 501 fseek( f, 0, SEEK_END );
kevman 0:38ceb79fef03 502 n = (size_t) ftell( f );
kevman 0:38ceb79fef03 503 fseek( f, 0, SEEK_SET );
kevman 0:38ceb79fef03 504
kevman 0:38ceb79fef03 505 if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE )
kevman 0:38ceb79fef03 506 n = MBEDTLS_ENTROPY_MAX_SEED_SIZE;
kevman 0:38ceb79fef03 507
kevman 0:38ceb79fef03 508 if( fread( buf, 1, n, f ) != n )
kevman 0:38ceb79fef03 509 ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
kevman 0:38ceb79fef03 510 else
kevman 0:38ceb79fef03 511 ret = mbedtls_entropy_update_manual( ctx, buf, n );
kevman 0:38ceb79fef03 512
kevman 0:38ceb79fef03 513 fclose( f );
kevman 0:38ceb79fef03 514
kevman 0:38ceb79fef03 515 mbedtls_platform_zeroize( buf, sizeof( buf ) );
kevman 0:38ceb79fef03 516
kevman 0:38ceb79fef03 517 if( ret != 0 )
kevman 0:38ceb79fef03 518 return( ret );
kevman 0:38ceb79fef03 519
kevman 0:38ceb79fef03 520 return( mbedtls_entropy_write_seed_file( ctx, path ) );
kevman 0:38ceb79fef03 521 }
kevman 0:38ceb79fef03 522 #endif /* MBEDTLS_FS_IO */
kevman 0:38ceb79fef03 523
kevman 0:38ceb79fef03 524 #if defined(MBEDTLS_SELF_TEST)
kevman 0:38ceb79fef03 525 #if !defined(MBEDTLS_TEST_NULL_ENTROPY)
kevman 0:38ceb79fef03 526 /*
kevman 0:38ceb79fef03 527 * Dummy source function
kevman 0:38ceb79fef03 528 */
kevman 0:38ceb79fef03 529 static int entropy_dummy_source( void *data, unsigned char *output,
kevman 0:38ceb79fef03 530 size_t len, size_t *olen )
kevman 0:38ceb79fef03 531 {
kevman 0:38ceb79fef03 532 ((void) data);
kevman 0:38ceb79fef03 533
kevman 0:38ceb79fef03 534 memset( output, 0x2a, len );
kevman 0:38ceb79fef03 535 *olen = len;
kevman 0:38ceb79fef03 536
kevman 0:38ceb79fef03 537 return( 0 );
kevman 0:38ceb79fef03 538 }
kevman 0:38ceb79fef03 539 #endif /* !MBEDTLS_TEST_NULL_ENTROPY */
kevman 0:38ceb79fef03 540
kevman 0:38ceb79fef03 541 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
kevman 0:38ceb79fef03 542
kevman 0:38ceb79fef03 543 static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len )
kevman 0:38ceb79fef03 544 {
kevman 0:38ceb79fef03 545 int ret = 0;
kevman 0:38ceb79fef03 546 size_t entropy_len = 0;
kevman 0:38ceb79fef03 547 size_t olen = 0;
kevman 0:38ceb79fef03 548 size_t attempts = buf_len;
kevman 0:38ceb79fef03 549
kevman 0:38ceb79fef03 550 while( attempts > 0 && entropy_len < buf_len )
kevman 0:38ceb79fef03 551 {
kevman 0:38ceb79fef03 552 if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len,
kevman 0:38ceb79fef03 553 buf_len - entropy_len, &olen ) ) != 0 )
kevman 0:38ceb79fef03 554 return( ret );
kevman 0:38ceb79fef03 555
kevman 0:38ceb79fef03 556 entropy_len += olen;
kevman 0:38ceb79fef03 557 attempts--;
kevman 0:38ceb79fef03 558 }
kevman 0:38ceb79fef03 559
kevman 0:38ceb79fef03 560 if( entropy_len < buf_len )
kevman 0:38ceb79fef03 561 {
kevman 0:38ceb79fef03 562 ret = 1;
kevman 0:38ceb79fef03 563 }
kevman 0:38ceb79fef03 564
kevman 0:38ceb79fef03 565 return( ret );
kevman 0:38ceb79fef03 566 }
kevman 0:38ceb79fef03 567
kevman 0:38ceb79fef03 568
kevman 0:38ceb79fef03 569 static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf,
kevman 0:38ceb79fef03 570 size_t buf_len )
kevman 0:38ceb79fef03 571 {
kevman 0:38ceb79fef03 572 unsigned char set= 0xFF;
kevman 0:38ceb79fef03 573 unsigned char unset = 0x00;
kevman 0:38ceb79fef03 574 size_t i;
kevman 0:38ceb79fef03 575
kevman 0:38ceb79fef03 576 for( i = 0; i < buf_len; i++ )
kevman 0:38ceb79fef03 577 {
kevman 0:38ceb79fef03 578 set &= buf[i];
kevman 0:38ceb79fef03 579 unset |= buf[i];
kevman 0:38ceb79fef03 580 }
kevman 0:38ceb79fef03 581
kevman 0:38ceb79fef03 582 return( set == 0xFF || unset == 0x00 );
kevman 0:38ceb79fef03 583 }
kevman 0:38ceb79fef03 584
kevman 0:38ceb79fef03 585 /*
kevman 0:38ceb79fef03 586 * A test to ensure hat the entropy sources are functioning correctly
kevman 0:38ceb79fef03 587 * and there is no obvious failure. The test performs the following checks:
kevman 0:38ceb79fef03 588 * - The entropy source is not providing only 0s (all bits unset) or 1s (all
kevman 0:38ceb79fef03 589 * bits set).
kevman 0:38ceb79fef03 590 * - The entropy source is not providing values in a pattern. Because the
kevman 0:38ceb79fef03 591 * hardware could be providing data in an arbitrary length, this check polls
kevman 0:38ceb79fef03 592 * the hardware entropy source twice and compares the result to ensure they
kevman 0:38ceb79fef03 593 * are not equal.
kevman 0:38ceb79fef03 594 * - The error code returned by the entropy source is not an error.
kevman 0:38ceb79fef03 595 */
kevman 0:38ceb79fef03 596 int mbedtls_entropy_source_self_test( int verbose )
kevman 0:38ceb79fef03 597 {
kevman 0:38ceb79fef03 598 int ret = 0;
kevman 0:38ceb79fef03 599 unsigned char buf0[2 * sizeof( unsigned long long int )];
kevman 0:38ceb79fef03 600 unsigned char buf1[2 * sizeof( unsigned long long int )];
kevman 0:38ceb79fef03 601
kevman 0:38ceb79fef03 602 if( verbose != 0 )
kevman 0:38ceb79fef03 603 mbedtls_printf( " ENTROPY_BIAS test: " );
kevman 0:38ceb79fef03 604
kevman 0:38ceb79fef03 605 memset( buf0, 0x00, sizeof( buf0 ) );
kevman 0:38ceb79fef03 606 memset( buf1, 0x00, sizeof( buf1 ) );
kevman 0:38ceb79fef03 607
kevman 0:38ceb79fef03 608 if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 )
kevman 0:38ceb79fef03 609 goto cleanup;
kevman 0:38ceb79fef03 610 if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 )
kevman 0:38ceb79fef03 611 goto cleanup;
kevman 0:38ceb79fef03 612
kevman 0:38ceb79fef03 613 /* Make sure that the returned values are not all 0 or 1 */
kevman 0:38ceb79fef03 614 if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 )
kevman 0:38ceb79fef03 615 goto cleanup;
kevman 0:38ceb79fef03 616 if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 )
kevman 0:38ceb79fef03 617 goto cleanup;
kevman 0:38ceb79fef03 618
kevman 0:38ceb79fef03 619 /* Make sure that the entropy source is not returning values in a
kevman 0:38ceb79fef03 620 * pattern */
kevman 0:38ceb79fef03 621 ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0;
kevman 0:38ceb79fef03 622
kevman 0:38ceb79fef03 623 cleanup:
kevman 0:38ceb79fef03 624 if( verbose != 0 )
kevman 0:38ceb79fef03 625 {
kevman 0:38ceb79fef03 626 if( ret != 0 )
kevman 0:38ceb79fef03 627 mbedtls_printf( "failed\n" );
kevman 0:38ceb79fef03 628 else
kevman 0:38ceb79fef03 629 mbedtls_printf( "passed\n" );
kevman 0:38ceb79fef03 630
kevman 0:38ceb79fef03 631 mbedtls_printf( "\n" );
kevman 0:38ceb79fef03 632 }
kevman 0:38ceb79fef03 633
kevman 0:38ceb79fef03 634 return( ret != 0 );
kevman 0:38ceb79fef03 635 }
kevman 0:38ceb79fef03 636
kevman 0:38ceb79fef03 637 #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
kevman 0:38ceb79fef03 638
kevman 0:38ceb79fef03 639 /*
kevman 0:38ceb79fef03 640 * The actual entropy quality is hard to test, but we can at least
kevman 0:38ceb79fef03 641 * test that the functions don't cause errors and write the correct
kevman 0:38ceb79fef03 642 * amount of data to buffers.
kevman 0:38ceb79fef03 643 */
kevman 0:38ceb79fef03 644 int mbedtls_entropy_self_test( int verbose )
kevman 0:38ceb79fef03 645 {
kevman 0:38ceb79fef03 646 int ret = 1;
kevman 0:38ceb79fef03 647 #if !defined(MBEDTLS_TEST_NULL_ENTROPY)
kevman 0:38ceb79fef03 648 mbedtls_entropy_context ctx;
kevman 0:38ceb79fef03 649 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
kevman 0:38ceb79fef03 650 unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
kevman 0:38ceb79fef03 651 size_t i, j;
kevman 0:38ceb79fef03 652 #endif /* !MBEDTLS_TEST_NULL_ENTROPY */
kevman 0:38ceb79fef03 653
kevman 0:38ceb79fef03 654 if( verbose != 0 )
kevman 0:38ceb79fef03 655 mbedtls_printf( " ENTROPY test: " );
kevman 0:38ceb79fef03 656
kevman 0:38ceb79fef03 657 #if !defined(MBEDTLS_TEST_NULL_ENTROPY)
kevman 0:38ceb79fef03 658 mbedtls_entropy_init( &ctx );
kevman 0:38ceb79fef03 659
kevman 0:38ceb79fef03 660 /* First do a gather to make sure we have default sources */
kevman 0:38ceb79fef03 661 if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 )
kevman 0:38ceb79fef03 662 goto cleanup;
kevman 0:38ceb79fef03 663
kevman 0:38ceb79fef03 664 ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16,
kevman 0:38ceb79fef03 665 MBEDTLS_ENTROPY_SOURCE_WEAK );
kevman 0:38ceb79fef03 666 if( ret != 0 )
kevman 0:38ceb79fef03 667 goto cleanup;
kevman 0:38ceb79fef03 668
kevman 0:38ceb79fef03 669 if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 )
kevman 0:38ceb79fef03 670 goto cleanup;
kevman 0:38ceb79fef03 671
kevman 0:38ceb79fef03 672 /*
kevman 0:38ceb79fef03 673 * To test that mbedtls_entropy_func writes correct number of bytes:
kevman 0:38ceb79fef03 674 * - use the whole buffer and rely on ASan to detect overruns
kevman 0:38ceb79fef03 675 * - collect entropy 8 times and OR the result in an accumulator:
kevman 0:38ceb79fef03 676 * any byte should then be 0 with probably 2^(-64), so requiring
kevman 0:38ceb79fef03 677 * each of the 32 or 64 bytes to be non-zero has a false failure rate
kevman 0:38ceb79fef03 678 * of at most 2^(-58) which is acceptable.
kevman 0:38ceb79fef03 679 */
kevman 0:38ceb79fef03 680 for( i = 0; i < 8; i++ )
kevman 0:38ceb79fef03 681 {
kevman 0:38ceb79fef03 682 if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 )
kevman 0:38ceb79fef03 683 goto cleanup;
kevman 0:38ceb79fef03 684
kevman 0:38ceb79fef03 685 for( j = 0; j < sizeof( buf ); j++ )
kevman 0:38ceb79fef03 686 acc[j] |= buf[j];
kevman 0:38ceb79fef03 687 }
kevman 0:38ceb79fef03 688
kevman 0:38ceb79fef03 689 for( j = 0; j < sizeof( buf ); j++ )
kevman 0:38ceb79fef03 690 {
kevman 0:38ceb79fef03 691 if( acc[j] == 0 )
kevman 0:38ceb79fef03 692 {
kevman 0:38ceb79fef03 693 ret = 1;
kevman 0:38ceb79fef03 694 goto cleanup;
kevman 0:38ceb79fef03 695 }
kevman 0:38ceb79fef03 696 }
kevman 0:38ceb79fef03 697
kevman 0:38ceb79fef03 698 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
kevman 0:38ceb79fef03 699 if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 )
kevman 0:38ceb79fef03 700 goto cleanup;
kevman 0:38ceb79fef03 701 #endif
kevman 0:38ceb79fef03 702
kevman 0:38ceb79fef03 703 cleanup:
kevman 0:38ceb79fef03 704 mbedtls_entropy_free( &ctx );
kevman 0:38ceb79fef03 705 #endif /* !MBEDTLS_TEST_NULL_ENTROPY */
kevman 0:38ceb79fef03 706
kevman 0:38ceb79fef03 707 if( verbose != 0 )
kevman 0:38ceb79fef03 708 {
kevman 0:38ceb79fef03 709 if( ret != 0 )
kevman 0:38ceb79fef03 710 mbedtls_printf( "failed\n" );
kevman 0:38ceb79fef03 711 else
kevman 0:38ceb79fef03 712 mbedtls_printf( "passed\n" );
kevman 0:38ceb79fef03 713
kevman 0:38ceb79fef03 714 mbedtls_printf( "\n" );
kevman 0:38ceb79fef03 715 }
kevman 0:38ceb79fef03 716
kevman 0:38ceb79fef03 717 return( ret != 0 );
kevman 0:38ceb79fef03 718 }
kevman 0:38ceb79fef03 719 #endif /* MBEDTLS_SELF_TEST */
kevman 0:38ceb79fef03 720
kevman 0:38ceb79fef03 721 #endif /* MBEDTLS_ENTROPY_C */