Merge changes from topic "default_dice_hal"

* changes:
  Dice HAL: Add VTS Test.
  Dice HAL: Added default implementation.
This commit is contained in:
Janis Danisevskis 2022-03-16 20:16:15 +00:00 committed by Gerrit Code Review
commit 49a1688f5e
9 changed files with 441 additions and 0 deletions

View file

@ -0,0 +1,30 @@
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.dice-service.non-secure-software",
srcs: ["service.rs"],
relative_install_path: "hw",
vendor: true,
rustlibs: [
"android.hardware.security.dice-V1-rust",
"libdiced_open_dice_cbor",
"libdiced_sample_inputs",
"libdiced_vendor",
"libandroid_logger",
"libanyhow",
"libbinder_rs",
"liblog_rust",
"libserde",
],
init_rc: ["android.hardware.security.dice-service.non-secure-software.rc"],
vintf_fragments: [
"android.hardware.security.dice-service.non-secure-software.xml",
],
}

View file

@ -0,0 +1,9 @@
service vendor.dice /vendor/bin/hw/android.hardware.security.dice-service.non-secure-software
class early_hal
user nobody
# The diced HAL cannot be allowed to restart. When it crashes for any reason.
# it loses security critical state. The only remedy is to restart the device.
# This may be implementation depended. It is safe to restart the HAL if the
# state change during a call to "demote" is is preserved.
# see android/hardware/security/dice/IDiceDevice.aidl for details on "demote".
oneshot

View file

@ -0,0 +1,6 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.security.dice</name>
<fqname>IDiceDevice/default</fqname>
</hal>
</manifest>

View file

@ -0,0 +1,107 @@
// 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.
//! Main entry point for the android.hardware.security.dice service.
use anyhow::Result;
use diced::{
dice,
hal_node::{DiceArtifacts, DiceDevice, ResidentHal, UpdatableDiceArtifacts},
};
use diced_sample_inputs::make_sample_bcc_and_cdis;
use serde::{Deserialize, Serialize};
use std::convert::TryInto;
use std::panic;
use std::sync::Arc;
static DICE_HAL_SERVICE_NAME: &str = "android.hardware.security.dice.IDiceDevice/default";
#[derive(Debug, Serialize, Deserialize, Clone)]
struct InsecureSerializableArtifacts {
cdi_attest: [u8; dice::CDI_SIZE],
cdi_seal: [u8; dice::CDI_SIZE],
bcc: Vec<u8>,
}
impl DiceArtifacts for InsecureSerializableArtifacts {
fn cdi_attest(&self) -> &[u8; dice::CDI_SIZE] {
&self.cdi_attest
}
fn cdi_seal(&self) -> &[u8; dice::CDI_SIZE] {
&self.cdi_seal
}
fn bcc(&self) -> Vec<u8> {
self.bcc.clone()
}
}
impl UpdatableDiceArtifacts for InsecureSerializableArtifacts {
fn with_artifacts<F, T>(&self, f: F) -> Result<T>
where
F: FnOnce(&dyn DiceArtifacts) -> Result<T>,
{
f(self)
}
fn update(self, new_artifacts: &impl DiceArtifacts) -> Result<Self> {
Ok(Self {
cdi_attest: *new_artifacts.cdi_attest(),
cdi_seal: *new_artifacts.cdi_seal(),
bcc: new_artifacts.bcc(),
})
}
}
fn main() {
android_logger::init_once(
android_logger::Config::default()
.with_tag("android.hardware.security.dice")
.with_min_level(log::Level::Debug),
);
// Redirect panic messages to logcat.
panic::set_hook(Box::new(|panic_info| {
log::error!("{}", panic_info);
}));
// Saying hi.
log::info!("android.hardware.security.dice is starting.");
let (cdi_attest, cdi_seal, bcc) =
make_sample_bcc_and_cdis().expect("Failed to construct sample dice chain.");
let hal_impl = Arc::new(
unsafe {
// Safety: ResidentHal cannot be used in multi threaded processes.
// This service does not start a thread pool. The main thread is the only thread
// joining the thread pool, thereby keeping the process single threaded.
ResidentHal::new(InsecureSerializableArtifacts {
cdi_attest: cdi_attest[..]
.try_into()
.expect("Failed to convert cdi_attest to array reference."),
cdi_seal: cdi_seal[..]
.try_into()
.expect("Failed to convert cdi_seal to array reference."),
bcc,
})
}
.expect("Failed to create ResidentHal implementation."),
);
let hal = DiceDevice::new_as_binder(hal_impl).expect("Failed to construct hal service.");
binder::add_service(DICE_HAL_SERVICE_NAME, hal.as_binder())
.expect("Failed to register IDiceDevice Service");
log::info!("Joining thread pool now.");
binder::ProcessState::join_thread_pool();
}

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."),
})
}