Skip to content

Commit

Permalink
attest: Add function to record a measurement observed by the platform.
Browse files Browse the repository at this point in the history
This function is *not* idempotent: if the 'record' function is called
with the same parameters repeatedly the measurement log will eventually
fill up resulting in an error. The measurement log is just an array of
measurements (aka [u8; 32]) that is managed in an ArrayVec. The 'record'
function takes an enum parameter identifying the hash algorithm and a
lease holding the digest. We pass the digest as a lease partially because
humility / hiffy can't pass arbitrary arrays as parameters, but also
because it's possible that in the future we'll need to support digests
with varying lengths.
  • Loading branch information
flihp committed Aug 1, 2023
1 parent 82d536b commit 9898417
Show file tree
Hide file tree
Showing 11 changed files with 121 additions and 13 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ path = "sys/abi"

[workspace.dependencies]
anyhow = { version = "1.0.31", default-features = false, features = ["std"] }
arrayvec = { version = "0.7.4", default-features = false }
atty = { version = "0.2", default-features = false }
bitfield = { version = "0.13", default-features = false }
bitflags = { version = "1.2.1", default-features = false }
Expand All @@ -46,6 +47,7 @@ cortex-m = { version = "0.7", default-features = false, features = ["inline-asm"
cortex-m-rt = { version = "0.6.12", default-features = false }
cortex-m-semihosting = { version = "0.5.0", default-features = false }
crc = { version = "3.0.0", default-features = false }
crypto-common = { version = "0.1.6", default-features = false }
ctrlc = { version = "3.1.5", default-features = false }
derive_more = { version = "0.99", default-features = false, features = ["from", "into"] }
digest = { version = "0.10", default-features = false }
Expand Down
4 changes: 2 additions & 2 deletions app/lpc55xpresso/app-sprot.toml
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,8 @@ pins = [
[tasks.attest]
name = "task-attest"
priority = 5
max-sizes = {flash = 12512, ram = 16384}
stacksize = 9000
max-sizes = {flash = 13600, ram = 16384}
stacksize = 9304
start = true
extern-regions = ["dice_alias", "dice_certs"]

Expand Down
4 changes: 2 additions & 2 deletions app/lpc55xpresso/app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ extern-regions = ["sram2"]
[tasks.attest]
name = "task-attest"
priority = 5
max-sizes = {flash = 12256, ram = 16384}
stacksize = 9000
max-sizes = {flash = 13600, ram = 16384}
stacksize = 9304
start = true
extern-regions = ["dice_alias", "dice_certs"]

Expand Down
4 changes: 2 additions & 2 deletions app/oxide-rot-1/app-dev.toml
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ binary_path = "../../target/gimlet-c/dist/default/final.bin"
[tasks.attest]
name = "task-attest"
priority = 5
max-sizes = {flash = 12512, ram = 16384}
stacksize = 9000
max-sizes = {flash = 13600, ram = 16384}
stacksize = 9304
start = true
extern-regions = ["dice_alias", "dice_certs"]

Expand Down
4 changes: 2 additions & 2 deletions app/oxide-rot-1/app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ task-slots = ["swd"]
[tasks.attest]
name = "task-attest"
priority = 5
max-sizes = {flash = 12256, ram = 16384}
stacksize = 9000
max-sizes = {flash = 13600, ram = 16384}
stacksize = 9304
start = true
extern-regions = ["dice_alias", "dice_certs"]

Expand Down
4 changes: 2 additions & 2 deletions app/rot-carrier/app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,8 @@ binary_path = "../../target/gemini-bu/dist/final.bin"
[tasks.attest]
name = "task-attest"
priority = 5
max-sizes = {flash = 12256, ram = 16384}
stacksize = 9000
max-sizes = {flash = 13600, ram = 16384}
stacksize = 9304
start = true
extern-regions = ["dice_alias", "dice_certs"]

Expand Down
16 changes: 15 additions & 1 deletion idl/attest.idol
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ Interface(
),
encoding: Hubpack,
idempotent: true,
)
),
"record": (
doc: "Record a measurment",
args: {
"algorithm": "HashAlgorithm",
},
leases: {
"data": (type: "[u8]", read: true),
},
reply: Result(
ok: "()",
err: Complex("AttestError"),
),
encoding: Hubpack,
),
}
)
17 changes: 17 additions & 0 deletions task/attest-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@ pub enum AttestError {
InvalidCertIndex,
NoCerts,
OutOfRange,
MeasurementLogFull,
TaskRestarted,
BadLease,
UnsupportedAlgorithm,
}

impl From<idol_runtime::ServerDeath> for AttestError {
fn from(_: idol_runtime::ServerDeath) -> Self {
AttestError::TaskRestarted
}
}

#[derive(
Copy, Clone, Debug, Deserialize, Eq, PartialEq, Serialize, SerializedSize,
)]
pub enum HashAlgorithm {
Sha3_256,
}

include!(concat!(env!("OUT_DIR"), "/client_stub.rs"));
3 changes: 3 additions & 0 deletions task/attest/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ version = "0.1.0"
edition = "2021"

[dependencies]
arrayvec.workspace = true
crypto-common = { workspace = true }
lib-dice = { path = "../../lib/dice" }
hubpack = { workspace = true }
idol-runtime = { workspace = true }
Expand All @@ -12,6 +14,7 @@ ringbuf = { path = "../../lib/ringbuf" }
serde = { workspace = true }
stage0-handoff = { path = "../../lib/stage0-handoff" }
attest-api = { path = "../attest-api" }
sha3 = { workspace = true }
unwrap-lite = { path = "../../lib/unwrap-lite" }
userlib = { path = "../../sys/userlib", features = ["panic-messages"] }
zerocopy = { workspace = true }
Expand Down
67 changes: 65 additions & 2 deletions task/attest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@

mod config;

use attest_api::AttestError;
use arrayvec::ArrayVec;
use attest_api::{AttestError, HashAlgorithm};
use config::DataRegion;
use core::slice;
use crypto_common::{typenum::Unsigned, OutputSizeUser};
use hubpack::SerializedSize;
use idol_runtime::{ClientError, Leased, RequestError, W};
use lib_dice::{AliasData, CertData};
use ringbuf::{ringbuf, ringbuf_entry};
use serde::Deserialize;
use sha3::Sha3_256Core;
use stage0_handoff::{HandoffData, HandoffDataLoadError};
use zerocopy::AsBytes;

Expand All @@ -42,6 +45,8 @@ enum Trace {
Index(u32),
Offset(u32),
Startup,
Record(HashAlgorithm),
BadLease(usize),
None,
}

Expand Down Expand Up @@ -70,16 +75,57 @@ fn load_data_from_region<
}
}

// the size of the measurements we record
// NOTE: the rust crypto digest traits don't expose consts for the lengths
// of various hash functions
const SHA3_256_DIGEST_SIZE: usize =
<Sha3_256Core as OutputSizeUser>::OutputSize::USIZE;

// the number of Measurements we can record
const CAPACITY: usize = 16;

#[derive(Clone, Copy, Debug, PartialEq)]
struct Digest<const N: usize>([u8; N]);

#[derive(Clone, Copy, Debug, PartialEq)]
enum Measurement {
Sha3_256(Digest<SHA3_256_DIGEST_SIZE>),
}

impl Measurement {
fn new(
algorithm: HashAlgorithm,
data: idol_runtime::Leased<idol_runtime::R, [u8]>,
) -> Result<Self, RequestError<AttestError>> {
Ok(match algorithm {
HashAlgorithm::Sha3_256 => {
if data.len() != SHA3_256_DIGEST_SIZE {
ringbuf_entry!(Trace::BadLease(data.len()));
return Err(AttestError::BadLease.into());
}

let mut digest = Digest([0u8; SHA3_256_DIGEST_SIZE]);
data.read_range(0..digest.0.len(), &mut digest.0)
.map_err(|_| RequestError::went_away())?;

Measurement::Sha3_256(digest)
}
})
}
}

struct AttestServer {
alias_data: Option<AliasData>,
cert_data: Option<CertData>,
measurements: ArrayVec<Measurement, CAPACITY>,
}

impl Default for AttestServer {
fn default() -> Self {
Self {
alias_data: load_data_from_region(&ALIAS_DATA),
cert_data: load_data_from_region(&CERT_DATA),
measurements: ArrayVec::<Measurement, CAPACITY>::new(),
}
}
}
Expand Down Expand Up @@ -190,6 +236,23 @@ impl idl::InOrderAttestImpl for AttestServer {

Ok(())
}

fn record(
&mut self,
_: &userlib::RecvMessage,
algorithm: HashAlgorithm,
data: idol_runtime::Leased<idol_runtime::R, [u8]>,
) -> Result<(), RequestError<AttestError>> {
ringbuf_entry!(Trace::Record(algorithm));

if self.measurements.is_full() {
return Err(AttestError::MeasurementLogFull.into());
}

self.measurements.push(Measurement::new(algorithm, data)?);

Ok(())
}
}

#[export_name = "main"]
Expand All @@ -204,7 +267,7 @@ fn main() -> ! {
}

mod idl {
use super::AttestError;
use super::{AttestError, HashAlgorithm};

include!(concat!(env!("OUT_DIR"), "/server_stub.rs"));
}

0 comments on commit 9898417

Please sign in to comment.