From abf6a630a0b0724eef80e78b57d9573b0c0656af Mon Sep 17 00:00:00 2001 From: James Sadler Date: Fri, 6 Nov 2026 21:43:43 +1100 Subject: [PATCH] test(stack-kms-azure): name the fixture AES key the vendor key The emulator's AES key-wrap helpers called the key a KEK. CONTEXT.md lists KEK as a term to avoid: the vendor key is the key that wraps. Rename TEST_ONLY_KEK to TEST_ONLY_VENDOR_KEY and the kek parameters to vendor_key. --- packages/stack-kms-azure/tests/common/mod.rs | 20 ++++++++++---------- packages/stack-kms-azure/tests/fixtures.rs | 18 ++++++++++++------ 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/packages/stack-kms-azure/tests/common/mod.rs b/packages/stack-kms-azure/tests/common/mod.rs index e08aec455..3a53a9f84 100644 --- a/packages/stack-kms-azure/tests/common/mod.rs +++ b/packages/stack-kms-azure/tests/common/mod.rs @@ -51,8 +51,8 @@ pub fn issued_at() -> SystemTime { } /// The TEST-ONLY 256-bit AES key of the fixture `oct-HSM` key version: the -/// RFC 3394 example key-encryption key (`00 01 .. 1F`). It is no one's key. -pub const TEST_ONLY_KEK: [u8; 32] = [ +/// RFC 3394 example key (`00 01 .. 1F`). It is no one's key. +pub const TEST_ONLY_VENDOR_KEY: [u8; 32] = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, ]; @@ -76,9 +76,9 @@ const KW_IV: [u8; 8] = [0xA6; 8]; /// AES key wrap (RFC 3394) under a 256-bit key: an implementation for the /// emulator, pinned by the RFC's own example in `tests/fixtures.rs`. -pub fn kw_wrap(kek: &[u8; 32], plaintext: &[u8]) -> Vec { +pub fn kw_wrap(vendor_key: &[u8; 32], plaintext: &[u8]) -> Vec { assert!(plaintext.len().is_multiple_of(8) && plaintext.len() >= 16); - let cipher = Aes256::new(GenericArray::from_slice(kek)); + let cipher = Aes256::new(GenericArray::from_slice(vendor_key)); let n = plaintext.len() / 8; let mut a = KW_IV; let mut r: Vec<[u8; 8]> = plaintext.chunks(8).map(|c| c.try_into().unwrap()).collect(); @@ -99,11 +99,11 @@ pub fn kw_wrap(kek: &[u8; 32], plaintext: &[u8]) -> Vec { } /// AES key unwrap (RFC 3394). `None` when the integrity check fails. -pub fn kw_unwrap(kek: &[u8; 32], ciphertext: &[u8]) -> Option> { +pub fn kw_unwrap(vendor_key: &[u8; 32], ciphertext: &[u8]) -> Option> { if !ciphertext.len().is_multiple_of(8) || ciphertext.len() < 24 { return None; } - let cipher = Aes256::new(GenericArray::from_slice(kek)); + let cipher = Aes256::new(GenericArray::from_slice(vendor_key)); let n = ciphertext.len() / 8 - 1; let mut a: [u8; 8] = ciphertext[..8].try_into().unwrap(); let mut r: Vec<[u8; 8]> = ciphertext[8..] @@ -544,10 +544,10 @@ impl KeyVaultEmulator { .unwrap(), ), ("unwrapkey", Material::Rsa) => self.rsa.decrypt(Oaep::new::(), &value).ok(), - ("wrapkey", Material::Aes(kek)) => { - (value.len().is_multiple_of(8) && value.len() >= 16).then(|| kw_wrap(kek, &value)) - } - ("unwrapkey", Material::Aes(kek)) => kw_unwrap(kek, &value), + ("wrapkey", Material::Aes(vendor_key)) => (value.len().is_multiple_of(8) + && value.len() >= 16) + .then(|| kw_wrap(vendor_key, &value)), + ("unwrapkey", Material::Aes(vendor_key)) => kw_unwrap(vendor_key, &value), _ => None, }; match result { diff --git a/packages/stack-kms-azure/tests/fixtures.rs b/packages/stack-kms-azure/tests/fixtures.rs index f395a7895..610948a3d 100644 --- a/packages/stack-kms-azure/tests/fixtures.rs +++ b/packages/stack-kms-azure/tests/fixtures.rs @@ -23,7 +23,7 @@ use base64ct::{Base64UrlUnpadded, Encoding}; use common::{ fixture_client, issued_at, kw_unwrap, kw_wrap, load, replay, test_only_rsa_key, Fixture, FixtureResponse, KeyVaultEmulator, Replay, CLIENT_ID, CLIENT_SECRET, OCT_KEY, OCT_VERSION, - RSA_KEY, RSA_OLD_VERSION, RSA_VERSION, TENANT, TEST_ONLY_KEK, TOKEN, + RSA_KEY, RSA_OLD_VERSION, RSA_VERSION, TENANT, TEST_ONLY_VENDOR_KEY, TOKEN, }; use rsa::sha2::Sha256; use rsa::Oaep; @@ -186,10 +186,13 @@ fn the_fixture_ciphertexts_open_under_the_test_only_keys() { let fixtures: Vec = load("hsm_wrap.json"); let plaintext = b64(&fixtures[1].request.body["value"]); let ciphertext = b64(&fixtures[1].response.body["value"]); - assert_eq!(kw_unwrap(&TEST_ONLY_KEK, &ciphertext).unwrap(), plaintext); - assert_eq!(kw_wrap(&TEST_ONLY_KEK, &plaintext), ciphertext); + assert_eq!( + kw_unwrap(&TEST_ONLY_VENDOR_KEY, &ciphertext).unwrap(), + plaintext + ); + assert_eq!(kw_wrap(&TEST_ONLY_VENDOR_KEY, &plaintext), ciphertext); - // RFC 3394, 4.6: 256 bits of key data with a 256-bit KEK. + // RFC 3394, 4.6: 256 bits of key data with a 256-bit key (the vendor key). let key_data: Vec = (0..16u8) .map(|i| i * 0x11) .chain(0..16u8) @@ -199,8 +202,11 @@ fn the_fixture_ciphertexts_open_under_the_test_only_keys() { 0x26, 0x3F, 0x57, 0x86, 0xE2, 0xD8, 0x0E, 0xD3, 0x26, 0xCB, 0xC7, 0xF0, 0xE7, 0x1A, 0x99, 0xF4, 0x3B, 0xFB, 0x98, 0x8B, 0x9B, 0x7A, 0x02, 0xDD, 0x21, ]; - assert_eq!(kw_wrap(&TEST_ONLY_KEK, &key_data), expected); - assert_eq!(kw_unwrap(&TEST_ONLY_KEK, &expected).unwrap(), key_data); + assert_eq!(kw_wrap(&TEST_ONLY_VENDOR_KEY, &key_data), expected); + assert_eq!( + kw_unwrap(&TEST_ONLY_VENDOR_KEY, &expected).unwrap(), + key_data + ); } fn fixed_clock() -> stack_kms_azure::Clock {