-
Notifications
You must be signed in to change notification settings - Fork 790
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[rom_ext_e2e] Add an ownership transfer test
1. Create a library of helper functions for facilitating ownership transfer tests. 2. Create a basic ownership transfer test that transfers chip ownership from the default `fake` test owner to a `dummy` owner. Signed-off-by: Chris Frantz <[email protected]> (cherry picked from commit 0ad99c9) (cherry picked from commit 71cc612)
- Loading branch information
Showing
12 changed files
with
318 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# 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 = "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, | ||
}, | ||
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-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) | ||
""", | ||
test_harness = "//sw/host/tests/ownership:transfer_test", | ||
), | ||
rsa_key = { | ||
"//sw/device/silicon_creator/lib/ownership/keys/dummy:app_prod": "app_prod", | ||
}, | ||
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", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# 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_rust//rust:defs.bzl", "rust_binary", "rust_library") | ||
load("//rules:ujson.bzl", "ujson_rust") | ||
|
||
package(default_visibility = ["//visibility:public"]) | ||
|
||
rust_library( | ||
name = "transfer_lib", | ||
srcs = ["transfer_lib.rs"], | ||
deps = [ | ||
"//sw/host/opentitanlib", | ||
"@crate_index//:anyhow", | ||
"@crate_index//:log", | ||
], | ||
) | ||
|
||
rust_binary( | ||
name = "transfer_test", | ||
srcs = [ | ||
"transfer_test.rs", | ||
], | ||
deps = [ | ||
":transfer_lib", | ||
"//sw/host/opentitanlib", | ||
"@crate_index//:anyhow", | ||
"@crate_index//:clap", | ||
"@crate_index//:humantime", | ||
"@crate_index//:log", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// Copyright lowRISC contributors (OpenTitan project). | ||
// Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
#![allow(clippy::bool_assert_comparison)] | ||
use anyhow::{anyhow, Result}; | ||
use opentitanlib::app::TransportWrapper; | ||
use opentitanlib::chip::boot_log::BootLog; | ||
use opentitanlib::chip::boot_svc::{Message, UnlockMode}; | ||
use opentitanlib::chip::helper::{OwnershipActivateParams, OwnershipUnlockParams}; | ||
use opentitanlib::chip::rom_error::RomError; | ||
use opentitanlib::crypto::ecdsa::EcdsaPrivateKey; | ||
use opentitanlib::crypto::rsa::RsaPublicKey; | ||
use opentitanlib::ownership::{ | ||
ApplicationKeyDomain, KeyMaterial, OwnerApplicationKey, OwnerBlock, OwnerConfigItem, | ||
OwnershipKeyAlg, | ||
}; | ||
use opentitanlib::rescue::serial::RescueSerial; | ||
|
||
use std::path::Path; | ||
|
||
/// Gets the BootLog. | ||
pub fn get_boot_log(transport: &TransportWrapper, rescue: &RescueSerial) -> Result<BootLog> { | ||
rescue.enter(transport, /*reset=*/ true)?; | ||
rescue.get_boot_log() | ||
} | ||
|
||
/// Prepares an UnlockOwnership command, sends it to the chip and gets the response. | ||
pub fn ownership_unlock( | ||
transport: &TransportWrapper, | ||
rescue: &RescueSerial, | ||
mode: UnlockMode, | ||
nonce: u64, | ||
unlock_key: &Path, | ||
next_owner: Option<&Path>, | ||
) -> Result<()> { | ||
let unlock = OwnershipUnlockParams { | ||
mode: Some(mode), | ||
nonce: Some(nonce), | ||
next_owner: next_owner.map(|p| p.into()), | ||
sign: Some(unlock_key.into()), | ||
..Default::default() | ||
} | ||
.apply_to(Option::<&mut std::fs::File>::None)?; | ||
|
||
rescue.enter(transport, /*reset=*/ true)?; | ||
rescue.ownership_unlock(unlock)?; | ||
rescue.enter(transport, /*reset=*/ false)?; | ||
let result = rescue.get_boot_svc()?; | ||
match &result.message { | ||
Message::OwnershipUnlockResponse(r) if r.status == RomError::Ok => Ok(()), | ||
_ => Err(anyhow!("Unexpected response: {result:x?}")), | ||
} | ||
} | ||
|
||
/// Prepares an UnlockOwnership command (with UnlockMode::Any), sends it to the chip and gets the response. | ||
pub fn ownership_unlock_any( | ||
transport: &TransportWrapper, | ||
rescue: &RescueSerial, | ||
nonce: u64, | ||
unlock_key: &Path, | ||
) -> Result<()> { | ||
ownership_unlock(transport, rescue, UnlockMode::Any, nonce, unlock_key, None) | ||
} | ||
|
||
/// Prepares an OwnershipActivate command, sends it to the chip and gets the response. | ||
pub fn ownership_activate( | ||
transport: &TransportWrapper, | ||
rescue: &RescueSerial, | ||
nonce: u64, | ||
activate_key: &Path, | ||
) -> Result<()> { | ||
let activate = OwnershipActivateParams { | ||
nonce: Some(nonce), | ||
sign: Some(activate_key.into()), | ||
..Default::default() | ||
} | ||
.apply_to(Option::<&mut std::fs::File>::None)?; | ||
|
||
rescue.enter(transport, /*reset=*/ true)?; | ||
rescue.ownership_activate(activate)?; | ||
rescue.enter(transport, /*reset=*/ false)?; | ||
let result = rescue.get_boot_svc()?; | ||
match &result.message { | ||
Message::OwnershipActivateResponse(r) if r.status == RomError::Ok => Ok(()), | ||
_ => Err(anyhow!("Unexpected response: {result:x?}")), | ||
} | ||
} | ||
|
||
/// Prepares an OwnerBlock and sends it to the chip. | ||
pub fn create_owner( | ||
transport: &TransportWrapper, | ||
rescue: &RescueSerial, | ||
owner_key: &Path, | ||
activate_key: &Path, | ||
unlock_key: &Path, | ||
app_key: &Path, | ||
) -> Result<()> { | ||
let owner_key = EcdsaPrivateKey::load(owner_key)?; | ||
let activate_key = EcdsaPrivateKey::load(activate_key)?; | ||
let unlock_key = EcdsaPrivateKey::load(unlock_key)?; | ||
let app_key = RsaPublicKey::from_pkcs1_der_file(app_key)?; | ||
let mut owner = OwnerBlock { | ||
owner_key: KeyMaterial::Ecdsa(owner_key.public_key().try_into()?), | ||
activate_key: KeyMaterial::Ecdsa(activate_key.public_key().try_into()?), | ||
unlock_key: KeyMaterial::Ecdsa(unlock_key.public_key().try_into()?), | ||
data: vec![OwnerConfigItem::ApplicationKey(OwnerApplicationKey { | ||
key_alg: OwnershipKeyAlg::Rsa, | ||
key_domain: ApplicationKeyDomain::Prod, | ||
key: KeyMaterial::Rsa(app_key.try_into()?), | ||
..Default::default() | ||
})], | ||
..Default::default() | ||
}; | ||
owner.sign(&owner_key)?; | ||
let mut owner_config = Vec::new(); | ||
owner.write(&mut owner_config)?; | ||
rescue.enter(transport, /*reset=*/ true)?; | ||
rescue.set_owner_config(&owner_config)?; | ||
Ok(()) | ||
} |
Oops, something went wrong.