diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml index da318886a5..6ed8e8f354 100644 --- a/compatibility_matrices/compatibility_matrix.9.xml +++ b/compatibility_matrices/compatibility_matrix.9.xml @@ -508,6 +508,14 @@ SIM[1-9][0-9]* + + android.hardware.security.authgraph + 1 + + IAuthGraphKeyExchange + nonsecure + + android.hardware.security.secureclock 1 diff --git a/security/authgraph/aidl/Android.bp b/security/authgraph/aidl/Android.bp new file mode 100644 index 0000000000..d94f640570 --- /dev/null +++ b/security/authgraph/aidl/Android.bp @@ -0,0 +1,88 @@ +// 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +aidl_interface { + name: "android.hardware.security.authgraph", + vendor_available: true, + srcs: [ + "android/hardware/security/authgraph/*.aidl", + ], + stability: "vintf", + frozen: false, + backend: { + java: { + platform_apis: true, + }, + ndk: { + apps_enabled: false, + }, + rust: { + enabled: true, + apex_available: [ + "//apex_available:platform", + "com.android.virt", + ], + }, + }, +} + +// cc_defaults that includes the latest Authgraph AIDL library. +// Modules that depend on Authgraph directly can include this cc_defaults to avoid +// managing dependency versions explicitly. +cc_defaults { + name: "authgraph_use_latest_hal_aidl_ndk_static", + static_libs: [ + "android.hardware.security.authgraph-V1-ndk", + ], +} + +cc_defaults { + name: "authgraph_use_latest_hal_aidl_ndk_shared", + shared_libs: [ + "android.hardware.security.authgraph-V1-ndk", + ], +} + +cc_defaults { + name: "authgraph_use_latest_hal_aidl_cpp_static", + static_libs: [ + "android.hardware.security.authgraph-V1-cpp", + ], +} + +cc_defaults { + name: "authgraph_use_latest_hal_aidl_cpp_shared", + shared_libs: [ + "android.hardware.security.authgraph-V1-cpp", + ], +} + +// A rust_defaults that includes the latest Authgraph AIDL library. +// Modules that depend on Authgraph directly can include this rust_defaults to avoid +// managing dependency versions explicitly. +rust_defaults { + name: "authgraph_use_latest_hal_aidl_rust", + rustlibs: [ + "android.hardware.security.authgraph-V1-rust", + ], +} diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Arc.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Arc.aidl new file mode 100644 index 0000000000..dc86fbd5b8 --- /dev/null +++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Arc.aidl @@ -0,0 +1,39 @@ +/* + * 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.authgraph; +/* @hide */ +@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability +parcelable Arc { + byte[] arc; +} diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Error.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Error.aidl new file mode 100644 index 0000000000..1a78b54550 --- /dev/null +++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Error.aidl @@ -0,0 +1,50 @@ +/* + * 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.authgraph; +/* @hide */ +@Backing(type="int") @VintfStability +enum Error { + OK = 0, + INVALID_PEER_NONCE = (-1) /* -1 */, + INVALID_PEER_KE_KEY = (-2) /* -2 */, + INVALID_IDENTITY = (-3) /* -3 */, + INVALID_CERT_CHAIN = (-4) /* -4 */, + INVALID_SIGNATURE = (-5) /* -5 */, + INVALID_KE_KEY = (-6) /* -6 */, + INVALID_PUB_KEY_IN_KEY = (-7) /* -7 */, + INVALID_PRIV_KEY_ARC_IN_KEY = (-8) /* -8 */, + INVALID_SHARED_KEY_ARCS = (-9) /* -9 */, + MEMORY_ALLOCATION_FAILED = (-10) /* -10 */, + INCOMPATIBLE_PROTOCOL_VERSION = (-11) /* -11 */, +} diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl new file mode 100644 index 0000000000..2c56f339dd --- /dev/null +++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl @@ -0,0 +1,42 @@ +/* + * 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.authgraph; +/* @hide */ +@VintfStability +interface IAuthGraphKeyExchange { + android.hardware.security.authgraph.SessionInitiationInfo create(); + android.hardware.security.authgraph.KeInitResult init(in android.hardware.security.authgraph.PubKey peerPubKey, in android.hardware.security.authgraph.Identity peerId, in byte[] peerNonce, in int peerVersion); + android.hardware.security.authgraph.SessionInfo finish(in android.hardware.security.authgraph.PubKey peerPubKey, in android.hardware.security.authgraph.Identity peerId, in android.hardware.security.authgraph.SessionIdSignature peerSignature, in byte[] peerNonce, in int peerVersion, in android.hardware.security.authgraph.Key ownKey); + android.hardware.security.authgraph.Arc[2] authenticationComplete(in android.hardware.security.authgraph.SessionIdSignature peerSignature, in android.hardware.security.authgraph.Arc[2] sharedKeys); +} diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Identity.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Identity.aidl new file mode 100644 index 0000000000..bd5453ee82 --- /dev/null +++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Identity.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.authgraph; +@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability +parcelable Identity { + byte[] identity; +} diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/KeInitResult.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/KeInitResult.aidl new file mode 100644 index 0000000000..8c91523784 --- /dev/null +++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/KeInitResult.aidl @@ -0,0 +1,39 @@ +/* + * 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.authgraph; +@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability +parcelable KeInitResult { + android.hardware.security.authgraph.SessionInitiationInfo sessionInitiationInfo; + android.hardware.security.authgraph.SessionInfo sessionInfo; +} diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Key.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Key.aidl new file mode 100644 index 0000000000..5b4ebbf923 --- /dev/null +++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/Key.aidl @@ -0,0 +1,39 @@ +/* + * 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.authgraph; +@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability +parcelable Key { + @nullable android.hardware.security.authgraph.PubKey pubKey; + @nullable android.hardware.security.authgraph.Arc arcFromPBK; +} diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PlainPubKey.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PlainPubKey.aidl new file mode 100644 index 0000000000..f070bfaef4 --- /dev/null +++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PlainPubKey.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.authgraph; +@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability +parcelable PlainPubKey { + byte[] plainPubKey; +} diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PubKey.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PubKey.aidl new file mode 100644 index 0000000000..4c3376eb4d --- /dev/null +++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/PubKey.aidl @@ -0,0 +1,39 @@ +/* + * 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.authgraph; +@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability +union PubKey { + android.hardware.security.authgraph.PlainPubKey plainKey; + android.hardware.security.authgraph.SignedPubKey signedKey; +} diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionIdSignature.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionIdSignature.aidl new file mode 100644 index 0000000000..6dabc0a080 --- /dev/null +++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionIdSignature.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.authgraph; +@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability +parcelable SessionIdSignature { + byte[] signature; +} diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInfo.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInfo.aidl new file mode 100644 index 0000000000..427962b5b2 --- /dev/null +++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInfo.aidl @@ -0,0 +1,40 @@ +/* + * 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.authgraph; +@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability +parcelable SessionInfo { + android.hardware.security.authgraph.Arc[2] sharedKeys; + byte[] sessionId; + android.hardware.security.authgraph.SessionIdSignature signature; +} diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInitiationInfo.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInitiationInfo.aidl new file mode 100644 index 0000000000..bf55e74a2a --- /dev/null +++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SessionInitiationInfo.aidl @@ -0,0 +1,41 @@ +/* + * 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.authgraph; +@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability +parcelable SessionInitiationInfo { + android.hardware.security.authgraph.Key key; + android.hardware.security.authgraph.Identity identity; + byte[] nonce; + int version; +} diff --git a/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SignedPubKey.aidl b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SignedPubKey.aidl new file mode 100644 index 0000000000..3dbaed81b8 --- /dev/null +++ b/security/authgraph/aidl/aidl_api/android.hardware.security.authgraph/current/android/hardware/security/authgraph/SignedPubKey.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.authgraph; +@RustDerive(Clone=true, Eq=true, PartialEq=true) @VintfStability +parcelable SignedPubKey { + byte[] signedPubKey; +} diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Arc.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/Arc.aidl new file mode 100644 index 0000000000..855ce5c5c4 --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/Arc.aidl @@ -0,0 +1,34 @@ +/* + * 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.authgraph; + +/** + * This is the definition of the data format of an Arc. + * @hide + */ +@VintfStability +@RustDerive(Clone=true, Eq=true, PartialEq=true) +parcelable Arc { + /** + * The messages exchanged between the domains in the AuthGraph protocol are called Arcs. + * An arc is simply AES-GCM. Encryption of a payload P with a key K and additional + * authentication data (AAD) D: (i.e. Arc = Enc(K, P, D)). + * + * Data is CBOR-encoded according to the `Arc` CDDL definition in Arc.cddl. + */ + byte[] arc; +} diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Arc.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/Arc.cddl new file mode 100644 index 0000000000..4c1b965ab1 --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/Arc.cddl @@ -0,0 +1,115 @@ +; +; 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. +; +Arc = [ ; COSE_Encrypt0 [RFC9052 s5.2] + protected : bstr .cbor ArcProtectedHeaders, + unprotected : { + 5 : bstr .size 12 ; IV + }, + ciphertext : bstr ; Enc(K, bstr .cbor Payload, encoded ArcEncStruct) +] + +ArcProtectedHeaders = { + 1 : 3, ; Algorithm: AES-GCM mode w/ 256-bit key, 128-bit tag + ? -70001 : { + Permission }, ; One or more Permissions + ? -70002 : { + Limitation }, ; One or more Limitations + ? -70003 : int, ; Timestamp in milliseconds since some starting point (generally + ; the most recent device boot) which all of the applications within + ; the secure domain must agree upon + ? -70004 : bstr .size 16, ; Nonce used in key exchange methods + ? -70005 : PayloadType, ; Payload type, if needed to disambiguate, when processing an arc + ? -70006 : int, ; Version of the payload structure (if applicable) + ? -70007 : int, ; Sequence number (if needed to prevent replay attacks) + ? -70008 : Direction ; Direction of the encryption key (i.e. whether it is used to + ; encrypt incoming messages or outgoing messages) + ? -70009 : bool, ; "authentication_completed" - this is used during authenticated + ; key exchange indicate whether signature verification is done + ? -70010 : bstr .size 32 ; "session_id" computed during key exchange protocol +} + +; Permissions indicate what an arc can be used with. Permissions are added to an arc during the +; `create()` primitive operation and are propagated during `mint` and `snap` primitive operations. +Permission = &( + -4770552 : IdentityEncoded, ; "source_id" - in the operations performed by a source, the + ; source adds its own identity to the permissions of an arc. + -4770553 : IdentityEncoded, ; "sink_id" - in the operations performed by a sink, the sink + ; adds its own identity to the permissions of an arc. + -4770555 : [ +IdentityEncoded ] ; "minting_allowed" - defines the set of TA identities + ; to whom the payload key is allowed to be minted. + -4770556 : bool ; "deleted_on_biometric_change" - A Boolean value that + ; indicates whether an auth key issued from a biometric TA is + ; invalidated on new biometric enrollment or removal of all + ; biometrics. +) + +; Limitations indicate what restrictions are applied on the usage of an arc. Permissions are added +; to an arc during the `create` primitive operation and are propagated during `snap` primitive +; operation. +Limitation = &( + -4770554 : bstr, ; "challenge" - is added to an arc that transfers an auth key to a channel + ; key, in order to ensure the freshness of the authentication. + ; A challenge is issued by a sink (e.g. Keymint TA, Biometric TAs). +) + +; INCLUDE Identity.cddl for: Identity +IdentityEncoded = bstr .cbor Identity + +Direction = &( + In: 1, + Out: 2, +) + +PayloadType = &( + SecretKey: 1, + Arc: 2, + ; Any other payload types should also be defined here +) + +Payload = &( + SecretKey, + Arc, + ; Any other payload formats should also be defined here +) + +SecretKey = &( ; One of the payload types of an Arc is a secret key + SymmetricKey, + ECPrivateKey, ; Private key of a key pair generated for key exchange +) + +ECPrivateKey = { ; COSE_Key [RFC9052 s7] + 1 : 2, ; Key type : EC2 + 3 : -25, ; Algorithm: ECDH ES w/ HKDF 256 - generate key directly + ? 4 : [7], ; Key_ops: [derive key] + -1 : 1, ; Curve: P-256 + ? -2 : bstr, ; x coordinate + ? -3 : bstr, ; y coordinate + -4 : bstr, ; private key (d) +} + +SymmetricKey = { ; COSE_Key [RFC9052 s7] - For symmetric key encryption + 1 : 4, ; Key type : Symmetric + 3 : 3, ; Algorithm : AES-GCM mode w/ 256-bit key, 128-bit tag + 4 : [ 4 ], ; Key_ops: [decrypt] + -1 : bstr .size 32, ; Key value (k) +} + +ArcEncStruct = [ ; COSE_Enc_structure [RFC9052 s5.3] + context : "Encrypt0", + protected : bstr .cbor ArcProtectedHeaders, + external_aad : bstr .size 0, +] + +; INCLUDE generateCertificateRequestV2.cddl for: PubKeyEd25519, PubKeyECDSA256, PubKeyECDSA384 +; from hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/ diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/DicePolicy.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/DicePolicy.cddl new file mode 100644 index 0000000000..a7dcbc6ca0 --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/DicePolicy.cddl @@ -0,0 +1,33 @@ +; +; 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. +; +DicePolicy = [ + 1, ; dice policy version + + nodeConstraintList ; for each entry in dice chain +] + +nodeConstraintList = [ + * nodeConstraint +] + +; We may add a hashConstraint item later +nodeConstraint = exactMatchConstraint / geConstraint + +exactMatchConstraint = [1, keySpec, value] +geConstraint = [2, keySpec, int] + +keySpec = [value+] + +value = bool / int / tstr / bstr \ No newline at end of file diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Error.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/Error.aidl new file mode 100644 index 0000000000..1ad6054636 --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/Error.aidl @@ -0,0 +1,51 @@ +/* + * 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.authgraph; + +/** + * AuthGraph error codes. Aidl will return these error codes as service specific errors in + * EX_SERVICE_SPECIFIC. + * @hide + */ +@VintfStability +@Backing(type="int") +enum Error { + /* Success */ + OK = 0, + /* Invalid peer nonce for key exchange */ + INVALID_PEER_NONCE = -1, + /* Invalid key exchange public key by the peer */ + INVALID_PEER_KE_KEY = -2, + /* Invalid identity of the peer */ + INVALID_IDENTITY = -3, + /* Invalid certificate chain in the identity of the peer */ + INVALID_CERT_CHAIN = -4, + /* Invalid signature by the peer */ + INVALID_SIGNATURE = -5, + /* Invalid key exchange key created by a particular party themselves to be used as a handle */ + INVALID_KE_KEY = -6, + /* Invalid public key in the `Key` struct */ + INVALID_PUB_KEY_IN_KEY = -7, + /* Invalid private key arc in the `Key` struct */ + INVALID_PRIV_KEY_ARC_IN_KEY = -8, + /* Invalid shared key arcs */ + INVALID_SHARED_KEY_ARCS = -9, + /* Memory allocation failed */ + MEMORY_ALLOCATION_FAILED = -10, + /* The protocol version negotiated with the sink is incompatible */ + INCOMPATIBLE_PROTOCOL_VERSION = -11, +} diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/ExplicitKeyDiceCertChain.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/ExplicitKeyDiceCertChain.cddl new file mode 100644 index 0000000000..3de5617028 --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/ExplicitKeyDiceCertChain.cddl @@ -0,0 +1,30 @@ +; +; 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. +; +ExplicitKeyDiceCertChain = [ + 1, ; version, hopefully will never change + DiceCertChainInitialPayload, + * DiceChainEntry +] + +DiceCertChainInitialPayload = { + -4670552 : bstr .cbor PubKeyEd25519 / + bstr .cbor PubKeyECDSA256 / + bstr .cbor PubKeyECDSA384 ; subjectPublicKey +} + +; INCLUDE generateCertificateRequestV2.cddl for: PubKeyEd25519, PubKeyECDSA256, PubKeyECDSA384, +; DiceChainEntry +; from hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/ diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl new file mode 100644 index 0000000000..6ceb09cd08 --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/IAuthGraphKeyExchange.aidl @@ -0,0 +1,216 @@ +/* + * 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.authgraph; + +import android.hardware.security.authgraph.Arc; +import android.hardware.security.authgraph.Identity; +import android.hardware.security.authgraph.KeInitResult; +import android.hardware.security.authgraph.Key; +import android.hardware.security.authgraph.PubKey; +import android.hardware.security.authgraph.SessionIdSignature; +import android.hardware.security.authgraph.SessionInfo; +import android.hardware.security.authgraph.SessionInitiationInfo; + +/** + * AuthGraph interface definition for authenticated key exchange between two parties: P1 (source) + * and P2 (sink). + * Pre-requisites: each participant should have a: + * 1. Persistent identity - e.g. a signing key pair with a self signed certificate or a DICE + * certificate chain. + * 2. A symmetric encryption key kept in memory with per-boot life time of the participant + * (a.k.a per-boot key) + * + * ErrorCodes are defined in android.hardware.security.authgraph.ErrorCode.aidl. + * @hide + */ +@VintfStability +interface IAuthGraphKeyExchange { + /** + * This method is invoked on P1 (source). + * Create an ephermeral EC key pair on NIST curve P-256 and a nonce (of 16 bytes) for + * key exchange. + * + * @return SessionInitiationInfo including the `Key` containing the public key of the created + * key pair and an arc from the per-boot key to the private key, the nonce, the persistent + * identity and the latest protocol version (i.e. AIDL version) supported. + * + * Note: The arc from the per-boot key to the private key in `Key` of the return type: + * `SessionInitiationInfo` serves two purposes: + * i. A mapping to correlate `create` and `finish` calls to P1 in a particular instance of the + * key exchange protocol. + * ii.A way to minimize the in-memory storage (P1 can include the nonce in the protected headers + * of the arc). + * However, P1 should maintain some form of in-memory record to be able to verify that the input + * `Key` sent to `finish` is from an unfinished instance of a key exchange protocol, to prevent + * any replay attacks in `finish`. + */ + SessionInitiationInfo create(); + + /** + * This method is invoked on P2 (sink). + * Perform the following steps for key exchange: + * 0. If either `peerPubKey`, `peerId`, `peerNonce` is not in the expected format, return + * errors: INVALID_PEER_KE_KEY, INVALID_IDENTITY, INVALID_PEER_NONCE respectively. + * 1. Create an ephemeral EC key pair on NIST curve P-256. + * 2. Create a nonce (of 16 bytes). + * 3. Compute the diffie-hellman shared secret: Z. + * 4. Compute a salt = bstr .cbor [ + * source_version: int, ; from input `peerVersion` + * sink_pub_key: bstr .cbor PlainPubKey, ; from step #1 + * source_pub_key: bstr .cbor PlainPubKey, ; from input `peerPubKey` + * sink_nonce: bstr .size 16, ; from step #2 + * source_nonce: bstr .size 16, ; from input `peerNonce` + * sink_cert_chain: bstr .cbor ExplicitKeyDiceCertChain, ; from own identity + * source_cert_chain: bstr .cbor ExplicitKeyDiceCertChain, ; from input `peerId` + * ] + * 5. Extract a cryptographic secret S from Z, using the salt from #4 above. + * 6. Derive two symmetric encryption keys of 256 bits with: + * i. b"KE_ENCRYPTION_KEY_SOURCE_TO_SINK" as context for the key used to encrypt incoming + * messages + * ii. b"KE_ENCRYPTION_KEY_SINK_TO_SOURCE" as context for the key used to encrypt outgoing + * messages + * 7. Create arcs from the per-boot key to each of the two shared keys from step #6 and + * mark authentication_complete = false in arcs' protected headers. + * 8. Derive a MAC key with b"KE_HMAC_KEY" as the context. + * 9. Compute session_id_input = bstr .cbor [ + * sink_nonce: bstr .size 16, + * source_nonce: bstr .size 16, + * ], + * 10.Compute a session_id as a 256 bits HMAC over the session_id_input from step#9 with + * the key from step #8. + * 11.Create a signature over the session_id from step #10, using the signing key which is + * part of the party's identity. + * + * @param peerPubKey - the public key of the key pair created by the peer (P1) for key exchange + * + * @param peerId - the persistent identity of the peer + * + * @param peerNonce - nonce created by the peer + * + * @param peerVersion - an integer representing the latest protocol version (i.e. AIDL version) + * supported by the peer + * + * @return KeInitResult including the `Key` containing the public key of the created key pair, + * the nonce, the persistent identity, two shared key arcs from step #7, session id, signature + * over the session id and the negotiated protocol version. The negotiated protocol version + * should be less than or equal to the peer's version. + * + * Note: The two shared key arcs in the return type: `KeInitResult` serves two purposes: + * i. A mapping to correlate `init` and `authenticationComplete` calls to P2 in a particular + * instance of the key exchange protocol. + * ii.A way to minimize the in-memory storage of P2 allocated for key exchange. + * However, P2 should maintain some in-memory record to be able to verify that the input + * `sharedkeys` sent to `authenticationComplete` and to any subsequent AuthGraph protocol + * methods are valid shared keys agreed with the party identified by `peerId`, to prevent + * any replay attacks in `authenticationComplete` and in any subsequent AuthGraph protocol + * methods which use the shared keys to encrypt the secret messages. + */ + KeInitResult init( + in PubKey peerPubKey, in Identity peerId, in byte[] peerNonce, in int peerVersion); + + /** + * This method is invoked on P1 (source). + * Perform the following steps: + * 0. If either `peerPubKey`, `peerId`, `peerNonce` is not in the expected format, return + * errors: INVALID_PEER_KE_KEY, INVALID_IDENTITY, INVALID_PEER_NONCE respectively. If + * `peerVersion` is greater than the version advertised in `create`, return error: + * INCOMPATIBLE_PROTOCOL_VERSION. + * If `ownKey` is not in the in-memory records for unfinished instances of a key + * exchange protocol, return error: INVALID_KE_KEY. Similarly, if the public key or the + * arc containing the private key in `ownKey` is invalid, return INVALID_PUB_KEY_IN_KEY + * and INVALID_PRIV_KEY_ARC_IN_KEY respectively. + * 1. Compute the diffie-hellman shared secret: Z. + * 2. Compute a salt = bstr .cbor [ + * source_version: int, ; the protocol version used in `create` + * sink_pub_key: bstr .cbor PlainPubKey, ; from input `peerPubKey` + * source_pub_key: bstr .cbor PlainPubKey, ; from the output of `create` + * sink_nonce: bstr .size 16, ; from input `peerNonce` + * source_nonce: bstr .size 16, ; from the output of `create` + * sink_cert_chain: bstr .cbor ExplicitKeyDiceCertChain, ; from input `peerId` + * source_cert_chain: bstr .cbor ExplicitKeyDiceCertChain, ; from own identity + * ] + * 3. Extract a cryptographic secret S from Z, using the salt from #2 above. + * 4. Derive two symmetric encryption keys of 256 bits with: + * i. b"KE_ENCRYPTION_KEY_SOURCE_TO_SINK" as context for the key used to encrypt outgoing + * messages + * ii. b"KE_ENCRYPTION_KEY_SINK_TO_SOURCE" as context for the key used to encrypt incoming + * messages + * 5. Derive a MAC key with b"KE_HMAC_KEY" as the context. + * 6. Compute session_id_input = bstr .cbor [ + * sink_nonce: bstr .size 16, + * source_nonce: bstr .size 16, + * ], + * 7. Compute a session_id as a 256 bits HMAC over the session_id_input from step #6 with + * the key from step #5. + * 8. Verify the peer's signature over the session_id from step #7. If successful, proceed, + * otherwise, return error: INVALID_SIGNATURE. + * 9. Create arcs from the per-boot key to each of the two shared keys from step #4 and + * mark authentication_complete = true in arcs' protected headers. + * 10.Create a signature over the session_id from step #7, using the signing key which is + * part of the party's identity. + * + * @param peerPubKey - the public key of the key pair created by the peer (P2) for key exchange + * + * @param peerId - the persistent identity of the peer + * + * @param peerSignature - the signature created by the peer over the session id computed by the + * peer + * + * @param peerNonce - nonce created by the peer + * + * @param peerVersion - an integer representing the protocol version (i.e. AIDL version) + * negotiated with the peer + * + * @param ownKey - the key created by P1 (source) in `create()` for key exchange + * + * @return SessionInfo including the two shared key arcs from step #9, session id and the + * signature over the session id. + * + * Note: The two shared key arcs in the return type: `SessionInfo` serves two purposes: + * i. A mapping to correlate the key exchange protocol taken place with a particular peer and + * subsequent AuthGraph protocols execued with the same peer. + * ii.A way to minimize the in-memory storage for shared keys. + * However, P1 should maintain some in-memory record to be able to verify that the shared key + * arcs sent to any subsequent AuthGraph protocol methods are valid shared keys agreed with the + * party identified by `peerId`, to prevent any replay attacks. + */ + SessionInfo finish(in PubKey peerPubKey, in Identity peerId, + in SessionIdSignature peerSignature, in byte[] peerNonce, in int peerVersion, + in Key ownKey); + + /** + * This method is invoked on P2 (sink). + * Perform the following steps: + * 0. If input `sharedKeys` is invalid (i.e. they cannot be decrypted with P2's per-boot key + * or they are not in P2's in-memory records as valid shared keys agreed with the party + * identified by `peerId`), return error: INVALID_SHARED_KEY_ARCS. + * 1. Verify that both shared key arcs have the same session id and peer identity. + * 2. Verify the peer's signature over the session id attached to the shared key arcs' + * headers. If successful, proceed, otherwise, return error: INVALID_SIGNATURE. + * 3. Mark authentication_complete = true in the shared key arcs' headers + * + * @param peerSignature - the signature created by the peer over the session id computed by the + * peer + * + * @param sharedKeys - two shared key arcs created by P2 in `init`. P2 obtains from the arcs' + * protected headers, the session id and the peer's identity to verify the + * peer's signature over the session id. + * + * @return Arc[] - an array of two updated shared key arcs + */ + Arc[2] authenticationComplete(in SessionIdSignature peerSignature, in Arc[2] sharedKeys); +} diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Identity.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/Identity.aidl new file mode 100644 index 0000000000..9e350e8091 --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/Identity.aidl @@ -0,0 +1,43 @@ +/* + * 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.authgraph; + +/** + * Persistent (versioned) identity of a participant of Authgraph key exchange. + * Identity consists of two main parts: + * 1. a certificate chain (e.g. a DICE certificate chain) + * 2. (optional) a policy specifying how to verify the certificate chain - if a policy is not + * provided, a simple byte-to-byte comparison of the certificate chain is assumed. + * + * During identity verification, the certificate chain of the identity attached to the access + * request is compared against the policy of the identity attached to the persistent resources. + * + * The usage of policy based identity verification in Authgraph is three-fold: + * 1. Retain access to persistent resources for the newer versions of the party who + * created them, even when parts of the certificate chain are updated in the new version. + * 2. Deny access to the new persistent resources for the older versions of the party + * who created the new persistent resources. + * 3. Trigger rotation of critical keys encrypted in persistent arcs created by the previous + * version of the party, by including an updated policy in the identity attached to the + * access request. + */ +@VintfStability +@RustDerive(Clone=true, Eq=true, PartialEq=true) +parcelable Identity { + /* Data is CBOR-encoded according to the `Identity` CDDL definition in Identity.cddl */ + byte[] identity; +} diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Identity.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/Identity.cddl new file mode 100644 index 0000000000..0419421fa6 --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/Identity.cddl @@ -0,0 +1,23 @@ +; +; 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. +; +Identity = [ + 1, ; Version + cert_chain: bstr .cbor ExplicitKeyDiceCertChain, + policy: bstr .cbor DicePolicy / nil, +] + +; INCLUDE ExplicitKeyDiceCertChain.cddl for: ExplicitKeyDiceCertChain +; INCLUDE DicePolicy.cddl for: DicePolicy diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/KeInitResult.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/KeInitResult.aidl new file mode 100644 index 0000000000..b4ae451cd1 --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/KeInitResult.aidl @@ -0,0 +1,37 @@ +/* + * 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.authgraph; + +import android.hardware.security.authgraph.SessionInfo; +import android.hardware.security.authgraph.SessionInitiationInfo; + +/** + * The return type for the init() step of authenticated key exchange. + */ +@VintfStability +@RustDerive(Clone=true, Eq=true, PartialEq=true) +parcelable KeInitResult { + /** + * Session initiation information. + */ + SessionInitiationInfo sessionInitiationInfo; + + /** + * Session information. + */ + SessionInfo sessionInfo; +} diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/Key.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/Key.aidl new file mode 100644 index 0000000000..11fe174608 --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/Key.aidl @@ -0,0 +1,41 @@ +/* + * 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.authgraph; + +import android.hardware.security.authgraph.Arc; +import android.hardware.security.authgraph.PubKey; + +/** + * The type that encapsulates a key. Key can be either a symmetric key or an asymmetric key. + * If it is an asymmetric key, it is used for key exchange. + */ +@VintfStability +@RustDerive(Clone=true, Eq=true, PartialEq=true) +parcelable Key { + /** + * If the Key is an asymmetric key, public key should be present. + */ + @nullable PubKey pubKey; + + /** + * Arc from the per-boot key to the payload key. The payload key is either the symmetric key + * or the private key of an asymmetric key, based on the type of the key being created. + * This is marked as optional because there are instances where only the public key is returned, + * e.g. `init` method in the key exchange protocol. + */ + @nullable Arc arcFromPBK; +} diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.aidl new file mode 100644 index 0000000000..5483ec5d7a --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.aidl @@ -0,0 +1,28 @@ +/* + * 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.authgraph; + +/** + * One of the two enum variants of the enum type: `PubKey`. This represents the plain public key + * material encoded as a COSE_Key. + */ +@VintfStability +@RustDerive(Clone=true, Eq=true, PartialEq=true) +parcelable PlainPubKey { + /* Data is CBOR-encoded according to the `PlainPubKey` CDDL definition in PlainPubKey.cddl */ + byte[] plainPubKey; +} diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.cddl new file mode 100644 index 0000000000..34b316b135 --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/PlainPubKey.cddl @@ -0,0 +1,24 @@ +; +; 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. +; + +; P-256 public key for key exchange. +PlainPubKey = [ ; COSE_Key [RFC9052 s7] + 1 : 2, ; Key type : EC2 + 3 : -27, ; Algorithm : ECDH-SS + HKDF-256 + -1 : 1, ; Curve: P256 + -2 : bstr, ; X coordinate, big-endian + -3 : bstr ; Y coordinate, big-endian +] diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/PubKey.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/PubKey.aidl new file mode 100644 index 0000000000..864087178a --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/PubKey.aidl @@ -0,0 +1,37 @@ +/* + * 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.authgraph; + +import android.hardware.security.authgraph.PlainPubKey; +import android.hardware.security.authgraph.SignedPubKey; + +/** + * The enum type representing the public key of an asymmetric key pair. + */ +@VintfStability +@RustDerive(Clone=true, Eq=true, PartialEq=true) +union PubKey { + /** + * Plain public key material encoded as a COSE_Key. + */ + PlainPubKey plainKey; + + /** + * Public key signed with the long term signing key of the party. + */ + SignedPubKey signedKey; +} diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.aidl new file mode 100644 index 0000000000..2fa8b4c8b9 --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.aidl @@ -0,0 +1,28 @@ +/* + * 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.authgraph; + +/** + * Signature computed by a party over the session id during authenticated key exchange. + */ +@VintfStability +@RustDerive(Clone=true, Eq=true, PartialEq=true) +parcelable SessionIdSignature { + /* Data is CBOR-encoded according to the `SessionIdSignature` CDDL definition in + * SessionIdSignature.cddl */ + byte[] signature; +} diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.cddl new file mode 100644 index 0000000000..038a0f01f4 --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/SessionIdSignature.cddl @@ -0,0 +1,33 @@ +; +; 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. +; +SessionIdSignature = [ ; COSE_Sign1 (untagged) [RFC9052 s4.2] + protected: bstr .cbor SessionIdSignatureProtected, + unprotected: {}, + payload: nil, ; session ID payload to be transported separately + signature: bstr ; PureEd25519(privateKey, SessionIdSignatureSigStruct) / + ; ECDSA(privateKey, SessionIdSignatureSigStruct) +] + +SessionIdSignatureProtected = { + 1 : AlgorithmEdDSA / AlgorithmES256, +} + +SessionIdSignatureSigStruct = [ ; Sig_structure for SessionIdSignature [ RFC9052 s4.4] + context: "Signature1", + protected: bstr SessionIdSignatureProtected, + external_aad: bstr .size 0, + payload: bstr, ; session ID payload provided separately +] diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SessionInfo.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInfo.aidl new file mode 100644 index 0000000000..ef49a1a1c0 --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInfo.aidl @@ -0,0 +1,50 @@ +/* + * 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.authgraph; + +import android.hardware.security.authgraph.Arc; +import android.hardware.security.authgraph.SessionIdSignature; + +/** + * Session information returned as part of authenticated key exchange. + */ +@VintfStability +@RustDerive(Clone=true, Eq=true, PartialEq=true) +parcelable SessionInfo { + /** + * The arcs that encrypt the two derived symmetric encryption keys (for two-way communication) + * from the party's per-boot key. + */ + Arc[2] sharedKeys; + + /** + * The value of the session id computed by the two parties during the authenticate key + * exchange. Apart from the usage of the session id by the two peers, session id is also useful + * to verify (by a third party) that the key exchange was successful. + */ + byte[] sessionId; + + /** + * The signature over the session id, created by the party who computed the session id. + * + * If there is one or more `DiceChainEntry` in the `ExplicitKeyDiceCertChain` of the party's + * identity, the signature is verified with the public key in the leaf of the chain of + * DiceChainEntries (i.e the public key in the last of the array of DiceChainEntries). + * Otherwise, the signature is verified with the `DiceCertChainInitialPayload`. + */ + SessionIdSignature signature; +} diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SessionInitiationInfo.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInitiationInfo.aidl new file mode 100644 index 0000000000..c630d91907 --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/SessionInitiationInfo.aidl @@ -0,0 +1,69 @@ +/* + * 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.authgraph; + +import android.hardware.security.authgraph.Arc; +import android.hardware.security.authgraph.Identity; +import android.hardware.security.authgraph.Key; + +/** + * Session initiation information returned as part of authenticated key exchange. + */ +@VintfStability +@RustDerive(Clone=true, Eq=true, PartialEq=true) +parcelable SessionInitiationInfo { + /** + * An ephemeral EC key created for the ECDH process. + */ + Key key; + + /** + * The identity of the party who created the Diffie-Hellman key exchange key. + */ + Identity identity; + + /** + * Nonce value specific to this session. The nonce serves three purposes: + * 1. freshness of key exchange + * 2. creating a session id (a publicly known value related to the exchanged keys) + * 3. usage as salt into the HKDF-EXTRACT function during key derivation from the shared DH key + */ + byte[] nonce; + + /** + * The protocol version (i.e. AIDL version) - This is used to prevent version downgrade attacks + * as follows: + * 1. In `create`, the source advertises the latest protocol version supported by the source, + * which is given as input to the `init` call on the sink in the input parameter: + * `peerVersion`. + * 2. In `init`, the sink includes the `peerVersion` in the inputs to the derivation of the + * shared keys. Then the sink returns the latest protocol version supported by the sink, + * which is given as input to the `finish` call on the source in the input parameter: + * `peerVersion`. + * 3. In `finish`, the source first checks whether the sink's version is equal or less than the + * source's version and includes in the source's version in the inputs to the derivation of + * the shared keys. + * Analysis: if an attacker-in-the-middle wanted the two parties to use an older (vulnerable) + * version of the protocol, they can invoke `init` with a version that is lower than the version + * advertised by the source in `create`. However, since both parties include the source's + * version in the inputs to the derivation of the shared keys, the two parties won't end up with + * the same shared keys in the presence of such an attack. This is detected when checking the + * signature on the session id in `finish`, at which point the protocol aborts. Therefore, + * an attacker cannot successfully launch a version downgrade attack on this protocol. + */ + int version; +} diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.aidl b/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.aidl new file mode 100644 index 0000000000..72ee219a9b --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.aidl @@ -0,0 +1,28 @@ +/* + * 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.authgraph; + +/** + * One of the two enum variants of the enum type: `PubKey`. This represents the public key signed + * with the long term signing key of the party. + */ +@VintfStability +@RustDerive(Clone=true, Eq=true, PartialEq=true) +parcelable SignedPubKey { + /* Data is CBOR-encoded according to the `SignedPubKey` CDDL definition in SignedPubKey.cddl */ + byte[] signedPubKey; +} diff --git a/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.cddl b/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.cddl new file mode 100644 index 0000000000..f23a492e8b --- /dev/null +++ b/security/authgraph/aidl/android/hardware/security/authgraph/SignedPubKey.cddl @@ -0,0 +1,41 @@ +; +; 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. +; +SignedPubKey = [ ; COSE_Sign1 (untagged) [RFC9052 s4.2] + protected: bstr .cbor SignedPubKeyProtected, + unprotected: {}, + payload: bstr .cbor PlainPubKey, + signature: bstr ; PureEd25519(privateKey, SignedPubKeySigStruct) / + ; ECDSA(privateKey, SignedPubKeySigStruct) +] + +SignedPubKeyProtected = { + 1 : AlgorithmEdDSA / AlgorithmES256, + ? -70011 : Identity, ; the party who performs the signing operation adds its own + ; identity to the protected headers. +} + +SignedPubKeySigStruct = [ ; Sig_structure for SignedPubKey [ RFC9052 s4.4] + context: "Signature1", + protected: bstr SignedPubKeyProtected, + external_aad: bstr .size 0, + payload: bstr .cbor PlainPubKey, +] + +AlgorithmES256 = -7 ; [RFC9053 s2.1] +AlgorithmEdDSA = -8 ; [RFC9053 s2.2] + +; INCLUDE PlainPubKey.cddl for: PlainPubKey +; INCLUDE Identity.cddl for: Identity \ No newline at end of file diff --git a/security/authgraph/aidl/vts/functional/Android.bp b/security/authgraph/aidl/vts/functional/Android.bp new file mode 100644 index 0000000000..fc13759021 --- /dev/null +++ b/security/authgraph/aidl/vts/functional/Android.bp @@ -0,0 +1,48 @@ +// +// 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_test { + name: "VtsAidlAuthGraphSessionTest", + defaults: [ + "VtsHalTargetTestDefaults", + "authgraph_use_latest_hal_aidl_ndk_static", + "use_libaidlvintf_gtest_helper_static", + ], + cflags: [ + "-Wall", + "-Wextra", + ], + srcs: [ + "AuthGraphSessionTest.cpp", + ], + shared_libs: [ + "libbinder_ndk", + "libcrypto", + ], + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/security/authgraph/aidl/vts/functional/AuthGraphSessionTest.cpp b/security/authgraph/aidl/vts/functional/AuthGraphSessionTest.cpp new file mode 100644 index 0000000000..d9dea7735a --- /dev/null +++ b/security/authgraph/aidl/vts/functional/AuthGraphSessionTest.cpp @@ -0,0 +1,375 @@ +/* + * 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. + */ +#define LOG_TAG "authgraph_session_test" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace aidl::android::hardware::security::authgraph::test { +using ::aidl::android::hardware::security::authgraph::Error; + +namespace { + +// Check that the signature in the encoded COSE_Sign1 data is correct, and that the payload matches. +// TODO: maybe drop separate payload, and extract it from cose_sign1.payload (and return it). +void CheckSignature(std::vector& /*pub_cose_key*/, std::vector& /*payload*/, + std::vector& /*cose_sign1*/) { + // TODO: implement me +} + +void CheckSignature(std::vector& pub_cose_key, std::vector& payload, + SessionIdSignature& signature) { + return CheckSignature(pub_cose_key, payload, signature.signature); +} + +std::vector SigningKeyFromIdentity(const Identity& identity) { + // TODO: This is a CBOR-encoded `Identity` which currently happens to be a COSE_Key with the + // pubkey This will change in future. + return identity.identity; +} + +} // namespace + +class AuthGraphSessionTest : public ::testing::TestWithParam { + public: + enum ErrorType { AIDL_ERROR, BINDER_ERROR }; + + union ErrorValue { + Error aidl_error; + int32_t binder_error; + }; + + struct ReturnedError { + ErrorType err_type; + ErrorValue err_val; + + friend bool operator==(const ReturnedError& lhs, const ReturnedError& rhs) { + return lhs.err_type == rhs.err_type; + switch (lhs.err_type) { + case ErrorType::AIDL_ERROR: + return lhs.err_val.aidl_error == rhs.err_val.aidl_error; + case ErrorType::BINDER_ERROR: + return lhs.err_val.binder_error == rhs.err_val.binder_error; + } + } + }; + + const ReturnedError OK = {.err_type = ErrorType::AIDL_ERROR, .err_val.aidl_error = Error::OK}; + + ReturnedError GetReturnError(const ::ndk::ScopedAStatus& result) { + if (result.isOk()) { + return OK; + } + int32_t exception_code = result.getExceptionCode(); + int32_t error_code = result.getServiceSpecificError(); + if (exception_code == EX_SERVICE_SPECIFIC && error_code != 0) { + ReturnedError re = {.err_type = ErrorType::AIDL_ERROR, + .err_val.aidl_error = static_cast(error_code)}; + return re; + } + ReturnedError re = {.err_type = ErrorType::BINDER_ERROR, + .err_val.binder_error = exception_code}; + return re; + } + + // Build the parameters for the VTS test by enumerating the available HAL instances + static std::vector build_params() { + auto params = ::android::getAidlHalInstanceNames(IAuthGraphKeyExchange::descriptor); + return params; + } + + void SetUp() override { + ASSERT_TRUE(AServiceManager_isDeclared(GetParam().c_str())) + << "No instance declared for " << GetParam(); + ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str())); + authNode_ = IAuthGraphKeyExchange::fromBinder(binder); + ASSERT_NE(authNode_, nullptr) << "Failed to get Binder reference for " << GetParam(); + } + + void TearDown() override {} + + protected: + std::shared_ptr authNode_; +}; + +TEST_P(AuthGraphSessionTest, Mainline) { + std::shared_ptr source = authNode_; + std::shared_ptr sink = authNode_; + + // Step 1: create an ephemeral ECDH key at the source. + SessionInitiationInfo source_init_info; + ASSERT_EQ(OK, GetReturnError(source->create(&source_init_info))); + ASSERT_TRUE(source_init_info.key.pubKey.has_value()); + ASSERT_TRUE(source_init_info.key.arcFromPBK.has_value()); + + // Step 2: pass the source's ECDH public key and other session info to the sink. + KeInitResult init_result; + ASSERT_EQ(OK, GetReturnError(sink->init(source_init_info.key.pubKey.value(), + source_init_info.identity, source_init_info.nonce, + source_init_info.version, &init_result))); + SessionInitiationInfo sink_init_info = init_result.sessionInitiationInfo; + ASSERT_TRUE(sink_init_info.key.pubKey.has_value()); + // The sink_init_info.arcFromPBK need not be populated, as the ephemeral key agreement + // key is no longer needed. + + SessionInfo sink_info = init_result.sessionInfo; + ASSERT_EQ((int)sink_info.sharedKeys.size(), 2) << "Expect two symmetric keys from init()"; + ASSERT_GT((int)sink_info.sessionId.size(), 0) << "Expect non-empty session ID from sink"; + std::vector sink_signing_key = SigningKeyFromIdentity(sink_init_info.identity); + CheckSignature(sink_signing_key, sink_info.sessionId, sink_info.signature); + + // Step 3: pass the sink's ECDH public key and other session info to the source, so it can + // calculate the same pair of symmetric keys. + SessionInfo source_info; + ASSERT_EQ(OK, GetReturnError(source->finish(sink_init_info.key.pubKey.value(), + sink_init_info.identity, sink_info.signature, + sink_init_info.nonce, sink_init_info.version, + source_init_info.key, &source_info))); + ASSERT_EQ((int)source_info.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()"; + ASSERT_GT((int)source_info.sessionId.size(), 0) << "Expect non-empty session ID from source"; + std::vector source_signing_key = SigningKeyFromIdentity(source_init_info.identity); + CheckSignature(source_signing_key, source_info.sessionId, source_info.signature); + + // Both ends should agree on the session ID. + ASSERT_EQ(source_info.sessionId, sink_info.sessionId); + + // Step 4: pass the source's session ID info back to the sink, so it can check it and + // update the symmetric keys so they're marked as authentication complete. + std::array auth_complete_result; + ASSERT_EQ(OK, GetReturnError(sink->authenticationComplete( + source_info.signature, sink_info.sharedKeys, &auth_complete_result))); + ASSERT_EQ((int)auth_complete_result.size(), 2) + << "Expect two symmetric keys from authComplete()"; + sink_info.sharedKeys = auth_complete_result; + + // At this point the sink and source have agreed on the same pair of symmetric keys, + // encoded as `sink_info.sharedKeys` and `source_info.sharedKeys`. +} + +TEST_P(AuthGraphSessionTest, ParallelSink) { + std::shared_ptr source = authNode_; + std::shared_ptr sink1 = authNode_; + std::shared_ptr sink2 = authNode_; + + // Step 1: create ephemeral ECDH keys at the source. + SessionInitiationInfo source_init1_info; + ASSERT_EQ(OK, GetReturnError(source->create(&source_init1_info))); + ASSERT_TRUE(source_init1_info.key.pubKey.has_value()); + ASSERT_TRUE(source_init1_info.key.arcFromPBK.has_value()); + SessionInitiationInfo source_init2_info; + ASSERT_EQ(OK, GetReturnError(source->create(&source_init2_info))); + ASSERT_TRUE(source_init2_info.key.pubKey.has_value()); + ASSERT_TRUE(source_init2_info.key.arcFromPBK.has_value()); + + // Step 2: pass the source's ECDH public keys and other session info to the sinks. + KeInitResult init1_result; + ASSERT_EQ(OK, GetReturnError(sink1->init(source_init1_info.key.pubKey.value(), + source_init1_info.identity, source_init1_info.nonce, + source_init1_info.version, &init1_result))); + SessionInitiationInfo sink1_init_info = init1_result.sessionInitiationInfo; + ASSERT_TRUE(sink1_init_info.key.pubKey.has_value()); + + SessionInfo sink1_info = init1_result.sessionInfo; + ASSERT_EQ((int)sink1_info.sharedKeys.size(), 2) << "Expect two symmetric keys from init()"; + ASSERT_GT((int)sink1_info.sessionId.size(), 0) << "Expect non-empty session ID from sink"; + std::vector sink1_signing_key = SigningKeyFromIdentity(sink1_init_info.identity); + CheckSignature(sink1_signing_key, sink1_info.sessionId, sink1_info.signature); + KeInitResult init2_result; + ASSERT_EQ(OK, GetReturnError(sink2->init(source_init2_info.key.pubKey.value(), + source_init2_info.identity, source_init2_info.nonce, + source_init2_info.version, &init2_result))); + SessionInitiationInfo sink2_init_info = init2_result.sessionInitiationInfo; + ASSERT_TRUE(sink2_init_info.key.pubKey.has_value()); + + SessionInfo sink2_info = init2_result.sessionInfo; + ASSERT_EQ((int)sink2_info.sharedKeys.size(), 2) << "Expect two symmetric keys from init()"; + ASSERT_GT((int)sink2_info.sessionId.size(), 0) << "Expect non-empty session ID from sink"; + std::vector sink2_signing_key = SigningKeyFromIdentity(sink2_init_info.identity); + CheckSignature(sink2_signing_key, sink2_info.sessionId, sink2_info.signature); + + // Step 3: pass each sink's ECDH public key and other session info to the source, so it can + // calculate the same pair of symmetric keys. + SessionInfo source_info1; + ASSERT_EQ(OK, GetReturnError(source->finish(sink1_init_info.key.pubKey.value(), + sink1_init_info.identity, sink1_info.signature, + sink1_init_info.nonce, sink1_init_info.version, + source_init1_info.key, &source_info1))); + ASSERT_EQ((int)source_info1.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()"; + ASSERT_GT((int)source_info1.sessionId.size(), 0) << "Expect non-empty session ID from source"; + std::vector source_signing_key1 = SigningKeyFromIdentity(source_init1_info.identity); + CheckSignature(source_signing_key1, source_info1.sessionId, source_info1.signature); + SessionInfo source_info2; + ASSERT_EQ(OK, GetReturnError(source->finish(sink2_init_info.key.pubKey.value(), + sink2_init_info.identity, sink2_info.signature, + sink2_init_info.nonce, sink2_init_info.version, + source_init2_info.key, &source_info2))); + ASSERT_EQ((int)source_info2.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()"; + ASSERT_GT((int)source_info2.sessionId.size(), 0) << "Expect non-empty session ID from source"; + std::vector source_signing_key2 = SigningKeyFromIdentity(source_init2_info.identity); + CheckSignature(source_signing_key2, source_info2.sessionId, source_info2.signature); + + // Both ends should agree on the session ID. + ASSERT_EQ(source_info1.sessionId, sink1_info.sessionId); + ASSERT_EQ(source_info2.sessionId, sink2_info.sessionId); + + // Step 4: pass the source's session ID info back to the sink, so it can check it and + // update the symmetric keys so they're marked as authentication complete. + std::array auth_complete_result1; + ASSERT_EQ(OK, GetReturnError(sink1->authenticationComplete( + source_info1.signature, sink1_info.sharedKeys, &auth_complete_result1))); + ASSERT_EQ((int)auth_complete_result1.size(), 2) + << "Expect two symmetric keys from authComplete()"; + sink1_info.sharedKeys = auth_complete_result1; + std::array auth_complete_result2; + ASSERT_EQ(OK, GetReturnError(sink2->authenticationComplete( + source_info2.signature, sink2_info.sharedKeys, &auth_complete_result2))); + ASSERT_EQ((int)auth_complete_result2.size(), 2) + << "Expect two symmetric keys from authComplete()"; + sink2_info.sharedKeys = auth_complete_result2; +} + +TEST_P(AuthGraphSessionTest, ParallelSource) { + std::shared_ptr source1 = authNode_; + std::shared_ptr source2 = authNode_; + std::shared_ptr sink = authNode_; + + // Step 1: create an ephemeral ECDH key at each of the sources. + SessionInitiationInfo source1_init_info; + ASSERT_EQ(OK, GetReturnError(source1->create(&source1_init_info))); + ASSERT_TRUE(source1_init_info.key.pubKey.has_value()); + ASSERT_TRUE(source1_init_info.key.arcFromPBK.has_value()); + SessionInitiationInfo source2_init_info; + ASSERT_EQ(OK, GetReturnError(source1->create(&source2_init_info))); + ASSERT_TRUE(source2_init_info.key.pubKey.has_value()); + ASSERT_TRUE(source2_init_info.key.arcFromPBK.has_value()); + + // Step 2: pass each source's ECDH public key and other session info to the sink. + KeInitResult init1_result; + ASSERT_EQ(OK, GetReturnError(sink->init(source1_init_info.key.pubKey.value(), + source1_init_info.identity, source1_init_info.nonce, + source1_init_info.version, &init1_result))); + SessionInitiationInfo sink_init1_info = init1_result.sessionInitiationInfo; + ASSERT_TRUE(sink_init1_info.key.pubKey.has_value()); + + SessionInfo sink_info1 = init1_result.sessionInfo; + ASSERT_EQ((int)sink_info1.sharedKeys.size(), 2) << "Expect two symmetric keys from init()"; + ASSERT_GT((int)sink_info1.sessionId.size(), 0) << "Expect non-empty session ID from sink"; + std::vector sink_signing_key1 = SigningKeyFromIdentity(sink_init1_info.identity); + CheckSignature(sink_signing_key1, sink_info1.sessionId, sink_info1.signature); + + KeInitResult init2_result; + ASSERT_EQ(OK, GetReturnError(sink->init(source2_init_info.key.pubKey.value(), + source2_init_info.identity, source2_init_info.nonce, + source2_init_info.version, &init2_result))); + SessionInitiationInfo sink_init2_info = init2_result.sessionInitiationInfo; + ASSERT_TRUE(sink_init2_info.key.pubKey.has_value()); + + SessionInfo sink_info2 = init2_result.sessionInfo; + ASSERT_EQ((int)sink_info2.sharedKeys.size(), 2) << "Expect two symmetric keys from init()"; + ASSERT_GT((int)sink_info2.sessionId.size(), 0) << "Expect non-empty session ID from sink"; + std::vector sink_signing_key2 = SigningKeyFromIdentity(sink_init2_info.identity); + CheckSignature(sink_signing_key2, sink_info2.sessionId, sink_info2.signature); + + // Step 3: pass the sink's ECDH public keys and other session info to the each of the sources. + SessionInfo source1_info; + ASSERT_EQ(OK, GetReturnError(source1->finish(sink_init1_info.key.pubKey.value(), + sink_init1_info.identity, sink_info1.signature, + sink_init1_info.nonce, sink_init1_info.version, + source1_init_info.key, &source1_info))); + ASSERT_EQ((int)source1_info.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()"; + ASSERT_GT((int)source1_info.sessionId.size(), 0) << "Expect non-empty session ID from source"; + std::vector source1_signing_key = SigningKeyFromIdentity(source1_init_info.identity); + CheckSignature(source1_signing_key, source1_info.sessionId, source1_info.signature); + + SessionInfo source2_info; + ASSERT_EQ(OK, GetReturnError(source2->finish(sink_init2_info.key.pubKey.value(), + sink_init2_info.identity, sink_info2.signature, + sink_init2_info.nonce, sink_init2_info.version, + source2_init_info.key, &source2_info))); + ASSERT_EQ((int)source2_info.sharedKeys.size(), 2) << "Expect two symmetric keys from finsh()"; + ASSERT_GT((int)source2_info.sessionId.size(), 0) << "Expect non-empty session ID from source"; + std::vector source2_signing_key = SigningKeyFromIdentity(source2_init_info.identity); + CheckSignature(source2_signing_key, source2_info.sessionId, source2_info.signature); + + // Both ends should agree on the session ID. + ASSERT_EQ(source1_info.sessionId, sink_info1.sessionId); + ASSERT_EQ(source2_info.sessionId, sink_info2.sessionId); + + // Step 4: pass the each source's session ID info back to the sink, so it can check it and + // update the symmetric keys so they're marked as authentication complete. + std::array auth_complete_result1; + ASSERT_EQ(OK, GetReturnError(sink->authenticationComplete( + source1_info.signature, sink_info1.sharedKeys, &auth_complete_result1))); + ASSERT_EQ((int)auth_complete_result1.size(), 2) + << "Expect two symmetric keys from authComplete()"; + sink_info1.sharedKeys = auth_complete_result1; + std::array auth_complete_result2; + ASSERT_EQ(OK, GetReturnError(sink->authenticationComplete( + source2_info.signature, sink_info2.sharedKeys, &auth_complete_result2))); + ASSERT_EQ((int)auth_complete_result2.size(), 2) + << "Expect two symmetric keys from authComplete()"; + sink_info2.sharedKeys = auth_complete_result2; +} + +TEST_P(AuthGraphSessionTest, FreshNonces) { + std::shared_ptr source = authNode_; + std::shared_ptr sink = authNode_; + + SessionInitiationInfo source_init_info1; + ASSERT_EQ(OK, GetReturnError(source->create(&source_init_info1))); + SessionInitiationInfo source_init_info2; + ASSERT_EQ(OK, GetReturnError(source->create(&source_init_info2))); + + // Two calls to create() should result in the same identity but different nonce values. + ASSERT_EQ(source_init_info1.identity, source_init_info2.identity); + ASSERT_NE(source_init_info1.nonce, source_init_info2.nonce); + ASSERT_NE(source_init_info1.key.pubKey, source_init_info2.key.pubKey); + ASSERT_NE(source_init_info1.key.arcFromPBK, source_init_info2.key.arcFromPBK); + + KeInitResult init_result1; + ASSERT_EQ(OK, GetReturnError(sink->init(source_init_info1.key.pubKey.value(), + source_init_info1.identity, source_init_info1.nonce, + source_init_info1.version, &init_result1))); + KeInitResult init_result2; + ASSERT_EQ(OK, GetReturnError(sink->init(source_init_info2.key.pubKey.value(), + source_init_info2.identity, source_init_info2.nonce, + source_init_info2.version, &init_result2))); + + // Two calls to init() should result in the same identity buf different nonces and session IDs. + ASSERT_EQ(init_result1.sessionInitiationInfo.identity, + init_result2.sessionInitiationInfo.identity); + ASSERT_NE(init_result1.sessionInitiationInfo.nonce, init_result2.sessionInitiationInfo.nonce); + ASSERT_NE(init_result1.sessionInfo.sessionId, init_result2.sessionInfo.sessionId); +} + +INSTANTIATE_TEST_SUITE_P(PerInstance, AuthGraphSessionTest, + testing::ValuesIn(AuthGraphSessionTest::build_params()), + ::android::PrintInstanceNameToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AuthGraphSessionTest); + +} // namespace aidl::android::hardware::security::authgraph::test + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/security/authgraph/default/Android.bp b/security/authgraph/default/Android.bp new file mode 100644 index 0000000000..9de3bc11da --- /dev/null +++ b/security/authgraph/default/Android.bp @@ -0,0 +1,46 @@ +// +// 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +rust_binary { + name: "android.hardware.security.authgraph-service.nonsecure", + relative_install_path: "hw", + vendor: true, + init_rc: ["authgraph.rc"], + vintf_fragments: ["authgraph.xml"], + defaults: [ + "authgraph_use_latest_hal_aidl_rust", + ], + rustlibs: [ + "libandroid_logger", + "libauthgraph_core", + "libauthgraph_boringssl", + "libauthgraph_hal", + "libbinder_rs", + "liblibc", + "liblog_rust", + ], + srcs: [ + "src/main.rs", + ], +} diff --git a/security/authgraph/default/authgraph.rc b/security/authgraph/default/authgraph.rc new file mode 100644 index 0000000000..022299404a --- /dev/null +++ b/security/authgraph/default/authgraph.rc @@ -0,0 +1,5 @@ +service vendor.authgraph /vendor/bin/hw/android.hardware.security.authgraph-service.nonsecure + interface aidl android.hardware.security.authgraph.IAuthGraph/nonsecure + class hal + user nobody + group nobody diff --git a/security/authgraph/default/authgraph.xml b/security/authgraph/default/authgraph.xml new file mode 100644 index 0000000000..9529a0afe5 --- /dev/null +++ b/security/authgraph/default/authgraph.xml @@ -0,0 +1,10 @@ + + + android.hardware.security.authgraph + 1 + + IAuthGraphKeyExchange + nonsecure + + + diff --git a/security/authgraph/default/src/main.rs b/security/authgraph/default/src/main.rs new file mode 100644 index 0000000000..2112e58176 --- /dev/null +++ b/security/authgraph/default/src/main.rs @@ -0,0 +1,227 @@ +/* + * 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. + */ + +//! Default implementation of the AuthGraph key exchange HAL. +//! +//! This implementation of the HAL is only intended to allow testing and policy compliance. A real +//! implementation of the AuthGraph HAL would be implemented in a secure environment, and would not +//! be independently registered with service manager (a secure component that uses AuthGraph would +//! expose an entrypoint that allowed retrieval of the specific IAuthGraphKeyExchange instance that +//! is correlated with the component). + +use android_hardware_security_authgraph::aidl::android::hardware::security::authgraph::{ + Arc::Arc, IAuthGraphKeyExchange::BnAuthGraphKeyExchange, + IAuthGraphKeyExchange::IAuthGraphKeyExchange, Identity::Identity, KeInitResult::KeInitResult, + Key::Key, PubKey::PubKey, SessionIdSignature::SessionIdSignature, SessionInfo::SessionInfo, + SessionInitiationInfo::SessionInitiationInfo, +}; +use authgraph_boringssl as boring; +use authgraph_core::{key::MillisecondsSinceEpoch, keyexchange as ke, traits}; +use authgraph_hal::{err_to_binder, Innto, TryInnto}; +use log::{error, info}; +use std::ffi::CString; +use std::sync::Mutex; + +static SERVICE_NAME: &str = "android.hardware.security.authgraph.IAuthGraphKeyExchange"; +static SERVICE_INSTANCE: &str = "nonsecure"; + +/// Local error type for failures in the HAL service. +#[derive(Debug, Clone)] +struct HalServiceError(String); + +impl From for HalServiceError { + fn from(s: String) -> Self { + Self(s) + } +} + +fn main() { + if let Err(e) = inner_main() { + panic!("HAL service failed: {:?}", e); + } +} + +fn inner_main() -> Result<(), HalServiceError> { + // Initialize Android logging. + android_logger::init_once( + android_logger::Config::default() + .with_tag("authgraph-hal-nonsecure") + .with_min_level(log::Level::Info) + .with_log_id(android_logger::LogId::System), + ); + // Redirect panic messages to logcat. + std::panic::set_hook(Box::new(|panic_info| { + error!("{}", panic_info); + })); + + info!("Insecure AuthGraph key exchange HAL service is starting."); + + info!("Starting thread pool now."); + binder::ProcessState::start_thread_pool(); + + // Register the service + let service = AuthGraphService::new_as_binder(); + let service_name = format!("{}/{}", SERVICE_NAME, SERVICE_INSTANCE); + binder::add_service(&service_name, service.as_binder()).map_err(|e| { + format!( + "Failed to register service {} because of {:?}.", + service_name, e + ) + })?; + + info!("Successfully registered AuthGraph HAL services."); + binder::ProcessState::join_thread_pool(); + info!("AuthGraph HAL service is terminating."); // should not reach here + Ok(()) +} + +/// Non-secure implementation of the AuthGraph key exchange service. +struct AuthGraphService { + imp: Mutex, +} + +impl AuthGraphService { + /// Create a new instance. + fn new() -> Self { + Self { + imp: Mutex::new(traits::TraitImpl { + aes_gcm: Box::new(boring::BoringAes), + ecdh: Box::new(boring::BoringEcDh), + ecdsa: Box::new(boring::BoringEcDsa), + hmac: Box::new(boring::BoringHmac), + hkdf: Box::new(boring::BoringHkdf), + sha256: Box::new(boring::BoringSha256), + rng: Box::new(boring::BoringRng), + device: Box::::default(), + clock: Some(Box::new(StdClock)), + }), + } + } + + /// Create a new instance wrapped in a proxy object. + pub fn new_as_binder() -> binder::Strong { + BnAuthGraphKeyExchange::new_binder(Self::new(), binder::BinderFeatures::default()) + } +} + +impl binder::Interface for AuthGraphService {} + +/// Extract (and require) an unsigned public key as bytes from a [`PubKey`]. +fn unsigned_pub_key(pub_key: &PubKey) -> binder::Result<&[u8]> { + match pub_key { + PubKey::PlainKey(key) => Ok(&key.plainPubKey), + PubKey::SignedKey(_) => Err(binder::Status::new_exception( + binder::ExceptionCode::ILLEGAL_ARGUMENT, + Some(&CString::new("expected unsigned public key").unwrap()), + )), + } +} + +/// This nonsecure implementation of the AuthGraph HAL interface directly calls the AuthGraph +/// reference implementation library code; a real implementation requires the AuthGraph +/// code to run in a secure environment, not within Android. +impl IAuthGraphKeyExchange for AuthGraphService { + fn create(&self) -> binder::Result { + info!("create()"); + let mut imp = self.imp.lock().unwrap(); + let info = ke::create(&mut *imp).map_err(err_to_binder)?; + Ok(info.innto()) + } + fn init( + &self, + peer_pub_key: &PubKey, + peer_id: &Identity, + peer_nonce: &[u8], + peer_version: i32, + ) -> binder::Result { + info!("init(v={peer_version})"); + let mut imp = self.imp.lock().unwrap(); + let peer_pub_key = unsigned_pub_key(peer_pub_key)?; + let result = ke::init( + &mut *imp, + peer_pub_key, + &peer_id.identity, + &peer_nonce, + peer_version, + ) + .map_err(err_to_binder)?; + Ok(result.innto()) + } + + fn finish( + &self, + peer_pub_key: &PubKey, + peer_id: &Identity, + peer_signature: &SessionIdSignature, + peer_nonce: &[u8], + peer_version: i32, + own_key: &Key, + ) -> binder::Result { + info!("finish(v={peer_version})"); + let mut imp = self.imp.lock().unwrap(); + let peer_pub_key = unsigned_pub_key(peer_pub_key)?; + let own_key: Key = own_key.clone(); + let own_key: authgraph_core::key::Key = own_key.try_innto()?; + let session_info = ke::finish( + &mut *imp, + peer_pub_key, + &peer_id.identity, + &peer_signature.signature, + &peer_nonce, + peer_version, + own_key, + ) + .map_err(err_to_binder)?; + Ok(session_info.innto()) + } + + fn authenticationComplete( + &self, + peer_signature: &SessionIdSignature, + shared_keys: &[Arc; 2], + ) -> binder::Result<[Arc; 2]> { + info!("authComplete()"); + let mut imp = self.imp.lock().unwrap(); + let shared_keys = [shared_keys[0].arc.clone(), shared_keys[1].arc.clone()]; + let arcs = ke::authentication_complete(&mut *imp, &peer_signature.signature, shared_keys) + .map_err(err_to_binder)?; + Ok(arcs.map(|arc| Arc { arc })) + } +} + +/// Monotonic clock. +#[derive(Default)] +pub struct StdClock; + +impl traits::MonotonicClock for StdClock { + fn now(&self) -> authgraph_core::key::MillisecondsSinceEpoch { + let mut time = libc::timespec { + tv_sec: 0, // libc::time_t + tv_nsec: 0, // libc::c_long + }; + let rc = + // Safety: `time` is a valid structure. + unsafe { libc::clock_gettime(libc::CLOCK_BOOTTIME, &mut time as *mut libc::timespec) }; + if rc < 0 { + log::warn!("failed to get time!"); + return MillisecondsSinceEpoch(0); + } + // The types in `libc::timespec` may be different on different architectures, + // so allow conversion to `i64`. + #[allow(clippy::unnecessary_cast)] + MillisecondsSinceEpoch((time.tv_sec as i64 * 1000) + (time.tv_nsec as i64 / 1000 / 1000)) + } +}