Software APIs
dif_keymgr.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_regs.h" // Generated.
13
14/**
15 * Make sure dif_keymgr_sideload_clr_t enum is in sync with autogenarated
16 * values.
17 */
18OT_ASSERT_ENUM_VALUE(kDifKeyMgrSideLoadClearNone,
19 KEYMGR_SIDELOAD_CLEAR_VAL_VALUE_NONE);
20OT_ASSERT_ENUM_VALUE(kDifKeyMgrSideLoadClearAes,
21 KEYMGR_SIDELOAD_CLEAR_VAL_VALUE_AES);
22OT_ASSERT_ENUM_VALUE(kDifKeyMgrSideLoadClearKmac,
23 KEYMGR_SIDELOAD_CLEAR_VAL_VALUE_KMAC);
24OT_ASSERT_ENUM_VALUE(kDifKeyMgrSideLoadClearOtbn,
25 KEYMGR_SIDELOAD_CLEAR_VAL_VALUE_OTBN);
26OT_ASSERT_ENUM_VALUE(kDifKeyMgrSideLoadClearAll,
27 KEYMGR_SIDELOAD_CLEAR_VAL_MASK);
28
29/**
30 * Address spaces of SEALING_SW_BINDING_N, SALT_N, SW_SHARE0_OUTPUT_N, and
31 * SW_SHARE1_OUTPUT_N registers must be contiguous to be able to use
32 * `mmio_region_memcpy_to/from_mmio32()`.
33 */
34static_assert(KEYMGR_SEALING_SW_BINDING_1_REG_OFFSET ==
35 KEYMGR_SEALING_SW_BINDING_0_REG_OFFSET + 4,
36 "SEALING_SW_BINDING_N registers must be contiguous.");
37static_assert(KEYMGR_SEALING_SW_BINDING_2_REG_OFFSET ==
38 KEYMGR_SEALING_SW_BINDING_0_REG_OFFSET + 8,
39 "SEALING_SW_BINDING_N registers must be contiguous.");
40static_assert(KEYMGR_SEALING_SW_BINDING_3_REG_OFFSET ==
41 KEYMGR_SEALING_SW_BINDING_0_REG_OFFSET + 12,
42 "SEALING_SW_BINDING_N registers must be contiguous.");
43static_assert(KEYMGR_SEALING_SW_BINDING_4_REG_OFFSET ==
44 KEYMGR_SEALING_SW_BINDING_0_REG_OFFSET + 16,
45 "SEALING_SW_BINDING_N registers must be contiguous.");
46static_assert(KEYMGR_SEALING_SW_BINDING_5_REG_OFFSET ==
47 KEYMGR_SEALING_SW_BINDING_0_REG_OFFSET + 20,
48 "SEALING_SW_BINDING_N registers must be contiguous.");
49static_assert(KEYMGR_SEALING_SW_BINDING_6_REG_OFFSET ==
50 KEYMGR_SEALING_SW_BINDING_0_REG_OFFSET + 24,
51 "SEALING_SW_BINDING_N registers must be contiguous.");
52static_assert(KEYMGR_SEALING_SW_BINDING_7_REG_OFFSET ==
53 KEYMGR_SEALING_SW_BINDING_0_REG_OFFSET + 28,
54 "SEALING_SW_BINDING_N registers must be contiguous.");
55
56static_assert(KEYMGR_SALT_1_REG_OFFSET == KEYMGR_SALT_0_REG_OFFSET + 4,
57 "SALT_N registers must be contiguous.");
58static_assert(KEYMGR_SALT_2_REG_OFFSET == KEYMGR_SALT_0_REG_OFFSET + 8,
59 "SALT_N registers must be contiguous.");
60static_assert(KEYMGR_SALT_3_REG_OFFSET == KEYMGR_SALT_0_REG_OFFSET + 12,
61 "SALT_N registers must be contiguous.");
62static_assert(KEYMGR_SALT_4_REG_OFFSET == KEYMGR_SALT_0_REG_OFFSET + 16,
63 "SALT_N registers must be contiguous.");
64static_assert(KEYMGR_SALT_5_REG_OFFSET == KEYMGR_SALT_0_REG_OFFSET + 20,
65 "SALT_N registers must be contiguous.");
66static_assert(KEYMGR_SALT_6_REG_OFFSET == KEYMGR_SALT_0_REG_OFFSET + 24,
67 "SALT_N registers must be contiguous.");
68static_assert(KEYMGR_SALT_7_REG_OFFSET == KEYMGR_SALT_0_REG_OFFSET + 28,
69 "SALT_N registers must be contiguous.");
70
71static_assert(KEYMGR_SW_SHARE0_OUTPUT_1_REG_OFFSET ==
72 KEYMGR_SW_SHARE0_OUTPUT_0_REG_OFFSET + 4,
73 "SW_SHARE0_OUTPUT_N registers must be contiguous.");
74static_assert(KEYMGR_SW_SHARE0_OUTPUT_2_REG_OFFSET ==
75 KEYMGR_SW_SHARE0_OUTPUT_0_REG_OFFSET + 8,
76 "SW_SHARE0_OUTPUT_N registers must be contiguous.");
77static_assert(KEYMGR_SW_SHARE0_OUTPUT_3_REG_OFFSET ==
78 KEYMGR_SW_SHARE0_OUTPUT_0_REG_OFFSET + 12,
79 "SW_SHARE0_OUTPUT_N registers must be contiguous.");
80static_assert(KEYMGR_SW_SHARE0_OUTPUT_4_REG_OFFSET ==
81 KEYMGR_SW_SHARE0_OUTPUT_0_REG_OFFSET + 16,
82 "SW_SHARE0_OUTPUT_N registers must be contiguous.");
83static_assert(KEYMGR_SW_SHARE0_OUTPUT_5_REG_OFFSET ==
84 KEYMGR_SW_SHARE0_OUTPUT_0_REG_OFFSET + 20,
85 "SW_SHARE0_OUTPUT_N registers must be contiguous.");
86static_assert(KEYMGR_SW_SHARE0_OUTPUT_6_REG_OFFSET ==
87 KEYMGR_SW_SHARE0_OUTPUT_0_REG_OFFSET + 24,
88 "SW_SHARE0_OUTPUT_N registers must be contiguous.");
89static_assert(KEYMGR_SW_SHARE0_OUTPUT_7_REG_OFFSET ==
90 KEYMGR_SW_SHARE0_OUTPUT_0_REG_OFFSET + 28,
91 "SW_SHARE0_OUTPUT_N registers must be contiguous.");
92
93static_assert(KEYMGR_SW_SHARE1_OUTPUT_1_REG_OFFSET ==
94 KEYMGR_SW_SHARE1_OUTPUT_0_REG_OFFSET + 4,
95 "SW_SHARE1_OUTPUT_N registers must be contiguous.");
96static_assert(KEYMGR_SW_SHARE1_OUTPUT_2_REG_OFFSET ==
97 KEYMGR_SW_SHARE1_OUTPUT_0_REG_OFFSET + 8,
98 "SW_SHARE1_OUTPUT_N registers must be contiguous.");
99static_assert(KEYMGR_SW_SHARE1_OUTPUT_3_REG_OFFSET ==
100 KEYMGR_SW_SHARE1_OUTPUT_0_REG_OFFSET + 12,
101 "SW_SHARE1_OUTPUT_N registers must be contiguous.");
102static_assert(KEYMGR_SW_SHARE1_OUTPUT_4_REG_OFFSET ==
103 KEYMGR_SW_SHARE1_OUTPUT_0_REG_OFFSET + 16,
104 "SW_SHARE1_OUTPUT_N registers must be contiguous.");
105static_assert(KEYMGR_SW_SHARE1_OUTPUT_5_REG_OFFSET ==
106 KEYMGR_SW_SHARE1_OUTPUT_0_REG_OFFSET + 20,
107 "SW_SHARE1_OUTPUT_N registers must be contiguous.");
108static_assert(KEYMGR_SW_SHARE1_OUTPUT_6_REG_OFFSET ==
109 KEYMGR_SW_SHARE1_OUTPUT_0_REG_OFFSET + 24,
110 "SW_SHARE1_OUTPUT_N registers must be contiguous.");
111static_assert(KEYMGR_SW_SHARE1_OUTPUT_7_REG_OFFSET ==
112 KEYMGR_SW_SHARE1_OUTPUT_0_REG_OFFSET + 28,
113 "SW_SHARE1_OUTPUT_N registers must be contiguous.");
114
115/**
116 * Error code constants of `dif_keymgr_status_code_t` are masks for the bits of
117 * ERR_CODE register shifted left by 1.
118 */
119static_assert(kDifKeymgrStatusCodeInvalidOperation >> 1 ==
120 1 << KEYMGR_ERR_CODE_INVALID_OP_BIT,
121 "Layout of ERR_CODE register changed.");
122static_assert(kDifKeymgrStatusCodeInvalidKmacInput >> 1 ==
123 1 << KEYMGR_ERR_CODE_INVALID_KMAC_INPUT_BIT,
124 "Layout of ERR_CODE register changed.");
125
126/**
127 * Checks if the key manager is ready for a new operation, i.e. it is idle and
128 * the CONFIG register is unlocked.
129 */
131static bool is_ready(const dif_keymgr_t *keymgr) {
132 // Keymgr must be idle and the CONTROL register must be writable.
133 uint32_t reg_op_status =
134 mmio_region_read32(keymgr->base_addr, KEYMGR_OP_STATUS_REG_OFFSET);
135 if (bitfield_field32_read(reg_op_status, KEYMGR_OP_STATUS_STATUS_FIELD) !=
136 KEYMGR_OP_STATUS_STATUS_VALUE_IDLE) {
137 return false;
138 }
139 uint32_t reg_cfg_regwen =
140 mmio_region_read32(keymgr->base_addr, KEYMGR_CFG_REGWEN_REG_OFFSET);
141 return bitfield_bit32_read(reg_cfg_regwen, KEYMGR_CFG_REGWEN_EN_BIT);
142}
143
144/**
145 * Max key version register information for a state transition.
146 */
148 /**
149 * Whether max key version must be set for this transition or not.
150 */
152 /**
153 * Max key version register offset to use.
154 */
155 uint32_t reg_offset;
156 /**
157 * Write-enable register offset to use.
158 */
160 /**
161 * Write-enable bit index.
162 */
164} max_key_version_reg_info_t;
165
166/**
167 * Returns max key version register information for transitioning from a state.
168 */
170static bool get_max_key_version_reg_info_for_next_state(
171 uint32_t cur_state, max_key_version_reg_info_t *reg_info) {
172 switch (cur_state) {
173 case KEYMGR_WORKING_STATE_STATE_VALUE_INIT:
174 *reg_info = (max_key_version_reg_info_t){
175 .is_required = true,
176 .reg_offset = KEYMGR_MAX_CREATOR_KEY_VER_SHADOWED_REG_OFFSET,
177 .wen_reg_offset = KEYMGR_MAX_CREATOR_KEY_VER_REGWEN_REG_OFFSET,
178 .wen_bit_index = KEYMGR_MAX_CREATOR_KEY_VER_REGWEN_EN_BIT,
179 };
180 return true;
181 case KEYMGR_WORKING_STATE_STATE_VALUE_CREATOR_ROOT_KEY:
182 *reg_info = (max_key_version_reg_info_t){
183 .is_required = true,
184 .reg_offset = KEYMGR_MAX_OWNER_INT_KEY_VER_SHADOWED_REG_OFFSET,
185 .wen_reg_offset = KEYMGR_MAX_OWNER_INT_KEY_VER_REGWEN_REG_OFFSET,
186 .wen_bit_index = KEYMGR_MAX_OWNER_INT_KEY_VER_REGWEN_EN_BIT,
187 };
188 return true;
189 case KEYMGR_WORKING_STATE_STATE_VALUE_OWNER_INTERMEDIATE_KEY:
190 *reg_info = (max_key_version_reg_info_t){
191 .is_required = true,
192 .reg_offset = KEYMGR_MAX_OWNER_KEY_VER_SHADOWED_REG_OFFSET,
193 .wen_reg_offset = KEYMGR_MAX_OWNER_KEY_VER_REGWEN_REG_OFFSET,
194 .wen_bit_index = KEYMGR_MAX_OWNER_KEY_VER_REGWEN_EN_BIT,
195 };
196 return true;
197 case KEYMGR_WORKING_STATE_STATE_VALUE_RESET:
198 case KEYMGR_WORKING_STATE_STATE_VALUE_OWNER_KEY:
199 case KEYMGR_WORKING_STATE_STATE_VALUE_DISABLED:
200 case KEYMGR_WORKING_STATE_STATE_VALUE_INVALID:
201 *reg_info = (max_key_version_reg_info_t){
202 .is_required = false,
203 };
204 return true;
205 default:
206 return false;
207 }
208}
209
210/**
211 * Parameters for starting a key manager operation.
212 *
213 * Values of the members must be the actual values that will be written to the
214 * CONTROL register.
215 */
217 /**
218 * Destination for this operation.
219 */
220 uint32_t dest;
221 /**
222 * Operation to start.
223 */
224 uint32_t op;
225 /**
226 * Compound Device Identifier type (sealing or attestation).
227 *
228 * Only relevant for the creation of identities, software and sideload keys,
229 * otherwise the key manager operations are identical for both types.
230 */
232} start_operation_params_t;
233
234/**
235 * Starts a key manager operation.
236 */
237static void start_operation(const dif_keymgr_t *keymgr,
238 start_operation_params_t params) {
239 uint32_t reg_control = bitfield_field32_write(
240 0, KEYMGR_CONTROL_SHADOWED_DEST_SEL_FIELD, params.dest);
241 reg_control = bitfield_field32_write(
242 reg_control, KEYMGR_CONTROL_SHADOWED_OPERATION_FIELD, params.op);
243 reg_control = bitfield_field32_write(
244 reg_control,
245 (bitfield_field32_t){.mask = 0x1u,
246 .index = KEYMGR_CONTROL_SHADOWED_CDI_SEL_BIT},
247 params.cdi_type);
248 mmio_region_write32_shadowed(keymgr->base_addr,
249 KEYMGR_CONTROL_SHADOWED_REG_OFFSET, reg_control);
250 mmio_region_write32(keymgr->base_addr, KEYMGR_START_REG_OFFSET,
251 1 << KEYMGR_START_EN_BIT);
252}
253
254dif_result_t dif_keymgr_configure(const dif_keymgr_t *keymgr,
255 dif_keymgr_config_t config) {
256 if (keymgr == NULL) {
257 return kDifBadArg;
258 }
259
260 uint32_t reg_val =
261 bitfield_field32_write(0, KEYMGR_RESEED_INTERVAL_SHADOWED_VAL_FIELD,
263 mmio_region_write32_shadowed(
264 keymgr->base_addr, KEYMGR_RESEED_INTERVAL_SHADOWED_REG_OFFSET, reg_val);
265
266 return kDifOk;
267}
268
269dif_result_t dif_keymgr_advance_state(const dif_keymgr_t *keymgr,
270 const dif_keymgr_state_params_t *params) {
271 if (keymgr == NULL) {
272 return kDifBadArg;
273 }
274
275 if (!is_ready(keymgr)) {
276 return kDifLocked;
277 }
278
279 // Get current state and determine if we need to set the max key version and
280 // sw binding value.
281 max_key_version_reg_info_t max_key_ver_reg_info;
282 uint32_t reg_working_state =
283 mmio_region_read32(keymgr->base_addr, KEYMGR_WORKING_STATE_REG_OFFSET);
284 if (!get_max_key_version_reg_info_for_next_state(
285 (bitfield_field32_read(reg_working_state,
286 KEYMGR_WORKING_STATE_STATE_FIELD)),
287 &max_key_ver_reg_info)) {
288 return kDifError;
289 }
290
291 // Set the binding value and max key version if keymgr is going to
292 // transition to an operational state.
293 if (max_key_ver_reg_info.is_required) {
294 if (params == NULL) {
295 return kDifBadArg;
296 }
297
298 // Check if SEALING_SW_BINDING_N registers are locked
299 uint32_t reg_sw_binding_wen = mmio_region_read32(
300 keymgr->base_addr, KEYMGR_SW_BINDING_REGWEN_REG_OFFSET);
301 if (!bitfield_bit32_read(reg_sw_binding_wen,
302 KEYMGR_SW_BINDING_REGWEN_EN_BIT)) {
303 return kDifLocked;
304 }
305
306 // Check if MAX_*_KEY_VER register is locked.
307 uint32_t reg_max_key_ver_wen = mmio_region_read32(
308 keymgr->base_addr, (ptrdiff_t)max_key_ver_reg_info.wen_reg_offset);
309 if (!bitfield_bit32_read(reg_max_key_ver_wen,
310 max_key_ver_reg_info.wen_bit_index)) {
311 return kDifLocked;
312 }
313
314 // Write and lock (rw0c) the software binding value. This register is
315 // unlocked by hardware upon a successful state transition.
316 mmio_region_memcpy_to_mmio32(
317 keymgr->base_addr, KEYMGR_SEALING_SW_BINDING_0_REG_OFFSET,
318 params->binding_value, sizeof(params->binding_value));
319 mmio_region_write32(keymgr->base_addr, KEYMGR_SW_BINDING_REGWEN_REG_OFFSET,
320 0);
321
322 // Write and lock (rw0c) the max key version.
323 mmio_region_write32_shadowed(keymgr->base_addr,
324 (ptrdiff_t)max_key_ver_reg_info.reg_offset,
325 params->max_key_version);
326 mmio_region_write32(keymgr->base_addr,
327 (ptrdiff_t)max_key_ver_reg_info.wen_reg_offset, 0);
328 } else if (params != NULL) {
329 return kDifBadArg;
330 }
331
332 // Advance state.
333 start_operation(keymgr,
334 (start_operation_params_t){
335 .dest = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_NONE,
336 .op = KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_ADVANCE,
337 });
338
339 return kDifOk;
340}
341
342dif_result_t dif_keymgr_advance_state_raw(const dif_keymgr_t *keymgr) {
343 if (keymgr == NULL) {
344 return kDifBadArg;
345 }
346
347 if (!is_ready(keymgr)) {
348 return kDifLocked;
349 }
350
351 // Advance state.
352 start_operation(keymgr,
353 (start_operation_params_t){
354 .dest = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_NONE,
355 .op = KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_ADVANCE,
356 });
357
358 return kDifOk;
359}
360
361dif_result_t dif_keymgr_disable(const dif_keymgr_t *keymgr) {
362 if (keymgr == NULL) {
363 return kDifBadArg;
364 }
365
366 if (!is_ready(keymgr)) {
367 return kDifLocked;
368 }
369
370 // Disable key manager.
371 start_operation(keymgr,
372 (start_operation_params_t){
373 .dest = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_NONE,
374 .op = KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_DISABLE,
375 });
376
377 return kDifOk;
378}
379
380dif_result_t dif_keymgr_get_status_codes(
381 const dif_keymgr_t *keymgr, dif_keymgr_status_codes_t *status_codes) {
382 if (keymgr == NULL || status_codes == NULL) {
383 return kDifBadArg;
384 }
385
386 // Read and clear OP_STATUS register (rw1c).
387 uint32_t reg_op_status =
388 mmio_region_read32(keymgr->base_addr, KEYMGR_OP_STATUS_REG_OFFSET);
389
390 bool is_idle = false;
391 bool has_error = false;
392 switch (reg_op_status) {
393 case KEYMGR_OP_STATUS_STATUS_VALUE_IDLE:
394 is_idle = true;
395 break;
396 case KEYMGR_OP_STATUS_STATUS_VALUE_DONE_SUCCESS:
397 is_idle = true;
398 mmio_region_write32(keymgr->base_addr, KEYMGR_OP_STATUS_REG_OFFSET,
399 reg_op_status);
400 break;
401 case KEYMGR_OP_STATUS_STATUS_VALUE_DONE_ERROR:
402 is_idle = true;
403 has_error = true;
404 mmio_region_write32(keymgr->base_addr, KEYMGR_OP_STATUS_REG_OFFSET,
405 reg_op_status);
406 break;
407 case KEYMGR_OP_STATUS_STATUS_VALUE_WIP:
408 break;
409 default:
410 return kDifError;
411 }
412
413 // Bit 0 of `dif_keymgr_status_codes_t` indicates whether the key manager is
414 // idle or not.
415 *status_codes =
416 (dif_keymgr_status_codes_t)bitfield_bit32_write(0, 0, is_idle);
417
418 if (has_error) {
419 // Read and clear ERR_CODE register (rw1c).
420 uint32_t reg_err_code =
421 mmio_region_read32(keymgr->base_addr, KEYMGR_ERR_CODE_REG_OFFSET);
422 mmio_region_write32(keymgr->base_addr, KEYMGR_ERR_CODE_REG_OFFSET,
423 reg_err_code);
424 // Error bits start from bit 1 in `dif_keymgr_status_codes_t`.
425 // Note: The mask is hardcoded since it is not auto generated yet.
426 const bitfield_field32_t kErrorBitfield = (bitfield_field32_t){
427 .mask = 0xF,
428 .index = 1,
429 };
430 if (reg_err_code > kErrorBitfield.mask || reg_err_code == 0) {
431 return kDifError;
432 }
433 *status_codes = (dif_keymgr_status_codes_t)bitfield_field32_write(
434 *status_codes, kErrorBitfield, reg_err_code);
435 }
436
437 return kDifOk;
438}
439
440dif_result_t dif_keymgr_get_state(const dif_keymgr_t *keymgr,
441 dif_keymgr_state_t *state) {
442 if (keymgr == NULL || state == NULL) {
443 return kDifBadArg;
444 }
445
446 uint32_t reg_state =
447 mmio_region_read32(keymgr->base_addr, KEYMGR_WORKING_STATE_REG_OFFSET);
448
449 switch (bitfield_field32_read(reg_state, KEYMGR_WORKING_STATE_STATE_FIELD)) {
450 case KEYMGR_WORKING_STATE_STATE_VALUE_RESET:
451 *state = kDifKeymgrStateReset;
452 return kDifOk;
453 case KEYMGR_WORKING_STATE_STATE_VALUE_INIT:
455 return kDifOk;
456 case KEYMGR_WORKING_STATE_STATE_VALUE_CREATOR_ROOT_KEY:
458 return kDifOk;
459 case KEYMGR_WORKING_STATE_STATE_VALUE_OWNER_INTERMEDIATE_KEY:
461 return kDifOk;
462 case KEYMGR_WORKING_STATE_STATE_VALUE_OWNER_KEY:
464 return kDifOk;
465 case KEYMGR_WORKING_STATE_STATE_VALUE_DISABLED:
467 return kDifOk;
468 case KEYMGR_WORKING_STATE_STATE_VALUE_INVALID:
469 *state = kDifKeymgrStateInvalid;
470 return kDifOk;
471 default:
472 return kDifError;
473 }
474}
475
476dif_result_t dif_keymgr_generate_identity_seed(
477 const dif_keymgr_t *keymgr, dif_keymgr_identity_seed_params_t params) {
478 if (keymgr == NULL) {
479 return kDifBadArg;
480 }
481
482 if (!is_ready(keymgr)) {
483 return kDifLocked;
484 }
485
486 start_operation(keymgr,
487 (start_operation_params_t){
488 .dest = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_NONE,
489 .op = KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_ID,
490 .cdi_type = params.cdi_type});
491
492 return kDifOk;
493}
494
495dif_result_t dif_keymgr_generate_versioned_key(
496 const dif_keymgr_t *keymgr, dif_keymgr_versioned_key_params_t params) {
497 if (keymgr == NULL) {
498 return kDifBadArg;
499 }
500
501 start_operation_params_t hw_op_params;
502 switch (params.dest) {
504 hw_op_params = (start_operation_params_t){
505 .dest = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_NONE,
506 .op = KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_SW_OUTPUT,
507 .cdi_type = params.cdi_type};
508 break;
510 hw_op_params = (start_operation_params_t){
511 .dest = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_AES,
512 .op = KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_HW_OUTPUT,
513 .cdi_type = params.cdi_type};
514 break;
516 hw_op_params = (start_operation_params_t){
517 .dest = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_KMAC,
518 .op = KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_HW_OUTPUT,
519 .cdi_type = params.cdi_type};
520 break;
522 hw_op_params = (start_operation_params_t){
523 .dest = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_OTBN,
524 .op = KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_HW_OUTPUT,
525 .cdi_type = params.cdi_type};
526 break;
527 default:
528 return kDifBadArg;
529 }
530
531 if (!is_ready(keymgr)) {
532 return kDifLocked;
533 }
534
535 // Set salt and version
536 mmio_region_memcpy_to_mmio32(keymgr->base_addr, KEYMGR_SALT_0_REG_OFFSET,
537 params.salt, sizeof(params.salt));
538 mmio_region_write32(keymgr->base_addr, KEYMGR_KEY_VERSION_REG_OFFSET,
539 params.version);
540
541 start_operation(keymgr, hw_op_params);
542
543 return kDifOk;
544}
545
546dif_result_t dif_keymgr_sideload_clear_set_enabled(const dif_keymgr_t *keymgr,
547 dif_toggle_t state) {
548 if (keymgr == NULL || !dif_is_valid_toggle(state)) {
549 return kDifBadArg;
550 }
551
553 ? kDifKeyMgrSideLoadClearAll
554 : kDifKeyMgrSideLoadClearNone;
555
556 mmio_region_write32(keymgr->base_addr, KEYMGR_SIDELOAD_CLEAR_REG_OFFSET, val);
557
558 return kDifOk;
559}
560
561dif_result_t dif_keymgr_sideload_clear_get_enabled(const dif_keymgr_t *keymgr,
562 dif_toggle_t *state) {
563 if (keymgr == NULL || state == NULL) {
564 return kDifBadArg;
565 }
566
567 uint32_t reg_val =
568 mmio_region_read32(keymgr->base_addr, KEYMGR_SIDELOAD_CLEAR_REG_OFFSET);
569 *state = dif_bool_to_toggle(reg_val == kDifKeyMgrSideLoadClearAll);
570
571 return kDifOk;
572}
573
574dif_result_t dif_keymgr_read_output(const dif_keymgr_t *keymgr,
575 dif_keymgr_output_t *output) {
576 if (keymgr == NULL || output == NULL) {
577 return kDifBadArg;
578 }
579
580 mmio_region_memcpy_from_mmio32(keymgr->base_addr,
581 KEYMGR_SW_SHARE0_OUTPUT_0_REG_OFFSET,
582 output->value[0], sizeof(output->value[0]));
583 mmio_region_memcpy_from_mmio32(keymgr->base_addr,
584 KEYMGR_SW_SHARE1_OUTPUT_0_REG_OFFSET,
585 output->value[1], sizeof(output->value[1]));
586
587 return kDifOk;
588}
589
590dif_result_t dif_keymgr_read_binding(const dif_keymgr_t *keymgr,
592 if (keymgr == NULL || output == NULL) {
593 return kDifBadArg;
594 }
595
596 mmio_region_memcpy_from_mmio32(keymgr->base_addr,
597 KEYMGR_SEALING_SW_BINDING_0_REG_OFFSET,
598 output->sealing, sizeof(output->sealing));
599
600 mmio_region_memcpy_from_mmio32(
601 keymgr->base_addr, KEYMGR_ATTEST_SW_BINDING_0_REG_OFFSET,
602 output->attestation, sizeof(output->attestation));
603
604 return kDifOk;
605}
606
607dif_result_t dif_keymgr_read_max_key_version(
608 const dif_keymgr_t *keymgr, dif_keymgr_max_key_version_t *versions) {
609 if (keymgr == NULL || versions == NULL) {
610 return kDifBadArg;
611 }
612
613 versions->creator_max_key_version = mmio_region_read32(
614 keymgr->base_addr, KEYMGR_MAX_CREATOR_KEY_VER_SHADOWED_REG_OFFSET);
615 versions->owner_int_max_key_version = mmio_region_read32(
616 keymgr->base_addr, KEYMGR_MAX_OWNER_INT_KEY_VER_SHADOWED_REG_OFFSET);
617 versions->owner_max_key_version = mmio_region_read32(
618 keymgr->base_addr, KEYMGR_MAX_OWNER_KEY_VER_SHADOWED_REG_OFFSET);
619
620 return kDifOk;
621}