-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
321 additions
and
10 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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 |
---|---|---|
|
@@ -13,6 +13,8 @@ use sha3::{ | |
Sha3_256Core, | ||
}; | ||
|
||
pub mod messages; | ||
|
||
#[cfg(feature = "std")] | ||
use thiserror::Error; | ||
|
||
|
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,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))) | ||
} |
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
Oops, something went wrong.