Skip to content

Commit

Permalink
messages WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
labbott committed Jul 25, 2024
1 parent 1d784b8 commit ec7a737
Show file tree
Hide file tree
Showing 9 changed files with 321 additions and 10 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ ron = "0.8"
rpassword = "7.3.1"
salty = { version = "0.3", default-features = false }
serde = { version = "1", default-features = false }
serde_repr = { version = "0.1", default-features = false }
serde-big-array = "0.5"
serde_json = { version = "1", features = ["std", "alloc"] }
serde_with = { version = "3.6", default-features = false }
Expand Down
1 change: 1 addition & 0 deletions attest-data/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ hubpack.workspace = true
thiserror = { workspace = true, optional = true }
salty.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_repr.workspace = true
serde_with = { workspace = true, features = ["macros"] }
sha3.workspace = true

Expand Down
2 changes: 2 additions & 0 deletions attest-data/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use sha3::{
Sha3_256Core,
};

pub mod messages;

#[cfg(feature = "std")]
use thiserror::Error;

Expand Down
288 changes: 288 additions & 0 deletions attest-data/src/messages.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,288 @@
use crate::NONCE_SIZE;
use hubpack::SerializedSize;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};

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)
pub const MAX_DATA_LEN: usize = NONCE_SIZE;

pub const MAX_REQUEST_SIZE: usize =
HostRotHeader::MAX_SIZE + HostToRotCommand::MAX_SIZE + MAX_DATA_LEN;

pub mod version {
pub const V1: u32 = 1;
}

#[derive(
Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, SerializedSize,
)]
pub struct HostRotHeader {
magic: u32,
version: u32,
}

impl Default for HostRotHeader {
fn default() -> Self {
Self::new()
}
}

impl HostRotHeader {
pub fn new() -> Self {
Self {
magic: ATTEST_MAGIC,
version: version::V1,
}
}
}

#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
Deserialize,
Serialize,
SerializedSize,
)]
#[repr(u32)]
pub enum HostToRotCommand {
/// Returns the certificate chain associated with the RoT
GetCertificates = 0,
/// Returns the measurement log
GetMeasurementLog = 1,
/// Calculates sign(sha3_256(hubpack(measurement_log) | nonce))
/// and returns the result.
Attest = 2,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
//#[repr(u32)]
pub enum HostToRotError {
_Unused,
/// Header magic was incorrect
MagicMismatch,
/// Mismatch of protocol versions
VersionMismatch,
/// Message failed to deserialize
Deserialize,
/// Wrong length of data arguments (expected no data or incorrect length)
IncorrectDataLen,
/// Unexpected command returned
UnexpectedCommand,
/// Error return from the sprot command
SprotError(SprotError),
}

#[derive(
Debug, Clone, Copy, PartialEq, Eq, Deserialize_repr, Serialize_repr,
)]
#[repr(u32)]
// Errors returned from the hubris side. This is _so many_
pub enum SprotError {
// protocol
/// CRC check failed.
ProtocolInvalidCrc,
/// FIFO overflow/underflow
ProtocolFlowError,
/// Unsupported protocol version
ProtocolUnsupportedProtocol,
/// Unknown message
ProtocolBadMessageType,
/// Transfer size is outside of maximum and minimum lenghts for message type.
ProtocolBadMessageLength,
// We cannot assert chip select
ProtocolCannotAssertCSn,
// The request timed out
ProtocolTimeout,
// Hubpack error
ProtocolDeserialization,
// The RoT has not de-asserted ROT_IRQ
ProtocolRotIrqRemainsAsserted,
// An unexpected response was received.
// This should basically be impossible. We only include it so we can
// return this error when unpacking a RspBody in idol calls.
ProtocolUnexpectedResponse,
// Failed to load update status
ProtocolBadUpdateStatus,
// Used for mapping From<idol_runtime::ServerDeath>
ProtocolTaskRestarted,
// The SP and RoT did not agree on whether the SP is sending
// a request or waiting for a reply.
ProtocolDesynchronized,

// Spi
SpiBadTransferSize,
SpiTaskRestarted,

// Update -- this should not get returned
UpdateError,
// Sprockets is deprecated but we still keep the error type
SprocketsError,
// Watchdog error, we should not get this
WatchdogError,

// Attest errors
AttestCertTooBig,
AttestInvalidCertIndex,
AttestNoCerts,
AttestOutOfRange,
AttestLogFull,
AttestLogTooBig,
AttestTaskRestarted,
AttestBadLease,
AttestUnsupportedAlgorithm,
AttestSerializeLog,
AttestSerializeSignature,
AttestSignatureTooBig,
}

impl From<HubpackError> for HostToRotError {
fn from(_: HubpackError) -> Self {
Self::Deserialize
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
pub enum RotToHost {
HostToRotError(HostToRotError),
RotCertificates,
RotMeasurementLog,
RotAttestation,
}

impl From<SprotError> for RotToHost {
fn from(e: SprotError) -> Self {
RotToHost::HostToRotError(HostToRotError::SprotError(e))
}
}

pub fn deserialize<T: DeserializeOwned>(
data: &[u8],
) -> Result<(HostRotHeader, T, &[u8]), HostToRotError> {
let (header, leftover) = hubpack::deserialize::<HostRotHeader>(data)?;
let (command, leftover) = hubpack::deserialize::<T>(leftover)?;

Ok((header, command, leftover))
}

pub fn parse_message(
buf: &[u8],
) -> Result<(HostToRotCommand, &[u8]), HostToRotError> {
let (header, command, leftover) = deserialize::<HostToRotCommand>(buf)?;

if header.magic != ATTEST_MAGIC {
return Err(HostToRotError::MagicMismatch);
}

if header.version != version::V1 {
return Err(HostToRotError::VersionMismatch);
}

match command {
// These commands don't take data
HostToRotCommand::GetCertificates
| HostToRotCommand::GetMeasurementLog => {
if !leftover.is_empty() {
return Err(HostToRotError::IncorrectDataLen);
}
}
HostToRotCommand::Attest => {
if leftover.len() != NONCE_SIZE {
return Err(HostToRotError::IncorrectDataLen);
}
}
}

Ok((command, leftover))
}

pub fn parse_response(
buf: &[u8],
expected: RotToHost,
) -> Result<&[u8], HostToRotError> {
let (header, command, leftover) = deserialize::<RotToHost>(buf)?;

if header.magic != ATTEST_MAGIC {
return Err(HostToRotError::MagicMismatch);
}

if header.version != version::V1 {
return Err(HostToRotError::VersionMismatch);
}

if command != expected {
return Err(HostToRotError::UnexpectedCommand);
}
Ok(leftover)
}

fn raw_serialize<F, S>(
out: &mut [u8],
header: &HostRotHeader,
command: &S,
fill_data: F,
) -> Result<usize, HubpackError>
where
F: FnOnce(&mut [u8]) -> Result<usize, S>,
S: Serialize,
{
let header_len = hubpack::serialize(out, header)?;
let mut n = header_len;

let out_data_end = out.len();

n += hubpack::serialize(&mut out[n..out_data_end], command)?;

match fill_data(&mut out[n..out_data_end]) {
Ok(data_this_message) => {
assert!(data_this_message <= out_data_end - n);
n += data_this_message;
}
Err(e) => {
n = header_len;
n += hubpack::serialize(&mut out[n..out_data_end], &e)?;
}
}

Ok(n)
}

pub fn try_serialize<F, S>(
out: &mut [u8],
command: &S,
fill_data: F,
) -> Result<usize, HubpackError>
where
F: FnOnce(&mut [u8]) -> Result<usize, S>,
S: Serialize,
{
let header = HostRotHeader {
magic: ATTEST_MAGIC,
version: version::V1,
};

raw_serialize(out, &header, command, fill_data)
}

pub fn serialize<F>(
out: &mut [u8],
command: &impl Serialize,
fill_data: F,
) -> Result<usize, HubpackError>
where
F: FnOnce(&mut [u8]) -> usize,
{
let header = HostRotHeader {
magic: ATTEST_MAGIC,
version: version::V1,
};

raw_serialize(out, &header, command, |buf| Ok(fill_data(buf)))
}
12 changes: 6 additions & 6 deletions dice-cert-tmpl/src/csr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,15 @@ mod tests {
];

#[rustfmt::skip]
const PUB: &'static [u8] = &[
const PUB: &[u8] = &[
0x27, 0xfb, 0x87, 0x77, 0x77, 0x36, 0x54, 0xfb,
0x78, 0xb3, 0x46, 0x6b, 0x95, 0x0e, 0x15, 0x2b,
0x8b, 0xcd, 0x0c, 0x9b, 0x8a, 0x08, 0xfc, 0x7a,
0xef, 0x68, 0x97, 0x1e, 0xab, 0xa0, 0x87, 0x70,
];

#[rustfmt::skip]
const SIG: &'static [u8] = &[
const SIG: &[u8] = &[
0xf5, 0xf5, 0xcf, 0xde, 0x58, 0x87, 0x6a, 0x0e,
0xa6, 0xb3, 0x3f, 0x23, 0x98, 0xd6, 0x97, 0x0c,
0x3a, 0xaa, 0xb2, 0xdf, 0xa0, 0x6e, 0x5b, 0xf7,
Expand All @@ -186,7 +186,7 @@ mod tests {
];

#[rustfmt::skip]
const SIGNDATA: &'static [u8] = &[
const SIGNDATA: &[u8] = &[
0x30, 0x81, 0x90, 0x02, 0x01, 0x00, 0x30, 0x5d,
0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x10, 0x30,
Expand All @@ -210,7 +210,7 @@ mod tests {

#[test]
fn get_pub_offsets() -> Result {
let mut csr = CSR.clone();
let mut csr = CSR;
let csr = Csr::from_slice(&mut csr);
let (start, end) = csr.get_pub_offsets()?;
assert_eq!(&csr.as_bytes()[start..end], PUB);
Expand All @@ -219,7 +219,7 @@ mod tests {

#[test]
fn get_sig_offsets() -> Result {
let mut csr = CSR.clone();
let mut csr = CSR;
let csr = Csr::from_slice(&mut csr);
let (start, end) = csr.get_sig_offsets()?;
assert_eq!(&csr.as_bytes()[start..end], SIG);
Expand All @@ -228,7 +228,7 @@ mod tests {

#[test]
fn get_signdata_offsets() -> Result {
let mut csr = CSR.clone();
let mut csr = CSR;
let csr = Csr::from_slice(&mut csr);
let (start, end) = csr.get_signdata_offsets()?;
assert_eq!(&csr.as_bytes()[start..end], SIGNDATA);
Expand Down
Loading

0 comments on commit ec7a737

Please sign in to comment.