From 18cafa0a1193009b431a8aff56e5905503cb6cfc Mon Sep 17 00:00:00 2001 From: Shikha Panwar Date: Thu, 5 Oct 2023 18:45:04 +0000 Subject: [PATCH] Introduce Secretkeeper HAL interface Secretkeeper is a privileged component which seals the secrets of pVM instances & releases them on successful authentication of the pVM. The HAL should be backed by a secure TA of higher privilege than a pVM. This patch introduces a subset of HAL spec - the SecretManagement api. The protocol is cbor based (specified in SecretManagement.cddl). Test: atest VtsSecretkeeperTargetTest Bug: 293429085 Change-Id: I8e650f27d506d378a94bbc8834c68a005fb12253 --- security/secretkeeper/aidl/Android.bp | 36 ++++++ .../security/secretkeeper/ISecretkeeper.aidl | 38 ++++++ .../security/secretkeeper/ISecretkeeper.aidl | 74 +++++++++++ .../secretkeeper/SecretManagement.cddl | 116 ++++++++++++++++++ 4 files changed, 264 insertions(+) create mode 100644 security/secretkeeper/aidl/Android.bp create mode 100644 security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl create mode 100644 security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl create mode 100644 security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretManagement.cddl diff --git a/security/secretkeeper/aidl/Android.bp b/security/secretkeeper/aidl/Android.bp new file mode 100644 index 0000000000..c77d2995b7 --- /dev/null +++ b/security/secretkeeper/aidl/Android.bp @@ -0,0 +1,36 @@ +// Copyright (C) 2023 The Android Open Source Project +// +// 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 { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +aidl_interface { + name: "android.hardware.security.secretkeeper", + vendor_available: true, + srcs: ["android/hardware/security/secretkeeper/*.aidl"], + stability: "vintf", + backend: { + ndk: { + enabled: true, + }, + rust: { + enabled: true, + apex_available: [ + "//apex_available:platform", + "com.android.virt", + ], + }, + }, +} diff --git a/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl b/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl new file mode 100644 index 0000000000..2eb33c56c9 --- /dev/null +++ b/security/secretkeeper/aidl/aidl_api/android.hardware.security.secretkeeper/current/android/hardware/security/secretkeeper/ISecretkeeper.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.security.secretkeeper; +@VintfStability +interface ISecretkeeper { + byte[] processSecretManagementRequest(in byte[] request); +} diff --git a/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl new file mode 100644 index 0000000000..af715a90cd --- /dev/null +++ b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/ISecretkeeper.aidl @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * 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 android.hardware.security.secretkeeper; + +@VintfStability +/** + * Secretkeeper service definition. + * + * An ISecretkeeper instance provides secure storage of secrets on behalf of other components in + * Android, in particular for protected virtual machine instances. From the perspective of security + * privilege, Secretkeeper must be implemented in an environment with privilege higher than any of + * its clients. Since AVF based protected Virtual Machines are one set of its clients, the + * implementation of ISecretkeeper should live in a secure environment, such as: + * - A trusted execution environment such as ARM TrustZone. + * - A completely separate, purpose-built and certified secure CPU. + * + * TODO(b/291224769): Extend the HAL interface to include: + * 1. Session setup api: This is used to perform cryptographic operations that allow shared keys to + * be exchanged between session participants, typically (but not necessarily) a pVM instance and + * Secretkeeper. This session setup is based on public key cryptography. + * 2. Dice policy operation - These allow sealing of the secrets with a class of Dice chains. + * Typical operations are (securely) updating the dice policy sealing the Secrets above. These + * operations are core to AntiRollback protected secrets - ie, ensuring secrets of a pVM are only + * accessible to same or higher versions of the images. + * 3. Maintenance api: This is required for removing the Secretkeeper entries for obsolete pvMs. + */ +interface ISecretkeeper { + /** + * processSecretManagementRequest method is used for interacting with the Secret Management API + * + * Secret Management API: The clients can use this API to store (& get) 32 bytes of data. + * The API is a CBOR based protocol, which follows request/response model. + * See SecretManagement.cddl for the API spec. + * + * Further, the requests (from client) & responses (from service) must be encrypted into + * ProtectedRequestPacket & ProtectedResponsePacket using symmetric keys agreed between + * the client & service. This cryptographic protection is required because the messages are + * ferried via Android, which is allowed to be outside the TCB of clients (for example protected + * Virtual Machines). For this, service (& client) must implement a key exchange protocol, which + * is critical for establishing the secure channel. + * + * Secretkeeper database should guarantee the following properties: + * 1. Confidentiality: No entity (of security privilege lower than Secretkeeper) should + * be able to get a client's data in clear. + * + * 2. Integrity: The data is protected against malicious Android OS tampering with database. + * ie, if Android (userspace & kernel) tampers with the client's secret, the Secretkeeper + * service must be able to detect it & return error when clients requests for their secrets. + * Note: the integrity requirements also include Antirollback protection ie, reverting the + * database into an old state should be detected. + * + * 3. The data is persistent across device boot. + * Note: Denial of service is not in scope. A malicious Android may be able to delete data, + * but for ideal Android, the data should be persistent. + * + * @param CBOR-encoded ProtectedRequestPacket. See SecretManagement.cddl for its definition. + * @return CBOR-encoded ProtectedResponsePacket. See SecretManagement.cddl for its definition + */ + byte[] processSecretManagementRequest(in byte[] request); +} diff --git a/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretManagement.cddl b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretManagement.cddl new file mode 100644 index 0000000000..5631937335 --- /dev/null +++ b/security/secretkeeper/aidl/android/hardware/security/secretkeeper/SecretManagement.cddl @@ -0,0 +1,116 @@ +; CDDL for the Secret Management API. +; Also see processSecretManagementRequest method in ISecretkeeper.aidl + +; ProtectedRequestPacket is used by client for accessing Secret Management API +; in Secretkeeper service. The service returns ProtectedResponsePacket of the corresponding type. + +; ProtectedRequestPacket & ProtectedResponsePacket are encrypted wrappers +; on RequestPacket & ResponsePacket using symmetric keys agreed between Secretkeeper & clients +; (these are referred to as KeySourceToSink & KeySinkToSource) +; +; The API operation required is encoded using 'Opcode', the arguments using 'Params' +; and returned values as 'Result'. + +ProtectedRequestPacket = + ProtectedGetVersionRequest / ProtectedStoreSecretRequest / ProtectedGetSecretRequest +ProtectedResponsePacket = + ProtectedGetVersionResponse / ProtectedStoreSecretResponse / ProtectedGetSecretResponse + +ProtectedGetVersionRequest = ProtectedRequestPacket +ProtectedGetVersionResponse = ProtectedResponsePacket +ProtectedStoreSecretRequest = ProtectedRequestPacket +ProtectedStoreSecretResponse = ProtectedResponsePacket +ProtectedGetSecretRequest = ProtectedRequestPacket +ProtectedGetSecretResponse = ProtectedResponsePacket + +GetVersionRequestPacket = RequestPacket +GetVersionResponsePacket = ResponsePacket +StoreSecretRequestPacket = RequestPacket +StoreSecretResponsePacket = ResponsePacket +GetSecretRequestPacket = RequestPacket +GetSecretResponsePacket = ResponsePacket + +RequestPacket = [ + Opcode, + Params +] +ResponsePacket = ResponsePacketError / ResponsePacketSuccess + +ResponsePacketSuccess = [ + 0, ; Indicates successful Response + result : Result +] +ResponsePacketError = [ + error_code: ErrorCode, ; Indicate the error + error_message: tstr ; Additional human-readable context +] + +Opcode = &( + GetVersionOpcode: 1, ; Get version of the SecretManagement API + StoreSecretOpcode: 2, ; Store a secret + GetSecretOpcode: 3, ; Get the secret +) + +GetVersionParams = () +GetVersionResult = (version : uint) + +StoreSecretParams = ( + id : bstr .size 64 ; Unique identifier of the secret + secret : bstr .size 32, + sealing_policy : bstr .cbor DicePolicy, ; See DicePolicy.cddl for definition of DicePolicy +) +StoreSecretResult = () + +GetSecretParams = ( + id : bstr .size 64 ; Unique identifier of the secret + ; Use this to update the sealing policy associated with a secret during GetSecret operation. + updated_sealing_policy : bstr .cbor DicePolicy / nil, +) +GetSecretResult = (secret : bstr .size 32) + + +ProtectedRequestPacket = CryptoPayload +ProtectedResponsePacket = ProtectedResponseError + / ProtectedResponseSuccess + +ProtectedResponseSuccess = [ + 0, ; Indicates successful crypto operations. Note: Payload + ; may contain Error from functional layer. + message: CryptoPayload ; message is the encrypted payload +] + +ProtectedResponseError = [ + error_code: CryptoErrorCode, ; Indicates the error. This is in cleartext & will be + ; visible to Android. These are errors from crypto + ; layer & indicates the request could not even be read + message: tstr ; Additional human-readable context +] + +CryptoPayload = [ ; COSE_Encrypt0 (untagged), [RFC 9052 s5.2] + protected: bstr .cbor { + 1 : 3, ; Algorithm: AES-GCM mode w/ 256-bit key, 128-bit tag + 4 : bstr ; key identifier, uniquely identifies the session + ; TODO(b/291228560): Refer to the Key Exchange spec. + }, + unprotected: { + 5 : bstr .size 12 ; IV + }, + ciphertext : bstr ; AES-GCM-256(Key, bstr .cbor Payload) + ; AAD for the encryption is CBOR-serialized + ; Enc_structure (RFC 9052 s5.3) with empty external_aad. +] + +; TODO(b/291224769): Create a more exhaustive set of CryptoErrorCode +CryptoErrorCode = &( + CryptoErrorCode_SessionExpired: 1, +) + +; TODO(b/291224769): Create a more exhaustive set of ErrorCodes +ErrorCode = &( + ; Use this as if no other error code can be used. + ErrorCode_UnexpectedServerError: 1, + ; Indicate the Request was malformed & hence couldnt be served. + ErrorCode_RequestMalformed: 2, +) + +; INCLUDE DicePolicy.cddl for: DicePolicy \ No newline at end of file