Skip to content

Commit

Permalink
[rom_ext_e2e] More ownership transfer tests
Browse files Browse the repository at this point in the history
The tests added by this change are all simple variations on
the ownership transfer test added in lowRISC#24419.  They involve verifying the
different modes and error conditions (e.g. using the wrong key).

Adds the following tests:
- `bad_unlock_test`; Fixes lowRISC#24466
- `bad_activate_test`; Fixes lowRISC#24467
- `bad_owner_block_test`; Fixes lowRISC#24468
- `bad_app_key_test`; Fixes lowRISC#24469
- `transfer_endorsed_test`; Fixes lowRISC#24470
- `bad_endorsee_test`; Fixes lowRISC#24471
- `locked_update_test`; Fixes lowRISC#24472
- `bad_locked_update_test` & `bad_locked_update_no_exec_test`; Fixes lowRISC#24473

Signed-off-by: Chris Frantz <cfrantz@google.com>
  • Loading branch information
cfrantz committed Aug 30, 2024
1 parent 0ad99c9 commit 1f21fd3
Show file tree
Hide file tree
Showing 9 changed files with 412 additions and 44 deletions.
2 changes: 1 addition & 1 deletion rules/opentitan/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def opentitan_test(
kind = "flash",
deps = [],
copts = [],
data = [],
defines = [],
local_defines = [],
includes = [],
Expand All @@ -154,7 +155,6 @@ def opentitan_test(
dv = _dv_params(),
silicon = _silicon_params(),
verilator = _verilator_params(),
data = [],
**kwargs):
"""Instantiate a test per execution environment.
Expand Down
5 changes: 5 additions & 0 deletions sw/device/silicon_creator/lib/ownership/keys/dummy/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ filegroup(
srcs = ["owner_ecdsa_p256.der"],
)

filegroup(
name = "owner_key_pub",
srcs = ["owner_ecdsa_p256.pub.der"],
)

filegroup(
name = "activate_key",
srcs = ["activate_ecdsa_p256.der"],
Expand Down
15 changes: 15 additions & 0 deletions sw/device/silicon_creator/lib/ownership/keys/fake/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ filegroup(
srcs = ["owner_ecdsa_p256.der"],
)

filegroup(
name = "owner_key_pub",
srcs = ["owner_ecdsa_p256.pub.der"],
)

filegroup(
name = "activate_key",
srcs = ["activate_ecdsa_p256.der"],
Expand All @@ -50,3 +55,13 @@ filegroup(
name = "unlock_key",
srcs = ["unlock_ecdsa_p256.der"],
)

filegroup(
name = "app_prod",
srcs = ["app_prod_key_rsa_3072_exp_f4.der"],
)

filegroup(
name = "app_prod_pub",
srcs = ["app_prod_key_rsa_3072_exp_f4.pub.der"],
)
231 changes: 215 additions & 16 deletions sw/device/silicon_creator/rom_ext/e2e/ownership/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,27 @@ load(
"fpga_params",
"opentitan_test",
)
load(
"//sw/device/silicon_creator/rom_ext/e2e/ownership:defs.bzl",
"ownership_transfer_test",
)

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

opentitan_test(
name = "ownership_transfer_test",
srcs = ["//sw/device/silicon_creator/rom_ext/e2e/verified_boot:boot_test"],
exec_env = {
"//hw/top_earlgrey:fpga_hyper310_rom_ext": None,
},
# TODO(#24462): The tests in this file are marked `changes_otp = True`,
# but they don't change OTP. They modify the ownership INFO pages,
# so we need to clear the bitstream after the test, which is what the
# `changes_otp` parameter actually does.

# rom_ext_e2e_testplan.hjson%rom_ext_e2e_transfer_any_test
ownership_transfer_test(
name = "transfer_any_test",
fpga = fpga_params(
# This test doesn't change OTP, but it modifies the ownership INFO
# pages, so we need to clear the bitstream after the test, which is
# what the `changes_otp` parameter actually does.
changes_otp = True,
data = [
"//sw/device/silicon_creator/lib/ownership/keys/dummy:activate_key",
"//sw/device/silicon_creator/lib/ownership/keys/dummy:app_prod_pub",
"//sw/device/silicon_creator/lib/ownership/keys/dummy:owner_key",
"//sw/device/silicon_creator/lib/ownership/keys/dummy:unlock_key",
"//sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key",
],
test_cmd = """
--clear-bitstream
--bootstrap={firmware}
--unlock-mode=Any
--unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key)
--next-owner-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:owner_key)
--next-unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:unlock_key)
Expand All @@ -49,3 +46,205 @@ opentitan_test(
"//sw/device/silicon_creator/lib/drivers:retention_sram",
],
)

# rom_ext_e2e_testplan.hjson%rom_ext_e2e_bad_unlock_test
ownership_transfer_test(
name = "bad_unlock_test",
fpga = fpga_params(
changes_otp = True,
test_cmd = """
--clear-bitstream
--bootstrap={firmware}
--unlock-mode=Any
# NOTE: We use the wrong unlock key to test that the unlock operation fails.
--unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:activate_key)
--next-owner-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:owner_key)
--next-unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:unlock_key)
--next-activate-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:activate_key)
--next-application-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:app_prod_pub)
--expected-error=OwnershipInvalidSignature
""",
test_harness = "//sw/host/tests/ownership:transfer_test",
),
)

# rom_ext_e2e_testplan.hjson%rom_ext_e2e_bad_activate_test
ownership_transfer_test(
name = "bad_activate_test",
fpga = fpga_params(
changes_otp = True,
test_cmd = """
--clear-bitstream
--bootstrap={firmware}
--unlock-mode=Any
--unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key)
# NOTE: We use the wrong activate key to test that the activate operation fails.
--activate-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key)
--next-owner-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:owner_key)
--next-unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:unlock_key)
--next-activate-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:activate_key)
--next-application-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:app_prod_pub)
--expected-error=OwnershipInvalidSignature
""",
test_harness = "//sw/host/tests/ownership:transfer_test",
),
)

# rom_ext_e2e_testplan.hjson%rom_ext_e2e_bad_owner_block_test
ownership_transfer_test(
name = "bad_owner_block_test",
fpga = fpga_params(
changes_otp = True,
test_cmd = """
--clear-bitstream
--bootstrap={firmware}
--unlock-mode=Any
--unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key)
--next-owner-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:owner_key)
--next-unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:unlock_key)
--next-activate-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:activate_key)
--next-application-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:app_prod_pub)
--corrupt-owner-block-signature=true
--dual-owner-boot-check=false
--expected-error=OwnershipInvalidInfoPage
""",
test_harness = "//sw/host/tests/ownership:transfer_test",
),
)

# rom_ext_e2e_testplan.hjson%rom_ext_e2e_bad_app_key_test
ownership_transfer_test(
name = "bad_app_key_test",
fpga = fpga_params(
changes_otp = True,
test_cmd = """
--clear-bitstream
--bootstrap={firmware}
--unlock-mode=Any
--unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key)
--next-owner-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:owner_key)
--next-unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:unlock_key)
--next-activate-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:activate_key)
# NOTE: We use the wrong app key (fake instead of dummy) to test that we cannot boot
# the test program after completing the transfer.
--next-application-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:app_prod_pub)
--expected-error=OwnershipKeyNotFound
""",
test_harness = "//sw/host/tests/ownership:transfer_test",
),
)

# rom_ext_e2e_testplan.hjson%rom_ext_e2e_transfer_endorsed_test
ownership_transfer_test(
name = "transfer_endorsed_test",
fpga = fpga_params(
changes_otp = True,
test_cmd = """
--clear-bitstream
--bootstrap={firmware}
--unlock-mode=Endorsed
--unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key)
--next-owner-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:owner_key)
--next-owner-key-pub=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:owner_key_pub)
--next-unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:unlock_key)
--next-activate-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:activate_key)
--next-application-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:app_prod_pub)
""",
test_harness = "//sw/host/tests/ownership:transfer_test",
),
)

# rom_ext_e2e_testplan.hjson%rom_ext_e2e_bad_endorsee_test
ownership_transfer_test(
name = "bad_endorsee_test",
fpga = fpga_params(
changes_otp = True,
test_cmd = """
--clear-bitstream
--bootstrap={firmware}
--unlock-mode=Endorsed
--unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key)
--next-owner-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:owner_key)
# NOTE: We use the wrong next-owner-public-key to test that endorsee is rejected and the activate operation fails.
--next-owner-key-pub=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:owner_key_pub)
--next-unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:unlock_key)
--next-activate-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:activate_key)
--next-application-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:app_prod_pub)
--dual-owner-boot-check=false
--expected-error=OwnershipInvalidInfoPage
""",
test_harness = "//sw/host/tests/ownership:transfer_test",
),
)

# rom_ext_e2e_testplan.hjson%rom_ext_e2e_locked_update_test
ownership_transfer_test(
name = "locked_update_test",
fpga = fpga_params(
changes_otp = True,
test_cmd = """
--clear-bitstream
--bootstrap={firmware}
--unlock-mode=Update
--unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key)
--next-owner-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:owner_key)
--next-unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key)
--next-activate-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:activate_key)
# NOTE: We rotate the `fake` test owner's application key to the dummy key to test that
# we can execute code with the new key.
--next-application-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:app_prod_pub)
""",
test_harness = "//sw/host/tests/ownership:transfer_test",
),
)

# rom_ext_e2e_testplan.hjson%rom_ext_e2e_bad_locked_update_test
# Part 1: Ensure a LockedUpdate with a new owner key is rejected.
ownership_transfer_test(
name = "bad_locked_update_test",
fpga = fpga_params(
changes_otp = True,
test_cmd = """
--clear-bitstream
--bootstrap={firmware}
--unlock-mode=Update
--unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key)
# NOTE: We use the wrong owner key to test that the activate operation fails.
--next-owner-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:owner_key)
--next-unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key)
--next-activate-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:activate_key)
--next-application-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:app_prod_pub)
--dual-owner-boot-check=false
--expected-error=OwnershipInvalidInfoPage
""",
test_harness = "//sw/host/tests/ownership:transfer_test",
),
rsa_key = {
"//sw/device/silicon_creator/lib/ownership/keys/fake:app_prod": "app_prod",
},
)

# rom_ext_e2e_testplan.hjson%rom_ext_e2e_bad_locked_update_test
# Part 2: Ensure a LockedUpdate denies execution to anything signed with new app keys.
ownership_transfer_test(
name = "bad_locked_update_no_exec_test",
fpga = fpga_params(
changes_otp = True,
test_cmd = """
--clear-bitstream
--bootstrap={firmware}
--unlock-mode=Update
--unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key)
--next-unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key)
--next-activate-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:activate_key)
# NOTE: We use the wrong owner key and the dummy app key (which the ownership_transfer_test rule
# uses for signing) to check that owner code execution is denied in the intermediate
# dual-owner state.
--next-owner-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:owner_key)
--next-application-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:app_prod_pub)
--expected-error=OwnershipKeyNotFound
""",
test_harness = "//sw/host/tests/ownership:transfer_test",
),
)
46 changes: 46 additions & 0 deletions sw/device/silicon_creator/rom_ext/e2e/ownership/defs.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# 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",
"opentitan_test",
)

def ownership_transfer_test(
name,
srcs = ["//sw/device/silicon_creator/rom_ext/e2e/verified_boot:boot_test"],
exec_env = {
"//hw/top_earlgrey:fpga_cw310_rom_ext": None,
},
rsa_key = {
"//sw/device/silicon_creator/lib/ownership/keys/dummy:app_prod": "app_prod",
},
data = [
"//sw/device/silicon_creator/lib/ownership/keys/dummy:activate_key",
"//sw/device/silicon_creator/lib/ownership/keys/dummy:app_prod_pub",
"//sw/device/silicon_creator/lib/ownership/keys/dummy:owner_key",
"//sw/device/silicon_creator/lib/ownership/keys/dummy:owner_key_pub",
"//sw/device/silicon_creator/lib/ownership/keys/dummy:unlock_key",
"//sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key",
"//sw/device/silicon_creator/lib/ownership/keys/fake:activate_key",
"//sw/device/silicon_creator/lib/ownership/keys/fake:owner_key",
"//sw/device/silicon_creator/lib/ownership/keys/fake:owner_key_pub",
"//sw/device/silicon_creator/lib/ownership/keys/fake:app_prod_pub",
],
deps = [
"//sw/device/lib/base:status",
"//sw/device/lib/testing/test_framework:ottf_main",
"//sw/device/silicon_creator/lib:boot_log",
"//sw/device/silicon_creator/lib/drivers:retention_sram",
],
**kwargs):
opentitan_test(
name = name,
srcs = srcs,
exec_env = exec_env,
rsa_key = rsa_key,
data = data,
deps = deps,
**kwargs
)
23 changes: 23 additions & 0 deletions sw/host/opentitanlib/src/chip/rom_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,28 @@
// SPDX-License-Identifier: Apache-2.0

use crate::with_unknown;
use std::error::Error;

include!(env!("rom_error_enum"));

impl Error for RomError {}

impl From<RomError> for Result<(), RomError> {
fn from(error: RomError) -> Self {
if error == RomError::Ok {
Ok(())
} else {
Err(error)
}
}
}

impl From<RomError> for Result<(), anyhow::Error> {
fn from(error: RomError) -> Self {
if error == RomError::Ok {
Ok(())
} else {
Err(error.into())
}
}
}
1 change: 1 addition & 0 deletions sw/host/tests/ownership/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ rust_binary(
"@crate_index//:clap",
"@crate_index//:humantime",
"@crate_index//:log",
"@crate_index//:regex",
],
)
Loading

0 comments on commit 1f21fd3

Please sign in to comment.