From bcb2f3be8788f82a9d8820b860f3d3aa5adde2f8 Mon Sep 17 00:00:00 2001
From: Ulrond <131959864+Ulrond@users.noreply.github.com>
Date: Wed, 1 Apr 2026 14:29:16 +0100
Subject: [PATCH 1/5] Add CryptoEngine and KeyVault HAL interfaces
Introduces two new HAL modules for platform cryptography:
CryptoEngine (com.rdk.hal.cryptoengine):
- Standalone crypto operations with TEE or software backend
- Session-based streaming (begin/update/finish) and one-shot methods
- AES, RSA, EC, HMAC, ChaCha20-Poly1305, key derivation (HKDF, PBKDF2, DH, NFLX-DH)
- IV auto-generation with prepend convention
- Hardware RNG support
KeyVault (com.rdk.hal.keyvault):
- Secure key storage with named vault instances
- Key material stays inside TEE via attached CryptoEngine
- Key metadata (algorithm, type, usages) bound at creation time
- Keypair generation for asymmetric algorithms
- Generic derive-into-vault for all KDF types
- Per-vault OTP-derived encryption, HMAC-authenticated keystores
- Platform-provisioned and application-created vaults via HFP
Closes #385
Relates to #130
---
cryptoengine/current/CMakeLists.txt | 31 ++
.../com/rdk/hal/cryptoengine/Algorithm.aidl | 42 +++
.../com/rdk/hal/cryptoengine/BlockMode.aidl | 39 +++
.../rdk/hal/cryptoengine/CryptoConfig.aidl | 112 +++++++
.../com/rdk/hal/cryptoengine/Digest.aidl | 39 +++
.../com/rdk/hal/cryptoengine/EcCurve.aidl | 41 +++
.../hal/cryptoengine/EngineCapabilities.aidl | 50 ++++
.../rdk/hal/cryptoengine/ICryptoEngine.aidl | 78 +++++
.../cryptoengine/ICryptoEngineController.aidl | 164 ++++++++++
.../hal/cryptoengine/ICryptoOperation.aidl | 76 +++++
.../rdk/hal/cryptoengine/KeyDerivation.aidl | 39 +++
.../com/rdk/hal/cryptoengine/KeyPurpose.aidl | 46 +++
.../com/rdk/hal/cryptoengine/KeyType.aidl | 35 +++
.../com/rdk/hal/cryptoengine/PaddingMode.aidl | 39 +++
.../rdk/hal/cryptoengine/SecurityLevel.aidl | 31 ++
cryptoengine/current/hfp-cryptoengine.yaml | 87 ++++++
cryptoengine/metadata.yaml | 34 +++
keyvault/current/CMakeLists.txt | 33 ++
.../com/rdk/hal/keyvault/DerivedKeySpec.aidl | 51 ++++
.../com/rdk/hal/keyvault/IKeyVault.aidl | 130 ++++++++
.../rdk/hal/keyvault/IKeyVaultController.aidl | 281 ++++++++++++++++++
.../hal/keyvault/IKeyVaultEventListener.aidl | 65 ++++
.../com/rdk/hal/keyvault/KeyDescriptor.aidl | 55 ++++
.../rdk/hal/keyvault/VaultCapabilities.aidl | 48 +++
.../com/rdk/hal/keyvault/VaultState.aidl | 34 +++
keyvault/current/hfp-keyvault.yaml | 85 ++++++
keyvault/metadata.yaml | 32 ++
27 files changed, 1797 insertions(+)
create mode 100644 cryptoengine/current/CMakeLists.txt
create mode 100644 cryptoengine/current/com/rdk/hal/cryptoengine/Algorithm.aidl
create mode 100644 cryptoengine/current/com/rdk/hal/cryptoengine/BlockMode.aidl
create mode 100644 cryptoengine/current/com/rdk/hal/cryptoengine/CryptoConfig.aidl
create mode 100644 cryptoengine/current/com/rdk/hal/cryptoengine/Digest.aidl
create mode 100644 cryptoengine/current/com/rdk/hal/cryptoengine/EcCurve.aidl
create mode 100644 cryptoengine/current/com/rdk/hal/cryptoengine/EngineCapabilities.aidl
create mode 100644 cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoEngine.aidl
create mode 100644 cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoEngineController.aidl
create mode 100644 cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoOperation.aidl
create mode 100644 cryptoengine/current/com/rdk/hal/cryptoengine/KeyDerivation.aidl
create mode 100644 cryptoengine/current/com/rdk/hal/cryptoengine/KeyPurpose.aidl
create mode 100644 cryptoengine/current/com/rdk/hal/cryptoengine/KeyType.aidl
create mode 100644 cryptoengine/current/com/rdk/hal/cryptoengine/PaddingMode.aidl
create mode 100644 cryptoengine/current/com/rdk/hal/cryptoengine/SecurityLevel.aidl
create mode 100644 cryptoengine/current/hfp-cryptoengine.yaml
create mode 100644 cryptoengine/metadata.yaml
create mode 100644 keyvault/current/CMakeLists.txt
create mode 100644 keyvault/current/com/rdk/hal/keyvault/DerivedKeySpec.aidl
create mode 100644 keyvault/current/com/rdk/hal/keyvault/IKeyVault.aidl
create mode 100644 keyvault/current/com/rdk/hal/keyvault/IKeyVaultController.aidl
create mode 100644 keyvault/current/com/rdk/hal/keyvault/IKeyVaultEventListener.aidl
create mode 100644 keyvault/current/com/rdk/hal/keyvault/KeyDescriptor.aidl
create mode 100644 keyvault/current/com/rdk/hal/keyvault/VaultCapabilities.aidl
create mode 100644 keyvault/current/com/rdk/hal/keyvault/VaultState.aidl
create mode 100644 keyvault/current/hfp-keyvault.yaml
create mode 100644 keyvault/metadata.yaml
diff --git a/cryptoengine/current/CMakeLists.txt b/cryptoengine/current/CMakeLists.txt
new file mode 100644
index 00000000..93241588
--- /dev/null
+++ b/cryptoengine/current/CMakeLists.txt
@@ -0,0 +1,31 @@
+cmake_minimum_required(VERSION 3.8)
+project(CryptoEngine LANGUAGES NONE VERSION 1.0)
+
+if (NOT COMMAND compile_aidl)
+ message(FATAL_ERROR "Do not invoke module level CMake directly!\nInvoke CMake at root level instead!")
+endif()
+
+set(SRC_DIR com/rdk/hal/cryptoengine)
+
+set(SRC
+ ${SRC_DIR}/ICryptoEngine.aidl
+ ${SRC_DIR}/ICryptoEngineController.aidl
+ ${SRC_DIR}/ICryptoOperation.aidl
+ ${SRC_DIR}/CryptoConfig.aidl
+ ${SRC_DIR}/EngineCapabilities.aidl
+ ${SRC_DIR}/Algorithm.aidl
+ ${SRC_DIR}/BlockMode.aidl
+ ${SRC_DIR}/Digest.aidl
+ ${SRC_DIR}/EcCurve.aidl
+ ${SRC_DIR}/KeyDerivation.aidl
+ ${SRC_DIR}/KeyPurpose.aidl
+ ${SRC_DIR}/KeyType.aidl
+ ${SRC_DIR}/PaddingMode.aidl
+ ${SRC_DIR}/SecurityLevel.aidl
+)
+
+set(INCLUDE_DIRECTORY
+ .
+)
+
+compile_aidl(${SRC} INCLUDE_DIRECTORY ${INCLUDE_DIRECTORY})
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/Algorithm.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/Algorithm.aidl
new file mode 100644
index 00000000..e7faae29
--- /dev/null
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/Algorithm.aidl
@@ -0,0 +1,42 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.cryptoengine;
+
+/**
+ * @brief Cryptographic algorithms.
+ *
+ * Based on PRD Firebolt Cryptography Capabilities requirements and
+ * W3C WebCrypto algorithm registry.
+ */
+@VintfStability
+@Backing(type="int")
+enum Algorithm {
+ /** Not configured. Must be explicitly set by the caller. */
+ UNSET = -1,
+ /** AES symmetric cipher (128, 192, 256-bit). */
+ AES = 0,
+ /** Elliptic Curve (ECDSA sign/verify, ECDH key agreement, Ed25519). */
+ EC = 1,
+ /** HMAC message authentication code. */
+ HMAC = 2,
+ /** RSA asymmetric cipher (RSA-OAEP, RSA-PSS, RSASSA-PKCS1-v1_5). */
+ RSA = 3,
+ /** ChaCha20-Poly1305 authenticated encryption. */
+ CHACHA20_POLY1305 = 4,
+}
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/BlockMode.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/BlockMode.aidl
new file mode 100644
index 00000000..b8aecdc5
--- /dev/null
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/BlockMode.aidl
@@ -0,0 +1,39 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.cryptoengine;
+
+/**
+ * @brief Block cipher modes.
+ */
+@VintfStability
+@Backing(type="int")
+enum BlockMode {
+ /** Not configured. Must be explicitly set by the caller. */
+ UNSET = -1,
+ /** Cipher Block Chaining. */
+ CBC = 0,
+ /** Counter mode. */
+ CTR = 1,
+ /** Galois/Counter Mode (authenticated encryption). */
+ GCM = 2,
+ /** Electronic Codebook (not recommended for general use). */
+ ECB = 3,
+ /** AES Key Wrap (RFC 3394). */
+ KW = 4,
+}
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/CryptoConfig.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/CryptoConfig.aidl
new file mode 100644
index 00000000..ee0322f1
--- /dev/null
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/CryptoConfig.aidl
@@ -0,0 +1,112 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.cryptoengine;
+
+import com.rdk.hal.cryptoengine.Algorithm;
+import com.rdk.hal.cryptoengine.BlockMode;
+import com.rdk.hal.cryptoengine.Digest;
+import com.rdk.hal.cryptoengine.EcCurve;
+import com.rdk.hal.cryptoengine.KeyDerivation;
+import com.rdk.hal.cryptoengine.PaddingMode;
+
+/**
+ * @brief Configuration for a crypto operation.
+ *
+ * Used with ICryptoEngineController.begin() when operating on
+ * caller-provided key material (not vault-managed keys).
+ *
+ * Describes the full set of parameters needed for any supported
+ * crypto operation. Callers must explicitly set all fields relevant
+ * to the requested operation. Fields default to UNSET and the
+ * implementation must reject operations with unconfigured required fields.
+ */
+@VintfStability
+parcelable CryptoConfig {
+
+ // -- Algorithm selection --
+
+ /** Algorithm to use (AES, EC, HMAC, RSA, ChaCha20-Poly1305). Must be set. */
+ Algorithm algorithm = Algorithm.UNSET;
+
+ // -- Symmetric cipher parameters --
+
+ /** Block mode for AES operations (CBC, CTR, GCM, ECB, KW). */
+ BlockMode blockMode = BlockMode.UNSET;
+ /** Padding mode (NONE, PKCS7 for AES; RSA_OAEP, RSA_PSS for RSA). */
+ PaddingMode paddingMode = PaddingMode.UNSET;
+ /** Key size in bits (128, 192, 256 for AES; 2048, 3072, 4096 for RSA). 0 = not set. */
+ int keySizeBits = 0;
+ /** Raw key material for standalone operations. Empty when using vault-managed keys. */
+ byte[] keyData = {};
+
+ /** Initialization vector or nonce.
+ *
+ * If null, the engine auto-generates a random IV using the hardware RNG
+ * and prepends it to the ciphertext output. On decrypt, the engine reads
+ * the IV from the first bytes of the ciphertext input.
+ *
+ * If provided, the engine uses the given IV as-is and does NOT prepend it
+ * to the output. The caller is responsible for storing and providing the
+ * IV on decrypt.
+ *
+ * Sizes: AES-CBC/CTR: 16 bytes. AES-GCM: 12 bytes. ChaCha20: 12 bytes. */
+ @nullable byte[] iv;
+
+ // -- Authenticated encryption parameters (GCM, ChaCha20-Poly1305) --
+
+ /** Additional authenticated data. Authenticated but not encrypted. */
+ @nullable byte[] aad;
+ /** Authentication tag length in bits (GCM: 96, 104, 112, 120, 128). 0 = not set. */
+ int macLengthBits = 0;
+
+ // -- Digest / HMAC parameters --
+
+ /** Digest algorithm for HMAC, sign/verify, and KDF operations. */
+ Digest digest = Digest.UNSET;
+
+ // -- Elliptic curve parameters --
+
+ /** EC curve for key generation or agreement (P-256, P-384, Ed25519, X25519). */
+ EcCurve ecCurve = EcCurve.UNSET;
+
+ // -- Key derivation parameters --
+
+ /** Key derivation function (HKDF, PBKDF2, NFLX-DH, DH). */
+ KeyDerivation kdf = KeyDerivation.UNSET;
+ /** Salt for HKDF or PBKDF2. Null for unsalted derivation.
+ * HKDF: recommended HashLen bytes (e.g. 32 for SHA-256), any length valid.
+ * PBKDF2: minimum 16 bytes (NIST SP 800-132). */
+ @nullable byte[] salt;
+ /** Info/context string for HKDF. */
+ @nullable byte[] info;
+ /** Iteration count for PBKDF2. 0 = not set. */
+ int pbkdf2Iterations = 0;
+ /** Desired output key length in bits for key derivation. 0 = not set. */
+ int derivedKeyLengthBits = 0;
+
+ // -- RSA parameters --
+
+ /** RSA public exponent. Only used for RSA key generation. 0 = not set. */
+ long rsaPublicExponent = 0;
+
+ // -- Key wrapping --
+
+ /** Wrapped key data for unwrap operations. */
+ @nullable byte[] wrappedKeyData;
+}
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/Digest.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/Digest.aidl
new file mode 100644
index 00000000..397f4c80
--- /dev/null
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/Digest.aidl
@@ -0,0 +1,39 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.cryptoengine;
+
+/**
+ * @brief Digest algorithms.
+ *
+ * Aligned with W3C WebCrypto digest algorithms.
+ */
+@VintfStability
+@Backing(type="int")
+enum Digest {
+ /** Not configured. Must be explicitly set by the caller. */
+ UNSET = -1,
+ NONE = 0,
+ SHA_2_224 = 2,
+ SHA_2_256 = 3,
+ SHA_2_384 = 4,
+ SHA_2_512 = 5,
+ SHA_3_256 = 6,
+ SHA_3_384 = 7,
+ SHA_3_512 = 8,
+}
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/EcCurve.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/EcCurve.aidl
new file mode 100644
index 00000000..ec2a5128
--- /dev/null
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/EcCurve.aidl
@@ -0,0 +1,41 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.cryptoengine;
+
+/**
+ * @brief Elliptic curve identifiers.
+ *
+ * Aligned with W3C WebCrypto named curves.
+ */
+@VintfStability
+@Backing(type="int")
+enum EcCurve {
+ /** Not configured. Must be explicitly set by the caller. */
+ UNSET = -1,
+ /** NIST P-256 (secp256r1). Used by ECDSA and ECDH. */
+ P_256 = 0,
+ /** NIST P-384 (secp384r1). */
+ P_384 = 1,
+ /** NIST P-521 (secp521r1). */
+ P_521 = 2,
+ /** Curve25519 for Ed25519 signing. */
+ ED25519 = 3,
+ /** Curve25519 for X25519 key agreement. */
+ X25519 = 4,
+}
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/EngineCapabilities.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/EngineCapabilities.aidl
new file mode 100644
index 00000000..663c0534
--- /dev/null
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/EngineCapabilities.aidl
@@ -0,0 +1,50 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.cryptoengine;
+
+import com.rdk.hal.cryptoengine.Algorithm;
+import com.rdk.hal.cryptoengine.BlockMode;
+import com.rdk.hal.cryptoengine.Digest;
+import com.rdk.hal.cryptoengine.SecurityLevel;
+
+/**
+ * @brief Capabilities of a crypto engine instance.
+ *
+ * Returned by ICryptoEngine.getCapabilities() to allow callers to
+ * introspect what the engine supports on this platform.
+ */
+@VintfStability
+parcelable EngineCapabilities {
+ /** HAL version string. */
+ @utf8InCpp String halVersion;
+ /** Security level of this engine (SOFTWARE or TEE). */
+ SecurityLevel securityLevel = SecurityLevel.SOFTWARE;
+ /** Supported algorithms. */
+ Algorithm[] algorithms = {};
+ /** Supported block modes. */
+ BlockMode[] blockModes = {};
+ /** Supported digests. */
+ Digest[] digests = {};
+ /** Supported key sizes in bits. */
+ int[] keySizes = {};
+ /** Maximum concurrent operations. */
+ int maxConcurrentOperations = 0;
+ /** Whether hardware crypto acceleration is available. */
+ boolean hardwareAccelerated = false;
+}
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoEngine.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoEngine.aidl
new file mode 100644
index 00000000..6bca7fa4
--- /dev/null
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoEngine.aidl
@@ -0,0 +1,78 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.cryptoengine;
+
+import com.rdk.hal.cryptoengine.ICryptoEngineController;
+import com.rdk.hal.cryptoengine.EngineCapabilities;
+
+/**
+ * @brief Crypto Engine HAL Manager interface.
+ * @author Gerald Weatherup
+ *
+ * Top-level entry point for a standalone crypto engine instance.
+ * A crypto engine performs cryptographic operations (encrypt, decrypt,
+ * hash, sign, verify) independently of any key storage.
+ *
+ * Engines can be attached to a KeyVault to operate on vault-managed keys,
+ * or used standalone with caller-provided key material.
+ *
+ * The implementation may use hardware crypto acceleration (TEE) or
+ * a software fallback, depending on platform capabilities.
+ *
+ *
Exception Handling
+ * Unless otherwise specified, this interface follows standard Android Binder semantics:
+ * - Success: The method returns `binder::Status::Exception::EX_NONE` and all output parameters/return values are valid.
+ * - Failure (Exception): The method returns a service-specific exception (e.g., `EX_SERVICE_SPECIFIC`, `EX_ILLEGAL_ARGUMENT`).
+ * In this case, output parameters and return values contain undefined (garbage) memory and must not be used.
+ * The caller must ignore any output variables.
+ */
+@VintfStability
+interface ICryptoEngine {
+ /** The service name to publish. To be returned by getServiceName() in the derived class. */
+ const @utf8InCpp String serviceName = "CryptoEngine";
+
+ /**
+ * @brief Get the capabilities of this crypto engine.
+ *
+ * @returns EngineCapabilities describing supported algorithms, modes, and limits.
+ */
+ EngineCapabilities getCapabilities();
+
+ /**
+ * @brief Open a new crypto engine session.
+ *
+ * Returns a controller for performing crypto operations.
+ * Each controller maps to an independent crypto engine instance.
+ *
+ * @returns ICryptoEngineController for crypto operations, or null on failure.
+ * @exception binder::Status EX_ILLEGAL_STATE if max concurrent sessions reached.
+ */
+ @nullable ICryptoEngineController open();
+
+ /**
+ * @brief Close a crypto engine session.
+ *
+ * All active operations on this controller are aborted and the
+ * underlying crypto engine instance is freed.
+ *
+ * @param controller The controller to close (obtained from open()).
+ * @returns true if the session was closed, false if the controller was not recognised.
+ */
+ boolean close(in ICryptoEngineController controller);
+}
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoEngineController.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoEngineController.aidl
new file mode 100644
index 00000000..38a55ee0
--- /dev/null
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoEngineController.aidl
@@ -0,0 +1,164 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.cryptoengine;
+
+import com.rdk.hal.cryptoengine.ICryptoOperation;
+import com.rdk.hal.cryptoengine.CryptoConfig;
+import com.rdk.hal.cryptoengine.Digest;
+import com.rdk.hal.cryptoengine.KeyPurpose;
+
+/**
+ * @brief Per-session controller for a crypto engine instance.
+ * @author Gerald Weatherup
+ *
+ * Obtained via ICryptoEngine.open(). Provides raw cryptographic operations
+ * independent of key storage. The engine operates on either:
+ * - Caller-provided key material (via CryptoConfig.keyData)
+ * - A vault-managed key (when attached to a KeyVault via the vault's begin())
+ *
+ * This separation ensures the crypto engine is composable — it can be
+ * used standalone or attached to a vault as needed.
+ *
+ * Exception Handling
+ * Unless otherwise specified, this interface follows standard Android Binder semantics:
+ * - Success: The method returns `binder::Status::Exception::EX_NONE` and all output parameters/return values are valid.
+ * - Failure (Exception): The method returns a service-specific exception.
+ * In this case, output parameters and return values contain undefined memory and must not be used.
+ */
+@VintfStability
+interface ICryptoEngineController {
+
+ // -------------------------------------------------------------------------
+ // Streaming crypto operations (begin / update / finish)
+ // -------------------------------------------------------------------------
+
+ /**
+ * @brief Begin a crypto operation with caller-provided key material.
+ *
+ * Supports all algorithm/mode combinations advertised by the engine's
+ * EngineCapabilities. The key data and operation parameters are provided
+ * in the CryptoConfig. Returns an operation handle for streaming.
+ *
+ * Supported operation types:
+ * - ENCRYPT / DECRYPT: AES-CBC, AES-CTR, AES-GCM, AES-ECB, ChaCha20-Poly1305, RSA-OAEP
+ * - SIGN / VERIFY: HMAC, ECDSA, Ed25519, RSA-PSS, RSA-PKCS1-v1_5
+ * - AGREE_KEY: ECDH (P-256, P-384, X25519)
+ * - WRAP_KEY / UNWRAP_KEY: AES-KW, RSA-OAEP
+ * - DERIVE_KEY / DERIVE_BITS: HKDF, PBKDF2, DH, NFLX-DH
+ *
+ * IV handling
+ * If config.iv is null, the engine auto-generates a random IV and prepends
+ * it to the ciphertext output from finish(). On decrypt with iv=null, the
+ * engine reads the IV from the first bytes of the input.
+ * If config.iv is provided, it is used as-is and NOT prepended to the output.
+ *
+ * @param purpose The operation type.
+ * @param config Crypto configuration including algorithm, mode, key data, IV, AAD.
+ * @returns ICryptoOperation handle for update/finish/abort.
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if config is invalid or algorithm not supported.
+ * @exception binder::Status EX_ILLEGAL_STATE if max concurrent operations reached.
+ * @exception binder::Status EX_UNSUPPORTED_OPERATION if the algorithm/mode combination is not supported by this engine.
+ */
+ ICryptoOperation begin(in KeyPurpose purpose, in CryptoConfig config);
+
+ // -------------------------------------------------------------------------
+ // One-shot digest operations
+ // -------------------------------------------------------------------------
+
+ /**
+ * @brief Compute a message digest.
+ *
+ * Stateless, one-shot operation. Does not require a key.
+ *
+ * @param digest The digest algorithm to use (SHA-1, SHA-2-256, SHA-3-256, etc.).
+ * @param data The data to hash.
+ * @returns Digest bytes (length depends on algorithm: SHA-256=32, SHA-384=48, SHA-512=64).
+ * @exception binder::Status EX_UNSUPPORTED_OPERATION if the digest algorithm is not supported.
+ */
+ byte[] computeDigest(in Digest digest, in byte[] data);
+
+ /**
+ * @brief Compute HMAC over data using a caller-provided key.
+ *
+ * @param digest The digest algorithm for the HMAC (e.g. SHA_2_256).
+ * @param key The HMAC key.
+ * @param data The data to authenticate.
+ * @returns HMAC value (length matches digest output size).
+ * @exception binder::Status EX_UNSUPPORTED_OPERATION if the digest algorithm is not supported.
+ */
+ byte[] computeHmac(in Digest digest, in byte[] key, in byte[] data);
+
+ // -------------------------------------------------------------------------
+ // One-shot encrypt / decrypt
+ // -------------------------------------------------------------------------
+
+ /**
+ * @brief One-shot encrypt for small payloads.
+ *
+ * Convenience method equivalent to begin(ENCRYPT) + finish(data).
+ *
+ * IV handling
+ * If config.iv is null, the engine auto-generates a random IV and
+ * prepends it to the returned ciphertext:
+ * output = [IV] + [ciphertext] + [auth tag if GCM/Poly1305]
+ * If config.iv is provided, the output is ciphertext only (no prepended IV).
+ *
+ * @param config Crypto configuration (algorithm, mode, key, IV, AAD).
+ * @param plaintext Data to encrypt.
+ * @returns Ciphertext. If IV was auto-generated, it is prepended.
+ * Auth tag is appended for GCM/Poly1305.
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if config is invalid.
+ */
+ byte[] encrypt(in CryptoConfig config, in byte[] plaintext);
+
+ /**
+ * @brief One-shot decrypt for small payloads.
+ *
+ * Convenience method equivalent to begin(DECRYPT) + finish(data).
+ *
+ * IV handling
+ * If config.iv is null, the engine reads the IV from the first bytes
+ * of the ciphertext input (as produced by encrypt with iv=null):
+ * input = [IV] + [ciphertext] + [auth tag if GCM/Poly1305]
+ * If config.iv is provided, the input is treated as ciphertext only.
+ *
+ * @param config Crypto configuration (algorithm, mode, key, IV, AAD).
+ * @param ciphertext Data to decrypt. If IV was auto-generated on encrypt,
+ * it must be prepended to the ciphertext.
+ * @returns Plaintext.
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if config is invalid.
+ * @exception binder::Status EX_SERVICE_SPECIFIC if auth tag verification fails.
+ */
+ byte[] decrypt(in CryptoConfig config, in byte[] ciphertext);
+
+ // -------------------------------------------------------------------------
+ // Random number generation
+ // -------------------------------------------------------------------------
+
+ /**
+ * @brief Generate cryptographically secure random bytes.
+ *
+ * Uses the platform's hardware RNG when available.
+ *
+ * @param length Number of random bytes to generate.
+ * @returns Random byte array of the requested length.
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if length is zero or exceeds 4096.
+ */
+ byte[] generateRandom(in int length);
+}
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoOperation.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoOperation.aidl
new file mode 100644
index 00000000..8f7267ab
--- /dev/null
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoOperation.aidl
@@ -0,0 +1,76 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.cryptoengine;
+
+/**
+ * @brief Handle for an in-progress cryptographic operation.
+ * @author Gerald Weatherup
+ *
+ * Returned by ICryptoEngineController.begin() or IKeyVaultController.begin().
+ * Callers stream data through update() and complete with finish().
+ *
+ * Each operation maps to a crypto engine instance internally.
+ *
+ * Exception Handling
+ * Unless otherwise specified, this interface follows standard Android Binder semantics:
+ * - Success: The method returns `binder::Status::Exception::EX_NONE` and all output parameters/return values are valid.
+ * - Failure (Exception): The method returns a service-specific exception.
+ * In this case, output parameters and return values contain undefined memory and must not be used.
+ */
+@VintfStability
+interface ICryptoOperation {
+
+ /**
+ * @brief Feed data into the operation.
+ *
+ * For encryption/decryption, returns processed output bytes.
+ * For signing, returns empty until finish().
+ * May be called multiple times for streaming.
+ *
+ * @param input Data to process.
+ * @returns Processed output bytes (may be empty for signing operations).
+ * @exception binder::Status EX_ILLEGAL_STATE if the operation has been finalised or aborted.
+ */
+ byte[] update(in byte[] input);
+
+ /**
+ * @brief Complete the operation and return final output.
+ *
+ * For encryption: returns remaining ciphertext + GCM auth tag (if applicable).
+ * For decryption: verifies GCM tag and returns remaining plaintext.
+ * For signing: returns the signature.
+ * For verification: input is the signature to verify; returns empty on success.
+ *
+ * After finish(), this operation handle is invalidated.
+ *
+ * @param input Optional final data to process (may be null).
+ * @returns Final output bytes.
+ * @exception binder::Status EX_ILLEGAL_STATE if the operation has already been finalised.
+ * @exception binder::Status EX_SERVICE_SPECIFIC if GCM tag verification fails during decryption.
+ */
+ byte[] finish(in @nullable byte[] input);
+
+ /**
+ * @brief Abort the operation, releasing all resources.
+ *
+ * After abort(), this operation handle is invalidated.
+ * Calling abort() on an already-finalised operation is a no-op.
+ */
+ void abort();
+}
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/KeyDerivation.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/KeyDerivation.aidl
new file mode 100644
index 00000000..62b05138
--- /dev/null
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/KeyDerivation.aidl
@@ -0,0 +1,39 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.cryptoengine;
+
+/**
+ * @brief Key derivation function identifiers.
+ *
+ * Used with KeyPurpose.DERIVE_KEY and KeyPurpose.DERIVE_BITS.
+ */
+@VintfStability
+@Backing(type="int")
+enum KeyDerivation {
+ /** Not configured. Must be explicitly set by the caller. */
+ UNSET = -1,
+ /** HMAC-based Extract-and-Expand Key Derivation Function (RFC 5869). */
+ HKDF = 0,
+ /** Password-Based Key Derivation Function 2 (RFC 2898). */
+ PBKDF2 = 1,
+ /** Netflix authenticated Diffie-Hellman key derivation. */
+ NFLX_DH = 2,
+ /** Standard Diffie-Hellman key exchange. */
+ DH = 3,
+}
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/KeyPurpose.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/KeyPurpose.aidl
new file mode 100644
index 00000000..856d34ac
--- /dev/null
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/KeyPurpose.aidl
@@ -0,0 +1,46 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.cryptoengine;
+
+/**
+ * @brief Permitted purposes for a key.
+ *
+ * Bound to the key at creation time and enforced at operation begin().
+ * Aligned with W3C WebCrypto KeyUsages.
+ */
+@VintfStability
+@Backing(type="int")
+enum KeyPurpose {
+ /** Not configured. Must be explicitly set by the caller. */
+ UNSET = -1,
+ ENCRYPT = 0,
+ DECRYPT = 1,
+ SIGN = 2,
+ VERIFY = 3,
+ /** Key agreement (ECDH, DH). */
+ AGREE_KEY = 4,
+ /** Wrap a key for transport or storage (AES-KW, RSA-OAEP). */
+ WRAP_KEY = 5,
+ /** Unwrap a wrapped key. */
+ UNWRAP_KEY = 6,
+ /** Derive a new key from this key (HKDF, PBKDF2, NFLX-DH). */
+ DERIVE_KEY = 7,
+ /** Derive raw secret bits from a key. */
+ DERIVE_BITS = 8,
+}
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/KeyType.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/KeyType.aidl
new file mode 100644
index 00000000..cf040411
--- /dev/null
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/KeyType.aidl
@@ -0,0 +1,35 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.cryptoengine;
+
+/**
+ * @brief The type of a cryptographic key.
+ *
+ * Aligned with W3C WebCrypto CryptoKey.type and Netflix DPI NF_Crypto_KeyType.
+ */
+@VintfStability
+@Backing(type="int")
+enum KeyType {
+ /** A secret symmetric key (AES, HMAC). */
+ SECRET = 0,
+ /** The public half of an asymmetric keypair (RSA, EC). */
+ PUBLIC = 1,
+ /** The private half of an asymmetric keypair (RSA, EC). */
+ PRIVATE = 2,
+}
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/PaddingMode.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/PaddingMode.aidl
new file mode 100644
index 00000000..98637a58
--- /dev/null
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/PaddingMode.aidl
@@ -0,0 +1,39 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.cryptoengine;
+
+/**
+ * @brief Padding modes for cipher and signature operations.
+ */
+@VintfStability
+@Backing(type="int")
+enum PaddingMode {
+ /** Not configured. Must be explicitly set by the caller. */
+ UNSET = -1,
+ /** No padding. Caller must ensure data is block-aligned. */
+ NONE = 0,
+ /** PKCS#7 padding for AES block ciphers. */
+ PKCS7 = 1,
+ /** RSA Optimal Asymmetric Encryption Padding. */
+ RSA_OAEP = 2,
+ /** RSA Probabilistic Signature Scheme. */
+ RSA_PSS = 3,
+ /** RSA PKCS#1 v1.5 signature. */
+ RSA_PKCS1_V1_5 = 4,
+}
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/SecurityLevel.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/SecurityLevel.aidl
new file mode 100644
index 00000000..155504b4
--- /dev/null
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/SecurityLevel.aidl
@@ -0,0 +1,31 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.cryptoengine;
+
+/**
+ * @brief Security level of the crypto environment.
+ */
+@VintfStability
+@Backing(type="int")
+enum SecurityLevel {
+ /** Software-only crypto implementation (OpenSSL). */
+ SOFTWARE = 0,
+ /** Trusted Execution Environment (ARM TrustZone, OP-TEE). */
+ TEE = 1,
+}
diff --git a/cryptoengine/current/hfp-cryptoengine.yaml b/cryptoengine/current/hfp-cryptoengine.yaml
new file mode 100644
index 00000000..99daa79e
--- /dev/null
+++ b/cryptoengine/current/hfp-cryptoengine.yaml
@@ -0,0 +1,87 @@
+#** *****************************************************************************
+# *
+# * If not stated otherwise in this file or this component's LICENSE file the
+# * following copyright and licenses apply:
+# *
+# * Copyright 2026 RDK Management
+# *
+# * Licensed under the Apache License, Version 2.0 (the "License");
+# * you may not use this file except in compliance with the License.
+# * You may obtain a copy of the License at
+# *
+# *
+# * http://www.apache.org/licenses/LICENSE-2.0
+# *
+# * Unless required by applicable law or agreed to in writing, software
+# * distributed under the License is distributed on an "AS IS" BASIS,
+# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# * See the License for the specific language governing permissions and
+# * limitations under the License.
+# *
+#** ******************************************************************************
+
+# HAL Feature Profile for crypto engine
+
+cryptoengine:
+ interfaceVersion: current
+
+ # Security level of this engine instance
+ securityLevel: TEE # TEE or SOFTWARE
+
+ # Maximum concurrent streaming operations (begin/update/finish)
+ maxConcurrentOperations: 32
+
+ # Whether hardware crypto acceleration is available
+ hardwareAccelerated: true
+
+ # Supported algorithms
+ supportedAlgorithms:
+ - AES
+ - EC
+ - HMAC
+ - RSA
+ - CHACHA20_POLY1305
+
+ # Supported block modes
+ supportedBlockModes:
+ - CBC
+ - CTR
+ - GCM
+ - ECB
+ - KW
+
+ # Supported padding modes
+ supportedPaddingModes:
+ - NONE
+ - PKCS7
+ - RSA_OAEP
+ - RSA_PSS
+ - RSA_PKCS1_V1_5
+
+ # Supported digest algorithms
+ supportedDigests:
+ - SHA_2_224
+ - SHA_2_256
+ - SHA_2_384
+ - SHA_2_512
+
+ # Supported elliptic curves
+ supportedEcCurves:
+ - P_256
+ - P_384
+ - ED25519
+ - X25519
+
+ # Supported key derivation functions
+ supportedKeyDerivations:
+ - HKDF
+ - PBKDF2
+ - NFLX_DH
+ - DH
+
+ # Supported key sizes in bits (per algorithm)
+ supportedKeySizes:
+ AES: [128, 192, 256]
+ RSA: [2048, 3072, 4096]
+ EC: [256, 384, 521] # Maps to P-256, P-384, P-521
+ HMAC: [128, 256, 512]
diff --git a/cryptoengine/metadata.yaml b/cryptoengine/metadata.yaml
new file mode 100644
index 00000000..91afdad9
--- /dev/null
+++ b/cryptoengine/metadata.yaml
@@ -0,0 +1,34 @@
+component: cryptoengine
+version: 0.0.1.0
+generation: 1
+status: RED
+description: >
+ Crypto Engine HAL providing standalone cryptographic operations (encrypt,
+ decrypt, hash, sign, verify, random) independent of key storage. Engines
+ can be attached to a KeyVault to operate on vault-managed keys, or used
+ standalone with caller-provided key material. Supports platform-specific
+ hardware crypto acceleration (TEE) or software fallback.
+type: SOC
+
+lifecycle:
+ review_started: ~
+ review_deadline: ~
+ target_green_date: ~
+
+scope:
+ - AES encrypt/decrypt (CBC, CTR, GCM)
+ - SHA-256/384/512 digest
+ - HMAC-SHA256 sign/verify
+ - EC operations (ECDSA, ECDH) - Phase 2
+ - Cryptographically secure random number generation
+ - Streaming operation model (begin/update/finish)
+ - Hardware crypto acceleration when available
+
+notes:
+ owners: "Architecture + Security"
+ dependencies: "Shared enums from KeyVault HAL (com.rdk.hal.keyvault)"
+
+reviewers:
+ RTAB_Group: pending
+ Architecture: pending
+ Security: pending
diff --git a/keyvault/current/CMakeLists.txt b/keyvault/current/CMakeLists.txt
new file mode 100644
index 00000000..a6dadded
--- /dev/null
+++ b/keyvault/current/CMakeLists.txt
@@ -0,0 +1,33 @@
+cmake_minimum_required(VERSION 3.8)
+project(KeyVault LANGUAGES NONE VERSION 1.0)
+
+if (NOT COMMAND compile_aidl)
+ message(FATAL_ERROR "Do not invoke module level CMake directly!\nInvoke CMake at root level instead!")
+endif()
+
+set(CRYPTOENGINE_VERSION "current")
+set(SRC_DIR com/rdk/hal/keyvault)
+set(CRYPTOENGINE_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../cryptoengine/${CRYPTOENGINE_VERSION}/com/rdk/hal/cryptoengine)
+
+set(SRC
+ ${SRC_DIR}/IKeyVault.aidl
+ ${SRC_DIR}/IKeyVaultController.aidl
+ ${SRC_DIR}/IKeyVaultEventListener.aidl
+ ${SRC_DIR}/DerivedKeySpec.aidl
+ ${SRC_DIR}/KeyDescriptor.aidl
+ ${SRC_DIR}/VaultCapabilities.aidl
+ ${SRC_DIR}/VaultState.aidl
+ ${CRYPTOENGINE_SRC_DIR}/Algorithm.aidl
+ ${CRYPTOENGINE_SRC_DIR}/CryptoConfig.aidl
+ ${CRYPTOENGINE_SRC_DIR}/Digest.aidl
+ ${CRYPTOENGINE_SRC_DIR}/ICryptoEngineController.aidl
+ ${CRYPTOENGINE_SRC_DIR}/KeyType.aidl
+ ${CRYPTOENGINE_SRC_DIR}/SecurityLevel.aidl
+)
+
+set(INCLUDE_DIRECTORY
+ .
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../cryptoengine/${CRYPTOENGINE_VERSION}
+)
+
+compile_aidl(${SRC} INCLUDE_DIRECTORY ${INCLUDE_DIRECTORY})
diff --git a/keyvault/current/com/rdk/hal/keyvault/DerivedKeySpec.aidl b/keyvault/current/com/rdk/hal/keyvault/DerivedKeySpec.aidl
new file mode 100644
index 00000000..0f44a8ac
--- /dev/null
+++ b/keyvault/current/com/rdk/hal/keyvault/DerivedKeySpec.aidl
@@ -0,0 +1,51 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.keyvault;
+
+import com.rdk.hal.cryptoengine.Algorithm;
+import com.rdk.hal.cryptoengine.Digest;
+import com.rdk.hal.cryptoengine.KeyType;
+
+/**
+ * @brief Specification for a key to be produced by a derive-into-vault operation.
+ *
+ * Each DerivedKeySpec describes one output key: its alias, algorithm,
+ * type, size, allowed usages, and extractability. The vault stores
+ * the derived key material under the given alias with these properties.
+ *
+ * For NFLX-DH, three specs are provided (encryption, hmac, wrapping).
+ * For HKDF/PBKDF2, typically one spec is provided.
+ */
+@VintfStability
+parcelable DerivedKeySpec {
+ /** Alias under which the derived key will be stored in the vault. */
+ @utf8InCpp String alias;
+ /** Algorithm of the derived key (AES, HMAC, etc.). */
+ Algorithm algorithm = Algorithm.UNSET;
+ /** Key type (SECRET for symmetric derivation). */
+ KeyType keyType = KeyType.SECRET;
+ /** Key size in bits. */
+ int keySizeBits = 0;
+ /** Allowed usages as a bitmask of KeyPurpose values. */
+ int usages = 0;
+ /** Whether the derived key material can be exported. */
+ boolean extractable = false;
+ /** Digest algorithm associated with this key (for HMAC keys). */
+ Digest digest = Digest.UNSET;
+}
diff --git a/keyvault/current/com/rdk/hal/keyvault/IKeyVault.aidl b/keyvault/current/com/rdk/hal/keyvault/IKeyVault.aidl
new file mode 100644
index 00000000..7872e706
--- /dev/null
+++ b/keyvault/current/com/rdk/hal/keyvault/IKeyVault.aidl
@@ -0,0 +1,130 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.keyvault;
+
+import com.rdk.hal.keyvault.IKeyVaultController;
+import com.rdk.hal.keyvault.IKeyVaultEventListener;
+import com.rdk.hal.cryptoengine.SecurityLevel;
+
+/**
+ * @brief KeyVault HAL Manager interface.
+ * @author Gerald Weatherup
+ *
+ * Top-level entry point for the KeyVault HAL. Provides discovery of
+ * available vault instances and factory methods to open vault sessions.
+ *
+ * A KeyVault is a configured crypto engine instance with its own key
+ * material, crypto policy, and access rules. Multiple vaults can coexist
+ * for different requirements (e.g. app secure storage, platform identity,
+ * Netflix MSL, DRM provisioning).
+ *
+ * Each vault has its own attached crypto engine and keystore, with
+ * key material encrypted by OTP-derived root keys.
+ *
+ * Exception Handling
+ * Unless otherwise specified, this interface follows standard Android Binder semantics:
+ * - Success: The method returns `binder::Status::Exception::EX_NONE` and all output parameters/return values are valid.
+ * - Failure (Exception): The method returns a service-specific exception (e.g., `EX_SERVICE_SPECIFIC`, `EX_ILLEGAL_ARGUMENT`).
+ * In this case, output parameters and return values contain undefined (garbage) memory and must not be used.
+ * The caller must ignore any output variables.
+ */
+@VintfStability
+interface IKeyVault {
+ /** The service name to publish. To be returned by getServiceName() in the derived class. */
+ const @utf8InCpp String serviceName = "KeyVault";
+
+ /**
+ * @brief Get the list of available vault names.
+ *
+ * Vault names are defined by platform configuration and may include
+ * pre-provisioned vaults (e.g. "platform-identity") and runtime-created
+ * vaults (e.g. per-app vaults).
+ *
+ * @returns Array of vault name strings.
+ */
+ @utf8InCpp String[] getVaultNames();
+
+ /**
+ * @brief Get the security level of a named vault.
+ *
+ * @param vaultName The name of the vault to query.
+ * @returns SecurityLevel of the vault (SOFTWARE or TEE).
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if vaultName is not recognised.
+ */
+ SecurityLevel getSecurityLevel(in @utf8InCpp String vaultName);
+
+ /**
+ * @brief Open a session to a named vault.
+ *
+ * Returns a controller interface for key management and crypto operations
+ * within the specified vault. The controller remains valid until close()
+ * is called or the device enters deep sleep (for TEE-backed vaults).
+ *
+ * @param vaultName The name of the vault to open.
+ * @param listener Event listener for vault lifecycle events. May be null.
+ * @returns IKeyVaultController for the opened vault session, or null on failure.
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if vaultName is not recognised.
+ * @exception binder::Status EX_ILLEGAL_STATE if the vault is already at max sessions.
+ */
+ @nullable IKeyVaultController open(in @utf8InCpp String vaultName, in @nullable IKeyVaultEventListener listener);
+
+ /**
+ * @brief Close a vault session.
+ *
+ * All active operations on this controller are aborted. Key material
+ * remains persisted in the vault's partition.
+ *
+ * @param controller The controller to close (obtained from open()).
+ * @returns true if the session was closed, false if the controller was not recognised.
+ */
+ boolean close(in IKeyVaultController controller);
+
+ // -------------------------------------------------------------------------
+ // Application-created vaults
+ // -------------------------------------------------------------------------
+
+ /**
+ * @brief Create a new vault at runtime.
+ *
+ * Applications may create additional vaults beyond the platform-provisioned
+ * ones, subject to the limits defined in the HFP (allowApplicationVaults,
+ * maxApplicationVaults).
+ *
+ * @param vaultName Unique name for the new vault.
+ * @param securityLevel Requested security level (SOFTWARE or TEE).
+ * @param maxKeys Maximum number of keys this vault can hold.
+ * @returns true if the vault was created successfully.
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if vaultName already exists.
+ * @exception binder::Status EX_ILLEGAL_STATE if max application vaults reached.
+ * @exception binder::Status EX_UNSUPPORTED_OPERATION if application vault creation is not permitted.
+ */
+ boolean createVault(in @utf8InCpp String vaultName, in SecurityLevel securityLevel, in int maxKeys);
+
+ /**
+ * @brief Destroy a runtime-created vault and all its keys.
+ *
+ * Only application-created vaults can be destroyed. Platform-provisioned
+ * vaults cannot be removed.
+ *
+ * @param vaultName The name of the vault to destroy.
+ * @returns true if the vault was destroyed.
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if vaultName does not exist or is platform-provisioned.
+ */
+ boolean destroyVault(in @utf8InCpp String vaultName);
+}
diff --git a/keyvault/current/com/rdk/hal/keyvault/IKeyVaultController.aidl b/keyvault/current/com/rdk/hal/keyvault/IKeyVaultController.aidl
new file mode 100644
index 00000000..94708b32
--- /dev/null
+++ b/keyvault/current/com/rdk/hal/keyvault/IKeyVaultController.aidl
@@ -0,0 +1,281 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.keyvault;
+
+import com.rdk.hal.cryptoengine.Algorithm;
+import com.rdk.hal.cryptoengine.CryptoConfig;
+import com.rdk.hal.cryptoengine.Digest;
+import com.rdk.hal.cryptoengine.ICryptoEngineController;
+import com.rdk.hal.cryptoengine.KeyType;
+import com.rdk.hal.keyvault.DerivedKeySpec;
+import com.rdk.hal.keyvault.IKeyVaultEventListener;
+import com.rdk.hal.keyvault.KeyDescriptor;
+import com.rdk.hal.keyvault.VaultCapabilities;
+import com.rdk.hal.keyvault.VaultState;
+
+/**
+ * @brief Per-session controller for a KeyVault instance.
+ * @author Gerald Weatherup
+ *
+ * Obtained via IKeyVault.open(). Provides key storage, lifecycle,
+ * and access control scoped to a single vault instance.
+ *
+ * The vault is purely a key store — it holds key material, manages
+ * key metadata, and controls access. To perform crypto operations on
+ * vault-managed keys, attach a configured ICryptoEngineController to
+ * this vault. The engine then uses the vault's keys for its operations
+ * based on its own crypto configuration.
+ *
+ * Exception Handling
+ * Unless otherwise specified, this interface follows standard Android Binder semantics:
+ * - Success: The method returns `binder::Status::Exception::EX_NONE` and all output parameters/return values are valid.
+ * - Failure (Exception): The method returns a service-specific exception (e.g., `EX_SERVICE_SPECIFIC`, `EX_ILLEGAL_ARGUMENT`).
+ * In this case, output parameters and return values contain undefined (garbage) memory and must not be used.
+ */
+@VintfStability
+interface IKeyVaultController {
+
+ // -------------------------------------------------------------------------
+ // Crypto engine attachment
+ // -------------------------------------------------------------------------
+
+ /**
+ * @brief Attach a configured crypto engine to this vault.
+ *
+ * Once attached, the engine can operate on this vault's keys.
+ * The engine's crypto configuration (algorithm, mode, etc.) determines
+ * how the vault's keys are used — the vault itself has no opinion on
+ * crypto operations.
+ *
+ * @param engine A configured ICryptoEngineController to attach.
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if engine is null.
+ * @exception binder::Status EX_ILLEGAL_STATE if an engine is already attached.
+ */
+ void attachCryptoEngine(in ICryptoEngineController engine);
+
+ /**
+ * @brief Detach the currently attached crypto engine.
+ *
+ * Any in-flight operations using vault keys are aborted.
+ *
+ * @exception binder::Status EX_ILLEGAL_STATE if no engine is attached.
+ */
+ void detachCryptoEngine();
+
+ // -------------------------------------------------------------------------
+ // Vault introspection
+ // -------------------------------------------------------------------------
+
+ /**
+ * @brief Get the capabilities of this vault instance.
+ *
+ * @returns VaultCapabilities describing key limits, security level,
+ * and persistence behaviour.
+ */
+ VaultCapabilities getCapabilities();
+
+ /**
+ * @brief Get the current state of this vault.
+ *
+ * Callers should check state after open() before attempting key operations.
+ *
+ * @returns VaultState (READY, ERROR).
+ */
+ VaultState getVaultState();
+
+ // -------------------------------------------------------------------------
+ // Key lifecycle
+ // -------------------------------------------------------------------------
+
+ /**
+ * @brief Generate a new symmetric key within this vault.
+ *
+ * The key material is created inside the secure environment and never
+ * leaves it. Algorithm and usages are bound to the key at creation
+ * time and enforced on all subsequent operations.
+ *
+ * @param alias Unique name for the key within this vault.
+ * @param algorithm Algorithm for this key (AES, HMAC).
+ * @param keySizeBits Key size in bits (e.g. 128, 256).
+ * @param usages Allowed usages as a bitmask of KeyPurpose values.
+ * @param extractable Whether the raw key material can be exported.
+ * @returns KeyDescriptor for the newly created key.
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if alias already exists, algorithm/size is invalid, or usages are incompatible with algorithm.
+ * @exception binder::Status EX_SERVICE_SPECIFIC if the vault has reached its key limit.
+ */
+ KeyDescriptor generateKey(in @utf8InCpp String alias, in Algorithm algorithm, in int keySizeBits, in int usages, in boolean extractable);
+
+ /**
+ * @brief Generate an asymmetric keypair within this vault.
+ *
+ * Both the public and private key are stored in the vault under
+ * separate aliases. The public key bytes are also returned directly
+ * for transmission to a peer (e.g. DH key exchange).
+ *
+ * @param publicAlias Alias for the public key in the vault.
+ * @param privateAlias Alias for the private key in the vault.
+ * @param algorithm Algorithm for this keypair (EC, RSA, DH).
+ * @param keySizeBits Key size in bits.
+ * @param usages Allowed usages for the private key as a bitmask of KeyPurpose values.
+ * @param extractable Whether the private key material can be exported.
+ * @returns KeyDescriptor[] — two descriptors: [0] = public, [1] = private.
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if aliases already exist or params are invalid.
+ * @exception binder::Status EX_SERVICE_SPECIFIC if the vault has reached its key limit.
+ */
+ KeyDescriptor[] generateKeyPair(in @utf8InCpp String publicAlias, in @utf8InCpp String privateAlias, in Algorithm algorithm, in int keySizeBits, in int usages, in boolean extractable);
+
+ /**
+ * @brief Import raw key material into this vault.
+ *
+ * The key data is encrypted at rest using the vault's root-derived key
+ * and persisted. Algorithm and usages are bound at import time.
+ *
+ * @param alias Unique name for the key within this vault.
+ * @param algorithm Algorithm for this key.
+ * @param keyType Key type (SECRET, PUBLIC, or PRIVATE).
+ * @param keyData Raw key material to import.
+ * @param usages Allowed usages as a bitmask of KeyPurpose values.
+ * @param extractable Whether the raw key material can be exported later.
+ * @returns KeyDescriptor for the imported key.
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if alias already exists, keyData is empty, or params are invalid.
+ */
+ KeyDescriptor importKey(in @utf8InCpp String alias, in Algorithm algorithm, in KeyType keyType, in byte[] keyData, in int usages, in boolean extractable);
+
+ /**
+ * @brief Export raw key material from the vault.
+ *
+ * Only permitted for keys created with extractable = true.
+ *
+ * @param alias The alias of the key to export.
+ * @returns Raw key material bytes.
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if alias does not exist.
+ * @exception binder::Status EX_SECURITY if the key is not extractable.
+ */
+ byte[] exportKey(in @utf8InCpp String alias);
+
+ /**
+ * @brief Delete a key from this vault.
+ *
+ * The key material is securely erased and the keystore is re-persisted.
+ *
+ * @param alias The alias of the key to delete.
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if alias does not exist.
+ */
+ void deleteKey(in @utf8InCpp String alias);
+
+ /**
+ * @brief Delete all keys from this vault.
+ *
+ * @post The vault is empty. All key material is securely erased.
+ */
+ void deleteAllKeys();
+
+ /**
+ * @brief Rotate a key, creating a new version under the same alias.
+ *
+ * The previous version is retained for decryption of existing data.
+ * New encrypt operations use the latest version. The key version
+ * counter in the KeyDescriptor is incremented.
+ *
+ * @param alias The alias of the key to rotate.
+ * @returns Updated KeyDescriptor with the new version number.
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if alias does not exist.
+ */
+ KeyDescriptor rotateKey(in @utf8InCpp String alias);
+
+ /**
+ * @brief List all keys in this vault.
+ *
+ * @returns Array of KeyDescriptor for every key in the vault.
+ */
+ KeyDescriptor[] listKeys();
+
+ /**
+ * @brief Get the descriptor for a specific key by alias.
+ *
+ * @param alias The alias of the key to look up.
+ * @returns KeyDescriptor, or null if not found.
+ */
+ @nullable KeyDescriptor getKeyInfo(in @utf8InCpp String alias);
+
+ // -------------------------------------------------------------------------
+ // Key derivation into vault
+ // -------------------------------------------------------------------------
+
+ /**
+ * @brief Derive one or more keys and store them directly in this vault.
+ *
+ * Performs key derivation using the attached crypto engine and stores
+ * the resulting key(s) in the vault without exposing raw material.
+ * Each output key is described by a DerivedKeySpec (alias, algorithm,
+ * type, size, usages).
+ *
+ * Supports all derivation functions: HKDF, PBKDF2, DH, NFLX-DH.
+ * For NFLX-DH, three output specs are expected (encryption, hmac, wrapping).
+ * For HKDF/PBKDF2, typically one output spec.
+ *
+ * The source key for derivation must already exist in this vault
+ * (referenced by alias in config.keyAlias) and have DERIVE_KEY usage.
+ *
+ * @param config Crypto configuration for the derivation (kdf, digest, salt, info, etc.).
+ * config.keyData is ignored — the source key is taken from the vault.
+ * @param sourceKeyAlias Alias of the source key in this vault.
+ * @param peerPublicKey Peer's public key for DH/NFLX-DH. Null for HKDF/PBKDF2.
+ * @param outputKeys Specifications for each derived key to store.
+ * @returns KeyDescriptor[] for each derived key, in the same order as outputKeys.
+ * @exception binder::Status EX_ILLEGAL_ARGUMENT if sourceKeyAlias doesn't exist, config is invalid, or output specs are invalid.
+ * @exception binder::Status EX_SECURITY if the source key doesn't have DERIVE_KEY usage.
+ * @exception binder::Status EX_ILLEGAL_STATE if no crypto engine is attached.
+ */
+ KeyDescriptor[] deriveIntoVault(in CryptoConfig config, in @utf8InCpp String sourceKeyAlias, in @nullable byte[] peerPublicKey, in DerivedKeySpec[] outputKeys);
+
+ // -------------------------------------------------------------------------
+ // Flush / persistence
+ // -------------------------------------------------------------------------
+
+ /**
+ * @brief Flush any pending changes to persistent storage.
+ *
+ * Ensures all key additions, deletions, and metadata changes are
+ * written to the underlying keystore partition and re-authenticated
+ * (e.g. HMAC re-signed).
+ *
+ * @exception binder::Status EX_SERVICE_SPECIFIC if the write fails.
+ */
+ void flush();
+
+ // -------------------------------------------------------------------------
+ // Event listeners
+ // -------------------------------------------------------------------------
+
+ /**
+ * @brief Register for vault lifecycle events (deep sleep, key invalidation).
+ *
+ * @param listener The event listener to register.
+ * @post listener receives onDeviceSuspending/onDeviceResumed/onKeyInvalidated callbacks.
+ */
+ void registerEventListener(in IKeyVaultEventListener listener);
+
+ /**
+ * @brief Unregister a previously registered event listener.
+ *
+ * @param listener The event listener to unregister.
+ */
+ void unregisterEventListener(in IKeyVaultEventListener listener);
+}
diff --git a/keyvault/current/com/rdk/hal/keyvault/IKeyVaultEventListener.aidl b/keyvault/current/com/rdk/hal/keyvault/IKeyVaultEventListener.aidl
new file mode 100644
index 00000000..f598c49f
--- /dev/null
+++ b/keyvault/current/com/rdk/hal/keyvault/IKeyVaultEventListener.aidl
@@ -0,0 +1,65 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.keyvault;
+
+import com.rdk.hal.keyvault.VaultState;
+
+/**
+ * @brief Asynchronous event listener for KeyVault state changes.
+ * @author Gerald Weatherup
+ *
+ * Registered via IKeyVaultController to receive notifications about
+ * vault lifecycle events, key expiry, and power state transitions.
+ */
+@VintfStability
+oneway interface IKeyVaultEventListener {
+
+ /**
+ * @brief The vault state has changed.
+ *
+ * Fired on error conditions and initial readiness.
+ *
+ * @param state The new vault state (READY, ERROR).
+ */
+ void onVaultStateChanged(in VaultState state);
+
+ /**
+ * @brief A key has expired (TTL reached).
+ *
+ * The key material has been purged from the vault.
+ *
+ * @param alias The alias of the expired key.
+ */
+ void onKeyExpired(in @utf8InCpp String alias);
+
+ /**
+ * @brief A key has been deleted or otherwise invalidated.
+ *
+ * @param alias The alias of the key that was removed.
+ */
+ void onKeyInvalidated(in @utf8InCpp String alias);
+
+ /**
+ * @brief A key has been rotated to a new version.
+ *
+ * @param alias The alias of the rotated key.
+ * @param newVersion The new version number.
+ */
+ void onKeyRotated(in @utf8InCpp String alias, in int newVersion);
+}
diff --git a/keyvault/current/com/rdk/hal/keyvault/KeyDescriptor.aidl b/keyvault/current/com/rdk/hal/keyvault/KeyDescriptor.aidl
new file mode 100644
index 00000000..f21e16c0
--- /dev/null
+++ b/keyvault/current/com/rdk/hal/keyvault/KeyDescriptor.aidl
@@ -0,0 +1,55 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.keyvault;
+
+import com.rdk.hal.cryptoengine.Algorithm;
+import com.rdk.hal.cryptoengine.Digest;
+import com.rdk.hal.cryptoengine.KeyType;
+
+/**
+ * @brief Metadata describing a key stored in a vault.
+ *
+ * Returned by key generation, import, listing, and lookup operations.
+ * The key material itself is never exposed — only the descriptor is
+ * visible to callers. All fields are set at key creation time and
+ * immutable for the lifetime of the key (except keyVersion on rotation).
+ */
+@VintfStability
+parcelable KeyDescriptor {
+ /** Unique alias for this key within the vault. */
+ @utf8InCpp String alias;
+ /** Algorithm associated with this key (AES, EC, HMAC, RSA, ChaCha20-Poly1305). */
+ Algorithm algorithm = Algorithm.UNSET;
+ /** Key type: SECRET (symmetric), PUBLIC, or PRIVATE (asymmetric). */
+ KeyType keyType = KeyType.SECRET;
+ /** Key size in bits. */
+ int keySizeBits = 0;
+ /** Allowed usages as a bitmask of KeyPurpose values (ENCRYPT|DECRYPT, SIGN|VERIFY, etc.). */
+ int usages = 0;
+ /** Whether the raw key material can be exported. */
+ boolean extractable = false;
+ /** Digest algorithm associated with this key (e.g. SHA_2_256 for HMAC keys). */
+ Digest digest = Digest.UNSET;
+ /** Current key version (incremented on rotation). */
+ int keyVersion = 0;
+ /** Creation timestamp (milliseconds since epoch). */
+ long createdAtMs = 0;
+ /** Expiry timestamp (milliseconds since epoch). 0 = no expiry. */
+ long expiresAtMs = 0;
+}
diff --git a/keyvault/current/com/rdk/hal/keyvault/VaultCapabilities.aidl b/keyvault/current/com/rdk/hal/keyvault/VaultCapabilities.aidl
new file mode 100644
index 00000000..a5377702
--- /dev/null
+++ b/keyvault/current/com/rdk/hal/keyvault/VaultCapabilities.aidl
@@ -0,0 +1,48 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.keyvault;
+
+import com.rdk.hal.cryptoengine.SecurityLevel;
+
+/**
+ * @brief Capabilities of a vault instance.
+ *
+ * Returned by getCapabilities() to allow callers to introspect
+ * the vault's storage limits, security level, and persistence behaviour.
+ * Crypto capabilities are queried from the attached crypto engine, not the vault.
+ */
+@VintfStability
+parcelable VaultCapabilities {
+ /** Human-readable vault name (e.g. "app-secure-storage", "netflix-msl"). */
+ @utf8InCpp String vaultName;
+ /** HAL version string. */
+ @utf8InCpp String halVersion;
+ /** Security level of this vault's key storage. */
+ SecurityLevel securityLevel = SecurityLevel.SOFTWARE;
+ /** Maximum number of keys this vault can hold. */
+ int maxKeys = 0;
+ /** Supported key sizes in bits. */
+ int[] keySizes = {};
+ /** Whether keys in this vault survive deep sleep. */
+ boolean persistsAcrossSleep = false;
+ /** Total storage capacity in bytes for this vault's partition. */
+ long storageCapacityBytes = 0;
+ /** Current storage usage in bytes. */
+ long storageUsedBytes = 0;
+}
diff --git a/keyvault/current/com/rdk/hal/keyvault/VaultState.aidl b/keyvault/current/com/rdk/hal/keyvault/VaultState.aidl
new file mode 100644
index 00000000..b16bd182
--- /dev/null
+++ b/keyvault/current/com/rdk/hal/keyvault/VaultState.aidl
@@ -0,0 +1,34 @@
+/*
+ * If not stated otherwise in this file or this component's LICENSE file the
+ * following copyright and licenses apply:
+ *
+ * Copyright 2026 RDK Management
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.rdk.hal.keyvault;
+
+/**
+ * @brief Lifecycle state of a vault instance.
+ *
+ * On deep sleep the HAL is closed; on resume it is reopened.
+ * Callers should check state after open() before attempting operations.
+ */
+@VintfStability
+@Backing(type="int")
+enum VaultState {
+ /** Vault is ready — keys are accessible. */
+ READY = 0,
+ /** Vault encountered an error (e.g. keystore corruption, HMAC validation failure). */
+ ERROR = 1,
+}
diff --git a/keyvault/current/hfp-keyvault.yaml b/keyvault/current/hfp-keyvault.yaml
new file mode 100644
index 00000000..b0482335
--- /dev/null
+++ b/keyvault/current/hfp-keyvault.yaml
@@ -0,0 +1,85 @@
+#** *****************************************************************************
+# *
+# * If not stated otherwise in this file or this component's LICENSE file the
+# * following copyright and licenses apply:
+# *
+# * Copyright 2026 RDK Management
+# *
+# * Licensed under the Apache License, Version 2.0 (the "License");
+# * you may not use this file except in compliance with the License.
+# * You may obtain a copy of the License at
+# *
+# *
+# * http://www.apache.org/licenses/LICENSE-2.0
+# *
+# * Unless required by applicable law or agreed to in writing, software
+# * distributed under the License is distributed on an "AS IS" BASIS,
+# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# * See the License for the specific language governing permissions and
+# * limitations under the License.
+# *
+#** ******************************************************************************
+
+# HAL Feature Profile for key vault
+#
+# Defines the platform-provisioned vault instances and their constraints.
+# Applications may also create additional vaults at runtime via the HAL API.
+
+keyvault:
+ interfaceVersion: current
+
+ # Whether applications can create new vaults at runtime
+ # (in addition to the platform-provisioned vaults below)
+ allowApplicationVaults: true
+
+ # Maximum number of application-created vaults (0 = unlimited)
+ maxApplicationVaults: 16
+
+ # Platform-provisioned vault instances
+ # These are created at boot and available immediately.
+ vaults:
+
+ - name: "platform-identity"
+ description: "Device identity certificates and signing keys"
+ securityLevel: TEE
+ maxKeys: 16
+ supportedKeySizes: [256, 384, 521, 2048, 4096]
+ persistsAcrossSleep: true
+ storageCapacityBytes: 65536
+ extractable: false # Keys in this vault are never extractable
+
+ - name: "app-secure-storage"
+ description: "Per-application encrypted key-value storage"
+ securityLevel: TEE
+ maxKeys: 256
+ supportedKeySizes: [128, 256]
+ persistsAcrossSleep: true
+ storageCapacityBytes: 1048576 # 1 MB
+ extractable: false
+
+ - name: "drm-provisioning"
+ description: "DRM key provisioning and device credentials"
+ securityLevel: TEE
+ maxKeys: 32
+ supportedKeySizes: [128, 256]
+ persistsAcrossSleep: true
+ storageCapacityBytes: 131072 # 128 KB
+ extractable: false
+
+ - name: "msl"
+ description: "Message Security Layer session keys"
+ securityLevel: TEE
+ maxKeys: 64
+ supportedKeySizes: [128, 256]
+ persistsAcrossSleep: false # Session keys are re-derived after sleep
+ storageCapacityBytes: 65536
+ extractable: false
+
+ - name: "general-purpose"
+ description: "Shared general-purpose vault for platform services"
+ securityLevel: SOFTWARE
+ maxKeys: 128
+ supportedKeySizes: [128, 192, 256]
+ persistsAcrossSleep: true
+ storageCapacityBytes: 524288 # 512 KB
+ extractable: true # Keys can be exported from this vault
diff --git a/keyvault/metadata.yaml b/keyvault/metadata.yaml
new file mode 100644
index 00000000..64c42f7e
--- /dev/null
+++ b/keyvault/metadata.yaml
@@ -0,0 +1,32 @@
+component: keyvault
+version: 0.0.1.0
+generation: 1
+status: RED
+description: >
+ KeyVault HAL providing configurable vault instances with independent
+ key material, crypto policy, and access rules. Uses OTP-protected
+ keystores and an attached crypto engine. Supports AES-GCM authenticated
+ encryption, runtime key generation, and per-vault security levels
+ (SOFTWARE/TEE).
+type: SOC
+
+lifecycle:
+ review_started: ~
+ review_deadline: ~
+ target_green_date: ~
+
+scope:
+ - Key generation and import within TEE/software vaults
+ - Vault lifecycle and session management
+ - Per-vault crypto policy and access rules
+ - Keystore persistence and HMAC validation
+ - Deep sleep key invalidation and recovery
+
+notes:
+ owners: "Architecture + Security"
+ dependencies: "Crypto Engine HAL (com.rdk.hal.cryptoengine)"
+
+reviewers:
+ RTAB_Group: pending
+ Architecture: pending
+ Security: pending
From 52d089f512d5bf285e75f704057425304cb68090 Mon Sep 17 00:00:00 2001
From: Ulrond <131959864+Ulrond@users.noreply.github.com>
Date: Wed, 1 Apr 2026 23:50:37 +0100
Subject: [PATCH 2/5] Add CMAC and Concat KDF support for Widevine OEMCrypto
- Add CMAC = 5 to Algorithm enum (AES-128 CMAC, required by Widevine
OEMCrypto v16/v19 for OPKI_DeriveKeyWithCMAC key ladder)
- Add CONCAT_KDF = 4 to KeyDerivation enum (NIST SP 800-56A, used for
ECDH key agreement and cert store derivation)
- Add CMAC_KDF = 5 to KeyDerivation enum (NIST SP 800-108 counter-mode
CMAC-AES-128, required by Widevine OEMCrypto for key ladder derivation)
- Update HFP to include CMAC in supportedAlgorithms and CONCAT_KDF +
CMAC_KDF in supportedKeyDerivations
Relates to #385
---
cryptoengine/current/com/rdk/hal/cryptoengine/Algorithm.aidl | 2 ++
.../current/com/rdk/hal/cryptoengine/KeyDerivation.aidl | 4 ++++
cryptoengine/current/hfp-cryptoengine.yaml | 3 +++
3 files changed, 9 insertions(+)
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/Algorithm.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/Algorithm.aidl
index e7faae29..a5e91f36 100644
--- a/cryptoengine/current/com/rdk/hal/cryptoengine/Algorithm.aidl
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/Algorithm.aidl
@@ -39,4 +39,6 @@ enum Algorithm {
RSA = 3,
/** ChaCha20-Poly1305 authenticated encryption. */
CHACHA20_POLY1305 = 4,
+ /** CMAC message authentication code (AES-128). Required by Widevine OEMCrypto for key derivation. */
+ CMAC = 5,
}
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/KeyDerivation.aidl b/cryptoengine/current/com/rdk/hal/cryptoengine/KeyDerivation.aidl
index 62b05138..80756eb1 100644
--- a/cryptoengine/current/com/rdk/hal/cryptoengine/KeyDerivation.aidl
+++ b/cryptoengine/current/com/rdk/hal/cryptoengine/KeyDerivation.aidl
@@ -36,4 +36,8 @@ enum KeyDerivation {
NFLX_DH = 2,
/** Standard Diffie-Hellman key exchange. */
DH = 3,
+ /** Concatenation KDF (NIST SP 800-56A Section 5.8.1). Used for ECDH key agreement and cert store derivation. */
+ CONCAT_KDF = 4,
+ /** Counter-mode CMAC-AES-128 KDF (NIST SP 800-108). Required by Widevine OEMCrypto for key ladder derivation. */
+ CMAC_KDF = 5,
}
diff --git a/cryptoengine/current/hfp-cryptoengine.yaml b/cryptoengine/current/hfp-cryptoengine.yaml
index 99daa79e..c757aea4 100644
--- a/cryptoengine/current/hfp-cryptoengine.yaml
+++ b/cryptoengine/current/hfp-cryptoengine.yaml
@@ -41,6 +41,7 @@ cryptoengine:
- HMAC
- RSA
- CHACHA20_POLY1305
+ - CMAC
# Supported block modes
supportedBlockModes:
@@ -78,6 +79,8 @@ cryptoengine:
- PBKDF2
- NFLX_DH
- DH
+ - CONCAT_KDF
+ - CMAC_KDF
# Supported key sizes in bits (per algorithm)
supportedKeySizes:
From af8d63b9a7b1a81a78d8cda0952355378e43772a Mon Sep 17 00:00:00 2001
From: Ulrond <131959864+Ulrond@users.noreply.github.com>
Date: Wed, 1 Apr 2026 23:53:05 +0100
Subject: [PATCH 3/5] Rename to crypto_engine/key_vault and add design
documentation
- Rename cryptoengine/ -> crypto_engine/
- Rename keyvault/ -> key_vault/
- Add crypto_engine.md design doc (session model, use cases, IV handling)
- Add key_vault.md design doc (architecture, TEE/TA model, cold boot,
vault access control, use cases)
- Fix CMakeLists.txt cross-module path reference
Relates to #385
---
.../current/CMakeLists.txt | 0
.../com/rdk/hal/cryptoengine/Algorithm.aidl | 0
.../com/rdk/hal/cryptoengine/BlockMode.aidl | 0
.../rdk/hal/cryptoengine/CryptoConfig.aidl | 0
.../com/rdk/hal/cryptoengine/Digest.aidl | 0
.../com/rdk/hal/cryptoengine/EcCurve.aidl | 0
.../hal/cryptoengine/EngineCapabilities.aidl | 0
.../rdk/hal/cryptoengine/ICryptoEngine.aidl | 0
.../cryptoengine/ICryptoEngineController.aidl | 0
.../hal/cryptoengine/ICryptoOperation.aidl | 0
.../rdk/hal/cryptoengine/KeyDerivation.aidl | 0
.../com/rdk/hal/cryptoengine/KeyPurpose.aidl | 0
.../com/rdk/hal/cryptoengine/KeyType.aidl | 0
.../com/rdk/hal/cryptoengine/PaddingMode.aidl | 0
.../rdk/hal/cryptoengine/SecurityLevel.aidl | 0
crypto_engine/current/crypto_engine.md | 441 ++++++++++++++
.../current/hfp-cryptoengine.yaml | 0
{cryptoengine => crypto_engine}/metadata.yaml | 0
.../current/CMakeLists.txt | 4 +-
.../com/rdk/hal/keyvault/DerivedKeySpec.aidl | 0
.../com/rdk/hal/keyvault/IKeyVault.aidl | 0
.../rdk/hal/keyvault/IKeyVaultController.aidl | 0
.../hal/keyvault/IKeyVaultEventListener.aidl | 0
.../com/rdk/hal/keyvault/KeyDescriptor.aidl | 0
.../rdk/hal/keyvault/VaultCapabilities.aidl | 0
.../com/rdk/hal/keyvault/VaultState.aidl | 0
.../current/hfp-keyvault.yaml | 0
key_vault/current/key_vault.md | 562 ++++++++++++++++++
{keyvault => key_vault}/metadata.yaml | 0
29 files changed, 1005 insertions(+), 2 deletions(-)
rename {cryptoengine => crypto_engine}/current/CMakeLists.txt (100%)
rename {cryptoengine => crypto_engine}/current/com/rdk/hal/cryptoengine/Algorithm.aidl (100%)
rename {cryptoengine => crypto_engine}/current/com/rdk/hal/cryptoengine/BlockMode.aidl (100%)
rename {cryptoengine => crypto_engine}/current/com/rdk/hal/cryptoengine/CryptoConfig.aidl (100%)
rename {cryptoengine => crypto_engine}/current/com/rdk/hal/cryptoengine/Digest.aidl (100%)
rename {cryptoengine => crypto_engine}/current/com/rdk/hal/cryptoengine/EcCurve.aidl (100%)
rename {cryptoengine => crypto_engine}/current/com/rdk/hal/cryptoengine/EngineCapabilities.aidl (100%)
rename {cryptoengine => crypto_engine}/current/com/rdk/hal/cryptoengine/ICryptoEngine.aidl (100%)
rename {cryptoengine => crypto_engine}/current/com/rdk/hal/cryptoengine/ICryptoEngineController.aidl (100%)
rename {cryptoengine => crypto_engine}/current/com/rdk/hal/cryptoengine/ICryptoOperation.aidl (100%)
rename {cryptoengine => crypto_engine}/current/com/rdk/hal/cryptoengine/KeyDerivation.aidl (100%)
rename {cryptoengine => crypto_engine}/current/com/rdk/hal/cryptoengine/KeyPurpose.aidl (100%)
rename {cryptoengine => crypto_engine}/current/com/rdk/hal/cryptoengine/KeyType.aidl (100%)
rename {cryptoengine => crypto_engine}/current/com/rdk/hal/cryptoengine/PaddingMode.aidl (100%)
rename {cryptoengine => crypto_engine}/current/com/rdk/hal/cryptoengine/SecurityLevel.aidl (100%)
create mode 100644 crypto_engine/current/crypto_engine.md
rename {cryptoengine => crypto_engine}/current/hfp-cryptoengine.yaml (100%)
rename {cryptoengine => crypto_engine}/metadata.yaml (100%)
rename {keyvault => key_vault}/current/CMakeLists.txt (88%)
rename {keyvault => key_vault}/current/com/rdk/hal/keyvault/DerivedKeySpec.aidl (100%)
rename {keyvault => key_vault}/current/com/rdk/hal/keyvault/IKeyVault.aidl (100%)
rename {keyvault => key_vault}/current/com/rdk/hal/keyvault/IKeyVaultController.aidl (100%)
rename {keyvault => key_vault}/current/com/rdk/hal/keyvault/IKeyVaultEventListener.aidl (100%)
rename {keyvault => key_vault}/current/com/rdk/hal/keyvault/KeyDescriptor.aidl (100%)
rename {keyvault => key_vault}/current/com/rdk/hal/keyvault/VaultCapabilities.aidl (100%)
rename {keyvault => key_vault}/current/com/rdk/hal/keyvault/VaultState.aidl (100%)
rename {keyvault => key_vault}/current/hfp-keyvault.yaml (100%)
create mode 100644 key_vault/current/key_vault.md
rename {keyvault => key_vault}/metadata.yaml (100%)
diff --git a/cryptoengine/current/CMakeLists.txt b/crypto_engine/current/CMakeLists.txt
similarity index 100%
rename from cryptoengine/current/CMakeLists.txt
rename to crypto_engine/current/CMakeLists.txt
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/Algorithm.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/Algorithm.aidl
similarity index 100%
rename from cryptoengine/current/com/rdk/hal/cryptoengine/Algorithm.aidl
rename to crypto_engine/current/com/rdk/hal/cryptoengine/Algorithm.aidl
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/BlockMode.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/BlockMode.aidl
similarity index 100%
rename from cryptoengine/current/com/rdk/hal/cryptoengine/BlockMode.aidl
rename to crypto_engine/current/com/rdk/hal/cryptoengine/BlockMode.aidl
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/CryptoConfig.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/CryptoConfig.aidl
similarity index 100%
rename from cryptoengine/current/com/rdk/hal/cryptoengine/CryptoConfig.aidl
rename to crypto_engine/current/com/rdk/hal/cryptoengine/CryptoConfig.aidl
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/Digest.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/Digest.aidl
similarity index 100%
rename from cryptoengine/current/com/rdk/hal/cryptoengine/Digest.aidl
rename to crypto_engine/current/com/rdk/hal/cryptoengine/Digest.aidl
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/EcCurve.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/EcCurve.aidl
similarity index 100%
rename from cryptoengine/current/com/rdk/hal/cryptoengine/EcCurve.aidl
rename to crypto_engine/current/com/rdk/hal/cryptoengine/EcCurve.aidl
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/EngineCapabilities.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/EngineCapabilities.aidl
similarity index 100%
rename from cryptoengine/current/com/rdk/hal/cryptoengine/EngineCapabilities.aidl
rename to crypto_engine/current/com/rdk/hal/cryptoengine/EngineCapabilities.aidl
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoEngine.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/ICryptoEngine.aidl
similarity index 100%
rename from cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoEngine.aidl
rename to crypto_engine/current/com/rdk/hal/cryptoengine/ICryptoEngine.aidl
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoEngineController.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/ICryptoEngineController.aidl
similarity index 100%
rename from cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoEngineController.aidl
rename to crypto_engine/current/com/rdk/hal/cryptoengine/ICryptoEngineController.aidl
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoOperation.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/ICryptoOperation.aidl
similarity index 100%
rename from cryptoengine/current/com/rdk/hal/cryptoengine/ICryptoOperation.aidl
rename to crypto_engine/current/com/rdk/hal/cryptoengine/ICryptoOperation.aidl
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/KeyDerivation.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/KeyDerivation.aidl
similarity index 100%
rename from cryptoengine/current/com/rdk/hal/cryptoengine/KeyDerivation.aidl
rename to crypto_engine/current/com/rdk/hal/cryptoengine/KeyDerivation.aidl
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/KeyPurpose.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/KeyPurpose.aidl
similarity index 100%
rename from cryptoengine/current/com/rdk/hal/cryptoengine/KeyPurpose.aidl
rename to crypto_engine/current/com/rdk/hal/cryptoengine/KeyPurpose.aidl
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/KeyType.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/KeyType.aidl
similarity index 100%
rename from cryptoengine/current/com/rdk/hal/cryptoengine/KeyType.aidl
rename to crypto_engine/current/com/rdk/hal/cryptoengine/KeyType.aidl
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/PaddingMode.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/PaddingMode.aidl
similarity index 100%
rename from cryptoengine/current/com/rdk/hal/cryptoengine/PaddingMode.aidl
rename to crypto_engine/current/com/rdk/hal/cryptoengine/PaddingMode.aidl
diff --git a/cryptoengine/current/com/rdk/hal/cryptoengine/SecurityLevel.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/SecurityLevel.aidl
similarity index 100%
rename from cryptoengine/current/com/rdk/hal/cryptoengine/SecurityLevel.aidl
rename to crypto_engine/current/com/rdk/hal/cryptoengine/SecurityLevel.aidl
diff --git a/crypto_engine/current/crypto_engine.md b/crypto_engine/current/crypto_engine.md
new file mode 100644
index 00000000..1fe7ea8e
--- /dev/null
+++ b/crypto_engine/current/crypto_engine.md
@@ -0,0 +1,441 @@
+# CryptoEngine HAL
+
+## Overview
+
+The CryptoEngine HAL provides standalone cryptographic operations independent of key storage. It abstracts platform-specific crypto acceleration (TEE) or software fallback (OpenSSL) behind a uniform AIDL interface.
+
+The engine operates on caller-provided key material and configuration. It has no concept of key storage or ownership — it receives keys, performs operations, and returns results.
+
+Excluded: key storage, key lifecycle, and access policy.
+
+---
+
+## References
+
+!!! info References
+|||
+|-|-|
+|**Interface Definition**|[cryptoengine/current](./com/rdk/hal/cryptoengine/)|
+|**API Documentation**| Generated from AIDL Javadoc comments |
+|**HAL Interface Type**| AIDL and Binder |
+|**HAL Feature Profile**| [hfp-cryptoengine.yaml](./hfp-cryptoengine.yaml) |
+
+---
+
+## Related Pages
+
+!!! tip "Related Pages"
+- [KeyVault HAL](../../keyvault/current/document.md) — key storage and lifecycle; attaches a CryptoEngine for operations on vault-managed keys
+- [HAL Feature Profile](./hfp-cryptoengine.yaml) — platform-specific capability declaration
+
+---
+
+## Functional Overview
+
+The CryptoEngine HAL has three layers:
+
+| Interface | Role |
+|-----------|------|
+| `ICryptoEngine` | Top-level manager. Enumerates capabilities and opens sessions. |
+| `ICryptoEngineController` | Per-session controller. Provides streaming (`begin`/`update`/`finish`) and one-shot crypto operations. |
+| `ICryptoOperation` | Handle for an in-progress streaming operation. |
+
+The engine supports:
+
+- **Symmetric encryption/decryption** — AES-CBC, AES-CTR, AES-GCM, AES-ECB, ChaCha20-Poly1305
+- **Asymmetric encryption/decryption** — RSA-OAEP
+- **Signing/verification** — HMAC, ECDSA, Ed25519, RSA-PSS, RSA-PKCS1-v1_5
+- **Key agreement** — ECDH (P-256, P-384, X25519)
+- **Key wrapping** — AES-KW, RSA-OAEP
+- **Key derivation** — HKDF, PBKDF2, DH, NFLX-DH
+- **Digest** — SHA-1, SHA-2-224, SHA-2-256, SHA-2-384, SHA-2-512
+- **Random number generation** — hardware RNG when available
+
+---
+
+## Implementation Requirements
+
+| # | Requirement | Comments |
+|---|-------------|---------|
+| HAL.CE.1 | The service shall register with Binder Service Manager using the service name `CryptoEngine`. | Defined as `ICryptoEngine.serviceName`. |
+| HAL.CE.2 | The service shall support at least 32 concurrent streaming operations. | Per HFP `maxConcurrentOperations`. |
+| HAL.CE.3 | `begin()` shall return `EX_ILLEGAL_STATE` when the concurrent operation limit is reached. | Callers must `finish()` or `abort()` existing operations. |
+| HAL.CE.4 | One-shot methods (`encrypt`, `decrypt`, `computeDigest`, `computeHmac`) shall be stateless and thread-safe. | No session required for one-shot use. |
+| HAL.CE.5 | `generateRandom()` shall use the platform hardware RNG when available. | Fallback to software CSPRNG is acceptable. |
+| HAL.CE.6 | GCM authentication tag verification failure shall return `EX_SERVICE_SPECIFIC`. | Must not return partial plaintext on tag failure. |
+| HAL.CE.7 | After `finish()` or `abort()`, the `ICryptoOperation` handle shall be invalidated. | Further calls to `update()`/`finish()` return `EX_ILLEGAL_STATE`. |
+
+---
+
+## Interface Definitions
+
+| AIDL File | Description |
+|-----------|-------------|
+| `ICryptoEngine.aidl` | Top-level manager: capabilities query, session open/close |
+| `ICryptoEngineController.aidl` | Per-session controller: streaming and one-shot crypto operations |
+| `ICryptoOperation.aidl` | In-progress operation handle: update/finish/abort |
+| `CryptoConfig.aidl` | Parcelable: full configuration for a crypto operation |
+| `EngineCapabilities.aidl` | Parcelable: advertised algorithms, modes, and limits |
+| `Algorithm.aidl` | Enum: AES, EC, HMAC, RSA, CHACHA20_POLY1305 |
+| `BlockMode.aidl` | Enum: CBC, CTR, GCM, ECB, KW |
+| `PaddingMode.aidl` | Enum: NONE, PKCS7, RSA_OAEP, RSA_PSS, RSA_PKCS1_V1_5 |
+| `Digest.aidl` | Enum: SHA-1, SHA-2 family |
+| `EcCurve.aidl` | Enum: P-256, P-384, Ed25519, X25519 |
+| `KeyDerivation.aidl` | Enum: HKDF, PBKDF2, NFLX_DH, DH |
+| `KeyPurpose.aidl` | Enum: ENCRYPT, DECRYPT, SIGN, VERIFY, AGREE_KEY, WRAP_KEY, UNWRAP_KEY, DERIVE_KEY, DERIVE_BITS |
+| `SecurityLevel.aidl` | Enum: SOFTWARE, TEE |
+
+---
+
+## Initialization
+
+1. The platform starts the CryptoEngine HAL service process.
+2. The service registers `ICryptoEngine` with Binder Service Manager under the name `CryptoEngine`.
+3. Clients obtain the `ICryptoEngine` proxy via Service Manager lookup.
+4. Clients call `getCapabilities()` to discover supported algorithms and limits.
+5. Clients call `open()` to obtain an `ICryptoEngineController` session.
+
+The CryptoEngine operates standalone with no dependencies on other HAL services.
+
+---
+
+## Product Customization
+
+Platform vendors customize the engine via the HAL Feature Profile ([hfp-cryptoengine.yaml](./hfp-cryptoengine.yaml)):
+
+- **Security level** — `TEE` or `SOFTWARE`
+- **Supported algorithms, block modes, padding modes, digests, EC curves, KDFs**
+- **Supported key sizes** per algorithm
+- **Maximum concurrent operations**
+- **Hardware acceleration** availability
+
+The `EngineCapabilities` parcelable returned by `getCapabilities()` reflects these settings at runtime.
+
+---
+
+## System Context
+
+The CryptoEngine HAL runs as an REE process. For TEE-backed engines (`securityLevel: TEE`), all crypto operations are delegated to the Trusted Application via the TEE client API. For software engines, operations use a software backend (e.g. OpenSSL).
+
+```mermaid
+flowchart TD
+ subgraph REE [Rich Execution Environment]
+ App[Application] -->|Binder IPC| CE[ICryptoEngine]
+ CE -->|open| Ctrl[ICryptoEngineController]
+ Ctrl -->|begin| Op[ICryptoOperation]
+ end
+
+ subgraph TEE [Trusted Execution Environment]
+ TA[Trusted Application]
+ end
+
+ Ctrl -->|"TEE client API"| TA
+
+ style REE fill:#f8f8f8,stroke:#ccc
+ style TEE fill:#e8f5e9,stroke:#4a4
+ style CE fill:#4a9eff,color:#fff
+ style Ctrl fill:#4a9eff,color:#fff
+ style Op fill:#4a9eff,color:#fff
+ style TA fill:#2ecc71,color:#fff
+```
+
+- The CryptoEngine is the **only REE component that talks to the TA**. All crypto operations (encrypt, decrypt, sign, derive, etc.) are forwarded to the TA when the engine's security level is TEE.
+- The engine receives key material, configuration, and data. It does not know or care where the key material came from.
+- For `securityLevel: SOFTWARE`, the engine uses a software backend (e.g. OpenSSL) and does not communicate with the TA.
+
+---
+
+## Session Model
+
+The CryptoEngine is not a singleton. `ICryptoEngine` is a manager that creates independent sessions. Each session is an `ICryptoEngineController` that can run multiple concurrent operations.
+
+```text
+ICryptoEngine (one service, registered with Binder)
+ ├── open() → ICryptoEngineController (session 1)
+ │ ├── begin() → ICryptoOperation (operation A)
+ │ └── begin() → ICryptoOperation (operation B)
+ ├── open() → ICryptoEngineController (session 2)
+ │ └── begin() → ICryptoOperation (operation C)
+ └── close(session)
+```
+
+### Three interface levels
+
+| Interface | Lifecycle | What it does |
+|-----------|-----------|--------------|
+| `ICryptoEngine` | One per service | Service lookup, capability query, session open/close. |
+| `ICryptoEngineController` | One per `open()` call | Streaming operations (`begin`), one-shot operations (`encrypt`, `decrypt`, `computeHmac`, `computeDigest`, `generateRandom`). Each controller is an independent session. |
+| `ICryptoOperation` | One per `begin()` call | Feed data (`update`), complete (`finish`), or cancel (`abort`). Handle is invalidated after `finish()` or `abort()`. |
+
+### Full session lifecycle
+
+```mermaid
+sequenceDiagram
+ participant App as Application
+ participant CE as ICryptoEngine
+ participant Ctrl as ICryptoEngineController
+ participant Op as ICryptoOperation
+
+ App->>CE: getCapabilities()
+ CE-->>App: EngineCapabilities
+
+ App->>CE: open()
+ CE-->>App: ICryptoEngineController
+
+ Note over Ctrl: One-shot operation (no ICryptoOperation needed)
+ App->>Ctrl: computeHmac(SHA_2_256, keyBytes, data)
+ Ctrl-->>App: hmacBytes
+
+ Note over Ctrl: Streaming operation
+ App->>Ctrl: begin(ENCRYPT, config)
+ Ctrl-->>App: ICryptoOperation
+
+ App->>Op: update(chunk1)
+ Op-->>App: ciphertext1
+ App->>Op: update(chunk2)
+ Op-->>App: ciphertext2
+ App->>Op: finish(null)
+ Op-->>App: final ciphertext + tag
+ Note over Op: Handle invalidated
+
+ App->>CE: close(controller)
+ Note over Ctrl: Session ended, all resources freed
+```
+
+### Resource management
+
+- Multiple controllers can be open concurrently (each is an independent session).
+- Each controller can have multiple concurrent operations up to `maxConcurrentOperations`.
+- One-shot methods (`encrypt`, `computeHmac`, etc.) do not consume an operation slot.
+- If a client process dies, Binder death notification triggers cleanup of all its sessions and operations.
+
+---
+
+## Use Cases
+
+The CryptoEngine operates standalone with caller-provided key material.
+
+### HMAC Signing
+
+**If you need to** sign requests or data for integrity verification using a key the caller holds:
+
+```mermaid
+sequenceDiagram
+ participant App as Application
+ participant CE as ICryptoEngineController
+
+ App->>CE: computeHmac(SHA_2_256, keyBytes, data)
+ CE-->>App: signatureBytes
+```
+
+For larger payloads, use the streaming model:
+
+```mermaid
+sequenceDiagram
+ participant App as Application
+ participant CE as ICryptoEngineController
+ participant Op as ICryptoOperation
+
+ App->>CE: begin(SIGN, config{algorithm=HMAC, digest=SHA_2_256, keyData=keyBytes})
+ CE-->>App: ICryptoOperation
+ App->>Op: update(chunk1)
+ App->>Op: update(chunk2)
+ App->>Op: finish(null)
+ Op-->>App: signatureBytes
+```
+
+### Hashing (Digest)
+
+**If you need to** compute a hash of data for integrity checking:
+
+```mermaid
+sequenceDiagram
+ participant App as Application
+ participant CE as ICryptoEngineController
+
+ App->>CE: computeDigest(SHA_2_256, data)
+ CE-->>App: digestBytes
+```
+
+No key required. Stateless one-shot operation.
+
+### Standalone Encryption / Decryption
+
+**If you need to** encrypt or decrypt data with a caller-provided key:
+
+```mermaid
+sequenceDiagram
+ participant App as Application
+ participant CE as ICryptoEngineController
+
+ Note over App: iv=null — engine auto-generates and prepends
+ App->>CE: encrypt(config{algorithm=AES, blockMode=CBC, keyData=keyBytes, iv=null}, plaintext)
+ CE-->>App: [random IV] + [ciphertext]
+
+ Note over App: Pass the whole blob back to decrypt
+ App->>CE: decrypt(config{algorithm=AES, blockMode=CBC, keyData=keyBytes, iv=null}, ivAndCiphertext)
+ CE-->>App: plaintext
+```
+
+### IV Handling Convention
+
+When `config.iv` is **null**, the engine auto-generates a cryptographically random IV and prepends it to the ciphertext output. On decrypt, the engine reads the IV from the first bytes of the input. The caller stores the entire blob as-is — no separate IV management needed.
+
+| Mode | IV size | Encrypt output (iv=null) | Decrypt input |
+|------|---------|--------------------------|---------------|
+| AES-CBC | 16 bytes | `[16-byte IV] + [ciphertext]` | same blob |
+| AES-CTR | 16 bytes | `[16-byte IV] + [ciphertext]` | same blob |
+| AES-GCM | 12 bytes | `[12-byte nonce] + [ciphertext] + [16-byte tag]` | same blob |
+| ChaCha20-Poly1305 | 12 bytes | `[12-byte nonce] + [ciphertext] + [16-byte tag]` | same blob |
+
+When `config.iv` is **provided**, the engine uses it as-is and does NOT prepend it to the output. The caller is responsible for storing and providing the IV on decrypt. This mode is for callers that need explicit IV control (e.g. protocols with their own IV management).
+
+### HMAC / Signature Verification
+
+**If you need to** verify a signature or HMAC against received data:
+
+```mermaid
+sequenceDiagram
+ participant App as Application
+ participant CE as ICryptoEngineController
+ participant Op as ICryptoOperation
+
+ App->>CE: begin(VERIFY, config{algorithm=HMAC, digest=SHA_2_256, keyData=keyBytes})
+ CE-->>App: ICryptoOperation
+ App->>Op: update(data)
+ App->>Op: finish(signatureBytes)
+ Op-->>App: success or EX_SERVICE_SPECIFIC on mismatch
+```
+
+Works the same way for ECDSA, RSA-PSS, and RSA-PKCS1-v1_5 verification — change the algorithm and provide the public key.
+
+### Key Wrapping / Unwrapping
+
+**If you need to** wrap a key for secure transport or unwrap a received wrapped key:
+
+```mermaid
+sequenceDiagram
+ participant App as Application
+ participant CE as ICryptoEngineController
+ participant Op as ICryptoOperation
+
+ Note over App,CE: Wrap a key for transport
+ App->>CE: begin(WRAP_KEY, config{algorithm=AES, blockMode=KW, keyData=wrappingKey})
+ CE-->>App: ICryptoOperation
+ App->>Op: finish(keyToWrap)
+ Op-->>App: wrappedKeyBytes
+
+ Note over App,CE: Unwrap a received key
+ App->>CE: begin(UNWRAP_KEY, config{algorithm=AES, blockMode=KW, keyData=wrappingKey})
+ CE-->>App: ICryptoOperation
+ App->>Op: finish(wrappedKeyBytes)
+ Op-->>App: unwrappedKeyBytes
+```
+
+### Key Derivation (standalone)
+
+**If you need to** derive raw key bytes (e.g. for use as a session token or to pass to another system):
+
+```mermaid
+sequenceDiagram
+ participant App as Application
+ participant CE as ICryptoEngineController
+ participant Op as ICryptoOperation
+
+ App->>CE: begin(DERIVE_BITS, config{kdf=HKDF, digest=SHA_2_256, keyData=baseKey, salt=..., info=...})
+ CE-->>App: ICryptoOperation
+ App->>Op: finish(null)
+ Op-->>App: derivedBytes
+```
+
+### Random Number Generation
+
+**If you need** cryptographically secure random bytes:
+
+```mermaid
+sequenceDiagram
+ participant App as Application
+ participant CE as ICryptoEngineController
+
+ App->>CE: generateRandom(32)
+ CE-->>App: 32 random bytes
+```
+
+Uses the platform hardware RNG when available.
+
+---
+
+## Operation and Data Flow
+
+### Streaming operations (begin / update / finish)
+
+```mermaid
+sequenceDiagram
+ participant C as Client
+ participant Ctrl as ICryptoEngineController
+ participant Op as ICryptoOperation
+
+ C->>Ctrl: begin(ENCRYPT, config)
+ Ctrl-->>C: ICryptoOperation
+
+ loop For each data chunk
+ C->>Op: update(chunk)
+ Op-->>C: processed bytes
+ end
+
+ C->>Op: finish(finalChunk)
+ Op-->>C: final bytes + auth tag
+ Note over Op: Handle invalidated
+```
+
+### One-shot operations
+
+For small payloads, clients can skip the streaming model:
+
+- `encrypt(config, plaintext)` — equivalent to `begin(ENCRYPT) + finish(plaintext)`
+- `decrypt(config, ciphertext)` — equivalent to `begin(DECRYPT) + finish(ciphertext)`
+- `computeDigest(digest, data)` — stateless hash, no session required
+- `computeHmac(digest, key, data)` — stateless HMAC
+
+---
+
+## Event Handling
+
+The CryptoEngine HAL does not emit asynchronous events. All operations are synchronous request/response over Binder.
+
+For asynchronous lifecycle events (deep sleep, key invalidation), see the [KeyVault HAL](../../keyvault/current/document.md) and its `IKeyVaultEventListener`.
+
+---
+
+## State Machine / Lifecycle
+
+### Operation lifecycle
+
+```mermaid
+stateDiagram-v2
+ [*] --> ACTIVE : begin()
+ ACTIVE --> ACTIVE : update()
+ ACTIVE --> FINALISED : finish()
+ ACTIVE --> ABORTED : abort()
+ FINALISED --> [*]
+ ABORTED --> [*]
+```
+
+- `begin()` creates an `ACTIVE` operation.
+- `update()` can be called zero or more times while `ACTIVE`.
+- `finish()` completes the operation and returns final output.
+- `abort()` discards all state without producing output.
+- After `finish()` or `abort()`, the `ICryptoOperation` handle is invalidated.
+
+---
+
+## Error Handling
+
+| Exception | Meaning |
+|-----------|---------|
+| `EX_ILLEGAL_ARGUMENT` | Invalid configuration, unsupported key size, empty input. |
+| `EX_ILLEGAL_STATE` | Operation on an invalidated handle, max sessions/operations reached. |
+| `EX_UNSUPPORTED_OPERATION` | Algorithm or mode not supported by this engine. |
+| `EX_SERVICE_SPECIFIC` | GCM/Poly1305 authentication tag verification failure, or internal engine error. |
+
+On any exception, output parameters contain undefined memory and must not be used.
diff --git a/cryptoengine/current/hfp-cryptoengine.yaml b/crypto_engine/current/hfp-cryptoengine.yaml
similarity index 100%
rename from cryptoengine/current/hfp-cryptoengine.yaml
rename to crypto_engine/current/hfp-cryptoengine.yaml
diff --git a/cryptoengine/metadata.yaml b/crypto_engine/metadata.yaml
similarity index 100%
rename from cryptoengine/metadata.yaml
rename to crypto_engine/metadata.yaml
diff --git a/keyvault/current/CMakeLists.txt b/key_vault/current/CMakeLists.txt
similarity index 88%
rename from keyvault/current/CMakeLists.txt
rename to key_vault/current/CMakeLists.txt
index a6dadded..dd9f7165 100644
--- a/keyvault/current/CMakeLists.txt
+++ b/key_vault/current/CMakeLists.txt
@@ -7,7 +7,7 @@ endif()
set(CRYPTOENGINE_VERSION "current")
set(SRC_DIR com/rdk/hal/keyvault)
-set(CRYPTOENGINE_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../cryptoengine/${CRYPTOENGINE_VERSION}/com/rdk/hal/cryptoengine)
+set(CRYPTOENGINE_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../crypto_engine/${CRYPTOENGINE_VERSION}/com/rdk/hal/cryptoengine)
set(SRC
${SRC_DIR}/IKeyVault.aidl
@@ -27,7 +27,7 @@ set(SRC
set(INCLUDE_DIRECTORY
.
- ${CMAKE_CURRENT_SOURCE_DIR}/../../cryptoengine/${CRYPTOENGINE_VERSION}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../crypto_engine/${CRYPTOENGINE_VERSION}
)
compile_aidl(${SRC} INCLUDE_DIRECTORY ${INCLUDE_DIRECTORY})
diff --git a/keyvault/current/com/rdk/hal/keyvault/DerivedKeySpec.aidl b/key_vault/current/com/rdk/hal/keyvault/DerivedKeySpec.aidl
similarity index 100%
rename from keyvault/current/com/rdk/hal/keyvault/DerivedKeySpec.aidl
rename to key_vault/current/com/rdk/hal/keyvault/DerivedKeySpec.aidl
diff --git a/keyvault/current/com/rdk/hal/keyvault/IKeyVault.aidl b/key_vault/current/com/rdk/hal/keyvault/IKeyVault.aidl
similarity index 100%
rename from keyvault/current/com/rdk/hal/keyvault/IKeyVault.aidl
rename to key_vault/current/com/rdk/hal/keyvault/IKeyVault.aidl
diff --git a/keyvault/current/com/rdk/hal/keyvault/IKeyVaultController.aidl b/key_vault/current/com/rdk/hal/keyvault/IKeyVaultController.aidl
similarity index 100%
rename from keyvault/current/com/rdk/hal/keyvault/IKeyVaultController.aidl
rename to key_vault/current/com/rdk/hal/keyvault/IKeyVaultController.aidl
diff --git a/keyvault/current/com/rdk/hal/keyvault/IKeyVaultEventListener.aidl b/key_vault/current/com/rdk/hal/keyvault/IKeyVaultEventListener.aidl
similarity index 100%
rename from keyvault/current/com/rdk/hal/keyvault/IKeyVaultEventListener.aidl
rename to key_vault/current/com/rdk/hal/keyvault/IKeyVaultEventListener.aidl
diff --git a/keyvault/current/com/rdk/hal/keyvault/KeyDescriptor.aidl b/key_vault/current/com/rdk/hal/keyvault/KeyDescriptor.aidl
similarity index 100%
rename from keyvault/current/com/rdk/hal/keyvault/KeyDescriptor.aidl
rename to key_vault/current/com/rdk/hal/keyvault/KeyDescriptor.aidl
diff --git a/keyvault/current/com/rdk/hal/keyvault/VaultCapabilities.aidl b/key_vault/current/com/rdk/hal/keyvault/VaultCapabilities.aidl
similarity index 100%
rename from keyvault/current/com/rdk/hal/keyvault/VaultCapabilities.aidl
rename to key_vault/current/com/rdk/hal/keyvault/VaultCapabilities.aidl
diff --git a/keyvault/current/com/rdk/hal/keyvault/VaultState.aidl b/key_vault/current/com/rdk/hal/keyvault/VaultState.aidl
similarity index 100%
rename from keyvault/current/com/rdk/hal/keyvault/VaultState.aidl
rename to key_vault/current/com/rdk/hal/keyvault/VaultState.aidl
diff --git a/keyvault/current/hfp-keyvault.yaml b/key_vault/current/hfp-keyvault.yaml
similarity index 100%
rename from keyvault/current/hfp-keyvault.yaml
rename to key_vault/current/hfp-keyvault.yaml
diff --git a/key_vault/current/key_vault.md b/key_vault/current/key_vault.md
new file mode 100644
index 00000000..28653e3a
--- /dev/null
+++ b/key_vault/current/key_vault.md
@@ -0,0 +1,562 @@
+# KeyVault HAL
+
+## Overview
+
+The KeyVault HAL provides secure key storage and lifecycle management. It abstracts platform-specific secure storage (TEE, HSM) behind a uniform AIDL interface, offering named vault instances with independent key material, access rules, and persistence policies.
+
+A KeyVault is purely a key store — it holds key material and manages key metadata. To perform cryptographic operations on vault-managed keys, callers attach an `ICryptoEngineController` to the vault. The engine then uses the vault's keys for its operations.
+
+Excluded: cryptographic operations themselves — these are the responsibility of the CryptoEngine HAL.
+
+---
+
+## Architectural Model
+
+Key material is created, stored, and operated on **inside the TEE** — it never crosses into the REE in plaintext. Callers interact with keys only through opaque aliases and descriptors.
+
+### System Layers
+
+The HAL services run in the REE as normal Linux processes. The KeyVault manages key metadata and persistence. The CryptoEngine is the only component that talks to the Trusted Application (TA) inside the TEE. The KeyVault uses the CryptoEngine for all operations that touch key material.
+
+```mermaid
+flowchart TD
+ subgraph APP_LAYER [Application Layer - REE]
+ App[Application]
+ end
+
+ subgraph SVC_LAYER [Service Layer - REE]
+ Svc[RDK Crypto Service]
+ AA[AppArmor + UID
vault access policy]
+ Svc --> AA
+ end
+
+ subgraph HAL_LAYER [HAL Layer - REE]
+ HAL_KV[KeyVault HAL
metadata + storage I/O]
+ HAL_CE[CryptoEngine HAL
all crypto operations]
+ KS[(Encrypted Keystore)]
+ HAL_KV -->|"attachCryptoEngine"| HAL_CE
+ HAL_KV <-->|"read/write encrypted blobs"| KS
+ end
+
+ subgraph TEE_LAYER [Trusted Execution Environment]
+ TA[Trusted Application
key material + crypto ops]
+ OTP[(OTP Root Keys)]
+ TA -->|"derive per-vault keys"| OTP
+ end
+
+ App -->|"aliases, config, data"| Svc
+ AA -->|"allowed"| HAL_KV
+ HAL_CE -->|"TEE client API"| TA
+
+ style APP_LAYER fill:#f0f0f0,stroke:#999
+ style SVC_LAYER fill:#fff3e0,stroke:#e67e22
+ style HAL_LAYER fill:#e3f2fd,stroke:#1976d2
+ style TEE_LAYER fill:#e8f5e9,stroke:#388e3c
+ style TA fill:#2ecc71,color:#fff
+ style OTP fill:#e67e22,color:#fff
+ style KS fill:#666,color:#fff
+```
+
+### How operations flow through the layers
+
+The CryptoEngine is the only REE component that communicates with the TA. The KeyVault delegates all crypto to the CryptoEngine, which forwards to the TA. The TA runs inside the TEE (ARM TrustZone) where the REE — including the Linux kernel — cannot read or modify its memory.
+
+| Operation | KeyVault | CryptoEngine | TA (inside TEE) | Result |
+|-----------|----------|-------------|-----------------|--------|
+| **Generate key** | Requests key gen via CryptoEngine | Forwards to TA | Generates key with hardware RNG. Encrypts blob with OTP-derived vault key. | Encrypted blob returned. KeyVault writes to persistent storage. |
+| **Import key** | Passes raw material to CryptoEngine | Forwards to TA | Encrypts material with OTP-derived vault key. | Encrypted blob returned. KeyVault writes to persistent storage. |
+| **Encrypt** | Reads encrypted blob from persistent storage. Passes blob + plaintext to CryptoEngine. | Forwards to TA | Decrypts blob. Encrypts plaintext with the key. Key stays in TEE memory. | Ciphertext returned. |
+| **Decrypt** | Reads encrypted blob from persistent storage. Passes blob + ciphertext to CryptoEngine. | Forwards to TA | Decrypts blob. Decrypts ciphertext. | Plaintext returned. |
+| **Sign / HMAC** | Reads encrypted blob. Passes blob + data to CryptoEngine. | Forwards to TA | Decrypts blob. Computes signature. | Signature returned. |
+| **Derive into vault** | Reads source blob. Passes blob + peer key + specs to CryptoEngine. | Forwards to TA | Decrypts source key. Derives new keys. Encrypts each. | Encrypted blobs returned. KeyVault writes all to persistent storage. |
+| **Export key** | Reads encrypted blob. Passes to CryptoEngine. | Forwards to TA | Decrypts blob. Checks extractable flag. | Raw material (if extractable) or error. |
+
+The KeyVault handles metadata and storage I/O. The CryptoEngine handles TEE communication. Plaintext key material only ever exists inside the TA.
+
+### How keys are protected at rest
+
+```mermaid
+flowchart LR
+ subgraph TEE [Trusted Execution Environment]
+ OTP[OTP Root Key] -->|KDF| VK[Per-Vault Key]
+ VK -->|AES-GCM encrypt| EB[Encrypted Key Blob]
+ VK -->|HMAC-SHA256| MAC[Keystore HMAC]
+ end
+
+ subgraph REE [REE]
+ EB -->|via CryptoEngine| CE[CryptoEngine HAL]
+ MAC -->|via CryptoEngine| CE
+ CE --> KV[KeyVault HAL]
+ KV -->|write| STORE[(Encrypted Keystore)]
+ end
+
+ style TEE fill:#e8f5e9,stroke:#388e3c
+ style REE fill:#e3f2fd,stroke:#1976d2
+ style OTP fill:#e67e22,color:#fff
+ style VK fill:#2ecc71,color:#fff
+ style STORE fill:#666,color:#fff
+```
+
+1. The TA derives a **per-vault encryption key** from the hardware OTP root using a KDF. Each vault has its own derived key — compromise of one vault's data does not expose another.
+2. The TA **encrypts each key blob with AES-GCM** using the per-vault key. The GCM authentication tag ensures integrity.
+3. The encrypted blob is returned to the **CryptoEngine**, which passes it to the **KeyVault**. The KeyVault writes it to persistent storage. Neither the CryptoEngine nor the KeyVault can decrypt the blob.
+4. The TA computes an **HMAC over the keystore** so that tampering with any blob or metadata is detected on the next load.
+5. On boot, the KeyVault reads blobs from persistent storage, passes them through the CryptoEngine to the TA, and the TA validates the HMAC and re-derives vault keys from OTP before making keys available.
+
+### Cold boot vault initialisation
+
+On power-on, the TA derives per-vault encryption keys from the hardware OTP root. No vault key is ever stored — it is re-derived deterministically on every boot and lives only in TEE RAM.
+
+```text
+Vault Key = KDF(OTP_ROOT_KEY, vault_name)
+```
+
+```mermaid
+sequenceDiagram
+ participant SoC as SoC Power-On
+ participant TEE as TEE / TA
+ participant CE as CryptoEngine HAL (REE)
+ participant KV as KeyVault HAL (REE)
+ participant KS as Encrypted Keystore
+
+ SoC->>TEE: TEE initialises, TA loaded
+
+ KV->>KV: Read HFP — discover vault names
+
+ loop For each vault
+ KV->>CE: Initialise vault (vault_name)
+ CE->>TEE: Initialise vault (vault_name)
+ TEE->>TEE: Read OTP root key from SoC fuses
+ TEE->>TEE: Derive vault_key = KDF(OTP, vault_name)
+ TEE->>TEE: Hold vault_key in TEE RAM
+
+ KV->>KS: Read encrypted blobs for this vault
+ KS-->>KV: Encrypted blobs
+ KV->>CE: Validate keystore (encrypted blobs)
+ CE->>TEE: Decrypt blobs + validate HMAC
+ TEE->>TEE: Decrypt with vault_key, verify HMAC
+
+ alt HMAC valid
+ TEE-->>CE: OK
+ CE-->>KV: Vault state = READY
+ else HMAC invalid or corruption
+ TEE-->>CE: Error
+ CE-->>KV: Vault state = ERROR
+ end
+ end
+
+ KV->>KV: Register with Binder Service Manager
+ Note over KV: Clients can now open() vaults
+
+ Note over TEE: Vault keys exist only in TEE RAM
+ Note over TEE: On deep sleep / power loss — TEE RAM is wiped
+ Note over TEE: On resume — full sequence repeats
+```
+
+The vault key is **ephemeral** — it is derived on every boot, lives only in TEE RAM, and is lost on power loss or deep sleep. Because the derivation is deterministic (same OTP + same vault name = same key), the TA can always re-derive it and decrypt the stored blobs.
+
+This means:
+
+- **No vault key on disk.** Nothing to steal from persistent storage.
+- **No vault key in REE RAM.** The CryptoEngine and KeyVault never see the vault key.
+- **Device-bound.** A different device has a different OTP, so it derives a different vault key and cannot decrypt the blobs.
+
+### Key principles
+
+- **KeyVault manages metadata and persistence.** It holds aliases, descriptors, and encrypted blobs. It reads and writes the encrypted keystore. It never performs crypto directly — it delegates to the attached CryptoEngine.
+- **CryptoEngine is the TEE gateway.** It is the only REE component that communicates with the TA. All key generation, encryption, decryption, signing, and derivation flow through the CryptoEngine to the TA.
+- **The TA is the security boundary.** Plaintext key material exists only in TEE-protected memory. The TA generates keys, encrypts blobs with OTP-derived vault keys, and performs all crypto operations.
+- **Encrypted blobs transit the REE but are opaque.** The KeyVault and CryptoEngine handle encrypted blobs as byte arrays. Only the TA can decrypt them using OTP-derived keys that never leave the TEE.
+- **Named vaults provide natural isolation.** Each vault has its own OTP-derived encryption key. Compromise of one vault's blobs does not expose another vault's keys.
+- **SOFTWARE fallback.** For vaults with `securityLevel: SOFTWARE`, the CryptoEngine uses a software backend (e.g. OpenSSL) instead of the TA. Key material is still encrypted at rest but is present in REE process memory during operations.
+
+---
+
+## Use Cases
+
+### Authenticated Key Exchange
+
+**If you need to** establish session keys with a remote server via Diffie-Hellman:
+
+1. Open a TEE-backed vault
+2. `generateKeyPair()` — private key stays in vault, public key bytes returned
+3. Send public key to remote peer, receive their public key
+4. `deriveIntoVault()` — derive session keys (encryption, HMAC, wrapping) directly into vault
+5. Attach a crypto engine and use the derived keys for encrypted communication
+
+Key material never leaves the TEE. The caller only holds aliases and descriptors.
+
+```mermaid
+sequenceDiagram
+ participant App as Application
+ participant Ctrl as IKeyVaultController
+ participant CE as ICryptoEngineController
+
+ App->>Ctrl: generateKeyPair("dh-pub", "dh-priv", DH, 2048, DERIVE, false)
+ Ctrl-->>App: [pubDescriptor, privDescriptor]
+ App->>Ctrl: exportKey("dh-pub")
+ Ctrl-->>App: publicKeyBytes
+
+ Note over App: Exchange public keys with remote peer
+
+ App->>Ctrl: deriveIntoVault(config{kdf=...}, "dh-priv", peerPublicKey, outputSpecs[])
+ Ctrl-->>App: [encDescriptor, hmacDescriptor, ...]
+
+ App->>Ctrl: attachCryptoEngine(engine)
+ App->>CE: begin(ENCRYPT, config{keyAlias="session-enc"})
+ CE-->>App: ICryptoOperation
+```
+
+### Encrypted Persistent Storage
+
+**If you need to** store sensitive data (tokens, credentials, app state) encrypted on disk:
+
+1. Open a TEE-backed vault
+2. `generateKey()` — create a non-extractable AES key bound to the device
+3. Attach a crypto engine
+4. `encrypt()` data before writing to disk; `decrypt()` on read
+5. Key is device-bound — data cannot be decrypted on another device
+
+```mermaid
+sequenceDiagram
+ participant App as Application
+ participant Ctrl as IKeyVaultController
+ participant CE as ICryptoEngineController
+
+ App->>Ctrl: generateKey("storage-key", AES, 256, ENCRYPT|DECRYPT, false)
+ Ctrl-->>App: KeyDescriptor
+
+ App->>Ctrl: attachCryptoEngine(engine)
+
+ App->>CE: encrypt(config{keyAlias="storage-key", blockMode=CBC}, plaintext)
+ CE-->>App: ciphertext
+ Note over App: Write ciphertext to persistent storage
+
+ App->>CE: decrypt(config{keyAlias="storage-key", blockMode=CBC}, ciphertext)
+ CE-->>App: plaintext
+```
+
+### Device Identity and mTLS
+
+**If you need to** authenticate the device to a backend service using mutual TLS:
+
+1. Open the platform identity vault (contains factory-provisioned keypair)
+2. Export the public certificate (extractable) for the TLS handshake
+3. Attach a crypto engine for the private key signing operation
+4. The private key signs the TLS challenge inside the TEE — it never enters REE memory
+
+```mermaid
+sequenceDiagram
+ participant Svc as Service
+ participant Ctrl as IKeyVaultController
+ participant CE as ICryptoEngineController
+
+ Svc->>Ctrl: exportKey("device-cert-pub")
+ Ctrl-->>Svc: certificateBytes
+
+ Note over Svc: Present certificate in TLS handshake
+
+ Svc->>Ctrl: attachCryptoEngine(engine)
+ Svc->>CE: begin(SIGN, config{algorithm=EC, keyAlias="device-cert-priv"})
+ Note over CE: Private key signs challenge inside TEE
+```
+
+### Key Derivation (HKDF / PBKDF2)
+
+**If you need to** derive a new key from an existing secret (e.g. from a master key or password):
+
+1. Open a vault containing the base key
+2. `deriveIntoVault()` with the derivation config (HKDF with salt/info, or PBKDF2 with salt/iterations)
+3. The derived key is stored directly in the vault — raw material is never exposed
+
+```mermaid
+sequenceDiagram
+ participant App as Application
+ participant Ctrl as IKeyVaultController
+
+ App->>Ctrl: deriveIntoVault(config{kdf=HKDF, digest=SHA_2_256, salt=..., info=...}, "master-key", null, [derivedKeySpec])
+ Ctrl-->>App: [derivedKeyDescriptor]
+```
+
+---
+
+## Vault Access Control
+
+The HAL is caller-agnostic — it does not enforce per-app access control. Access control is the responsibility of the RDK Crypto Service, which sits between applications and the HAL.
+
+### How App-to-Vault Isolation Works
+
+Each application runs in its own container or process. The RDK Crypto Service receives all vault requests via Binder IPC, identifies the caller, and checks whether that caller is permitted to access the requested vault. If not, the request is rejected before it reaches the HAL.
+
+```mermaid
+flowchart TD
+ A1[App A] -->|Binder IPC| Svc[RDK Crypto Service]
+ A2[App B] -->|Binder IPC| Svc
+ A3[Platform Service] -->|Binder IPC| Svc
+
+ Svc -->|1. Identify caller| ID[AppArmor label + Binder UID]
+ ID -->|2. Check policy| Policy[Vault Access Policy]
+ Policy -->|Allowed| HAL[KeyVault HAL]
+ Policy -->|Denied| Err[EX_SECURITY]
+
+ style Svc fill:#ff9f43,color:#fff
+ style HAL fill:#4a9eff,color:#fff
+ style Policy fill:#e74c3c,color:#fff
+```
+
+Isolation is enforced in two layers:
+
+**AppArmor (mandatory access control)** — each application has an AppArmor profile that confines what it can do. The RDK Crypto Service reads the caller's AppArmor label via `/proc//attr/apparmor/current` and matches it against the vault access policy. This is a kernel-enforced boundary — the application cannot bypass or modify its own profile.
+
+**Binder caller UID (defence-in-depth)** — the RDK Crypto Service calls `getCallingUid()` on every request and checks it against a mapping of UID to permitted vault names. This catches misconfigured AppArmor profiles and provides a second verification of caller identity.
+
+Both checks must pass. If either fails, the service returns `EX_SECURITY` and the request never reaches the HAL.
+
+### Vault Access Policy
+
+The service maintains a vault access policy that maps caller identities to permitted vaults. This is a platform configuration file loaded at service startup.
+
+```yaml
+# /etc/rdk/crypto-service/vault-access.yaml
+vault-access:
+ - profile: "app-a"
+ vaults: ["app-a-storage"]
+
+ - profile: "app-b"
+ vaults: ["app-b-storage"]
+
+ - profile: "platform-service"
+ vaults: ["platform-identity", "drm-provisioning"]
+
+ # Default: no access to any vault
+```
+
+When an application calls `open(vaultName)`:
+
+1. Service reads the caller's AppArmor profile name
+2. Service looks up the profile in the vault access policy
+3. If the requested vault is in the allowed list, the request is forwarded to the HAL
+4. If not, `EX_SECURITY` is returned
+
+This is declarative, auditable, and updatable without changing the HAL or recompiling applications. The platform integrator defines the policy at build time; the service enforces it at runtime.
+
+---
+
+## References
+
+!!! info References
+|||
+|-|-|
+|**Interface Definition**|[keyvault/current](./com/rdk/hal/keyvault/)|
+|**API Documentation**| Generated from AIDL Javadoc comments |
+|**HAL Interface Type**| AIDL and Binder |
+|**HAL Feature Profile**| [hfp-keyvault.yaml](./hfp-keyvault.yaml) |
+
+---
+
+## Related Pages
+
+!!! tip "Related Pages"
+- [CryptoEngine HAL](../../cryptoengine/current/document.md) — crypto operations; attached to a vault via `attachCryptoEngine()`
+- [HAL Feature Profile](./hfp-keyvault.yaml) — platform-provisioned vaults and constraints
+
+---
+
+## Functional Overview
+
+The KeyVault HAL has three layers:
+
+| Interface | Role |
+|-----------|------|
+| `IKeyVault` | Top-level manager. Enumerates vaults, opens sessions, creates/destroys runtime vaults. |
+| `IKeyVaultController` | Per-session controller. Key lifecycle (generate, import, export, delete, rotate), crypto engine attachment, and vault introspection. |
+| `IKeyVaultEventListener` | Asynchronous callback interface for vault state changes, key expiry, and key invalidation. |
+
+---
+
+## Implementation Requirements
+
+| # | Requirement | Comments |
+|---|-------------|---------|
+| HAL.KV.1 | The service shall register with Binder Service Manager using the service name `KeyVault`. | Defined as `IKeyVault.serviceName`. |
+| HAL.KV.2 | Platform-provisioned vaults shall be available immediately after service startup. | Defined in HFP `vaults` section. |
+| HAL.KV.3 | Key material for TEE-backed vaults shall never leave the secure environment in plaintext. | Export returns `EX_SECURITY` for non-extractable keys. |
+| HAL.KV.4 | Key material at rest shall be encrypted using OTP-derived root keys. | Per-vault encryption with HMAC-authenticated keystores. |
+| HAL.KV.5 | On deep sleep, the HAL is closed. On resume, the HAL is reopened and vaults re-initialise. | Callers check `getVaultState()` after `open()`. |
+| HAL.KV.6 | `flush()` shall persist all pending changes and re-sign the keystore HMAC. | Write failure returns `EX_SERVICE_SPECIFIC`. |
+| HAL.KV.7 | Application-created vaults shall be subject to HFP limits (`allowApplicationVaults`, `maxApplicationVaults`). | `createVault()` returns `EX_UNSUPPORTED_OPERATION` if not permitted. |
+| HAL.KV.8 | Platform-provisioned vaults shall not be destroyable. | `destroyVault()` returns `EX_ILLEGAL_ARGUMENT`. |
+
+---
+
+## Interface Definitions
+
+| AIDL File | Description |
+|-----------|-------------|
+| `IKeyVault.aidl` | Top-level manager: vault enumeration, session open/close, runtime vault create/destroy |
+| `IKeyVaultController.aidl` | Per-session controller: key lifecycle, crypto engine attachment, vault introspection |
+| `IKeyVaultEventListener.aidl` | Oneway callback interface: state changes, key expiry, key invalidation, key rotation |
+| `VaultCapabilities.aidl` | Parcelable: vault name, security level, key limits, persistence, storage capacity |
+| `DerivedKeySpec.aidl` | Parcelable: output key spec for deriveIntoVault (alias, algorithm, type, size, usages) |
+| `KeyDescriptor.aidl` | Parcelable: key alias, algorithm, type, size, usages, extractability, digest, version, timestamps |
+| `VaultState.aidl` | Enum: READY, ERROR |
+
+---
+
+## Initialization
+
+1. The platform starts the KeyVault HAL service process.
+2. The service reads the HAL Feature Profile to discover platform-provisioned vaults.
+3. For each provisioned vault, the service initialises the keystore partition and validates the HMAC.
+4. The service registers `IKeyVault` with Binder Service Manager under the name `KeyVault`.
+5. Clients obtain the `IKeyVault` proxy via Service Manager lookup.
+6. Clients call `getVaultNames()` to discover available vaults.
+7. Clients call `open(vaultName, listener)` to obtain an `IKeyVaultController` session.
+
+---
+
+## Product Customization
+
+Platform vendors customize vaults via the HAL Feature Profile ([hfp-keyvault.yaml](./hfp-keyvault.yaml)):
+
+- **Application vault policy** — whether apps can create runtime vaults, and how many
+- **Platform-provisioned vaults** — each with:
+ - Name and description
+ - Security level (`SOFTWARE` or `TEE`)
+ - Maximum key count
+ - Supported key sizes
+ - Deep sleep persistence behaviour
+ - Storage capacity
+ - Key extractability policy
+
+Example provisioned vaults:
+
+| Vault | Security | Persists Sleep | Extractable | Use Case |
+|-------|----------|---------------|-------------|----------|
+| `platform-identity` | TEE | Yes | No | Device certificates and signing keys |
+| `app-secure-storage` | TEE | Yes | No | Per-application encrypted key-value storage |
+| `drm-provisioning` | TEE | Yes | No | DRM key provisioning and device credentials |
+| `netflix-msl` | TEE | No | No | Netflix MSL session keys (re-derived after sleep) |
+| `general-purpose` | SOFTWARE | Yes | Yes | Shared vault for platform services |
+
+---
+
+## Resource Management
+
+| Operation | Behaviour |
+|-----------|-----------|
+| `IKeyVault.open(name, listener)` | Opens a session to a named vault. Returns `IKeyVaultController`. |
+| `IKeyVault.close(controller)` | Aborts active operations, releases the session. Key material remains persisted. |
+| `IKeyVaultController.attachCryptoEngine(engine)` | Binds a crypto engine to this vault session. Only one engine per session. |
+| `IKeyVaultController.detachCryptoEngine()` | Unbinds the engine. Aborts in-flight operations using vault keys. |
+| `IKeyVault.createVault(name, level, maxKeys)` | Creates a runtime vault (subject to HFP limits). |
+| `IKeyVault.destroyVault(name)` | Destroys a runtime vault and securely erases all its keys. |
+
+- Multiple sessions can be open to the same vault concurrently.
+- If a client process dies, Binder death notification triggers cleanup of its sessions.
+
+---
+
+## Operation and Data Flow
+
+### Key generation and use
+
+```mermaid
+sequenceDiagram
+ participant C as Client
+ participant KV as IKeyVault
+ participant Ctrl as IKeyVaultController
+ participant CE as ICryptoEngineController
+ participant Op as ICryptoOperation
+
+ C->>KV: open("app-secure-storage", listener)
+ KV-->>C: IKeyVaultController
+
+ C->>Ctrl: generateKey("session-key", AES, 256, ENCRYPT|DECRYPT, false)
+ Ctrl-->>C: KeyDescriptor
+
+ C->>Ctrl: attachCryptoEngine(engine)
+
+ Note over CE,Ctrl: Engine now operates on vault keys
+
+ C->>CE: begin(ENCRYPT, config)
+ CE-->>C: ICryptoOperation
+ C->>Op: update(data)
+ Op-->>C: ciphertext
+ C->>Op: finish(null)
+ Op-->>C: final ciphertext + tag
+
+ C->>Ctrl: detachCryptoEngine()
+ C->>KV: close(controller)
+```
+
+### Key import and export
+
+- `importKey(alias, algorithm, keyType, keyData, usages, extractable)` — encrypts raw key material at rest using vault root-derived key
+- `exportKey(alias)` — returns raw key material only if `extractable == true`
+- `deleteKey(alias)` — securely erases key material and re-persists the keystore
+
+---
+
+## Event Handling
+
+Events are delivered via `IKeyVaultEventListener` (oneway/async):
+
+| Event | Trigger |
+|-------|---------|
+| `onVaultStateChanged(state)` | Vault seal/unseal transitions (deep sleep/resume), error conditions, initial readiness. |
+| `onKeyExpired(alias)` | Key TTL reached. Key material has been purged. |
+| `onKeyInvalidated(alias)` | Key deleted or otherwise invalidated. |
+| `onKeyRotated(alias, newVersion)` | Key rotated to a new version. |
+
+Listeners are registered either at `open()` time or via `registerEventListener()` / `unregisterEventListener()`.
+
+---
+
+## State Machine / Lifecycle
+
+### Vault state
+
+```mermaid
+stateDiagram-v2
+ [*] --> READY : Boot / keystore valid
+ [*] --> ERROR : Keystore corruption / HMAC failure
+ READY --> ERROR : Runtime error
+ ERROR --> [*] : Service restart
+```
+
+- `READY` — keys are accessible. Normal operating state.
+- `ERROR` — keystore corruption detected (e.g. HMAC validation failure).
+
+On deep sleep the HAL is closed; on resume it is reopened and vaults re-initialise. Callers should check `getVaultState()` after `open()` before attempting key operations.
+
+---
+
+## Platform Capabilities
+
+Queried at runtime via `IKeyVaultController.getCapabilities()`:
+
+| Field | Description |
+|-------|-------------|
+| `vaultName` | Human-readable vault name |
+| `halVersion` | HAL version string |
+| `securityLevel` | `SOFTWARE` or `TEE` |
+| `maxKeys` | Maximum key count for this vault |
+| `keySizes` | Supported key sizes in bits |
+| `persistsAcrossSleep` | Whether keys survive deep sleep |
+| `storageCapacityBytes` | Total keystore partition size |
+| `storageUsedBytes` | Current usage |
+
+---
+
+## Error Handling
+
+| Exception | Meaning |
+|-----------|---------|
+| `EX_ILLEGAL_ARGUMENT` | Unknown vault name, duplicate alias, empty key data, attempt to destroy platform vault. |
+| `EX_ILLEGAL_STATE` | Max sessions reached, engine already/not attached. |
+| `EX_UNSUPPORTED_OPERATION` | Application vault creation not permitted by HFP. |
+| `EX_SECURITY` | Attempt to export a non-extractable key. |
+| `EX_SERVICE_SPECIFIC` | Key limit reached, keystore write failure, internal error. |
+
+On any exception, output parameters contain undefined memory and must not be used.
diff --git a/keyvault/metadata.yaml b/key_vault/metadata.yaml
similarity index 100%
rename from keyvault/metadata.yaml
rename to key_vault/metadata.yaml
From 1c9c9b25ed1f5e93beadc4122b09ce6bffb20478 Mon Sep 17 00:00:00 2001
From: Ulrond <131959864+Ulrond@users.noreply.github.com>
Date: Wed, 1 Apr 2026 23:55:24 +0100
Subject: [PATCH 4/5] Fix document headers to match repo pattern
- Remove ## Overview heading (content follows # Title directly)
- Remove duplicate References/Related Pages sections from key_vault.md
- Fix Related Pages link in crypto_engine.md to point to key_vault path
---
crypto_engine/current/crypto_engine.md | 4 +--
key_vault/current/key_vault.md | 38 +++++++++++---------------
2 files changed, 17 insertions(+), 25 deletions(-)
diff --git a/crypto_engine/current/crypto_engine.md b/crypto_engine/current/crypto_engine.md
index 1fe7ea8e..8177a4a9 100644
--- a/crypto_engine/current/crypto_engine.md
+++ b/crypto_engine/current/crypto_engine.md
@@ -1,7 +1,5 @@
# CryptoEngine HAL
-## Overview
-
The CryptoEngine HAL provides standalone cryptographic operations independent of key storage. It abstracts platform-specific crypto acceleration (TEE) or software fallback (OpenSSL) behind a uniform AIDL interface.
The engine operates on caller-provided key material and configuration. It has no concept of key storage or ownership — it receives keys, performs operations, and returns results.
@@ -25,7 +23,7 @@ Excluded: key storage, key lifecycle, and access policy.
## Related Pages
!!! tip "Related Pages"
-- [KeyVault HAL](../../keyvault/current/document.md) — key storage and lifecycle; attaches a CryptoEngine for operations on vault-managed keys
+- [KeyVault HAL](../../key_vault/current/key_vault.md) — key storage and lifecycle; attaches a CryptoEngine for operations on vault-managed keys
- [HAL Feature Profile](./hfp-cryptoengine.yaml) — platform-specific capability declaration
---
diff --git a/key_vault/current/key_vault.md b/key_vault/current/key_vault.md
index 28653e3a..3b8b0d60 100644
--- a/key_vault/current/key_vault.md
+++ b/key_vault/current/key_vault.md
@@ -1,13 +1,27 @@
# KeyVault HAL
-## Overview
-
The KeyVault HAL provides secure key storage and lifecycle management. It abstracts platform-specific secure storage (TEE, HSM) behind a uniform AIDL interface, offering named vault instances with independent key material, access rules, and persistence policies.
A KeyVault is purely a key store — it holds key material and manages key metadata. To perform cryptographic operations on vault-managed keys, callers attach an `ICryptoEngineController` to the vault. The engine then uses the vault's keys for its operations.
Excluded: cryptographic operations themselves — these are the responsibility of the CryptoEngine HAL.
+## References
+
+!!! info References
+ |||
+ |-|-|
+ |**Interface Definition**|[key_vault/current](./com/rdk/hal/keyvault/)|
+ |**API Documentation**| Generated from AIDL Javadoc comments |
+ |**HAL Interface Type**| AIDL and Binder |
+ |**HAL Feature Profile**| [hfp-keyvault.yaml](./hfp-keyvault.yaml) |
+
+## Related Pages
+
+!!! tip "Related Pages"
+ - [CryptoEngine HAL](../../crypto_engine/current/crypto_engine.md) — crypto operations; attached to a vault via `attachCryptoEngine()`
+ - [HAL Feature Profile](./hfp-keyvault.yaml) — platform-provisioned vaults and constraints
+
---
## Architectural Model
@@ -342,26 +356,6 @@ This is declarative, auditable, and updatable without changing the HAL or recomp
---
-## References
-
-!!! info References
-|||
-|-|-|
-|**Interface Definition**|[keyvault/current](./com/rdk/hal/keyvault/)|
-|**API Documentation**| Generated from AIDL Javadoc comments |
-|**HAL Interface Type**| AIDL and Binder |
-|**HAL Feature Profile**| [hfp-keyvault.yaml](./hfp-keyvault.yaml) |
-
----
-
-## Related Pages
-
-!!! tip "Related Pages"
-- [CryptoEngine HAL](../../cryptoengine/current/document.md) — crypto operations; attached to a vault via `attachCryptoEngine()`
-- [HAL Feature Profile](./hfp-keyvault.yaml) — platform-provisioned vaults and constraints
-
----
-
## Functional Overview
The KeyVault HAL has three layers:
From 60278d5771915893398d42c9493904b19b1ecddb Mon Sep 17 00:00:00 2001
From: Ulrond <131959864+Ulrond@users.noreply.github.com>
Date: Sat, 4 Apr 2026 11:13:32 +0100
Subject: [PATCH 5/5] Address Copilot review feedback
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Fix KeyPurpose enum values to power-of-two flags for bitmask usage
(ENCRYPT=1, DECRYPT=2, SIGN=4, etc.) — was sequential 0,1,2,3
- Fix ICryptoOperation doc: remove reference to IKeyVaultController.begin()
- Fix deriveIntoVault doc: remove reference to non-existent config.keyAlias
- Fix registerEventListener doc: list actual callback methods
- Fix IKeyVaultEventListener doc: remove "power state transitions" reference
- Fix IKeyVault overview: vault is a logical keystore, not a crypto engine
- Fix generateKeyPair doc: clarify only descriptors returned, use exportKey
for raw public key bytes
- Fix computeDigest doc: remove SHA-1 reference (dropped from Digest enum)
- Fix crypto_engine metadata.yaml: dependency is None, not KeyVault
- Fix crypto_engine.md: remove SHA-1 from digest list, fix Digest.aidl desc
Relates to #385
---
.../cryptoengine/ICryptoEngineController.aidl | 2 +-
.../hal/cryptoengine/ICryptoOperation.aidl | 2 +-
.../com/rdk/hal/cryptoengine/KeyPurpose.aidl | 27 ++++++++++---------
crypto_engine/current/crypto_engine.md | 4 +--
crypto_engine/metadata.yaml | 10 ++++---
.../com/rdk/hal/keyvault/IKeyVault.aidl | 13 ++++-----
.../rdk/hal/keyvault/IKeyVaultController.aidl | 12 ++++-----
.../hal/keyvault/IKeyVaultEventListener.aidl | 2 +-
key_vault/metadata.yaml | 4 ++-
9 files changed, 42 insertions(+), 34 deletions(-)
diff --git a/crypto_engine/current/com/rdk/hal/cryptoengine/ICryptoEngineController.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/ICryptoEngineController.aidl
index 38a55ee0..b3d6136a 100644
--- a/crypto_engine/current/com/rdk/hal/cryptoengine/ICryptoEngineController.aidl
+++ b/crypto_engine/current/com/rdk/hal/cryptoengine/ICryptoEngineController.aidl
@@ -86,7 +86,7 @@ interface ICryptoEngineController {
*
* Stateless, one-shot operation. Does not require a key.
*
- * @param digest The digest algorithm to use (SHA-1, SHA-2-256, SHA-3-256, etc.).
+ * @param digest The digest algorithm to use (e.g. SHA_2_256, SHA_3_256).
* @param data The data to hash.
* @returns Digest bytes (length depends on algorithm: SHA-256=32, SHA-384=48, SHA-512=64).
* @exception binder::Status EX_UNSUPPORTED_OPERATION if the digest algorithm is not supported.
diff --git a/crypto_engine/current/com/rdk/hal/cryptoengine/ICryptoOperation.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/ICryptoOperation.aidl
index 8f7267ab..17fae662 100644
--- a/crypto_engine/current/com/rdk/hal/cryptoengine/ICryptoOperation.aidl
+++ b/crypto_engine/current/com/rdk/hal/cryptoengine/ICryptoOperation.aidl
@@ -22,7 +22,7 @@ package com.rdk.hal.cryptoengine;
* @brief Handle for an in-progress cryptographic operation.
* @author Gerald Weatherup
*
- * Returned by ICryptoEngineController.begin() or IKeyVaultController.begin().
+ * Returned by ICryptoEngineController.begin().
* Callers stream data through update() and complete with finish().
*
* Each operation maps to a crypto engine instance internally.
diff --git a/crypto_engine/current/com/rdk/hal/cryptoengine/KeyPurpose.aidl b/crypto_engine/current/com/rdk/hal/cryptoengine/KeyPurpose.aidl
index 856d34ac..7e10a1dc 100644
--- a/crypto_engine/current/com/rdk/hal/cryptoengine/KeyPurpose.aidl
+++ b/crypto_engine/current/com/rdk/hal/cryptoengine/KeyPurpose.aidl
@@ -21,26 +21,29 @@ package com.rdk.hal.cryptoengine;
/**
* @brief Permitted purposes for a key.
*
- * Bound to the key at creation time and enforced at operation begin().
+ * Values are power-of-two flags for use as a bitmask in KeyDescriptor.usages
+ * and DerivedKeySpec.usages (e.g. ENCRYPT | DECRYPT).
+ *
+ * When used as the purpose parameter in begin(), a single value is passed.
+ * When stored as key usages, values are OR'd together.
+ *
* Aligned with W3C WebCrypto KeyUsages.
*/
@VintfStability
@Backing(type="int")
enum KeyPurpose {
- /** Not configured. Must be explicitly set by the caller. */
- UNSET = -1,
- ENCRYPT = 0,
- DECRYPT = 1,
- SIGN = 2,
- VERIFY = 3,
+ ENCRYPT = 1 << 0,
+ DECRYPT = 1 << 1,
+ SIGN = 1 << 2,
+ VERIFY = 1 << 3,
/** Key agreement (ECDH, DH). */
- AGREE_KEY = 4,
+ AGREE_KEY = 1 << 4,
/** Wrap a key for transport or storage (AES-KW, RSA-OAEP). */
- WRAP_KEY = 5,
+ WRAP_KEY = 1 << 5,
/** Unwrap a wrapped key. */
- UNWRAP_KEY = 6,
+ UNWRAP_KEY = 1 << 6,
/** Derive a new key from this key (HKDF, PBKDF2, NFLX-DH). */
- DERIVE_KEY = 7,
+ DERIVE_KEY = 1 << 7,
/** Derive raw secret bits from a key. */
- DERIVE_BITS = 8,
+ DERIVE_BITS = 1 << 8,
}
diff --git a/crypto_engine/current/crypto_engine.md b/crypto_engine/current/crypto_engine.md
index 8177a4a9..f87afa80 100644
--- a/crypto_engine/current/crypto_engine.md
+++ b/crypto_engine/current/crypto_engine.md
@@ -46,7 +46,7 @@ The engine supports:
- **Key agreement** — ECDH (P-256, P-384, X25519)
- **Key wrapping** — AES-KW, RSA-OAEP
- **Key derivation** — HKDF, PBKDF2, DH, NFLX-DH
-- **Digest** — SHA-1, SHA-2-224, SHA-2-256, SHA-2-384, SHA-2-512
+- **Digest** — SHA-2-224, SHA-2-256, SHA-2-384, SHA-2-512, SHA-3-256, SHA-3-384, SHA-3-512
- **Random number generation** — hardware RNG when available
---
@@ -77,7 +77,7 @@ The engine supports:
| `Algorithm.aidl` | Enum: AES, EC, HMAC, RSA, CHACHA20_POLY1305 |
| `BlockMode.aidl` | Enum: CBC, CTR, GCM, ECB, KW |
| `PaddingMode.aidl` | Enum: NONE, PKCS7, RSA_OAEP, RSA_PSS, RSA_PKCS1_V1_5 |
-| `Digest.aidl` | Enum: SHA-1, SHA-2 family |
+| `Digest.aidl` | Enum: SHA-2 family, SHA-3 family |
| `EcCurve.aidl` | Enum: P-256, P-384, Ed25519, X25519 |
| `KeyDerivation.aidl` | Enum: HKDF, PBKDF2, NFLX_DH, DH |
| `KeyPurpose.aidl` | Enum: ENCRYPT, DECRYPT, SIGN, VERIFY, AGREE_KEY, WRAP_KEY, UNWRAP_KEY, DERIVE_KEY, DERIVE_BITS |
diff --git a/crypto_engine/metadata.yaml b/crypto_engine/metadata.yaml
index 91afdad9..5d62b896 100644
--- a/crypto_engine/metadata.yaml
+++ b/crypto_engine/metadata.yaml
@@ -1,7 +1,7 @@
component: cryptoengine
-version: 0.0.1.0
+version: 0.1.0.0
generation: 1
-status: RED
+status: GREEN
description: >
Crypto Engine HAL providing standalone cryptographic operations (encrypt,
decrypt, hash, sign, verify, random) independent of key storage. Engines
@@ -26,9 +26,11 @@ scope:
notes:
owners: "Architecture + Security"
- dependencies: "Shared enums from KeyVault HAL (com.rdk.hal.keyvault)"
+ dependencies: "None"
reviewers:
RTAB_Group: pending
Architecture: pending
- Security: pending
+ Product_Architecture: pending
+ Kernel_Architecture: pending
+ VTS_Team: pending
diff --git a/key_vault/current/com/rdk/hal/keyvault/IKeyVault.aidl b/key_vault/current/com/rdk/hal/keyvault/IKeyVault.aidl
index 7872e706..402da2cf 100644
--- a/key_vault/current/com/rdk/hal/keyvault/IKeyVault.aidl
+++ b/key_vault/current/com/rdk/hal/keyvault/IKeyVault.aidl
@@ -29,13 +29,14 @@ import com.rdk.hal.cryptoengine.SecurityLevel;
* Top-level entry point for the KeyVault HAL. Provides discovery of
* available vault instances and factory methods to open vault sessions.
*
- * A KeyVault is a configured crypto engine instance with its own key
- * material, crypto policy, and access rules. Multiple vaults can coexist
- * for different requirements (e.g. app secure storage, platform identity,
- * Netflix MSL, DRM provisioning).
+ * A KeyVault is a logical keystore (key namespace) with its own key
+ * material, access rules, and persistence policy. Multiple vaults can
+ * coexist for different requirements (e.g. app secure storage, platform
+ * identity, session keys, DRM provisioning).
*
- * Each vault has its own attached crypto engine and keystore, with
- * key material encrypted by OTP-derived root keys.
+ * Key material is encrypted at rest by OTP-derived root keys. To perform
+ * crypto operations on vault-managed keys, callers attach an
+ * ICryptoEngineController to the vault session.
*
* Exception Handling
* Unless otherwise specified, this interface follows standard Android Binder semantics:
diff --git a/key_vault/current/com/rdk/hal/keyvault/IKeyVaultController.aidl b/key_vault/current/com/rdk/hal/keyvault/IKeyVaultController.aidl
index 94708b32..dc746337 100644
--- a/key_vault/current/com/rdk/hal/keyvault/IKeyVaultController.aidl
+++ b/key_vault/current/com/rdk/hal/keyvault/IKeyVaultController.aidl
@@ -125,8 +125,8 @@ interface IKeyVaultController {
* @brief Generate an asymmetric keypair within this vault.
*
* Both the public and private key are stored in the vault under
- * separate aliases. The public key bytes are also returned directly
- * for transmission to a peer (e.g. DH key exchange).
+ * separate aliases. Only key descriptors are returned from this call;
+ * callers must use exportKey(publicAlias) to obtain raw public key bytes.
*
* @param publicAlias Alias for the public key in the vault.
* @param privateAlias Alias for the private key in the vault.
@@ -231,10 +231,10 @@ interface IKeyVaultController {
* For HKDF/PBKDF2, typically one output spec.
*
* The source key for derivation must already exist in this vault
- * (referenced by alias in config.keyAlias) and have DERIVE_KEY usage.
+ * (referenced by the sourceKeyAlias parameter) and have DERIVE_KEY usage.
*
* @param config Crypto configuration for the derivation (kdf, digest, salt, info, etc.).
- * config.keyData is ignored — the source key is taken from the vault.
+ * config.keyData is ignored — the source key is taken from the vault via sourceKeyAlias.
* @param sourceKeyAlias Alias of the source key in this vault.
* @param peerPublicKey Peer's public key for DH/NFLX-DH. Null for HKDF/PBKDF2.
* @param outputKeys Specifications for each derived key to store.
@@ -265,10 +265,10 @@ interface IKeyVaultController {
// -------------------------------------------------------------------------
/**
- * @brief Register for vault lifecycle events (deep sleep, key invalidation).
+ * @brief Register for vault lifecycle events.
*
* @param listener The event listener to register.
- * @post listener receives onDeviceSuspending/onDeviceResumed/onKeyInvalidated callbacks.
+ * @post listener receives onVaultStateChanged, onKeyExpired, onKeyInvalidated, and onKeyRotated callbacks.
*/
void registerEventListener(in IKeyVaultEventListener listener);
diff --git a/key_vault/current/com/rdk/hal/keyvault/IKeyVaultEventListener.aidl b/key_vault/current/com/rdk/hal/keyvault/IKeyVaultEventListener.aidl
index f598c49f..3e49bce0 100644
--- a/key_vault/current/com/rdk/hal/keyvault/IKeyVaultEventListener.aidl
+++ b/key_vault/current/com/rdk/hal/keyvault/IKeyVaultEventListener.aidl
@@ -25,7 +25,7 @@ import com.rdk.hal.keyvault.VaultState;
* @author Gerald Weatherup
*
* Registered via IKeyVaultController to receive notifications about
- * vault lifecycle events, key expiry, and power state transitions.
+ * vault state changes, key expiry, key invalidation, and key rotation.
*/
@VintfStability
oneway interface IKeyVaultEventListener {
diff --git a/key_vault/metadata.yaml b/key_vault/metadata.yaml
index 64c42f7e..bcdd1f60 100644
--- a/key_vault/metadata.yaml
+++ b/key_vault/metadata.yaml
@@ -29,4 +29,6 @@ notes:
reviewers:
RTAB_Group: pending
Architecture: pending
- Security: pending
+ Product_Architecture: pending
+ Kernel_Architecture: pending
+ VTS_Team: pending