Skip to content

Commit 83acb58

Browse files
cfrantzpamaury
authored andcommitted
[rom_ext] Advance the security version if requested
1. Make the ROM_EXT detect the `secver_write` extension in the manifest. If present and the manifest security version is greater than the current boot_data minimum security version, update the value and write boot_data. 2. Add a string flag to the build system that allows the `secver_write` value to be set at build time. 3. Add a test which sequences firmware through a series of ROM_EXTs which advance the security version. Confirm each update and confirm that an older ROM_EXT will no longer execute. Signed-off-by: Chris Frantz <[email protected]> (cherry picked from commit 86dce8a)
1 parent 614edcf commit 83acb58

File tree

7 files changed

+230
-0
lines changed

7 files changed

+230
-0
lines changed

rules/manifest.bzl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,21 @@ def _manifest_impl(ctx):
186186
},
187187
)
188188

189+
secver_write = ctx.attr.secver_write
190+
if secver_write == "none":
191+
# nothing to do
192+
pass
193+
elif secver_write in ("false", "true"):
194+
mf["extension_params"].append(
195+
{
196+
"secver_write": {
197+
"secver_write": json.decode(secver_write),
198+
},
199+
},
200+
)
201+
else:
202+
fail("Unknown value for secver_write:", secver_write)
203+
189204
if ctx.attr.isfb_erase_allowed_policy:
190205
mf["extension_params"].append(
191206
{
@@ -229,6 +244,7 @@ _manifest = rule(
229244
"extensions": attr.string_list(doc = "Names of the manifest extensions as an array of strings"),
230245
"integrator_specific_firmware_binding": attr.string(doc = "Create an Integrator Specific Firmware Block (ISFB) JSON object"),
231246
"isfb_erase_allowed_policy": attr.string(doc = "Create an ISFB Erase Allowed Policy JSON object"),
247+
"secver_write": attr.string(default = "none", values = ["none", "false", "true"], doc = "Add the secver_write extension with the specified value"),
232248
},
233249
)
234250

sw/device/silicon_creator/lib/manifest.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,6 @@ extern rom_error_t manifest_ext_get_spx_key(
4444
extern rom_error_t manifest_ext_get_spx_signature(
4545
const manifest_t *manifest,
4646
const manifest_ext_spx_signature_t **spx_signature);
47+
extern rom_error_t manifest_ext_get_secver_write(
48+
const manifest_t *manifest,
49+
const manifest_ext_secver_write_t **secver_write);

sw/device/silicon_creator/rom_ext/BUILD

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ load(
1313
"ROM_EXT_VERSION",
1414
"SLOTS",
1515
)
16+
load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
1617

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

@@ -21,6 +22,20 @@ filegroup(
2122
srcs = glob(["**/*.md"]),
2223
)
2324

25+
string_flag(
26+
name = "secver_write",
27+
build_setting_default = "false",
28+
values = [
29+
"false",
30+
"true",
31+
],
32+
)
33+
34+
config_setting(
35+
name = "secver_write_true",
36+
flag_values = {":secver_write": "true"},
37+
)
38+
2439
cc_library(
2540
name = "rom_ext_manifest",
2641
srcs = ["rom_ext_manifest.c"],

sw/device/silicon_creator/rom_ext/defs.bzl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
33
# SPDX-License-Identifier: Apache-2.0
44

5+
def secver_write_selection():
6+
"""Return the secver_write value based on the configuration setting."""
7+
return select({
8+
"//sw/device/silicon_creator/rom_ext:secver_write_true": "true",
9+
"//conditions:default": "false",
10+
})
11+
512
# The ROM_EXT version number to encode into the manifest.
613
# NOTE: the version numbers are integers, but have to be encoded as strings
714
# because of how the bazel rule accepts attributes.
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
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+
load("//rules:const.bzl", "CONST", "hex", "hex_digits")
6+
load("//rules:cross_platform.bzl", "dual_cc_library", "dual_inputs")
7+
load("//rules:linker.bzl", "ld_library")
8+
load("//rules:manifest.bzl", "manifest")
9+
load("//rules/opentitan:defs.bzl", "fpga_params", "opentitan_binary", "opentitan_test")
10+
load(
11+
"//sw/device/silicon_creator/rom_ext:defs.bzl",
12+
"ROM_EXT_VARIATIONS",
13+
"ROM_EXT_VERSION",
14+
"SLOTS",
15+
)
16+
17+
package(default_visibility = ["//visibility:public"])
18+
19+
manifest(d = {
20+
"name": "manifest0",
21+
"identifier": hex(CONST.ROM_EXT),
22+
"visibility": ["//visibility:public"],
23+
"version_major": "0",
24+
"version_minor": "0",
25+
"security_version": "0",
26+
"secver_write": "false",
27+
})
28+
29+
manifest(d = {
30+
"name": "manifest1",
31+
"identifier": hex(CONST.ROM_EXT),
32+
"visibility": ["//visibility:public"],
33+
"version_major": "0",
34+
"version_minor": "1",
35+
"security_version": "1",
36+
"secver_write": "true",
37+
})
38+
39+
manifest(d = {
40+
"name": "manifest2",
41+
"identifier": hex(CONST.ROM_EXT),
42+
"visibility": ["//visibility:public"],
43+
"version_major": "0",
44+
"version_minor": "2",
45+
"security_version": "2",
46+
"secver_write": "false",
47+
})
48+
49+
manifest(d = {
50+
"name": "manifest3",
51+
"identifier": hex(CONST.ROM_EXT),
52+
"visibility": ["//visibility:public"],
53+
"version_major": "0",
54+
"version_minor": "3",
55+
"security_version": "3",
56+
"secver_write": "true",
57+
})
58+
59+
_TEST_ROM_EXTS = {
60+
"0": {
61+
"manifest": ":manifest0",
62+
},
63+
"1": {
64+
"manifest": ":manifest1",
65+
},
66+
"2": {
67+
"manifest": ":manifest2",
68+
},
69+
"3": {
70+
"manifest": ":manifest3",
71+
},
72+
}
73+
74+
[
75+
opentitan_binary(
76+
name = "rom_ext_{}".format(name),
77+
testonly = True,
78+
ecdsa_key = {"//sw/device/silicon_creator/rom/keys/fake/ecdsa:prod_key_0_ecdsa_p256": "prod_key_0"},
79+
exec_env = [
80+
"//hw/top_earlgrey:fpga_cw310",
81+
"//hw/top_earlgrey:fpga_cw340",
82+
],
83+
linker_script = "//sw/device/silicon_creator/rom_ext:ld_slot_virtual",
84+
manifest = param["manifest"],
85+
spx_key = {"//sw/device/silicon_creator/rom/keys/fake/spx:prod_key_0_spx": "prod_key_0"},
86+
transitive_features = [
87+
"minsize",
88+
"use_lld",
89+
],
90+
deps = [
91+
"//sw/device/lib/crt",
92+
"//sw/device/silicon_creator/lib:manifest_def",
93+
"//sw/device/silicon_creator/lib/ownership:test_owner",
94+
"//sw/device/silicon_creator/lib/ownership/keys/fake",
95+
"//sw/device/silicon_creator/lib/rescue:rescue_xmodem",
96+
"//sw/device/silicon_creator/rom_ext:rom_ext_dice_x509",
97+
"//sw/device/silicon_creator/rom_ext/imm_section:main_section_dice_x509_slot_virtual",
98+
],
99+
)
100+
for name, param in _TEST_ROM_EXTS.items()
101+
]
102+
103+
opentitan_test(
104+
name = "secver_write_test",
105+
exec_env = {
106+
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
107+
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
108+
},
109+
fpga = fpga_params(
110+
assemble = "{rom_ext}@0 {boot_test}@0x10000",
111+
binaries = {
112+
":boot_test": "boot_test",
113+
":rom_ext_1": "rom_ext1",
114+
":rom_ext_2": "rom_ext2",
115+
":rom_ext_3": "rom_ext3",
116+
},
117+
changes_otp = True,
118+
exit_success = "BFV:{}".format(hex_digits(CONST.BFV.BOOT_POLICY.ROLLBACK)),
119+
rom_ext = ":rom_ext_0",
120+
test_cmd = """
121+
# First, assemble the additional images we'll need for this test.
122+
--exec="image assemble -s 131072 --mirror=false -o fw1.bin {rom_ext1}@0 {boot_test}@0x10000"
123+
--exec="image assemble -s 131072 --mirror=false -o fw2.bin {rom_ext2}@0 {boot_test}@0x10000"
124+
--exec="image assemble -s 131072 --mirror=false -o fw3.bin {rom_ext3}@0 {boot_test}@0x10000"
125+
--exec="transport init"
126+
--exec="fpga clear-bitstream"
127+
--exec="fpga load-bitstream {bitstream}"
128+
129+
# Bootstrap the initial version 0 into SlotA
130+
--exec="bootstrap --clear-uart=true {firmware}"
131+
--exec="console --non-interactive --exit-success='rom_ext_min_sec_ver = 0'"
132+
133+
# Rescue and update to SlotB. We expect to update the secver.
134+
--exec="rescue firmware --raw --slot=SlotB fw1.bin"
135+
--exec="console --non-interactive --exit-success='rom_ext_min_sec_ver = 1'"
136+
137+
# Rescue and update to SlotA. We expect NOT to update the secver.
138+
--exec="rescue firmware --raw --slot=SlotA fw2.bin"
139+
--exec="console --non-interactive --exit-success='rom_ext_min_sec_ver = 1'"
140+
141+
# Rescue and update to SlotB. We expect to update the secver.
142+
--exec="rescue firmware --raw --slot=SlotB fw3.bin"
143+
--exec="console --non-interactive --exit-success='rom_ext_min_sec_ver = 3'"
144+
145+
# Finally, bootstrap back to version 0, which we expect NOT to work.
146+
--exec="bootstrap --clear-uart=true {firmware}"
147+
--exec="console --non-interactive --exit-success='{exit_success}' --timeout=10s"
148+
no-op
149+
""",
150+
),
151+
)
152+
153+
opentitan_binary(
154+
name = "boot_test",
155+
testonly = True,
156+
srcs = ["//sw/device/silicon_creator/rom_ext/e2e/verified_boot:boot_test"],
157+
exec_env = {
158+
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
159+
"//hw/top_earlgrey:fpga_cw340_rom_ext": None,
160+
},
161+
deps = [
162+
"//sw/device/lib/base:status",
163+
"//sw/device/lib/testing/test_framework:ottf_main",
164+
"//sw/device/silicon_creator/lib:boot_log",
165+
"//sw/device/silicon_creator/lib/drivers:retention_sram",
166+
],
167+
)

sw/device/silicon_creator/rom_ext/rom_ext.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,23 @@ static void rom_ext_rescue_lockdown(boot_data_t *boot_data) {
653653
owner_block_info_lockdown(owner_config.info);
654654
}
655655

656+
static rom_error_t rom_ext_advance_secver(boot_data_t *boot_data,
657+
const manifest_t *manifest) {
658+
const manifest_ext_secver_write_t *secver;
659+
rom_error_t error;
660+
error = manifest_ext_get_secver_write(manifest, &secver);
661+
if (error == kErrorOk) {
662+
if (secver->write == kHardenedBoolTrue &&
663+
manifest->security_version > boot_data->min_security_version_rom_ext) {
664+
// If our security version is greater than the minimum security version
665+
// advance the minimum version to our version.
666+
boot_data->min_security_version_rom_ext = manifest->security_version;
667+
return boot_data_write(boot_data);
668+
}
669+
}
670+
return kErrorOk;
671+
}
672+
656673
static rom_error_t rom_ext_start(boot_data_t *boot_data, boot_log_t *boot_log) {
657674
HARDENED_RETURN_IF_ERROR(rom_ext_init(boot_data));
658675
const manifest_t *self = rom_ext_manifest();
@@ -675,6 +692,9 @@ static rom_error_t rom_ext_start(boot_data_t *boot_data, boot_log_t *boot_log) {
675692
dbg_printf("info: imm_section hash unenforced\r\n");
676693
}
677694

695+
// Maybe advance the security version.
696+
HARDENED_RETURN_IF_ERROR(rom_ext_advance_secver(boot_data, self));
697+
678698
// Prepare dice chain builder for CDI_1.
679699
HARDENED_RETURN_IF_ERROR(dice_chain_init());
680700

sw/device/silicon_creator/rom_ext/sival/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ load(
1212
"ROM_EXT_VARIATIONS",
1313
"ROM_EXT_VERSION",
1414
"SLOTS",
15+
"secver_write_selection",
1516
)
1617

1718
package(default_visibility = ["//visibility:public"])
@@ -22,6 +23,7 @@ manifest(d = {
2223
"version_major": ROM_EXT_VERSION.MAJOR,
2324
"version_minor": ROM_EXT_VERSION.MINOR,
2425
"security_version": ROM_EXT_VERSION.SECURITY,
26+
"secver_write": secver_write_selection(),
2527
"visibility": ["//visibility:private"],
2628
})
2729

0 commit comments

Comments
 (0)