Skip to content

Commit

Permalink
[imm_rom_ext] Mint CDI_0 certs in immutable rom ext
Browse files Browse the repository at this point in the history
Since CDI_0 attests the integrity of rom_ext, this PR moves the UDS & CDI_0
stage to the immutable rom_ext part, which will be executed before mutable
rom_ext, to establish root trust in hardware.

SKU owners can choose whether the immutability should be enforced using the
`CREATOR_SW_CFG_IMMUTABLE_ROM_EXT_EN` OTP field.

Change-Id: If971654a27ea32eaf74d20d385e48801d28e1da5
Signed-off-by: Yi-Hsuan Deng <[email protected]>
  • Loading branch information
sasdf committed Dec 17, 2024
1 parent c534d13 commit c97c3c6
Show file tree
Hide file tree
Showing 15 changed files with 220 additions and 25 deletions.
19 changes: 19 additions & 0 deletions sw/device/silicon_creator/imm_rom_ext/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,23 @@ cc_library(
name = "main_lib",
srcs = ["imm_rom_ext.c"],
hdrs = ["imm_rom_ext.h"],
deps = [
"//hw/top_earlgrey/ip_autogen/flash_ctrl:flash_ctrl_c_regs",
"//sw/device/lib/arch:device",
"//sw/device/lib/base:macros",
"//sw/device/silicon_creator/lib:dbg_print",
"//sw/device/silicon_creator/lib:epmp_state",
"//sw/device/silicon_creator/lib:error",
"//sw/device/silicon_creator/lib:manifest",
"//sw/device/silicon_creator/lib:shutdown",
"//sw/device/silicon_creator/lib/base:boot_measurements",
"//sw/device/silicon_creator/lib/base:sec_mmio",
"//sw/device/silicon_creator/lib/base:static_critical",
"//sw/device/silicon_creator/lib/cert:dice_chain",
"//sw/device/silicon_creator/lib/drivers:pinmux",
"//sw/device/silicon_creator/lib/drivers:rnd",
"//sw/device/silicon_creator/lib/drivers:uart",
"//sw/device/silicon_creator/lib/ownership:ownership_key",
"//sw/device/silicon_creator/rom_ext:rom_ext_manifest",
],
)
10 changes: 10 additions & 0 deletions sw/device/silicon_creator/imm_rom_ext/e2e/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copyright lowRISC contributors (OpenTitan project).
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

package(default_visibility = ["//visibility:public"])

filegroup(
name = "empty_test",
srcs = ["empty_test.c"],
)
26 changes: 26 additions & 0 deletions sw/device/silicon_creator/imm_rom_ext/e2e/boot_message/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright lowRISC contributors (OpenTitan project).
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

load(
"//rules/opentitan:defs.bzl",
"fpga_params",
"opentitan_test",
)

package(default_visibility = ["//visibility:public"])

opentitan_test(
name = "boot_test",
srcs = ["//sw/device/silicon_creator/imm_rom_ext/e2e:empty_test"],
exec_env = {
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
},
fpga = fpga_params(
exit_success = "\nIMM_ROM_EXT:",
),
deps = [
"//sw/device/lib/testing/test_framework:ottf_main",
],
)
9 changes: 9 additions & 0 deletions sw/device/silicon_creator/imm_rom_ext/e2e/empty_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/lib/testing/test_framework/ottf_main.h"

OTTF_DEFINE_TEST_CONFIG();

bool test_main(void) { return true; }
59 changes: 58 additions & 1 deletion sw/device/silicon_creator/imm_rom_ext/imm_rom_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,64 @@

#include "sw/device/silicon_creator/imm_rom_ext/imm_rom_ext.h"

#include "sw/device/lib/arch/device.h"
#include "sw/device/lib/base/macros.h"
#include "sw/device/silicon_creator/lib/base/boot_measurements.h"
#include "sw/device/silicon_creator/lib/base/sec_mmio.h"
#include "sw/device/silicon_creator/lib/cert/dice_chain.h"
#include "sw/device/silicon_creator/lib/dbg_print.h"
#include "sw/device/silicon_creator/lib/drivers/pinmux.h"
#include "sw/device/silicon_creator/lib/drivers/rnd.h"
#include "sw/device/silicon_creator/lib/drivers/uart.h"
#include "sw/device/silicon_creator/lib/epmp_state.h"
#include "sw/device/silicon_creator/lib/error.h"
#include "sw/device/silicon_creator/lib/manifest.h"
#include "sw/device/silicon_creator/lib/ownership/ownership_key.h"
#include "sw/device/silicon_creator/lib/shutdown.h"
#include "sw/device/silicon_creator/rom_ext/rom_ext_manifest.h"

OT_WARN_UNUSED_RESULT
static rom_error_t imm_rom_ext_start(void) {
// Check the ePMP state.
HARDENED_RETURN_IF_ERROR(epmp_state_check());
// Check sec_mmio expectations.
// We don't check the counters since we don't want to tie ROM_EXT to a
// specific ROM version.
sec_mmio_check_values(rnd_uint32());

// Initialize Immutable ROM EXT.
sec_mmio_next_stage_init();
// Configure UART0 as stdout.
pinmux_init_uart0_tx();
uart_init(kUartNCOValue);

dbg_printf("IMM_ROM_EXT v0.1\r\n");

// Establish our identity.
const manifest_t *rom_ext = rom_ext_manifest();
HARDENED_RETURN_IF_ERROR(dice_chain_init());
// TODO: Move UDS cert check to mutable ROM_EXT.
HARDENED_RETURN_IF_ERROR(dice_chain_attestation_silicon());

// Sideload sealing key to KMAC hw keyslot.
HARDENED_RETURN_IF_ERROR(ownership_seal_init());

HARDENED_RETURN_IF_ERROR(
dice_chain_attestation_creator(&boot_measurements.rom_ext, rom_ext));

// Write the DICE certs to flash if they have been updated.
HARDENED_RETURN_IF_ERROR(dice_chain_flush_flash());

return kErrorOk;
}

void imm_rom_ext_main(void) {
// TODO(opentitan#24368): Implement this.
rom_error_t error = imm_rom_ext_start();
if (launder32(error) != kErrorOk) {
shutdown_finalize(error);
}
HARDENED_CHECK_EQ(error, kErrorOk);

// Go back to ROM / Mutable ROM_EXT.
return;
}
3 changes: 2 additions & 1 deletion sw/device/silicon_creator/lib/cert/dice_chain.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ rom_error_t dice_chain_attestation_creator(
}
dice_chain.endorsement_pubkey_id = dice_chain.subject_pubkey_id;

sc_keymgr_sw_binding_unlock_wait();

return kErrorOk;
}

Expand Down Expand Up @@ -410,7 +412,6 @@ rom_error_t dice_chain_attestation_owner(
}
dice_chain.endorsement_pubkey_id = dice_chain.subject_pubkey_id;

// TODO: elimiate this call when we've fully programmed keymgr and lock it.
sc_keymgr_sw_binding_unlock_wait();

return kErrorOk;
Expand Down
2 changes: 2 additions & 0 deletions sw/device/silicon_creator/lib/drivers/pinmux.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ static void configure_output(pinmux_output_t output) {
output.outsel);
}

void pinmux_init_uart0_tx(void) { configure_output(kOutputUart0); }

void pinmux_init(void) {
uint32_t bootstrap_dis =
otp_read32(OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_BOOTSTRAP_DIS_OFFSET);
Expand Down
5 changes: 5 additions & 0 deletions sw/device/silicon_creator/lib/drivers/pinmux.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ extern "C" {
*/
void pinmux_init(void);

/**
* Initialize the pinmux with output UART0 only.
*/
void pinmux_init_uart0_tx(void);

/**
* Read the SW_STRAP value.
*
Expand Down
8 changes: 8 additions & 0 deletions sw/device/silicon_creator/lib/drivers/pinmux_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,13 @@ TEST_F(InitTest, WithoutBootstrap) {
pinmux_init();
}

TEST_F(InitTest, Uart0TxOnly) {
// The outputs that will be configured.
EXPECT_ABS_WRITE32(RegOutSel(kTopEarlgreyPinmuxMioOutIoc4),
kTopEarlgreyPinmuxOutselUart0Tx);

pinmux_init_uart0_tx();
}

} // namespace
} // namespace pinmux_unittest
21 changes: 14 additions & 7 deletions sw/device/silicon_creator/rom/e2e/address_translation/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ package(default_visibility = ["//visibility:public"])
opentitan_test(
name = "rom_ext_a_flash_a",
exec_env = {
"//hw/top_earlgrey:fpga_cw310_rom_with_fake_keys": None,
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
},
fpga = fpga_params(
assemble = "{firmware}@{offset}",
Expand All @@ -42,7 +43,8 @@ opentitan_test(
opentitan_test(
name = "rom_ext_b_flash_b",
exec_env = {
"//hw/top_earlgrey:fpga_cw310_rom_with_fake_keys": None,
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
},
fpga = fpga_params(
assemble = "{firmware}@{offset}",
Expand All @@ -58,7 +60,8 @@ opentitan_test(
opentitan_test(
name = "rom_ext_a_flash_b",
exec_env = {
"//hw/top_earlgrey:fpga_cw310_rom_with_fake_keys": None,
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
},
fpga = fpga_params(
assemble = "{firmware}@{offset}",
Expand All @@ -74,7 +77,8 @@ opentitan_test(
opentitan_test(
name = "rom_ext_b_flash_a",
exec_env = {
"//hw/top_earlgrey:fpga_cw310_rom_with_fake_keys": None,
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
},
fpga = fpga_params(
assemble = "{firmware}@{offset}",
Expand All @@ -90,7 +94,8 @@ opentitan_test(
opentitan_test(
name = "rom_ext_v_flash_a",
exec_env = {
"//hw/top_earlgrey:fpga_cw310_rom_with_fake_keys": None,
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
},
fpga = fpga_params(
assemble = "{firmware}@{offset}",
Expand All @@ -106,7 +111,8 @@ opentitan_test(
opentitan_test(
name = "rom_ext_v_flash_b",
exec_env = {
"//hw/top_earlgrey:fpga_cw310_rom_with_fake_keys": None,
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
},
fpga = fpga_params(
assemble = "{firmware}@{offset}",
Expand All @@ -122,7 +128,8 @@ opentitan_test(
opentitan_test(
name = "rom_ext_a_flash_a_bad_addr_trans",
exec_env = {
"//hw/top_earlgrey:fpga_cw310_rom_with_fake_keys": None,
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
},
fpga = fpga_params(
assemble = "{firmware}@{offset}",
Expand Down
3 changes: 2 additions & 1 deletion sw/device/silicon_creator/rom/e2e/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ MSG_TEMPLATE_BFV_LCV = "{}{}\r\n{}{}\r\n(?s:.*){}{}\r\n{}{}\r\n".format(
"{1}",
)

MSG_STARTING_ROM_EXT = "Starting ROM_EXT"
# When starting ROM_EXT, immutable section will always run first.
MSG_STARTING_ROM_EXT = "\nIMM_ROM_EXT v"

MSG_PASS = "PASS!"

Expand Down
15 changes: 15 additions & 0 deletions sw/device/silicon_creator/rom_ext/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,18 @@ cc_library(
],
)

cc_library(
name = "rom_ext_manifest",
srcs = ["rom_ext_manifest.c"],
hdrs = ["rom_ext_manifest.h"],
target_compatible_with = [OPENTITAN_CPU],
deps = [
"//hw/top_earlgrey/sw/autogen:top_earlgrey",
"//sw/device/lib/base:macros",
"//sw/device/silicon_creator/lib:manifest",
],
)

dual_cc_library(
name = "rom_ext_boot_policy_ptrs",
srcs = dual_inputs(
Expand Down Expand Up @@ -207,6 +219,7 @@ cc_library(
":rescue",
":rom_ext_boot_policy",
":rom_ext_boot_policy_ptrs",
":rom_ext_manifest",
":sigverify_keys",
"//hw/ip/sram_ctrl/data:sram_ctrl_c_regs",
"//hw/top_earlgrey/ip_autogen/flash_ctrl:flash_ctrl_c_regs",
Expand All @@ -220,9 +233,11 @@ cc_library(
"//sw/device/silicon_creator/lib:boot_data",
"//sw/device/silicon_creator/lib:boot_log",
"//sw/device/silicon_creator/lib:dbg_print",
"//sw/device/silicon_creator/lib:epmp_state",
"//sw/device/silicon_creator/lib:manifest",
"//sw/device/silicon_creator/lib:manifest_def",
"//sw/device/silicon_creator/lib:shutdown",
"//sw/device/silicon_creator/lib/base:boot_measurements",
"//sw/device/silicon_creator/lib/base:chip",
"//sw/device/silicon_creator/lib/base:sec_mmio",
"//sw/device/silicon_creator/lib/base:static_critical",
Expand Down
17 changes: 2 additions & 15 deletions sw/device/silicon_creator/rom_ext/rom_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "sw/device/silicon_creator/rom_ext/rescue.h"
#include "sw/device/silicon_creator/rom_ext/rom_ext_boot_policy.h"
#include "sw/device/silicon_creator/rom_ext/rom_ext_boot_policy_ptrs.h"
#include "sw/device/silicon_creator/rom_ext/rom_ext_manifest.h"
#include "sw/device/silicon_creator/rom_ext/sigverify_keys.h"

#include "flash_ctrl_regs.h" // Generated.
Expand Down Expand Up @@ -140,17 +141,6 @@ static uint32_t rom_ext_current_slot(void) {
return side;
}

OT_WARN_UNUSED_RESULT
const manifest_t *rom_ext_manifest(void) {
uint32_t pc = 0;
asm("auipc %[pc], 0;" : [pc] "=r"(pc));
const uint32_t kFlashHalf = TOP_EARLGREY_FLASH_CTRL_MEM_SIZE_BYTES / 2;
// Align the PC to the current flash side. The ROM_EXT must be the first
// entity in each flash side, so this alignment is the manifest address.
pc &= ~(kFlashHalf - 1);
return (const manifest_t *)pc;
}

void rom_ext_check_rom_expectations(void) {
// Check the ePMP state.
SHUTDOWN_IF_ERROR(epmp_state_check());
Expand Down Expand Up @@ -619,11 +609,8 @@ static rom_error_t rom_ext_start(boot_data_t *boot_data, boot_log_t *boot_log) {
dbg_printf("Starting ROM_EXT %u.%u\r\n", self->version_major,
self->version_minor);

// Establish our identity.
// Prepare dice chain builder for CDI_1.
HARDENED_RETURN_IF_ERROR(dice_chain_init());
HARDENED_RETURN_IF_ERROR(dice_chain_attestation_silicon());
HARDENED_RETURN_IF_ERROR(
dice_chain_attestation_creator(&boot_measurements.rom_ext, self));

// Initialize the boot_log in retention RAM.
const chip_info_t *rom_chip_info = (const chip_info_t *)_rom_chip_info_start;
Expand Down
23 changes: 23 additions & 0 deletions sw/device/silicon_creator/rom_ext/rom_ext_manifest.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/silicon_creator/rom_ext/rom_ext_manifest.h"

#include "sw/device/silicon_creator/lib/manifest.h"

#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" // Generated.

enum {
kFlashHalf = TOP_EARLGREY_FLASH_CTRL_MEM_SIZE_BYTES / 2,
};

const manifest_t *rom_ext_manifest(void) {
uintptr_t pc = 0;
asm("auipc %[pc], 0;" : [pc] "=r"(pc));

// Align the PC to the current flash side. The ROM_EXT must be the first
// entity in each flash side, so this alignment is the manifest address.
pc &= ~((uintptr_t)kFlashHalf - 1);
return (const manifest_t *)pc;
}
25 changes: 25 additions & 0 deletions sw/device/silicon_creator/rom_ext/rom_ext_manifest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_ROM_EXT_MANIFEST_H_
#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_ROM_EXT_MANIFEST_H_

#include "sw/device/lib/base/macros.h"
#include "sw/device/silicon_creator/lib/manifest.h"

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus

/**
* Return the pointer to rom_ext manifest on the active flash bank.
*/
OT_WARN_UNUSED_RESULT
const manifest_t *rom_ext_manifest(void);

#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_ROM_EXT_MANIFEST_H_

0 comments on commit c97c3c6

Please sign in to comment.