summaryrefslogtreecommitdiff
path: root/board/cr50/dcrypto/fips_rand.h
blob: af39269382eb6b72ea5c3822f94657e33346b1e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* Copyright 2020 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#ifndef __EC_BOARD_CR50_FIPS_RAND_H
#define __EC_BOARD_CR50_FIPS_RAND_H

#include <stddef.h>
#include <string.h>

#include "common.h"
#include "dcrypto.h"
#include "util.h"

#ifdef __cplusplus
extern "C" {
#endif

#define TRNG_SAMPLE_BITS 1

/**
 * Initialize the true random number generator (TRNG) in FIPS-compliant
 * way:
 * 1. Set 1-bit alphabet
 * 2. Set maximum possible range for internal ring-oscillator
 * 3. Disable any other post-processing beyond #2
 **/
void fips_init_trng(void);

/**
 * Returns random number with indication wherever reading is valid. This is
 * different from rand() which doesn't provide any indication.
 * High 32-bits set to zero in case of error; otherwise value >> 32 == 1
 * Use of uint64_t vs. struct results in more efficient code.
 */
uint64_t read_rand(void);

/**
 * TRNG Health Tests
 *
 * If any of the approved continuous health tests are used by the entropy
 * source, the false positive probability for these tests shall be set to
 * at least 2^(-50)  (NIST SP 800-90B 4.3).
 * Reason for 2^(-50) vs 2^(-40) is to minimize impact to user experience
 * due to false positives.
 *
 * For H1 minimal assessed entropy H >=0.85 for 1-bit samples
 * using NIST Entropy Assessment tool.
 */

/**
 * The entropy source's startup tests shall run the continuous health tests
 * over at least 4096 consecutive samples. We use 1-bit samples
 */
#define TRNG_INIT_BITS	(4096 * TRNG_SAMPLE_BITS)
#define TRNG_INIT_WORDS (BITS_TO_WORDS(TRNG_INIT_BITS))

/**
 * (1) Repetition Count Test (RCT) NIST SP 800-90B 4.4.1
 * Cut off value is computed as:
 * c = ceil(1 + (-log2 alpha)/H);
 * alpha = 2^-50, H = 0.85; RCT_CUTOFF = CEIL(1+(50/0.85))
 */
#define RCT_CUTOFF_SAMPLES 60

/**
 * Number of 32-bit words containing RCT_CUTOFF_SAMPLES samples
 */
#define RCT_CUTOFF_WORDS (BITS_TO_WORDS(RCT_CUTOFF_SAMPLES))

/**
 * (2) Adaptive Proportion Test (APT), NIST SP 800-90B 4.4.2, Table 2
 */
#if TRNG_SAMPLE_BITS == 1
/* APT Windows size W = 1024 for 1 bit samples */
#define APT_WINDOW_SIZE_SAMPLES 1024
#else
/* or 512 samples if more than 1 bit per sample */
#define APT_WINDOW_SIZE_SAMPLES 512
#endif
#define APT_WINDOW_SIZE_BITS   (APT_WINDOW_SIZE_SAMPLES * TRNG_SAMPLE_BITS)
#define APT_WINDOW_SIZE_NWORDS (BITS_TO_WORDS(APT_WINDOW_SIZE_BITS))
/**
 * Cut off value = CRITBINOM(W, power(2,(-H)),1-α).
 * 692 = CRITBINOM(1024, power(2,(-0.85)), 1 - 2^(-50))
 */
#define APT_CUTOFF_SAMPLES 692

/**
 * FIPS-compliant TRNG startup.
 * The entropy source's startup tests shall run the continuous health tests
 * over at least 4096 consecutive samples.
 * Note: This function can throw FIPS_FATAL_TRNG error
 *
 * To hide latency of reading TRNG data, this test is executed in 2 stages
 * @param stage is 0 or 1, choosing the stage. On each stage 2048
 * samples are processed. Assuming that some other tasks can be executed
 * between stages, when TRNG FIFO if filled with samples.
 *
 * Some number of samples will be available in entropy_fifo
 */
bool fips_trng_startup(int stage);


/* initialize cr50-wide DRBG replacing rand */
bool fips_drbg_init(void);
/* mark cr50-wide DRBG as not initialized */
void fips_drbg_init_clear(void);

/* FIPS DRBG initialized at boot time/first use. */
extern struct drbg_ctx fips_drbg;

/**
 * Generate valid P-256 random from FIPS DRBG, reseed DRBG with entropy from
 * verified TRNG if needed.
 *
 * @param drbg DRBG to use
 * @param out output value
 * @return HMAC_DRBG_SUCCESS if out contains random.
 */
enum hmac_result fips_p256_hmac_drbg_generate(struct drbg_ctx *drbg,
					      p256_int *out);

/* wrapper around dcrypto_p256_ecdsa_sign using FIPS-compliant HMAC_DRBG */
int fips_p256_ecdsa_sign(const p256_int *key, const p256_int *message,
			 p256_int *r, p256_int *s);
/**
 * wrapper around hmac_drbg_generate to automatically reseed drbg
 * when needed.
 */
enum hmac_result fips_hmac_drbg_generate_reseed(struct drbg_ctx *ctx, void *out,
						size_t out_len,
						const void *input,
						size_t input_len);
#ifdef __cplusplus
}
#endif
#endif /* ! __EC_BOARD_CR50_FIPS_RAND_H */