diff --git a/Cargo.lock b/Cargo.lock index 2b58ffaa93..bbac5042e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -546,8 +546,18 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "757c0ded2af11d8e739c4daea1ac623dd1624b06c844cf3f5a39f1bdbd99bb12" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.13.0", + "darling_macro 0.13.0", +] + +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core 0.20.3", + "darling_macro 0.20.3", ] [[package]] @@ -564,17 +574,42 @@ dependencies = [ "syn 1.0.94", ] +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.29", +] + [[package]] name = "darling_macro" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade7bff147130fe5e6d39f089c6bd49ec0250f35d70b2eebf72afdfc919f15cc" dependencies = [ - "darling_core", + "darling_core 0.13.0", "quote", "syn 1.0.94", ] +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core 0.20.3", + "quote", + "syn 2.0.29", +] + [[package]] name = "demo-stm32f4-discovery" version = "0.1.0" @@ -3142,7 +3177,7 @@ dependencies = [ "num-traits", "ron", "serde", - "serde_with", + "serde_with 1.11.0", ] [[package]] @@ -3518,9 +3553,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.147" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] @@ -3545,13 +3580,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.147" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 1.0.94", + "syn 2.0.29", ] [[package]] @@ -3593,7 +3628,17 @@ checksum = "ad6056b4cb69b6e43e3a0f055def223380baecc99da683884f205bf347f7c4b3" dependencies = [ "rustversion", "serde", - "serde_with_macros", + "serde_with_macros 1.5.1", +] + +[[package]] +name = "serde_with" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ca3b16a3d82c4088f343b7480a93550b3eabe1a358569c2dfe38bbcead07237" +dependencies = [ + "serde", + "serde_with_macros 3.3.0", ] [[package]] @@ -3602,12 +3647,24 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12e47be9471c72889ebafb5e14d5ff930d89ae7a67bbdb5f8abb564f845a927e" dependencies = [ - "darling", + "darling 0.13.0", "proc-macro2", "quote", "syn 1.0.94", ] +[[package]] +name = "serde_with_macros" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e6be15c453eb305019bfa438b1593c731f36a289a7853f7707ee29e870b3b3c" +dependencies = [ + "darling 0.20.3", + "proc-macro2", + "quote", + "syn 2.0.29", +] + [[package]] name = "sha2" version = "0.10.6" @@ -3930,9 +3987,11 @@ dependencies = [ "idol", "idol-runtime", "lib-dice", + "mutable-statics", "num-traits", "ringbuf", "serde", + "serde_with 3.3.0", "sha3", "stage0-handoff", "unwrap-lite", diff --git a/app/lpc55xpresso/app.toml b/app/lpc55xpresso/app.toml index d62195c81c..465aeb8287 100644 --- a/app/lpc55xpresso/app.toml +++ b/app/lpc55xpresso/app.toml @@ -142,7 +142,7 @@ extern-regions = ["sram2"] [tasks.attest] name = "task-attest" priority = 5 -max-sizes = {flash = 13600, ram = 16384} +max-sizes = {flash = 14800, ram = 16384} stacksize = 9304 start = true extern-regions = ["dice_alias", "dice_certs"] diff --git a/app/oxide-rot-1/app-dev.toml b/app/oxide-rot-1/app-dev.toml index 499fdf69ec..21580a7d67 100644 --- a/app/oxide-rot-1/app-dev.toml +++ b/app/oxide-rot-1/app-dev.toml @@ -158,7 +158,7 @@ binary_path = "../../target/gimlet-c/dist/default/final.bin" [tasks.attest] name = "task-attest" priority = 5 -max-sizes = {flash = 13600, ram = 16384} +max-sizes = {flash = 14800, ram = 16384} stacksize = 9304 start = true extern-regions = ["dice_alias", "dice_certs"] diff --git a/app/oxide-rot-1/app.toml b/app/oxide-rot-1/app.toml index 78e46c0d81..d6a06d2ee8 100644 --- a/app/oxide-rot-1/app.toml +++ b/app/oxide-rot-1/app.toml @@ -137,7 +137,7 @@ task-slots = ["swd"] [tasks.attest] name = "task-attest" priority = 5 -max-sizes = {flash = 13600, ram = 16384} +max-sizes = {flash = 14800, ram = 16384} stacksize = 9304 start = true extern-regions = ["dice_alias", "dice_certs"] diff --git a/app/rot-carrier/app.toml b/app/rot-carrier/app.toml index 25f3fc5c06..2bb8aa23a7 100644 --- a/app/rot-carrier/app.toml +++ b/app/rot-carrier/app.toml @@ -204,8 +204,8 @@ binary_path = "../../target/gemini-bu/dist/final.bin" [tasks.attest] name = "task-attest" priority = 5 -max-sizes = {flash = 13600, ram = 16384} -stacksize = 9304 +max-sizes = {flash = 14800, ram = 16384} +stacksize = 9952 start = true extern-regions = ["dice_alias", "dice_certs"] diff --git a/idl/attest.idol b/idl/attest.idol index e28216d280..1baf4c0d4c 100644 --- a/idl/attest.idol +++ b/idl/attest.idol @@ -55,5 +55,28 @@ Interface( ), encoding: Hubpack, ), + "log": ( + doc: "Get the measurement log", + args: { + "offset" : "u32", + }, + leases: { + "dest": (type: "[u8]", write: true), + }, + reply: Result( + ok: "()", + err: Complex("AttestError"), + ), + encoding: Hubpack, + ), + "log_len": ( + doc: "Get length of the serialized measurement log", + reply: Result( + ok: "u32", + err: Complex("AttestError"), + ), + encoding: Hubpack, + idempotent: true, + ), } ) diff --git a/task/attest-api/src/lib.rs b/task/attest-api/src/lib.rs index 309f7e4803..9b69350633 100644 --- a/task/attest-api/src/lib.rs +++ b/task/attest-api/src/lib.rs @@ -18,10 +18,12 @@ pub enum AttestError { InvalidCertIndex, NoCerts, OutOfRange, - MeasurementLogFull, + LogFull, + LogTooBig, TaskRestarted, BadLease, UnsupportedAlgorithm, + SerializeLog, } impl From for AttestError { diff --git a/task/attest/Cargo.toml b/task/attest/Cargo.toml index 4702e1039d..6f4d79a5c0 100644 --- a/task/attest/Cargo.toml +++ b/task/attest/Cargo.toml @@ -9,9 +9,11 @@ crypto-common = { workspace = true } lib-dice = { path = "../../lib/dice" } hubpack = { workspace = true } idol-runtime = { workspace = true } +mutable-statics = { path = "../../lib/mutable-statics" } num-traits = { workspace = true } ringbuf = { path = "../../lib/ringbuf" } serde = { workspace = true } +serde_with = { version = "3.3.0", default-features = false, features = ["macros"] } stage0-handoff = { path = "../../lib/stage0-handoff" } attest-api = { path = "../attest-api" } sha3 = { workspace = true } diff --git a/task/attest/src/main.rs b/task/attest/src/main.rs index d45f277a63..e022cc4ddf 100644 --- a/task/attest/src/main.rs +++ b/task/attest/src/main.rs @@ -18,8 +18,10 @@ use crypto_common::{typenum::Unsigned, OutputSizeUser}; use hubpack::SerializedSize; use idol_runtime::{ClientError, Leased, RequestError, W}; use lib_dice::{AliasData, CertData}; +use mutable_statics::mutable_statics; use ringbuf::{ringbuf, ringbuf_entry}; -use serde::Deserialize; +use serde::{Deserialize, Serialize}; +use serde_with::serde_as; use sha3::Sha3_256Core; use stage0_handoff::{HandoffData, HandoffDataLoadError}; use zerocopy::AsBytes; @@ -46,6 +48,8 @@ enum Trace { Startup, Record(HashAlgorithm), BadLease(usize), + LogLen(u32), + Log, None, } @@ -84,8 +88,9 @@ const SHA3_256_DIGEST_SIZE: usize = const CAPACITY: usize = 16; // Digest is a fixed length array of bytes -#[derive(Clone, Copy, Debug, PartialEq)] -struct Digest([u8; N]); +#[serde_as] +#[derive(Clone, Copy, Debug, PartialEq, Serialize, SerializedSize)] +struct Digest(#[serde_as(as = "[_; N]")] [u8; N]); impl Default for Digest { fn default() -> Self { @@ -96,7 +101,7 @@ impl Default for Digest { type Sha3_256Digest = Digest; // Measurement is an enum that can hold any of the supported hash algorithms -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, Serialize, SerializedSize)] enum Measurement { Sha3_256(Sha3_256Digest), } @@ -129,16 +134,19 @@ impl Default for Measurement { } } -// Would have been nice to use ArrayVec but it's particularly difficult to -// use with hubpack. +// ArrayVec has everything we need but isn't compatible with hubpack. We only +// need a small subset of its functionality so this saves us some flash. +#[serde_as] +#[derive(Serialize, SerializedSize)] struct Log { - index: usize, + index: u32, + #[serde_as(as = "[_; N]")] measurements: [Measurement; N], } impl Log { fn is_full(&self) -> bool { - if self.index == N { + if self.index as usize == N { true } else { false @@ -147,7 +155,7 @@ impl Log { fn push(&mut self, measurement: Measurement) -> bool { if !self.is_full() { - self.measurements[self.index] = measurement; + self.measurements[self.index as usize] = measurement; self.index += 1; true } else { @@ -167,14 +175,19 @@ impl Default for Log { struct AttestServer { alias_data: Option, + buf: &'static mut [u8; Log::::MAX_SIZE], cert_data: Option, measurements: Log, } impl Default for AttestServer { fn default() -> Self { + let buf = mutable_statics! { + static mut LOG_BUF: [u8; Log::::MAX_SIZE] = [|| 0; _]; + }; Self { alias_data: load_data_from_region(&ALIAS_DATA), + buf, cert_data: load_data_from_region(&CERT_DATA), measurements: Log::::default(), } @@ -293,13 +306,44 @@ impl idl::InOrderAttestImpl for AttestServer { ringbuf_entry!(Trace::Record(algorithm)); if self.measurements.is_full() { - return Err(AttestError::MeasurementLogFull.into()); + return Err(AttestError::LogFull.into()); } self.measurements.push(Measurement::new(algorithm, data)?); Ok(()) } + + fn log( + &mut self, + _: &userlib::RecvMessage, + offset: u32, + dest: Leased, + ) -> Result<(), RequestError> { + ringbuf_entry!(Trace::Log); + + hubpack::serialize(self.buf, &self.measurements) + .map_err(|_| AttestError::SerializeLog)?; + + let offset = offset as usize; + dest.write_range(0..dest.len(), &self.buf[offset..offset + dest.len()]) + .map_err(|_| RequestError::Fail(ClientError::WentAway))?; + + Ok(()) + } + + fn log_len( + &mut self, + _: &userlib::RecvMessage, + ) -> Result> { + let len = hubpack::serialize(self.buf, &self.measurements) + .map_err(|_| AttestError::SerializeLog)?; + let len = u32::try_from(len).map_err(|_| AttestError::LogTooBig)?; + + ringbuf_entry!(Trace::LogLen(len)); + + Ok(len) + } } #[export_name = "main"]