Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 41 additions & 35 deletions ddi/tbor/types/src/sd_create_peer_backup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
//! Host-side wrapper for the TBOR `SdCreatePeerBackup` command.
//!
//! `SdCreatePeerBackup` is an **in-session** command that creates a
//! peer-transferable backup of a security domain: it takes the local
//! partition-owner-key backup (`pok_local_backup`), re-masks it for the
//! destination peer named by `dst_evidence` under the named sealing key,
//! and returns the peer backup (`pok_peer_backup`).
//! peer-transferable backup of a security domain (manticore §3.3.10): it
//! recovers BKS3 from the caller's device-local backup (`pok_local_backup`)
//! and HPKE-Auth-seals it to the destination peer named by `dst_evidence` —
//! authenticated by the sender's own masked SD-sealing key — returning the
//! peer backup (`pok_peer_backup`). Peer cloning is gated by the security
//! domain's `allow_peer_cloning` policy flag.
//!
//! Both wire schemas are shared with the firmware handler via
//! `azihsm_fw_ddi_tbor_types::sd_create_peer_backup`; this module adds the
Expand All @@ -23,6 +25,9 @@ use alloc::vec::Vec;

use crate::evidence::ReportDescriptor;
use crate::policy::PartPolicy;
use crate::sd_create_remote_backup::MASKED_SD_LEN;
use crate::sd_create_remote_backup::POK_REMOTE_BACKUP_LEN;
use crate::sd_sealing_key_gen::MASKED_SEALING_KEY_LEN;
use crate::tbor;
use crate::CertDescriptor;

Expand All @@ -31,21 +36,26 @@ pub const TBOR_OP_SD_CREATE_PEER_BACKUP: u8 = 0x0E;

/// Host-facing TBOR `SdCreatePeerBackup` request.
#[tbor(opcode = TBOR_OP_SD_CREATE_PEER_BACKUP, session_ctrl = in_session)]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TborSdCreatePeerBackupReq {
/// Session id this request is bound to. Cross-checked against the
/// SQE-carried session id by the dispatcher.
#[tbor(session_id)]
pub session_id: u16,

/// Vault id (`HsmKeyId`) of the sealing key the `pok_local_backup` is
/// bound to. Carried as a `KeyId` (inline 16-bit, TOC entry type 1);
/// represented here as the raw `u16` handle.
#[tbor(key_id)]
pub sealing_key_id: u16,
/// The sender's masked SD-sealing key (from `SdSealingKeyGen`), exactly
/// [`MASKED_SEALING_KEY_LEN`] (180 B). Unmasked on-device to recover
/// the sender's private HPKE key (`SndrPriv`) that authenticates the
/// seal. A fixed-length `[u8; N]` field; the firmware schema is the
/// length authority.
pub masked_sealing_key: [u8; MASKED_SEALING_KEY_LEN],

/// Unified [`PartPolicy`] describing the security domain being backed
/// up. Encoded as its 484-byte little-endian image.
pub policy: PartPolicy,

/// Destination manufacturer certificate-chain descriptors. Flattened
/// from the firmware `dst_evidence` field group (its four TOC
/// from the firmware `dst_evidence` field group (first of its four TOC
/// entries); the DER bytes travel out of band.
#[tbor(max_len = 8)]
pub dst_mfgr_cert_chain: Vec<CertDescriptor>,
Expand All @@ -61,26 +71,21 @@ pub struct TborSdCreatePeerBackupReq {
/// Destination attestation-report (COSE_Sign1) descriptor.
pub dst_report: ReportDescriptor,

/// Unified [`PartPolicy`] describing the security domain being backed
/// up. Encoded as its 484-byte little-endian image.
pub policy: PartPolicy,

/// Local partition-owner-key backup to re-mask (a masked BKS3 wrapped
/// under the device-local key). Exactly 180 B on the wire; the
/// firmware schema is the length authority.
#[tbor(max_len = 180)]
pub pok_local_backup: Vec<u8>,
/// Device-local partition-owner-key backup (a masked BKS3 wrapped under
/// `PartLocalMK`) from which BKS3 is recovered. Exactly
/// [`MASKED_SD_LEN`] (180 B); the firmware schema is the length
/// authority.
pub pok_local_backup: [u8; MASKED_SD_LEN],
}

/// Host-facing TBOR `SdCreatePeerBackup` response.
#[tbor(response)]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TborSdCreatePeerBackupResp {
/// Partition-owner-key backup re-masked for the destination peer
/// (exactly 180 B on the wire; the firmware schema is the length
/// authority).
#[tbor(max_len = 180)]
pub pok_peer_backup: Vec<u8>,
/// Peer backup: an HPKE-Auth seal of BKS3 (exactly
/// [`POK_REMOTE_BACKUP_LEN`] = 161 B on the wire; the firmware schema is
/// the length authority). A fixed-length `[u8; N]` field.
pub pok_peer_backup: [u8; POK_REMOTE_BACKUP_LEN],
}

#[cfg(test)]
Expand All @@ -89,26 +94,27 @@ mod tests {

use super::*;

const POK_BACKUP_LEN: usize = 180;

#[test]
fn request_encodes_fields() {
let req = TborSdCreatePeerBackupReq {
session_id: 9,
sealing_key_id: 0x1234,
masked_sealing_key: [0u8; MASKED_SEALING_KEY_LEN],
policy: PartPolicy::zeroed(),
pok_local_backup: alloc::vec![0xABu8; POK_BACKUP_LEN],
..Default::default()
dst_mfgr_cert_chain: Vec::new(),
dst_owner_cert_chain: Vec::new(),
dst_part_owner_cert_chain: Vec::new(),
dst_report: ReportDescriptor::default(),
pok_local_backup: [0xABu8; MASKED_SD_LEN],
};

let mut buf = [0u8; 1024];
let frame = req.encode_request(&mut buf).expect("encode");

// The 484-byte policy plus the 180-byte backup must be carried in
// the data section.
// The 484-byte policy plus the sealing key and the backup must be
// carried in the data section.
assert!(
frame.len() > 484 + POK_BACKUP_LEN,
"encoded frame must carry the policy and backup"
frame.len() > 484 + MASKED_SEALING_KEY_LEN + MASKED_SD_LEN,
"encoded frame must carry the policy, key, and backup"
);
}
}
93 changes: 46 additions & 47 deletions ddi/tbor/types/src/sd_restore_peer_backup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@
//! Host-side wrapper for the TBOR `SdRestorePeerBackup` command.
//!
//! `SdRestorePeerBackup` is an **in-session** command that restores a
//! security domain from a peer backup: it unmasks the caller-supplied
//! peer partition-owner-key backup (`pok_peer_backup`, a masked BKS3)
//! under the named sealing key, re-wraps it under the device-local key,
//! and returns the local backup (`pok_local_backup`) together with the
//! security-domain masking-key backup (`sd_mk_backup`).
//! security domain from a **peer** backup (manticore §3.3.11): it
//! HPKE-Auth-opens the caller-supplied `pok_peer_backup` (an HPKE seal of
//! BKS3) with the masked receiver key — authenticated by the sender peer's
//! attested key — recovers `SDMK` from `prev_sd_mk_backup`, and returns the
//! device-local backups (`pok_local_backup`, `sd_mk_backup`). It is
//! `SdRestoreRemoteBackup` plus a peer-cloning policy gate.
//!
//! Both wire schemas are shared with the firmware handler via
//! `azihsm_fw_ddi_tbor_types::sd_restore_peer_backup`; this module adds
//! the host-facing value types so [`exec_op_tbor`] returns owned response
//! values. The firmware splices the source attestation evidence in as an
//! `Evidence` field group; the host derive has no field-group support, so
//! this wrapper spells those four TOC entries out explicitly as the
//! `src_*` cert-chain / report descriptor fields.
//! `azihsm_fw_ddi_tbor_types::sd_restore_peer_backup`; this module adds the
//! host-facing value types so [`exec_op_tbor`] returns owned response
//! values.
//!
//! [`exec_op_tbor`]: ../../azihsm_ddi_interface/trait.DdiDev.html#method.exec_op_tbor

use alloc::vec::Vec;

use crate::evidence::ReportDescriptor;
use crate::policy::PartPolicy;
use crate::sd_create_remote_backup::POK_REMOTE_BACKUP_LEN;
use crate::sd_create_remote_backup::SD_MK_BACKUP_LEN;
use crate::sd_sealing_key_gen::MASKED_SEALING_KEY_LEN;
use crate::tbor;
use crate::CertDescriptor;

Expand All @@ -32,50 +33,48 @@ pub const TBOR_OP_SD_RESTORE_PEER_BACKUP: u8 = 0x0F;

/// Host-facing TBOR `SdRestorePeerBackup` request.
#[tbor(opcode = TBOR_OP_SD_RESTORE_PEER_BACKUP, session_ctrl = in_session)]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct TborSdRestorePeerBackupReq {
/// Session id this request is bound to. Cross-checked against the
/// SQE-carried session id by the dispatcher.
#[tbor(session_id)]
pub session_id: u16,

/// Vault id (`HsmKeyId`) of the sealing key the `pok_peer_backup` is
/// bound to. Carried as a `KeyId` (inline 16-bit, TOC entry type 1);
/// represented here as the raw `u16` handle.
#[tbor(key_id)]
pub sealing_key_id: u16,
/// The receiver's masked SD-sealing key (from `SdSealingKeyGen`),
/// exactly [`MASKED_SEALING_KEY_LEN`] (180 B). Unmasked on-device to
/// recover the receiver's private HPKE key (`RcvrPriv`).
pub masked_sealing_key: [u8; MASKED_SEALING_KEY_LEN],

/// Source manufacturer certificate-chain descriptors. Flattened from
/// the firmware `src_evidence` field group (its four TOC entries); the
/// DER bytes travel out of band.
/// Unified [`PartPolicy`] describing the security domain being
/// restored. Encoded as its 484-byte little-endian image.
pub policy: PartPolicy,

/// Source peer manufacturer certificate-chain descriptors. Flattened
/// from the firmware `src_evidence` field group (first of its four TOC
/// entries); the DER bytes travel out of band.
#[tbor(max_len = 8)]
pub src_mfgr_cert_chain: Vec<CertDescriptor>,

/// Source owner certificate-chain descriptors.
/// Source peer owner certificate-chain descriptors.
#[tbor(max_len = 8)]
pub src_owner_cert_chain: Vec<CertDescriptor>,

/// Source partition-owner certificate-chain descriptors.
/// Source peer partition-owner certificate-chain descriptors.
#[tbor(max_len = 8)]
pub src_part_owner_cert_chain: Vec<CertDescriptor>,

/// Source attestation-report (COSE_Sign1) descriptor.
/// Source peer attestation-report (COSE_Sign1) descriptor.
pub src_report: ReportDescriptor,

/// Unified [`PartPolicy`] describing the security domain being
/// restored. Encoded as its 484-byte little-endian image.
pub policy: PartPolicy,

/// Peer partition-owner-key backup to restore (a masked BKS3).
/// Exactly 180 B on the wire; the firmware schema is the length
/// Peer backup to restore: an HPKE-Auth seal of BKS3, exactly
/// [`POK_REMOTE_BACKUP_LEN`] (161 B). The firmware schema is the length
/// authority.
#[tbor(max_len = 180)]
pub pok_peer_backup: Vec<u8>,
pub pok_peer_backup: [u8; POK_REMOTE_BACKUP_LEN],

/// Security-domain masking-key backup envelope. Exactly 164 B on the
/// wire; the firmware schema is the length authority.
#[tbor(max_len = 164)]
pub sd_mk_backup: Vec<u8>,
/// Previous security-domain masking-key backup (SDMK masked under the
/// derived SDBMK), exactly [`SD_MK_BACKUP_LEN`] (164 B), from which
/// `SDMK` is recovered.
pub prev_sd_mk_backup: [u8; SD_MK_BACKUP_LEN],
}

/// Host-facing TBOR `SdRestorePeerBackup` response.
Expand All @@ -100,28 +99,28 @@ mod tests {

use super::*;

const POK_BACKUP_LEN: usize = 180;
const SD_MK_BACKUP_LEN: usize = 164;

#[test]
fn request_encodes_all_fields() {
let req = TborSdRestorePeerBackupReq {
session_id: 9,
sealing_key_id: 0x1234,
masked_sealing_key: [0u8; MASKED_SEALING_KEY_LEN],
policy: PartPolicy::zeroed(),
pok_peer_backup: alloc::vec![0xABu8; POK_BACKUP_LEN],
sd_mk_backup: alloc::vec![0xCDu8; SD_MK_BACKUP_LEN],
..Default::default()
src_mfgr_cert_chain: Vec::new(),
src_owner_cert_chain: Vec::new(),
src_part_owner_cert_chain: Vec::new(),
src_report: ReportDescriptor::default(),
pok_peer_backup: [0xABu8; POK_REMOTE_BACKUP_LEN],
prev_sd_mk_backup: [0xCDu8; SD_MK_BACKUP_LEN],
};

let mut buf = [0u8; 1024];
let mut buf = [0u8; 2048];
let frame = req.encode_request(&mut buf).expect("encode");

// The 484-byte policy plus the two backup blobs must be carried in
// the data section.
// The 484-byte policy plus the sealing key and the two backups must
// be carried in the data section.
assert!(
frame.len() > 484 + POK_BACKUP_LEN + SD_MK_BACKUP_LEN,
"encoded frame must carry the policy and backups"
frame.len() > 484 + MASKED_SEALING_KEY_LEN + POK_REMOTE_BACKUP_LEN + SD_MK_BACKUP_LEN,
"encoded frame must carry the policy, key, and backups"
);
}
}
6 changes: 6 additions & 0 deletions ddi/tbor/types/src/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,12 @@ pub enum TborStatus {
/// backup whose bound SVN is newer than the current firmware SVN
/// (mirror of `HsmError::SdBackupSvnRollback`).
SdBackupSvnRollback = 0x08700109,

/// A `SdCreatePeerBackup` / `SdRestorePeerBackup` handler was asked to
/// clone a security domain to (or from) a peer, but the partition's
/// policy does not permit peer cloning (mirror of
/// `HsmError::SdPeerCloningNotAllowed`).
SdPeerCloningNotAllowed = 0x0870010A,
}

impl core::fmt::Debug for TborStatus {
Expand Down
2 changes: 2 additions & 0 deletions ddi/tbor/types/tests/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ pub mod part_final;
pub mod part_info;
pub mod part_init;
pub mod psk_change;
pub mod sd_create_peer_backup;
pub mod sd_create_remote_backup;
pub mod sd_reseal_remote_backup;
pub mod sd_restore_local_backup;
pub mod sd_restore_peer_backup;
pub mod sd_restore_remote_backup;
pub mod sd_sealing_key_gen;
pub mod session_close;
Expand Down
Loading
Loading