Skip to content

Commit 1ae0d14

Browse files
committed
[keymgr_dpe, dif] Add missing API calls
Add three missing features to the dif of the keymgr_dpe. - The disable function to transition the keymgr_dpe into the disabled state - The configuration function to set the re-seeding interval of the keymgr_dpe - Any sideloaded key on the sideload interface can now be cleared by sw Add an empty `dif_keymgr_dpe_unittest.cc` file to avoid triggering error during the top integration, tracked in Issue #30609. Signed-off-by: Raphael Roth <rroth@lowrisc.org>
1 parent 17e7709 commit 1ae0d14

3 files changed

Lines changed: 155 additions & 1 deletion

File tree

sw/device/lib/dif/dif_keymgr_dpe.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,10 @@ dif_result_t dif_keymgr_dpe_initialize(const dif_keymgr_dpe_t *keymgr_dpe,
166166
return kDifLocked;
167167
}
168168

169+
// TODO(#30667): Verify if the max key version needs to be written here too!
170+
// When loading the UDS the RTL fetches the max key version from
171+
// the SW register. Verify that the lock is released when the
172+
// version register is locked.
169173
uint32_t reg_control = bitfield_field32_write(
170174
KEYMGR_DPE_CONTROL_SHADOWED_REG_RESVAL,
171175
KEYMGR_DPE_CONTROL_SHADOWED_SLOT_DST_SEL_FIELD, slot_dst_sel);
@@ -279,6 +283,28 @@ dif_result_t dif_keymgr_dpe_erase_slot(
279283
return kDifOk;
280284
}
281285

286+
dif_result_t dif_keymgr_dpe_disable(const dif_keymgr_dpe_t *keymgr_dpe) {
287+
if (keymgr_dpe == NULL) {
288+
return kDifBadArg;
289+
}
290+
291+
if (!is_ready(keymgr_dpe)) {
292+
return kDifLocked;
293+
}
294+
295+
uint32_t reg_control = bitfield_field32_write(
296+
KEYMGR_DPE_CONTROL_SHADOWED_REG_RESVAL,
297+
KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_FIELD,
298+
KEYMGR_DPE_CONTROL_SHADOWED_OPERATION_VALUE_DISABLE);
299+
mmio_region_write32_shadowed(keymgr_dpe->base_addr,
300+
KEYMGR_DPE_CONTROL_SHADOWED_REG_OFFSET,
301+
reg_control);
302+
mmio_region_write32(keymgr_dpe->base_addr, KEYMGR_DPE_START_REG_OFFSET,
303+
1 << KEYMGR_DPE_START_EN_BIT);
304+
305+
return kDifOk;
306+
}
307+
282308
dif_result_t dif_keymgr_dpe_generate(
283309
const dif_keymgr_dpe_t *keymgr_dpe,
284310
const dif_keymgr_dpe_generate_params_t *params) {
@@ -405,3 +431,40 @@ dif_result_t dif_keymgr_dpe_get_state(const dif_keymgr_dpe_t *keymgr_dpe,
405431
bitfield_field32_read(reg_state, KEYMGR_DPE_WORKING_STATE_STATE_FIELD);
406432
return kDifOk;
407433
}
434+
435+
dif_result_t dif_keymgr_dpe_clear_sideload_key(
436+
const dif_keymgr_dpe_t *keymgr_dpe,
437+
dif_keymgr_dpe_sideload_clr_t clear_dest) {
438+
if (keymgr_dpe == NULL) {
439+
return kDifBadArg;
440+
}
441+
442+
mmio_region_write32(keymgr_dpe->base_addr,
443+
KEYMGR_DPE_SIDELOAD_CLEAR_REG_OFFSET, clear_dest);
444+
445+
return kDifOk;
446+
}
447+
448+
dif_result_t dif_keymgr_dpe_configure(const dif_keymgr_dpe_t *keymgr_dpe,
449+
dif_keymgr_dpe_config_t config) {
450+
if (keymgr_dpe == NULL) {
451+
return kDifBadArg;
452+
}
453+
454+
// Verify if the register is unlocked
455+
uint32_t reseed_regwen = mmio_region_read32(
456+
keymgr_dpe->base_addr, KEYMGR_DPE_RESEED_INTERVAL_REGWEN_REG_OFFSET);
457+
if (!bitfield_bit32_read(reseed_regwen,
458+
KEYMGR_DPE_RESEED_INTERVAL_REGWEN_EN_BIT)) {
459+
return kDifLocked;
460+
}
461+
462+
uint32_t reg_val =
463+
bitfield_field32_write(0, KEYMGR_DPE_RESEED_INTERVAL_SHADOWED_VAL_FIELD,
464+
config.entropy_reseed_interval);
465+
mmio_region_write32_shadowed(keymgr_dpe->base_addr,
466+
KEYMGR_DPE_RESEED_INTERVAL_SHADOWED_REG_OFFSET,
467+
reg_val);
468+
469+
return kDifOk;
470+
}

sw/device/lib/dif/dif_keymgr_dpe.h

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,33 @@ typedef enum dif_keymgr_dpe_state {
4242
kDifKeymgrDpeStateInvalid = 3
4343
} dif_keymgr_dpe_state_t;
4444

45+
/**
46+
* Enumeration for side load slot clearing.
47+
*/
48+
typedef enum dif_keymgr_sideload_clr {
49+
kDifKeymgrDpeSideLoadClearNone = 0,
50+
kDifKeymgrDpeSideLoadClearAes = 1,
51+
kDifKeymgrDpeSideLoadClearKmac = 2,
52+
kDifKeymgrDpeSideLoadClearOtbn = 3,
53+
// Using different value than those enumerated above should clear all slots,
54+
// so we can use the mask value of this field to denote ALL case.
55+
kDifKeymgrDpeSideLoadClearAll = 7,
56+
} dif_keymgr_dpe_sideload_clr_t;
57+
58+
/**
59+
* Runtime configuration for keymgr dpe.
60+
*/
61+
typedef struct dif_keymgr_dpe_config {
62+
/**
63+
* Number of keymgr_dpe cycles before the entropy is reseeded.
64+
*
65+
* Keymgr dpe uses random values generated by the entropy source for
66+
* initializing its state and clearing sideload keys. This value determines
67+
* the frequency at which this random value is updated.
68+
*/
69+
uint16_t entropy_reseed_interval;
70+
} dif_keymgr_dpe_config_t;
71+
4572
/**
4673
* Input parameters for advancing a DPE context/slot.
4774
*/
@@ -252,6 +279,20 @@ dif_result_t dif_keymgr_dpe_erase_slot(
252279
const dif_keymgr_dpe_t *keymgr_dpe,
253280
const dif_keymgr_dpe_erase_params_t *params);
254281

282+
/**
283+
* Disables key manager dpe.
284+
*
285+
* This function disables keymgr dpe until the next power cycle by making
286+
* it transition to the "disabled" state. The "disabled" state is a terminal
287+
* state where the keymgr dpe is no longer operational and its secret value
288+
* are wiped.
289+
*
290+
* @param keymgr_dpe A key manager handle.
291+
* @return The result of the operation.
292+
*/
293+
OT_WARN_UNUSED_RESULT
294+
dif_result_t dif_keymgr_dpe_disable(const dif_keymgr_dpe_t *keymgr_dpe);
295+
255296
/**
256297
* Generate a SW/HW key from a chosen keymgr_dpe slot.
257298
*
@@ -288,7 +329,7 @@ dif_result_t dif_keymgr_dpe_get_status_codes(
288329
*/
289330
OT_WARN_UNUSED_RESULT
290331
dif_result_t dif_keymgr_dpe_get_state(const dif_keymgr_dpe_t *keymgr_dpe,
291-
uint32_t *state);
332+
dif_keymgr_dpe_state_t *state);
292333

293334
/**
294335
* Read the value of SW generated key from its related CSR. It is the
@@ -302,6 +343,33 @@ OT_WARN_UNUSED_RESULT
302343
dif_result_t dif_keymgr_dpe_read_output(const dif_keymgr_dpe_t *keymgr_dpe,
303344
dif_keymgr_dpe_output_t *output);
304345

346+
/**
347+
* Starts or stops clearing of sideload keys.
348+
*
349+
* Calling this function on a set of output register causes keymgr dpe to clear
350+
* sideload keys continuously using randomness. Callers must disable the
351+
* clearing of sideload keys to resume normal sideload operation.
352+
*
353+
* @param keymgr_dpe A key manager handle.
354+
* @param clear_dest Target sideload key.
355+
* @return The result of the operation.
356+
*/
357+
OT_WARN_UNUSED_RESULT
358+
dif_result_t dif_keymgr_dpe_clear_sideload_key(
359+
const dif_keymgr_dpe_t *keymgr_dpe,
360+
dif_keymgr_dpe_sideload_clr_t clear_dest);
361+
362+
/**
363+
* Runtime configuration for keymgr dpe.
364+
*
365+
* @param keymgr_dpe A key manager handle.
366+
* @param config configuration for the keymgr dpe.
367+
* @return The result of the operation.
368+
*/
369+
OT_WARN_UNUSED_RESULT
370+
dif_result_t dif_keymgr_dpe_configure(const dif_keymgr_dpe_t *keymgr_dpe,
371+
dif_keymgr_dpe_config_t config);
372+
305373
#ifdef __cplusplus
306374
} // extern "C"
307375
#endif // __cplusplus
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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+
5+
#include "sw/device/lib/dif/dif_keymgr_dpe.h"
6+
7+
#include <array>
8+
9+
#include "gtest/gtest.h"
10+
#include "sw/device/lib/base/mmio.h"
11+
#include "sw/device/lib/base/mock_mmio.h"
12+
#include "sw/device/lib/dif/dif_base.h"
13+
#include "sw/device/lib/dif/dif_test_base.h"
14+
15+
#include "hw/top/keymgr_dpe_regs.h" // Generated
16+
17+
namespace dif_keymgr_dpe_unittest {
18+
namespace {
19+
20+
// TODO(#30609): Write these unittests
21+
22+
} // namespace
23+
} // namespace dif_keymgr_dpe_unittest

0 commit comments

Comments
 (0)