From 2a01220820e17939a0e4b43a1c4a95023696ae8e Mon Sep 17 00:00:00 2001 From: "Stuart R. Anderson" Date: Wed, 23 Sep 2026 08:41:15 -0700 Subject: [PATCH 1/2] Fix hmac_smoke test_hmac_requires_sign_permission_smoke to run on emu only (#740) The test's module doc already documents this as an emu-only test (deriving a derive-only VarHmac256 key via HKDF then attempting to sign), but the #[cfg] gate used not(feature = "mock") which also included real hardware (nix backend). Real HSM firmware rejects the derive-only VarHmac256 HKDF-derive step with InvalidPermissions before the test reaches its intended sign-permission assertion, causing spurious failures on real hardware. Verified: all 616 tests pass with --features mock, and a locally built azihsm_ddi_tests binary (nix/real-hardware backend) run against real AZIHSM hardware now passes 599/599 (0 failed). Co-authored-by: Stuart R. Anderson Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ddi/mbor/types/tests/integration/hmac_smoke.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ddi/mbor/types/tests/integration/hmac_smoke.rs b/ddi/mbor/types/tests/integration/hmac_smoke.rs index 5efc8a0be..65670962f 100644 --- a/ddi/mbor/types/tests/integration/hmac_smoke.rs +++ b/ddi/mbor/types/tests/integration/hmac_smoke.rs @@ -101,7 +101,7 @@ fn test_hmac_unknown_key_smoke() { ); } -#[cfg(not(feature = "mock"))] +#[cfg(feature = "emu")] #[test] fn test_hmac_requires_sign_permission_smoke() { ddi_dev_test( From 1f1085947ab5fd1027e8854daf5872d5ef3a327b Mon Sep 17 00:00:00 2001 From: "Stuart R. Anderson" Date: Fri, 9 Oct 2026 09:54:43 -0700 Subject: [PATCH 2/2] Relax hmac_smoke sign-permission test to run on real HW too test_hmac_requires_sign_permission_smoke was gated to emu only because real firmware rejects the derive-only VarHmac key at creation time (InvalidPermissions from HkdfDerive), rather than at the later MAC-sign attempt like the emu backend. Change the gate to not(feature = "mock") and accept InvalidPermissions at either the key-derivation step (real HW) or the MAC-sign step (emu), so the test exercises the same permission-enforcement guarantee uniformly across both non-mock backends. Verified: mock 2/2 (test still excluded), emu 4/4, real HW 4/4 (previously 3/4 with the unconditional emu-only gate removed). --- .../types/tests/integration/hmac_smoke.rs | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/ddi/mbor/types/tests/integration/hmac_smoke.rs b/ddi/mbor/types/tests/integration/hmac_smoke.rs index 65670962f..5a0b809f0 100644 --- a/ddi/mbor/types/tests/integration/hmac_smoke.rs +++ b/ddi/mbor/types/tests/integration/hmac_smoke.rs @@ -10,9 +10,13 @@ //! HMAC kind): same, deriving `VarHmac256` / `384` / `512`. //! - **Unknown key** (both backends): a MAC against a non-existent //! `key_id` is rejected with `KeyNotFound`. -//! - **Sign permission** (emu only): a `derive`-only HMAC key cannot -//! generate a MAC — rejected with `InvalidPermissions` (MAC -//! generation is a PKCS#11 `C_Sign` operation requiring `CKA_SIGN`). +//! - **Sign permission** (emu + real HW, not mock): a `derive`-only +//! HMAC key cannot generate a MAC. Real HW's firmware rejects the +//! `derive`-only key's creation outright (it requires `SignVerify` +//! on every HMAC-class key); emu permits creating the key and +//! rejects the MAC attempt instead. Both are accepted as proof the +//! permission is enforced (MAC generation is a PKCS#11 `C_Sign` +//! operation requiring `CKA_SIGN`). #![cfg(test)] @@ -101,7 +105,7 @@ fn test_hmac_unknown_key_smoke() { ); } -#[cfg(feature = "emu")] +#[cfg(not(feature = "mock"))] #[test] fn test_hmac_requires_sign_permission_smoke() { ddi_dev_test( @@ -112,6 +116,19 @@ fn test_hmac_requires_sign_permission_smoke() { // try to generate a MAC with it. MAC generation is a // PKCS#11 `C_Sign` operation, so a key lacking `CKA_SIGN` // must be rejected. + // + // The two backends reject this at different points: + // - emu (fw/core's software emulator) permits creating a + // derive-only VarHmac key, then rejects the MAC attempt + // with `InvalidPermissions` (the scenario this test was + // originally written to exercise). + // - real hardware's firmware requires `SignVerify` usage + // for every HMAC-class key, with no `derive`-only + // carve-out, so it rejects the key creation itself with + // `InvalidPermissions` before a MAC is ever attempted. + // Both are valid proof that a key without sign permission + // can't produce a MAC; accept either so this test is + // backend-agnostic rather than emu-only. let (secret_id, _) = create_ecdh_secrets(session_id, dev, DdiKeyType::Secret256); let key_props = helper_key_properties(DdiKeyUsage::Derive, DdiKeyAvailability::Session); let derived = helper_hkdf_derive( @@ -126,8 +143,18 @@ fn test_hmac_requires_sign_permission_smoke() { None, key_props, Some(32), - ) - .expect("derive-only var-HMAC key should be created"); + ); + + let derived = match derived { + Ok(derived) => derived, + Err(err) => { + assert!( + matches!(err, DdiError::DdiStatus(DdiStatus::InvalidPermissions)), + "expected InvalidPermissions rejecting derive-only key creation, got {err:?}" + ); + return; + } + }; let err = hmac_msg(dev, session_id, derived.data.key_id) .expect_err("MAC with a derive-only key must be rejected");