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  reg = bitfield_field32_write(reg, CSRNG_CTRL_FIPS_FORCE_ENABLE_FIELD,
58  kMultiBitBool4False);
59  mmio_region_write32(csrng->base_addr, CSRNG_CTRL_REG_OFFSET, reg);
60  return kDifOk;
61 }
62 
64  const dif_csrng_t *csrng, dif_csrng_entropy_src_toggle_t entropy_src_enable,
65  const dif_csrng_seed_material_t *seed_material) {
66  if (csrng == NULL || seed_material == NULL) {
67  return kDifBadArg;
68  }
69  return csrng_send_app_cmd(csrng->base_addr, kCsrngAppCmdTypeCsrng,
71  .id = kCsrngAppCmdInstantiate,
72  .entropy_src_enable = entropy_src_enable,
73  .seed_material = seed_material,
74  });
75 }
76 
78  const dif_csrng_seed_material_t *seed_material) {
79  if (csrng == NULL || seed_material == NULL) {
80  return kDifBadArg;
81  }
82  return csrng_send_app_cmd(csrng->base_addr, kCsrngAppCmdTypeCsrng,
84  .id = kCsrngAppCmdReseed,
85  .seed_material = seed_material,
86  });
87 }
88 
90  const dif_csrng_seed_material_t *seed_material) {
91  if (csrng == NULL || seed_material == NULL) {
92  return kDifBadArg;
93  }
94  return csrng_send_app_cmd(csrng->base_addr, kCsrngAppCmdTypeCsrng,
96  .id = kCsrngAppCmdUpdate,
97  .seed_material = seed_material,
98  });
99 }
100 
102  if (csrng == NULL || len == 0) {
103  return kDifBadArg;
104  }
105 
106  // Round up the number of 128bit blocks. Aligning with respect to uint32_t.
107  // TODO(#6112): Consider using a canonical reference for alignment operations.
108  const uint32_t num_128bit_blocks = (len + 3) / 4;
109  return csrng_send_app_cmd(csrng->base_addr, kCsrngAppCmdTypeCsrng,
110  (csrng_app_cmd_t){
111  .id = kCsrngAppCmdGenerate,
112  .generate_len = num_128bit_blocks,
113  });
114 }
115 
117  size_t len) {
118  if (csrng == NULL || buf == NULL) {
119  return kDifBadArg;
120  }
121 
122  for (size_t i = 0; i < len; ++i) {
123  // Block until there is more data available in the genbits buffer.
124  if (i % kCsrngGenBitsBufferSize == 0) {
125  spin_until_ready(csrng);
126  }
127  buf[i] = mmio_region_read32(csrng->base_addr, CSRNG_GENBITS_REG_OFFSET);
128  }
129  return kDifOk;
130 }
131 
133  if (csrng == NULL) {
134  return kDifBadArg;
135  }
136  return csrng_send_app_cmd(csrng->base_addr, kCsrngAppCmdTypeCsrng,
137  (csrng_app_cmd_t){
138  .id = kCsrngAppCmdUninstantiate,
139  });
140 }
141 
143  const dif_csrng_t *csrng, dif_csrng_cmd_status_t *status) {
144  if (csrng == NULL || status == NULL) {
145  return kDifBadArg;
146  }
148 
149  uint32_t reg =
150  mmio_region_read32(csrng->base_addr, CSRNG_SW_CMD_STS_REG_OFFSET);
151  bool cmd_ready = bitfield_bit32_read(reg, CSRNG_SW_CMD_STS_CMD_RDY_BIT);
152  uint32_t cmd_sts = bitfield_field32_read(reg, CSRNG_SW_CMD_STS_CMD_STS_FIELD);
153 
154  status->cmd_sts = cmd_sts;
155  // If the command did not execute successfully, return the error status.
156  if (cmd_sts != 0) {
158  return kDifOk;
159  }
160 
161  if (cmd_ready) {
163  return kDifOk;
164  }
165 
167  return kDifOk;
168 }
169 
171  dif_csrng_fifo_t fifo) {
172  if (csrng == NULL) {
173  return kDifBadArg;
174  }
175 
176  uint32_t fifo_bit;
177  switch (fifo) {
178  case kDifCsrngFifoCmd:
179  fifo_bit = CSRNG_ERR_CODE_SFIFO_CMD_ERR_BIT;
180  break;
181  case kDifCsrngFifoGenBits:
182  fifo_bit = CSRNG_ERR_CODE_SFIFO_GENBITS_ERR_BIT;
183  break;
184  case kDifCsrngFifoCmdReq:
185  fifo_bit = CSRNG_ERR_CODE_SFIFO_CMDREQ_ERR_BIT;
186  break;
187  case kDifCsrngFifoRcStage:
188  fifo_bit = CSRNG_ERR_CODE_SFIFO_RCSTAGE_ERR_BIT;
189  break;
190  case kDifCsrngFifoKeyVrc:
191  fifo_bit = CSRNG_ERR_CODE_SFIFO_KEYVRC_ERR_BIT;
192  break;
193  case kDifCsrngFifoUpdateReq:
194  fifo_bit = CSRNG_ERR_CODE_SFIFO_UPDREQ_ERR_BIT;
195  break;
196  case kDifCsrngFifoBencRec:
197  fifo_bit = CSRNG_ERR_CODE_SFIFO_BENCREQ_ERR_BIT;
198  break;
199  case kDifCsrngFifoBencAck:
200  fifo_bit = CSRNG_ERR_CODE_SFIFO_BENCACK_ERR_BIT;
201  break;
202  case kDifCsrngFifoPData:
203  fifo_bit = CSRNG_ERR_CODE_SFIFO_PDATA_ERR_BIT;
204  break;
205  case kDifCsrngFifoFinal:
206  fifo_bit = CSRNG_ERR_CODE_SFIFO_FINAL_ERR_BIT;
207  break;
208  case kDifCsrngFifoGBencAck:
209  fifo_bit = CSRNG_ERR_CODE_SFIFO_GBENCACK_ERR_BIT;
210  break;
211  case kDifCsrngFifoGrcStage:
212  fifo_bit = CSRNG_ERR_CODE_SFIFO_GRCSTAGE_ERR_BIT;
213  break;
214  case kDifCsrngFifoGGenReq:
215  fifo_bit = CSRNG_ERR_CODE_SFIFO_GGENREQ_ERR_BIT;
216  break;
217  case kDifCsrngFifoGadStage:
218  fifo_bit = CSRNG_ERR_CODE_SFIFO_GADSTAGE_ERR_BIT;
219  break;
220  case kDifCsrngFifoBlockEnc:
221  fifo_bit = CSRNG_ERR_CODE_SFIFO_BLKENC_ERR_BIT;
222  break;
223  default:
224  return kDifBadArg;
225  }
226 
227  DIF_RETURN_IF_ERROR(check_locked(csrng));
228  mmio_region_write32(csrng->base_addr, CSRNG_ERR_CODE_TEST_REG_OFFSET,
229  fifo_bit);
230  return kDifOk;
231 }
232 
234  dif_csrng_error_t error) {
235  if (csrng == NULL) {
236  return kDifBadArg;
237  }
238 
239  uint32_t error_bit;
240  switch (error) {
242  error_bit = CSRNG_ERR_CODE_CMD_STAGE_SM_ERR_BIT;
243  break;
245  error_bit = CSRNG_ERR_CODE_MAIN_SM_ERR_BIT;
246  break;
248  error_bit = CSRNG_ERR_CODE_DRBG_GEN_SM_ERR_BIT;
249  break;
251  error_bit = CSRNG_ERR_CODE_DRBG_UPDBE_SM_ERR_BIT;
252  break;
254  error_bit = CSRNG_ERR_CODE_DRBG_UPDOB_SM_ERR_BIT;
255  break;
256  case kDifCsrngErrorAesSm:
257  error_bit = CSRNG_ERR_CODE_AES_CIPHER_SM_ERR_BIT;
258  break;
260  error_bit = CSRNG_ERR_CODE_CMD_GEN_CNT_ERR_BIT;
261  break;
263  error_bit = CSRNG_ERR_CODE_FIFO_WRITE_ERR_BIT;
264  break;
266  error_bit = CSRNG_ERR_CODE_FIFO_READ_ERR_BIT;
267  break;
269  error_bit = CSRNG_ERR_CODE_FIFO_STATE_ERR_BIT;
270  break;
271  default:
272  return kDifBadArg;
273  }
274 
275  DIF_RETURN_IF_ERROR(check_locked(csrng));
276  mmio_region_write32(csrng->base_addr, CSRNG_ERR_CODE_TEST_REG_OFFSET,
277  error_bit);
278  return kDifOk;
279 }
280 
282  uint32_t *state) {
283  if (csrng == NULL || state == NULL) {
284  return kDifBadArg;
285  }
286 
287  *state = mmio_region_read32(csrng->base_addr, CSRNG_MAIN_SM_STATE_REG_OFFSET);
288  return kDifOk;
289 }
290 
292  uint32_t *exceptions) {
293  if (csrng == NULL || exceptions == NULL) {
294  return kDifBadArg;
295  }
296 
297  *exceptions =
298  mmio_region_read32(csrng->base_addr, CSRNG_HW_EXC_STS_REG_OFFSET);
299  return kDifOk;
300 }
301 
303  if (csrng == NULL) {
304  return kDifBadArg;
305  }
306 
307  mmio_region_write32(csrng->base_addr, CSRNG_HW_EXC_STS_REG_OFFSET, 0);
308  return kDifOk;
309 }
310 
313  if (csrng == NULL || status == NULL) {
314  return kDifBadArg;
315  }
316  get_output_status(csrng, status);
317  return kDifOk;
318 }
319 
321  const dif_csrng_t *csrng, dif_csrng_internal_state_id_t instance_id,
323  if (csrng == NULL || state == NULL) {
324  return kDifBadArg;
325  }
326 
327  // Select the instance id to read the internal state from, request a state
328  // machine halt, and wait for the internal registers to be ready to be read.
329  uint32_t reg = bitfield_field32_write(
330  0, CSRNG_INT_STATE_NUM_INT_STATE_NUM_FIELD, instance_id);
331  mmio_region_write32(csrng->base_addr, CSRNG_INT_STATE_NUM_REG_OFFSET, reg);
332  uint32_t actual_reg =
333  mmio_region_read32(csrng->base_addr, CSRNG_INT_STATE_NUM_REG_OFFSET);
334  if (reg != actual_reg) {
335  return kDifError;
336  }
337 
338  // Read the internal state.
339  state->reseed_counter =
340  mmio_region_read32(csrng->base_addr, CSRNG_INT_STATE_VAL_REG_OFFSET);
341 
342  for (size_t i = 0; i < ARRAYSIZE(state->v); ++i) {
343  state->v[i] =
344  mmio_region_read32(csrng->base_addr, CSRNG_INT_STATE_VAL_REG_OFFSET);
345  }
346 
347  for (size_t i = 0; i < ARRAYSIZE(state->key); ++i) {
348  state->key[i] =
349  mmio_region_read32(csrng->base_addr, CSRNG_INT_STATE_VAL_REG_OFFSET);
350  }
351 
352  uint32_t flags =
353  mmio_region_read32(csrng->base_addr, CSRNG_INT_STATE_VAL_REG_OFFSET);
354 
355  // The following bit indexes are defined in
356  // https://docs.opentitan.org/hw/ip/csrng/doc/#working-state-values
357  state->instantiated = bitfield_bit32_read(flags, /*bit_index=*/0u);
358  state->fips_compliance = bitfield_bit32_read(flags, /*bit_index=*/1u);
359 
360  return kDifOk;
361 }
362 
364  const dif_csrng_t *csrng, dif_csrng_internal_state_id_t instance_id,
365  uint32_t *reseed_counter) {
366  if (csrng == NULL || reseed_counter == NULL) {
367  return kDifBadArg;
368  }
369 
370  uint32_t reg_offset;
371  switch (instance_id) {
373  reg_offset = CSRNG_RESEED_COUNTER_0_REG_OFFSET;
374  break;
376  reg_offset = CSRNG_RESEED_COUNTER_1_REG_OFFSET;
377  break;
379  reg_offset = CSRNG_RESEED_COUNTER_2_REG_OFFSET;
380  break;
381  default:
382  return kDifBadArg;
383  }
384 
385  // Read the reseed counter.
386  *reseed_counter = mmio_region_read32(csrng->base_addr, (ptrdiff_t)reg_offset);
387 
388  return kDifOk;
389 }
390 
392  if (csrng == NULL) {
393  return kDifBadArg;
394  }
395  mmio_region_write32(csrng->base_addr, CSRNG_REGWEN_REG_OFFSET, 0);
396  return kDifOk;
397 }
398 
399 dif_result_t dif_csrng_is_locked(const dif_csrng_t *csrng, bool *is_locked) {
400  if (csrng == NULL || is_locked == NULL) {
401  return kDifBadArg;
402  }
403  *is_locked = check_locked(csrng) != kDifOk;
404  return kDifOk;
405 }
406 
408  if (csrng == NULL) {
409  return kDifBadArg;
410  }
411  DIF_RETURN_IF_ERROR(check_locked(csrng));
412  mmio_region_write32(csrng->base_addr, CSRNG_CTRL_REG_OFFSET,
413  CSRNG_CTRL_REG_RESVAL);
414  return kDifOk;
415 }
416 
418  uint32_t *alerts) {
419  if (csrng == NULL || alerts == NULL) {
420  return kDifBadArg;
421  }
422 
423  *alerts =
424  mmio_region_read32(csrng->base_addr, CSRNG_RECOV_ALERT_STS_REG_OFFSET);
425 
426  return kDifOk;
427 }
428 
430  if (csrng == NULL) {
431  return kDifBadArg;
432  }
433  mmio_region_write32(csrng->base_addr, CSRNG_RECOV_ALERT_STS_REG_OFFSET, 0);
434  return kDifOk;
435 }