Software APIs
dif_keymgr_dpe.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 
7 #include <assert.h>
8 
10 
11 #include "keymgr_dpe_regs.h" // Generated.
13 
14 /**
15  * Address spaces of SW_BINDING_N, SALT_N, SW_SHARE0_OUTPUT_N, and
16  * SW_SHARE1_OUTPUT_N registers must be contiguous to be able to use
17  * `mmio_region_memcpy_to/from_mmio32()`.
18  */
19 static_assert(KEYMGR_DPE_SW_BINDING_1_REG_OFFSET ==
20  KEYMGR_DPE_SW_BINDING_0_REG_OFFSET + 4,
21  "SW_BINDING_N registers must be contiguous.");
22 static_assert(KEYMGR_DPE_SW_BINDING_2_REG_OFFSET ==
23  KEYMGR_DPE_SW_BINDING_0_REG_OFFSET + 8,
24  "SW_BINDING_N registers must be contiguous.");
25 static_assert(KEYMGR_DPE_SW_BINDING_3_REG_OFFSET ==
26  KEYMGR_DPE_SW_BINDING_0_REG_OFFSET + 12,
27  "SW_BINDING_N registers must be contiguous.");
28 static_assert(KEYMGR_DPE_SW_BINDING_4_REG_OFFSET ==
29  KEYMGR_DPE_SW_BINDING_0_REG_OFFSET + 16,
30  "SW_BINDING_N registers must be contiguous.");
31 static_assert(KEYMGR_DPE_SW_BINDING_5_REG_OFFSET ==
32  KEYMGR_DPE_SW_BINDING_0_REG_OFFSET + 20,
33  "SW_BINDING_N registers must be contiguous.");
34 static_assert(KEYMGR_DPE_SW_BINDING_6_REG_OFFSET ==
35  KEYMGR_DPE_SW_BINDING_0_REG_OFFSET + 24,
36  "SW_BINDING_N registers must be contiguous.");
37 static_assert(KEYMGR_DPE_SW_BINDING_7_REG_OFFSET ==
38  KEYMGR_DPE_SW_BINDING_0_REG_OFFSET + 28,
39  "SW_BINDING_N registers must be contiguous.");
40 
41 static_assert(KEYMGR_DPE_SALT_1_REG_OFFSET == KEYMGR_DPE_SALT_0_REG_OFFSET + 4,
42  "SALT_N registers must be contiguous.");
43 static_assert(KEYMGR_DPE_SALT_2_REG_OFFSET == KEYMGR_DPE_SALT_0_REG_OFFSET + 8,
44  "SALT_N registers must be contiguous.");
45 static_assert(KEYMGR_DPE_SALT_3_REG_OFFSET == KEYMGR_DPE_SALT_0_REG_OFFSET + 12,
46  "SALT_N registers must be contiguous.");
47 static_assert(KEYMGR_DPE_SALT_4_REG_OFFSET == KEYMGR_DPE_SALT_0_REG_OFFSET + 16,
48  "SALT_N registers must be contiguous.");
49 static_assert(KEYMGR_DPE_SALT_5_REG_OFFSET == KEYMGR_DPE_SALT_0_REG_OFFSET + 20,
50  "SALT_N registers must be contiguous.");
51 static_assert(KEYMGR_DPE_SALT_6_REG_OFFSET == KEYMGR_DPE_SALT_0_REG_OFFSET + 24,
52  "SALT_N registers must be contiguous.");
53 static_assert(KEYMGR_DPE_SALT_7_REG_OFFSET == KEYMGR_DPE_SALT_0_REG_OFFSET + 28,
54  "SALT_N registers must be contiguous.");
55 
56 static_assert(KEYMGR_DPE_SW_SHARE0_OUTPUT_1_REG_OFFSET ==
57  KEYMGR_DPE_SW_SHARE0_OUTPUT_0_REG_OFFSET + 4,
58  "SW_SHARE0_OUTPUT_N registers must be contiguous.");
59 static_assert(KEYMGR_DPE_SW_SHARE0_OUTPUT_2_REG_OFFSET ==
60  KEYMGR_DPE_SW_SHARE0_OUTPUT_0_REG_OFFSET + 8,
61  "SW_SHARE0_OUTPUT_N registers must be contiguous.");
62 static_assert(KEYMGR_DPE_SW_SHARE0_OUTPUT_3_REG_OFFSET ==
63  KEYMGR_DPE_SW_SHARE0_OUTPUT_0_REG_OFFSET + 12,
64  "SW_SHARE0_OUTPUT_N registers must be contiguous.");
65 static_assert(KEYMGR_DPE_SW_SHARE0_OUTPUT_4_REG_OFFSET ==
66  KEYMGR_DPE_SW_SHARE0_OUTPUT_0_REG_OFFSET + 16,
67  "SW_SHARE0_OUTPUT_N registers must be contiguous.");
68 static_assert(KEYMGR_DPE_SW_SHARE0_OUTPUT_5_REG_OFFSET ==
69  KEYMGR_DPE_SW_SHARE0_OUTPUT_0_REG_OFFSET + 20,
70  "SW_SHARE0_OUTPUT_N registers must be contiguous.");
71 static_assert(KEYMGR_DPE_SW_SHARE0_OUTPUT_6_REG_OFFSET ==
72  KEYMGR_DPE_SW_SHARE0_OUTPUT_0_REG_OFFSET + 24,
73  "SW_SHARE0_OUTPUT_N registers must be contiguous.");
74 static_assert(KEYMGR_DPE_SW_SHARE0_OUTPUT_7_REG_OFFSET ==
75  KEYMGR_DPE_SW_SHARE0_OUTPUT_0_REG_OFFSET + 28,
76  "SW_SHARE0_OUTPUT_N registers must be contiguous.");
77 
78 static_assert(KEYMGR_DPE_SW_SHARE1_OUTPUT_1_REG_OFFSET ==
79  KEYMGR_DPE_SW_SHARE1_OUTPUT_0_REG_OFFSET + 4,
80  "SW_SHARE1_OUTPUT_N registers must be contiguous.");
81 static_assert(KEYMGR_DPE_SW_SHARE1_OUTPUT_2_REG_OFFSET ==
82  KEYMGR_DPE_SW_SHARE1_OUTPUT_0_REG_OFFSET + 8,
83  "SW_SHARE1_OUTPUT_N registers must be contiguous.");
84 static_assert(KEYMGR_DPE_SW_SHARE1_OUTPUT_3_REG_OFFSET ==
85  KEYMGR_DPE_SW_SHARE1_OUTPUT_0_REG_OFFSET + 12,
86  "SW_SHARE1_OUTPUT_N registers must be contiguous.");
87 static_assert(KEYMGR_DPE_SW_SHARE1_OUTPUT_4_REG_OFFSET ==
88  KEYMGR_DPE_SW_SHARE1_OUTPUT_0_REG_OFFSET + 16,
89  "SW_SHARE1_OUTPUT_N registers must be contiguous.");
90 static_assert(KEYMGR_DPE_SW_SHARE1_OUTPUT_5_REG_OFFSET ==
91  KEYMGR_DPE_SW_SHARE1_OUTPUT_0_REG_OFFSET + 20,
92  "SW_SHARE1_OUTPUT_N registers must be contiguous.");
93 static_assert(KEYMGR_DPE_SW_SHARE1_OUTPUT_6_REG_OFFSET ==
94  KEYMGR_DPE_SW_SHARE1_OUTPUT_0_REG_OFFSET + 24,
95  "SW_SHARE1_OUTPUT_N registers must be contiguous.");
96 static_assert(KEYMGR_DPE_SW_SHARE1_OUTPUT_7_REG_OFFSET ==
97  KEYMGR_DPE_SW_SHARE1_OUTPUT_0_REG_OFFSET + 28,
98  "SW_SHARE1_OUTPUT_N registers must be contiguous.");
99 
100 /**
101  * Error code constants of `dif_keymgr_dpe_status_code_t` are masks for the bits
102  * of ERR_CODE register shifted left by 1.
103  */
104 static_assert(kDifKeymgrDpeStatusCodeInvalidOperation >> 1 ==
105  1 << KEYMGR_DPE_ERR_CODE_INVALID_OP_BIT,
106  "Layout of ERR_CODE register changed.");
107 static_assert(kDifKeymgrDpeStatusCodeInvalidKmacInput >> 1 ==
108  1 << KEYMGR_DPE_ERR_CODE_INVALID_KMAC_INPUT_BIT,
109  "Layout of ERR_CODE register changed.");
110 
111 /**
112  * Ensure that enum values for versioned key generation match the parameters
113  * generated by HW.
114  */
115 static_assert(kDifKeymgrDpeKeyDestAes ==
116  KEYMGR_DPE_CONTROL_SHADOWED_DEST_SEL_VALUE_AES,
117  "Key destination macros must match the values from its enum.");
118 static_assert(kDifKeymgrDpeKeyDestKmac ==
119  KEYMGR_DPE_CONTROL_SHADOWED_DEST_SEL_VALUE_KMAC,
120  "Key destination macros must match the values from its enum.");
121 static_assert(kDifKeymgrDpeKeyDestOtbn ==
122  KEYMGR_DPE_CONTROL_SHADOWED_DEST_SEL_VALUE_OTBN,
123  "Key destination macros must match the values from its enum.");
124 
125 /**
126  * Ensure that SW-visible FSM values match the one defined as SW enum.
127  */
128 static_assert(kDifKeymgrDpeStateReset ==
129  KEYMGR_DPE_WORKING_STATE_STATE_VALUE_RESET,
130  "Keymgr_DPE reported FSM state and SW enums must match.");
131 static_assert(kDifKeymgrDpeStateAvailable ==
132  KEYMGR_DPE_WORKING_STATE_STATE_VALUE_AVAILABLE,
133  "Keymgr_DPE reported FSM state and SW enums must match.");
134 static_assert(kDifKeymgrDpeStateDisabled ==
135  KEYMGR_DPE_WORKING_STATE_STATE_VALUE_DISABLED,
136  "Keymgr_DPE reported FSM state and SW enums must match.");
137 static_assert(kDifKeymgrDpeStateInvalid ==
138  KEYMGR_DPE_WORKING_STATE_STATE_VALUE_INVALID,
139  "Keymgr_DPE reported FSM state and SW enums must match.");
140 
141 /**
142  * Checks if the key manager is ready for a new operation, i.e. it is idle and
143  * the CONFIG register is unlocked.
144  */
146 static bool is_ready(const dif_keymgr_dpe_t *keymgr_dpe) {
147  // KeymgrDPE must be idle and the CONTROL register must be writable.
148  uint32_t reg_op_status = mmio_region_read32(keymgr_dpe->base_addr,
149  KEYMGR_DPE_OP_STATUS_REG_OFFSET);
150  if (bitfield_field32_read(reg_op_status, KEYMGR_DPE_OP_STATUS_STATUS_FIELD) !=
151  KEYMGR_DPE_OP_STATUS_STATUS_VALUE_IDLE) {
152  return false;
153  }
154  uint32_t reg_cfg_regwen = mmio_region_read32(
155  keymgr_dpe->base_addr, KEYMGR_DPE_CFG_REGWEN_REG_OFFSET);
156  return bitfield_bit32_read(reg_cfg_regwen, KEYMGR_DPE_CFG_REGWEN_EN_BIT);
157 }
158 
160  uint32_t slot_dst_sel) {
161  if (keymgr_dpe == NULL) {
162  return kDifBadArg;
163  }
164 
165  if (!is_ready(keymgr_dpe)) {
166  return kDifLocked;
167  }
168 
169  uint32_t reg_control = bitfield_field32_write(
170  KEYMGR_DPE_CONTROL_SHADOWED_REG_RESVAL,
171  KEYMGR_DPE_CONTROL_SHADOWED_SLOT_DST_SEL_FIELD, slot_dst_sel);
172  reg_control = bitfield_field32_write(
173  reg_control, KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_FIELD,
174  KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_VALUE_ADVANCE);
175  mmio_region_write32_shadowed(keymgr_dpe->base_addr,
176  KEYMGR_DPE_CONTROL_SHADOWED_REG_OFFSET,
177  reg_control);
178 
179  mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_START_REG_OFFSET,
180  1 << KEYMGR_DPE_START_EN_BIT);
181 
182  return kDifOk;
183 }
184 
186  const dif_keymgr_dpe_t *keymgr_dpe,
187  const dif_keymgr_dpe_advance_params_t *params) {
188  if (keymgr_dpe == NULL || params == NULL) {
189  return kDifBadArg;
190  }
191 
192  if (!is_ready(keymgr_dpe)) {
193  return kDifLocked;
194  }
195 
196  // If either of SLOT_POLICY_REGWEN, MAX_KEY_VER_REGWEN or SW_BINDING_REGWEN is
197  // locked, return error.
198  uint32_t slot_policy_regwen = mmio_region_read32(
199  keymgr_dpe->base_addr, KEYMGR_DPE_SLOT_POLICY_REGWEN_REG_OFFSET);
200  if (!bitfield_bit32_read(slot_policy_regwen,
201  KEYMGR_DPE_SLOT_POLICY_REGWEN_EN_BIT)) {
202  return kDifLocked;
203  }
204 
205  uint32_t reg_max_key_ver_wen = mmio_region_read32(
206  keymgr_dpe->base_addr, KEYMGR_DPE_MAX_KEY_VER_REGWEN_REG_OFFSET);
207  if (!bitfield_bit32_read(reg_max_key_ver_wen,
208  KEYMGR_DPE_MAX_KEY_VER_REGWEN_EN_BIT)) {
209  return kDifLocked;
210  }
211 
212  uint32_t sw_binding_regwen = mmio_region_read32(
213  keymgr_dpe->base_addr, KEYMGR_DPE_SW_BINDING_REGWEN_REG_OFFSET);
214  if (!bitfield_bit32_read(sw_binding_regwen,
215  KEYMGR_DPE_SW_BINDING_REGWEN_EN_BIT)) {
216  return kDifLocked;
217  }
218 
219  // Now that we know REGWEN registers are enabled, we can write each value and
220  // then lock REGWEN registers (rw0c).
221  mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_SLOT_POLICY_REG_OFFSET,
222  params->slot_policy);
223  mmio_region_write32(keymgr_dpe->base_addr,
224  KEYMGR_DPE_SLOT_POLICY_REGWEN_REG_OFFSET, 0);
225 
226  mmio_region_write32_shadowed(keymgr_dpe->base_addr,
227  KEYMGR_DPE_MAX_KEY_VER_SHADOWED_REG_OFFSET,
228  params->max_key_version);
229  mmio_region_write32(keymgr_dpe->base_addr,
230  KEYMGR_DPE_MAX_KEY_VER_REGWEN_REG_OFFSET, 0);
231 
233  keymgr_dpe->base_addr, KEYMGR_DPE_SW_BINDING_0_REG_OFFSET,
234  params->binding_value, sizeof(params->binding_value));
235  mmio_region_write32(keymgr_dpe->base_addr,
236  KEYMGR_DPE_SW_BINDING_REGWEN_REG_OFFSET, 0);
237 
238  uint32_t reg_control = bitfield_field32_write(
239  KEYMGR_DPE_CONTROL_SHADOWED_REG_RESVAL,
240  KEYMGR_DPE_CONTROL_SHADOWED_SLOT_SRC_SEL_FIELD, params->slot_src_sel);
241  reg_control = bitfield_field32_write(
242  reg_control, KEYMGR_DPE_CONTROL_SHADOWED_SLOT_DST_SEL_FIELD,
243  params->slot_dst_sel);
244  reg_control = bitfield_field32_write(
245  reg_control, KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_FIELD,
246  KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_VALUE_ADVANCE);
247  mmio_region_write32_shadowed(keymgr_dpe->base_addr,
248  KEYMGR_DPE_CONTROL_SHADOWED_REG_OFFSET,
249  reg_control);
250  mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_START_REG_OFFSET,
251  1 << KEYMGR_DPE_START_EN_BIT);
252 
253  return kDifOk;
254 }
255 
257  const dif_keymgr_dpe_t *keymgr_dpe,
258  const dif_keymgr_dpe_erase_params_t *params) {
259  if (keymgr_dpe == NULL) {
260  return kDifBadArg;
261  }
262 
263  if (!is_ready(keymgr_dpe)) {
264  return kDifLocked;
265  }
266 
267  uint32_t reg_control = bitfield_field32_write(
268  KEYMGR_DPE_CONTROL_SHADOWED_REG_RESVAL,
269  KEYMGR_DPE_CONTROL_SHADOWED_SLOT_DST_SEL_FIELD, params->slot_dst_sel);
270  reg_control = bitfield_field32_write(
271  reg_control, KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_FIELD,
272  KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_VALUE_ERASE_SLOT);
273  mmio_region_write32_shadowed(keymgr_dpe->base_addr,
274  KEYMGR_DPE_CONTROL_SHADOWED_REG_OFFSET,
275  reg_control);
276  mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_START_REG_OFFSET,
277  1 << KEYMGR_DPE_START_EN_BIT);
278 
279  return kDifOk;
280 }
281 
283  const dif_keymgr_dpe_t *keymgr_dpe,
284  const dif_keymgr_dpe_generate_params_t *params) {
285  if (keymgr_dpe == NULL || params == NULL) {
286  return kDifBadArg;
287  }
288 
289  if (!is_ready(keymgr_dpe)) {
290  return kDifLocked;
291  }
292 
293  uint32_t reg_control = bitfield_field32_write(
294  KEYMGR_DPE_CONTROL_SHADOWED_REG_RESVAL,
295  KEYMGR_DPE_CONTROL_SHADOWED_DEST_SEL_FIELD, params->key_dest);
296  reg_control = bitfield_field32_write(
297  reg_control, KEYMGR_DPE_CONTROL_SHADOWED_SLOT_SRC_SEL_FIELD,
298  params->slot_src_sel);
299 
300  if (params->sideload_key) {
301  reg_control = bitfield_field32_write(
302  reg_control, KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_FIELD,
303  KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_HW_OUTPUT);
304  } else {
305  reg_control = bitfield_field32_write(
306  reg_control, KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_FIELD,
307  KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_SW_OUTPUT);
308  }
309  mmio_region_write32_shadowed(keymgr_dpe->base_addr,
310  KEYMGR_DPE_CONTROL_SHADOWED_REG_OFFSET,
311  reg_control);
312 
313  // Write SALT and VERSION.
315  KEYMGR_DPE_SALT_0_REG_OFFSET, params->salt,
316  sizeof(params->salt));
317  mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_KEY_VERSION_REG_OFFSET,
318  params->version);
319 
320  // Start the operation
321  mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_START_REG_OFFSET,
322  1 << KEYMGR_DPE_START_EN_BIT);
323 
324  return kDifOk;
325 }
326 
328  dif_keymgr_dpe_output_t *output) {
329  if (keymgr_dpe == NULL || output == NULL) {
330  return kDifBadArg;
331  }
332 
334  KEYMGR_DPE_SW_SHARE0_OUTPUT_0_REG_OFFSET,
335  output->value[0], sizeof(output->value[0]));
337  KEYMGR_DPE_SW_SHARE1_OUTPUT_0_REG_OFFSET,
338  output->value[1], sizeof(output->value[1]));
339 
340  return kDifOk;
341 }
342 
344  const dif_keymgr_dpe_t *keymgr_dpe,
345  dif_keymgr_dpe_status_codes_t *status_codes) {
346  if (keymgr_dpe == NULL || status_codes == NULL) {
347  return kDifBadArg;
348  }
349 
350  // Read and clear OP_STATUS register (rw1c).
351  uint32_t reg_op_status = mmio_region_read32(keymgr_dpe->base_addr,
352  KEYMGR_DPE_OP_STATUS_REG_OFFSET);
353 
354  bool is_idle = false;
355  bool has_error = false;
356  switch (reg_op_status) {
357  case KEYMGR_DPE_OP_STATUS_STATUS_VALUE_IDLE:
358  is_idle = true;
359  break;
360  case KEYMGR_DPE_OP_STATUS_STATUS_VALUE_DONE_SUCCESS:
361  is_idle = true;
362  mmio_region_write32(keymgr_dpe->base_addr,
363  KEYMGR_DPE_OP_STATUS_REG_OFFSET, reg_op_status);
364  break;
365  case KEYMGR_DPE_OP_STATUS_STATUS_VALUE_DONE_ERROR:
366  is_idle = true;
367  has_error = true;
368  mmio_region_write32(keymgr_dpe->base_addr,
369  KEYMGR_DPE_OP_STATUS_REG_OFFSET, reg_op_status);
370  break;
371  case KEYMGR_DPE_OP_STATUS_STATUS_VALUE_WIP:
372  break;
373  default:
374  return kDifError;
375  }
376 
377  // `kIdleBitfield` defines the idle field within
378  // `dif_keymgr_dpe_status_codes_t`.
380  0, kIdleBitfield, is_idle);
381 
382  if (has_error) {
383  // Read and clear ERR_CODE register (rw1c).
384  uint32_t reg_err_code = mmio_region_read32(keymgr_dpe->base_addr,
385  KEYMGR_DPE_ERR_CODE_REG_OFFSET);
386  mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_ERR_CODE_REG_OFFSET,
387  reg_err_code);
389  *status_codes, kErrorBitfield, reg_err_code);
390  }
391 
392  return kDifOk;
393 }
394 
396  dif_keymgr_dpe_state_t *state) {
397  if (keymgr_dpe == NULL || state == NULL) {
398  return kDifBadArg;
399  }
400 
401  uint32_t reg_state = mmio_region_read32(keymgr_dpe->base_addr,
402  KEYMGR_DPE_WORKING_STATE_REG_OFFSET);
403 
404  *state =
405  bitfield_field32_read(reg_state, KEYMGR_DPE_WORKING_STATE_STATE_FIELD);
406  return kDifOk;
407 }