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