diff --git a/hw/top_earlgrey/BUILD b/hw/top_earlgrey/BUILD index e4a69e89efbda..a11bab4feb0e5 100644 --- a/hw/top_earlgrey/BUILD +++ b/hw/top_earlgrey/BUILD @@ -8,7 +8,6 @@ load( ) load( "//rules/opentitan:defs.bzl", - "CLEAR_KEY_SET", "DEFAULT_TEST_FAILURE_MSG", "DEFAULT_TEST_SUCCESS_MSG", "fpga_cw305", diff --git a/signing/BUILD b/signing/BUILD index e68909fe7b8f4..e9561b1c0f592 100644 --- a/signing/BUILD +++ b/signing/BUILD @@ -2,6 +2,8 @@ # Licensed under the Apache License, Version 2.0, see LICENSE for details. # SPDX-License-Identifier: Apache-2.0 +load("@bazel_skylib//rules:common_settings.bzl", "string_flag") + package(default_visibility = ["//visibility:public"]) label_flag( @@ -16,6 +18,54 @@ config_setting( }, ) +# TODO(#24641): Simplify key selection after eliminating RSA keys. +# The currently released ROM_EXT binary for ES silicon (version 0.4) supports +# only RSA keys. The next release will eliminate RSA keys in favor of ECDSA +# keys. In order to allow current users to continue to build RSA-signed +# applications (e.g. tests), we default to an `owner_key_type` of RSA. Ad-hoc +# testing on ES DEV parts running the as-yet unreleased ROM_EXT (at the head +# of this branch) can select ECDSA keys. +# +# Note that the FPGA targets always run the ROM_EXT from head, and always +# select an ECDSA key regardless of the `owner_key_type` setting. +# +# This key-type selection will be removed when we finish converting to ECDSA +# and eliminate RSA keys for application signing. +string_flag( + name = "owner_key_type", + build_setting_default = "rsa", + values = [ + "rsa", + "ecdsa", + ], +) + +config_setting( + name = "owner_key_rsa", + flag_values = {":owner_key_type": "rsa"}, +) + +config_setting( + name = "owner_key_ecdsa", + flag_values = {":owner_key_type": "ecdsa"}, +) + +config_setting( + name = "test_keys_rsa", + flag_values = { + ":token": "//signing/tokens:local", + ":owner_key_type": "rsa", + }, +) + +config_setting( + name = "test_keys_ecdsa", + flag_values = { + ":token": "//signing/tokens:local", + ":owner_key_type": "ecdsa", + }, +) + filegroup( name = "none_key", srcs = ["skip.bit"], diff --git a/sw/device/silicon_creator/lib/ownership/keys/dummy/app_prod_rsa_3072_exp_f4.der b/sw/device/silicon_creator/lib/ownership/keys/dummy/app_prod_rsa_3072_exp_f4.der deleted file mode 100644 index a41d54d309f0f..0000000000000 Binary files a/sw/device/silicon_creator/lib/ownership/keys/dummy/app_prod_rsa_3072_exp_f4.der and /dev/null differ diff --git a/sw/device/silicon_creator/lib/ownership/keys/dummy/app_prod_rsa_3072_exp_f4.pub.der b/sw/device/silicon_creator/lib/ownership/keys/dummy/app_prod_rsa_3072_exp_f4.pub.der deleted file mode 100644 index cfea71681c78e..0000000000000 Binary files a/sw/device/silicon_creator/lib/ownership/keys/dummy/app_prod_rsa_3072_exp_f4.pub.der and /dev/null differ diff --git a/sw/device/silicon_creator/lib/ownership/test_owner.c b/sw/device/silicon_creator/lib/ownership/test_owner.c index ff0399bc0eb55..da764a4fdfb4b 100644 --- a/sw/device/silicon_creator/lib/ownership/test_owner.c +++ b/sw/device/silicon_creator/lib/ownership/test_owner.c @@ -132,13 +132,6 @@ rom_error_t sku_creator_owner_init(boot_data_t *bootdata, ownership_seal_page(/*page=*/0); memcpy(&owner_page[1], &owner_page[0], sizeof(owner_page[0])); - RETURN_IF_ERROR(owner_block_parse(&owner_page[0], config, keyring)); - RETURN_IF_ERROR(owner_block_flash_apply(config->flash, kBootSlotA, - bootdata->primary_bl0_slot)); - RETURN_IF_ERROR(owner_block_flash_apply(config->flash, kBootSlotB, - bootdata->primary_bl0_slot)); - RETURN_IF_ERROR(owner_block_info_apply(config->info)); - // Since this module should only get linked in to FPGA builds, we can simply // thunk the ownership state to LockedOwner. bootdata->ownership_state = kOwnershipStateLockedOwner; @@ -151,13 +144,6 @@ rom_error_t sku_creator_owner_init(boot_data_t *bootdata, &owner_page[0])); owner_page_valid[0] = kOwnerPageStatusSealed; - OT_DISCARD(flash_ctrl_info_erase(&kFlashCtrlInfoPageOwnerSlot1, - kFlashCtrlEraseTypePage)); - OT_DISCARD(flash_ctrl_info_write(&kFlashCtrlInfoPageOwnerSlot1, 0, - sizeof(owner_page[0]) / sizeof(uint32_t), - &owner_page[0])); - owner_page_valid[1] = kOwnerPageStatusSealed; - OT_DISCARD(boot_data_write(bootdata)); dbg_printf("sku_creator_owner_init: saved to flash\r\n"); return kErrorOk; diff --git a/sw/device/silicon_creator/rom_ext/defs.bzl b/sw/device/silicon_creator/rom_ext/defs.bzl index 464c57ea73bca..51ec98c05b58d 100644 --- a/sw/device/silicon_creator/rom_ext/defs.bzl +++ b/sw/device/silicon_creator/rom_ext/defs.bzl @@ -10,3 +10,9 @@ ROM_EXT_VERSION = struct( MINOR = "1", SECURITY = "0", ) + +SLOTS = [ + "a", + "b", + "virtual", +] diff --git a/sw/device/silicon_creator/rom_ext/rescue.c b/sw/device/silicon_creator/rom_ext/rescue.c index 2931b8f69c51d..1f3a1508d3397 100644 --- a/sw/device/silicon_creator/rom_ext/rescue.c +++ b/sw/device/silicon_creator/rom_ext/rescue.c @@ -110,10 +110,37 @@ static void change_speed(void) { } } +#ifdef ROM_EXT_KLOBBER_ALLOWED +// In order to facilitate debuging and manual test flows for ownerhsip transfer, +// we allow the owner pages to be erased if and only if the chip is in the DEV +// lifecycle state AND the ROM_EXT was specifically built to allow owner erase. +// +// In the general case, the `KLBR` command does not exist. It can only be +// enabled by silicon_creator and only for DEV chips. +static void ownership_erase(void) { + lifecycle_state_t lc_state = lifecycle_state_get(); + if (lc_state == kLcStateDev) { + OT_DISCARD(flash_ctrl_info_erase(&kFlashCtrlInfoPageOwnerSlot0, + kFlashCtrlEraseTypePage)); + OT_DISCARD(flash_ctrl_info_erase(&kFlashCtrlInfoPageOwnerSlot1, + kFlashCtrlEraseTypePage)); + dbg_printf("ok: erased owner blocks\r\n"); + } else { + dbg_printf("error: erase not allowed in state %x\r\n", lc_state); + } +} +#endif + static void validate_mode(uint32_t mode, rescue_state_t *state, boot_data_t *bootdata) { dbg_printf("\r\nmode: %C\r\n", bitfield_byteswap32(mode)); hardened_bool_t allow = owner_rescue_command_allowed(state->config, mode); +#ifdef ROM_EXT_KLOBBER_ALLOWED + if (mode == kRescueModeKlobber) { + ownership_erase(); + return; + } +#endif if (allow == kHardenedBoolTrue) { switch (mode) { case kRescueModeBaud: diff --git a/sw/device/silicon_creator/rom_ext/rescue.h b/sw/device/silicon_creator/rom_ext/rescue.h index 1d94ebf2e865c..0aa5c4d758148 100644 --- a/sw/device/silicon_creator/rom_ext/rescue.h +++ b/sw/device/silicon_creator/rom_ext/rescue.h @@ -28,6 +28,8 @@ typedef enum { kRescueModeBootSvcRsp = 0x42525350, /** `BREQ` */ kRescueModeBootSvcReq = 0x42524551, + /** `KLBR` */ + kRescueModeKlobber = 0x4b4c4252, /** `OWNR` */ kRescueModeOwnerBlock = 0x4f574e52, /** `OPG0` */ diff --git a/sw/device/silicon_creator/rom_ext/sival/BUILD b/sw/device/silicon_creator/rom_ext/sival/BUILD index 0f954c41053dc..00d831a5b3040 100644 --- a/sw/device/silicon_creator/rom_ext/sival/BUILD +++ b/sw/device/silicon_creator/rom_ext/sival/BUILD @@ -15,6 +15,7 @@ load( "//sw/device/silicon_creator/imm_rom_ext:defs.bzl", "SLOT_A_IMM_ROM_EXT_SECTIONS", "SLOT_B_IMM_ROM_EXT_SECTIONS", + "SLOT_VIRTUAL_IMM_ROM_EXT_SECTIONS", ) package(default_visibility = ["//visibility:public"]) @@ -26,6 +27,12 @@ LINK_ORDER = [ "$(location //sw/device/lib/crt)", ] +SLOTS = { + "a": SLOT_A_IMM_ROM_EXT_SECTIONS, + "b": SLOT_B_IMM_ROM_EXT_SECTIONS, + "virtual": SLOT_VIRTUAL_IMM_ROM_EXT_SECTIONS, +} + manifest(d = { "name": "manifest_sival", "identifier": hex(CONST.ROM_EXT), @@ -40,110 +47,68 @@ manifest(d = { # You can manually create such a bitstream with: # # bazel build //hw/bitstream/universal:splice --//hw/bitstream/universal:env=//hw/top_earlgrey:fpga_cw310_sival -opentitan_binary( - name = "rom_ext_fake_prod_signed_slot_a", - ecdsa_key = {"//sw/device/silicon_creator/rom/keys/fake/ecdsa:prod_key_0_ecdsa_p256": "prod_key_0"}, - exec_env = [ - "//hw/top_earlgrey:silicon_creator", - "//hw/top_earlgrey:fpga_cw310", - "//hw/top_earlgrey:fpga_cw340", - "//hw/top_earlgrey:sim_dv_base", - "//hw/top_earlgrey:sim_verilator_base", - ], - extra_bazel_features = [ - "minsize", - "use_lld", - ], - immutable_rom_ext_sections = SLOT_A_IMM_ROM_EXT_SECTIONS["main"], - linker_script = "//sw/device/silicon_creator/rom_ext:ld_slot_a", - linkopts = LINK_ORDER, - manifest = ":manifest_sival", - # TODO(#26060): Temporarily disable SPX signing of ROM_EXT. - #spx_key = {"//sw/device/silicon_creator/rom/keys/fake/spx:prod_key_0_spx": "prod_key_0"}, - deps = [ - "//sw/device/lib/crt", - "//sw/device/silicon_creator/lib:manifest_def", - "//sw/device/silicon_creator/rom_ext", - "//sw/device/silicon_creator/rom_ext/sival/keys", - ], -) - -opentitan_binary( - name = "rom_ext_fake_prod_signed_slot_b", - ecdsa_key = {"//sw/device/silicon_creator/rom/keys/fake/ecdsa:prod_key_0_ecdsa_p256": "prod_key_0"}, - exec_env = [ - "//hw/top_earlgrey:silicon_creator", - "//hw/top_earlgrey:fpga_cw310", - "//hw/top_earlgrey:fpga_cw340", - "//hw/top_earlgrey:sim_dv_base", - "//hw/top_earlgrey:sim_verilator_base", - ], - extra_bazel_features = [ - "minsize", - "use_lld", - ], - immutable_rom_ext_sections = SLOT_B_IMM_ROM_EXT_SECTIONS["main"], - linker_script = "//sw/device/silicon_creator/rom_ext:ld_slot_b", - linkopts = LINK_ORDER, - manifest = ":manifest_sival", - # TODO(#26060): Temporarily disable SPX signing of ROM_EXT. - #spx_key = {"//sw/device/silicon_creator/rom/keys/fake/spx:prod_key_0_spx": "prod_key_0"}, - deps = [ - "//sw/device/lib/crt", - "//sw/device/silicon_creator/lib:manifest_def", - "//sw/device/silicon_creator/rom_ext", - "//sw/device/silicon_creator/rom_ext/sival/keys", - ], -) - -opentitan_binary( - name = "rom_ext_real_prod_signed_slot_a", - exec_env = [ - "//hw/top_earlgrey:silicon_creator", - "//hw/top_earlgrey:fpga_cw310", - ], - extra_bazel_features = [ - "minsize", - "use_lld", - ], - immutable_rom_ext_sections = SLOT_A_IMM_ROM_EXT_SECTIONS["main"], - linker_script = "//sw/device/silicon_creator/rom_ext:ld_slot_a", - linkopts = LINK_ORDER, - deps = [ - "//sw/device/lib/crt", - "//sw/device/silicon_creator/lib:manifest_def", - "//sw/device/silicon_creator/rom_ext", - "//sw/device/silicon_creator/rom_ext/sival/keys", - ], -) +[ + opentitan_binary( + name = "rom_ext_fake_prod_signed_slot_{}".format(slot), + ecdsa_key = {"//sw/device/silicon_creator/rom/keys/fake/ecdsa:prod_key_0_ecdsa_p256": "prod_key_0"}, + exec_env = [ + "//hw/top_earlgrey:silicon_creator", + "//hw/top_earlgrey:fpga_cw310", + "//hw/top_earlgrey:fpga_cw340", + "//hw/top_earlgrey:sim_dv_base", + "//hw/top_earlgrey:sim_verilator_base", + ], + extra_bazel_features = [ + "minsize", + "use_lld", + ], + immutable_rom_ext_sections = imm_sections["main"], + linker_script = "//sw/device/silicon_creator/rom_ext:ld_slot_{}".format(slot), + linkopts = LINK_ORDER, + manifest = ":manifest_sival", + # TODO(#26060): Temporarily disable SPX signing of ROM_EXT. + #spx_key = {"//sw/device/silicon_creator/rom/keys/fake/spx:prod_key_0_spx": "prod_key_0"}, + deps = [ + ":sival_owner", + "//sw/device/lib/crt", + "//sw/device/silicon_creator/lib:manifest_def", + "//sw/device/silicon_creator/rom_ext", + ], + ) + for slot, imm_sections in SLOTS.items() +] -opentitan_binary( - name = "rom_ext_real_prod_signed_slot_b", - exec_env = [ - "//hw/top_earlgrey:silicon_creator", - "//hw/top_earlgrey:fpga_cw310", - ], - extra_bazel_features = [ - "minsize", - "use_lld", - ], - immutable_rom_ext_sections = SLOT_B_IMM_ROM_EXT_SECTIONS["main"], - linker_script = "//sw/device/silicon_creator/rom_ext:ld_slot_b", - linkopts = LINK_ORDER, - deps = [ - "//sw/device/lib/crt", - "//sw/device/silicon_creator/lib:manifest_def", - "//sw/device/silicon_creator/rom_ext", - "//sw/device/silicon_creator/rom_ext/sival/keys", - ], -) +[ + opentitan_binary( + name = "rom_ext_real_prod_signed_slot_{}".format(slot), + exec_env = [ + "//hw/top_earlgrey:silicon_creator", + "//hw/top_earlgrey:fpga_cw310", + "//hw/top_earlgrey:fpga_cw340", + ], + extra_bazel_features = [ + "minsize", + "use_lld", + ], + immutable_rom_ext_sections = imm_sections["main"], + linker_script = "//sw/device/silicon_creator/rom_ext:ld_slot_{}".format(slot), + linkopts = LINK_ORDER, + deps = [ + ":sival_owner", + "//sw/device/lib/crt", + "//sw/device/silicon_creator/lib:manifest_def", + "//sw/device/silicon_creator/rom_ext", + ], + ) + for slot, imm_sections in SLOTS.items() +] offline_presigning_artifacts( name = "presigning", testonly = True, srcs = [ - ":rom_ext_real_prod_signed_slot_a", - ":rom_ext_real_prod_signed_slot_b", + ":rom_ext_real_prod_signed_slot_{}".format(slot) + for slot in SLOTS ], ecdsa_key = { "//sw/device/silicon_creator/rom/keys/fake/ecdsa:prod_key_0_ecdsa_p256": "prod_key_0_ecdsa_p256", @@ -171,3 +136,17 @@ offline_signature_attach( ], tags = ["manual"], ) + +cc_library( + name = "sival_owner", + srcs = ["sival_owner.c"], + deps = [ + "//sw/device/silicon_creator/lib:boot_data", + "//sw/device/silicon_creator/lib/drivers:flash_ctrl", + "//sw/device/silicon_creator/lib/ownership", + "//sw/device/silicon_creator/lib/ownership:datatypes", + "//sw/device/silicon_creator/lib/ownership:owner_block", + "//sw/device/silicon_creator/rom_ext/sival/keys:includes", + ], + alwayslink = True, +) diff --git a/sw/device/silicon_creator/rom_ext/sival/keys/BUILD b/sw/device/silicon_creator/rom_ext/sival/keys/BUILD index 1256d8eac5a8d..5d6ab21332a75 100644 --- a/sw/device/silicon_creator/rom_ext/sival/keys/BUILD +++ b/sw/device/silicon_creator/rom_ext/sival/keys/BUILD @@ -6,6 +6,19 @@ load("//rules:signing.bzl", "keyset") package(default_visibility = ["//visibility:public"]) +cc_library( + name = "includes", + hdrs = [ + "appkey_dev_0.h", + "appkey_prod_0.h", + "appkey_test_0.h", + "earlgrey_z0_sival_1.h", + "ownership_activate_key.h", + "ownership_owner_key.h", + "ownership_unlock_key.h", + ], +) + cc_library( name = "keys", srcs = [ @@ -49,6 +62,9 @@ keyset( build_setting_default = "", keys = { "earlgrey_z0_sival_1.der": "earlgrey_z0_sival_1", + "appkey_dev_0.der": "appkey_dev_0", + "appkey_prod_0.der": "appkey_prod_0", + "appkey_test_0.der": "appkey_test_0", }, profile = "earlgrey_z0_sival", tool = "//signing:token", diff --git a/sw/device/silicon_creator/rom_ext/sival/keys/README.md b/sw/device/silicon_creator/rom_ext/sival/keys/README.md new file mode 100644 index 0000000000000..6bcaa37bbd0f7 --- /dev/null +++ b/sw/device/silicon_creator/rom_ext/sival/keys/README.md @@ -0,0 +1,41 @@ +# SiVAL owner and application keys + +The keys in this directory are the owner and application keys for the SiVAL owner. +The private components of these keys are stored in CloudKMS in the `ot-earlgrey-z0-sival` keyring. + +These keys were generated using the `gcloud` command line tool: + +```bash +KEYS=( + appkey_dev_0 + appkey_prod_0 + appkey_test_0 + ownership_owner_key + ownership_activate_key + ownership_unlock_key +) + +for KEY in ${KEYS[@]}; do + gcloud kms keys create ${KEY} \ + --keyring ot-earlgrey-z0-sival \ + --location us-west1 \ + --purpose "asymmetric-signing" \ + --default-algorithm "ec-sign-p256-sha256" \ + --protection-level hsm +done +``` + +The keys were then exported from CloudKMS using `hsmtool` and converted to C headers with `opentitantool`: + +```bash +for KEY in ${KEYS[@]}; do + hsmtool --token ot-earlgrey-z0-sival \ + ecdsa export \ + -l ${KEY} \ + -f der \ + sw/device/silicon_creator/rom_ext/sival/keys/${KEY}.der + + opentitantool ecdsa key export \ + sw/device/silicon_creator/rom_ext/sival/keys/${KEY}.der +done +``` diff --git a/sw/device/silicon_creator/rom_ext/sival/keys/appkey_dev_0.der b/sw/device/silicon_creator/rom_ext/sival/keys/appkey_dev_0.der new file mode 100644 index 0000000000000..984231b2397db Binary files /dev/null and b/sw/device/silicon_creator/rom_ext/sival/keys/appkey_dev_0.der differ diff --git a/sw/device/silicon_creator/rom_ext/sival/keys/appkey_dev_0.h b/sw/device/silicon_creator/rom_ext/sival/keys/appkey_dev_0.h new file mode 100644 index 0000000000000..a11f5fb01574b --- /dev/null +++ b/sw/device/silicon_creator/rom_ext/sival/keys/appkey_dev_0.h @@ -0,0 +1,16 @@ +// 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_SIVAL_KEYS_APPKEY_DEV_0_H_ +#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_SIVAL_KEYS_APPKEY_DEV_0_H_ + +#define APPKEY_DEV_0 \ + { \ + .x = {0x471b4b2c, 0xb41fed57, 0x99b552c6, 0x9015d9ed, \ + 0x825f0c70, 0x068d88e5, 0x69993ee3, 0x9dfab76b}, \ + .y = {0x9c7a9b58, 0xd1fdf9e5, 0x39fe85eb, 0x8f6215f7, \ + 0x9e52b774, 0xd61c01d0, 0x400a4da6, 0x6ffe324e}, \ + } + +#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_SIVAL_KEYS_APPKEY_DEV_0_H_ diff --git a/sw/device/silicon_creator/rom_ext/sival/keys/appkey_prod_0.der b/sw/device/silicon_creator/rom_ext/sival/keys/appkey_prod_0.der new file mode 100644 index 0000000000000..58d139ce59b92 Binary files /dev/null and b/sw/device/silicon_creator/rom_ext/sival/keys/appkey_prod_0.der differ diff --git a/sw/device/silicon_creator/rom_ext/sival/keys/appkey_prod_0.h b/sw/device/silicon_creator/rom_ext/sival/keys/appkey_prod_0.h new file mode 100644 index 0000000000000..6a75f43d0b79e --- /dev/null +++ b/sw/device/silicon_creator/rom_ext/sival/keys/appkey_prod_0.h @@ -0,0 +1,16 @@ +// 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_SIVAL_KEYS_APPKEY_PROD_0_H_ +#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_SIVAL_KEYS_APPKEY_PROD_0_H_ + +#define APPKEY_PROD_0 \ + { \ + .x = {0x03340a84, 0x9aed01b4, 0x017cbd69, 0xdb2924af, \ + 0xfa6ea854, 0xcd804134, 0xb5668540, 0x5305de4b}, \ + .y = {0x135958d2, 0x0526bfdd, 0xc5574602, 0xc82e3dff, \ + 0x861defab, 0xf7c94dea, 0x657a1eb9, 0x70ae605c}, \ + } + +#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_SIVAL_KEYS_APPKEY_PROD_0_H_ diff --git a/sw/device/silicon_creator/rom_ext/sival/keys/appkey_test_0.der b/sw/device/silicon_creator/rom_ext/sival/keys/appkey_test_0.der new file mode 100644 index 0000000000000..09f435575c0f3 Binary files /dev/null and b/sw/device/silicon_creator/rom_ext/sival/keys/appkey_test_0.der differ diff --git a/sw/device/silicon_creator/rom_ext/sival/keys/appkey_test_0.h b/sw/device/silicon_creator/rom_ext/sival/keys/appkey_test_0.h new file mode 100644 index 0000000000000..67a57218efae2 --- /dev/null +++ b/sw/device/silicon_creator/rom_ext/sival/keys/appkey_test_0.h @@ -0,0 +1,16 @@ +// 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_SIVAL_KEYS_APPKEY_TEST_0_H_ +#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_SIVAL_KEYS_APPKEY_TEST_0_H_ + +#define APPKEY_TEST_0 \ + { \ + .x = {0x644e94f3, 0x74075e81, 0x9913e83f, 0xc77ae6d3, \ + 0x00476998, 0x98f54835, 0x89478240, 0x98197460}, \ + .y = {0x4812eddd, 0x93796b25, 0x6a2db917, 0x6e38f40d, \ + 0xd414a8b5, 0x8fe3ebdb, 0x1bc1841c, 0xa040b4f5}, \ + } + +#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_SIVAL_KEYS_APPKEY_TEST_0_H_ diff --git a/sw/device/silicon_creator/rom_ext/sival/keys/ownership_activate_key.der b/sw/device/silicon_creator/rom_ext/sival/keys/ownership_activate_key.der new file mode 100644 index 0000000000000..4a8f3a9a595a6 Binary files /dev/null and b/sw/device/silicon_creator/rom_ext/sival/keys/ownership_activate_key.der differ diff --git a/sw/device/silicon_creator/rom_ext/sival/keys/ownership_activate_key.h b/sw/device/silicon_creator/rom_ext/sival/keys/ownership_activate_key.h new file mode 100644 index 0000000000000..deaf1440bb33e --- /dev/null +++ b/sw/device/silicon_creator/rom_ext/sival/keys/ownership_activate_key.h @@ -0,0 +1,15 @@ +// 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_SIVAL_KEYS_OWNERSHIP_ACTIVATE_KEY_H_ +#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_SIVAL_KEYS_OWNERSHIP_ACTIVATE_KEY_H_ + +#define OWNERSHIP_ACTIVATE_KEY \ + { \ + 0x722fcac6, 0x11f2207a, 0xa406b0ca, 0x6f9d8ccb, 0x36034b0a, 0x5938db28, \ + 0x5e134f00, 0x8fca8f01, 0x65028265, 0x87c93df1, 0xcd12dd2e, \ + 0x2aefda74, 0x353dadbb, 0x576cc96a, 0x28e5699a, 0x34b6b35c, \ + } + +#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_SIVAL_KEYS_OWNERSHIP_ACTIVATE_KEY_H_ diff --git a/sw/device/silicon_creator/rom_ext/sival/keys/ownership_owner_key.der b/sw/device/silicon_creator/rom_ext/sival/keys/ownership_owner_key.der new file mode 100644 index 0000000000000..9633bb732874b Binary files /dev/null and b/sw/device/silicon_creator/rom_ext/sival/keys/ownership_owner_key.der differ diff --git a/sw/device/silicon_creator/rom_ext/sival/keys/ownership_owner_key.h b/sw/device/silicon_creator/rom_ext/sival/keys/ownership_owner_key.h new file mode 100644 index 0000000000000..8a79fae26cfa8 --- /dev/null +++ b/sw/device/silicon_creator/rom_ext/sival/keys/ownership_owner_key.h @@ -0,0 +1,15 @@ +// 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_SIVAL_KEYS_OWNERSHIP_OWNER_KEY_H_ +#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_SIVAL_KEYS_OWNERSHIP_OWNER_KEY_H_ + +#define OWNERSHIP_OWNER_KEY \ + { \ + 0x25d3e660, 0x6b9401bb, 0x2d1f5aee, 0x875afd25, 0xaaec4927, 0xda4db14f, \ + 0x5d8589d7, 0xa1d16920, 0x3e1c985f, 0x2382ab29, 0x8691f8a4, \ + 0xc23a8311, 0x1dc2bd4f, 0x52faf2a0, 0xecbd0854, 0x4c80901b, \ + } + +#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_SIVAL_KEYS_OWNERSHIP_OWNER_KEY_H_ diff --git a/sw/device/silicon_creator/rom_ext/sival/keys/ownership_unlock_key.der b/sw/device/silicon_creator/rom_ext/sival/keys/ownership_unlock_key.der new file mode 100644 index 0000000000000..1878ca686c990 Binary files /dev/null and b/sw/device/silicon_creator/rom_ext/sival/keys/ownership_unlock_key.der differ diff --git a/sw/device/silicon_creator/rom_ext/sival/keys/ownership_unlock_key.h b/sw/device/silicon_creator/rom_ext/sival/keys/ownership_unlock_key.h new file mode 100644 index 0000000000000..f442418ace36d --- /dev/null +++ b/sw/device/silicon_creator/rom_ext/sival/keys/ownership_unlock_key.h @@ -0,0 +1,15 @@ +// 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_SIVAL_KEYS_OWNERSHIP_UNLOCK_KEY_H_ +#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_SIVAL_KEYS_OWNERSHIP_UNLOCK_KEY_H_ + +#define OWNERSHIP_UNLOCK_KEY \ + { \ + 0xbba01e3e, 0x8fd4e130, 0x141168e0, 0x46bd37f7, 0x93998070, 0x455abb63, \ + 0xb3a97219, 0x3dc97b59, 0x37a94aba, 0x810a3baa, 0x83e294a8, \ + 0xc414ec9e, 0x0b6dc453, 0xd7295f00, 0x9c21ea58, 0x3c0788fa, \ + } + +#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_ROM_EXT_SIVAL_KEYS_OWNERSHIP_UNLOCK_KEY_H_ diff --git a/sw/device/silicon_creator/rom_ext/sival/sival_owner.c b/sw/device/silicon_creator/rom_ext/sival/sival_owner.c new file mode 100644 index 0000000000000..c292144e77cf0 --- /dev/null +++ b/sw/device/silicon_creator/rom_ext/sival/sival_owner.c @@ -0,0 +1,150 @@ +// 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/base/hardened_memory.h" +#include "sw/device/lib/base/macros.h" +#include "sw/device/lib/base/memory.h" +#include "sw/device/silicon_creator/lib/dbg_print.h" +#include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h" +#include "sw/device/silicon_creator/lib/error.h" +#include "sw/device/silicon_creator/lib/ownership/owner_block.h" +#include "sw/device/silicon_creator/lib/ownership/ownership.h" +#include "sw/device/silicon_creator/lib/ownership/ownership_key.h" +#include "sw/device/silicon_creator/rom_ext/sival/keys/appkey_dev_0.h" +#include "sw/device/silicon_creator/rom_ext/sival/keys/appkey_prod_0.h" +#include "sw/device/silicon_creator/rom_ext/sival/keys/appkey_test_0.h" +#include "sw/device/silicon_creator/rom_ext/sival/keys/ownership_activate_key.h" +#include "sw/device/silicon_creator/rom_ext/sival/keys/ownership_owner_key.h" +#include "sw/device/silicon_creator/rom_ext/sival/keys/ownership_unlock_key.h" + +/* + * This module overrides the weak `sku_creator_owner_init` symbol in + * ownership.c, thus allowing existing sival chips without an ownership + * configuration to receive their ownership config simply installing the latest + * ROM_EXT. + */ + +#define SIVAL_OWNER_CONFIG_VERSION 1 + +rom_error_t sku_creator_owner_init(boot_data_t *bootdata, + owner_config_t *config, + owner_application_keyring_t *keyring) { + owner_key_t owner = (owner_key_t){ + // Although this is an ECDSA key, we initialize the `raw` member of the + // union to zero-initialize the unused space. + .raw = OWNERSHIP_OWNER_KEY}; + ownership_state_t state = bootdata->ownership_state; + + if (state == kOwnershipStateUnlockedSelf || + state == kOwnershipStateUnlockedAny || + state == kOwnershipStateUnlockedEndorsed) { + // Nothing to do when in an unlocked state. + return kErrorOk; + } else if (state == kOwnershipStateLockedOwner) { + if (hardened_memeq(owner.raw, owner_page[0].owner_key.raw, + ARRAYSIZE(owner.raw)) != kHardenedBoolTrue || + SIVAL_OWNER_CONFIG_VERSION <= owner_page[0].config_version) { + // Different owner or already newest config version; nothing to do. + return kErrorOk; + } + } else { + // State is an unknown value, which is the same as kOwnershipStateRecovery. + // We'll not return, thus allowing the owner config below to be programmed + // into flash. + } + + memset(&owner_page[0], 0, sizeof(owner_page[0])); + owner_page[0].header.tag = kTlvTagOwner; + owner_page[0].header.length = 2048; + owner_page[0].struct_version = 0; + owner_page[0].sram_exec_mode = kOwnerSramExecModeDisabledLocked; + owner_page[0].ownership_key_alg = kOwnershipKeyAlgEcdsaP256; + owner_page[0].config_version = SIVAL_OWNER_CONFIG_VERSION; + owner_page[0].min_security_version_bl0 = UINT32_MAX; + owner_page[0].owner_key = owner; + owner_page[0].activate_key = (owner_key_t){ + // Although this is an ECDSA key, we initialize the `raw` member of the + // union to zero-initialize the unused space. + .raw = OWNERSHIP_ACTIVATE_KEY}; + owner_page[0].unlock_key = (owner_key_t){ + // Although this is an ECDSA key, we initialize the `raw` member of the + // union to zero-initialize the unused space. + .raw = OWNERSHIP_UNLOCK_KEY}; + + owner_application_key_t *app = (owner_application_key_t *)owner_page[0].data; + *app = (owner_application_key_t){ + .header = + { + .tag = kTlvTagApplicationKey, + .length = kTlvLenApplicationKeyEcdsa, + }, + .key_alg = kOwnershipKeyAlgEcdsaP256, + .key_domain = kOwnerAppDomainTest, + .key_diversifier = {0}, + .usage_constraint = 0, + .data = + { + .ecdsa = APPKEY_TEST_0, + }, + }; + + app = (owner_application_key_t *)((uintptr_t)app + app->header.length); + *app = (owner_application_key_t){ + .header = + { + .tag = kTlvTagApplicationKey, + .length = kTlvLenApplicationKeyEcdsa, + }, + .key_alg = kOwnershipKeyAlgEcdsaP256, + .key_domain = kOwnerAppDomainProd, + .key_diversifier = {0}, + .usage_constraint = 0, + .data = + { + .ecdsa = APPKEY_PROD_0, + }, + }; + + app = (owner_application_key_t *)((uintptr_t)app + app->header.length); + *app = (owner_application_key_t){ + .header = + { + .tag = kTlvTagApplicationKey, + .length = kTlvLenApplicationKeyEcdsa, + }, + .key_alg = kOwnershipKeyAlgEcdsaP256, + .key_domain = kOwnerAppDomainDev, + .key_diversifier = {0}, + .usage_constraint = 0, + .data = + { + .ecdsa = APPKEY_DEV_0, + }, + }; + + // Fill the remainder of the data segment with the end tag (0x5a5a5a5a). + app = (owner_application_key_t *)((uintptr_t)app + app->header.length); + size_t len = (uintptr_t)(owner_page[0].data + sizeof(owner_page[0].data)) - + (uintptr_t)app; + memset(app, 0x5a, len); + + ownership_seal_page(/*page=*/0); + memcpy(&owner_page[1], &owner_page[0], sizeof(owner_page[0])); + + // Since this code should only execute when the ownership state is unknown, we + // can thunk the ownership state to LockedOwner. + bootdata->ownership_state = kOwnershipStateLockedOwner; + + // Write the configuration to page 0. + OT_DISCARD(flash_ctrl_info_erase(&kFlashCtrlInfoPageOwnerSlot0, + kFlashCtrlEraseTypePage)); + OT_DISCARD(flash_ctrl_info_write(&kFlashCtrlInfoPageOwnerSlot0, 0, + sizeof(owner_page[0]) / sizeof(uint32_t), + &owner_page[0])); + owner_page_valid[0] = kOwnerPageStatusSealed; + + OT_DISCARD(boot_data_write(bootdata)); + dbg_printf("sku_creator_owner_init: saved to flash\r\n"); + return kErrorOk; +} diff --git a/sw/host/opentitanlib/src/rescue/serial.rs b/sw/host/opentitanlib/src/rescue/serial.rs index b126018a91911..82388645fef28 100644 --- a/sw/host/opentitanlib/src/rescue/serial.rs +++ b/sw/host/opentitanlib/src/rescue/serial.rs @@ -34,6 +34,7 @@ impl RescueSerial { pub const GET_OWNER_PAGE0: [u8; 4] = *b"OPG0"; pub const GET_OWNER_PAGE1: [u8; 4] = *b"OPG1"; pub const OT_ID: [u8; 4] = *b"OTID"; + pub const ERASE_OWNER: [u8; 4] = *b"KLBR"; pub const WAIT: [u8; 4] = *b"WAIT"; const BAUD_115K: [u8; 4] = *b"115K"; @@ -184,4 +185,9 @@ impl RescueSerial { xm.send(&*self.uart, data)?; Ok(()) } + + pub fn erase_owner(&self) -> Result<()> { + self.set_mode(Self::ERASE_OWNER)?; + Ok(()) + } } diff --git a/sw/host/opentitantool/src/command/rescue.rs b/sw/host/opentitantool/src/command/rescue.rs index 34266050dc806..6aec7b1b88b7d 100644 --- a/sw/host/opentitantool/src/command/rescue.rs +++ b/sw/host/opentitantool/src/command/rescue.rs @@ -455,6 +455,39 @@ impl CommandDispatch for GetOwnerConfig { } } +#[derive(Debug, Args)] +pub struct EraseOwner { + #[command(flatten)] + params: UartParams, + #[arg( + long, + default_value_t = true, + action = clap::ArgAction::Set, + help = "Reset the target to enter rescue mode" + )] + reset_target: bool, + #[arg(long, default_value_t = false, help = "Really erase the owner config")] + really: bool, +} + +impl CommandDispatch for EraseOwner { + fn run( + &self, + _context: &dyn Any, + transport: &TransportWrapper, + ) -> Result>> { + if self.really { + let uart = self.params.create(transport)?; + let rescue = RescueSerial::new(uart); + rescue.enter(transport, self.reset_target)?; + rescue.erase_owner()?; + Ok(None) + } else { + Err(anyhow!("The owner may only be erased on DEV lifecycle-state chips with a ROM_EXT configured to permit owner erasing.\n\nUse the `--really` flag to send the command.")) + } + } +} + #[derive(Debug, Subcommand, CommandDispatch)] pub enum BootSvcCommand { Get(GetBootSvc), @@ -467,6 +500,7 @@ pub enum BootSvcCommand { pub enum RescueCommand { #[command(subcommand)] BootSvc(BootSvcCommand), + EraseOwner(EraseOwner), GetBootLog(GetBootLog), GetDeviceId(GetDeviceId), Firmware(Firmware),