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 "hw/top/keymgr_dpe_regs.h" // Generated.
12#include "sw/device/lib/dif/autogen/dif_keymgr_dpe_autogen.h"
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 */
19static_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.");
22static_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.");
25static_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.");
28static_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.");
31static_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.");
34static_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.");
37static_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
41static_assert(KEYMGR_DPE_SALT_1_REG_OFFSET == KEYMGR_DPE_SALT_0_REG_OFFSET + 4,
42 "SALT_N registers must be contiguous.");
43static_assert(KEYMGR_DPE_SALT_2_REG_OFFSET == KEYMGR_DPE_SALT_0_REG_OFFSET + 8,
44 "SALT_N registers must be contiguous.");
45static_assert(KEYMGR_DPE_SALT_3_REG_OFFSET == KEYMGR_DPE_SALT_0_REG_OFFSET + 12,
46 "SALT_N registers must be contiguous.");
47static_assert(KEYMGR_DPE_SALT_4_REG_OFFSET == KEYMGR_DPE_SALT_0_REG_OFFSET + 16,
48 "SALT_N registers must be contiguous.");
49static_assert(KEYMGR_DPE_SALT_5_REG_OFFSET == KEYMGR_DPE_SALT_0_REG_OFFSET + 20,
50 "SALT_N registers must be contiguous.");
51static_assert(KEYMGR_DPE_SALT_6_REG_OFFSET == KEYMGR_DPE_SALT_0_REG_OFFSET + 24,
52 "SALT_N registers must be contiguous.");
53static_assert(KEYMGR_DPE_SALT_7_REG_OFFSET == KEYMGR_DPE_SALT_0_REG_OFFSET + 28,
54 "SALT_N registers must be contiguous.");
55
56static_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.");
59static_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.");
62static_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.");
65static_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.");
68static_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.");
71static_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.");
74static_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
78static_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.");
81static_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.");
84static_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.");
87static_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.");
90static_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.");
93static_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.");
96static_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
100static_assert(KEYMGR_DPE_METADATA_LOW_1_REG_OFFSET ==
101 KEYMGR_DPE_METADATA_LOW_0_REG_OFFSET + 4,
102 "METADATA_LOW_N registers must be contiguous.");
103static_assert(KEYMGR_DPE_METADATA_HIGH_1_REG_OFFSET ==
104 KEYMGR_DPE_METADATA_HIGH_0_REG_OFFSET + 4,
105 "METADATA_HIGH_N registers must be contiguous.");
106static_assert(KEYMGR_DPE_METADATA_LOW_MULTIREG_COUNT ==
107 KEYMGR_DPE_PARAM_NUM_MAX_HW_SLOT,
108 "METADATA_LOW_N register count must match the number of HW "
109 "slots.");
110static_assert(KEYMGR_DPE_METADATA_HIGH_MULTIREG_COUNT ==
111 KEYMGR_DPE_PARAM_NUM_MAX_HW_SLOT,
112 "METADATA_HIGH_N register count must match the number of HW "
113 "slots.");
114
115/**
116 * Error code constants of `dif_keymgr_dpe_status_code_t` are masks for the bits
117 * of ERR_CODE register shifted left by 1.
118 */
119static_assert(kDifKeymgrDpeStatusCodeInvalidOperation >> 1 ==
120 1 << KEYMGR_DPE_ERR_CODE_INVALID_OP_BIT,
121 "Layout of ERR_CODE register changed.");
122static_assert(kDifKeymgrDpeStatusCodeInvalidKmacInput >> 1 ==
123 1 << KEYMGR_DPE_ERR_CODE_INVALID_KMAC_INPUT_BIT,
124 "Layout of ERR_CODE register changed.");
125
126/**
127 * Ensure that enum values for versioned key generation match the parameters
128 * generated by HW.
129 */
130static_assert(kDifKeymgrDpeKeyDestAes ==
131 KEYMGR_DPE_CONTROL_SHADOWED_DEST_SEL_VALUE_AES,
132 "Key destination macros must match the values from its enum.");
133static_assert(kDifKeymgrDpeKeyDestKmac ==
134 KEYMGR_DPE_CONTROL_SHADOWED_DEST_SEL_VALUE_KMAC,
135 "Key destination macros must match the values from its enum.");
136static_assert(kDifKeymgrDpeKeyDestOtbn ==
137 KEYMGR_DPE_CONTROL_SHADOWED_DEST_SEL_VALUE_OTBN,
138 "Key destination macros must match the values from its enum.");
139static_assert(kDifKeymgrDpeKeyDestHmac ==
140 KEYMGR_DPE_CONTROL_SHADOWED_DEST_SEL_VALUE_HMAC,
141 "Key destination macros must match the values from its enum.");
142
143/**
144 * Ensure that SW-visible FSM values match the one defined as SW enum.
145 */
146static_assert(kDifKeymgrDpeStateReset ==
147 KEYMGR_DPE_WORKING_STATE_STATE_VALUE_RESET,
148 "Keymgr_DPE reported FSM state and SW enums must match.");
149static_assert(kDifKeymgrDpeStateAvailable ==
150 KEYMGR_DPE_WORKING_STATE_STATE_VALUE_AVAILABLE,
151 "Keymgr_DPE reported FSM state and SW enums must match.");
152static_assert(kDifKeymgrDpeStateDisabled ==
153 KEYMGR_DPE_WORKING_STATE_STATE_VALUE_DISABLED,
154 "Keymgr_DPE reported FSM state and SW enums must match.");
155static_assert(kDifKeymgrDpeStateInvalid ==
156 KEYMGR_DPE_WORKING_STATE_STATE_VALUE_INVALID,
157 "Keymgr_DPE reported FSM state and SW enums must match.");
158
159/**
160 * Checks if the key manager is ready for a new operation, i.e. it is idle and
161 * the CONFIG register is unlocked.
162 */
164static bool is_ready(const dif_keymgr_dpe_t *keymgr_dpe) {
165 // KeymgrDPE must be idle and the CONTROL register must be writable.
166 uint32_t reg_op_status = mmio_region_read32(keymgr_dpe->base_addr,
167 KEYMGR_DPE_OP_STATUS_REG_OFFSET);
168 if (bitfield_field32_read(reg_op_status, KEYMGR_DPE_OP_STATUS_STATUS_FIELD) !=
169 KEYMGR_DPE_OP_STATUS_STATUS_VALUE_IDLE) {
170 return false;
171 }
172 uint32_t reg_cfg_regwen = mmio_region_read32(
173 keymgr_dpe->base_addr, KEYMGR_DPE_CFG_REGWEN_REG_OFFSET);
174 return bitfield_bit32_read(reg_cfg_regwen, KEYMGR_DPE_CFG_REGWEN_EN_BIT);
175}
176
177dif_result_t dif_keymgr_dpe_initialize(const dif_keymgr_dpe_t *keymgr_dpe,
178 uint32_t slot_dst_sel) {
179 if (keymgr_dpe == NULL) {
180 return kDifBadArg;
181 }
182
183 if (!is_ready(keymgr_dpe)) {
184 return kDifLocked;
185 }
186
187 uint32_t reg_control = bitfield_field32_write(
188 KEYMGR_DPE_CONTROL_SHADOWED_REG_RESVAL,
189 KEYMGR_DPE_CONTROL_SHADOWED_SLOT_DST_SEL_FIELD, slot_dst_sel);
190 reg_control = bitfield_field32_write(
191 reg_control, KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_FIELD,
192 KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_VALUE_ADVANCE);
193 mmio_region_write32_shadowed(keymgr_dpe->base_addr,
194 KEYMGR_DPE_CONTROL_SHADOWED_REG_OFFSET,
195 reg_control);
196
197 mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_START_REG_OFFSET,
198 1 << KEYMGR_DPE_START_EN_BIT);
199
200 return kDifOk;
201}
202
203dif_result_t dif_keymgr_dpe_advance_state(
204 const dif_keymgr_dpe_t *keymgr_dpe,
205 const dif_keymgr_dpe_advance_params_t *params) {
206 if (keymgr_dpe == NULL || params == NULL) {
207 return kDifBadArg;
208 }
209
210 if (!is_ready(keymgr_dpe)) {
211 return kDifLocked;
212 }
213
214 // If either of SLOT_POLICY_REGWEN, MAX_KEY_VER_REGWEN or SW_BINDING_REGWEN is
215 // locked, return error.
216 uint32_t slot_policy_regwen = mmio_region_read32(
217 keymgr_dpe->base_addr, KEYMGR_DPE_SLOT_POLICY_REGWEN_REG_OFFSET);
218 if (!bitfield_bit32_read(slot_policy_regwen,
219 KEYMGR_DPE_SLOT_POLICY_REGWEN_EN_BIT)) {
220 return kDifLocked;
221 }
222
223 uint32_t reg_max_key_ver_wen = mmio_region_read32(
224 keymgr_dpe->base_addr, KEYMGR_DPE_MAX_KEY_VER_REGWEN_REG_OFFSET);
225 if (!bitfield_bit32_read(reg_max_key_ver_wen,
226 KEYMGR_DPE_MAX_KEY_VER_REGWEN_EN_BIT)) {
227 return kDifLocked;
228 }
229
230 uint32_t sw_binding_regwen = mmio_region_read32(
231 keymgr_dpe->base_addr, KEYMGR_DPE_SW_BINDING_REGWEN_REG_OFFSET);
232 if (!bitfield_bit32_read(sw_binding_regwen,
233 KEYMGR_DPE_SW_BINDING_REGWEN_EN_BIT)) {
234 return kDifLocked;
235 }
236
237 // Now that we know REGWEN registers are enabled, we can write each value and
238 // then lock REGWEN registers (rw0c).
239 mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_SLOT_POLICY_REG_OFFSET,
240 params->slot_policy);
241 mmio_region_write32(keymgr_dpe->base_addr,
242 KEYMGR_DPE_SLOT_POLICY_REGWEN_REG_OFFSET, 0);
243
244 mmio_region_write32_shadowed(keymgr_dpe->base_addr,
245 KEYMGR_DPE_MAX_KEY_VER_SHADOWED_REG_OFFSET,
246 params->max_key_version);
247 mmio_region_write32(keymgr_dpe->base_addr,
248 KEYMGR_DPE_MAX_KEY_VER_REGWEN_REG_OFFSET, 0);
249
250 mmio_region_memcpy_to_mmio32(
251 keymgr_dpe->base_addr, KEYMGR_DPE_SW_BINDING_0_REG_OFFSET,
252 params->binding_value, sizeof(params->binding_value));
253 mmio_region_write32(keymgr_dpe->base_addr,
254 KEYMGR_DPE_SW_BINDING_REGWEN_REG_OFFSET, 0);
255
256 uint32_t reg_control = bitfield_field32_write(
257 KEYMGR_DPE_CONTROL_SHADOWED_REG_RESVAL,
258 KEYMGR_DPE_CONTROL_SHADOWED_SLOT_SRC_SEL_FIELD, params->slot_src_sel);
259 reg_control = bitfield_field32_write(
260 reg_control, KEYMGR_DPE_CONTROL_SHADOWED_SLOT_DST_SEL_FIELD,
261 params->slot_dst_sel);
262 reg_control = bitfield_field32_write(
263 reg_control, KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_FIELD,
264 KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_VALUE_ADVANCE);
265 mmio_region_write32_shadowed(keymgr_dpe->base_addr,
266 KEYMGR_DPE_CONTROL_SHADOWED_REG_OFFSET,
267 reg_control);
268 mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_START_REG_OFFSET,
269 1 << KEYMGR_DPE_START_EN_BIT);
270
271 return kDifOk;
272}
273
274dif_result_t dif_keymgr_dpe_erase_slot(
275 const dif_keymgr_dpe_t *keymgr_dpe,
276 const dif_keymgr_dpe_erase_params_t *params) {
277 if (keymgr_dpe == NULL) {
278 return kDifBadArg;
279 }
280
281 if (!is_ready(keymgr_dpe)) {
282 return kDifLocked;
283 }
284
285 uint32_t reg_control = bitfield_field32_write(
286 KEYMGR_DPE_CONTROL_SHADOWED_REG_RESVAL,
287 KEYMGR_DPE_CONTROL_SHADOWED_SLOT_DST_SEL_FIELD, params->slot_dst_sel);
288 reg_control = bitfield_field32_write(
289 reg_control, KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_FIELD,
290 KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_VALUE_ERASE_SLOT);
291 mmio_region_write32_shadowed(keymgr_dpe->base_addr,
292 KEYMGR_DPE_CONTROL_SHADOWED_REG_OFFSET,
293 reg_control);
294 mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_START_REG_OFFSET,
295 1 << KEYMGR_DPE_START_EN_BIT);
296
297 return kDifOk;
298}
299
300dif_result_t dif_keymgr_dpe_get_metadata(const dif_keymgr_dpe_t *keymgr_dpe,
301 uint32_t slot,
302 dif_keymgr_dpe_metadata_t *metadata) {
303 if (keymgr_dpe == NULL || metadata == NULL ||
304 slot >= KEYMGR_DPE_PARAM_NUM_MAX_HW_SLOT) {
305 return kDifBadArg;
306 }
307
308 metadata->max_key_version = mmio_region_read32(
309 keymgr_dpe->base_addr, (ptrdiff_t)(KEYMGR_DPE_METADATA_LOW_0_REG_OFFSET +
310 slot * sizeof(uint32_t)));
311
312 uint32_t reg_high = mmio_region_read32(
313 keymgr_dpe->base_addr, (ptrdiff_t)(KEYMGR_DPE_METADATA_HIGH_0_REG_OFFSET +
314 slot * sizeof(uint32_t)));
315 metadata->valid =
316 bitfield_bit32_read(reg_high, KEYMGR_DPE_METADATA_HIGH_0_VALID_0_BIT);
317 metadata->boot_stage = bitfield_field32_read(
318 reg_high, KEYMGR_DPE_METADATA_HIGH_0_BOOT_STAGE_0_FIELD);
319
320 uint32_t slot_policy = 0;
321 slot_policy = bitfield_bit32_write(
322 slot_policy, KEYMGR_DPE_SLOT_POLICY_ALLOW_CHILD_BIT,
323 bitfield_bit32_read(reg_high,
324 KEYMGR_DPE_METADATA_HIGH_0_ALLOW_CHILD_POLICY_0_BIT));
325 slot_policy = bitfield_bit32_write(
326 slot_policy, KEYMGR_DPE_SLOT_POLICY_EXPORTABLE_BIT,
327 bitfield_bit32_read(reg_high,
328 KEYMGR_DPE_METADATA_HIGH_0_EXPORTABLE_POLICY_0_BIT));
329 slot_policy = bitfield_bit32_write(
330 slot_policy, KEYMGR_DPE_SLOT_POLICY_RETAIN_PARENT_BIT,
331 bitfield_bit32_read(
332 reg_high, KEYMGR_DPE_METADATA_HIGH_0_RETAIN_PARENT_POLICY_0_BIT));
333 slot_policy = bitfield_bit32_write(
334 slot_policy, KEYMGR_DPE_SLOT_POLICY_ALLOW_KEYGEN_BIT,
335 bitfield_bit32_read(
336 reg_high, KEYMGR_DPE_METADATA_HIGH_0_ALLOW_KEYGEN_POLICY_0_BIT));
337 metadata->slot_policy = slot_policy;
338
339 return kDifOk;
340}
341
342dif_result_t dif_keymgr_dpe_disable(const dif_keymgr_dpe_t *keymgr_dpe) {
343 if (keymgr_dpe == NULL) {
344 return kDifBadArg;
345 }
346
347 if (!is_ready(keymgr_dpe)) {
348 return kDifLocked;
349 }
350
351 uint32_t reg_control = bitfield_field32_write(
352 KEYMGR_DPE_CONTROL_SHADOWED_REG_RESVAL,
353 KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_FIELD,
354 KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_VALUE_DISABLE);
355 mmio_region_write32_shadowed(keymgr_dpe->base_addr,
356 KEYMGR_DPE_CONTROL_SHADOWED_REG_OFFSET,
357 reg_control);
358 mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_START_REG_OFFSET,
359 1 << KEYMGR_DPE_START_EN_BIT);
360
361 return kDifOk;
362}
363
364dif_result_t dif_keymgr_dpe_generate(
365 const dif_keymgr_dpe_t *keymgr_dpe,
366 const dif_keymgr_dpe_generate_params_t *params) {
367 if (keymgr_dpe == NULL || params == NULL) {
368 return kDifBadArg;
369 }
370
371 if (!is_ready(keymgr_dpe)) {
372 return kDifLocked;
373 }
374
375 uint32_t reg_control = bitfield_field32_write(
376 KEYMGR_DPE_CONTROL_SHADOWED_REG_RESVAL,
377 KEYMGR_DPE_CONTROL_SHADOWED_DEST_SEL_FIELD, params->key_dest);
378 reg_control = bitfield_field32_write(
379 reg_control, KEYMGR_DPE_CONTROL_SHADOWED_SLOT_SRC_SEL_FIELD,
380 params->slot_src_sel);
381
382 if (params->sideload_key) {
383 reg_control = bitfield_field32_write(
384 reg_control, KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_FIELD,
385 KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_HW_OUTPUT);
386 } else {
387 reg_control = bitfield_field32_write(
388 reg_control, KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_FIELD,
389 KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_SW_OUTPUT);
390 }
391 mmio_region_write32_shadowed(keymgr_dpe->base_addr,
392 KEYMGR_DPE_CONTROL_SHADOWED_REG_OFFSET,
393 reg_control);
394
395 // Write SALT and VERSION.
396 mmio_region_memcpy_to_mmio32(keymgr_dpe->base_addr,
397 KEYMGR_DPE_SALT_0_REG_OFFSET, params->salt,
398 sizeof(params->salt));
399 mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_KEY_VERSION_REG_OFFSET,
400 params->version);
401
402 // Start the operation
403 mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_START_REG_OFFSET,
404 1 << KEYMGR_DPE_START_EN_BIT);
405
406 return kDifOk;
407}
408
409dif_result_t dif_keymgr_dpe_read_output(const dif_keymgr_dpe_t *keymgr_dpe,
410 dif_keymgr_dpe_output_t *output) {
411 if (keymgr_dpe == NULL || output == NULL) {
412 return kDifBadArg;
413 }
414
415 mmio_region_memcpy_from_mmio32(keymgr_dpe->base_addr,
416 KEYMGR_DPE_SW_SHARE0_OUTPUT_0_REG_OFFSET,
417 output->value[0], sizeof(output->value[0]));
418 mmio_region_memcpy_from_mmio32(keymgr_dpe->base_addr,
419 KEYMGR_DPE_SW_SHARE1_OUTPUT_0_REG_OFFSET,
420 output->value[1], sizeof(output->value[1]));
421
422 return kDifOk;
423}
424
425dif_result_t dif_keymgr_dpe_get_status_codes(
426 const dif_keymgr_dpe_t *keymgr_dpe,
427 dif_keymgr_dpe_status_codes_t *status_codes) {
428 if (keymgr_dpe == NULL || status_codes == NULL) {
429 return kDifBadArg;
430 }
431
432 // Read and clear OP_STATUS register (rw1c).
433 uint32_t reg_op_status = mmio_region_read32(keymgr_dpe->base_addr,
434 KEYMGR_DPE_OP_STATUS_REG_OFFSET);
435
436 bool is_idle = false;
437 bool has_error = false;
438 switch (reg_op_status) {
439 case KEYMGR_DPE_OP_STATUS_STATUS_VALUE_IDLE:
440 is_idle = true;
441 break;
442 case KEYMGR_DPE_OP_STATUS_STATUS_VALUE_DONE_SUCCESS:
443 is_idle = true;
444 mmio_region_write32(keymgr_dpe->base_addr,
445 KEYMGR_DPE_OP_STATUS_REG_OFFSET, reg_op_status);
446 break;
447 case KEYMGR_DPE_OP_STATUS_STATUS_VALUE_DONE_ERROR:
448 is_idle = true;
449 has_error = true;
450 mmio_region_write32(keymgr_dpe->base_addr,
451 KEYMGR_DPE_OP_STATUS_REG_OFFSET, reg_op_status);
452 break;
453 case KEYMGR_DPE_OP_STATUS_STATUS_VALUE_WIP:
454 break;
455 default:
456 return kDifError;
457 }
458
459 // `kIdleBitfield` defines the idle field within
460 // `dif_keymgr_dpe_status_codes_t`.
461 *status_codes = (dif_keymgr_dpe_status_codes_t)bitfield_field32_write(
462 0, kIdleBitfield, is_idle);
463
464 if (has_error) {
465 // Read and clear ERR_CODE register (rw1c).
466 uint32_t reg_err_code = mmio_region_read32(keymgr_dpe->base_addr,
467 KEYMGR_DPE_ERR_CODE_REG_OFFSET);
468 mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_ERR_CODE_REG_OFFSET,
469 reg_err_code);
470 *status_codes = (dif_keymgr_dpe_status_codes_t)bitfield_field32_write(
471 *status_codes, kErrorBitfield, reg_err_code);
472 }
473
474 return kDifOk;
475}
476
477dif_result_t dif_keymgr_dpe_get_state(const dif_keymgr_dpe_t *keymgr_dpe,
478 dif_keymgr_dpe_state_t *state) {
479 if (keymgr_dpe == NULL || state == NULL) {
480 return kDifBadArg;
481 }
482
483 uint32_t reg_state = mmio_region_read32(keymgr_dpe->base_addr,
484 KEYMGR_DPE_WORKING_STATE_REG_OFFSET);
485
486 *state =
487 bitfield_field32_read(reg_state, KEYMGR_DPE_WORKING_STATE_STATE_FIELD);
488 return kDifOk;
489}
490
491dif_result_t dif_keymgr_dpe_clear_sideload_key(
492 const dif_keymgr_dpe_t *keymgr_dpe,
494 if (keymgr_dpe == NULL) {
495 return kDifBadArg;
496 }
497
498 mmio_region_write32(keymgr_dpe->base_addr,
499 KEYMGR_DPE_SIDELOAD_CLEAR_REG_OFFSET, clear_dest);
500
501 return kDifOk;
502}
503
504dif_result_t dif_keymgr_dpe_configure(const dif_keymgr_dpe_t *keymgr_dpe,
506 if (keymgr_dpe == NULL) {
507 return kDifBadArg;
508 }
509
510 // Verify if the register is unlocked
511 uint32_t reseed_regwen = mmio_region_read32(
512 keymgr_dpe->base_addr, KEYMGR_DPE_RESEED_INTERVAL_REGWEN_REG_OFFSET);
513 if (!bitfield_bit32_read(reseed_regwen,
514 KEYMGR_DPE_RESEED_INTERVAL_REGWEN_EN_BIT)) {
515 return kDifLocked;
516 }
517
518 uint32_t reg_val =
519 bitfield_field32_write(0, KEYMGR_DPE_RESEED_INTERVAL_SHADOWED_VAL_FIELD,
521 mmio_region_write32_shadowed(keymgr_dpe->base_addr,
522 KEYMGR_DPE_RESEED_INTERVAL_SHADOWED_REG_OFFSET,
523 reg_val);
524
525 return kDifOk;
526}