summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-03-04 22:13:27 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-03-04 22:13:27 +0000
commit706c20dce4715fd7e7ca506245cbb5a012060492 (patch)
treea1bed122b76f0b5ba43215a0fc9afc8975e3f92d
parent0b7d54e4b210ce1d86a85410b2db000da494f5c8 (diff)
parent1e5b402b24805c2d30336d7269ae8dd9df5d778e (diff)
downloadRemoteKeyProvisioning-706c20dce4715fd7e7ca506245cbb5a012060492.tar.gz
Snap for 11526323 from 1e5b402b24805c2d30336d7269ae8dd9df5d778e to simpleperf-releasesimpleperf-release
Change-Id: I54975de51bcab56c6ed8ffa1aec233a3dc622958
-rw-r--r--app/TEST_MAPPING7
-rw-r--r--app/tests/avf/Android.bp29
-rw-r--r--app/tests/avf/AndroidManifest.xml26
-rw-r--r--app/tests/avf/AndroidTest.xml36
-rw-r--r--app/tests/avf/src/com/android/avf/rkpdapp/e2etest/AvfIntegrationTest.java142
5 files changed, 240 insertions, 0 deletions
diff --git a/app/TEST_MAPPING b/app/TEST_MAPPING
index 824fc9e..af4013a 100644
--- a/app/TEST_MAPPING
+++ b/app/TEST_MAPPING
@@ -15,6 +15,13 @@
"keywords": ["internal"]
}
],
+ "avf-postsubmit": [
+ {
+ // TODO(b/325610326): Add this target to presubmit once there is enough
+ // SLO data for it.
+ "name": "AvfRkpdAppIntegrationTests"
+ }
+ ],
"mainline-presubmit": [
{
"name": "RkpdAppGoogleUnitTests[com.google.android.rkpd.apex]"
diff --git a/app/tests/avf/Android.bp b/app/tests/avf/Android.bp
new file mode 100644
index 0000000..b32eed3
--- /dev/null
+++ b/app/tests/avf/Android.bp
@@ -0,0 +1,29 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "AvfRkpdAppIntegrationTests",
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "MicrodroidDeviceTestHelper",
+ "Nene",
+ "RkpdAppTestUtil",
+ "androidx.test.ext.junit",
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.work_work-testing",
+ "compatibility-common-util-devicesidelib",
+ "platform-test-annotations",
+ "truth",
+ ],
+ platform_apis: true,
+ test_suites: [
+ "general-tests",
+ "device-tests",
+ "mcts-rkpd",
+ "mts-rkpd",
+ ],
+ min_sdk_version: "33",
+ instrumentation_for: "rkpdapp",
+}
diff --git a/app/tests/avf/AndroidManifest.xml b/app/tests/avf/AndroidManifest.xml
new file mode 100644
index 0000000..0924ded
--- /dev/null
+++ b/app/tests/avf/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.avf.rkpdapp.e2etest">
+
+ <application />
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.rkpdapp"
+ android:label="AVF rkpd app integration tests" />
+</manifest>
diff --git a/app/tests/avf/AndroidTest.xml b/app/tests/avf/AndroidTest.xml
new file mode 100644
index 0000000..e57ca1d
--- /dev/null
+++ b/app/tests/avf/AndroidTest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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.
+-->
+<configuration description="AVF integration tests for the rkpd app.">
+ <option name="test-suite-tag" value="cts" />
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="AvfRkpdAppIntegrationTests.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.avf.rkpdapp.e2etest" />
+ </test>
+
+ <!-- Only run if RKPD mainline module is installed -->
+ <object type="module_controller"
+ class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+ <option name="enable" value="true" />
+ <option name="mainline-module-package-name" value="com.android.rkpd" />
+ </object>
+</configuration>
diff --git a/app/tests/avf/src/com/android/avf/rkpdapp/e2etest/AvfIntegrationTest.java b/app/tests/avf/src/com/android/avf/rkpdapp/e2etest/AvfIntegrationTest.java
new file mode 100644
index 0000000..46386a5
--- /dev/null
+++ b/app/tests/avf/src/com/android/avf/rkpdapp/e2etest/AvfIntegrationTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2024 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 com.android.avf.rkpdapp.e2etest;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+import static com.google.common.truth.TruthJUnit.assume;
+
+import android.hardware.security.keymint.IRemotelyProvisionedComponent;
+import android.os.Process;
+import android.os.SystemProperties;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.work.ListenableWorker;
+import androidx.work.testing.TestWorkerBuilder;
+
+import com.android.compatibility.common.util.CddTest;
+import com.android.microdroid.test.device.MicrodroidDeviceTestBase;
+import com.android.rkpdapp.database.ProvisionedKey;
+import com.android.rkpdapp.database.ProvisionedKeyDao;
+import com.android.rkpdapp.database.RkpdDatabase;
+import com.android.rkpdapp.interfaces.ServerInterface;
+import com.android.rkpdapp.interfaces.ServiceManagerInterface;
+import com.android.rkpdapp.interfaces.SystemInterface;
+import com.android.rkpdapp.provisioner.PeriodicProvisioner;
+import com.android.rkpdapp.testutil.SystemInterfaceSelector;
+import com.android.rkpdapp.utils.Settings;
+import com.android.rkpdapp.utils.X509Utils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.security.cert.X509Certificate;
+import java.time.Instant;
+import java.util.concurrent.Executors;
+
+/**
+ * End-to-end test for the pVM remote attestation (key provisioning/VM attestation).
+ *
+ * <p>To run this test, you need to:
+ *
+ * - Have an arm64 device supporting protected VMs.
+ * - Have a stable network connection on the device.
+ * - Have the RKP server hostname configured in the device. If not, you can set it using:
+ * $ adb shell setprop remote_provisioning.hostname remoteprovisioning.googleapis.com
+ */
+@RunWith(AndroidJUnit4.class)
+public class AvfIntegrationTest extends MicrodroidDeviceTestBase {
+ private static final String SERVICE_NAME = IRemotelyProvisionedComponent.DESCRIPTOR + "/avf";
+
+ private ProvisionedKeyDao mKeyDao;
+ private PeriodicProvisioner mProvisioner;
+
+ @Before
+ public void setUp() throws Exception {
+ assume().withMessage("AVF key provisioning is not supported on CF.")
+ .that(isCuttlefish())
+ .isFalse();
+ assume().withMessage("The RKP server hostname is not configured -- assume RKP disabled.")
+ .that(SystemProperties.get("remote_provisioning.hostname"))
+ .isNotEmpty();
+ assume().withMessage("RKP Integration tests rely on network availability.")
+ .that(ServerInterface.isNetworkConnected(getContext()))
+ .isTrue();
+
+ Settings.clearPreferences(getContext());
+ mKeyDao = RkpdDatabase.getDatabase(getContext()).provisionedKeyDao();
+ mKeyDao.deleteAllKeys();
+
+ mProvisioner =
+ TestWorkerBuilder.from(
+ getContext(),
+ PeriodicProvisioner.class,
+ Executors.newSingleThreadExecutor())
+ .build();
+
+ SystemInterface systemInterface =
+ SystemInterfaceSelector.getSystemInterfaceForServiceName(SERVICE_NAME);
+ ServiceManagerInterface.setInstances(new SystemInterface[] {systemInterface});
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ ServiceManagerInterface.setInstances(null);
+ if (mKeyDao != null) {
+ mKeyDao.deleteAllKeys();
+ }
+ Settings.clearPreferences(getContext());
+ }
+
+ @Test
+ @CddTest(requirements = {"9.17/C-1-1", "9.17/C-2-1"})
+ public void provisioningSucceeds() throws Exception {
+ assertWithMessage("There should be no keys in the database before provisioning")
+ .that(mKeyDao.getTotalKeysForIrpc(SERVICE_NAME))
+ .isEqualTo(0);
+
+ // Check provisioning succeeds.
+ assertThat(mProvisioner.doWork()).isEqualTo(ListenableWorker.Result.success());
+ int totalUnassignedKeys = mKeyDao.getTotalUnassignedKeysForIrpc(SERVICE_NAME);
+ assertWithMessage("There should be unassigned keys in the database after provisioning")
+ .that(totalUnassignedKeys)
+ .isGreaterThan(0);
+
+ ProvisionedKey attestationKey =
+ mKeyDao.getKeyForClientAndIrpc(SERVICE_NAME, Process.SYSTEM_UID, Process.myUid());
+ assertThat(attestationKey).isNull();
+ // Assign a key to a new client.
+ attestationKey =
+ mKeyDao.getOrAssignKey(
+ SERVICE_NAME, Instant.now(), Process.SYSTEM_UID, Process.myUid());
+
+ // Assert.
+ assertThat(attestationKey).isNotNull();
+ assertThat(attestationKey.irpcHal).isEqualTo(SERVICE_NAME);
+ assertWithMessage("One key should be assigned")
+ .that(mKeyDao.getTotalUnassignedKeysForIrpc(SERVICE_NAME))
+ .isEqualTo(totalUnassignedKeys - 1);
+
+ // Parsing the certificate chain successfully indicates that the chain is well-formed,
+ // each certificate is signed by the next one, and the root certificate is self-signed.
+ X509Certificate[] certs = X509Utils.formatX509Certs(attestationKey.certificateChain);
+ assertThat(certs.length).isGreaterThan(1);
+ assertThat(certs[0].getSubjectX500Principal().getName()).contains("O=AVF");
+ }
+}