| /**
|
| * CPU Jitter noise source -- this is the noise source based on the CPU
|
| * execution time jitter
|
| *
|
| * This function injects the individual bits of the time value into the
|
| * entropy pool using a hash.
|
| *
|
| * @ec [in] entropy collector struct
|
| * @time_delta [in] time delta to be injected
|
| * @loop_cnt [in] if a value not equal to 0 is set, use the given value as
|
| * number of loops to perform the hash operation
|
| * @stuck [in] Is the time delta identified as stuck?
|
| *
|
| * Output:
|
| * updated hash context
|
| */
|
| static void jent_hash_time(struct rand_data *ec, uint64_t time_delta,
|
| uint64_t loop_cnt, unsigned int stuck)
|
| {
|
| HASH_CTX_ON_STACK(ctx);
|
| /* Size of intermediary ensures a Keccak operation during hash_update */
|
| uint8_t intermediary[JENT_SHA3_MAX_SIZE_BLOCK] = { 0 };
|
| uint64_t j = 0, output_value;
|
| #define MAX_HASH_LOOP 3
|
| #define MIN_HASH_LOOP 0
|
|
|
| /* Ensure that macros cannot overflow jent_loop_shuffle() */
|
| BUILD_BUG_ON((MAX_HASH_LOOP + MIN_HASH_LOOP) > 63);
|
| uint64_t hash_loop_cnt =
|
| jent_loop_shuffle(ec, MAX_HASH_LOOP, MIN_HASH_LOOP);
|
|
|
| /* Ensure that everything will fit into the intermediary buffer. */
|
| BUILD_BUG_ON(sizeof(intermediary) < (JENT_SHA3_256_SIZE_DIGEST +
|
| sizeof(uint64_t)));
|
|
|
| jent_sha3_256_init(&ctx);
|
|
|
| /*
|
| * testing purposes -- allow test app to set the counter, not
|
| * needed during runtime
|
| */
|
| if (loop_cnt)
|
| hash_loop_cnt = loop_cnt;
|
|
|
| /*
|
| * This loop fills a buffer which is injected into the entropy pool.
|
| * The main reason for this loop is to execute something over which we
|
| * can perform a timing measurement. The injection of the resulting
|
| * data into the pool is performed to ensure the result is used and
|
| * the compiler cannot optimize the loop away in case the result is not
|
| * used at all. Yet that data is considered "additional information"
|
| * considering the terminology from SP800-90A without any entropy.
|
| *
|
| * Note, it does not matter which or how much data you inject, we are
|
| * interested in one Keccack1600 compression operation performed with
|
| * the sha3_final.
|
| */
|
| for (j = 0; j < hash_loop_cnt; j++) {
|
| jent_sha3_update(&ctx, intermediary, JENT_SHA3_256_SIZE_DIGEST);
|
| jent_sha3_update(&ctx, (uint8_t *)&ec->rct_count,
|
| sizeof(ec->rct_count));
|
| jent_sha3_update(&ctx, (uint8_t *)&ec->apt_cutoff,
|
| sizeof(ec->apt_cutoff));
|
| jent_sha3_update(&ctx, (uint8_t *)&ec->apt_observations,
|
| sizeof(ec->apt_observations));
|
| jent_sha3_update(&ctx, (uint8_t *)&ec->apt_count,
|
| sizeof(ec->apt_count));
|
| jent_sha3_update(&ctx,(uint8_t *) &ec->apt_base,
|
| sizeof(ec->apt_base));
|
| jent_sha3_update(&ctx, (uint8_t *)&j, sizeof(uint64_t));
|
| jent_sha3_final(&ctx, intermediary);
|
| }
|
|
|
| /*
|
| * Insert the time stamp into the intermediary buffer after the message
|
| * digest of the intermediate data.
|
| *
|
| * If the time stamp is stuck, do not finally insert the value into the
|
| * intermediary buffer. Although this operation should not do any harm
|
| * even when the time stamp has no entropy, SP800-90B requires that any
|
| * conditioning operation to have an identical amount of input data
|
| * according to section 3.1.5.
|
| */
|
| if (!stuck) {
|
| /* Insert the time. */
|
| output_value = time_delta;
|
| } else {
|
| /* The time is considered stuck. Insert the fixed value 0. */
|
| output_value = 0;
|
| }
|
|
|
| memcpy(intermediary + JENT_SHA3_256_SIZE_DIGEST,
|
| (uint8_t *)&output_value, sizeof(uint64_t));
|
|
|
| /*
|
| * Inject the data from the intermediary buffer, including the hash we
|
| * are using for timing, and (if the timer is not stuck) the time stamp.
|
| * Only the time is considered to contain any entropy. The intermediary
|
| * buffer is exactly SHA3-256-rate-size to always cause a Keccak
|
| * operation.
|
| */
|
| jent_sha3_update(ec->hash_state, intermediary, sizeof(intermediary));
|
|
|
| jent_memset_secure(&ctx, JENT_SHA_MAX_CTX_SIZE);
|
| jent_memset_secure(intermediary, sizeof(intermediary));
|
| }
|