Skip to content

Commit 50d60e5

Browse files
sasdftimothytrippel
authored andcommitted
[sw,dice] Store CDI 0 to static_critical section
The previous method of transferring CDI_0 from immutable ROM_EXT to mutable ROM_EXT stored data in flash memory, negatively impacting both firmware size and boot time. To solve the issue, this commit allocates space within the static_critical section to transfer the CDI_0 cert using RAM. Change-Id: I7cda7bdd1cd2adebb80c1089189b7960ae7f1deb Signed-off-by: Yi-Hsuan Deng <yhdeng@google.com>
1 parent 0f9da60 commit 50d60e5

File tree

11 files changed

+190
-45
lines changed

11 files changed

+190
-45
lines changed

sw/device/silicon_creator/imm_rom_ext/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ cc_library(
3535
"//sw/device/silicon_creator/lib/base:boot_measurements",
3636
"//sw/device/silicon_creator/lib/base:sec_mmio",
3737
"//sw/device/silicon_creator/lib/base:static_critical",
38+
"//sw/device/silicon_creator/lib/base:static_dice",
3839
"//sw/device/silicon_creator/lib/cert:dice_chain",
3940
"//sw/device/silicon_creator/lib/drivers:rnd",
4041
"//sw/device/silicon_creator/lib/ownership:ownership_key",
@@ -65,6 +66,7 @@ ld_library(
6566
"//hw/top_earlgrey/sw/autogen:top_earlgrey_memory",
6667
"//sw/device:info_sections",
6768
"//sw/device/silicon_creator/lib/base:static_critical_sections",
69+
"//sw/device/silicon_creator/lib/base:static_dice_sections",
6870
],
6971
)
7072

sw/device/silicon_creator/imm_rom_ext/imm_rom_ext.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ static rom_error_t imm_rom_ext_start(void) {
4848
// Establish our identity.
4949
const manifest_t *rom_ext = rom_ext_manifest();
5050
HARDENED_RETURN_IF_ERROR(dice_chain_init());
51-
// TODO: Move UDS cert check to mutable ROM_EXT.
5251
HARDENED_RETURN_IF_ERROR(dice_chain_attestation_silicon());
5352

5453
// Sideload sealing key to KMAC hw keyslot.
@@ -57,9 +56,6 @@ static rom_error_t imm_rom_ext_start(void) {
5756
HARDENED_RETURN_IF_ERROR(
5857
dice_chain_attestation_creator(&boot_measurements.rom_ext, rom_ext));
5958

60-
// Write the DICE certs to flash if they have been updated.
61-
HARDENED_RETURN_IF_ERROR(dice_chain_flush_flash());
62-
6359
// Make mutable part executable.
6460
HARDENED_RETURN_IF_ERROR(imm_rom_ext_epmp_mutable_rx(rom_ext));
6561

sw/device/silicon_creator/imm_rom_ext/imm_rom_ext_common.ld

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ SECTIONS {
8383
*/
8484
INCLUDE sw/device/silicon_creator/lib/base/static_critical.ld
8585

86+
/**
87+
* Critical static data that is accessible by both the immutable and
88+
* mutable ROM extension.
89+
*/
90+
INCLUDE sw/device/silicon_creator/lib/base/static_dice.ld
91+
8692
/**
8793
* Mutable data section, at the bottom of ram_main. This will be initialized
8894
* from flash at runtime by the CRT.

sw/device/silicon_creator/lib/base/BUILD

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,32 @@ cc_library(
124124
],
125125
)
126126

127+
cc_library(
128+
name = "static_dice_cdi_0",
129+
srcs = ["static_dice_cdi_0.c"],
130+
hdrs = ["static_dice_cdi_0.h"],
131+
deps = [
132+
"//sw/device/lib/base:macros",
133+
"//sw/device/silicon_creator/lib/drivers:hmac",
134+
],
135+
# This library provides a special symbol that the linker will find.
136+
alwayslink = True,
137+
)
138+
139+
ld_library(
140+
name = "static_dice_sections",
141+
includes = [
142+
"static_dice.ld",
143+
],
144+
)
145+
146+
cc_library(
147+
name = "static_dice",
148+
deps = [
149+
":static_dice_cdi_0",
150+
],
151+
)
152+
127153
cc_library(
128154
name = "chip",
129155
hdrs = ["chip.h"],
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
/**
6+
* DICE variables stored in the .static_dice section of RAM.
7+
*
8+
* These variables are transferred from immutable ROM_EXT to mutable ROM_EXT.
9+
*
10+
* This file should be included inside of a `SECTIONS` block where a
11+
* `ram_main` memory is defined, and should come before all other main
12+
* memory sections and after the .static_critical section.
13+
*/
14+
15+
.static_dice (NOLOAD) : ALIGN(4) {
16+
ASSERT(
17+
. == ORIGIN(ram_main) + SIZEOF(.static_critical),
18+
"Error: .static_dice section does not follow the .static_critical section.");
19+
20+
KEEP(*(.static_dice.cdi_0))
21+
22+
ASSERT(
23+
SIZEOF(.static_dice) == 1092,
24+
"Error: .static_dice section size has changed");
25+
} > ram_main
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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/silicon_creator/lib/base/static_dice_cdi_0.h"
6+
7+
#include "sw/device/lib/base/macros.h"
8+
9+
// CDI 0 cert signed by immutable ROM_EXT.
10+
//
11+
// This is placed at a fixed location in memory within the
12+
// .static_dice section. It will be populated by the immutable
13+
// ROM_EXT before the jump to mutable ROM_EXT.
14+
OT_SET_BSS_SECTION(".static_dice.cdi_0",
15+
OT_USED static_dice_cdi_0_t static_dice_cdi_0;)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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+
#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_BASE_STATIC_DICE_CDI_0_H_
6+
#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_BASE_STATIC_DICE_CDI_0_H_
7+
8+
#include <stdint.h>
9+
10+
#include "sw/device/lib/base/macros.h"
11+
#include "sw/device/silicon_creator/lib/drivers/hmac.h"
12+
13+
enum {
14+
kCdi0CertStaticCriticalSizeBytes = 1024,
15+
};
16+
17+
// The dice chain information that the immutable ROM_EXT will pass to the
18+
// mutable ROM_EXT.
19+
typedef struct {
20+
hmac_digest_t uds_pubkey_id;
21+
hmac_digest_t cdi_0_pubkey_id;
22+
uint32_t cert_size;
23+
uint8_t cert_data[kCdi0CertStaticCriticalSizeBytes];
24+
} static_dice_cdi_0_t;
25+
26+
OT_ASSERT_MEMBER_OFFSET(static_dice_cdi_0_t, uds_pubkey_id, 0);
27+
OT_ASSERT_MEMBER_OFFSET(static_dice_cdi_0_t, cdi_0_pubkey_id, 32);
28+
OT_ASSERT_MEMBER_OFFSET(static_dice_cdi_0_t, cert_size, 64);
29+
OT_ASSERT_MEMBER_OFFSET(static_dice_cdi_0_t, cert_data, 68);
30+
OT_ASSERT_SIZE(static_dice_cdi_0_t, 1092);
31+
32+
extern static_dice_cdi_0_t static_dice_cdi_0;
33+
34+
#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_BASE_STATIC_DICE_CDI_0_H_

sw/device/silicon_creator/lib/cert/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ cc_library(
226226
"//sw/device/silicon_creator/lib:manifest",
227227
"//sw/device/silicon_creator/lib/base:boot_measurements",
228228
"//sw/device/silicon_creator/lib/base:sec_mmio",
229+
"//sw/device/silicon_creator/lib/base:static_dice_cdi_0",
229230
"//sw/device/silicon_creator/lib/base:util",
230231
"//sw/device/silicon_creator/lib/cert:dice",
231232
"//sw/device/silicon_creator/lib/drivers:flash_ctrl",

sw/device/silicon_creator/lib/cert/dice_chain.c

Lines changed: 73 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "sw/device/lib/crypto/drivers/entropy.h"
1111
#include "sw/device/silicon_creator/lib/base/boot_measurements.h"
1212
#include "sw/device/silicon_creator/lib/base/sec_mmio.h"
13+
#include "sw/device/silicon_creator/lib/base/static_dice_cdi_0.h"
1314
#include "sw/device/silicon_creator/lib/base/util.h"
1415
#include "sw/device/silicon_creator/lib/cert/dice.h"
1516
#include "sw/device/silicon_creator/lib/dbg_print.h"
@@ -97,6 +98,11 @@ typedef struct dice_chain {
9798

9899
static dice_chain_t dice_chain;
99100

101+
cert_key_id_pair_t dice_chain_cdi_0_key_ids = (cert_key_id_pair_t){
102+
.endorsement = &static_dice_cdi_0.uds_pubkey_id,
103+
.cert = &static_dice_cdi_0.cdi_0_pubkey_id,
104+
};
105+
100106
// Get the size of the remaining tail space that is not processed yet.
101107
OT_WARN_UNUSED_RESULT
102108
OT_NOINLINE
@@ -277,31 +283,13 @@ rom_error_t dice_chain_attestation_silicon(void) {
277283
sc_keymgr_advance_state();
278284
HARDENED_RETURN_IF_ERROR(sc_keymgr_state_check(kScKeymgrStateCreatorRootKey));
279285
HARDENED_RETURN_IF_ERROR(otbn_boot_cert_ecc_p256_keygen(
280-
kDiceKeyUds, &dice_chain.subject_pubkey_id, &dice_chain.subject_pubkey));
281-
282-
// Switch page for the factory provisioned UDS cert.
283-
RETURN_IF_ERROR(dice_chain_load_flash(&kFlashCtrlInfoPageFactoryCerts));
284-
285-
// Check if the UDS cert is valid.
286-
RETURN_IF_ERROR(dice_chain_load_cert_obj("UDS", /*name_size=*/4));
287-
if (dice_chain.cert_valid == kHardenedBoolFalse) {
288-
// The UDS key ID (and cert itself) should never change unless:
289-
// 1. there is a hardware issue / the page has been corrupted, or
290-
// 2. the cert has not yet been provisioned.
291-
//
292-
// In both cases, we do nothing, and boot normally, later attestation
293-
// attempts will fail in a detectable manner.
294-
dbg_puts("Warning: UDS certificate not valid.\r\n");
295-
} else {
296-
// Cert is valid, move to the next one.
297-
dice_chain_next_cert_obj();
298-
}
286+
kDiceKeyUds, &static_dice_cdi_0.uds_pubkey_id,
287+
&dice_chain.subject_pubkey));
299288

300289
// Save UDS key for signing next stage cert.
301290
RETURN_IF_ERROR(otbn_boot_attestation_key_save(
302291
kDiceKeyUds.keygen_seed_idx, kDiceKeyUds.type,
303292
*kDiceKeyUds.keymgr_diversifier));
304-
dice_chain.endorsement_pubkey_id = dice_chain.subject_pubkey_id;
305293

306294
return kErrorOk;
307295
}
@@ -319,7 +307,8 @@ rom_error_t dice_chain_attestation_creator(
319307
/*attest_binding=*/rom_ext_measurement,
320308
rom_ext_manifest->max_key_version));
321309
HARDENED_RETURN_IF_ERROR(otbn_boot_cert_ecc_p256_keygen(
322-
kDiceKeyCdi0, &dice_chain.subject_pubkey_id, &dice_chain.subject_pubkey));
310+
kDiceKeyCdi0, &static_dice_cdi_0.cdi_0_pubkey_id,
311+
&dice_chain.subject_pubkey));
323312

324313
// Switch page for the device generated CDI_0.
325314
RETURN_IF_ERROR(dice_chain_load_flash(&kFlashCtrlInfoPageDiceCerts));
@@ -332,33 +321,83 @@ rom_error_t dice_chain_attestation_creator(
332321
if (dice_chain.cert_valid == kHardenedBoolFalse) {
333322
dbg_puts("CDI_0 certificate not valid. Updating it ...\r\n");
334323
// Update the cert page buffer.
335-
size_t updated_cert_size = kScratchCertSizeBytes;
336-
HARDENED_RETURN_IF_ERROR(
337-
dice_cdi_0_cert_build((hmac_digest_t *)rom_ext_measurement->data,
338-
rom_ext_manifest->security_version,
339-
&dice_chain.key_ids, &dice_chain.subject_pubkey,
340-
dice_chain.scratch_cert, &updated_cert_size));
341-
RETURN_IF_ERROR(dice_chain_push_cert("CDI_0", dice_chain.scratch_cert,
342-
updated_cert_size));
324+
static_dice_cdi_0.cert_size = sizeof(static_dice_cdi_0.cert_data);
325+
HARDENED_RETURN_IF_ERROR(dice_cdi_0_cert_build(
326+
(hmac_digest_t *)rom_ext_measurement->data,
327+
rom_ext_manifest->security_version, &dice_chain_cdi_0_key_ids,
328+
&dice_chain.subject_pubkey, static_dice_cdi_0.cert_data,
329+
&static_dice_cdi_0.cert_size));
343330
} else {
344-
// Cert is valid, move to the next one.
345-
dice_chain_next_cert_obj();
346-
347331
// Replace UDS with CDI_0 key for endorsing next stage cert.
348332
HARDENED_RETURN_IF_ERROR(otbn_boot_attestation_key_save(
349333
kDiceKeyCdi0.keygen_seed_idx, kDiceKeyCdi0.type,
350334
*kDiceKeyCdi0.keymgr_diversifier));
351335
}
352-
dice_chain.endorsement_pubkey_id = dice_chain.subject_pubkey_id;
353336

354337
sc_keymgr_sw_binding_unlock_wait();
355338

356339
return kErrorOk;
357340
}
358341

342+
// Compare the UDS identity in the static critical section to the UDS cert
343+
// cached in the flash.
344+
static rom_error_t dice_chain_attestation_check_uds(void) {
345+
// Switch page for the factory provisioned UDS cert.
346+
RETURN_IF_ERROR(dice_chain_load_flash(&kFlashCtrlInfoPageFactoryCerts));
347+
348+
// Check if the UDS cert is valid.
349+
dice_chain.endorsement_pubkey_id = static_dice_cdi_0.uds_pubkey_id;
350+
dice_chain.subject_pubkey_id = static_dice_cdi_0.uds_pubkey_id;
351+
RETURN_IF_ERROR(dice_chain_load_cert_obj("UDS", /*name_size=*/4));
352+
if (dice_chain.cert_valid == kHardenedBoolFalse) {
353+
// The UDS key ID (and cert itself) should never change unless:
354+
// 1. there is a hardware issue / the page has been corrupted, or
355+
// 2. the cert has not yet been provisioned.
356+
//
357+
// In both cases, we do nothing, and boot normally, later attestation
358+
// attempts will fail in a detectable manner.
359+
360+
// CAUTION: This error message should match the one in
361+
// //sw/host/provisioning/ft_lib/src/lib.rs
362+
dbg_puts("error: UDS certificate not valid\r\n");
363+
}
364+
365+
return kErrorOk;
366+
}
367+
368+
// Compare the CDI_0 identity in the static critical section to the CDI_0 cert
369+
// cached in the flash, and refresh the cache if invalid.
370+
static rom_error_t dice_chain_attestation_check_cdi_0(void) {
371+
// Switch page for the device CDI chain.
372+
RETURN_IF_ERROR(dice_chain_load_flash(&kFlashCtrlInfoPageDiceCerts));
373+
374+
// Seek to skip previous objects.
375+
RETURN_IF_ERROR(dice_chain_skip_cert_obj("UDS", /*name_size=*/4));
376+
377+
// Refresh cdi 0 if invalid
378+
dice_chain.endorsement_pubkey_id = static_dice_cdi_0.cdi_0_pubkey_id;
379+
dice_chain.subject_pubkey_id = static_dice_cdi_0.cdi_0_pubkey_id;
380+
RETURN_IF_ERROR(dice_chain_load_cert_obj("CDI_0", /*name_size=*/6));
381+
if (dice_chain.cert_valid == kHardenedBoolFalse) {
382+
dbg_puts("warning: CDI_0 certificate not valid; updating\r\n");
383+
// Update the cert page buffer.
384+
RETURN_IF_ERROR(dice_chain_push_cert("CDI_0", static_dice_cdi_0.cert_data,
385+
static_dice_cdi_0.cert_size));
386+
} else {
387+
// Cert is valid, move to the next one.
388+
dice_chain_next_cert_obj();
389+
}
390+
391+
return kErrorOk;
392+
}
393+
359394
rom_error_t dice_chain_attestation_owner(
360395
const manifest_t *owner_manifest, keymgr_binding_value_t *bl0_measurement,
361396
hmac_digest_t *owner_measurement, keymgr_binding_value_t *sealing_binding) {
397+
// Handles the certificates from the immutable rom_ext first.
398+
RETURN_IF_ERROR(dice_chain_attestation_check_uds());
399+
RETURN_IF_ERROR(dice_chain_attestation_check_cdi_0());
400+
362401
// Generate CDI_1 attestation keys and (potentially) update certificate.
363402
SEC_MMIO_WRITE_INCREMENT(kScKeymgrSecMmioSwBindingSet +
364403
kScKeymgrSecMmioOwnerIntMaxVerSet);
@@ -384,14 +423,7 @@ rom_error_t dice_chain_attestation_owner(
384423
HARDENED_RETURN_IF_ERROR(otbn_boot_cert_ecc_p256_keygen(
385424
kDiceKeyCdi1, &dice_chain.subject_pubkey_id, &dice_chain.subject_pubkey));
386425

387-
// Switch page for the device generated CDI_1.
388-
RETURN_IF_ERROR(dice_chain_load_flash(&kFlashCtrlInfoPageDiceCerts));
389-
390-
// Seek to skip previous objects.
391-
RETURN_IF_ERROR(dice_chain_skip_cert_obj("UDS", /*name_size=*/4));
392-
RETURN_IF_ERROR(dice_chain_skip_cert_obj("CDI_0", /*name_size=*/6));
393-
394-
// Check if the current CDI_0 cert is valid.
426+
// Check if the current CDI_1 cert is valid.
395427
RETURN_IF_ERROR(dice_chain_load_cert_obj("CDI_1", /*name_size=*/6));
396428
if (dice_chain.cert_valid == kHardenedBoolFalse) {
397429
dbg_puts("CDI_1 certificate not valid. Updating it ...\r\n");

sw/device/silicon_creator/rom_ext/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ ld_library(
104104
deps = [
105105
"//sw/device:info_sections",
106106
"//sw/device/silicon_creator/lib/base:static_critical_sections",
107+
"//sw/device/silicon_creator/lib/base:static_dice_sections",
107108
],
108109
)
109110

@@ -191,6 +192,7 @@ cc_library(
191192
"//sw/device/silicon_creator/lib/base:chip",
192193
"//sw/device/silicon_creator/lib/base:sec_mmio",
193194
"//sw/device/silicon_creator/lib/base:static_critical",
195+
"//sw/device/silicon_creator/lib/base:static_dice",
194196
"//sw/device/silicon_creator/lib/boot_svc:boot_svc_msg",
195197
"//sw/device/silicon_creator/lib/cert:dice_chain",
196198
"//sw/device/silicon_creator/lib/drivers:ast",

sw/device/silicon_creator/rom_ext/rom_ext_common.ld

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,12 @@ SECTIONS {
147147
*/
148148
INCLUDE sw/device/silicon_creator/lib/base/static_critical.ld
149149

150+
/**
151+
* Critical static data that is accessible by both the immutable and
152+
* mutable ROM extension.
153+
*/
154+
INCLUDE sw/device/silicon_creator/lib/base/static_dice.ld
155+
150156
/**
151157
* Mutable data section, at the bottom of ram_main. This will be initialized
152158
* from flash at runtime by the CRT.

0 commit comments

Comments
 (0)