AuthSecret HAL

A security HAL to allow vendor to cryptographically tie components to
the primary user's credential.

Test: AuthSecretHidlTest
Bug: 71527305
Change-Id: I67ebf423dfccb00415d1d79b54e3ded31256cfff
diff --git a/authsecret/1.0/Android.bp b/authsecret/1.0/Android.bp
new file mode 100644
index 0000000..9cde99a
--- /dev/null
+++ b/authsecret/1.0/Android.bp
@@ -0,0 +1,17 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.authsecret@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IAuthSecret.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
+
diff --git a/authsecret/1.0/IAuthSecret.hal b/authsecret/1.0/IAuthSecret.hal
new file mode 100644
index 0000000..d2cb5da
--- /dev/null
+++ b/authsecret/1.0/IAuthSecret.hal
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 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.authsecret@1.0;
+
+/**
+ * This security HAL allows vendor components to be cryptographically tied to
+ * the primary user's credential. For example, security hardware could require
+ * proof that the credential is known before applying updates.
+ *
+ * This HAL is optional so does not require an implementation on device.
+ */
+interface IAuthSecret {
+    /**
+     * When the primary user correctly enters their credential, this method is
+     * passed a secret derived from that credential to prove that their
+     * credential is known.
+     *
+     * The first time this is called, the secret must be used to provision state
+     * that depends on the primary user's credential. The same secret is passed
+     * on each call until a factory reset after which there must be a new
+     * secret.
+     *
+     * The secret must be at lesat 16 bytes.
+     *
+     * @param secret blob derived from the primary user's credential.
+     */
+    primaryUserCredential(vec<uint8_t> secret);
+
+    /**
+     * Called from recovery during factory reset. The secret is now lost and can
+     * no longer be derived. Any data linked to the secret must be destroyed and
+     * any dependence on the secret must be removed.
+     */
+    factoryReset();
+};
diff --git a/authsecret/1.0/default/Android.bp b/authsecret/1.0/default/Android.bp
new file mode 100644
index 0000000..5c3234f
--- /dev/null
+++ b/authsecret/1.0/default/Android.bp
@@ -0,0 +1,21 @@
+cc_binary {
+    name: "android.hardware.authsecret@1.0-service",
+    init_rc: ["android.hardware.authsecret@1.0-service.rc"],
+    relative_install_path: "hw",
+    vendor: true,
+    srcs: [
+        "service.cpp",
+        "AuthSecret.cpp",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.authsecret@1.0",
+    ],
+}
diff --git a/authsecret/1.0/default/AuthSecret.cpp b/authsecret/1.0/default/AuthSecret.cpp
new file mode 100644
index 0000000..46a3ec1
--- /dev/null
+++ b/authsecret/1.0/default/AuthSecret.cpp
@@ -0,0 +1,47 @@
+#include "AuthSecret.h"
+
+namespace android {
+namespace hardware {
+namespace authsecret {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::authsecret::V1_0::IAuthSecret follow.
+Return<void> AuthSecret::primaryUserCredential(const hidl_vec<uint8_t>& secret) {
+    (void)secret;
+
+    // To create a dependency on the credential, it is recommended to derive a
+    // different value from the provided secret for each purpose e.g.
+    //
+    //     purpose1_secret = hash( "purpose1" || secret )
+    //     purpose2_secret = hash( "purpose2" || secret )
+    //
+    // The derived values can then be used as cryptographic keys or stored
+    // securely for comparison in a future call.
+    //
+    // For example, a security module might require that the credential has been
+    // entered before it applies any updates. This can be achieved by storing a
+    // derived value in the module and only applying updates when the same
+    // derived value is presented again.
+    //
+    // This implementation does nothing.
+
+    return Void();
+}
+
+Return<void> AuthSecret::factoryReset() {
+    // Clear all dependency on the secret.
+    //
+    // With the example of updating a security module, the stored value must be
+    // cleared so that the new primary user enrolled as the approver of updates.
+    //
+    // This implementation does nothing as there is no dependence on the secret.
+
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace authsecret
+}  // namespace hardware
+}  // namespace android
diff --git a/authsecret/1.0/default/AuthSecret.h b/authsecret/1.0/default/AuthSecret.h
new file mode 100644
index 0000000..edb49b8
--- /dev/null
+++ b/authsecret/1.0/default/AuthSecret.h
@@ -0,0 +1,36 @@
+#ifndef ANDROID_HARDWARE_AUTHSECRET_V1_0_AUTHSECRET_H
+#define ANDROID_HARDWARE_AUTHSECRET_V1_0_AUTHSECRET_H
+
+#include <android/hardware/authsecret/1.0/IAuthSecret.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace authsecret {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct AuthSecret : public IAuthSecret {
+    // Methods from ::android::hardware::authsecret::V1_0::IAuthSecret follow.
+    Return<void> primaryUserCredential(const hidl_vec<uint8_t>& secret) override;
+    Return<void> factoryReset() override;
+
+    // Methods from ::android::hidl::base::V1_0::IBase follow.
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace authsecret
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUTHSECRET_V1_0_AUTHSECRET_H
diff --git a/authsecret/1.0/default/android.hardware.authsecret@1.0-service.rc b/authsecret/1.0/default/android.hardware.authsecret@1.0-service.rc
new file mode 100644
index 0000000..e82da7e
--- /dev/null
+++ b/authsecret/1.0/default/android.hardware.authsecret@1.0-service.rc
@@ -0,0 +1,4 @@
+service vendor.authsecret-1-0 /vendor/bin/hw/android.hardware.authsecret@1.0-service
+    class hal
+    user system
+    group system
diff --git a/authsecret/1.0/default/service.cpp b/authsecret/1.0/default/service.cpp
new file mode 100644
index 0000000..4acd16c
--- /dev/null
+++ b/authsecret/1.0/default/service.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.1 (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.1
+ *
+ * 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 "android.hardware.authsecret@1.0-service"
+
+#include <android/hardware/authsecret/1.0/IAuthSecret.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "AuthSecret.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::authsecret::V1_0::IAuthSecret;
+using android::hardware::authsecret::V1_0::implementation::AuthSecret;
+using android::sp;
+using android::status_t;
+using android::OK;
+
+int main() {
+    configureRpcThreadpool(1, true);
+
+    sp<IAuthSecret> authSecret = new AuthSecret;
+    status_t status = authSecret->registerAsService();
+    LOG_ALWAYS_FATAL_IF(status != OK, "Could not register IAuthSecret");
+
+    joinRpcThreadpool();
+    return 0;
+}
diff --git a/authsecret/1.0/vts/functional/Android.bp b/authsecret/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..de9f560
--- /dev/null
+++ b/authsecret/1.0/vts/functional/Android.bp
@@ -0,0 +1,22 @@
+//
+// Copyright (C) 2018 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.
+//
+
+cc_test {
+    name: "VtsHalAuthSecretV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalAuthSecretV1_0TargetTest.cpp"],
+    static_libs: ["android.hardware.authsecret@1.0"],
+}
diff --git a/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
new file mode 100644
index 0000000..b0cbd91
--- /dev/null
+++ b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include <android/hardware/authsecret/1.0/IAuthSecret.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::authsecret::V1_0::IAuthSecret;
+using ::android::sp;
+
+/**
+ * There is no expected behaviour that can be tested so these tests check the
+ * HAL doesn't crash with different execution orders.
+ */
+struct AuthSecretHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+    virtual void SetUp() override {
+        authsecret = ::testing::VtsHalHidlTargetTestBase::getService<IAuthSecret>();
+        ASSERT_NE(authsecret, nullptr);
+        authsecret->factoryReset();
+    }
+
+    sp<IAuthSecret> authsecret;
+};
+
+/* Provision the primary user with a secret. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredential) {
+    hidl_vec<uint8_t> secret{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+    authsecret->primaryUserCredential(secret);
+}
+
+/* Provision the primary user with a large secret. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialWithLargeSecret) {
+    hidl_vec<uint8_t> secret{89,  233, 52,  29,  130, 210, 229, 170, 124, 102, 56,  238, 198,
+                             199, 246, 152, 185, 123, 155, 215, 29,  252, 30,  70,  118, 29,
+                             149, 36,  222, 203, 163, 7,   72,  56,  247, 19,  198, 76,  71,
+                             37,  120, 201, 220, 70,  150, 18,  23,  22,  236, 57,  184, 86,
+                             190, 122, 210, 207, 74,  51,  222, 157, 74,  196, 86,  208};
+    authsecret->primaryUserCredential(secret);
+}
+
+/* Provision the primary user with a secret and pass the secret again. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialAndPassAgain) {
+    hidl_vec<uint8_t> secret{64, 2, 3, 0, 5, 6, 7, 172, 9, 10, 11, 255, 13, 14, 15, 83};
+    authsecret->primaryUserCredential(secret);
+    authsecret->primaryUserCredential(secret);
+}
+
+/* Provision the primary user with a secret and pass the secret again repeatedly. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialAndPassAgainMultipleTimes) {
+    hidl_vec<uint8_t> secret{1, 2, 34, 4, 5, 6, 7, 8, 9, 105, 11, 12, 13, 184, 15, 16};
+    authsecret->primaryUserCredential(secret);
+    constexpr int N = 5;
+    for (int i = 0; i < N; ++i) {
+        authsecret->primaryUserCredential(secret);
+    }
+}
+
+/* Factory reset before provisioning the primary user with a secret. */
+TEST_F(AuthSecretHidlTest, factoryResetWithoutProvisioningPrimaryUserCredential) {
+    authsecret->factoryReset();
+}
+
+/* Provision the primary user with a secret then factory reset. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialAndFactoryReset) {
+    hidl_vec<uint8_t> secret{1, 24, 124, 240, 5, 6, 7, 8, 9, 13, 11, 12, 189, 14, 195, 16};
+    authsecret->primaryUserCredential(secret);
+    authsecret->factoryReset();
+}
+
+/* Provision the primary differently after factory reset. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialDifferentlyAfterFactoryReset) {
+    {
+        hidl_vec<uint8_t> secret1{19, 0, 65, 20, 65, 12, 7, 8, 9, 13, 29, 12, 189, 32, 195, 16};
+        authsecret->primaryUserCredential(secret1);
+    }
+
+    authsecret->factoryReset();
+
+    {
+        hidl_vec<uint8_t> secret2{61, 93, 124, 240, 5, 0, 7, 201, 9, 129, 11, 12, 0, 14, 0, 16};
+        authsecret->primaryUserCredential(secret2);
+    }
+}
diff --git a/compatibility_matrix.current.xml b/compatibility_matrix.current.xml
index 9287d67..1aaef1e 100644
--- a/compatibility_matrix.current.xml
+++ b/compatibility_matrix.current.xml
@@ -16,6 +16,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.authsecret</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAuthSecret</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.automotive.evs</name>
         <version>1.0</version>
         <interface>