Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

crypto: jitter - replace LFSR with SHA3-256

Using the kernel crypto API, the SHA3-256 algorithm is used as
conditioning element to replace the LFSR in the Jitter RNG. All other
parts of the Jitter RNG are unchanged.

The application and use of the SHA-3 conditioning operation is identical
to the user space Jitter RNG 3.4.0 by applying the following concept:

- the Jitter RNG initializes a SHA-3 state which acts as the "entropy
pool" when the Jitter RNG is allocated.

- When a new time delta is obtained, it is inserted into the "entropy
pool" with a SHA-3 update operation. Note, this operation in most of
the cases is a simple memcpy() onto the SHA-3 stack.

- To cause a true SHA-3 operation for each time delta operation, a
second SHA-3 operation is performed hashing Jitter RNG status
information. The final message digest is also inserted into the
"entropy pool" with a SHA-3 update operation. Yet, this data is not
considered to provide any entropy, but it shall stir the entropy pool.

- To generate a random number, a SHA-3 final operation is performed to
calculate a message digest followed by an immediate SHA-3 init to
re-initialize the "entropy pool". The obtained message digest is one
block of the Jitter RNG that is returned to the caller.

Mathematically speaking, the random number generated by the Jitter RNG
is:

aux_t = SHA-3(Jitter RNG state data)

Jitter RNG block = SHA-3(time_i || aux_i || time_(i-1) || aux_(i-1) ||
... || time_(i-255) || aux_(i-255))

when assuming that the OSR = 1, i.e. the default value.

This operation implies that the Jitter RNG has an output-blocksize of
256 bits instead of the 64 bits of the LFSR-based Jitter RNG that is
replaced with this patch.

The patch also replaces the varying number of invocations of the
conditioning function with one fixed number of invocations. The use
of the conditioning function consistent with the userspace Jitter RNG
library version 3.4.0.

The code is tested with a system that exhibited the least amount of
entropy generated by the Jitter RNG: the SiFive Unmatched RISC-V
system. The measured entropy rate is well above the heuristically
implied entropy value of 1 bit of entropy per time delta. On all other
tested systems, the measured entropy rate is even higher by orders
of magnitude. The measurement was performed using updated tooling
provided with the user space Jitter RNG library test framework.

The performance of the Jitter RNG with this patch is about en par
with the performance of the Jitter RNG without the patch.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Stephan Müller and committed by
Herbert Xu
bb897c55 3908edf8

+219 -120
+1
crypto/Kconfig
··· 1277 1277 config CRYPTO_JITTERENTROPY 1278 1278 tristate "CPU Jitter Non-Deterministic RNG (Random Number Generator)" 1279 1279 select CRYPTO_RNG 1280 + select CRYPTO_SHA3 1280 1281 help 1281 1282 CPU Jitter RNG (Random Number Generator) from the Jitterentropy library 1282 1283
+164 -21
crypto/jitterentropy-kcapi.c
··· 2 2 * Non-physical true random number generator based on timing jitter -- 3 3 * Linux Kernel Crypto API specific code 4 4 * 5 - * Copyright Stephan Mueller <smueller@chronox.de>, 2015 5 + * Copyright Stephan Mueller <smueller@chronox.de>, 2015 - 2023 6 6 * 7 7 * Redistribution and use in source and binary forms, with or without 8 8 * modification, are permitted provided that the following conditions ··· 37 37 * DAMAGE. 38 38 */ 39 39 40 + #include <crypto/hash.h> 41 + #include <crypto/sha3.h> 40 42 #include <linux/fips.h> 41 43 #include <linux/kernel.h> 42 44 #include <linux/module.h> ··· 47 45 #include <crypto/internal/rng.h> 48 46 49 47 #include "jitterentropy.h" 48 + 49 + #define JENT_CONDITIONING_HASH "sha3-256-generic" 50 50 51 51 /*************************************************************************** 52 52 * Helper function ··· 62 58 void jent_zfree(void *ptr) 63 59 { 64 60 kfree_sensitive(ptr); 65 - } 66 - 67 - void jent_memcpy(void *dest, const void *src, unsigned int n) 68 - { 69 - memcpy(dest, src, n); 70 61 } 71 62 72 63 /* ··· 90 91 *out = tmp; 91 92 } 92 93 94 + int jent_hash_time(void *hash_state, __u64 time, u8 *addtl, 95 + unsigned int addtl_len, __u64 hash_loop_cnt, 96 + unsigned int stuck) 97 + { 98 + struct shash_desc *hash_state_desc = (struct shash_desc *)hash_state; 99 + SHASH_DESC_ON_STACK(desc, hash_state_desc->tfm); 100 + u8 intermediary[SHA3_256_DIGEST_SIZE]; 101 + __u64 j = 0; 102 + int ret; 103 + 104 + desc->tfm = hash_state_desc->tfm; 105 + 106 + if (sizeof(intermediary) != crypto_shash_digestsize(desc->tfm)) { 107 + pr_warn_ratelimited("Unexpected digest size\n"); 108 + return -EINVAL; 109 + } 110 + 111 + /* 112 + * This loop fills a buffer which is injected into the entropy pool. 113 + * The main reason for this loop is to execute something over which we 114 + * can perform a timing measurement. The injection of the resulting 115 + * data into the pool is performed to ensure the result is used and 116 + * the compiler cannot optimize the loop away in case the result is not 117 + * used at all. Yet that data is considered "additional information" 118 + * considering the terminology from SP800-90A without any entropy. 119 + * 120 + * Note, it does not matter which or how much data you inject, we are 121 + * interested in one Keccack1600 compression operation performed with 122 + * the crypto_shash_final. 123 + */ 124 + for (j = 0; j < hash_loop_cnt; j++) { 125 + ret = crypto_shash_init(desc) ?: 126 + crypto_shash_update(desc, intermediary, 127 + sizeof(intermediary)) ?: 128 + crypto_shash_finup(desc, addtl, addtl_len, intermediary); 129 + if (ret) 130 + goto err; 131 + } 132 + 133 + /* 134 + * Inject the data from the previous loop into the pool. This data is 135 + * not considered to contain any entropy, but it stirs the pool a bit. 136 + */ 137 + ret = crypto_shash_update(desc, intermediary, sizeof(intermediary)); 138 + if (ret) 139 + goto err; 140 + 141 + /* 142 + * Insert the time stamp into the hash context representing the pool. 143 + * 144 + * If the time stamp is stuck, do not finally insert the value into the 145 + * entropy pool. Although this operation should not do any harm even 146 + * when the time stamp has no entropy, SP800-90B requires that any 147 + * conditioning operation to have an identical amount of input data 148 + * according to section 3.1.5. 149 + */ 150 + if (!stuck) { 151 + ret = crypto_shash_update(hash_state_desc, (u8 *)&time, 152 + sizeof(__u64)); 153 + } 154 + 155 + err: 156 + shash_desc_zero(desc); 157 + memzero_explicit(intermediary, sizeof(intermediary)); 158 + 159 + return ret; 160 + } 161 + 162 + int jent_read_random_block(void *hash_state, char *dst, unsigned int dst_len) 163 + { 164 + struct shash_desc *hash_state_desc = (struct shash_desc *)hash_state; 165 + u8 jent_block[SHA3_256_DIGEST_SIZE]; 166 + /* Obtain data from entropy pool and re-initialize it */ 167 + int ret = crypto_shash_final(hash_state_desc, jent_block) ?: 168 + crypto_shash_init(hash_state_desc) ?: 169 + crypto_shash_update(hash_state_desc, jent_block, 170 + sizeof(jent_block)); 171 + 172 + if (!ret && dst_len) 173 + memcpy(dst, jent_block, dst_len); 174 + 175 + memzero_explicit(jent_block, sizeof(jent_block)); 176 + return ret; 177 + } 178 + 93 179 /*************************************************************************** 94 180 * Kernel crypto API interface 95 181 ***************************************************************************/ ··· 182 98 struct jitterentropy { 183 99 spinlock_t jent_lock; 184 100 struct rand_data *entropy_collector; 101 + struct crypto_shash *tfm; 102 + struct shash_desc *sdesc; 185 103 }; 186 - 187 - static int jent_kcapi_init(struct crypto_tfm *tfm) 188 - { 189 - struct jitterentropy *rng = crypto_tfm_ctx(tfm); 190 - int ret = 0; 191 - 192 - rng->entropy_collector = jent_entropy_collector_alloc(1, 0); 193 - if (!rng->entropy_collector) 194 - ret = -ENOMEM; 195 - 196 - spin_lock_init(&rng->jent_lock); 197 - return ret; 198 - } 199 104 200 105 static void jent_kcapi_cleanup(struct crypto_tfm *tfm) 201 106 { 202 107 struct jitterentropy *rng = crypto_tfm_ctx(tfm); 203 108 204 109 spin_lock(&rng->jent_lock); 110 + 111 + if (rng->sdesc) { 112 + shash_desc_zero(rng->sdesc); 113 + kfree(rng->sdesc); 114 + } 115 + rng->sdesc = NULL; 116 + 117 + if (rng->tfm) 118 + crypto_free_shash(rng->tfm); 119 + rng->tfm = NULL; 120 + 205 121 if (rng->entropy_collector) 206 122 jent_entropy_collector_free(rng->entropy_collector); 207 123 rng->entropy_collector = NULL; 208 124 spin_unlock(&rng->jent_lock); 125 + } 126 + 127 + static int jent_kcapi_init(struct crypto_tfm *tfm) 128 + { 129 + struct jitterentropy *rng = crypto_tfm_ctx(tfm); 130 + struct crypto_shash *hash; 131 + struct shash_desc *sdesc; 132 + int size, ret = 0; 133 + 134 + spin_lock_init(&rng->jent_lock); 135 + 136 + /* 137 + * Use SHA3-256 as conditioner. We allocate only the generic 138 + * implementation as we are not interested in high-performance. The 139 + * execution time of the SHA3 operation is measured and adds to the 140 + * Jitter RNG's unpredictable behavior. If we have a slower hash 141 + * implementation, the execution timing variations are larger. When 142 + * using a fast implementation, we would need to call it more often 143 + * as its variations are lower. 144 + */ 145 + hash = crypto_alloc_shash(JENT_CONDITIONING_HASH, 0, 0); 146 + if (IS_ERR(hash)) { 147 + pr_err("Cannot allocate conditioning digest\n"); 148 + return PTR_ERR(hash); 149 + } 150 + rng->tfm = hash; 151 + 152 + size = sizeof(struct shash_desc) + crypto_shash_descsize(hash); 153 + sdesc = kmalloc(size, GFP_KERNEL); 154 + if (!sdesc) { 155 + ret = -ENOMEM; 156 + goto err; 157 + } 158 + 159 + sdesc->tfm = hash; 160 + crypto_shash_init(sdesc); 161 + rng->sdesc = sdesc; 162 + 163 + rng->entropy_collector = jent_entropy_collector_alloc(1, 0, sdesc); 164 + if (!rng->entropy_collector) { 165 + ret = -ENOMEM; 166 + goto err; 167 + } 168 + 169 + spin_lock_init(&rng->jent_lock); 170 + return 0; 171 + 172 + err: 173 + jent_kcapi_cleanup(tfm); 174 + return ret; 209 175 } 210 176 211 177 static int jent_kcapi_random(struct crypto_rng *tfm, ··· 314 180 .cra_module = THIS_MODULE, 315 181 .cra_init = jent_kcapi_init, 316 182 .cra_exit = jent_kcapi_cleanup, 317 - 318 183 } 319 184 }; 320 185 321 186 static int __init jent_mod_init(void) 322 187 { 188 + SHASH_DESC_ON_STACK(desc, tfm); 189 + struct crypto_shash *tfm; 323 190 int ret = 0; 324 191 325 - ret = jent_entropy_init(); 192 + tfm = crypto_alloc_shash(JENT_CONDITIONING_HASH, 0, 0); 193 + if (IS_ERR(tfm)) 194 + return PTR_ERR(tfm); 195 + 196 + desc->tfm = tfm; 197 + crypto_shash_init(desc); 198 + ret = jent_entropy_init(desc); 199 + shash_desc_zero(desc); 200 + crypto_free_shash(tfm); 326 201 if (ret) { 327 202 /* Handle permanent health test error */ 328 203 if (fips_enabled)
+47 -96
crypto/jitterentropy.c
··· 2 2 * Non-physical true random number generator based on timing jitter -- 3 3 * Jitter RNG standalone code. 4 4 * 5 - * Copyright Stephan Mueller <smueller@chronox.de>, 2015 - 2020 5 + * Copyright Stephan Mueller <smueller@chronox.de>, 2015 - 2023 6 6 * 7 7 * Design 8 8 * ====== ··· 47 47 48 48 /* 49 49 * This Jitterentropy RNG is based on the jitterentropy library 50 - * version 2.2.0 provided at https://www.chronox.de/jent.html 50 + * version 3.4.0 provided at https://www.chronox.de/jent.html 51 51 */ 52 52 53 53 #ifdef __OPTIMIZE__ ··· 57 57 typedef unsigned long long __u64; 58 58 typedef long long __s64; 59 59 typedef unsigned int __u32; 60 + typedef unsigned char u8; 60 61 #define NULL ((void *) 0) 61 62 62 63 /* The entropy pool */ 63 64 struct rand_data { 65 + /* SHA3-256 is used as conditioner */ 66 + #define DATA_SIZE_BITS 256 64 67 /* all data values that are vital to maintain the security 65 68 * of the RNG are marked as SENSITIVE. A user must not 66 69 * access that information while the RNG executes its loops to 67 70 * calculate the next random value. */ 68 - __u64 data; /* SENSITIVE Actual random number */ 69 - __u64 old_data; /* SENSITIVE Previous random number */ 70 - __u64 prev_time; /* SENSITIVE Previous time stamp */ 71 - #define DATA_SIZE_BITS ((sizeof(__u64)) * 8) 72 - __u64 last_delta; /* SENSITIVE stuck test */ 73 - __s64 last_delta2; /* SENSITIVE stuck test */ 74 - unsigned int osr; /* Oversample rate */ 71 + void *hash_state; /* SENSITIVE hash state entropy pool */ 72 + __u64 prev_time; /* SENSITIVE Previous time stamp */ 73 + __u64 last_delta; /* SENSITIVE stuck test */ 74 + __s64 last_delta2; /* SENSITIVE stuck test */ 75 + unsigned int osr; /* Oversample rate */ 75 76 #define JENT_MEMORY_BLOCKS 64 76 77 #define JENT_MEMORY_BLOCKSIZE 32 77 78 #define JENT_MEMORY_ACCESSLOOPS 128 ··· 303 302 * an entropy collection. 304 303 * 305 304 * Input: 306 - * @ec entropy collector struct -- may be NULL 307 305 * @bits is the number of low bits of the timer to consider 308 306 * @min is the number of bits we shift the timer value to the right at 309 307 * the end to make sure we have a guaranteed minimum value 310 308 * 311 309 * @return Newly calculated loop counter 312 310 */ 313 - static __u64 jent_loop_shuffle(struct rand_data *ec, 314 - unsigned int bits, unsigned int min) 311 + static __u64 jent_loop_shuffle(unsigned int bits, unsigned int min) 315 312 { 316 313 __u64 time = 0; 317 314 __u64 shuffle = 0; ··· 317 318 unsigned int mask = (1<<bits) - 1; 318 319 319 320 jent_get_nstime(&time); 320 - /* 321 - * Mix the current state of the random number into the shuffle 322 - * calculation to balance that shuffle a bit more. 323 - */ 324 - if (ec) 325 - time ^= ec->data; 321 + 326 322 /* 327 323 * We fold the time value as much as possible to ensure that as many 328 324 * bits of the time stamp are included as possible. ··· 339 345 * execution time jitter 340 346 * 341 347 * This function injects the individual bits of the time value into the 342 - * entropy pool using an LFSR. 348 + * entropy pool using a hash. 343 349 * 344 - * The code is deliberately inefficient with respect to the bit shifting 345 - * and shall stay that way. This function is the root cause why the code 346 - * shall be compiled without optimization. This function not only acts as 347 - * folding operation, but this function's execution is used to measure 348 - * the CPU execution time jitter. Any change to the loop in this function 349 - * implies that careful retesting must be done. 350 - * 351 - * @ec [in] entropy collector struct 352 - * @time [in] time stamp to be injected 353 - * @loop_cnt [in] if a value not equal to 0 is set, use the given value as 354 - * number of loops to perform the folding 355 - * @stuck [in] Is the time stamp identified as stuck? 350 + * ec [in] entropy collector 351 + * time [in] time stamp to be injected 352 + * stuck [in] Is the time stamp identified as stuck? 356 353 * 357 354 * Output: 358 - * updated ec->data 359 - * 360 - * @return Number of loops the folding operation is performed 355 + * updated hash context in the entropy collector or error code 361 356 */ 362 - static void jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt, 363 - int stuck) 357 + static int jent_condition_data(struct rand_data *ec, __u64 time, int stuck) 364 358 { 365 - unsigned int i; 366 - __u64 j = 0; 367 - __u64 new = 0; 368 - #define MAX_FOLD_LOOP_BIT 4 369 - #define MIN_FOLD_LOOP_BIT 0 370 - __u64 fold_loop_cnt = 371 - jent_loop_shuffle(ec, MAX_FOLD_LOOP_BIT, MIN_FOLD_LOOP_BIT); 359 + #define SHA3_HASH_LOOP (1<<3) 360 + struct { 361 + int rct_count; 362 + unsigned int apt_observations; 363 + unsigned int apt_count; 364 + unsigned int apt_base; 365 + } addtl = { 366 + ec->rct_count, 367 + ec->apt_observations, 368 + ec->apt_count, 369 + ec->apt_base 370 + }; 372 371 373 - /* 374 - * testing purposes -- allow test app to set the counter, not 375 - * needed during runtime 376 - */ 377 - if (loop_cnt) 378 - fold_loop_cnt = loop_cnt; 379 - for (j = 0; j < fold_loop_cnt; j++) { 380 - new = ec->data; 381 - for (i = 1; (DATA_SIZE_BITS) >= i; i++) { 382 - __u64 tmp = time << (DATA_SIZE_BITS - i); 383 - 384 - tmp = tmp >> (DATA_SIZE_BITS - 1); 385 - 386 - /* 387 - * Fibonacci LSFR with polynomial of 388 - * x^64 + x^61 + x^56 + x^31 + x^28 + x^23 + 1 which is 389 - * primitive according to 390 - * http://poincare.matf.bg.ac.rs/~ezivkovm/publications/primpol1.pdf 391 - * (the shift values are the polynomial values minus one 392 - * due to counting bits from 0 to 63). As the current 393 - * position is always the LSB, the polynomial only needs 394 - * to shift data in from the left without wrap. 395 - */ 396 - tmp ^= ((new >> 63) & 1); 397 - tmp ^= ((new >> 60) & 1); 398 - tmp ^= ((new >> 55) & 1); 399 - tmp ^= ((new >> 30) & 1); 400 - tmp ^= ((new >> 27) & 1); 401 - tmp ^= ((new >> 22) & 1); 402 - new <<= 1; 403 - new ^= tmp; 404 - } 405 - } 406 - 407 - /* 408 - * If the time stamp is stuck, do not finally insert the value into 409 - * the entropy pool. Although this operation should not do any harm 410 - * even when the time stamp has no entropy, SP800-90B requires that 411 - * any conditioning operation (SP800-90B considers the LFSR to be a 412 - * conditioning operation) to have an identical amount of input 413 - * data according to section 3.1.5. 414 - */ 415 - if (!stuck) 416 - ec->data = new; 372 + return jent_hash_time(ec->hash_state, time, (u8 *)&addtl, sizeof(addtl), 373 + SHA3_HASH_LOOP, stuck); 417 374 } 418 375 419 376 /* ··· 398 453 #define MAX_ACC_LOOP_BIT 7 399 454 #define MIN_ACC_LOOP_BIT 0 400 455 __u64 acc_loop_cnt = 401 - jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT); 456 + jent_loop_shuffle(MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT); 402 457 403 458 if (NULL == ec || NULL == ec->mem) 404 459 return; ··· 466 521 stuck = jent_stuck(ec, current_delta); 467 522 468 523 /* Now call the next noise sources which also injects the data */ 469 - jent_lfsr_time(ec, current_delta, 0, stuck); 524 + if (jent_condition_data(ec, current_delta, stuck)) 525 + stuck = 1; 470 526 471 527 return stuck; 472 528 } 473 529 474 530 /* 475 531 * Generator of one 64 bit random number 476 - * Function fills rand_data->data 532 + * Function fills rand_data->hash_state 477 533 * 478 534 * @ec [in] Reference to entropy collector 479 535 */ ··· 521 575 * @return 0 when request is fulfilled or an error 522 576 * 523 577 * The following error codes can occur: 524 - * -1 entropy_collector is NULL 578 + * -1 entropy_collector is NULL or the generation failed 525 579 * -2 Intermittent health failure 526 580 * -3 Permanent health failure 527 581 */ ··· 551 605 * Perform startup health tests and return permanent 552 606 * error if it fails. 553 607 */ 554 - if (jent_entropy_init()) 608 + if (jent_entropy_init(ec->hash_state)) 555 609 return -3; 556 610 557 611 return -2; ··· 561 615 tocopy = (DATA_SIZE_BITS / 8); 562 616 else 563 617 tocopy = len; 564 - jent_memcpy(p, &ec->data, tocopy); 618 + if (jent_read_random_block(ec->hash_state, p, tocopy)) 619 + return -1; 565 620 566 621 len -= tocopy; 567 622 p += tocopy; ··· 576 629 ***************************************************************************/ 577 630 578 631 struct rand_data *jent_entropy_collector_alloc(unsigned int osr, 579 - unsigned int flags) 632 + unsigned int flags, 633 + void *hash_state) 580 634 { 581 635 struct rand_data *entropy_collector; 582 636 ··· 604 656 osr = 1; /* minimum sampling rate is 1 */ 605 657 entropy_collector->osr = osr; 606 658 659 + entropy_collector->hash_state = hash_state; 660 + 607 661 /* fill the data pad with non-zero values */ 608 662 jent_gen_entropy(entropy_collector); 609 663 ··· 619 669 jent_zfree(entropy_collector); 620 670 } 621 671 622 - int jent_entropy_init(void) 672 + int jent_entropy_init(void *hash_state) 623 673 { 624 674 int i; 625 675 __u64 delta_sum = 0; ··· 632 682 633 683 /* Required for RCT */ 634 684 ec.osr = 1; 685 + ec.hash_state = hash_state; 635 686 636 687 /* We could perform statistical tests here, but the problem is 637 688 * that we only have a few loop counts to do testing. These ··· 670 719 /* Invoke core entropy collection logic */ 671 720 jent_get_nstime(&time); 672 721 ec.prev_time = time; 673 - jent_lfsr_time(&ec, time, 0, 0); 722 + jent_condition_data(&ec, time, 0); 674 723 jent_get_nstime(&time2); 675 724 676 725 /* test whether timer works */
+7 -3
crypto/jitterentropy.h
··· 2 2 3 3 extern void *jent_zalloc(unsigned int len); 4 4 extern void jent_zfree(void *ptr); 5 - extern void jent_memcpy(void *dest, const void *src, unsigned int n); 6 5 extern void jent_get_nstime(__u64 *out); 6 + extern int jent_hash_time(void *hash_state, __u64 time, u8 *addtl, 7 + unsigned int addtl_len, __u64 hash_loop_cnt, 8 + unsigned int stuck); 9 + int jent_read_random_block(void *hash_state, char *dst, unsigned int dst_len); 7 10 8 11 struct rand_data; 9 - extern int jent_entropy_init(void); 12 + extern int jent_entropy_init(void *hash_state); 10 13 extern int jent_read_entropy(struct rand_data *ec, unsigned char *data, 11 14 unsigned int len); 12 15 13 16 extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr, 14 - unsigned int flags); 17 + unsigned int flags, 18 + void *hash_state); 15 19 extern void jent_entropy_collector_free(struct rand_data *entropy_collector);