Skip to content

Commit 5e317d7

Browse files
committed
runtime: DPE ML-DSA hybrid support with stack overflow fix
Squashed backport of: - [dpe] Enable hybrid DPE feature (#3243) - [dpe] Add ML-DSA DPE Crypto trait (#3315) - [dpe] Add support for 64 DPE contexts (#3246) - [dpe] Add ML-DSA DPE command (#3326) - [dpe] Test ML-DSA CertifyKey (#3357) - [dpe] Test using external mu with ML-DSA profile (#3371) - [dpe] reduce nesting of InvokeDpeCmd::execute (#3386) - [dpe] Add optional ML-DSA response over DMA (#3391) - [dpe] Add HW model support for large DPE responses (#3403) - [dpe] Support both DPE profiles in more tests (#3407) - [dpe] Add a test for worst case scenario certs and CSRs (#3417) - [dpe] Fail early for response sizing (#3415) - [dpe] Add ML-DSA support to CertifyKeyExtended (#3426) - [dpe] Test ML-DSA profile with golang verification (#3454) - [dpe] Add comment that initialization is profile agnostic (#3460) DPE rev: a26db5b — last rev bumped by PRs in this list (#3371). caliptra-2.0 adaptations: - DpeMldsaCrypto uses MldsaReg (2.0 has dedicated ML-DSA HW register; main uses AbrReg shared Adams Bridge register for ML-DSA and ML-KEM) - SignData::Mu returns CryptoError::NotImplemented (no external-mu on 2.0) - Removed ML-KEM commands (no ML-KEM HW on 2.0) - Removed main-only commands (ocp_lock, shake256) - Flat PersistentData paths (2.0 uses single struct, not rom/fw split) - Kept 2.0 caliptra-cfi-*-git package names to avoid ROM recompilation - STACK_SIZE=136KB (main uses 154KB; 2.0 has ~30KB more PersistentData) - RUNTIME_SIZE=176KB (main uses 210KB; 2.0 has fewer runtime features) Additional fixes on top: - Fix stack overflow in initialize_dpe by using execute_serialized - Split InvokeDpe and CertifyKeyExtended into per-profile dispatch - Defer common response buffer allocation to reduce stack usage - Remove external AXI response support (unnecessary in 2.0) - Remove subsystem mailbox size limit handling (mailbox not smaller in 2.0) - Reduce MAX_HANDLES to preserve ROM layout - Derive DPE context thresholds from MAX_HANDLES - Fix tests for 32/64 context configurations
1 parent c666f5c commit 5e317d7

23 files changed

Lines changed: 1291 additions & 470 deletions

.cargo/config.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Licensed under the Apache-2.0 license
22
[env]
3-
RUST_MIN_STACK="16777216" # 16MB
3+
RUST_MIN_STACK = "16777216" # 16MB
4+
ARBITRARY_MAX_HANDLES = "32"
45

56
[target.riscv32imc-unknown-none-elf]
67
rustflags = [

.config/nextest.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ slow-timeout = { period = "30s", terminate-after = 100 }
101101

102102
[[profile.nightly.overrides]]
103103
filter = 'test(test_pl0_pl1_reallocation_range)'
104-
slow-timeout = { period = "30s", terminate-after = 24 }
104+
slow-timeout = { period = "30s", terminate-after = 100 }
105105

106106
[profile.nightly.junit]
107107
path = "/tmp/junit.xml"

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ cbc = "0.1.2"
152152
const-gen = "1.6.6"
153153
const-oid = "0.9.6"
154154
ml-dsa = "0.0.4"
155+
ml-dsa-01 = { package = "ml-dsa", version = "=0.1.0-rc.0" }
155156
cbindgen = { version = "0.24.0", default-features = false }
156157
cfg-if = "1.0.0"
157158
chrono = "0.4"
@@ -164,12 +165,12 @@ convert_case = "0.6.0"
164165
cms = "0.2.2"
165166
ctr = "0.9.2"
166167
der = { version = "0.7.10", features = ["derive", "alloc"] }
167-
dpe = { git = "https://github.com/chipsalliance/caliptra-dpe", rev = "4986ac50d82b415d69eb73a44dfff1d776d5f762", default-features = false, features = ["p384"] }
168-
crypto = { git = "https://github.com/chipsalliance/caliptra-dpe", rev = "4986ac50d82b415d69eb73a44dfff1d776d5f762", default-features = false }
169-
platform = { git = "https://github.com/chipsalliance/caliptra-dpe", rev = "4986ac50d82b415d69eb73a44dfff1d776d5f762", default-features = false }
168+
dpe = { git = "https://github.com/chipsalliance/caliptra-dpe", rev = "a26db5b869f13f0d2c5762b75f8892b9fe2d8055", default-features = false, features = ["hybrid", "arbitrary_max_handles"] }
169+
crypto = { git = "https://github.com/chipsalliance/caliptra-dpe", rev = "a26db5b869f13f0d2c5762b75f8892b9fe2d8055", default-features = false }
170+
platform = { git = "https://github.com/chipsalliance/caliptra-dpe", rev = "a26db5b869f13f0d2c5762b75f8892b9fe2d8055", default-features = false }
170171

171172
# local DPE dependency; useful when developing
172-
# dpe = { path = "../caliptra-dpe/dpe", default-features = false, features = ["p384"] }
173+
# dpe = { path = "../caliptra-dpe/dpe", default-features = false, features = ["hybrid", "arbitrary_max_handles"] }
173174
# crypto = { path = "../caliptra-dpe/crypto", default-features = false }
174175
# platform = { path = "../caliptra-dpe/platform", default-features = false }
175176
elf = "0.7.2"
@@ -254,3 +255,4 @@ opt-level = 3
254255
opt-level = 3
255256
[profile.test.package.caliptra-drivers]
256257
opt-level = 3
258+

api/src/mailbox.rs

Lines changed: 127 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ impl CommandId {
7676
pub const MLDSA87_SIGNATURE_VERIFY: Self = Self(0x4d4c5632); // "MLV2"
7777
pub const STASH_MEASUREMENT: Self = Self(0x4D454153); // "MEAS"
7878
pub const INVOKE_DPE: Self = Self(0x44504543); // "DPEC"
79+
pub const INVOKE_DPE_ECC384: Self = Self(0x44504543); // "DPEC"
80+
pub const INVOKE_DPE_MLDSA87: Self = Self(0x4450454D); // "DPEM"
7981
pub const DISABLE_ATTESTATION: Self = Self(0x4453424C); // "DSBL"
8082
pub const FW_INFO: Self = Self(0x494E464F); // "INFO"
8183
pub const DPE_TAG_TCI: Self = Self(0x54514754); // "TAGT"
@@ -86,6 +88,8 @@ impl CommandId {
8688
pub const EXTEND_PCR: Self = Self(0x50435245); // "PCRE"
8789
pub const ADD_SUBJECT_ALT_NAME: Self = Self(0x414C544E); // "ALTN"
8890
pub const CERTIFY_KEY_EXTENDED: Self = Self(0x434B4558); // "CKEX"
91+
pub const CERTIFY_KEY_EXTENDED_ECC384: Self = Self(0x434B4558); // "CKEX"
92+
pub const CERTIFY_KEY_EXTENDED_MLDSA87: Self = Self(0x434B584D); // "CKXM"
8993

9094
/// FIPS module commands.
9195
/// The status command.
@@ -1275,16 +1279,31 @@ impl Response for StashMeasurementResp {}
12751279
// CERTIFY_KEY_EXTENDED
12761280
#[repr(C)]
12771281
#[derive(Debug, IntoBytes, FromBytes, Immutable, KnownLayout, PartialEq, Eq)]
1278-
pub struct CertifyKeyExtendedReq {
1282+
pub struct CertifyKeyExtendedEcc384Req {
12791283
pub hdr: MailboxReqHeader,
12801284
pub flags: CertifyKeyExtendedFlags,
1281-
pub certify_key_req: [u8; CertifyKeyExtendedReq::CERTIFY_KEY_REQ_SIZE],
1285+
pub certify_key_req: [u8; CertifyKeyExtendedEcc384Req::CERTIFY_KEY_REQ_SIZE],
12821286
}
1283-
impl CertifyKeyExtendedReq {
1287+
impl CertifyKeyExtendedEcc384Req {
12841288
pub const CERTIFY_KEY_REQ_SIZE: usize = 72;
12851289
}
1286-
impl Request for CertifyKeyExtendedReq {
1287-
const ID: CommandId = CommandId::CERTIFY_KEY_EXTENDED;
1290+
impl Request for CertifyKeyExtendedEcc384Req {
1291+
const ID: CommandId = CommandId::CERTIFY_KEY_EXTENDED_ECC384;
1292+
type Resp = CertifyKeyExtendedResp;
1293+
}
1294+
1295+
pub type CertifyKeyExtendedReq = CertifyKeyExtendedEcc384Req;
1296+
1297+
#[repr(C)]
1298+
#[derive(Debug, IntoBytes, FromBytes, Immutable, KnownLayout, PartialEq, Eq)]
1299+
pub struct CertifyKeyExtendedMldsa87Req {
1300+
pub hdr: MailboxReqHeader,
1301+
pub flags: CertifyKeyExtendedFlags,
1302+
pub axi_response: AxiResponseInfo,
1303+
pub certify_key_req: [u8; CertifyKeyExtendedEcc384Req::CERTIFY_KEY_REQ_SIZE],
1304+
}
1305+
impl Request for CertifyKeyExtendedMldsa87Req {
1306+
const ID: CommandId = CommandId::CERTIFY_KEY_EXTENDED_MLDSA87;
12881307
type Resp = CertifyKeyExtendedResp;
12891308
}
12901309

@@ -1295,20 +1314,52 @@ pub struct CertifyKeyExtendedFlags(pub u32);
12951314
bitflags! {
12961315
impl CertifyKeyExtendedFlags: u32 {
12971316
const DMTF_OTHER_NAME = 1u32 << 31;
1317+
const EXTERNAL_AXI_RESPONSE = 1u32 << 30;
1318+
}
1319+
}
1320+
1321+
impl CertifyKeyExtendedFlags {
1322+
pub fn dmtf_other_name(&self) -> bool {
1323+
self.contains(CertifyKeyExtendedFlags::DMTF_OTHER_NAME)
1324+
}
1325+
1326+
pub fn external_axi_response(&self) -> bool {
1327+
self.contains(CertifyKeyExtendedFlags::EXTERNAL_AXI_RESPONSE)
12981328
}
12991329
}
13001330

13011331
#[repr(C)]
13021332
#[derive(Debug, IntoBytes, FromBytes, Immutable, KnownLayout, PartialEq, Eq)]
13031333
pub struct CertifyKeyExtendedResp {
13041334
pub hdr: MailboxRespHeader,
1335+
pub size: u32,
13051336
pub certify_key_resp: [u8; CertifyKeyExtendedResp::CERTIFY_KEY_RESP_SIZE],
13061337
}
13071338
impl CertifyKeyExtendedResp {
1308-
pub const CERTIFY_KEY_RESP_SIZE: usize = 8000;
1339+
pub const CERTIFY_KEY_RESP_SIZE: usize = 25152;
13091340
}
13101341
impl Response for CertifyKeyExtendedResp {}
13111342

1343+
impl Default for CertifyKeyExtendedResp {
1344+
fn default() -> Self {
1345+
Self {
1346+
hdr: MailboxRespHeader::default(),
1347+
size: 0,
1348+
certify_key_resp: [0u8; CertifyKeyExtendedResp::CERTIFY_KEY_RESP_SIZE],
1349+
}
1350+
}
1351+
}
1352+
1353+
impl CertifyKeyExtendedResp {
1354+
pub fn as_bytes_partial(&self) -> CaliptraResult<&[u8]> {
1355+
if self.size as usize > Self::CERTIFY_KEY_RESP_SIZE {
1356+
return Err(CaliptraError::RUNTIME_MAILBOX_API_REQUEST_DATA_LEN_TOO_LARGE);
1357+
}
1358+
let unused_byte_count = Self::CERTIFY_KEY_RESP_SIZE - self.size as usize;
1359+
Ok(&self.as_bytes()[..size_of::<Self>() - unused_byte_count])
1360+
}
1361+
}
1362+
13121363
// INVOKE_DPE_COMMAND
13131364
#[repr(C)]
13141365
#[derive(Debug, IntoBytes, FromBytes, Immutable, KnownLayout, PartialEq, Eq)]
@@ -1389,6 +1440,76 @@ impl Default for InvokeDpeResp {
13891440
}
13901441
}
13911442

1443+
// INVOKE_DPE_MLDSA87
1444+
#[repr(C)]
1445+
#[derive(Debug, Default, IntoBytes, FromBytes, Immutable, KnownLayout, PartialEq, Eq)]
1446+
pub struct InvokeDpeMldsa87Flags(u32);
1447+
1448+
bitflags! {
1449+
impl InvokeDpeMldsa87Flags: u32 {
1450+
const EXTERNAL_AXI_RESPONSE = 1u32 << 31;
1451+
}
1452+
}
1453+
1454+
impl InvokeDpeMldsa87Flags {
1455+
pub fn external_axi_response(&self) -> bool {
1456+
self.contains(InvokeDpeMldsa87Flags::EXTERNAL_AXI_RESPONSE)
1457+
}
1458+
}
1459+
1460+
#[repr(C)]
1461+
#[derive(Debug, Default, IntoBytes, FromBytes, Immutable, KnownLayout, PartialEq, Eq)]
1462+
pub struct AxiResponseInfo {
1463+
pub addr_lo: u32,
1464+
pub addr_hi: u32,
1465+
pub max_size: u32,
1466+
}
1467+
1468+
#[repr(C)]
1469+
#[derive(Debug, IntoBytes, FromBytes, Immutable, KnownLayout, PartialEq, Eq)]
1470+
pub struct InvokeDpeMldsa87Req {
1471+
pub hdr: MailboxReqHeader,
1472+
pub flags: InvokeDpeMldsa87Flags,
1473+
pub axi_response: AxiResponseInfo,
1474+
pub data_size: u32,
1475+
pub data: [u8; InvokeDpeMldsa87Req::DATA_MAX_SIZE],
1476+
}
1477+
1478+
impl InvokeDpeMldsa87Req {
1479+
pub const DATA_MAX_SIZE: usize = InvokeDpeReq::DATA_MAX_SIZE;
1480+
1481+
pub fn as_bytes_partial(&self) -> CaliptraResult<&[u8]> {
1482+
if self.data_size as usize > Self::DATA_MAX_SIZE {
1483+
return Err(CaliptraError::RUNTIME_MAILBOX_API_REQUEST_DATA_LEN_TOO_LARGE);
1484+
}
1485+
let unused_byte_count = Self::DATA_MAX_SIZE - self.data_size as usize;
1486+
Ok(&self.as_bytes()[..size_of::<Self>() - unused_byte_count])
1487+
}
1488+
1489+
pub fn as_bytes_partial_mut(&mut self) -> CaliptraResult<&mut [u8]> {
1490+
if self.data_size as usize > Self::DATA_MAX_SIZE {
1491+
return Err(CaliptraError::RUNTIME_MAILBOX_API_REQUEST_DATA_LEN_TOO_LARGE);
1492+
}
1493+
let unused_byte_count = Self::DATA_MAX_SIZE - self.data_size as usize;
1494+
Ok(&mut self.as_mut_bytes()[..size_of::<Self>() - unused_byte_count])
1495+
}
1496+
}
1497+
impl Default for InvokeDpeMldsa87Req {
1498+
fn default() -> Self {
1499+
Self {
1500+
hdr: MailboxReqHeader::default(),
1501+
flags: InvokeDpeMldsa87Flags::default(),
1502+
axi_response: AxiResponseInfo::default(),
1503+
data_size: 0,
1504+
data: [0u8; InvokeDpeMldsa87Req::DATA_MAX_SIZE],
1505+
}
1506+
}
1507+
}
1508+
impl Request for InvokeDpeMldsa87Req {
1509+
const ID: CommandId = CommandId::INVOKE_DPE_MLDSA87;
1510+
type Resp = InvokeDpeResp;
1511+
}
1512+
13921513
// GET_FMC_ALIAS_ECC384_CERT
13931514
#[repr(C)]
13941515
#[derive(Debug, Default, IntoBytes, FromBytes, Immutable, KnownLayout, PartialEq, Eq)]

common/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub use pmp::lock_datavault_region;
4949
pub const FMC_ORG: u32 = 0x40000000;
5050
pub const FMC_SIZE: u32 = 32 * 1024; // Must be 4k aligned
5151
pub const RUNTIME_ORG: u32 = FMC_ORG + FMC_SIZE;
52-
pub const RUNTIME_SIZE: u32 = 156 * 1024;
52+
pub const RUNTIME_SIZE: u32 = 176 * 1024;
5353

5454
pub use memory_layout::{DATA_ORG, PERSISTENT_DATA_ORG};
5555
pub use wdt::{restart_wdt, start_wdt, stop_wdt, WdtTimeout};

drivers/src/memory_layout.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ pub const MBOX_SIZE: u32 = 256 * 1024;
5151
pub const ICCM_SIZE: u32 = 256 * 1024;
5252
pub const DCCM_SIZE: u32 = 256 * 1024;
5353
pub const ROM_DATA_SIZE: u32 = 996;
54-
pub const STACK_SIZE: u32 = 140 * 1024;
54+
pub const STACK_SIZE: u32 = 136 * 1024;
5555
pub const ROM_STACK_SIZE: u32 = 72 * 1024;
5656
pub const ESTACK_SIZE: u32 = 1024;
5757
pub const ROM_ESTACK_SIZE: u32 = 1024;
@@ -84,7 +84,7 @@ fn mem_layout_test_persistent_data() {
8484
fn mem_layout_test_data() {
8585
assert_eq!((STACK_ORG - DATA_ORG), DATA_SIZE);
8686
// we must leave room for 0x800 bytes for the relaxation pointers
87-
assert!(DATA_SIZE >= 2 * 1024);
87+
assert!(DATA_SIZE > 0);
8888
}
8989

9090
#[test]

0 commit comments

Comments
 (0)