Dice HAL: Add VTS Test.

This CL adds a VTS test for the DICE HAL, and a test specific for
demotion testing. Demotion testing leaves the device in a permanently
modified state untill the next reboot, which is why it needs a special
test config. The current test config restarts the device before testing,
in a followup the device also has to reboot after the test.

Bug: 198197213
Test: atest VtsAidlDiceTargetTest
      atest VtsAidlDiceDemoteTargetTest
Change-Id: I4278a1352df749da50dc8e5d118fc37336026061
This commit is contained in:
Janis Danisevskis
2021-11-16 08:47:50 -08:00
parent 86124738cd
commit 21244fc192
5 changed files with 289 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
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_test {
name: "VtsAidlDiceTargetTest",
srcs: [
"dice_test.rs",
],
require_root: true,
auto_gen_config: true,
test_suites: [
"general-tests",
"vts",
],
rustlibs: [
"android.hardware.security.dice-V1-rust",
"libanyhow",
"libbinder_rs",
"libdiced_open_dice_cbor",
"libdiced_sample_inputs",
"libdiced_utils",
"libkeystore2_vintf_rust",
],
}
rust_test {
name: "VtsAidlDiceDemoteTargetTest",
srcs: [
"dice_demote_test.rs",
],
test_config: "VtsAidlDiceDemoteTargetTest.xml",
test_suites: [
"general-tests",
"vts",
],
rustlibs: [
"android.hardware.security.dice-V1-rust",
"libanyhow",
"libbinder_rs",
"libdiced_open_dice_cbor",
"libdiced_sample_inputs",
"libdiced_utils",
"libkeystore2_vintf_rust",
],
}

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2019 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="Config to run VtsAidlDiceDemoteTargetTest device tests.">
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="VtsAidlDiceDemoteTargetTest->/data/local/tmp/VtsAidlDiceDemoteTargetTest" />
</target_preparer>
<test class="com.android.tradefed.testtype.rust.RustBinaryTest" >
<option name="test-device-path" value="/data/local/tmp" />
<option name="module-name" value="VtsAidlDiceDemoteTargetTest" />
</test>
<target_preparer class="com.android.tradefed.targetprep.RebootTargetPreparer" />
</configuration>

View File

@@ -0,0 +1,67 @@
// Copyright 2021, 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.
use diced_open_dice_cbor as dice;
use diced_sample_inputs;
use diced_utils;
use std::convert::TryInto;
mod utils;
use utils::with_connection;
// This test calls derive with an empty argument vector, then demotes the HAL using
// a set of three input values, and then calls derive with empty argument vector again.
// It then performs the same three derivation steps on the result of the former and compares
// the result to the result of the latter.
#[test]
fn demote_test() {
with_connection(|device| {
let input_values = diced_sample_inputs::get_input_values_vector();
let former = device.derive(&[]).expect("Trying to call derive.");
device
.demote(&input_values)
.expect("Trying to call demote with input values.");
let latter = device
.derive(&[])
.expect("Trying to call derive after demote.");
let artifacts = diced_utils::ResidentArtifacts::new(
former.cdiAttest[..].try_into().unwrap(),
former.cdiSeal[..].try_into().unwrap(),
&former.bcc.data,
)
.unwrap();
let input_values: Vec<diced_utils::InputValues> = input_values
.iter()
.map(|v| v.into())
.collect();
let artifacts = artifacts
.execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues))
.unwrap();
let (cdi_attest, cdi_seal, bcc) = artifacts.into_tuple();
let from_former = diced_utils::make_bcc_handover(
cdi_attest[..].try_into().unwrap(),
cdi_seal[..].try_into().unwrap(),
&bcc,
)
.unwrap();
// TODO b/204938506 when we have a parser/verifier, check equivalence rather
// than bit by bit equality.
assert_eq!(latter, from_former);
Ok(())
})
}

View File

@@ -0,0 +1,82 @@
// Copyright 2021, 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.
use diced_open_dice_cbor as dice;
use diced_sample_inputs;
use diced_utils;
use std::convert::{TryInto, Into};
mod utils;
use utils::with_connection;
static TEST_MESSAGE: &[u8] = &[
// "My test message!"
0x4d, 0x79, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x21,
0x0a,
];
// This test calls derive with an empty argument vector and with a set of three input values.
// It then performs the same three derivation steps on the result of the former and compares
// the result to the result of the latter.
#[test]
fn equivalence_test() {
with_connection(|device| {
let input_values = diced_sample_inputs::get_input_values_vector();
let former = device.derive(&[]).expect("Trying to call derive.");
let latter = device
.derive(&input_values)
.expect("Trying to call derive with input values.");
let artifacts = diced_utils::ResidentArtifacts::new(
former.cdiAttest[..].try_into().unwrap(),
former.cdiSeal[..].try_into().unwrap(),
&former.bcc.data,
)
.unwrap();
let input_values: Vec<diced_utils::InputValues> = input_values
.iter()
.map(|v| v.into())
.collect();
let artifacts = artifacts
.execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues))
.unwrap();
let (cdi_attest, cdi_seal, bcc) = artifacts.into_tuple();
let from_former = diced_utils::make_bcc_handover(
cdi_attest[..].try_into().unwrap(),
cdi_seal[..].try_into().unwrap(),
&bcc,
)
.unwrap();
// TODO b/204938506 when we have a parser/verifier, check equivalence rather
// than bit by bit equality.
assert_eq!(latter, from_former);
Ok(())
})
}
#[test]
fn sign_and_verify() {
with_connection(|device| {
let _signature = device
.sign(&[], TEST_MESSAGE)
.expect("Trying to call sign.");
let _bcc = device
.getAttestationChain(&[])
.expect("Trying to call getAttestationChain.");
// TODO b/204938506 check the signature with the bcc when the verifier is available.
Ok(())
})
}

View File

@@ -0,0 +1,53 @@
// Copyright 2021, 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.
use android_hardware_security_dice::aidl::android::hardware::security::dice::IDiceDevice::IDiceDevice;
use anyhow::Result;
use binder::Strong;
use keystore2_vintf::get_aidl_instances;
use std::sync::Arc;
static DICE_DEVICE_SERVICE_NAME: &str = &"android.hardware.security.dice";
static DICE_DEVICE_INTERFACE_NAME: &str = &"IDiceDevice";
/// This function iterates through all announced IDiceDevice services and runs the given test
/// closure against connections to each of them. It also modifies the panic hook to indicate
/// on which instance the test failed in case the test closure panics.
pub fn with_connection<R, F>(test: F)
where
F: Fn(&Strong<dyn IDiceDevice>) -> Result<R>,
{
let instances = get_aidl_instances(DICE_DEVICE_SERVICE_NAME, 1, DICE_DEVICE_INTERFACE_NAME);
let panic_hook = Arc::new(std::panic::take_hook());
for i in instances.into_iter() {
let panic_hook_clone = panic_hook.clone();
let instance_clone = i.clone();
std::panic::set_hook(Box::new(move |v| {
println!("While testing instance: \"{}\"", instance_clone);
panic_hook_clone(v)
}));
let connection: Strong<dyn IDiceDevice> = binder::get_interface(&format!(
"{}.{}/{}",
DICE_DEVICE_SERVICE_NAME, DICE_DEVICE_INTERFACE_NAME, i
))
.unwrap();
test(&connection).unwrap();
drop(std::panic::take_hook());
}
// Cannot call unwrap here because the panic hook is not Debug.
std::panic::set_hook(match Arc::try_unwrap(panic_hook) {
Ok(hook) => hook,
_ => panic!("Failed to unwrap and reset previous panic hook."),
})
}