[dice] Remove usages of the service android.hardware.security.dice
This cl removes the usages of the service
android.hardware.security.dice as the service itself is incomplete
and unused.
This helps us reduce some maintainance burden for the Rust dice
wrapper and util libraries such as libdiced_open_dice[_nostd],
libdiced_sample_inputs, libdiced_utils and their tests.
Test: atest diced_utils_test diced_sample_inputs_test \
diced_open_dice_cbor_test \
libdiced_open_dice_nostd.integration_test \
libdiced_open_dice.integration_test diced_open_dice_cbor_test
Test: m pvmfw_img microdroid_manager
Bug: 267575445
Change-Id: I87fc2d74c91e225752fc471143c75da6e4991aab
diff --git a/diced/Android.bp b/diced/Android.bp
index 6e857f4..6bd7c06 100644
--- a/diced/Android.bp
+++ b/diced/Android.bp
@@ -28,10 +28,7 @@
vendor_available: true,
rustlibs: [
- "android.hardware.security.dice-V1-rust",
"libanyhow",
- "libdiced_open_dice",
- "libkeystore2_crypto_rust",
],
}
@@ -42,10 +39,7 @@
test_suites: ["general-tests"],
auto_gen_config: true,
rustlibs: [
- "android.hardware.security.dice-V1-rust",
"libanyhow",
- "libdiced_open_dice",
- "libkeystore2_crypto_rust",
],
}
@@ -56,7 +50,6 @@
vendor_available: true,
rustlibs: [
- "android.hardware.security.dice-V1-rust",
"libanyhow",
"libdiced_open_dice",
"libdiced_utils",
@@ -70,77 +63,8 @@
test_suites: ["general-tests"],
auto_gen_config: true,
rustlibs: [
- "android.hardware.security.dice-V1-rust",
"libanyhow",
"libdiced_open_dice",
"libdiced_utils",
],
}
-
-rust_library {
- name: "libdiced_vendor",
- crate_name: "diced",
- srcs: ["src/lib_vendor.rs"],
-
- vendor_available: true,
- rustlibs: [
- "android.hardware.security.dice-V1-rust",
- "libdiced_open_dice",
- "libanyhow",
- "libbinder_rs",
- "libdiced_utils",
- "libkeystore2_crypto_rust",
- "liblibc",
- "liblog_rust",
- "libnix",
- "libserde",
- "libserde_cbor",
- "libthiserror",
- ],
-}
-
-rust_test {
- name: "diced_vendor_test",
- crate_name: "diced_vendor_test",
- srcs: ["src/lib_vendor.rs"],
- test_suites: ["general-tests"],
- auto_gen_config: true,
- rustlibs: [
- "android.hardware.security.dice-V1-rust",
- "libanyhow",
- "libdiced_open_dice",
- "libdiced_sample_inputs",
- "libdiced_utils",
- "libbinder_rs",
- "libkeystore2_crypto_rust",
- "liblibc",
- "liblog_rust",
- "libnix",
- "libserde",
- "libserde_cbor",
- "libthiserror",
- ],
-}
-
-rust_test {
- name: "diced_client_test",
- srcs: [
- "src/diced_client_test.rs",
- ],
- require_root: true,
- auto_gen_config: true,
- test_suites: [
- "general-tests",
- ],
-
- rustlibs: [
- "android.hardware.security.dice-V1-rust",
- "android.security.dice-rust",
- "libanyhow",
- "libbinder_rs",
- "libdiced_open_dice",
- "libdiced_sample_inputs",
- "libdiced_utils",
- "libnix",
- ],
-}
diff --git a/diced/TEST_MAPPING b/diced/TEST_MAPPING
index 8629b07..1b078a4 100644
--- a/diced/TEST_MAPPING
+++ b/diced/TEST_MAPPING
@@ -17,9 +17,6 @@
},
{
"name": "diced_sample_inputs_test"
- },
- {
- "name": "diced_vendor_test"
}
]
}
diff --git a/diced/aidl/Android.bp b/diced/aidl/Android.bp
deleted file mode 100644
index 57dad53..0000000
--- a/diced/aidl/Android.bp
+++ /dev/null
@@ -1,51 +0,0 @@
-// 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.
-
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "system_security_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["system_security_license"],
-}
-
-aidl_interface {
- name: "android.security.dice",
- srcs: [ "android/security/dice/*.aidl" ],
- unstable: true,
- imports: ["android.hardware.security.dice-V1"],
- backend: {
- java: {
- enabled: false,
- platform_apis: false,
- },
- rust: {
- enabled: true,
- apex_available: [
- "//apex_available:platform",
- "com.android.compos",
- "com.android.virt",
- ],
- },
- ndk: {
- enabled: true,
- apps_enabled: false,
- apex_available: [
- "//apex_available:platform",
- "com.android.compos",
- ],
- }
- },
-}
diff --git a/diced/aidl/android/security/dice/IDiceMaintenance.aidl b/diced/aidl/android/security/dice/IDiceMaintenance.aidl
deleted file mode 100644
index c81fdea..0000000
--- a/diced/aidl/android/security/dice/IDiceMaintenance.aidl
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package android.security.dice;
-
-import android.hardware.security.dice.InputValues;
-
-/**
- * The maintenance allows callers to prompt the DICE node to demote itself.
- *
- * @hide
- */
-@SensitiveData
-interface IDiceMaintenance {
- /**
- * The implementation must demote itself by deriving new effective artifacts
- * based on the list of input data passed to the function.
- * As opposed to the IDiceNode::demote, this function effects all clients of
- * the implementation.
- *
- * ## Error as service specific exception:
- * ResponseCode::PERMISSION_DENIED if the caller does not have the demote_self permission.
- * May produce any ResponseCode if anything went wrong.
- */
- void demoteSelf(in InputValues[] input_values);
-}
diff --git a/diced/aidl/android/security/dice/IDiceNode.aidl b/diced/aidl/android/security/dice/IDiceNode.aidl
deleted file mode 100644
index 2b3ef76..0000000
--- a/diced/aidl/android/security/dice/IDiceNode.aidl
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package android.security.dice;
-
-import android.hardware.security.dice.Bcc;
-import android.hardware.security.dice.BccHandover;
-import android.hardware.security.dice.InputValues;
-import android.hardware.security.dice.Signature;
-
-/**
- * An implementation of IDiceNode provides access to DICE secrets to its clients. It
- * uses binder's caller UID and security context to identify its callers and assures
- * That clients can only access their specific DICE secrets.
- * It may operate in two different modes, resident mode and proxy mode.
- *
- * ## Resident mode.
- * In resident mode, the node is in possession of the secrets corresponding to its level in
- * the dice tree. It can act as root of the sub tree that it serves. The secrets are memory
- * resident in the node. It identifies its callers and prepends the caller's identity to the
- * request's vector of input values. It then derives the required secrets by iterating through
- * the request's vector of input values in ascending order.
- *
- * ## Proxy mode.
- * In proxy mode, the node has a connection to a parent node. It serves its callers by verifying
- * their identity, by prefixing the client's vector of input values with client's identity, and
- * forwarding the request to the next level up.
- *
- * The modes are implementation details that are completely transparent to the clients.
- *
- * Privacy: Unprivileged apps may not use this service ever because it may provide access to a
- * device specific id that is stable across reinstalls, reboots, and applications.
- *
- * @hide
- */
-@SensitiveData
-interface IDiceNode {
- /**
- * Uses the a key derived from the caller's attestation secret to sign the payload using
- * RFC 8032 PureEd25519 and returns the signature. The payload is limited to 1024 bytes.
- *
- * ## Error as service specific exception:
- * ResponseCode::PERMISSION_DENIED if the caller does not have the use_sign permission.
- */
- Signature sign(in InputValues[] id, in byte[] payload);
-
- /**
- * Returns the attestation certificate chain of the caller if `inputValues` is empty or the
- * chain to the given child of the caller identified by the `inputValues` vector.
- *
- * ## Error as service specific exception:
- * ResponseCode::PERMISSION_DENIED if the caller does not have the get_attestation_chain
- * permission.
- */
- Bcc getAttestationChain(in InputValues[] inputValues);
-
- /**
- * This function allows a client to become a resident node. Called with empty InputValues
- * vectors, an implementation returns the client's DICE secrets. If inputValues is
- * not empty, the appropriate derivations are performed starting from the client's level.
- * The function must never return secrets pertaining to the implementation or a parent
- * thereof in the DICE hierarchy.
- *
- * ## Error as service specific exception:
- * ResponseCode::PERMISSION_DENIED if the implementation does not allow resident nodes
- * at the client's level.
- */
- BccHandover derive(in InputValues[] inputValues);
-
- /**
- * The client demotes itself to the given identity. When serving the calling client,
- * the implementation must append the given identities. Essentially, the client assumes
- * the identity of one of its children. This operation is not reversible, i.e., there
- * is no promotion. Further demotion is possible.
- *
- * If the operation fails for any reason. No further services must be provided. Ideally,
- * a device shutdown/reboot is triggered.
- *
- * ## Error as service specific exception:
- * ResponseCode::PERMISSION_DENIED if the caller does not have the demote permission.
- */
- void demote(in InputValues[] inputValues);
-}
diff --git a/diced/aidl/android/security/dice/ResponseCode.aidl b/diced/aidl/android/security/dice/ResponseCode.aidl
deleted file mode 100644
index 7c66058..0000000
--- a/diced/aidl/android/security/dice/ResponseCode.aidl
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.
- */
-
-package android.security.dice;
-
-@Backing(type="int")
-/**
- * Service specific error codes.
- * @hide
- */
-enum ResponseCode {
- /**
- * The caller has insufficient privilege to access the DICE API.
- */
- PERMISSION_DENIED = 1,
- /**
- * An unexpected error occurred, likely with IO or IPC.
- */
- SYSTEM_ERROR = 2,
- /**
- * Returned if the called function is not implemented.
- */
- NOT_IMPLEMENTED = 3,
-}
diff --git a/diced/src/diced_client_test.rs b/diced/src/diced_client_test.rs
deleted file mode 100644
index 7957f0a..0000000
--- a/diced/src/diced_client_test.rs
+++ /dev/null
@@ -1,177 +0,0 @@
-// 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::{
- Config::Config as BinderConfig, InputValues::InputValues as BinderInputValues,
- Mode::Mode as BinderMode,
-};
-use android_security_dice::aidl::android::security::dice::IDiceMaintenance::IDiceMaintenance;
-use android_security_dice::aidl::android::security::dice::IDiceNode::IDiceNode;
-use binder::Strong;
-use diced_open_dice as dice;
-use diced_open_dice::DiceArtifacts;
-use nix::libc::uid_t;
-use std::convert::TryInto;
-use std::ffi::CString;
-
-static DICE_NODE_SERVICE_NAME: &str = "android.security.dice.IDiceNode";
-static DICE_MAINTENANCE_SERVICE_NAME: &str = "android.security.dice.IDiceMaintenance";
-
-fn get_dice_node() -> Strong<dyn IDiceNode> {
- binder::get_interface(DICE_NODE_SERVICE_NAME).unwrap()
-}
-
-fn get_dice_maintenance() -> Strong<dyn IDiceMaintenance> {
- binder::get_interface(DICE_MAINTENANCE_SERVICE_NAME).unwrap()
-}
-
-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.
-fn equivalence_test() {
- let node = get_dice_node();
- let input_values = diced_sample_inputs::get_input_values_vector();
- let former = node.derive(&[]).expect("Trying to call derive.");
- let latter = node.derive(&input_values).expect("Trying to call derive with input values.");
- let artifacts =
- diced_utils::ResidentArtifacts::new(&former.cdiAttest, &former.cdiSeal, &former.bcc.data)
- .unwrap();
-
- let artifacts = artifacts.execute_steps(input_values.iter()).unwrap();
- let from_former = diced_utils::make_bcc_handover(
- artifacts.cdi_attest(),
- artifacts.cdi_seal(),
- artifacts.bcc().expect("bcc is none"),
- )
- .unwrap();
- // TODO when we have a parser/verifier, check equivalence rather
- // than bit by bit equality.
- assert_eq!(latter, from_former);
-}
-
-fn sign_and_verify() {
- let node = get_dice_node();
- let _signature = node.sign(&[], TEST_MESSAGE).expect("Trying to call sign.");
-
- let _bcc = node.getAttestationChain(&[]).expect("Trying to call getAttestationChain.");
- // TODO b/204938506 check the signature with the bcc when the verifier is available.
-}
-
-// This test calls derive with an empty argument vector, then demotes the itself 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.
-fn demote_test() {
- let node = get_dice_node();
- let input_values = diced_sample_inputs::get_input_values_vector();
- let former = node.derive(&[]).expect("Trying to call derive.");
- node.demote(&input_values).expect("Trying to call demote with input values.");
-
- let latter = node.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 artifacts = artifacts.execute_steps(input_values.iter()).unwrap();
- let from_former = diced_utils::make_bcc_handover(
- artifacts.cdi_attest(),
- artifacts.cdi_seal(),
- artifacts.bcc().expect("bcc is none"),
- )
- .unwrap();
- // TODO b/204938506 when we have a parser/verifier, check equivalence rather
- // than bit by bit equality.
- assert_eq!(latter, from_former);
-}
-
-fn client_input_values(uid: uid_t) -> BinderInputValues {
- let desc = CString::new(format!("{}", uid)).unwrap();
- BinderInputValues {
- codeHash: [0; dice::HASH_SIZE],
- config: BinderConfig {
- desc: dice::retry_bcc_format_config_descriptor(Some(desc.as_c_str()), None, true)
- .unwrap(),
- },
- authorityHash: [0; dice::HASH_SIZE],
- authorityDescriptor: None,
- mode: BinderMode::NORMAL,
- hidden: [0; dice::HIDDEN_SIZE],
- }
-}
-
-// This test calls derive with an empty argument vector `former` which look like this:
-// <common root> | <caller>
-// It then demotes diced using a set of three input values prefixed with the uid based input
-// values that diced would add to any call. It then calls derive with empty argument vector
-// again which will add another step using the identity of the caller. If diced was demoted
-// correctly the chain of `latter` will
-// look as follows:
-// <common root> | <caller> | <the three sample inputs> | <caller>
-//
-// It then performs the same three derivation steps followed by a set of caller input values
-// on `former` and compares it to `latter`.
-fn demote_self_test() {
- let maintenance = get_dice_maintenance();
- let node = get_dice_node();
- let input_values = diced_sample_inputs::get_input_values_vector();
- let former = node.derive(&[]).expect("Trying to call derive.");
-
- let client = client_input_values(nix::unistd::getuid().into());
-
- let mut demote_vector = vec![client.clone()];
- demote_vector.append(&mut input_values.clone());
- maintenance.demoteSelf(&demote_vector).expect("Trying to call demote_self with input values.");
-
- let latter = node.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 client = [client];
-
- let artifacts = artifacts.execute_steps(input_values.iter().chain(client.iter())).unwrap();
- let from_former = diced_utils::make_bcc_handover(
- artifacts.cdi_attest(),
- artifacts.cdi_seal(),
- artifacts.bcc().expect("bcc is none"),
- )
- .unwrap();
- // TODO b/204938506 when we have a parser/verifier, check equivalence rather
- // than bit by bit equality.
- assert_eq!(latter, from_former);
-}
-
-#[test]
-fn run_serialized_test() {
- equivalence_test();
- sign_and_verify();
- // The demote self test must run before the demote test or the test fails.
- // And since demotion is not reversible the test can only pass once per boot.
- demote_self_test();
- demote_test();
-}
diff --git a/diced/src/error_vendor.rs b/diced/src/error_vendor.rs
deleted file mode 100644
index e8657e0..0000000
--- a/diced/src/error_vendor.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-// 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::ResponseCode::ResponseCode;
-use anyhow::Result;
-use binder::{ExceptionCode, Result as BinderResult, Status as BinderStatus, StatusCode};
-use std::ffi::CString;
-
-/// This is the error type for DICE HAL implementations. It wraps
-/// `android::hardware::security::dice::ResponseCode` generated
-/// from AIDL in the `Rc` variant and Binder and BinderTransaction errors in the respective
-/// variants.
-#[allow(dead_code)] // Binder error forwarding will be needed when proxy nodes are implemented.
-#[derive(Debug, thiserror::Error, Eq, PartialEq, Clone)]
-pub enum Error {
- /// Wraps a dice `ResponseCode` as defined by the Keystore AIDL interface specification.
- #[error("Error::Rc({0:?})")]
- Rc(ResponseCode),
- /// Wraps a Binder exception code other than a service specific exception.
- #[error("Binder exception code {0:?}, {1:?}")]
- Binder(ExceptionCode, i32),
- /// Wraps a Binder status code.
- #[error("Binder transaction error {0:?}")]
- BinderTransaction(StatusCode),
-}
-
-/// This function should be used by dice service calls to translate error conditions
-/// into service specific exceptions.
-///
-/// All error conditions get logged by this function.
-///
-/// All `Error::Rc(x)` variants get mapped onto a service specific error code of x.
-/// `selinux::Error::PermissionDenied` is mapped on `ResponseCode::PERMISSION_DENIED`.
-///
-/// All non `Error` error conditions and the Error::Binder variant get mapped onto
-/// ResponseCode::SYSTEM_ERROR`.
-///
-/// `handle_ok` will be called if `result` is `Ok(value)` where `value` will be passed
-/// as argument to `handle_ok`. `handle_ok` must generate a `BinderResult<T>`, but it
-/// typically returns Ok(value).
-///
-/// # Examples
-///
-/// ```
-/// fn do_something() -> anyhow::Result<Vec<u8>> {
-/// Err(anyhow!(Error::Rc(ResponseCode::NOT_IMPLEMENTED)))
-/// }
-///
-/// map_or_log_err(do_something(), Ok)
-/// ```
-pub fn map_or_log_err<T, U, F>(result: Result<U>, handle_ok: F) -> BinderResult<T>
-where
- F: FnOnce(U) -> BinderResult<T>,
-{
- map_err_with(
- result,
- |e| {
- log::error!("{:?}", e);
- e
- },
- handle_ok,
- )
-}
-
-/// This function behaves similar to map_or_log_error, but it does not log the errors, instead
-/// it calls map_err on the error before mapping it to a binder result allowing callers to
-/// log or transform the error before mapping it.
-fn map_err_with<T, U, F1, F2>(result: Result<U>, map_err: F1, handle_ok: F2) -> BinderResult<T>
-where
- F1: FnOnce(anyhow::Error) -> anyhow::Error,
- F2: FnOnce(U) -> BinderResult<T>,
-{
- result.map_or_else(
- |e| {
- let e = map_err(e);
- let msg = match CString::new(format!("{:?}", e)) {
- Ok(msg) => Some(msg),
- Err(_) => {
- log::warn!(
- "Cannot convert error message to CStr. It contained a nul byte.
- Omitting message from service specific error."
- );
- None
- }
- };
- let rc = get_error_code(&e);
- Err(BinderStatus::new_service_specific_error(rc, msg.as_deref()))
- },
- handle_ok,
- )
-}
-
-/// Extracts the error code from an `anyhow::Error` mapping any error that does not have a
-/// root cause of `Error::Rc` onto `ResponseCode::SYSTEM_ERROR` and to `e` with `Error::Rc(e)`
-/// otherwise.
-fn get_error_code(e: &anyhow::Error) -> i32 {
- let root_cause = e.root_cause();
- match root_cause.downcast_ref::<Error>() {
- Some(Error::Rc(rcode)) => rcode.0,
- // If an Error::Binder reaches this stage we report a system error.
- // The exception code and possible service specific error will be
- // printed in the error log above.
- Some(Error::Binder(_, _)) | Some(Error::BinderTransaction(_)) => {
- ResponseCode::SYSTEM_ERROR.0
- }
- None => ResponseCode::SYSTEM_ERROR.0,
- }
-}
diff --git a/diced/src/hal_node.rs b/diced/src/hal_node.rs
deleted file mode 100644
index 33aeb2b..0000000
--- a/diced/src/hal_node.rs
+++ /dev/null
@@ -1,727 +0,0 @@
-// 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.
-
-//! This module provides `ResidentHal`, an implementation of a IDiceDevice HAL Interface.
-//! While the name implies that the DICE secrets are memory resident, the residency
-//! is augmented by the implementation of the traits `DiceArtifacts` and
-//! `UpdatableDiceArtifacts`. The implementation outsources all operations that
-//! involve the DICE secrets to a short lived child process. By implementing
-//! `UpdatableDiceArtifacts` accordingly, integrators can limit the exposure of
-//! the resident DICE secrets to user space memory. E.g., an implementation might only
-//! hold a path to a securefs file allowing the child to read and update the kernel state
-//! through this path directly.
-//!
-//! ## Important Safety Note.
-//! The module is not safe to use in multi threaded processes. It uses fork and runs
-//! code that is not async signal safe in the child. Implementing a HAL service without
-//! starting a thread pool is safe, but no secondary thread must be created.
-
-use crate::error_vendor::map_or_log_err;
-use android_hardware_security_dice::aidl::android::hardware::security::dice::{
- Bcc::Bcc, BccHandover::BccHandover, IDiceDevice::BnDiceDevice, IDiceDevice::IDiceDevice,
- InputValues::InputValues as BinderInputValues, Signature::Signature,
-};
-use anyhow::{Context, Result};
-use binder::{BinderFeatures, Result as BinderResult, Strong};
-use diced_open_dice as dice;
-pub use diced_open_dice::DiceArtifacts;
-use diced_utils as utils;
-use nix::sys::wait::{waitpid, WaitStatus};
-use nix::unistd::{
- close, fork, pipe as nix_pipe, read as nix_read, write as nix_write, ForkResult,
-};
-use serde::{de::DeserializeOwned, Deserialize, Serialize};
-use std::convert::TryInto;
-use std::io::{Read, Write};
-use std::os::unix::io::RawFd;
-use std::sync::{Arc, RwLock};
-use utils::ResidentArtifacts;
-pub use utils::UpdatableDiceArtifacts;
-
-/// PipeReader is a simple wrapper around raw pipe file descriptors.
-/// It takes ownership of the file descriptor and closes it on drop. It provides `read_all`, which
-/// reads from the pipe into an expending vector, until no more data can be read.
-struct PipeReader(RawFd);
-
-impl Read for PipeReader {
- fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
- let bytes = nix_read(self.0, buf)?;
- Ok(bytes)
- }
-}
-
-impl Drop for PipeReader {
- fn drop(&mut self) {
- close(self.0).expect("Failed to close reader pipe fd.");
- }
-}
-
-/// PipeWriter is a simple wrapper around raw pipe file descriptors.
-/// It takes ownership of the file descriptor and closes it on drop. It provides `write`, which
-/// writes the given buffer into the pipe, returning the number of bytes written.
-struct PipeWriter(RawFd);
-
-impl Write for PipeWriter {
- fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
- let written = nix_write(self.0, buf)?;
- Ok(written)
- }
-
- fn flush(&mut self) -> std::io::Result<()> {
- // Flush is a NO-OP.
- Ok(())
- }
-}
-
-impl Drop for PipeWriter {
- fn drop(&mut self) {
- close(self.0).expect("Failed to close writer pipe fd.");
- }
-}
-
-fn pipe() -> Result<(PipeReader, PipeWriter), nix::Error> {
- let (read_fd, write_fd) = nix_pipe()?;
- Ok((PipeReader(read_fd), PipeWriter(write_fd)))
-}
-
-#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, thiserror::Error)]
-enum RunForkedError {
- #[error("RunForkedError::String({0:?})")]
- String(String),
-}
-
-/// Run the given closure in a new process.
-/// Safety: The function runs code that is not async-signal-safe in the child after forking.
-/// This means, that this function must not be called by a multi threaded process.
-fn run_forked<F, R>(f: F) -> Result<R>
-where
- R: Serialize + DeserializeOwned,
- F: FnOnce() -> Result<R>,
-{
- let (reader, writer) = pipe().expect("Failed to create pipe.");
-
- match unsafe { fork() } {
- Ok(ForkResult::Parent { child, .. }) => {
- drop(writer);
- let status = waitpid(child, None).expect("Failed while waiting for child.");
- if let WaitStatus::Exited(_, 0) = status {
- // Child exited successfully.
- // Read the result from the pipe.
- // Deserialize the result and return it.
- let result: Result<R, RunForkedError> =
- serde_cbor::from_reader(reader).expect("Failed to deserialize result.");
-
- result.context("In run_forked:")
- } else {
- panic!("Child did not exit as expected {:?}", status);
- }
- }
- Ok(ForkResult::Child) => {
- // Run the closure.
- let result = f()
- .map_err(|err| RunForkedError::String(format! {"Nested anyhow error {:?}", err}));
-
- // Serialize the result of the closure.
- serde_cbor::to_writer(writer, &result).expect("Result serialization failed");
-
- // Set exit status to `0`.
- std::process::exit(0);
- }
- Err(errno) => {
- panic!("Failed to fork: {:?}", errno);
- }
- }
-}
-
-/// A DiceHal backend implementation.
-/// All functions, except `demote`, derive effective dice artifacts starting from
-/// this node and iterating through `input_values` in ascending order.
-pub trait DiceHalImpl {
- /// Signs the message using the effective dice artifacts and Ed25519Pure.
- fn sign(&self, input_values: &[BinderInputValues], message: &[u8]) -> Result<Signature>;
- /// Returns the effective attestation chain.
- fn get_attestation_chain(&self, input_values: &[BinderInputValues]) -> Result<Bcc>;
- /// Returns the effective dice artifacts.
- fn derive(&self, input_values: &[BinderInputValues]) -> Result<BccHandover>;
- /// This demotes the implementation itself. I.e. a resident node would replace its resident
- /// artifacts with the effective artifacts derived using `input_values`. A proxy node would
- /// simply call `demote` on its parent node. This is not reversible and changes
- /// the effective dice artifacts of all clients.
- fn demote(&self, input_values: &[BinderInputValues]) -> Result<()>;
-}
-
-/// The ResidentHal implements a IDiceDevice backend with memory resident DICE secrets.
-pub struct ResidentHal<T: UpdatableDiceArtifacts + Serialize + DeserializeOwned + Clone + Send> {
- artifacts: RwLock<T>,
-}
-
-impl<T: UpdatableDiceArtifacts + Serialize + DeserializeOwned + Clone + Send> ResidentHal<T> {
- /// Creates a new Resident node with the given dice secrets and certificate chain.
- /// ## Safety
- /// It is not safe to use implementations of ResidentHal in multi threaded environments.
- /// If using this library to implement a HAL service make sure not to start a thread pool.
- pub unsafe fn new(artifacts: T) -> Result<Self> {
- Ok(ResidentHal { artifacts: RwLock::new(artifacts) })
- }
-
- fn with_effective_artifacts<R, F>(&self, input_values: &[BinderInputValues], f: F) -> Result<R>
- where
- R: Serialize + DeserializeOwned,
- F: FnOnce(ResidentArtifacts) -> Result<R>,
- {
- let artifacts = self.artifacts.read().unwrap().clone();
-
- // Safety: run_forked must not be be called by a multi threaded process.
- // This requirement is propagated to the public interface of this module through
- // `ResidentHal::new`
- run_forked(move || {
- let artifacts = artifacts.with_artifacts(|a| ResidentArtifacts::new_from(a))?;
- let artifacts = artifacts
- .execute_steps(input_values)
- .context("In ResidentHal::get_effective_artifacts:")?;
- f(artifacts)
- })
- }
-}
-
-impl<T: UpdatableDiceArtifacts + Serialize + DeserializeOwned + Clone + Send> DiceHalImpl
- for ResidentHal<T>
-{
- fn sign(&self, input_values: &[BinderInputValues], message: &[u8]) -> Result<Signature> {
- let signature: Vec<u8> = self
- .with_effective_artifacts(input_values, |artifacts| {
- let (cdi_attest, _, _) = artifacts.into_tuple();
- let seed = dice::derive_cdi_private_key_seed(
- cdi_attest[..].try_into().with_context(|| {
- format!(
- "In ResidentHal::sign: Failed to convert cdi_attest (length: {}).",
- cdi_attest.len()
- )
- })?,
- )
- .context("In ResidentHal::sign: Failed to derive seed from cdi_attest.")?;
- let (_public_key, private_key) = dice::keypair_from_seed(seed.as_array())
- .context("In ResidentHal::sign: Failed to derive keypair from seed.")?;
- let signature = dice::sign(message, private_key.as_array())
- .context("In ResidentHal::sign: Failed to sign.")?;
- Ok(signature.to_vec())
- })
- .context("In ResidentHal::sign:")?;
- Ok(Signature { data: signature })
- }
-
- fn get_attestation_chain(&self, input_values: &[BinderInputValues]) -> Result<Bcc> {
- let bcc = self
- .with_effective_artifacts(input_values, |artifacts| {
- let (_, _, bcc) = artifacts.into_tuple();
- Ok(bcc)
- })
- .context("In ResidentHal::get_attestation_chain: Failed to get effective_artifacts.")?;
-
- Ok(Bcc { data: bcc })
- }
-
- fn derive(&self, input_values: &[BinderInputValues]) -> Result<BccHandover> {
- let (cdi_attest, cdi_seal, bcc): (Vec<u8>, Vec<u8>, Vec<u8>) = self
- .with_effective_artifacts(input_values, |artifacts| {
- let (cdi_attest, cdi_seal, bcc) = artifacts.into_tuple();
- Ok((cdi_attest[..].to_vec(), cdi_seal[..].to_vec(), bcc))
- })?;
-
- utils::make_bcc_handover(
- &cdi_attest
- .as_slice()
- .try_into()
- .context("In ResidentHal::derive: Trying to convert cdi_attest to sized array.")?,
- &cdi_seal
- .as_slice()
- .try_into()
- .context("In ResidentHal::derive: Trying to convert cdi_seal to sized array.")?,
- &bcc,
- )
- .context("In ResidentHal::derive: Trying to construct BccHandover.")
- }
-
- fn demote(&self, input_values: &[BinderInputValues]) -> Result<()> {
- let mut artifacts = self.artifacts.write().unwrap();
-
- let artifacts_clone = (*artifacts).clone();
-
- // Safety: run_forked may not be called from a multi threaded process.
- // This requirement is propagated to the public interface of this module through
- // `ResidentHal::new`
- *artifacts = run_forked(|| {
- let new_artifacts =
- artifacts_clone.with_artifacts(|a| ResidentArtifacts::new_from(a))?;
- let new_artifacts = new_artifacts
- .execute_steps(input_values)
- .context("In ResidentHal::get_effective_artifacts:")?;
- artifacts_clone.update(&new_artifacts)
- })?;
-
- Ok(())
- }
-}
-
-/// Implements android.hardware.security.dice.IDiceDevice. Forwards public API calls
-/// to the given DiceHalImpl backend.
-pub struct DiceDevice {
- hal_impl: Arc<dyn DiceHalImpl + Sync + Send>,
-}
-
-impl DiceDevice {
- /// Constructs an instance of DiceDevice, wraps it with a BnDiceDevice object and
- /// returns a strong pointer to the binder. The result can be used to register
- /// the service with service manager.
- pub fn new_as_binder(
- hal_impl: Arc<dyn DiceHalImpl + Sync + Send>,
- ) -> Result<Strong<dyn IDiceDevice>> {
- let result = BnDiceDevice::new_binder(DiceDevice { hal_impl }, BinderFeatures::default());
- Ok(result)
- }
-}
-
-impl binder::Interface for DiceDevice {}
-
-impl IDiceDevice for DiceDevice {
- fn sign(&self, input_values: &[BinderInputValues], message: &[u8]) -> BinderResult<Signature> {
- map_or_log_err(self.hal_impl.sign(input_values, message), Ok)
- }
- fn getAttestationChain(&self, input_values: &[BinderInputValues]) -> BinderResult<Bcc> {
- map_or_log_err(self.hal_impl.get_attestation_chain(input_values), Ok)
- }
- fn derive(&self, input_values: &[BinderInputValues]) -> BinderResult<BccHandover> {
- map_or_log_err(self.hal_impl.derive(input_values), Ok)
- }
- fn demote(&self, input_values: &[BinderInputValues]) -> BinderResult<()> {
- map_or_log_err(self.hal_impl.demote(input_values), Ok)
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
- use android_hardware_security_dice::aidl::android::hardware::security::dice::{
- BccHandover::BccHandover, Config::Config as BinderConfig,
- InputValues::InputValues as BinderInputValues, Mode::Mode as BinderMode,
- };
- use anyhow::{anyhow, Context, Result};
- use diced_open_dice as dice;
- use diced_sample_inputs;
- use diced_utils as utils;
- use std::ffi::CStr;
-
- #[derive(Debug, Serialize, Deserialize, Clone)]
- struct InsecureSerializableArtifacts {
- cdi_attest: [u8; dice::CDI_SIZE],
- cdi_seal: [u8; dice::CDI_SIZE],
- bcc: Vec<u8>,
- }
-
- impl From<dice::OwnedDiceArtifacts> for InsecureSerializableArtifacts {
- fn from(dice_artifacts: dice::OwnedDiceArtifacts) -> Self {
- let mut cdi_attest = [0u8; dice::CDI_SIZE];
- cdi_attest.copy_from_slice(dice_artifacts.cdi_attest());
- let mut cdi_seal = [0u8; dice::CDI_SIZE];
- cdi_seal.copy_from_slice(dice_artifacts.cdi_seal());
- Self { cdi_attest, cdi_seal, bcc: dice_artifacts.bcc().expect("bcc is none").to_vec() }
- }
- }
-
- 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) -> Option<&[u8]> {
- Some(&self.bcc)
- }
- }
-
- 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().ok_or_else(|| anyhow!("bcc is none"))?.to_vec(),
- })
- }
- }
-
- fn make_input_values(
- code: &str,
- config_name: &CStr,
- authority: &str,
- ) -> Result<BinderInputValues> {
- Ok(BinderInputValues {
- codeHash: dice::hash(code.as_bytes())
- .context("In make_input_values: code hash failed.")?,
- config: BinderConfig {
- desc: dice::retry_bcc_format_config_descriptor(Some(config_name), None, true)
- .context("In make_input_values: Failed to format config descriptor.")?,
- },
- authorityHash: dice::hash(authority.as_bytes())
- .context("In make_input_values: authority hash failed.")?,
- authorityDescriptor: None,
- mode: BinderMode::NORMAL,
- hidden: [0; dice::HIDDEN_SIZE],
- })
- }
-
- /// Test the resident artifact batched derivation in process.
- #[test]
- fn derive_with_resident_artifacts() -> Result<()> {
- let artifacts: ResidentArtifacts =
- diced_sample_inputs::make_sample_bcc_and_cdis()?.try_into()?;
-
- let input_values = &[
- make_input_values(
- "component 1 code",
- CStr::from_bytes_with_nul(b"component 1\0").unwrap(),
- "component 1 authority",
- )?,
- make_input_values(
- "component 2 code",
- CStr::from_bytes_with_nul(b"component 2\0").unwrap(),
- "component 2 authority",
- )?,
- make_input_values(
- "component 3 code",
- CStr::from_bytes_with_nul(b"component 3\0").unwrap(),
- "component 3 authority",
- )?,
- ];
- let new_artifacts = artifacts.execute_steps(input_values)?;
-
- let result = utils::make_bcc_handover(
- new_artifacts.cdi_attest(),
- new_artifacts.cdi_seal(),
- new_artifacts.bcc().unwrap(),
- )?;
-
- assert_eq!(result, make_derive_test_vector());
- Ok(())
- }
-
- /// Test the ResidentHal hal implementation which performs the derivation in a separate
- /// process and returns the result through a pipe. This test compares the result against
- /// the same test vector as the in process test above.
- #[test]
- fn derive_with_insecure_artifacts() -> Result<()> {
- let dice_artifacts = diced_sample_inputs::make_sample_bcc_and_cdis()?;
-
- // Safety: ResidentHal can only be used in single threaded environments.
- // On-device Rust tests run each test in a separate process.
- let hal_impl =
- unsafe { ResidentHal::new(InsecureSerializableArtifacts::from(dice_artifacts)) }
- .expect("Failed to create ResidentHal.");
-
- let bcc_handover = hal_impl
- .derive(&[
- make_input_values(
- "component 1 code",
- CStr::from_bytes_with_nul(b"component 1\0").unwrap(),
- "component 1 authority",
- )?,
- make_input_values(
- "component 2 code",
- CStr::from_bytes_with_nul(b"component 2\0").unwrap(),
- "component 2 authority",
- )?,
- make_input_values(
- "component 3 code",
- CStr::from_bytes_with_nul(b"component 3\0").unwrap(),
- "component 3 authority",
- )?,
- ])
- .expect("Failed to derive artifacts.");
-
- assert_eq!(bcc_handover, make_derive_test_vector());
- Ok(())
- }
-
- /// Demoting the implementation two steps and then performing one step of child derivation
- /// must yield the same outcome as three derivations with the same input values.
- #[test]
- fn demote() -> Result<()> {
- let dice_artifacts = diced_sample_inputs::make_sample_bcc_and_cdis()?;
-
- // Safety: ResidentHal can only be used in single threaded environments.
- // On-device Rust tests run each test in a separate process.
- let hal_impl =
- unsafe { ResidentHal::new(InsecureSerializableArtifacts::from(dice_artifacts)) }
- .expect("Failed to create ResidentHal.");
-
- hal_impl
- .demote(&[
- make_input_values(
- "component 1 code",
- CStr::from_bytes_with_nul(b"component 1\0").unwrap(),
- "component 1 authority",
- )?,
- make_input_values(
- "component 2 code",
- CStr::from_bytes_with_nul(b"component 2\0").unwrap(),
- "component 2 authority",
- )?,
- ])
- .expect("Failed to demote implementation.");
-
- let bcc_handover = hal_impl
- .derive(&[make_input_values(
- "component 3 code",
- CStr::from_bytes_with_nul(b"component 3\0").unwrap(),
- "component 3 authority",
- )?])
- .expect("Failed to derive artifacts.");
-
- assert_eq!(bcc_handover, make_derive_test_vector());
- Ok(())
- }
-
- fn make_derive_test_vector() -> BccHandover {
- utils::make_bcc_handover(
- &[
- // cdi_attest
- 0x8f, 0xdf, 0x93, 0x67, 0xd7, 0x0e, 0xf8, 0xb8, 0xd2, 0x9c, 0x30, 0xeb, 0x4e, 0x9b,
- 0x71, 0x5f, 0x9a, 0x5b, 0x67, 0xa6, 0x29, 0xe0, 0x00, 0x9b, 0x4d, 0xe6, 0x95, 0xcf,
- 0xf9, 0xed, 0x5e, 0x9b,
- ],
- &[
- // cdi_seal
- 0x15, 0x3e, 0xd6, 0x30, 0x5a, 0x8d, 0x4b, 0x6f, 0x07, 0x3f, 0x5d, 0x89, 0xc5, 0x6e,
- 0x30, 0xba, 0x05, 0x56, 0xfc, 0x66, 0xf4, 0xae, 0xce, 0x7f, 0x81, 0xb9, 0xc5, 0x21,
- 0x9b, 0x49, 0x3d, 0xe1,
- ],
- &[
- // bcc
- 0x87, 0xa5, 0x01, 0x01, 0x03, 0x27, 0x04, 0x81, 0x02, 0x20, 0x06, 0x21, 0x58, 0x20,
- 0x3e, 0x85, 0xe5, 0x72, 0x75, 0x55, 0xe5, 0x1e, 0xe7, 0xf3, 0x35, 0x94, 0x8e, 0xbb,
- 0xbd, 0x74, 0x1e, 0x1d, 0xca, 0x49, 0x9c, 0x97, 0x39, 0x77, 0x06, 0xd3, 0xc8, 0x6e,
- 0x8b, 0xd7, 0x33, 0xf9, 0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x59, 0x01, 0x8a, 0xa9,
- 0x01, 0x78, 0x28, 0x34, 0x32, 0x64, 0x38, 0x38, 0x36, 0x34, 0x66, 0x39, 0x37, 0x62,
- 0x36, 0x35, 0x34, 0x37, 0x61, 0x35, 0x30, 0x63, 0x31, 0x65, 0x30, 0x61, 0x37, 0x34,
- 0x39, 0x66, 0x38, 0x65, 0x66, 0x38, 0x62, 0x38, 0x31, 0x65, 0x63, 0x36, 0x32, 0x61,
- 0x66, 0x02, 0x78, 0x28, 0x31, 0x66, 0x36, 0x39, 0x36, 0x66, 0x30, 0x37, 0x32, 0x35,
- 0x32, 0x66, 0x32, 0x39, 0x65, 0x39, 0x33, 0x66, 0x65, 0x34, 0x64, 0x65, 0x31, 0x39,
- 0x65, 0x65, 0x33, 0x32, 0x63, 0x64, 0x38, 0x31, 0x64, 0x63, 0x34, 0x30, 0x34, 0x65,
- 0x37, 0x36, 0x3a, 0x00, 0x47, 0x44, 0x50, 0x58, 0x40, 0x16, 0x48, 0xf2, 0x55, 0x53,
- 0x23, 0xdd, 0x15, 0x2e, 0x83, 0x38, 0xc3, 0x64, 0x38, 0x63, 0x26, 0x0f, 0xcf, 0x5b,
- 0xd1, 0x3a, 0xd3, 0x40, 0x3e, 0x23, 0xf8, 0x34, 0x4c, 0x6d, 0xa2, 0xbe, 0x25, 0x1c,
- 0xb0, 0x29, 0xe8, 0xc3, 0xfb, 0xb8, 0x80, 0xdc, 0xb1, 0xd2, 0xb3, 0x91, 0x4d, 0xd3,
- 0xfb, 0x01, 0x0f, 0xe4, 0xe9, 0x46, 0xa2, 0xc0, 0x26, 0x57, 0x5a, 0xba, 0x30, 0xf7,
- 0x15, 0x98, 0x14, 0x3a, 0x00, 0x47, 0x44, 0x53, 0x56, 0xa3, 0x3a, 0x00, 0x01, 0x11,
- 0x71, 0x63, 0x41, 0x42, 0x4c, 0x3a, 0x00, 0x01, 0x11, 0x72, 0x01, 0x3a, 0x00, 0x01,
- 0x11, 0x73, 0xf6, 0x3a, 0x00, 0x47, 0x44, 0x52, 0x58, 0x40, 0x47, 0xae, 0x42, 0x27,
- 0x4c, 0xcb, 0x65, 0x4d, 0xee, 0x74, 0x2d, 0x05, 0x78, 0x2a, 0x08, 0x2a, 0xa5, 0xf0,
- 0xcf, 0xea, 0x3e, 0x60, 0xee, 0x97, 0x11, 0x4b, 0x5b, 0xe6, 0x05, 0x0c, 0xe8, 0x90,
- 0xf5, 0x22, 0xc4, 0xc6, 0x67, 0x7a, 0x22, 0x27, 0x17, 0xb3, 0x79, 0xcc, 0x37, 0x64,
- 0x5e, 0x19, 0x4f, 0x96, 0x37, 0x67, 0x3c, 0xd0, 0xc5, 0xed, 0x0f, 0xdd, 0xe7, 0x2e,
- 0x4f, 0x70, 0x97, 0x30, 0x3a, 0x00, 0x47, 0x44, 0x54, 0x58, 0x40, 0xf9, 0x00, 0x9d,
- 0xc2, 0x59, 0x09, 0xe0, 0xb6, 0x98, 0xbd, 0xe3, 0x97, 0x4a, 0xcb, 0x3c, 0xe7, 0x6b,
- 0x24, 0xc3, 0xe4, 0x98, 0xdd, 0xa9, 0x6a, 0x41, 0x59, 0x15, 0xb1, 0x23, 0xe6, 0xc8,
- 0xdf, 0xfb, 0x52, 0xb4, 0x52, 0xc1, 0xb9, 0x61, 0xdd, 0xbc, 0x5b, 0x37, 0x0e, 0x12,
- 0x12, 0xb2, 0xfd, 0xc1, 0x09, 0xb0, 0xcf, 0x33, 0x81, 0x4c, 0xc6, 0x29, 0x1b, 0x99,
- 0xea, 0xae, 0xfd, 0xaa, 0x0d, 0x3a, 0x00, 0x47, 0x44, 0x56, 0x41, 0x01, 0x3a, 0x00,
- 0x47, 0x44, 0x57, 0x58, 0x2d, 0xa5, 0x01, 0x01, 0x03, 0x27, 0x04, 0x81, 0x02, 0x20,
- 0x06, 0x21, 0x58, 0x20, 0xb1, 0x02, 0xcc, 0x2c, 0xb2, 0x6a, 0x3b, 0xe9, 0xc1, 0xd3,
- 0x95, 0x10, 0xa0, 0xe1, 0xff, 0x51, 0xde, 0x57, 0xd5, 0x65, 0x28, 0xfd, 0x7f, 0xeb,
- 0xd4, 0xca, 0x15, 0xf3, 0xca, 0xdf, 0x37, 0x88, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41,
- 0x20, 0x58, 0x40, 0x58, 0xd8, 0x03, 0x24, 0x53, 0x60, 0x57, 0xa9, 0x09, 0xfa, 0xab,
- 0xdc, 0x57, 0x1e, 0xf0, 0xe5, 0x1e, 0x51, 0x6f, 0x9e, 0xa3, 0x42, 0xe6, 0x6a, 0x8c,
- 0xaa, 0xad, 0x08, 0x48, 0xde, 0x7f, 0x4f, 0x6e, 0x2f, 0x7f, 0x39, 0x6c, 0xa1, 0xf8,
- 0x42, 0x71, 0xfe, 0x17, 0x3d, 0xca, 0x31, 0x83, 0x92, 0xed, 0xbb, 0x40, 0xb8, 0x10,
- 0xe0, 0xf2, 0x5a, 0x99, 0x53, 0x38, 0x46, 0x33, 0x97, 0x78, 0x05, 0x84, 0x43, 0xa1,
- 0x01, 0x27, 0xa0, 0x59, 0x01, 0x8a, 0xa9, 0x01, 0x78, 0x28, 0x31, 0x66, 0x36, 0x39,
- 0x36, 0x66, 0x30, 0x37, 0x32, 0x35, 0x32, 0x66, 0x32, 0x39, 0x65, 0x39, 0x33, 0x66,
- 0x65, 0x34, 0x64, 0x65, 0x31, 0x39, 0x65, 0x65, 0x33, 0x32, 0x63, 0x64, 0x38, 0x31,
- 0x64, 0x63, 0x34, 0x30, 0x34, 0x65, 0x37, 0x36, 0x02, 0x78, 0x28, 0x32, 0x35, 0x39,
- 0x34, 0x38, 0x39, 0x65, 0x36, 0x39, 0x37, 0x34, 0x38, 0x37, 0x30, 0x35, 0x64, 0x65,
- 0x33, 0x65, 0x32, 0x66, 0x34, 0x34, 0x32, 0x36, 0x37, 0x65, 0x61, 0x34, 0x39, 0x33,
- 0x38, 0x66, 0x66, 0x36, 0x61, 0x35, 0x37, 0x32, 0x35, 0x3a, 0x00, 0x47, 0x44, 0x50,
- 0x58, 0x40, 0xa4, 0x0c, 0xcb, 0xc1, 0xbf, 0xfa, 0xcc, 0xfd, 0xeb, 0xf4, 0xfc, 0x43,
- 0x83, 0x7f, 0x46, 0x8d, 0xd8, 0xd8, 0x14, 0xc1, 0x96, 0x14, 0x1f, 0x6e, 0xb3, 0xa0,
- 0xd9, 0x56, 0xb3, 0xbf, 0x2f, 0xfa, 0x88, 0x70, 0x11, 0x07, 0x39, 0xa4, 0xd2, 0xa9,
- 0x6b, 0x18, 0x28, 0xe8, 0x29, 0x20, 0x49, 0x0f, 0xbb, 0x8d, 0x08, 0x8c, 0xc6, 0x54,
- 0xe9, 0x71, 0xd2, 0x7e, 0xa4, 0xfe, 0x58, 0x7f, 0xd3, 0xc7, 0x3a, 0x00, 0x47, 0x44,
- 0x53, 0x56, 0xa3, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x63, 0x41, 0x56, 0x42, 0x3a, 0x00,
- 0x01, 0x11, 0x72, 0x01, 0x3a, 0x00, 0x01, 0x11, 0x73, 0xf6, 0x3a, 0x00, 0x47, 0x44,
- 0x52, 0x58, 0x40, 0x93, 0x17, 0xe1, 0x11, 0x27, 0x59, 0xd0, 0xef, 0x75, 0x0b, 0x2b,
- 0x1c, 0x0f, 0x5f, 0x52, 0xc3, 0x29, 0x23, 0xb5, 0x2a, 0xe6, 0x12, 0x72, 0x6f, 0x39,
- 0x86, 0x65, 0x2d, 0xf2, 0xe4, 0xe7, 0xd0, 0xaf, 0x0e, 0xa7, 0x99, 0x16, 0x89, 0x97,
- 0x21, 0xf7, 0xdc, 0x89, 0xdc, 0xde, 0xbb, 0x94, 0x88, 0x1f, 0xda, 0xe2, 0xf3, 0xe0,
- 0x54, 0xf9, 0x0e, 0x29, 0xb1, 0xbd, 0xe1, 0x0c, 0x0b, 0xd7, 0xf6, 0x3a, 0x00, 0x47,
- 0x44, 0x54, 0x58, 0x40, 0xb2, 0x69, 0x05, 0x48, 0x56, 0xb5, 0xfa, 0x55, 0x6f, 0xac,
- 0x56, 0xd9, 0x02, 0x35, 0x2b, 0xaa, 0x4c, 0xba, 0x28, 0xdd, 0x82, 0x3a, 0x86, 0xf5,
- 0xd4, 0xc2, 0xf1, 0xf9, 0x35, 0x7d, 0xe4, 0x43, 0x13, 0xbf, 0xfe, 0xd3, 0x36, 0xd8,
- 0x1c, 0x12, 0x78, 0x5c, 0x9c, 0x3e, 0xf6, 0x66, 0xef, 0xab, 0x3d, 0x0f, 0x89, 0xa4,
- 0x6f, 0xc9, 0x72, 0xee, 0x73, 0x43, 0x02, 0x8a, 0xef, 0xbc, 0x05, 0x98, 0x3a, 0x00,
- 0x47, 0x44, 0x56, 0x41, 0x01, 0x3a, 0x00, 0x47, 0x44, 0x57, 0x58, 0x2d, 0xa5, 0x01,
- 0x01, 0x03, 0x27, 0x04, 0x81, 0x02, 0x20, 0x06, 0x21, 0x58, 0x20, 0x96, 0x6d, 0x96,
- 0x42, 0xda, 0x64, 0x51, 0xad, 0xfa, 0x00, 0xbc, 0xbc, 0x95, 0x8a, 0xb0, 0xb9, 0x76,
- 0x01, 0xe6, 0xbd, 0xc0, 0x26, 0x79, 0x26, 0xfc, 0x0f, 0x1d, 0x87, 0x65, 0xf1, 0xf3,
- 0x99, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x40, 0x10, 0x7f, 0x77, 0xad,
- 0x70, 0xbd, 0x52, 0x81, 0x28, 0x8d, 0x24, 0x81, 0xb4, 0x3f, 0x21, 0x68, 0x9f, 0xc3,
- 0x80, 0x68, 0x86, 0x55, 0xfb, 0x2e, 0x6d, 0x96, 0xe1, 0xe1, 0xb7, 0x28, 0x8d, 0x63,
- 0x85, 0xba, 0x2a, 0x01, 0x33, 0x87, 0x60, 0x63, 0xbb, 0x16, 0x3f, 0x2f, 0x3d, 0xf4,
- 0x2d, 0x48, 0x5b, 0x87, 0xed, 0xda, 0x34, 0xeb, 0x9c, 0x4d, 0x14, 0xac, 0x65, 0xf4,
- 0xfa, 0xef, 0x45, 0x0b, 0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x59, 0x01, 0x8f, 0xa9,
- 0x01, 0x78, 0x28, 0x32, 0x35, 0x39, 0x34, 0x38, 0x39, 0x65, 0x36, 0x39, 0x37, 0x34,
- 0x38, 0x37, 0x30, 0x35, 0x64, 0x65, 0x33, 0x65, 0x32, 0x66, 0x34, 0x34, 0x32, 0x36,
- 0x37, 0x65, 0x61, 0x34, 0x39, 0x33, 0x38, 0x66, 0x66, 0x36, 0x61, 0x35, 0x37, 0x32,
- 0x35, 0x02, 0x78, 0x28, 0x35, 0x64, 0x34, 0x65, 0x64, 0x37, 0x66, 0x34, 0x31, 0x37,
- 0x61, 0x39, 0x35, 0x34, 0x61, 0x31, 0x38, 0x31, 0x34, 0x30, 0x37, 0x62, 0x35, 0x38,
- 0x38, 0x35, 0x61, 0x66, 0x64, 0x37, 0x32, 0x61, 0x35, 0x62, 0x66, 0x34, 0x30, 0x64,
- 0x61, 0x36, 0x3a, 0x00, 0x47, 0x44, 0x50, 0x58, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x3a, 0x00, 0x47, 0x44, 0x53, 0x58, 0x1a, 0xa3, 0x3a, 0x00, 0x01,
- 0x11, 0x71, 0x67, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x3a, 0x00, 0x01, 0x11,
- 0x72, 0x0c, 0x3a, 0x00, 0x01, 0x11, 0x73, 0xf6, 0x3a, 0x00, 0x47, 0x44, 0x52, 0x58,
- 0x40, 0x26, 0x1a, 0xbd, 0x26, 0xd8, 0x37, 0x8f, 0x4a, 0xf2, 0x9e, 0x49, 0x4d, 0x93,
- 0x23, 0xc4, 0x6e, 0x02, 0xda, 0xe0, 0x00, 0x02, 0xe7, 0xed, 0x29, 0xdf, 0x2b, 0xb3,
- 0x69, 0xf3, 0x55, 0x0e, 0x4c, 0x22, 0xdc, 0xcf, 0xf5, 0x92, 0xc9, 0xfa, 0x78, 0x98,
- 0xf1, 0x0e, 0x55, 0x5f, 0xf4, 0x45, 0xed, 0xc0, 0x0a, 0x72, 0x2a, 0x7a, 0x3a, 0xd2,
- 0xb1, 0xf7, 0x76, 0xfe, 0x2a, 0x6b, 0x7b, 0x2a, 0x53, 0x3a, 0x00, 0x47, 0x44, 0x54,
- 0x58, 0x40, 0x04, 0x25, 0x5d, 0x60, 0x5f, 0x5c, 0x45, 0x0d, 0xf2, 0x9a, 0x6e, 0x99,
- 0x30, 0x03, 0xb8, 0xd6, 0xe1, 0x99, 0x71, 0x1b, 0xf8, 0x44, 0xfa, 0xb5, 0x31, 0x79,
- 0x1c, 0x37, 0x68, 0x4e, 0x1d, 0xc0, 0x24, 0x74, 0x68, 0xf8, 0x80, 0x20, 0x3e, 0x44,
- 0xb1, 0x43, 0xd2, 0x9c, 0xfc, 0x12, 0x9e, 0x77, 0x0a, 0xde, 0x29, 0x24, 0xff, 0x2e,
- 0xfa, 0xc7, 0x10, 0xd5, 0x73, 0xd4, 0xc6, 0xdf, 0x62, 0x9f, 0x3a, 0x00, 0x47, 0x44,
- 0x56, 0x41, 0x01, 0x3a, 0x00, 0x47, 0x44, 0x57, 0x58, 0x2d, 0xa5, 0x01, 0x01, 0x03,
- 0x27, 0x04, 0x81, 0x02, 0x20, 0x06, 0x21, 0x58, 0x20, 0xdb, 0xe7, 0x5b, 0x3f, 0xa3,
- 0x42, 0xb0, 0x9c, 0xf8, 0x40, 0x8c, 0xb0, 0x9c, 0xf0, 0x0a, 0xaf, 0xdf, 0x6f, 0xe5,
- 0x09, 0x21, 0x11, 0x92, 0xe1, 0xf8, 0xc5, 0x09, 0x02, 0x3d, 0x1f, 0xb7, 0xc5, 0x3a,
- 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x40, 0xc4, 0xc1, 0xd7, 0x1c, 0x2d, 0x26,
- 0x89, 0x22, 0xcf, 0xa6, 0x99, 0x77, 0x30, 0x84, 0x86, 0x27, 0x59, 0x8f, 0xd8, 0x08,
- 0x75, 0xe0, 0xb2, 0xef, 0xf9, 0xfa, 0xa5, 0x40, 0x8c, 0xd3, 0xeb, 0xbb, 0xda, 0xf2,
- 0xc8, 0xae, 0x41, 0x22, 0x50, 0x9c, 0xe8, 0xb2, 0x9c, 0x9b, 0x3f, 0x8a, 0x78, 0x76,
- 0xab, 0xd0, 0xbe, 0xfc, 0xe4, 0x79, 0xcb, 0x1b, 0x2b, 0xaa, 0x4d, 0xdd, 0x15, 0x61,
- 0x42, 0x06, 0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x59, 0x01, 0x8d, 0xa9, 0x01, 0x78,
- 0x28, 0x35, 0x64, 0x34, 0x65, 0x64, 0x37, 0x66, 0x34, 0x31, 0x37, 0x61, 0x39, 0x35,
- 0x34, 0x61, 0x31, 0x38, 0x31, 0x34, 0x30, 0x37, 0x62, 0x35, 0x38, 0x38, 0x35, 0x61,
- 0x66, 0x64, 0x37, 0x32, 0x61, 0x35, 0x62, 0x66, 0x34, 0x30, 0x64, 0x61, 0x36, 0x02,
- 0x78, 0x28, 0x36, 0x39, 0x62, 0x31, 0x37, 0x36, 0x37, 0x35, 0x38, 0x61, 0x36, 0x66,
- 0x34, 0x34, 0x62, 0x35, 0x65, 0x38, 0x39, 0x39, 0x63, 0x64, 0x65, 0x33, 0x63, 0x66,
- 0x34, 0x35, 0x31, 0x39, 0x61, 0x39, 0x33, 0x35, 0x62, 0x63, 0x39, 0x66, 0x65, 0x34,
- 0x3a, 0x00, 0x47, 0x44, 0x50, 0x58, 0x40, 0x31, 0x0d, 0x31, 0xfa, 0x78, 0x58, 0x33,
- 0xf2, 0xf8, 0x58, 0x6b, 0xe9, 0x68, 0x32, 0x44, 0xd0, 0xfc, 0x2d, 0xe1, 0xfc, 0xe1,
- 0xc2, 0x4e, 0x2b, 0xa8, 0x2c, 0xa1, 0xc1, 0x48, 0xc6, 0xaa, 0x91, 0x89, 0x4f, 0xb7,
- 0x9c, 0x40, 0x74, 0x21, 0x36, 0x31, 0x45, 0x09, 0xdf, 0x0c, 0xb4, 0xf9, 0x9a, 0x59,
- 0xae, 0x4f, 0x21, 0x10, 0xc1, 0x38, 0xa8, 0xa2, 0xbe, 0xc6, 0x36, 0xf0, 0x56, 0x58,
- 0xdb, 0x3a, 0x00, 0x47, 0x44, 0x53, 0x58, 0x18, 0xa2, 0x3a, 0x00, 0x01, 0x11, 0x71,
- 0x6b, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x31, 0x3a, 0x00,
- 0x01, 0x11, 0x73, 0xf6, 0x3a, 0x00, 0x47, 0x44, 0x52, 0x58, 0x40, 0xce, 0x8a, 0x30,
- 0x4e, 0x31, 0x53, 0xea, 0xdd, 0x2f, 0xbd, 0x15, 0xbc, 0x6b, 0x0f, 0xe7, 0x43, 0x50,
- 0xef, 0x65, 0xec, 0x4e, 0x21, 0x64, 0x6e, 0x41, 0x22, 0xac, 0x87, 0xda, 0xf1, 0xf2,
- 0x80, 0xc6, 0x8a, 0xd8, 0x7b, 0xe8, 0xe2, 0x9b, 0x87, 0x21, 0x5e, 0x26, 0x23, 0x11,
- 0x89, 0x86, 0x57, 0x2d, 0x47, 0x73, 0x3f, 0x47, 0x87, 0xfa, 0x58, 0x5c, 0x78, 0x7b,
- 0xa3, 0xfc, 0x2b, 0x6c, 0xed, 0x3a, 0x00, 0x47, 0x44, 0x54, 0x58, 0x40, 0xd8, 0x40,
- 0xa0, 0x60, 0x45, 0x28, 0x5d, 0xd4, 0xc1, 0x08, 0x3c, 0xbc, 0x91, 0xf4, 0xa6, 0xa4,
- 0xde, 0xd3, 0x3d, 0xbb, 0x24, 0x46, 0xa3, 0x58, 0x49, 0x57, 0x4d, 0x2e, 0x6d, 0x7a,
- 0x78, 0x4b, 0x9d, 0x28, 0x9a, 0x4e, 0xf1, 0x23, 0x06, 0x35, 0xff, 0x8e, 0x1e, 0xb3,
- 0x02, 0x63, 0x62, 0x9a, 0x50, 0x6d, 0x18, 0x70, 0x8e, 0xe3, 0x2e, 0x29, 0xb4, 0x22,
- 0x71, 0x31, 0x39, 0x65, 0xd5, 0xb5, 0x3a, 0x00, 0x47, 0x44, 0x56, 0x41, 0x01, 0x3a,
- 0x00, 0x47, 0x44, 0x57, 0x58, 0x2d, 0xa5, 0x01, 0x01, 0x03, 0x27, 0x04, 0x81, 0x02,
- 0x20, 0x06, 0x21, 0x58, 0x20, 0x51, 0x3c, 0x4b, 0x56, 0x0b, 0x49, 0x0b, 0xee, 0xc5,
- 0x71, 0xd4, 0xe7, 0xbc, 0x44, 0x27, 0x4f, 0x4e, 0x67, 0xfc, 0x3a, 0xb9, 0x47, 0x8c,
- 0x6f, 0x24, 0x29, 0xf8, 0xb8, 0x2f, 0xa7, 0xb3, 0x4d, 0x3a, 0x00, 0x47, 0x44, 0x58,
- 0x41, 0x20, 0x58, 0x40, 0x4e, 0x6d, 0x0e, 0x2b, 0x1d, 0x44, 0x99, 0xb6, 0x63, 0x07,
- 0x86, 0x1a, 0xce, 0x4b, 0xdc, 0xd1, 0x3a, 0xdc, 0xbf, 0xaa, 0xb3, 0x06, 0xd9, 0xb5,
- 0x5c, 0x75, 0xf0, 0x14, 0x63, 0xa9, 0x1e, 0x7c, 0x56, 0x62, 0x2c, 0xa5, 0xda, 0xc9,
- 0x81, 0xcb, 0x3d, 0x63, 0x32, 0x6b, 0x76, 0x81, 0xd2, 0x93, 0xeb, 0xac, 0xfe, 0x0c,
- 0x87, 0x66, 0x9e, 0x87, 0x82, 0xb4, 0x81, 0x6e, 0x33, 0xf1, 0x08, 0x01, 0x84, 0x43,
- 0xa1, 0x01, 0x27, 0xa0, 0x59, 0x01, 0x8d, 0xa9, 0x01, 0x78, 0x28, 0x36, 0x39, 0x62,
- 0x31, 0x37, 0x36, 0x37, 0x35, 0x38, 0x61, 0x36, 0x66, 0x34, 0x34, 0x62, 0x35, 0x65,
- 0x38, 0x39, 0x39, 0x63, 0x64, 0x65, 0x33, 0x63, 0x66, 0x34, 0x35, 0x31, 0x39, 0x61,
- 0x39, 0x33, 0x35, 0x62, 0x63, 0x39, 0x66, 0x65, 0x34, 0x02, 0x78, 0x28, 0x32, 0x39,
- 0x65, 0x34, 0x62, 0x61, 0x63, 0x33, 0x30, 0x31, 0x65, 0x66, 0x36, 0x35, 0x61, 0x38,
- 0x31, 0x31, 0x62, 0x39, 0x39, 0x62, 0x30, 0x33, 0x64, 0x65, 0x39, 0x35, 0x34, 0x65,
- 0x61, 0x37, 0x36, 0x61, 0x38, 0x39, 0x31, 0x37, 0x38, 0x35, 0x3a, 0x00, 0x47, 0x44,
- 0x50, 0x58, 0x40, 0xa4, 0x03, 0xe3, 0xde, 0x44, 0x96, 0xed, 0x31, 0x41, 0xa0, 0xba,
- 0x59, 0xee, 0x2b, 0x03, 0x65, 0xcb, 0x63, 0x14, 0x78, 0xbe, 0xad, 0x24, 0x33, 0xb8,
- 0x6b, 0x52, 0xd8, 0xab, 0xd5, 0x79, 0x84, 0x98, 0x6c, 0xc2, 0x66, 0xeb, 0x6c, 0x24,
- 0xa6, 0xfa, 0x32, 0xa8, 0x16, 0xb8, 0x64, 0x37, 0x2b, 0xd4, 0xc0, 0xc4, 0xc2, 0x63,
- 0x25, 0x10, 0xce, 0x47, 0xe3, 0x49, 0xad, 0x41, 0xf5, 0xc8, 0xf6, 0x3a, 0x00, 0x47,
- 0x44, 0x53, 0x58, 0x18, 0xa2, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x6b, 0x63, 0x6f, 0x6d,
- 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x32, 0x3a, 0x00, 0x01, 0x11, 0x73, 0xf6,
- 0x3a, 0x00, 0x47, 0x44, 0x52, 0x58, 0x40, 0xc7, 0x50, 0x09, 0xd0, 0xe0, 0xdd, 0x80,
- 0x77, 0xae, 0xa7, 0xc8, 0x88, 0x1e, 0x88, 0xd0, 0xc7, 0x0d, 0x7c, 0x49, 0xc5, 0xb5,
- 0x64, 0x32, 0x28, 0x2c, 0x48, 0x94, 0xc0, 0xd6, 0x7d, 0x9c, 0x86, 0xda, 0xf7, 0x98,
- 0xc7, 0xae, 0xa4, 0x0e, 0x61, 0xc8, 0xb0, 0x8b, 0x8a, 0xe4, 0xad, 0xcf, 0xcf, 0x6d,
- 0x60, 0x60, 0x31, 0xdd, 0xa7, 0x24, 0x9b, 0x27, 0x16, 0x31, 0x90, 0x80, 0x70, 0xc3,
- 0xba, 0x3a, 0x00, 0x47, 0x44, 0x54, 0x58, 0x40, 0xf8, 0x86, 0xc6, 0x94, 0xf9, 0x3f,
- 0x66, 0x3c, 0x43, 0x01, 0x29, 0x27, 0x8d, 0x3c, 0xb2, 0x11, 0xf2, 0x04, 0xb6, 0x67,
- 0x4f, 0x5f, 0x90, 0xcb, 0xc6, 0x73, 0xe6, 0x25, 0x14, 0x63, 0xa7, 0x95, 0x11, 0x0e,
- 0xa0, 0x1d, 0x3f, 0x6a, 0x58, 0x0a, 0x53, 0xaa, 0x68, 0x3b, 0x92, 0x64, 0x2b, 0x2e,
- 0x79, 0x80, 0x70, 0x0e, 0x41, 0xf5, 0xe9, 0x2a, 0x36, 0x0a, 0xa4, 0xe8, 0xb4, 0xe5,
- 0xdd, 0xa6, 0x3a, 0x00, 0x47, 0x44, 0x56, 0x41, 0x01, 0x3a, 0x00, 0x47, 0x44, 0x57,
- 0x58, 0x2d, 0xa5, 0x01, 0x01, 0x03, 0x27, 0x04, 0x81, 0x02, 0x20, 0x06, 0x21, 0x58,
- 0x20, 0x9e, 0x04, 0x11, 0x24, 0x34, 0xba, 0x40, 0xed, 0x86, 0xe9, 0x48, 0x70, 0x3b,
- 0xe7, 0x76, 0xfa, 0xc5, 0xf6, 0x6d, 0xab, 0x86, 0x12, 0x00, 0xbe, 0xc7, 0x00, 0x69,
- 0x0e, 0x97, 0x97, 0xa6, 0x12, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x40,
- 0xb7, 0x31, 0xd5, 0x4c, 0x7d, 0xf5, 0xd7, 0xb8, 0xb4, 0x4f, 0x93, 0x47, 0x2c, 0x3d,
- 0x50, 0xcc, 0xad, 0x28, 0x23, 0x68, 0xcf, 0xc2, 0x90, 0xd7, 0x02, 0x00, 0xd8, 0xf1,
- 0x00, 0x14, 0x03, 0x90, 0x9e, 0x0b, 0x91, 0xa7, 0x22, 0x28, 0xfe, 0x55, 0x42, 0x30,
- 0x93, 0x05, 0x66, 0xcd, 0xce, 0xb8, 0x48, 0x07, 0x56, 0x54, 0x67, 0xa5, 0xd7, 0xe3,
- 0x16, 0xd6, 0x75, 0x7c, 0x94, 0x98, 0x1b, 0x0b, 0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0,
- 0x59, 0x01, 0x8d, 0xa9, 0x01, 0x78, 0x28, 0x32, 0x39, 0x65, 0x34, 0x62, 0x61, 0x63,
- 0x33, 0x30, 0x31, 0x65, 0x66, 0x36, 0x35, 0x61, 0x38, 0x31, 0x31, 0x62, 0x39, 0x39,
- 0x62, 0x30, 0x33, 0x64, 0x65, 0x39, 0x35, 0x34, 0x65, 0x61, 0x37, 0x36, 0x61, 0x38,
- 0x39, 0x31, 0x37, 0x38, 0x35, 0x02, 0x78, 0x28, 0x31, 0x38, 0x37, 0x36, 0x63, 0x61,
- 0x63, 0x34, 0x32, 0x33, 0x39, 0x35, 0x37, 0x66, 0x33, 0x62, 0x66, 0x62, 0x32, 0x62,
- 0x32, 0x63, 0x39, 0x33, 0x37, 0x64, 0x31, 0x34, 0x62, 0x62, 0x38, 0x30, 0x64, 0x30,
- 0x36, 0x37, 0x33, 0x65, 0x66, 0x66, 0x3a, 0x00, 0x47, 0x44, 0x50, 0x58, 0x40, 0xf4,
- 0x7d, 0x11, 0x21, 0xc1, 0x19, 0x57, 0x23, 0x08, 0x6e, 0x5f, 0xe4, 0x55, 0xc5, 0x08,
- 0x16, 0x40, 0x5f, 0x2a, 0x6f, 0x04, 0x1e, 0x6f, 0x22, 0xde, 0x53, 0xbd, 0x37, 0xe2,
- 0xfb, 0xb4, 0x0b, 0x65, 0xf4, 0xdc, 0xc9, 0xf4, 0xce, 0x2d, 0x82, 0x2a, 0xbc, 0xaf,
- 0x37, 0x80, 0x0b, 0x7f, 0xff, 0x3a, 0x98, 0x9c, 0xa7, 0x70, 0x4f, 0xbc, 0x59, 0x4f,
- 0x4e, 0xb1, 0x6d, 0xdf, 0x60, 0x39, 0x11, 0x3a, 0x00, 0x47, 0x44, 0x53, 0x58, 0x18,
- 0xa2, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x6b, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65,
- 0x6e, 0x74, 0x20, 0x33, 0x3a, 0x00, 0x01, 0x11, 0x73, 0xf6, 0x3a, 0x00, 0x47, 0x44,
- 0x52, 0x58, 0x40, 0xa4, 0xd5, 0x6f, 0xc8, 0xd6, 0xc7, 0xe4, 0x22, 0xb4, 0x7a, 0x26,
- 0x49, 0xd5, 0xb4, 0xc1, 0xc6, 0x1b, 0xfa, 0x14, 0x8c, 0x49, 0x72, 0x2f, 0xfe, 0xbc,
- 0xc1, 0xc8, 0xc6, 0x65, 0x62, 0x86, 0xf7, 0xf2, 0x74, 0x45, 0x9b, 0x1a, 0xa0, 0x2b,
- 0xc4, 0x27, 0x13, 0xc5, 0xc3, 0xe5, 0x28, 0xc2, 0x16, 0xcd, 0x90, 0x6d, 0xa0, 0xf7,
- 0x27, 0x04, 0xa8, 0xa2, 0x62, 0xaa, 0x2c, 0x0c, 0x75, 0xd5, 0x9d, 0x3a, 0x00, 0x47,
- 0x44, 0x54, 0x58, 0x40, 0x1d, 0x92, 0x34, 0xfb, 0xfe, 0x74, 0xb7, 0xce, 0x3a, 0x95,
- 0x45, 0xe5, 0x3e, 0x1f, 0x5f, 0x18, 0x53, 0x5f, 0xe1, 0x85, 0xb0, 0x1d, 0xe3, 0x8d,
- 0x53, 0x77, 0xdc, 0x86, 0x32, 0x3d, 0x9b, 0xf9, 0xa5, 0x51, 0x17, 0x51, 0x9a, 0xd8,
- 0xa6, 0x7d, 0x45, 0x98, 0x47, 0xa2, 0x73, 0x54, 0x66, 0x28, 0x66, 0x92, 0x1d, 0x28,
- 0x8a, 0xe7, 0x5d, 0xb8, 0x96, 0x4b, 0x6a, 0x9d, 0xee, 0xc2, 0xe9, 0x20, 0x3a, 0x00,
- 0x47, 0x44, 0x56, 0x41, 0x01, 0x3a, 0x00, 0x47, 0x44, 0x57, 0x58, 0x2d, 0xa5, 0x01,
- 0x01, 0x03, 0x27, 0x04, 0x81, 0x02, 0x20, 0x06, 0x21, 0x58, 0x20, 0x4d, 0xf5, 0x61,
- 0x1e, 0xa6, 0x64, 0x74, 0x0b, 0x6c, 0x99, 0x8b, 0x6d, 0x34, 0x42, 0x21, 0xdd, 0x82,
- 0x26, 0x13, 0xb4, 0xf0, 0xbc, 0x9a, 0x0b, 0xf6, 0x56, 0xbd, 0x5d, 0xea, 0xd5, 0x07,
- 0x7a, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x40, 0x40, 0x4d, 0x09, 0x0d,
- 0x80, 0xba, 0x12, 0x94, 0x05, 0xfb, 0x1a, 0x23, 0xa3, 0xcb, 0x28, 0x6f, 0xd7, 0x29,
- 0x95, 0xda, 0x83, 0x07, 0x3c, 0xbe, 0x7c, 0x37, 0xeb, 0x9c, 0xb2, 0x77, 0x10, 0x3f,
- 0x6a, 0x41, 0x80, 0xce, 0x56, 0xb7, 0x55, 0x22, 0x81, 0x77, 0x2d, 0x3c, 0xf8, 0x16,
- 0x38, 0x49, 0xcc, 0x9a, 0xe8, 0x3a, 0x03, 0x33, 0x4c, 0xe6, 0x87, 0x72, 0xf6, 0x5a,
- 0x4a, 0x3f, 0x4e, 0x0a,
- ],
- )
- .unwrap()
- }
-}
diff --git a/diced/src/lib_vendor.rs b/diced/src/lib_vendor.rs
deleted file mode 100644
index a04bb80..0000000
--- a/diced/src/lib_vendor.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// 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.
-
-//! This crate implements the android.hardware.security.dice.IDiceDevice interface
-//! and provides support for implementing a DICE HAL service.
-
-mod error_vendor;
-pub mod hal_node;
-pub use diced_open_dice as dice;
diff --git a/diced/src/sample_inputs.rs b/diced/src/sample_inputs.rs
index 6ad8ca9..19200a5 100644
--- a/diced/src/sample_inputs.rs
+++ b/diced/src/sample_inputs.rs
@@ -15,22 +15,65 @@
//! This module provides a set of sample input values for a DICE chain, a sample UDS,
//! as well as tuple of CDIs and BCC derived thereof.
-use android_hardware_security_dice::aidl::android::hardware::security::dice::{
- Config::Config as BinderConfig, InputValues::InputValues as BinderInputValues, Mode::Mode,
-};
use anyhow::{anyhow, Context, Result};
-use diced_open_dice as dice;
-use diced_open_dice::DiceArtifacts;
-use diced_utils::{cbor, to_dice_input_values};
+use diced_open_dice::{
+ derive_cdi_private_key_seed, keypair_from_seed, retry_bcc_format_config_descriptor,
+ retry_bcc_main_flow, retry_dice_main_flow, Config, DiceArtifacts, DiceMode, InputValues,
+ OwnedDiceArtifacts, CDI_SIZE, HASH_SIZE, HIDDEN_SIZE,
+};
+use diced_utils::cbor;
use std::ffi::CStr;
use std::io::Write;
/// Sample UDS used to perform the root dice flow by `make_sample_bcc_and_cdis`.
-pub static UDS: &[u8; dice::CDI_SIZE] = &[
+pub const UDS: &[u8; CDI_SIZE] = &[
0x65, 0x4f, 0xab, 0xa9, 0xa5, 0xad, 0x0f, 0x5e, 0x15, 0xc3, 0x12, 0xf7, 0x77, 0x45, 0xfa, 0x55,
0x18, 0x6a, 0xa6, 0x34, 0xb6, 0x7c, 0x82, 0x7b, 0x89, 0x4c, 0xc5, 0x52, 0xd3, 0x27, 0x35, 0x8e,
];
+const CODE_HASH_ABL: [u8; HASH_SIZE] = [
+ 0x16, 0x48, 0xf2, 0x55, 0x53, 0x23, 0xdd, 0x15, 0x2e, 0x83, 0x38, 0xc3, 0x64, 0x38, 0x63, 0x26,
+ 0x0f, 0xcf, 0x5b, 0xd1, 0x3a, 0xd3, 0x40, 0x3e, 0x23, 0xf8, 0x34, 0x4c, 0x6d, 0xa2, 0xbe, 0x25,
+ 0x1c, 0xb0, 0x29, 0xe8, 0xc3, 0xfb, 0xb8, 0x80, 0xdc, 0xb1, 0xd2, 0xb3, 0x91, 0x4d, 0xd3, 0xfb,
+ 0x01, 0x0f, 0xe4, 0xe9, 0x46, 0xa2, 0xc0, 0x26, 0x57, 0x5a, 0xba, 0x30, 0xf7, 0x15, 0x98, 0x14,
+];
+const AUTHORITY_HASH_ABL: [u8; HASH_SIZE] = [
+ 0xf9, 0x00, 0x9d, 0xc2, 0x59, 0x09, 0xe0, 0xb6, 0x98, 0xbd, 0xe3, 0x97, 0x4a, 0xcb, 0x3c, 0xe7,
+ 0x6b, 0x24, 0xc3, 0xe4, 0x98, 0xdd, 0xa9, 0x6a, 0x41, 0x59, 0x15, 0xb1, 0x23, 0xe6, 0xc8, 0xdf,
+ 0xfb, 0x52, 0xb4, 0x52, 0xc1, 0xb9, 0x61, 0xdd, 0xbc, 0x5b, 0x37, 0x0e, 0x12, 0x12, 0xb2, 0xfd,
+ 0xc1, 0x09, 0xb0, 0xcf, 0x33, 0x81, 0x4c, 0xc6, 0x29, 0x1b, 0x99, 0xea, 0xae, 0xfd, 0xaa, 0x0d,
+];
+const HIDDEN_ABL: [u8; HIDDEN_SIZE] = [
+ 0xa2, 0x01, 0xd0, 0xc0, 0xaa, 0x75, 0x3c, 0x06, 0x43, 0x98, 0x6c, 0xc3, 0x5a, 0xb5, 0x5f, 0x1f,
+ 0x0f, 0x92, 0x44, 0x3b, 0x0e, 0xd4, 0x29, 0x75, 0xe3, 0xdb, 0x36, 0xda, 0xc8, 0x07, 0x97, 0x4d,
+ 0xff, 0xbc, 0x6a, 0xa4, 0x8a, 0xef, 0xc4, 0x7f, 0xf8, 0x61, 0x7d, 0x51, 0x4d, 0x2f, 0xdf, 0x7e,
+ 0x8c, 0x3d, 0xa3, 0xfc, 0x63, 0xd4, 0xd4, 0x74, 0x8a, 0xc4, 0x14, 0x45, 0x83, 0x6b, 0x12, 0x7e,
+];
+const CODE_HASH_AVB: [u8; HASH_SIZE] = [
+ 0xa4, 0x0c, 0xcb, 0xc1, 0xbf, 0xfa, 0xcc, 0xfd, 0xeb, 0xf4, 0xfc, 0x43, 0x83, 0x7f, 0x46, 0x8d,
+ 0xd8, 0xd8, 0x14, 0xc1, 0x96, 0x14, 0x1f, 0x6e, 0xb3, 0xa0, 0xd9, 0x56, 0xb3, 0xbf, 0x2f, 0xfa,
+ 0x88, 0x70, 0x11, 0x07, 0x39, 0xa4, 0xd2, 0xa9, 0x6b, 0x18, 0x28, 0xe8, 0x29, 0x20, 0x49, 0x0f,
+ 0xbb, 0x8d, 0x08, 0x8c, 0xc6, 0x54, 0xe9, 0x71, 0xd2, 0x7e, 0xa4, 0xfe, 0x58, 0x7f, 0xd3, 0xc7,
+];
+const AUTHORITY_HASH_AVB: [u8; HASH_SIZE] = [
+ 0xb2, 0x69, 0x05, 0x48, 0x56, 0xb5, 0xfa, 0x55, 0x6f, 0xac, 0x56, 0xd9, 0x02, 0x35, 0x2b, 0xaa,
+ 0x4c, 0xba, 0x28, 0xdd, 0x82, 0x3a, 0x86, 0xf5, 0xd4, 0xc2, 0xf1, 0xf9, 0x35, 0x7d, 0xe4, 0x43,
+ 0x13, 0xbf, 0xfe, 0xd3, 0x36, 0xd8, 0x1c, 0x12, 0x78, 0x5c, 0x9c, 0x3e, 0xf6, 0x66, 0xef, 0xab,
+ 0x3d, 0x0f, 0x89, 0xa4, 0x6f, 0xc9, 0x72, 0xee, 0x73, 0x43, 0x02, 0x8a, 0xef, 0xbc, 0x05, 0x98,
+];
+const HIDDEN_AVB: [u8; HIDDEN_SIZE] = [
+ 0x5b, 0x3f, 0xc9, 0x6b, 0xe3, 0x95, 0x59, 0x40, 0x5e, 0x64, 0xe5, 0x64, 0x3f, 0xfd, 0x21, 0x09,
+ 0x9d, 0xf3, 0xcd, 0xc7, 0xa4, 0x2a, 0xe2, 0x97, 0xdd, 0xe2, 0x4f, 0xb0, 0x7d, 0x7e, 0xf5, 0x8e,
+ 0xd6, 0x4d, 0x84, 0x25, 0x54, 0x41, 0x3f, 0x8f, 0x78, 0x64, 0x1a, 0x51, 0x27, 0x9d, 0x55, 0x8a,
+ 0xe9, 0x90, 0x35, 0xab, 0x39, 0x80, 0x4b, 0x94, 0x40, 0x84, 0xa2, 0xfd, 0x73, 0xeb, 0x35, 0x7a,
+];
+const AUTHORITY_HASH_ANDROID: [u8; HASH_SIZE] = [
+ 0x04, 0x25, 0x5d, 0x60, 0x5f, 0x5c, 0x45, 0x0d, 0xf2, 0x9a, 0x6e, 0x99, 0x30, 0x03, 0xb8, 0xd6,
+ 0xe1, 0x99, 0x71, 0x1b, 0xf8, 0x44, 0xfa, 0xb5, 0x31, 0x79, 0x1c, 0x37, 0x68, 0x4e, 0x1d, 0xc0,
+ 0x24, 0x74, 0x68, 0xf8, 0x80, 0x20, 0x3e, 0x44, 0xb1, 0x43, 0xd2, 0x9c, 0xfc, 0x12, 0x9e, 0x77,
+ 0x0a, 0xde, 0x29, 0x24, 0xff, 0x2e, 0xfa, 0xc7, 0x10, 0xd5, 0x73, 0xd4, 0xc6, 0xdf, 0x62, 0x9f,
+];
+
fn encode_pub_key_ed25519(pub_key: &[u8], stream: &mut dyn Write) -> Result<()> {
cbor::encode_header(5 /* CBOR MAP */, 5, stream)
.context("In encode_pub_key_ed25519: Trying to encode map header.")?;
@@ -62,164 +105,85 @@
Ok(())
}
-/// Derives a tuple of (CDI_ATTEST, CDI_SEAL, BCC) derived of the vector of input values returned
-/// by `get_input_values_vector`.
-pub fn make_sample_bcc_and_cdis() -> Result<dice::OwnedDiceArtifacts> {
- let private_key_seed = dice::derive_cdi_private_key_seed(UDS)
+/// Makes a DICE chain (BCC) from the sample input.
+///
+/// The DICE chain is of the following format:
+/// public key derived from UDS -> ABL certificate -> AVB certificate -> Android certificate
+pub fn make_sample_bcc_and_cdis() -> Result<OwnedDiceArtifacts> {
+ let private_key_seed = derive_cdi_private_key_seed(UDS)
.context("In make_sample_bcc_and_cdis: Trying to derive private key seed.")?;
- let (public_key, _) = dice::keypair_from_seed(private_key_seed.as_array())
+ // Sets the root public key in DICE chain (BCC).
+ let (public_key, _) = keypair_from_seed(private_key_seed.as_array())
.context("In make_sample_bcc_and_cids: Failed to generate key pair.")?;
-
- let input_values_vector = get_input_values_vector();
-
- let (cdi_values, mut cert) =
- dice::retry_dice_main_flow(UDS, UDS, &to_dice_input_values(&input_values_vector[0]))
- .context("In make_sample_bcc_and_cdis: Trying to run first main flow.")?;
-
let mut bcc: Vec<u8> = vec![];
-
cbor::encode_header(4 /* CBOR ARRAY */, 2, &mut bcc)
.context("In make_sample_bcc_and_cdis: Trying to encode array header.")?;
encode_pub_key_ed25519(&public_key, &mut bcc)
.context("In make_sample_bcc_and_cdis: Trying encode pub_key.")?;
+ // Appends ABL certificate to DICE chain.
+ let config_descriptor = retry_bcc_format_config_descriptor(
+ Some(CStr::from_bytes_with_nul(b"ABL\0").unwrap()),
+ Some(1), // version
+ true,
+ )?;
+ let input_values = InputValues::new(
+ CODE_HASH_ABL,
+ Config::Descriptor(config_descriptor.as_slice()),
+ AUTHORITY_HASH_ABL,
+ DiceMode::kDiceModeNormal,
+ HIDDEN_ABL,
+ );
+ let (cdi_values, mut cert) = retry_dice_main_flow(UDS, UDS, &input_values)
+ .context("In make_sample_bcc_and_cdis: Trying to run first main flow.")?;
bcc.append(&mut cert);
- let dice_artifacts = dice::retry_bcc_main_flow(
- &cdi_values.cdi_attest,
- &cdi_values.cdi_seal,
- &bcc,
- &to_dice_input_values(&input_values_vector[1]),
- )
- .context("In make_sample_bcc_and_cdis: Trying to run first bcc main flow.")?;
- dice::retry_bcc_main_flow(
+ // Appends AVB certificate to DICE chain.
+ let config_descriptor = retry_bcc_format_config_descriptor(
+ Some(CStr::from_bytes_with_nul(b"AVB\0").unwrap()),
+ Some(1), // version
+ true,
+ )?;
+ let input_values = InputValues::new(
+ CODE_HASH_AVB,
+ Config::Descriptor(config_descriptor.as_slice()),
+ AUTHORITY_HASH_AVB,
+ DiceMode::kDiceModeNormal,
+ HIDDEN_AVB,
+ );
+ let dice_artifacts =
+ retry_bcc_main_flow(&cdi_values.cdi_attest, &cdi_values.cdi_seal, &bcc, &input_values)
+ .context("In make_sample_bcc_and_cdis: Trying to run first bcc main flow.")?;
+
+ // Appends Android certificate to DICE chain.
+ let config_descriptor = retry_bcc_format_config_descriptor(
+ Some(CStr::from_bytes_with_nul(b"Android\0").unwrap()),
+ Some(12), // version
+ true,
+ )?;
+ let input_values = InputValues::new(
+ [0u8; HASH_SIZE], // code_hash
+ Config::Descriptor(config_descriptor.as_slice()),
+ AUTHORITY_HASH_ANDROID,
+ DiceMode::kDiceModeNormal,
+ [0u8; HIDDEN_SIZE], // hidden
+ );
+ retry_bcc_main_flow(
dice_artifacts.cdi_attest(),
dice_artifacts.cdi_seal(),
dice_artifacts.bcc().ok_or_else(|| anyhow!("bcc is none"))?,
- &to_dice_input_values(&input_values_vector[2]),
+ &input_values,
)
.context("In make_sample_bcc_and_cdis: Trying to run second bcc main flow.")
}
-fn make_input_values(
- code_hash: dice::Hash,
- authority_hash: dice::Hash,
- config_name: &CStr,
- config_version: u64,
- config_resettable: bool,
- mode: Mode,
- hidden: dice::Hidden,
-) -> Result<BinderInputValues> {
- Ok(BinderInputValues {
- codeHash: code_hash,
- config: BinderConfig {
- desc: dice::retry_bcc_format_config_descriptor(
- Some(config_name),
- Some(config_version),
- config_resettable,
- )
- .context("In make_input_values: Failed to format config descriptor.")?,
- },
- authorityHash: authority_hash,
- authorityDescriptor: None,
- hidden,
- mode,
- })
-}
-
-/// Returns a set of sample input for a dice chain comprising the android boot loader ABL,
-/// the verified boot information AVB, and Android S.
-pub fn get_input_values_vector() -> Vec<BinderInputValues> {
- const CODE_HASH1: [u8; dice::HASH_SIZE] = [
- 0x16, 0x48, 0xf2, 0x55, 0x53, 0x23, 0xdd, 0x15, 0x2e, 0x83, 0x38, 0xc3, 0x64, 0x38, 0x63,
- 0x26, 0x0f, 0xcf, 0x5b, 0xd1, 0x3a, 0xd3, 0x40, 0x3e, 0x23, 0xf8, 0x34, 0x4c, 0x6d, 0xa2,
- 0xbe, 0x25, 0x1c, 0xb0, 0x29, 0xe8, 0xc3, 0xfb, 0xb8, 0x80, 0xdc, 0xb1, 0xd2, 0xb3, 0x91,
- 0x4d, 0xd3, 0xfb, 0x01, 0x0f, 0xe4, 0xe9, 0x46, 0xa2, 0xc0, 0x26, 0x57, 0x5a, 0xba, 0x30,
- 0xf7, 0x15, 0x98, 0x14,
- ];
- const AUTHORITY_HASH1: [u8; dice::HASH_SIZE] = [
- 0xf9, 0x00, 0x9d, 0xc2, 0x59, 0x09, 0xe0, 0xb6, 0x98, 0xbd, 0xe3, 0x97, 0x4a, 0xcb, 0x3c,
- 0xe7, 0x6b, 0x24, 0xc3, 0xe4, 0x98, 0xdd, 0xa9, 0x6a, 0x41, 0x59, 0x15, 0xb1, 0x23, 0xe6,
- 0xc8, 0xdf, 0xfb, 0x52, 0xb4, 0x52, 0xc1, 0xb9, 0x61, 0xdd, 0xbc, 0x5b, 0x37, 0x0e, 0x12,
- 0x12, 0xb2, 0xfd, 0xc1, 0x09, 0xb0, 0xcf, 0x33, 0x81, 0x4c, 0xc6, 0x29, 0x1b, 0x99, 0xea,
- 0xae, 0xfd, 0xaa, 0x0d,
- ];
- const HIDDEN1: [u8; dice::HIDDEN_SIZE] = [
- 0xa2, 0x01, 0xd0, 0xc0, 0xaa, 0x75, 0x3c, 0x06, 0x43, 0x98, 0x6c, 0xc3, 0x5a, 0xb5, 0x5f,
- 0x1f, 0x0f, 0x92, 0x44, 0x3b, 0x0e, 0xd4, 0x29, 0x75, 0xe3, 0xdb, 0x36, 0xda, 0xc8, 0x07,
- 0x97, 0x4d, 0xff, 0xbc, 0x6a, 0xa4, 0x8a, 0xef, 0xc4, 0x7f, 0xf8, 0x61, 0x7d, 0x51, 0x4d,
- 0x2f, 0xdf, 0x7e, 0x8c, 0x3d, 0xa3, 0xfc, 0x63, 0xd4, 0xd4, 0x74, 0x8a, 0xc4, 0x14, 0x45,
- 0x83, 0x6b, 0x12, 0x7e,
- ];
- const CODE_HASH2: [u8; dice::HASH_SIZE] = [
- 0xa4, 0x0c, 0xcb, 0xc1, 0xbf, 0xfa, 0xcc, 0xfd, 0xeb, 0xf4, 0xfc, 0x43, 0x83, 0x7f, 0x46,
- 0x8d, 0xd8, 0xd8, 0x14, 0xc1, 0x96, 0x14, 0x1f, 0x6e, 0xb3, 0xa0, 0xd9, 0x56, 0xb3, 0xbf,
- 0x2f, 0xfa, 0x88, 0x70, 0x11, 0x07, 0x39, 0xa4, 0xd2, 0xa9, 0x6b, 0x18, 0x28, 0xe8, 0x29,
- 0x20, 0x49, 0x0f, 0xbb, 0x8d, 0x08, 0x8c, 0xc6, 0x54, 0xe9, 0x71, 0xd2, 0x7e, 0xa4, 0xfe,
- 0x58, 0x7f, 0xd3, 0xc7,
- ];
- const AUTHORITY_HASH2: [u8; dice::HASH_SIZE] = [
- 0xb2, 0x69, 0x05, 0x48, 0x56, 0xb5, 0xfa, 0x55, 0x6f, 0xac, 0x56, 0xd9, 0x02, 0x35, 0x2b,
- 0xaa, 0x4c, 0xba, 0x28, 0xdd, 0x82, 0x3a, 0x86, 0xf5, 0xd4, 0xc2, 0xf1, 0xf9, 0x35, 0x7d,
- 0xe4, 0x43, 0x13, 0xbf, 0xfe, 0xd3, 0x36, 0xd8, 0x1c, 0x12, 0x78, 0x5c, 0x9c, 0x3e, 0xf6,
- 0x66, 0xef, 0xab, 0x3d, 0x0f, 0x89, 0xa4, 0x6f, 0xc9, 0x72, 0xee, 0x73, 0x43, 0x02, 0x8a,
- 0xef, 0xbc, 0x05, 0x98,
- ];
- const HIDDEN2: [u8; dice::HIDDEN_SIZE] = [
- 0x5b, 0x3f, 0xc9, 0x6b, 0xe3, 0x95, 0x59, 0x40, 0x5e, 0x64, 0xe5, 0x64, 0x3f, 0xfd, 0x21,
- 0x09, 0x9d, 0xf3, 0xcd, 0xc7, 0xa4, 0x2a, 0xe2, 0x97, 0xdd, 0xe2, 0x4f, 0xb0, 0x7d, 0x7e,
- 0xf5, 0x8e, 0xd6, 0x4d, 0x84, 0x25, 0x54, 0x41, 0x3f, 0x8f, 0x78, 0x64, 0x1a, 0x51, 0x27,
- 0x9d, 0x55, 0x8a, 0xe9, 0x90, 0x35, 0xab, 0x39, 0x80, 0x4b, 0x94, 0x40, 0x84, 0xa2, 0xfd,
- 0x73, 0xeb, 0x35, 0x7a,
- ];
- const AUTHORITY_HASH3: [u8; dice::HASH_SIZE] = [
- 0x04, 0x25, 0x5d, 0x60, 0x5f, 0x5c, 0x45, 0x0d, 0xf2, 0x9a, 0x6e, 0x99, 0x30, 0x03, 0xb8,
- 0xd6, 0xe1, 0x99, 0x71, 0x1b, 0xf8, 0x44, 0xfa, 0xb5, 0x31, 0x79, 0x1c, 0x37, 0x68, 0x4e,
- 0x1d, 0xc0, 0x24, 0x74, 0x68, 0xf8, 0x80, 0x20, 0x3e, 0x44, 0xb1, 0x43, 0xd2, 0x9c, 0xfc,
- 0x12, 0x9e, 0x77, 0x0a, 0xde, 0x29, 0x24, 0xff, 0x2e, 0xfa, 0xc7, 0x10, 0xd5, 0x73, 0xd4,
- 0xc6, 0xdf, 0x62, 0x9f,
- ];
- vec![
- make_input_values(
- CODE_HASH1,
- AUTHORITY_HASH1,
- CStr::from_bytes_with_nul(b"ABL\0").unwrap(), // config name
- 1, // config version
- true, // resettable
- Mode::NORMAL,
- HIDDEN1,
- )
- .unwrap(),
- make_input_values(
- CODE_HASH2,
- AUTHORITY_HASH2,
- CStr::from_bytes_with_nul(b"AVB\0").unwrap(), // config name
- 1, // config version
- true, // resettable
- Mode::NORMAL,
- HIDDEN2,
- )
- .unwrap(),
- make_input_values(
- [0; dice::HASH_SIZE], // code hash
- AUTHORITY_HASH3,
- CStr::from_bytes_with_nul(b"Android\0").unwrap(), // config name
- 12, // config version
- true, // resettable
- Mode::NORMAL,
- [0; dice::HIDDEN_SIZE], // hidden,
- )
- .unwrap(),
- ]
-}
-
#[cfg(test)]
mod test {
use super::*;
// This simple test checks if the invocation succeeds, essentially it tests
- // if the initial bcc is accepted by `DiceContext::bcc_main_flow`.
+ // if the initial bcc is accepted by `diced_open_dice::retry_bcc_main_flow`.
#[test]
fn make_sample_bcc_and_cdis_test() {
make_sample_bcc_and_cdis().unwrap();
diff --git a/diced/src/utils.rs b/diced/src/utils.rs
index 2789a60..0931e68 100644
--- a/diced/src/utils.rs
+++ b/diced/src/utils.rs
@@ -14,184 +14,6 @@
//! Implements utility functions and types for diced and the dice HAL.
-use android_hardware_security_dice::aidl::android::hardware::security::dice::{
- Bcc::Bcc, BccHandover::BccHandover, InputValues::InputValues as BinderInputValues,
- Mode::Mode as BinderMode,
-};
-use anyhow::{anyhow, Context, Result};
-use diced_open_dice as dice;
-use diced_open_dice::DiceArtifacts;
-use keystore2_crypto::ZVec;
-use std::convert::TryInto;
-
-/// Converts the `InputValues` from the binder to the `InputValues` type in `diced_open_dice` crate.
-pub fn to_dice_input_values(input: &BinderInputValues) -> dice::InputValues {
- if input.authorityDescriptor.is_some() {
- unimplemented!("Authority descriptor is not yet implemented in the current library.");
- }
- dice::InputValues::new(
- input.codeHash,
- dice::Config::Descriptor(input.config.desc.as_slice()),
- input.authorityHash,
- to_dice_mode(input.mode),
- input.hidden,
- )
-}
-
-fn to_dice_mode(binder_mode: BinderMode) -> dice::DiceMode {
- match binder_mode {
- BinderMode::NOT_INITIALIZED => dice::DiceMode::kDiceModeNotInitialized,
- BinderMode::NORMAL => dice::DiceMode::kDiceModeNormal,
- BinderMode::DEBUG => dice::DiceMode::kDiceModeDebug,
- BinderMode::RECOVERY => dice::DiceMode::kDiceModeMaintenance,
- _ => dice::DiceMode::kDiceModeNotInitialized,
- }
-}
-
-/// Initializes an aidl defined BccHandover object with the arguments `cdi_attest`, `cdi_seal`,
-/// and `bcc`.
-pub fn make_bcc_handover(
- cdi_attest: &[u8; dice::CDI_SIZE],
- cdi_seal: &[u8; dice::CDI_SIZE],
- bcc: &[u8],
-) -> Result<BccHandover> {
- Ok(BccHandover { cdiAttest: *cdi_attest, cdiSeal: *cdi_seal, bcc: Bcc { data: bcc.to_vec() } })
-}
-
-/// ResidentArtifacts stores a set of dice artifacts comprising CDI_ATTEST, CDI_SEAL,
-/// and the BCC formatted attestation certificate chain. The sensitive secrets are
-/// stored in zeroing vectors, and it implements functionality to perform DICE
-/// derivation steps using libopen-dice-cbor.
-/// TODO(b/268322533): Remove this struct with the unused HAL service dice
-pub struct ResidentArtifacts {
- cdi_attest: ZVec,
- cdi_seal: ZVec,
- bcc: Vec<u8>,
-}
-
-impl TryFrom<dice::OwnedDiceArtifacts> for ResidentArtifacts {
- type Error = anyhow::Error;
-
- fn try_from(dice_artifacts: dice::OwnedDiceArtifacts) -> Result<Self, Self::Error> {
- Ok(ResidentArtifacts {
- cdi_attest: dice_artifacts.cdi_attest().to_vec().try_into()?,
- cdi_seal: dice_artifacts.cdi_seal().to_vec().try_into()?,
- bcc: dice_artifacts.bcc().ok_or_else(|| anyhow!("bcc is none"))?.to_vec(),
- })
- }
-}
-
-impl ResidentArtifacts {
- /// Create a ResidentArtifacts object. The parameters ensure that the stored secrets
- /// can only have the appropriate size, so that subsequent casts to array references
- /// cannot fail.
- pub fn new(
- cdi_attest: &[u8; dice::CDI_SIZE],
- cdi_seal: &[u8; dice::CDI_SIZE],
- bcc: &[u8],
- ) -> Result<Self> {
- Ok(ResidentArtifacts {
- cdi_attest: cdi_attest[..]
- .try_into()
- .context("In ResidentArtifacts::new: Trying to convert cdi_attest to ZVec.")?,
- cdi_seal: cdi_seal[..]
- .try_into()
- .context("In ResidentArtifacts::new: Trying to convert cdi_seal to ZVec.")?,
- bcc: bcc.to_vec(),
- })
- }
-
- /// Creates a ResidentArtifacts object from another one implementing the DiceArtifacts
- /// trait. Like `new` this function can only create artifacts of appropriate size
- /// because DiceArtifacts returns array references of appropriate size.
- pub fn new_from<T: DiceArtifacts + ?Sized>(artifacts: &T) -> Result<Self> {
- Ok(ResidentArtifacts {
- cdi_attest: artifacts.cdi_attest().to_vec().try_into()?,
- cdi_seal: artifacts.cdi_seal().to_vec().try_into()?,
- bcc: artifacts.bcc().ok_or_else(|| anyhow!("bcc is none"))?.to_vec(),
- })
- }
-
- /// Attempts to clone the artifacts. This operation is fallible due to the fallible
- /// nature of ZVec.
- pub fn try_clone(&self) -> Result<Self> {
- Ok(ResidentArtifacts {
- cdi_attest: self
- .cdi_attest
- .try_clone()
- .context("In ResidentArtifacts::new: Trying to clone cdi_attest.")?,
- cdi_seal: self
- .cdi_seal
- .try_clone()
- .context("In ResidentArtifacts::new: Trying to clone cdi_seal.")?,
- bcc: self.bcc.clone(),
- })
- }
-
- /// Deconstruct the Artifacts into a tuple.
- /// (CDI_ATTEST, CDI_SEAL, BCC)
- pub fn into_tuple(self) -> (ZVec, ZVec, Vec<u8>) {
- let ResidentArtifacts { cdi_attest, cdi_seal, bcc } = self;
- (cdi_attest, cdi_seal, bcc)
- }
-
- fn execute_step(self, input_values: &BinderInputValues) -> Result<Self> {
- let ResidentArtifacts { cdi_attest, cdi_seal, bcc } = self;
-
- dice::retry_bcc_main_flow(
- cdi_attest[..].try_into().with_context(|| {
- format!("Trying to convert cdi_attest. (length: {})", cdi_attest.len())
- })?,
- cdi_seal[..].try_into().with_context(|| {
- format!("Trying to convert cdi_seal. (length: {})", cdi_seal.len())
- })?,
- &bcc,
- &to_dice_input_values(input_values),
- )
- .context("In ResidentArtifacts::execute_step:")?
- .try_into()
- }
-
- /// Iterate through the iterator of dice input values performing one
- /// BCC main flow step on each element.
- pub fn execute_steps<'a, I>(self, input_values: I) -> Result<Self>
- where
- I: IntoIterator<Item = &'a BinderInputValues>,
- {
- input_values
- .into_iter()
- .try_fold(self, |acc, input| acc.execute_step(input))
- .context("In ResidentArtifacts::execute_step:")
- }
-}
-
-/// Implement this trait to provide read and write access to a secure artifact
-/// storage that can be used by the ResidentHal implementation.
-pub trait UpdatableDiceArtifacts {
- /// With artifacts provides access to the stored artifacts for the duration
- /// of the function call by means of calling the callback.
- fn with_artifacts<F, T>(&self, f: F) -> Result<T>
- where
- F: FnOnce(&dyn DiceArtifacts) -> Result<T>;
-
- /// Consumes the object and returns a an updated version of itself.
- fn update(self, new_artifacts: &impl DiceArtifacts) -> Result<Self>
- where
- Self: Sized;
-}
-
-impl DiceArtifacts for ResidentArtifacts {
- fn cdi_attest(&self) -> &[u8; dice::CDI_SIZE] {
- self.cdi_attest[..].try_into().unwrap()
- }
- fn cdi_seal(&self) -> &[u8; dice::CDI_SIZE] {
- self.cdi_seal[..].try_into().unwrap()
- }
- fn bcc(&self) -> Option<&[u8]> {
- Some(&self.bcc)
- }
-}
-
/// This submodule implements a limited set of CBOR generation functionality. Essentially,
/// a cbor header generator and some convenience functions for number and BSTR encoding.
pub mod cbor {