mirror of
https://github.com/matter-labs/teepot.git
synced 2025-07-21 15:13:56 +02:00
feat: add tdx-extend, sha384-extend and rtmr-calc
This enables pre-calculating the TDX rtmr[1,2,3] values for an attested boot process. Signed-off-by: Harald Hoyer <harald@matterlabs.dev>
This commit is contained in:
parent
fbc4897dad
commit
5d32396966
12 changed files with 603 additions and 2 deletions
112
Cargo.lock
generated
112
Cargo.lock
generated
|
@ -975,6 +975,18 @@ dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cms"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7b77c319abfd5219629c45c34c89ba945ed3c5e49fcde9d16b6c3885f118a730"
|
||||||
|
dependencies = [
|
||||||
|
"const-oid",
|
||||||
|
"der 0.7.9",
|
||||||
|
"spki 0.7.3",
|
||||||
|
"x509-cert",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "combine"
|
name = "combine"
|
||||||
version = "4.6.7"
|
version = "4.6.7"
|
||||||
|
@ -1039,6 +1051,21 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc"
|
||||||
|
version = "3.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636"
|
||||||
|
dependencies = [
|
||||||
|
"crc-catalog",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc-catalog"
|
||||||
|
version = "2.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc24"
|
name = "crc24"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
@ -1264,7 +1291,7 @@ dependencies = [
|
||||||
"const-oid",
|
"const-oid",
|
||||||
"der_derive",
|
"der_derive",
|
||||||
"flagset",
|
"flagset",
|
||||||
"pem-rfc7468",
|
"pem-rfc7468 0.7.0",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1527,7 +1554,7 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
"group 0.13.0",
|
"group 0.13.0",
|
||||||
"hkdf",
|
"hkdf",
|
||||||
"pem-rfc7468",
|
"pem-rfc7468 0.7.0",
|
||||||
"pkcs8 0.10.2",
|
"pkcs8 0.10.2",
|
||||||
"rand_core 0.6.4",
|
"rand_core 0.6.4",
|
||||||
"sec1 0.7.3",
|
"sec1 0.7.3",
|
||||||
|
@ -1972,6 +1999,18 @@ dependencies = [
|
||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gpt"
|
||||||
|
version = "4.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ffa5448a0d9d541f1840c0e1b5fe513360861ca83c4b920619f54efe277f9254"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"crc",
|
||||||
|
"simple-bytes",
|
||||||
|
"uuid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "group"
|
name = "group"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
@ -3576,6 +3615,25 @@ version = "1.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pe-sign"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c04c052a5cf901a229d69fb8804b04c8017c143712529c6e8277aac243fc2989"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"cms",
|
||||||
|
"der 0.7.9",
|
||||||
|
"digest",
|
||||||
|
"num-traits",
|
||||||
|
"pem-rfc7468 1.0.0-rc.2",
|
||||||
|
"reqwest 0.12.9",
|
||||||
|
"rsa",
|
||||||
|
"sha1",
|
||||||
|
"sha2",
|
||||||
|
"x509-cert",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "peeking_take_while"
|
name = "peeking_take_while"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -3591,6 +3649,15 @@ dependencies = [
|
||||||
"base64ct",
|
"base64ct",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pem-rfc7468"
|
||||||
|
version = "1.0.0-rc.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2dfbfa5c6f0906884269722c5478e72fd4d6c0e24fe600332c6d62359567ce1"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.1"
|
version = "2.3.1"
|
||||||
|
@ -4251,6 +4318,20 @@ dependencies = [
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rtmr-calc"
|
||||||
|
version = "0.3.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"clap 4.5.23",
|
||||||
|
"gpt",
|
||||||
|
"hex",
|
||||||
|
"pe-sign",
|
||||||
|
"sha2",
|
||||||
|
"teepot",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.24"
|
version = "0.1.24"
|
||||||
|
@ -4810,6 +4891,16 @@ dependencies = [
|
||||||
"keccak",
|
"keccak",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha384-extend"
|
||||||
|
version = "0.3.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"clap 4.5.23",
|
||||||
|
"hex",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha3_ce"
|
name = "sha3_ce"
|
||||||
version = "0.10.6"
|
version = "0.10.6"
|
||||||
|
@ -4864,6 +4955,12 @@ dependencies = [
|
||||||
"rand_core 0.6.4",
|
"rand_core 0.6.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simple-bytes"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c11532d9d241904f095185f35dcdaf930b1427a94d5b01d7002d74ba19b44cc4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.9"
|
version = "0.4.9"
|
||||||
|
@ -5100,6 +5197,17 @@ dependencies = [
|
||||||
"bindgen 0.59.2",
|
"bindgen 0.59.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tdx-extend"
|
||||||
|
version = "0.3.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"clap 4.5.23",
|
||||||
|
"hex",
|
||||||
|
"teepot",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tee-key-preexec"
|
name = "tee-key-preexec"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
|
|
@ -29,6 +29,7 @@ ctrlc = "3.4"
|
||||||
enumset = { version = "1.1", features = ["serde"] }
|
enumset = { version = "1.1", features = ["serde"] }
|
||||||
futures-core = { version = "0.3.30", features = ["alloc"], default-features = false }
|
futures-core = { version = "0.3.30", features = ["alloc"], default-features = false }
|
||||||
getrandom = "0.2.14"
|
getrandom = "0.2.14"
|
||||||
|
gpt = "4.0.0"
|
||||||
hex = { version = "0.4.3", features = ["std"], default-features = false }
|
hex = { version = "0.4.3", features = ["std"], default-features = false }
|
||||||
intel-tee-quote-verification-rs = { package = "teepot-tee-quote-verification-rs", path = "crates/teepot-tee-quote-verification-rs", version = "0.3.0" }
|
intel-tee-quote-verification-rs = { package = "teepot-tee-quote-verification-rs", path = "crates/teepot-tee-quote-verification-rs", version = "0.3.0" }
|
||||||
intel-tee-quote-verification-sys = { version = "0.2.1" }
|
intel-tee-quote-verification-sys = { version = "0.2.1" }
|
||||||
|
@ -36,6 +37,7 @@ jsonrpsee-types = { version = "0.23", default-features = false }
|
||||||
num-integer = "0.1.46"
|
num-integer = "0.1.46"
|
||||||
num-traits = "0.2.18"
|
num-traits = "0.2.18"
|
||||||
p256 = "0.13.2"
|
p256 = "0.13.2"
|
||||||
|
pe-sign = "0.1.10"
|
||||||
pgp = "0.14.2"
|
pgp = "0.14.2"
|
||||||
pkcs8 = { version = "0.10" }
|
pkcs8 = { version = "0.10" }
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
|
|
18
bin/rtmr-calc/Cargo.toml
Normal file
18
bin/rtmr-calc/Cargo.toml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
[package]
|
||||||
|
name = "rtmr-calc"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow.workspace = true
|
||||||
|
clap.workspace = true
|
||||||
|
gpt.workspace = true
|
||||||
|
hex.workspace = true
|
||||||
|
pe-sign.workspace = true
|
||||||
|
sha2.workspace = true
|
||||||
|
teepot.workspace = true
|
||||||
|
tracing.workspace = true
|
237
bin/rtmr-calc/src/main.rs
Normal file
237
bin/rtmr-calc/src/main.rs
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// Copyright (c) 2024 Matter Labs
|
||||||
|
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
|
use clap::Parser;
|
||||||
|
use pesign::PE;
|
||||||
|
use sha2::{Digest, Sha384};
|
||||||
|
use std::{
|
||||||
|
fmt::{Display, Formatter},
|
||||||
|
io::{Error, ErrorKind, Read, Seek, SeekFrom},
|
||||||
|
path::PathBuf,
|
||||||
|
};
|
||||||
|
use teepot::log::{setup_logging, LogLevelParser};
|
||||||
|
use tracing::{debug, info, level_filters::LevelFilter};
|
||||||
|
|
||||||
|
/// Precalculate rtmr1 and rtmr2 values.
|
||||||
|
///
|
||||||
|
/// Currently tested with the Google confidential compute engines.
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(author, version, about, long_about = None)]
|
||||||
|
struct Arguments {
|
||||||
|
/// disk image to measure the GPT table from
|
||||||
|
#[arg(long)]
|
||||||
|
image: PathBuf,
|
||||||
|
/// path to the used UKI EFI binary
|
||||||
|
#[arg(long)]
|
||||||
|
bootefi: PathBuf,
|
||||||
|
/// path to the used linux kernel EFI binary (contained in the UKI)
|
||||||
|
#[arg(long)]
|
||||||
|
kernel: PathBuf,
|
||||||
|
/// Log level for the log output.
|
||||||
|
/// Valid values are: `off`, `error`, `warn`, `info`, `debug`, `trace`
|
||||||
|
#[clap(long, default_value_t = LevelFilter::WARN, value_parser = LogLevelParser)]
|
||||||
|
pub log_level: LevelFilter,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Rtmr {
|
||||||
|
state: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Rtmr {
|
||||||
|
pub fn extend(&mut self, hash: &[u8]) -> &[u8] {
|
||||||
|
self.state.extend(hash);
|
||||||
|
let bytes = Sha384::digest(&self.state);
|
||||||
|
self.state.resize(48, 0);
|
||||||
|
self.state.copy_from_slice(&bytes);
|
||||||
|
&self.state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Rtmr {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
state: [0u8; 48].to_vec(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Rtmr {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", hex::encode(&self.state))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let args = Arguments::parse();
|
||||||
|
tracing::subscriber::set_global_default(setup_logging(
|
||||||
|
env!("CARGO_CRATE_NAME"),
|
||||||
|
&args.log_level,
|
||||||
|
)?)?;
|
||||||
|
|
||||||
|
let mut rtmr1 = Rtmr::default();
|
||||||
|
let mut rtmr2 = Rtmr::default();
|
||||||
|
|
||||||
|
/*
|
||||||
|
- pcr_index: 1
|
||||||
|
event: efiaction
|
||||||
|
digests:
|
||||||
|
- method: sha384
|
||||||
|
digest: 77a0dab2312b4e1e57a84d865a21e5b2ee8d677a21012ada819d0a98988078d3d740f6346bfe0abaa938ca20439a8d71
|
||||||
|
digest_verification_status: verified
|
||||||
|
data: Q2FsbGluZyBFRkkgQXBwbGljYXRpb24gZnJvbSBCb290IE9wdGlvbg==
|
||||||
|
parsed_data:
|
||||||
|
Ok:
|
||||||
|
text: Calling EFI Application from Boot Option
|
||||||
|
*/
|
||||||
|
rtmr1.extend(&hex::decode("77a0dab2312b4e1e57a84d865a21e5b2ee8d677a21012ada819d0a98988078d3d740f6346bfe0abaa938ca20439a8d71")?);
|
||||||
|
|
||||||
|
/*
|
||||||
|
- pcr_index: 1
|
||||||
|
event: separator
|
||||||
|
digests:
|
||||||
|
- method: sha384
|
||||||
|
digest: 394341b7182cd227c5c6b07ef8000cdfd86136c4292b8e576573ad7ed9ae41019f5818b4b971c9effc60e1ad9f1289f0
|
||||||
|
digest_verification_status: verified
|
||||||
|
data: AAAAAA==
|
||||||
|
parsed_data:
|
||||||
|
Ok:
|
||||||
|
validseparator: UEFI
|
||||||
|
*/
|
||||||
|
rtmr1.extend(&hex::decode("394341b7182cd227c5c6b07ef8000cdfd86136c4292b8e576573ad7ed9ae41019f5818b4b971c9effc60e1ad9f1289f0")?);
|
||||||
|
|
||||||
|
// Open disk image.
|
||||||
|
let cfg = gpt::GptConfig::new().writable(false);
|
||||||
|
let disk = cfg.open(args.image)?;
|
||||||
|
|
||||||
|
// Print GPT layout.
|
||||||
|
info!("Disk (primary) header: {:#?}", disk.primary_header());
|
||||||
|
info!("Partition layout: {:#?}", disk.partitions());
|
||||||
|
|
||||||
|
let header = disk.primary_header()?;
|
||||||
|
let mut msr = Vec::<u8>::new();
|
||||||
|
let lb_size = disk.logical_block_size();
|
||||||
|
let mut device = disk.device_ref();
|
||||||
|
device.seek(SeekFrom::Start(lb_size.as_u64()))?;
|
||||||
|
let mut buf = [0u8; 92];
|
||||||
|
device.read_exact(&mut buf)?;
|
||||||
|
msr.extend_from_slice(&buf);
|
||||||
|
|
||||||
|
let pstart = header
|
||||||
|
.part_start
|
||||||
|
.checked_mul(lb_size.as_u64())
|
||||||
|
.ok_or_else(|| Error::new(ErrorKind::Other, "partition overflow - start offset"))?;
|
||||||
|
let _ = device.seek(SeekFrom::Start(pstart))?;
|
||||||
|
|
||||||
|
assert_eq!(header.part_size, 128);
|
||||||
|
assert!(header.num_parts < u8::MAX as _);
|
||||||
|
|
||||||
|
let empty_bytes = [0u8; 128];
|
||||||
|
|
||||||
|
msr.extend_from_slice(&disk.partitions().len().to_le_bytes());
|
||||||
|
|
||||||
|
for _ in 0..header.num_parts {
|
||||||
|
let mut bytes = empty_bytes;
|
||||||
|
|
||||||
|
device.read_exact(&mut bytes)?;
|
||||||
|
if bytes.eq(&empty_bytes) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
msr.extend_from_slice(&bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut hasher = Sha384::new();
|
||||||
|
hasher.update(&msr);
|
||||||
|
let result = hasher.finalize();
|
||||||
|
info!("GPT hash: {:x}", result);
|
||||||
|
|
||||||
|
rtmr1.extend(&result);
|
||||||
|
|
||||||
|
let mut pe = PE::from_path(&args.bootefi)?;
|
||||||
|
|
||||||
|
let hash = pe.calc_authenticode(pesign::cert::Algorithm::Sha384)?;
|
||||||
|
info!("hash of {:?}: {hash}", args.bootefi);
|
||||||
|
rtmr1.extend(&hex::decode(&hash)?);
|
||||||
|
|
||||||
|
let section_table = pe.get_section_table()?;
|
||||||
|
|
||||||
|
for section in section_table.iter() {
|
||||||
|
debug!(section_name = ?section.name()?);
|
||||||
|
}
|
||||||
|
|
||||||
|
for sect in [".linux", ".osrel", ".cmdline", ".initrd", ".uname", ".sbat"] {
|
||||||
|
let mut hasher = Sha384::new();
|
||||||
|
hasher.update(sect.as_bytes());
|
||||||
|
hasher.update([0u8]);
|
||||||
|
let out = hasher.finalize();
|
||||||
|
debug!(sect, "name: {out:x}");
|
||||||
|
rtmr2.extend(&out);
|
||||||
|
|
||||||
|
let s = section_table
|
||||||
|
.iter()
|
||||||
|
.find(|s| s.name().unwrap().eq(sect))
|
||||||
|
.ok_or(anyhow!("Failed to find section `{sect}`"))?;
|
||||||
|
|
||||||
|
let mut start = s.pointer_to_raw_data as u64;
|
||||||
|
let end = start + s.virtual_size as u64;
|
||||||
|
|
||||||
|
debug!(sect, start, end, len = (s.virtual_size));
|
||||||
|
|
||||||
|
let mut hasher = Sha384::new();
|
||||||
|
|
||||||
|
const CHUNK_SIZE: u64 = 1024 * 128;
|
||||||
|
loop {
|
||||||
|
if start >= end {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buf = vec![0; CHUNK_SIZE.min(end - start) as _];
|
||||||
|
pe.read_exact_at(start, buf.as_mut_slice())?;
|
||||||
|
hasher.update(buf.as_slice());
|
||||||
|
|
||||||
|
start += CHUNK_SIZE;
|
||||||
|
}
|
||||||
|
let digest = hasher.finalize();
|
||||||
|
debug!(sect, "binary: {digest:x}");
|
||||||
|
rtmr2.extend(&digest);
|
||||||
|
}
|
||||||
|
|
||||||
|
let hash = PE::from_path(&args.kernel)?.calc_authenticode(pesign::cert::Algorithm::Sha384)?;
|
||||||
|
info!("hash of {:?}: {hash}", args.kernel);
|
||||||
|
rtmr1.extend(&hex::decode(&hash)?);
|
||||||
|
|
||||||
|
/*
|
||||||
|
- pcr_index: 1
|
||||||
|
event: efiaction
|
||||||
|
digests:
|
||||||
|
- method: sha384
|
||||||
|
digest: 214b0bef1379756011344877743fdc2a5382bac6e70362d624ccf3f654407c1b4badf7d8f9295dd3dabdef65b27677e0
|
||||||
|
digest_verification_status: verified
|
||||||
|
data: RXhpdCBCb290IFNlcnZpY2VzIEludm9jYXRpb24=
|
||||||
|
parsed_data:
|
||||||
|
Ok:
|
||||||
|
text: Exit Boot Services Invocation
|
||||||
|
*/
|
||||||
|
rtmr1.extend(&hex::decode("214b0bef1379756011344877743fdc2a5382bac6e70362d624ccf3f654407c1b4badf7d8f9295dd3dabdef65b27677e0")?);
|
||||||
|
|
||||||
|
/*
|
||||||
|
- pcr_index: 1
|
||||||
|
event: efiaction
|
||||||
|
digests:
|
||||||
|
- method: sha384
|
||||||
|
digest: 0a2e01c85deae718a530ad8c6d20a84009babe6c8989269e950d8cf440c6e997695e64d455c4174a652cd080f6230b74
|
||||||
|
digest_verification_status: verified
|
||||||
|
data: RXhpdCBCb290IFNlcnZpY2VzIFJldHVybmVkIHdpdGggU3VjY2Vzcw==
|
||||||
|
parsed_data:
|
||||||
|
Ok:
|
||||||
|
text: Exit Boot Services Returned with Success
|
||||||
|
*/
|
||||||
|
rtmr1.extend(&hex::decode("0a2e01c85deae718a530ad8c6d20a84009babe6c8989269e950d8cf440c6e997695e64d455c4174a652cd080f6230b74")?);
|
||||||
|
|
||||||
|
println!("{{");
|
||||||
|
println!("\t\"rtmr1\": \"{rtmr1}\",");
|
||||||
|
println!("\t\"rtmr2\": \"{rtmr2}\"");
|
||||||
|
println!("}}");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
14
bin/sha384-extend/Cargo.toml
Normal file
14
bin/sha384-extend/Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "sha384-extend"
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow.workspace = true
|
||||||
|
clap.workspace = true
|
||||||
|
hex.workspace = true
|
||||||
|
sha2.workspace = true
|
39
bin/sha384-extend/src/main.rs
Normal file
39
bin/sha384-extend/src/main.rs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// Copyright (c) 2024 Matter Labs
|
||||||
|
|
||||||
|
//! Extend the TDX measurement
|
||||||
|
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
#![deny(clippy::all)]
|
||||||
|
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
use clap::Parser;
|
||||||
|
use sha2::Digest;
|
||||||
|
|
||||||
|
/// Calculate a TDX rtmr or TPM pcr sha384 value by extending it
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(author, version, about, long_about = None)]
|
||||||
|
struct Arguments {
|
||||||
|
/// digest in hex to extend with
|
||||||
|
#[arg(long)]
|
||||||
|
extend: String,
|
||||||
|
/// initial digest in hex
|
||||||
|
#[arg(long)]
|
||||||
|
digest: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let args = Arguments::parse();
|
||||||
|
|
||||||
|
// Parse the digest string as a hex array
|
||||||
|
let extend_bytes = hex::decode(&args.extend).context("Invalid digest format")?;
|
||||||
|
let mut digest_bytes = hex::decode(&args.digest).context("Invalid digest format")?;
|
||||||
|
|
||||||
|
digest_bytes.extend(extend_bytes);
|
||||||
|
|
||||||
|
let bytes = sha2::Sha384::digest(&digest_bytes);
|
||||||
|
let hex = hex::encode(bytes);
|
||||||
|
|
||||||
|
println!("{hex}");
|
||||||
|
Ok(())
|
||||||
|
}
|
16
bin/tdx-extend/Cargo.toml
Normal file
16
bin/tdx-extend/Cargo.toml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[package]
|
||||||
|
name = "tdx-extend"
|
||||||
|
publish = false
|
||||||
|
version.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow.workspace = true
|
||||||
|
clap.workspace = true
|
||||||
|
hex.workspace = true
|
||||||
|
teepot.workspace = true
|
||||||
|
tracing.workspace = true
|
60
bin/tdx-extend/src/main.rs
Normal file
60
bin/tdx-extend/src/main.rs
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// Copyright (c) 2024 Matter Labs
|
||||||
|
|
||||||
|
//! Extend the TDX measurement
|
||||||
|
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
#![deny(clippy::all)]
|
||||||
|
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
use clap::Parser;
|
||||||
|
use teepot::{
|
||||||
|
log::{setup_logging, LogLevelParser},
|
||||||
|
pad,
|
||||||
|
tdx::rtmr::TdxRtmrEvent,
|
||||||
|
};
|
||||||
|
use tracing::{error, level_filters::LevelFilter};
|
||||||
|
|
||||||
|
/// Extend a TDX rtmr with a hash digest for measured boot.
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(author, version, about, long_about = None)]
|
||||||
|
struct Arguments {
|
||||||
|
/// digest in hex to extend the rtmr with
|
||||||
|
#[arg(long)]
|
||||||
|
digest: String,
|
||||||
|
/// the number or the rtmr
|
||||||
|
#[arg(long, default_value = "2")]
|
||||||
|
rtmr: u64,
|
||||||
|
/// Log level for the log output.
|
||||||
|
/// Valid values are: `off`, `error`, `warn`, `info`, `debug`, `trace`
|
||||||
|
#[clap(long, default_value_t = LevelFilter::WARN, value_parser = LogLevelParser)]
|
||||||
|
pub log_level: LevelFilter,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main_with_error() -> Result<()> {
|
||||||
|
let args = Arguments::parse();
|
||||||
|
tracing::subscriber::set_global_default(setup_logging(
|
||||||
|
env!("CARGO_CRATE_NAME"),
|
||||||
|
&args.log_level,
|
||||||
|
)?)?;
|
||||||
|
|
||||||
|
// Parse the digest string as a hex array
|
||||||
|
let digest_bytes = hex::decode(&args.digest).context("Invalid digest format")?;
|
||||||
|
let extend_data: [u8; 48] = pad(&digest_bytes);
|
||||||
|
|
||||||
|
// Extend the TDX measurement with the extend data
|
||||||
|
TdxRtmrEvent::default()
|
||||||
|
.with_extend_data(extend_data)
|
||||||
|
.with_rtmr_index(args.rtmr)
|
||||||
|
.extend()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let ret = main_with_error();
|
||||||
|
if let Err(e) = &ret {
|
||||||
|
error!(error = %e, "Execution failed");
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
|
@ -13,3 +13,15 @@ pub mod quote;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
pub mod sgx;
|
pub mod sgx;
|
||||||
pub mod tdx;
|
pub mod tdx;
|
||||||
|
|
||||||
|
/// pad a byte slice to a fixed sized array
|
||||||
|
pub fn pad<const T: usize>(input: &[u8]) -> [u8; T] {
|
||||||
|
let mut output = [0; T];
|
||||||
|
let len = input.len();
|
||||||
|
if len > T {
|
||||||
|
output.copy_from_slice(&input[..T]);
|
||||||
|
} else {
|
||||||
|
output[..len].copy_from_slice(input);
|
||||||
|
}
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
//! Intel TDX helper functions.
|
//! Intel TDX helper functions.
|
||||||
|
|
||||||
|
pub mod rtmr;
|
||||||
|
|
||||||
pub use crate::sgx::tcblevel::{parse_tcb_levels, EnumSet, TcbLevel};
|
pub use crate::sgx::tcblevel::{parse_tcb_levels, EnumSet, TcbLevel};
|
||||||
use crate::sgx::QuoteError;
|
use crate::sgx::QuoteError;
|
||||||
pub use intel_tee_quote_verification_rs::Collateral;
|
pub use intel_tee_quote_verification_rs::Collateral;
|
||||||
|
|
90
crates/teepot/src/tdx/rtmr.rs
Normal file
90
crates/teepot/src/tdx/rtmr.rs
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// Copyright (c) 2024 Matter Labs
|
||||||
|
|
||||||
|
//! rtmr event data
|
||||||
|
|
||||||
|
use crate::sgx::QuoteError;
|
||||||
|
|
||||||
|
/// The actual rtmr event data handled in DCAP
|
||||||
|
#[repr(C, packed)]
|
||||||
|
pub struct TdxRtmrEvent {
|
||||||
|
/// Always 1
|
||||||
|
version: u32,
|
||||||
|
|
||||||
|
/// The RTMR that will be extended. As defined in
|
||||||
|
/// https://github.com/confidential-containers/td-shim/blob/main/doc/tdshim_spec.md#td-measurement
|
||||||
|
/// we will use RTMR 3 for guest application code and configuration.
|
||||||
|
rtmr_index: u64,
|
||||||
|
|
||||||
|
/// Data that will be used to extend RTMR
|
||||||
|
extend_data: [u8; 48usize],
|
||||||
|
|
||||||
|
/// Not used in DCAP
|
||||||
|
event_type: u32,
|
||||||
|
|
||||||
|
/// Always 0
|
||||||
|
event_data_size: u32,
|
||||||
|
|
||||||
|
/// Not used in DCAP
|
||||||
|
event_data: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TdxRtmrEvent {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
extend_data: [0; 48],
|
||||||
|
version: 1,
|
||||||
|
rtmr_index: 3,
|
||||||
|
event_type: 0,
|
||||||
|
event_data_size: 0,
|
||||||
|
event_data: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TdxRtmrEvent {
|
||||||
|
/// use the extend data
|
||||||
|
pub fn with_extend_data(mut self, extend_data: [u8; 48]) -> Self {
|
||||||
|
self.extend_data = extend_data;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// extend the rtmr index
|
||||||
|
pub fn with_rtmr_index(mut self, rtmr_index: u64) -> Self {
|
||||||
|
self.rtmr_index = rtmr_index;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// extending the index, consuming self
|
||||||
|
pub fn extend(self) -> Result<(), QuoteError> {
|
||||||
|
let event: Vec<u8> = self.into();
|
||||||
|
|
||||||
|
match tdx_attest_rs::tdx_att_extend(&event) {
|
||||||
|
tdx_attest_rs::tdx_attest_error_t::TDX_ATTEST_SUCCESS => Ok(()),
|
||||||
|
error_code => Err(error_code.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TdxRtmrEvent> for Vec<u8> {
|
||||||
|
fn from(val: TdxRtmrEvent) -> Self {
|
||||||
|
let event_ptr = &val as *const TdxRtmrEvent as *const u8;
|
||||||
|
let event_data_size = std::mem::size_of::<u8>() * val.event_data_size as usize;
|
||||||
|
let res_size = std::mem::size_of::<u32>() * 3
|
||||||
|
+ std::mem::size_of::<u64>()
|
||||||
|
+ std::mem::size_of::<[u8; 48]>()
|
||||||
|
+ event_data_size;
|
||||||
|
let mut res = vec![0; res_size];
|
||||||
|
unsafe {
|
||||||
|
for (i, chunk) in res.iter_mut().enumerate().take(res_size - event_data_size) {
|
||||||
|
*chunk = *event_ptr.add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let event_data = val.event_data;
|
||||||
|
for i in 0..event_data_size {
|
||||||
|
res[i + res_size - event_data_size] = event_data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,9 @@
|
||||||
|
|
||||||
outputs = [
|
outputs = [
|
||||||
"out"
|
"out"
|
||||||
|
"rtmr_calc"
|
||||||
|
"sha384_extend"
|
||||||
|
"tdx_extend"
|
||||||
"tee_key_preexec"
|
"tee_key_preexec"
|
||||||
"tee_ratls_preexec"
|
"tee_ratls_preexec"
|
||||||
"tee_self_attestation_test"
|
"tee_self_attestation_test"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue