Skip to content

Commit cecf48f

Browse files
[test] implement example CDI_1 key use test boilerplate
This adds boilerplate code to test the following scenario: 1. booting owner FW to sign something with the CDI_1 key, 2. booting a different owner FW to ensure the key changes and produces a different signature, and 3. booting the same owner FW in 1 to ensure the same signature in 1 can be reproduced. Signed-off-by: Tim Trippel <[email protected]>
1 parent e97b346 commit cecf48f

File tree

4 files changed

+195
-0
lines changed

4 files changed

+195
-0
lines changed

sw/device/silicon_creator/rom_ext/e2e/dice_chain/BUILD

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,3 +274,65 @@ DEBUG_MODE_TESTCASES = [
274274
for testcase in DEBUG_MODE_TESTCASES
275275
for variation in ROM_EXT_VARIATIONS.keys()
276276
]
277+
278+
[
279+
opentitan_binary(
280+
name = "cdi1_key_sign_for_assemble_{}".format(i),
281+
testonly = True,
282+
srcs = ["cdi1_key_sign_test.c"],
283+
exec_env = [
284+
"//hw/top_earlgrey:fpga_cw310_rom_ext",
285+
"//hw/top_earlgrey:fpga_cw340_rom_ext",
286+
],
287+
linker_script = "//sw/device/lib/testing/test_framework:ottf_ld_silicon_owner_slot_a",
288+
local_defines = [
289+
"EMPTY_TEST_MSG=\"Test Owner FW - {}.\"".format(i if i < 2 else 0),
290+
],
291+
manifest = ":owner_manifest",
292+
deps = [
293+
"//sw/device/lib/base:status",
294+
"//sw/device/lib/runtime:log",
295+
"//sw/device/lib/testing/test_framework:check",
296+
"//sw/device/lib/testing/test_framework:ottf_main",
297+
],
298+
)
299+
for i in range(3)
300+
]
301+
302+
[
303+
opentitan_binary_assemble(
304+
name = "cdi1_key_sign_rom_ext_owner_bundle_{}".format(i),
305+
testonly = True,
306+
bins = {
307+
"//sw/device/silicon_creator/rom_ext:rom_ext_dice_x509_slot_a": SLOTS["a"],
308+
":cdi1_key_sign_for_assemble_{}".format(i): OWNER_SLOTS["a"],
309+
},
310+
exec_env = [
311+
"//hw/top_earlgrey:fpga_cw310_rom_with_fake_keys",
312+
"//hw/top_earlgrey:fpga_cw340_rom_with_fake_keys",
313+
],
314+
)
315+
for i in range(3)
316+
]
317+
318+
opentitan_test(
319+
name = "cdi1_key_sign_test",
320+
exec_env = {
321+
"//hw/top_earlgrey:fpga_cw310_rom_with_fake_keys": None,
322+
"//hw/top_earlgrey:fpga_cw340_rom_with_fake_keys": None,
323+
},
324+
fpga = fpga_params(
325+
binaries = {
326+
":cdi1_key_sign_rom_ext_owner_bundle_0": "firmware",
327+
":cdi1_key_sign_rom_ext_owner_bundle_1": "second",
328+
":cdi1_key_sign_rom_ext_owner_bundle_2": "third",
329+
},
330+
otp = "//sw/device/silicon_creator/rom_ext/e2e:otp_img_secret2_locked_rma",
331+
test_cmd = """
332+
--bootstrap={firmware}
333+
--second-bootstrap={second}
334+
--third-bootstrap={third}
335+
""",
336+
test_harness = "//sw/host/tests/rom_ext/cdi1_key_sign",
337+
),
338+
)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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/base/status.h"
6+
#include "sw/device/lib/runtime/log.h"
7+
#include "sw/device/lib/testing/test_framework/check.h"
8+
#include "sw/device/lib/testing/test_framework/ottf_main.h"
9+
#include "sw/device/silicon_creator/lib/manifest_def.h"
10+
11+
OTTF_DEFINE_TEST_CONFIG();
12+
13+
bool test_main(void) {
14+
#ifdef EMPTY_TEST_MSG
15+
LOG_INFO(EMPTY_TEST_MSG);
16+
#endif
17+
18+
// TODO: Insert signing operation with CDI_1 key.
19+
20+
return true;
21+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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_rust//rust:defs.bzl", "rust_binary")
6+
7+
package(default_visibility = ["//visibility:public"])
8+
9+
rust_binary(
10+
name = "cdi1_key_sign",
11+
srcs = ["src/main.rs"],
12+
deps = [
13+
"//sw/host/opentitanlib",
14+
"@crate_index//:anyhow",
15+
"@crate_index//:clap",
16+
"@crate_index//:humantime",
17+
"@crate_index//:log",
18+
"@crate_index//:regex",
19+
],
20+
)
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
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+
use std::path::PathBuf;
6+
use std::time::Duration;
7+
8+
use opentitanlib::test_utils::init::InitializeTest;
9+
use opentitanlib::uart::console::{ExitStatus, UartConsole};
10+
11+
use anyhow::{anyhow, Context, Result};
12+
use clap::Parser;
13+
use regex::Regex;
14+
15+
/// CLI args for this test.
16+
#[derive(Debug, Parser)]
17+
struct Opts {
18+
#[command(flatten)]
19+
init: InitializeTest,
20+
21+
/// Second image (ROM_EXT + Owner FW bundle) to bootstrap.
22+
#[arg(long)]
23+
second_bootstrap: PathBuf,
24+
25+
/// Third image (ROM_EXT + Owner FW bundle) to bootstrap.
26+
#[arg(long)]
27+
third_bootstrap: PathBuf,
28+
29+
/// Console receive timeout.
30+
#[arg(long, value_parser = humantime::parse_duration, default_value = "30s")]
31+
timeout: Duration,
32+
}
33+
34+
fn main() -> Result<()> {
35+
let opts = Opts::parse();
36+
opts.init.init_logging();
37+
38+
// Bootstrap first ROM_EXT + Owner FW.
39+
let transport = opts.init.init_target()?;
40+
let uart = transport.uart("console").context("failed to get UART")?;
41+
42+
// Wait for owner FW message.
43+
let _ = UartConsole::wait_for(&*uart, r"Test Owner FW - 0", opts.timeout)?;
44+
45+
// Bootstrap second ROM_EXT + Owner FW.
46+
opts.init
47+
.bootstrap
48+
.load(&transport, &opts.second_bootstrap)?;
49+
50+
// Wait for owner FW message.
51+
let _ = UartConsole::wait_for(&*uart, r"Test Owner FW - 1", opts.timeout)?;
52+
53+
// Bootstrap second ROM_EXT + Owner FW.
54+
opts.init
55+
.bootstrap
56+
.load(&transport, &opts.third_bootstrap)?;
57+
58+
// Wait for pass message from owner firmware stage.
59+
let mut console = UartConsole {
60+
timeout: Some(opts.timeout),
61+
exit_success: Some(Regex::new(r"PASS.*\n")?),
62+
exit_failure: Some(Regex::new(r"BFV.*\n")?),
63+
newline: true,
64+
..Default::default()
65+
};
66+
let mut stdout = std::io::stdout();
67+
let result = console.interact(&*uart, None, Some(&mut stdout))?;
68+
match result {
69+
ExitStatus::None | ExitStatus::CtrlC => Ok(()),
70+
ExitStatus::Timeout => {
71+
if console.exit_success.is_some() {
72+
Err(anyhow!("Console timeout exceeded"))
73+
} else {
74+
Ok(())
75+
}
76+
}
77+
ExitStatus::ExitSuccess => {
78+
log::info!(
79+
"ExitSuccess({:?})",
80+
console.captures(result).unwrap().get(0).unwrap().as_str()
81+
);
82+
Ok(())
83+
}
84+
ExitStatus::ExitFailure => {
85+
log::info!(
86+
"ExitFailure({:?})",
87+
console.captures(result).unwrap().get(0).unwrap().as_str()
88+
);
89+
Err(anyhow!("Matched exit_failure expression"))
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)