BA / SerialCom

Fork of OmniWheels by Gustav Atmel

Committer:
gustavatmel
Date:
Tue May 01 15:47:08 2018 +0000
Revision:
1:9c5af431a1f1
sdf

Who changed what in which revision?

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