Merge "Minor cleanup on custom VM configs" into main
diff --git a/tests/testapk/Android.bp b/tests/testapk/Android.bp
index e32ff88..8314f43 100644
--- a/tests/testapk/Android.bp
+++ b/tests/testapk/Android.bp
@@ -57,6 +57,9 @@
"MicrodroidCrashNativeLib",
"libmicrodroid_testlib_rust",
"libvm_attestation_test_payload",
+
+ // Non-VM payload libraries
+ "libhwtrust_jni",
],
min_sdk_version: "33",
}
@@ -186,3 +189,20 @@
"libvm_payload_rs",
],
}
+
+rust_ffi_shared {
+ name: "libhwtrust_jni",
+ crate_name: "hwtrust_jni",
+ srcs: ["src/native/hwtrust_jni.rs"],
+ prefer_rlib: true,
+ rustlibs: [
+ "libandroid_logger",
+ "libanyhow",
+ "liblog_rust",
+ "libhwtrust",
+ "libjni",
+ ],
+ shared_libs: [
+ "libcrypto",
+ ],
+}
diff --git a/tests/testapk/src/java/com/android/microdroid/test/HwTrustJni.java b/tests/testapk/src/java/com/android/microdroid/test/HwTrustJni.java
new file mode 100644
index 0000000..3b237aa
--- /dev/null
+++ b/tests/testapk/src/java/com/android/microdroid/test/HwTrustJni.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 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.microdroid.test;
+
+class HwTrustJni {
+ static {
+ System.loadLibrary("hwtrust_jni");
+ }
+
+ /**
+ * Validates a DICE chain.
+ *
+ * @param diceChain The dice chain to validate.
+ * @return true if the dice chain is valid, false otherwise.
+ */
+ public static native boolean validateDiceChain(byte[] diceChain);
+}
diff --git a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
index fd67659..658b1bb 100644
--- a/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
+++ b/tests/testapk/src/java/com/android/microdroid/test/MicrodroidTests.java
@@ -1308,6 +1308,36 @@
}
@Test
+ @VsrTest(requirements = {"VSR-7.1-001.005"})
+ public void protectedVmHasValidDiceChain() throws Exception {
+ // This test validates two things regarding the pVM DICE chain:
+ // 1. The DICE chain is well-formed that all the entries conform to the DICE spec.
+ // 2. Each entry in the DICE chain is signed by the previous entry's subject public key.
+ assumeSupportedDevice();
+ assumeProtectedVM();
+ assumeVsrCompliant();
+ assumeTrue("Vendor API must be at least 202404", getVendorApiLevel() >= 202404);
+
+ grantPermission(VirtualMachine.USE_CUSTOM_VIRTUAL_MACHINE_PERMISSION);
+ VirtualMachineConfig config =
+ newVmConfigBuilderWithPayloadConfig("assets/vm_config.json")
+ .setDebugLevel(DEBUG_LEVEL_FULL)
+ .build();
+ VirtualMachine vm = forceCreateNewVirtualMachine("bcc_vm_for_vsr", config);
+ TestResults testResults =
+ runVmTestService(
+ TAG,
+ vm,
+ (service, results) -> {
+ results.mBcc = service.getBcc();
+ });
+ testResults.assertNoException();
+ byte[] bccBytes = testResults.mBcc;
+ assertThat(bccBytes).isNotNull();
+ assertThat(HwTrustJni.validateDiceChain(bccBytes)).isTrue();
+ }
+
+ @Test
@CddTest(requirements = {
"9.17/C-1-1",
"9.17/C-1-2"
diff --git a/tests/testapk/src/native/hwtrust_jni.rs b/tests/testapk/src/native/hwtrust_jni.rs
new file mode 100644
index 0000000..3b00364
--- /dev/null
+++ b/tests/testapk/src/native/hwtrust_jni.rs
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+//! JNI bindings to call into `hwtrust` from Java.
+
+use anyhow::Result;
+use hwtrust::{dice, session::Session};
+use jni::objects::{JByteArray, JClass};
+use jni::sys::jboolean;
+use jni::JNIEnv;
+use log::{debug, error, info};
+
+/// Validates the given DICE chain.
+#[no_mangle]
+pub extern "system" fn Java_com_android_microdroid_test_HwTrustJni_validateDiceChain(
+ env: JNIEnv,
+ _class: JClass,
+ dice_chain: JByteArray,
+) -> jboolean {
+ android_logger::init_once(
+ android_logger::Config::default()
+ .with_tag("hwtrust_jni")
+ .with_max_level(log::LevelFilter::Debug),
+ );
+ debug!("Starting the DICE chain validation ...");
+ match validate_dice_chain(env, dice_chain) {
+ Ok(_) => {
+ info!("DICE chain validated successfully");
+ true
+ }
+ Err(e) => {
+ error!("Failed to validate DICE chain: {:?}", e);
+ false
+ }
+ }
+ .into()
+}
+
+fn validate_dice_chain(env: JNIEnv, jdice_chain: JByteArray) -> Result<()> {
+ let dice_chain = env.convert_byte_array(jdice_chain)?;
+ let session = Session::default();
+ let _chain = dice::Chain::from_cbor(&session, &dice_chain)?;
+ Ok(())
+}
diff --git a/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java b/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
index cf6c3a7..102b86e 100644
--- a/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
+++ b/vmlauncher_app/java/com/android/virtualization/vmlauncher/MainActivity.java
@@ -323,7 +323,7 @@
} catch (VirtualMachineException e) {
vmm.delete(VM_NAME);
mVirtualMachine = vmm.create(VM_NAME, config);
- Log.e(TAG, "error" + e);
+ Log.e(TAG, "error for setting VM config", e);
}
Log.d(TAG, "vm start");
@@ -387,7 +387,9 @@
@Override
public void surfaceChanged(
SurfaceHolder holder, int format, int width, int height) {
- Log.d(TAG, "width: " + width + ", height: " + height);
+ Log.d(
+ TAG,
+ "surface changed, width: " + width + ", height: " + height);
}
@Override
@@ -413,8 +415,13 @@
runWithDisplayService(
(service) -> service.setCursorStream(pfds[1]));
} catch (Exception e) {
- Log.d("TAG", "failed to run cursor stream handler", e);
+ Log.d(TAG, "failed to run cursor stream handler", e);
}
+ Log.d(
+ TAG,
+ "ICrosvmAndroidDisplayService.setSurface("
+ + holder.getSurface()
+ + ")");
runWithDisplayService(
(service) ->
service.setSurface(
@@ -424,7 +431,12 @@
@Override
public void surfaceChanged(
SurfaceHolder holder, int format, int width, int height) {
- Log.d(TAG, "width: " + width + ", height: " + height);
+ Log.d(
+ TAG,
+ "cursor surface changed, width: "
+ + width
+ + ", height: "
+ + height);
}
@Override
@@ -432,13 +444,6 @@
Log.d(TAG, "ICrosvmAndroidDisplayService.removeSurface()");
runWithDisplayService(
(service) -> service.removeSurface(true /* forCursor */));
- if (mCursorStream != null) {
- try {
- mCursorStream.close();
- } catch (IOException e) {
- Log.d(TAG, "failed to close fd", e);
- }
- }
}
});
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
@@ -631,9 +636,9 @@
ICrosvmAndroidDisplayService.Stub.asInterface(vs.waitDisplayService());
assert service != null;
func.apply(service);
- Log.d(TAG, "job done");
+ Log.d(TAG, "display service runs successfully");
} catch (Exception e) {
- Log.d(TAG, "error", e);
+ Log.d(TAG, "error on running display service", e);
}
}
@@ -648,7 +653,7 @@
@Override
public void run() {
- Log.d(TAG, "CursorHandler");
+ Log.d(TAG, "running CursorHandler");
try {
ByteBuffer byteBuffer = ByteBuffer.allocate(8 /* (x: u32, y: u32) */);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
@@ -669,7 +674,7 @@
});
}
} catch (IOException e) {
- Log.e(TAG, e.getMessage());
+ Log.e(TAG, "failed to run CursorHandler", e);
}
}
}