Skip to content

Commit

Permalink
sprot: Plumbing to get the cert chain out of the attest task.
Browse files Browse the repository at this point in the history
This enables humility to get the cert chain from the RoT attest task by
way of the SP hiffy interface. This allows us to get the cert chain from
the RoT on production systems where the RoT is configured to disable the
debug port.
  • Loading branch information
flihp committed Jun 23, 2023
1 parent d8ef2de commit b695b58
Show file tree
Hide file tree
Showing 13 changed files with 252 additions and 24 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

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

6 changes: 3 additions & 3 deletions app/lpc55xpresso/app-sprot.toml
Original file line number Diff line number Diff line change
Expand Up @@ -183,14 +183,14 @@ task-slots = ["swd"]
[tasks.sprot]
name = "drv-lpc55-sprot-server"
priority = 6
max-sizes = {flash = 33056, ram = 32768}
max-sizes = {flash = 44000, ram = 32768}
uses = ["flexcomm8", "bootrom"]
features = ["spi0"]
start = true
notifications = ["spi-irq"]
interrupts = {"flexcomm8.hs_spi" = "spi-irq"}
stacksize = 16384
task-slots = ["gpio_driver", "syscon_driver", "update_server", "dumper"]
task-slots = ["gpio_driver", "syscon_driver", "update_server", "dumper", "attest"]

[tasks.sprot.config]
pins = [
Expand All @@ -211,7 +211,7 @@ pins = [
[tasks.attest]
name = "task-attest"
priority = 5
max-sizes = {flash = 12256, ram = 16384}
max-sizes = {flash = 12512, ram = 16384}
stacksize = 9000
start = true
extern-regions = ["dice_alias", "dice_certs"]
Expand Down
6 changes: 3 additions & 3 deletions app/oxide-rot-1/app-dev.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,14 @@ task-slots = ["syscon_driver"]
[tasks.sprot]
name = "drv-lpc55-sprot-server"
priority = 6
max-sizes = {flash = 34000, ram = 32768}
max-sizes = {flash = 44000, ram = 32768}
uses = ["flexcomm8", "bootrom"]
features = ["spi0"]
start = true
notifications = ["spi-irq"]
interrupts = {"flexcomm8.hs_spi" = "spi-irq"}
stacksize = 16384
task-slots = ["gpio_driver", "syscon_driver", "update_server", "dumper"]
task-slots = ["gpio_driver", "syscon_driver", "update_server", "dumper", "attest"]

[tasks.sprot.config]
pins = [
Expand Down Expand Up @@ -158,7 +158,7 @@ binary_path = "../../target/gimlet-c/dist/default/final.bin"
[tasks.attest]
name = "task-attest"
priority = 5
max-sizes = {flash = 12256, ram = 16384}
max-sizes = {flash = 12512, ram = 16384}
stacksize = 9000
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 @@ -68,14 +68,14 @@ task-slots = ["syscon_driver"]
[tasks.sprot]
name = "drv-lpc55-sprot-server"
priority = 6
max-sizes = {flash = 34000, ram = 32768}
max-sizes = {flash = 44000, ram = 32768}
uses = ["flexcomm8", "bootrom"]
features = ["spi0"]
start = true
notifications = ["spi-irq"]
interrupts = {"flexcomm8.hs_spi" = "spi-irq"}
stacksize = 16384
task-slots = ["gpio_driver", "syscon_driver", "update_server", "dumper"]
task-slots = ["gpio_driver", "syscon_driver", "update_server", "dumper", "attest"]

[tasks.sprot.config]
pins = [
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 @@ -108,14 +108,14 @@ task-slots = ["syscon_driver"]
[tasks.sprot]
name = "drv-lpc55-sprot-server"
priority = 6
max-sizes = {flash = 34000, ram = 32768}
max-sizes = {flash = 44000, ram = 32768}
uses = ["flexcomm8", "bootrom"]
features = ["spi0"]
start = true
notifications = ["spi-irq"]
interrupts = {"flexcomm8.hs_spi" = "spi-irq"}
stacksize = 16384
task-slots = ["gpio_driver", "syscon_driver", "update_server", "dumper"]
task-slots = ["gpio_driver", "syscon_driver", "update_server", "dumper", "attest"]

[tasks.sprot.config]
pins = [
Expand Down
1 change: 1 addition & 0 deletions drv/lpc55-sprot-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ sprockets-rot = { workspace = true }
static_assertions = { workspace = true }
zerocopy = { workspace = true }

attest-api = { path = "../../task/attest-api" }
drv-lpc55-gpio-api = { path = "../lpc55-gpio-api" }
drv-lpc55-spi = { path = "../lpc55-spi" }
drv-lpc55-syscon-api = { path = "../lpc55-syscon-api" }
Expand Down
77 changes: 69 additions & 8 deletions drv/lpc55-sprot-server/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use crate::Trace;
use attest_api::Attest;
use crc::{Crc, CRC_32_CKSUM};
use drv_lpc55_update_api::{SlotId, Update};
use drv_sprot_api::{
CabooseReq, CabooseRsp, DumpReq, DumpRsp, ReqBody, Request, Response,
RotIoStats, RotState, RotStatus, RspBody, SprocketsError, SprotError,
SprotProtocolError, UpdateReq, UpdateRsp, CURRENT_VERSION, MIN_VERSION,
REQUEST_BUF_SIZE, RESPONSE_BUF_SIZE,
AttestReq, AttestRsp, CabooseReq, CabooseRsp, DumpReq, DumpRsp, ReqBody,
Request, Response, RotIoStats, RotState, RotStatus, RspBody,
SprocketsError, SprotError, SprotProtocolError, UpdateReq, UpdateRsp,
CURRENT_VERSION, MIN_VERSION, REQUEST_BUF_SIZE, RESPONSE_BUF_SIZE,
};
use dumper_api::Dumper;
use lpc55_romapi::bootrom;
Expand All @@ -23,6 +24,8 @@ task_slot!(UPDATE_SERVER, update_server);

task_slot!(DUMPER, dumper);

task_slot!(ATTEST, attest);

pub const CRC32: Crc<u32> = Crc::<u32>::new(&CRC_32_CKSUM);

/// State that is set once at the start of the driver
Expand All @@ -42,12 +45,14 @@ pub struct StartupState {
/// Marker for data which should be copied after the packet is encoded
pub enum TrailingData {
Caboose { slot: SlotId, start: u32, size: u32 },
Attest { index: u32, offset: u32, size: u32 },
}

pub struct Handler {
sprocket: RotSprocket,
update: Update,
startup_state: StartupState,
attest: Attest,
}

impl Handler {
Expand All @@ -60,6 +65,7 @@ impl Handler {
max_request_size: REQUEST_BUF_SIZE.try_into().unwrap_lite(),
max_response_size: RESPONSE_BUF_SIZE.try_into().unwrap_lite(),
},
attest: Attest::from(ATTEST.get_task_id()),
}
}

Expand Down Expand Up @@ -90,7 +96,7 @@ impl Handler {

// In certain cases, handling the request has left us with trailing data
// that needs to be packed into the remaining packet space.
let size = match trailer {
match trailer {
Some(TrailingData::Caboose {
slot,
start,
Expand Down Expand Up @@ -121,10 +127,33 @@ impl Handler {
}
}
}
Some(TrailingData::Attest {
index,
offset,
size,
}) => {
let size: usize = usize::try_from(size).unwrap_lite();
if size > drv_sprot_api::MAX_BLOB_SIZE {
Response::pack(
&Err(SprotError::Protocol(
SprotProtocolError::BadMessageLength,
)),
tx_buf,
)
} else {
match Response::pack_with_cb(&rsp_body, tx_buf, |buf| {
self.attest
.cert(index, offset, &mut buf[..size])
.map_err(|e| RspBody::Attest(Err(e.into())))?;
Ok(size)
}) {
Ok(size) => size,
Err(e) => Response::pack(&Ok(e), tx_buf),
}
}
}
_ => Response::pack(&rsp_body, tx_buf),
};

size
}
}

pub fn handle_request(
Expand Down Expand Up @@ -232,6 +261,38 @@ impl Handler {
let boot_info = self.update.rot_boot_info()?;
Ok((RspBody::Update(boot_info.into()), None))
}
ReqBody::Attest(AttestReq::Cert {
index,
offset,
size,
}) => {
// This command returns a variable amount of data that belongs
// in the trailing data region of the response. We return a
// marker struct with the data necessary retrieve this data so
// the work can be done elsewhere.
Ok((
RspBody::Attest(Ok(AttestRsp::Cert)),
Some(TrailingData::Attest {
index,
offset,
size,
}),
))
}
ReqBody::Attest(AttestReq::CertChainLen) => {
let rsp = match self.attest.cert_chain_len() {
Ok(v) => Ok(AttestRsp::CertChainLen(v)),
Err(e) => Err(e),
};
Ok((RspBody::Attest(rsp), None))
}
ReqBody::Attest(AttestReq::CertLen(i)) => {
let rsp = match self.attest.cert_len(i) {
Ok(v) => Ok(AttestRsp::CertLen(v)),
Err(e) => Err(e),
};
Ok((RspBody::Attest(rsp), None))
}
}
}
}
1 change: 1 addition & 0 deletions drv/sprot-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ static_assertions.workspace = true
tlvc.workspace = true
zerocopy.workspace = true

attest-api = { path = "../../task/attest-api" }
derive-idol-err = { path = "../../lib/derive-idol-err" }
drv-caboose = { path = "../../drv/caboose" }
drv-lpc55-update-api = { path = "../../drv/lpc55-update-api" }
Expand Down
21 changes: 21 additions & 0 deletions drv/sprot-api/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

//! Errors for the sprot API

use attest_api::AttestError;
use derive_more::From;
use drv_caboose::CabooseError;
use drv_lpc55_update_api::RawCabooseError;
Expand Down Expand Up @@ -209,3 +210,23 @@ impl From<RawCabooseOrSprotError> for CabooseOrSprotError {
}
}
}

#[derive(Copy, Clone, Debug, From, Deserialize, Serialize, SerializedSize)]
pub enum AttestOrSprotError {
Sprot(SprotError),
Attest(AttestError),
}

impl From<SprotError> for RequestError<AttestOrSprotError> {
fn from(err: SprotError) -> Self {
AttestOrSprotError::from(err).into()
}
}

impl<V> From<AttestOrSprotError>
for Result<V, RequestError<AttestOrSprotError>>
{
fn from(err: AttestOrSprotError) -> Self {
Err(RequestError::Runtime(err))
}
}
22 changes: 20 additions & 2 deletions drv/sprot-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
extern crate memoffset;

mod error;
use attest_api::AttestError;
use drv_caboose::CabooseError;
use dumper_api::DumperError;
pub use error::{
CabooseOrSprotError, DumpOrSprotError, RawCabooseOrSprotError,
SprocketsError, SprotError, SprotProtocolError,
AttestOrSprotError, CabooseOrSprotError, DumpOrSprotError,
RawCabooseOrSprotError, SprocketsError, SprotError, SprotProtocolError,
};

use crc::{Crc, CRC_16_XMODEM};
Expand Down Expand Up @@ -328,6 +329,7 @@ pub enum ReqBody {
Dump(DumpReq),
// Added in sprot protocol version 3
Caboose(CabooseReq),
Attest(AttestReq),
}

/// Instruct the RoT to take a dump of the SP via SWD
Expand Down Expand Up @@ -363,6 +365,13 @@ pub enum CabooseReq {
Read { slot: SlotId, start: u32, size: u32 },
}

#[derive(Clone, Serialize, Deserialize, SerializedSize)]
pub enum AttestReq {
CertChainLen,
CertLen(u32),
Cert { index: u32, offset: u32, size: u32 },
}

/// A response used for RoT updates
#[derive(Clone, Serialize, Deserialize, SerializedSize, From)]
pub enum UpdateRsp {
Expand All @@ -380,6 +389,13 @@ pub enum CabooseRsp {
Read,
}

#[derive(Clone, Serialize, Deserialize, SerializedSize)]
pub enum AttestRsp {
CertChainLen(u32),
CertLen(u32),
Cert,
}

/// The body of a sprot response.
///
/// See [`Msg`] for details about versioning and message evolution.
Expand All @@ -404,6 +420,8 @@ pub enum RspBody {

// Added in sprot protocol version 3
Caboose(Result<CabooseRsp, RawCabooseError>),

Attest(Result<AttestRsp, AttestError>),
}

/// A response from the Dumper
Expand Down
Loading

0 comments on commit b695b58

Please sign in to comment.