Software APIs
entropy_kat.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 #include "sw/device/lib/crypto/drivers/entropy_kat.h"
5 
9 #include "sw/device/lib/crypto/drivers/entropy.h"
11 
12 #include "csrng_regs.h" // Generated
14 
15 #define MODULE_ID MAKE_MODULE_ID('e', 'n', 'k')
16 
17 enum {
18  kBaseCsrng = TOP_EARLGREY_CSRNG_BASE_ADDR,
19 };
20 
21 /**
22  * CSRNG internal state selector ID.
23  */
24 typedef enum entropy_csrng_internal_state_id {
25  /**
26  * CSRNG instance assigned to Entropy Distribution Network (EDN) 0.
27  */
29  /**
30  * CSRNG instance assigned to Entropy Distribution Network (EDN) 1.
31  */
33  /**
34  * CSRNG instance assigned to software interface.
35  */
37 } entropy_csrng_internal_state_id_t;
38 
39 /**
40  * CSRNG internal state.
41  */
43  /**
44  * Indicates the number of requests for pseudorandom bits since instantiation
45  * or reseeding.
46  */
47  uint32_t reseed_counter;
48  /**
49  * Internal V working state with a 128bit block size.
50  */
51  uint32_t v[4];
52  /**
53  * Internal key used to configure the internal CSRNG cipher.
54  */
55  uint32_t key[8];
56  /**
57  * Set to true when the CSRNG instance has been instantiated.
58  */
60  /**
61  * Set to true when FIPS compliant entropy was provided directly by the
62  * entropy source to instantiate or reseed the CSRNG instance.
63  */
66 
67 static void entropy_csrng_internal_state_get(
68  entropy_csrng_internal_state_id_t instance_id,
70  // Select the instance id to read the internal state from, request a state
71  // machine halt, and wait for the internal registers to be ready to be read.
72  uint32_t reg = bitfield_field32_write(
73  0, CSRNG_INT_STATE_NUM_INT_STATE_NUM_FIELD, instance_id);
74  abs_mmio_write32(kBaseCsrng + CSRNG_INT_STATE_NUM_REG_OFFSET, reg);
75 
76  // Read the internal state.
77  state->reseed_counter =
78  abs_mmio_read32(kBaseCsrng + CSRNG_INT_STATE_VAL_REG_OFFSET);
79 
80  for (size_t i = 0; i < ARRAYSIZE(state->v); ++i) {
81  state->v[i] = abs_mmio_read32(kBaseCsrng + CSRNG_INT_STATE_VAL_REG_OFFSET);
82  }
83 
84  for (size_t i = 0; i < ARRAYSIZE(state->key); ++i) {
85  state->key[i] =
86  abs_mmio_read32(kBaseCsrng + CSRNG_INT_STATE_VAL_REG_OFFSET);
87  }
88 
89  uint32_t flags = abs_mmio_read32(kBaseCsrng + CSRNG_INT_STATE_VAL_REG_OFFSET);
90 
91  // The following bit indexes are defined in
92  // https://docs.opentitan.org/hw/ip/csrng/doc/#working-state-values
93  state->instantiated = bitfield_bit32_read(flags, /*bit_index=*/0u);
94  state->fips_compliance = bitfield_bit32_read(flags, /*bit_index=*/1u);
95 }
96 
97 /**
98  * Checks the CSRNG internal state against `expected` values.
99  *
100  * @param csrng A CSRNG handle.
101  * @param expected Expected CSRNG internal state.
102  */
103 static status_t check_internal_state(
104  const entropy_csrng_internal_state_t *expected) {
106  entropy_csrng_internal_state_get(kCsrngInternalStateIdSw, &got);
107  if (memcmp(&got, expected, sizeof(entropy_csrng_internal_state_t)) == 0) {
108  return OK_STATUS();
109  }
110  return INTERNAL();
111 }
112 
113 status_t entropy_csrng_kat(void) {
114  // Check that the complex is initialized.
115  TRY(entropy_complex_check());
116 
117  TRY(entropy_csrng_uninstantiate());
118 
119  const entropy_seed_material_t kEntropyInput = {
120  .data = {0x73bec010, 0x9262474c, 0x16a30f76, 0x531b51de, 0x2ee494e5,
121  0xdfec9db3, 0xcb7a879d, 0x5600419c, 0xca79b0b0, 0xdda33b5c,
122  0xa468649e, 0xdf5d73fa},
123  .len = 12,
124  };
125  TRY(entropy_csrng_instantiate(
126  /*disable_trng_input=*/kHardenedBoolTrue, &kEntropyInput));
127 
128  const entropy_csrng_internal_state_t kExpectedStateInstantiate = {
129  .reseed_counter = 0,
130  .v = {0x06b8f59e, 0x43c0b2c2, 0x21052502, 0x217b5214},
131  .key = {0x941709fd, 0xd8a25860, 0x861aecf3, 0x98a701a1, 0x0eb2c33b,
132  0x74c08fad, 0x632d5227, 0x8c52f901},
133  .instantiated = true,
134  .fips_compliance = false,
135  };
136  TRY(check_internal_state(&kExpectedStateInstantiate));
137 
138  enum {
139  kExpectedOutputLen = 16,
140  };
141 
142  uint32_t got[kExpectedOutputLen];
143  TRY(entropy_csrng_generate(/*seed_material=*/NULL, got, kExpectedOutputLen,
144  /*fips_check=*/kHardenedBoolFalse));
145  TRY(entropy_csrng_generate(/*seed_material=*/NULL, got, kExpectedOutputLen,
146  /*fips_check=*/kHardenedBoolFalse));
147 
148  const entropy_csrng_internal_state_t kExpectedStateGenerate = {
149  .reseed_counter = 2,
150  .v = {0xe73e3392, 0x7d2e92b1, 0x1a0bac9d, 0x53c78ac6},
151 
152  .key = {0x66d1b85a, 0xc19d4dfd, 0x053b73e3, 0xe9dc0f90, 0x3f015bc8,
153  0x4436e5fd, 0x1cccc697, 0x1a1c6e5f},
154  .instantiated = true,
155  .fips_compliance = false,
156  };
157  TRY(check_internal_state(&kExpectedStateGenerate));
158 
159  // Note that the word order here is reversed compared to the NIST test
160  // vectors.
161  const uint32_t kExpectedOutput[kExpectedOutputLen] = {
162  0xd1c07cd9, 0x5af8a7f1, 0x1012c84c, 0xe48bb8cb, 0x87189e99, 0xd40fccb1,
163  0x771c619b, 0xdf82ab22, 0x80b1dc2f, 0x2581f391, 0x64f7ac0c, 0x510494b3,
164  0xa43c41b7, 0xdb17514c, 0x87b107ae, 0x793e01c5,
165  };
166  if (!memcmp(got, kExpectedOutput, sizeof(kExpectedOutput))) {
167  return OK_STATUS();
168  }
169 
170  return INTERNAL();
171 }