diff --git a/xtest/otdfctl.py b/xtest/otdfctl.py index b937aa58c..9ab99d478 100644 --- a/xtest/otdfctl.py +++ b/xtest/otdfctl.py @@ -312,7 +312,10 @@ def kas_registry_create_key( # Handle race condition: if key already exists, return the existing one if process.returncode != 0: err_str = (err.decode() if err else "") + (out.decode() if out else "") - if "Invalid key parameters: invalid algorithm" in err_str: + if ( + "Invalid key parameters: invalid algorithm" in err_str + or "key_algorithm_defined" in err_str + ): raise InvalidAlgorithm( f"Algorithm not supported by platform: {err_str}" ) diff --git a/xtest/tdfs.py b/xtest/tdfs.py index 4501604c6..2dcd28752 100644 --- a/xtest/tdfs.py +++ b/xtest/tdfs.py @@ -136,8 +136,10 @@ def __init__(self, **kwargs: dict[str, Any]): if self.semver >= (0, 13, 0): self.features.add("mechanism-ec-curves-384-521") - # X-Wing hybrid PQ/T KEM support (ML-KEM-768 + X25519) - if self.semver >= (0, 14, 0): + # X-Wing / secp+ML-KEM hybrid PQ/T KEM support. + # Key management API for hpqt:* algorithms landed after service/v0.15.0; + # v0.15.0 rejects them with a key_algorithm validation error. + if self.semver >= (0, 16, 0): self.features.add("mechanism-xwing") self.features.add("mechanism-secpmlkem") diff --git a/xtest/test_pqc.py b/xtest/test_pqc.py index 1d226cc69..4d5f14fc0 100644 --- a/xtest/test_pqc.py +++ b/xtest/test_pqc.py @@ -32,17 +32,19 @@ def _pem_decoded_len(pem: str) -> int: def assert_xwing_kao_sizes(kao: KeyAccessObject): - """Assert that an X-Wing KAO has correctly sized wrappedKey and ephemeralPublicKey.""" + """Assert that an X-Wing KAO has correctly sized wrappedKey. + + The wrappedKey is an ASN.1 DER structure containing the X-Wing KEM + ciphertext (1120 bytes) plus an AES-GCM encrypted DEK (~60 bytes) + and ASN.1 framing overhead, so it must be larger than the raw + ciphertext alone. hybrid-wrapped KAOs do not use ephemeralPublicKey. + """ wrapped_len = _b64_decoded_len(kao.wrappedKey) - assert wrapped_len == XWING_CIPHERTEXT_SIZE, ( - f"X-Wing wrappedKey should be {XWING_CIPHERTEXT_SIZE} bytes, got {wrapped_len}" - ) - assert kao.ephemeralPublicKey is not None, ( - "X-Wing KAO must include an ephemeralPublicKey" + assert wrapped_len > XWING_CIPHERTEXT_SIZE, ( + f"X-Wing wrappedKey should be > {XWING_CIPHERTEXT_SIZE} bytes, got {wrapped_len}" ) - epk_len = _b64_decoded_len(kao.ephemeralPublicKey) - assert epk_len == XWING_ENCAPSULATION_KEY_SIZE, ( - f"X-Wing ephemeralPublicKey should be {XWING_ENCAPSULATION_KEY_SIZE} bytes, got {epk_len}" + assert kao.ephemeralPublicKey is None, ( + "hybrid-wrapped X-Wing KAO should not have ephemeralPublicKey" )