diff --git a/Cargo.lock b/Cargo.lock index ed2419c..354b74c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -122,6 +122,7 @@ dependencies = [ "serde", "serde_with", "sha3", + "static_assertions", "thiserror", ] @@ -1298,6 +1299,12 @@ dependencies = [ "der", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "string-error" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index cac28e5..a95db74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ serde_with = { version = "3.6", default-features = false } serialport = { git = "https://github.com/jgallagher/serialport-rs", branch = "illumos-support" } sha2 = "0.10" sha3 = { version = "0.10", default-features = false } +static_assertions = { version = "1", default-features = false } string-error = "0.1" tempfile = { version = "3", default-features = false } thiserror = "1.0.57" diff --git a/attest-data/Cargo.toml b/attest-data/Cargo.toml index c1fe700..21242dc 100644 --- a/attest-data/Cargo.toml +++ b/attest-data/Cargo.toml @@ -11,6 +11,7 @@ salty.workspace = true serde = { workspace = true, features = ["derive"] } serde_with = { workspace = true, features = ["macros"] } sha3.workspace = true +static_assertions.workspace = true [features] std = ["getrandom", "thiserror"] diff --git a/attest-data/src/messages.rs b/attest-data/src/messages.rs index fcdec01..be36995 100644 --- a/attest-data/src/messages.rs +++ b/attest-data/src/messages.rs @@ -2,18 +2,21 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -use crate::NONCE_SIZE; +use crate::{NONCE_SIZE, SHA3_256_DIGEST_SIZE}; +use hubpack::error::Error as HubpackError; use hubpack::SerializedSize; use serde::{de::DeserializeOwned, Deserialize, Serialize}; -use hubpack::error::Error as HubpackError; - /// Magic value for [`Header::magic`] pub const ATTEST_MAGIC: u32 = 0xA77E5700; -/// Right now `Attest` is the only command that takes data (nonce) +/// Right now `Attest` and `TqSign` are the only commands that take data +/// argumenets. They happen to be the same length but to be extra cautious +/// add a static assertion. pub const MAX_DATA_LEN: usize = NONCE_SIZE; +static_assertions::const_assert!(SHA3_256_DIGEST_SIZE == 32); + pub const MAX_REQUEST_SIZE: usize = HostRotHeader::MAX_SIZE + HostToRotCommand::MAX_SIZE + MAX_DATA_LEN; @@ -49,13 +52,17 @@ impl HostRotHeader { )] #[repr(u32)] pub enum HostToRotCommand { - /// Returns the certificate chain associated with the RoT + /// Returns the certificate chain associated with the RoT-M GetCertificates, /// Returns the measurement log GetMeasurementLog, /// Calculates sign(sha3_256(hubpack(measurement_log) | nonce)) /// and returns the result. Attest, + /// Returns the certificate chain associated with TQ + GetTqCertificates, + /// Signs a sha3_256 message with the TQ key + TqSign, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)] @@ -151,6 +158,8 @@ pub enum RotToHost { RotCertificates, RotMeasurementLog, RotAttestation, + RotTqCertificates, + RotTqSign, } impl From for RotToHost { @@ -185,7 +194,8 @@ pub fn parse_message( match command { // These commands don't take data HostToRotCommand::GetCertificates - | HostToRotCommand::GetMeasurementLog => { + | HostToRotCommand::GetMeasurementLog + | HostToRotCommand::GetTqCertificates => { if !leftover.is_empty() { return Err(HostToRotError::IncorrectDataLen); } @@ -195,6 +205,11 @@ pub fn parse_message( return Err(HostToRotError::IncorrectDataLen); } } + HostToRotCommand::TqSign => { + if leftover.len() != SHA3_256_DIGEST_SIZE { + return Err(HostToRotError::IncorrectDataLen); + } + } } Ok((command, leftover)) diff --git a/verifier/src/lib.rs b/verifier/src/lib.rs index 04f5f0d..5b9faa6 100644 --- a/verifier/src/lib.rs +++ b/verifier/src/lib.rs @@ -229,6 +229,26 @@ impl PkiPathSignatureVerifier { } } +pub fn verify_signature( + alias: &Certificate, + hash: &[u8], + signature: &[u8], +) -> Result<()> { + use ed25519_dalek::{Signature, Verifier, VerifyingKey}; + + let signature = Signature::from_slice(signature)?; + + let alias = alias + .tbs_certificate + .subject_public_key_info + .subject_public_key + .as_bytes() + .ok_or_else(|| anyhow!("Invalid / unaligned public key"))?; + + let verifying_key = VerifyingKey::from_bytes(alias.try_into()?)?; + Ok(verifying_key.verify(hash, &signature)?) +} + pub fn verify_attestation( alias: &Certificate, attestation: &Attestation,