Software APIs
dif_csrng.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 
6 
11 #include "sw/device/lib/dif/dif_csrng_shared.h"
12 
13 #include "csrng_regs.h" // Generated
14 
15 /**
16  * Reads the output data register status.
17  */
18 static void get_output_status(const dif_csrng_t *csrng,
20  uint32_t reg =
21  mmio_region_read32(csrng->base_addr, CSRNG_GENBITS_VLD_REG_OFFSET);
22  status->valid_data =
23  bitfield_bit32_read(reg, CSRNG_GENBITS_VLD_GENBITS_VLD_BIT);
24  status->fips_mode =
25  bitfield_bit32_read(reg, CSRNG_GENBITS_VLD_GENBITS_FIPS_BIT);
26 }
27 
28 /**
29  * Returns true if the data register has valid data.
30  */
31 static void spin_until_ready(const dif_csrng_t *csrng) {
33  do {
34  get_output_status(csrng, &status);
35  } while (!status.valid_data);
36 }
37 
38 static dif_result_t check_locked(const dif_csrng_t *csrng) {
39  if (mmio_region_read32(csrng->base_addr, CSRNG_REGWEN_REG_OFFSET) == 0) {
40  return kDifLocked;
41  }
42  return kDifOk;
43 }
44 
46  if (csrng == NULL) {
47  return kDifBadArg;
48  }
49  DIF_RETURN_IF_ERROR(check_locked(csrng));
50 
51  uint32_t reg =
52  bitfield_field32_write(0, CSRNG_CTRL_ENABLE_FIELD, kMultiBitBool4True);
53  reg = bitfield_field32_write(reg, CSRNG_CTRL_SW_APP_ENABLE_FIELD,
54  kMultiBitBool4True);
55  reg = bitfield_field32_write(reg, CSRNG_CTRL_READ_INT_STATE_FIELD,
56  kMultiBitBool4True);
57  mmio_region_write32(csrng->base_addr, CSRNG_CTRL_REG_OFFSET, reg);
58  return kDifOk;
59 }
60 
62  const dif_csrng_t *csrng, dif_csrng_entropy_src_toggle_t entropy_src_enable,
63  const dif_csrng_seed_material_t *seed_material) {
64  if (csrng == NULL || seed_material == NULL) {
65  return kDifBadArg;
66  }
67  return csrng_send_app_cmd(csrng->base_addr, kCsrngAppCmdTypeCsrng,
69  .id = kCsrngAppCmdInstantiate,
70  .entropy_src_enable = entropy_src_enable,
71  .seed_material = seed_material,
72  });
73 }
74 
76  const dif_csrng_seed_material_t *seed_material) {
77  if (csrng == NULL || seed_material == NULL) {
78  return kDifBadArg;
79  }
80  return csrng_send_app_cmd(csrng->base_addr, kCsrngAppCmdTypeCsrng,
82  .id = kCsrngAppCmdReseed,
83  .seed_material = seed_material,
84  });
85 }
86 
88  const dif_csrng_seed_material_t *seed_material) {
89  if (csrng == NULL || seed_material == NULL) {
90  return kDifBadArg;
91  }
92  return csrng_send_app_cmd(csrng->base_addr, kCsrngAppCmdTypeCsrng,
94  .id = kCsrngAppCmdUpdate,
95  .seed_material = seed_material,
96  });
97 }
98 
100  if (csrng == NULL || len == 0) {
101  return kDifBadArg;
102  }
103 
104  // Round up the number of 128bit blocks. Aligning with respect to uint32_t.
105  // TODO(#6112): Consider using a canonical reference for alignment operations.
106  const uint32_t num_128bit_blocks = (len + 3) / 4;
107  return csrng_send_app_cmd(csrng->base_addr, kCsrngAppCmdTypeCsrng,
108  (csrng_app_cmd_t){
109  .id = kCsrngAppCmdGenerate,
110  .generate_len = num_128bit_blocks,
111  });
112 }
113 
115  size_t len) {
116  if (csrng == NULL || buf == NULL) {
117  return kDifBadArg;
118  }
119 
120  for (size_t i = 0; i < len; ++i) {
121  // Block until there is more data available in the genbits buffer.
122  if (i % kCsrngGenBitsBufferSize == 0) {
123  spin_until_ready(csrng);
124  }
125  buf[i] = mmio_region_read32(csrng->base_addr, CSRNG_GENBITS_REG_OFFSET);
126  }
127  return kDifOk;
128 }
129 
131  if (csrng == NULL) {
132  return kDifBadArg;
133  }
134  return csrng_send_app_cmd(csrng->base_addr, kCsrngAppCmdTypeCsrng,
135  (csrng_app_cmd_t){
136  .id = kCsrngAppCmdUninstantiate,
137  });
138 }
139 
141  const dif_csrng_t *csrng, dif_csrng_cmd_status_t *status) {
142  if (csrng == NULL || status == NULL) {
143  return kDifBadArg;
144  }
146 
147  uint32_t reg =
148  mmio_region_read32(csrng->base_addr, CSRNG_SW_CMD_STS_REG_OFFSET);
149  bool cmd_ready = bitfield_bit32_read(reg, CSRNG_SW_CMD_STS_CMD_RDY_BIT);
150  uint32_t cmd_sts = bitfield_field32_read(reg, CSRNG_SW_CMD_STS_CMD_STS_FIELD);
151 
152  status->cmd_sts = cmd_sts;
153  // If the command did not execute successfully, return the error status.
154  if (cmd_sts != 0) {
156  return kDifOk;
157  }
158 
159  if (cmd_ready) {
161  return kDifOk;
162  }
163 
165  return kDifOk;
166 }
167 
169  dif_csrng_fifo_t fifo) {
170  if (csrng == NULL) {
171  return kDifBadArg;
172  }
173 
174  uint32_t fifo_bit;
175  switch (fifo) {
176  case kDifCsrngFifoCmd:
177  fifo_bit = CSRNG_ERR_CODE_SFIFO_CMD_ERR_BIT;
178  break;
179  case kDifCsrngFifoGenBits:
180  fifo_bit = CSRNG_ERR_CODE_SFIFO_GENBITS_ERR_BIT;
181  break;
182  case kDifCsrngFifoCmdReq:
183  fifo_bit = CSRNG_ERR_CODE_SFIFO_CMDREQ_ERR_BIT;
184  break;
185  case kDifCsrngFifoRcStage:
186  fifo_bit = CSRNG_ERR_CODE_SFIFO_RCSTAGE_ERR_BIT;
187  break;
188  case kDifCsrngFifoKeyVrc:
189  fifo_bit = CSRNG_ERR_CODE_SFIFO_KEYVRC_ERR_BIT;
190  break;
191  case kDifCsrngFifoUpdateReq:
192  fifo_bit = CSRNG_ERR_CODE_SFIFO_UPDREQ_ERR_BIT;
193  break;
194  case kDifCsrngFifoBencRec:
195  fifo_bit = CSRNG_ERR_CODE_SFIFO_BENCREQ_ERR_BIT;
196  break;
197  case kDifCsrngFifoBencAck:
198  fifo_bit = CSRNG_ERR_CODE_SFIFO_BENCACK_ERR_BIT;
199  break;
200  case kDifCsrngFifoPData:
201  fifo_bit = CSRNG_ERR_CODE_SFIFO_PDATA_ERR_BIT;
202  break;
203  case kDifCsrngFifoFinal:
204  fifo_bit = CSRNG_ERR_CODE_SFIFO_FINAL_ERR_BIT;
205  break;
206  case kDifCsrngFifoGBencAck:
207  fifo_bit = CSRNG_ERR_CODE_SFIFO_GBENCACK_ERR_BIT;
208  break;
209  case kDifCsrngFifoGrcStage:
210  fifo_bit = CSRNG_ERR_CODE_SFIFO_GRCSTAGE_ERR_BIT;
211  break;
212  case kDifCsrngFifoGGenReq:
213  fifo_bit = CSRNG_ERR_CODE_SFIFO_GGENREQ_ERR_BIT;
214  break;
215  case kDifCsrngFifoGadStage:
216  fifo_bit = CSRNG_ERR_CODE_SFIFO_GADSTAGE_ERR_BIT;
217  break;
218  case kDifCsrngFifoBlockEnc:
219  fifo_bit = CSRNG_ERR_CODE_SFIFO_BLKENC_ERR_BIT;
220  break;
221  default:
222  return kDifBadArg;
223  }
224 
225  DIF_RETURN_IF_ERROR(check_locked(csrng));
226  mmio_region_write32(csrng->base_addr, CSRNG_ERR_CODE_TEST_REG_OFFSET,
227  fifo_bit);
228  return kDifOk;
229 }
230 
232  dif_csrng_error_t error) {
233  if (csrng == NULL) {
234  return kDifBadArg;
235  }
236 
237  uint32_t error_bit;
238  switch (error) {
240  error_bit = CSRNG_ERR_CODE_CMD_STAGE_SM_ERR_BIT;
241  break;
243  error_bit = CSRNG_ERR_CODE_MAIN_SM_ERR_BIT;
244  break;
246  error_bit = CSRNG_ERR_CODE_DRBG_GEN_SM_ERR_BIT;
247  break;
249  error_bit = CSRNG_ERR_CODE_DRBG_UPDBE_SM_ERR_BIT;
250  break;
252  error_bit = CSRNG_ERR_CODE_DRBG_UPDOB_SM_ERR_BIT;
253  break;
254  case kDifCsrngErrorAesSm:
255  error_bit = CSRNG_ERR_CODE_AES_CIPHER_SM_ERR_BIT;
256  break;
258  error_bit = CSRNG_ERR_CODE_CMD_GEN_CNT_ERR_BIT;
259  break;
261  error_bit = CSRNG_ERR_CODE_FIFO_WRITE_ERR_BIT;
262  break;
264  error_bit = CSRNG_ERR_CODE_FIFO_READ_ERR_BIT;
265  break;
267  error_bit = CSRNG_ERR_CODE_FIFO_STATE_ERR_BIT;
268  break;
269  default:
270  return kDifBadArg;
271  }
272 
273  DIF_RETURN_IF_ERROR(check_locked(csrng));
274  mmio_region_write32(csrng->base_addr, CSRNG_ERR_CODE_TEST_REG_OFFSET,
275  error_bit);
276  return kDifOk;
277 }
278 
280  uint32_t *state) {
281  if (csrng == NULL || state == NULL) {
282  return kDifBadArg;
283  }
284 
285  *state = mmio_region_read32(csrng->base_addr, CSRNG_MAIN_SM_STATE_REG_OFFSET);
286  return kDifOk;
287 }
288 
290  uint32_t *exceptions) {
291  if (csrng == NULL || exceptions == NULL) {
292  return kDifBadArg;
293  }
294 
295  *exceptions =
296  mmio_region_read32(csrng->base_addr, CSRNG_HW_EXC_STS_REG_OFFSET);
297  return kDifOk;
298 }
299 
301  if (csrng == NULL) {
302  return kDifBadArg;
303  }
304 
305  mmio_region_write32(csrng->base_addr, CSRNG_HW_EXC_STS_REG_OFFSET, 0);
306  return kDifOk;
307 }
308 
311  if (csrng == NULL || status == NULL) {
312  return kDifBadArg;
313  }
314  get_output_status(csrng, status);
315  return kDifOk;
316 }
317 
319  const dif_csrng_t *csrng, dif_csrng_internal_state_id_t instance_id,
321  if (csrng == NULL || state == NULL) {
322  return kDifBadArg;
323  }
324 
325  // Select the instance id to read the internal state from, request a state
326  // machine halt, and wait for the internal registers to be ready to be read.
327  uint32_t reg = bitfield_field32_write(
328  0, CSRNG_INT_STATE_NUM_INT_STATE_NUM_FIELD, instance_id);
329  mmio_region_write32(csrng->base_addr, CSRNG_INT_STATE_NUM_REG_OFFSET, reg);
330  uint32_t actual_reg =
331  mmio_region_read32(csrng->base_addr, CSRNG_INT_STATE_NUM_REG_OFFSET);
332  if (reg != actual_reg) {
333  return kDifError;
334  }
335 
336  // Read the internal state.
337  state->reseed_counter =
338  mmio_region_read32(csrng->base_addr, CSRNG_INT_STATE_VAL_REG_OFFSET);
339 
340  for (size_t i = 0; i < ARRAYSIZE(state->v); ++i) {
341  state->v[i] =
342  mmio_region_read32(csrng->base_addr, CSRNG_INT_STATE_VAL_REG_OFFSET);
343  }
344 
345  for (size_t i = 0; i < ARRAYSIZE(state->key); ++i) {
346  state->key[i] =
347  mmio_region_read32(csrng->base_addr, CSRNG_INT_STATE_VAL_REG_OFFSET);
348  }
349 
350  uint32_t flags =
351  mmio_region_read32(csrng->base_addr, CSRNG_INT_STATE_VAL_REG_OFFSET);
352 
353  // The following bit indexes are defined in
354  // https://docs.opentitan.org/hw/ip/csrng/doc/#working-state-values
355  state->instantiated = bitfield_bit32_read(flags, /*bit_index=*/0u);
356  state->fips_compliance = bitfield_bit32_read(flags, /*bit_index=*/1u);
357 
358  return kDifOk;
359 }
360 
362  if (csrng == NULL) {
363  return kDifBadArg;
364  }
365  mmio_region_write32(csrng->base_addr, CSRNG_REGWEN_REG_OFFSET, 0);
366  return kDifOk;
367 }
368 
369 dif_result_t dif_csrng_is_locked(const dif_csrng_t *csrng, bool *is_locked) {
370  if (csrng == NULL || is_locked == NULL) {
371  return kDifBadArg;
372  }
373  *is_locked = check_locked(csrng) != kDifOk;
374  return kDifOk;
375 }
376 
378  if (csrng == NULL) {
379  return kDifBadArg;
380  }
381  DIF_RETURN_IF_ERROR(check_locked(csrng));
382  mmio_region_write32(csrng->base_addr, CSRNG_CTRL_REG_OFFSET,
383  CSRNG_CTRL_REG_RESVAL);
384  return kDifOk;
385 }
386 
388  uint32_t *alerts) {
389  if (csrng == NULL || alerts == NULL) {
390  return kDifBadArg;
391  }
392 
393  *alerts =
394  mmio_region_read32(csrng->base_addr, CSRNG_RECOV_ALERT_STS_REG_OFFSET);
395 
396  return kDifOk;
397 }
398 
400  if (csrng == NULL) {
401  return kDifBadArg;
402  }
403  mmio_region_write32(csrng->base_addr, CSRNG_RECOV_ALERT_STS_REG_OFFSET, 0);
404  return kDifOk;
405 }