Diced: Add vendor library for DICE HAL implementations.

Bug: 198197213
Test: atest diced_vendor_test
Change-Id: If2bca4584206dc26a49ffd2fea71d7192d2678bf
diff --git a/diced/src/error_vendor.rs b/diced/src/error_vendor.rs
new file mode 100644
index 0000000..10d50dd
--- /dev/null
+++ b/diced/src/error_vendor.rs
@@ -0,0 +1,121 @@
+// 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::public_api::{
+    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
new file mode 100644
index 0000000..fd5384f
--- /dev/null
+++ b/diced/src/hal_node.rs
@@ -0,0 +1,722 @@
+// 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::public_api::{BinderFeatures, Result as BinderResult, Strong};
+use dice::{ContextImpl, OpenDiceCborContext};
+use diced_open_dice_cbor as dice;
+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::{DiceArtifacts, 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 input_values: Vec<utils::InputValues> =
+                input_values.iter().map(|v| v.try_into()).collect::<Result<_>>()?;
+            let artifacts = artifacts
+                .execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues))
+                .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 mut dice = OpenDiceCborContext::new();
+                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[..].try_into().with_context(|| {
+                        format!(
+                            "In ResidentHal::sign: Failed to convert seed (length: {}).",
+                            seed.len()
+                        )
+                    })?)
+                    .context("In ResidentHal::sign: Failed to derive keypair from seed.")?;
+                dice.sign(
+                    message,
+                    private_key[..].try_into().with_context(|| {
+                        format!(
+                            "In ResidentHal::sign: Failed to convert private_key (length: {}).",
+                            private_key.len()
+                        )
+                    })?,
+                )
+                .context("In ResidentHal::sign: Failed to sign.")
+            })
+            .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 input_values: Vec<utils::InputValues> =
+                input_values.iter().map(|v| v.try_into()).collect::<Result<_>>()?;
+
+            let new_artifacts = new_artifacts
+                .execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues))
+                .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::{Context, Result};
+    use diced_open_dice_cbor as dice;
+    use diced_sample_inputs;
+    use diced_utils as utils;
+
+    #[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 make_input_values(
+        code: &str,
+        config_name: &str,
+        authority: &str,
+    ) -> Result<BinderInputValues> {
+        let mut dice_ctx = dice::OpenDiceCborContext::new();
+        Ok(BinderInputValues {
+            codeHash: dice_ctx
+                .hash(code.as_bytes())
+                .context("In make_input_values: code hash failed.")?,
+            config: BinderConfig {
+                desc: dice::bcc::format_config_descriptor(Some(config_name), None, true)
+                    .context("In make_input_values: Failed to format config descriptor.")?,
+            },
+            authorityHash: dice_ctx
+                .hash(authority.as_bytes())
+                .context("In make_input_values: authority hash failed.")?,
+            authorityDescriptor: None,
+            mode: BinderMode::NORMAL,
+            hidden: vec![0; dice::HIDDEN_SIZE],
+        })
+    }
+
+    /// Test the resident artifact batched derivation in process.
+    #[test]
+    fn derive_with_resident_artifacts() -> Result<()> {
+        let (cdi_attest, cdi_seal, bcc) = diced_sample_inputs::make_sample_bcc_and_cdis()?;
+
+        let artifacts =
+            ResidentArtifacts::new(cdi_attest[..].try_into()?, cdi_seal[..].try_into()?, &bcc)?;
+
+        let input_values = &[
+            make_input_values("component 1 code", "component 1", "component 1 authority")?,
+            make_input_values("component 2 code", "component 2", "component 2 authority")?,
+            make_input_values("component 3 code", "component 3", "component 3 authority")?,
+        ];
+
+        let input_values: Vec<utils::InputValues> =
+            input_values.iter().map(|v| v.try_into()).collect::<Result<_>>()?;
+
+        let new_artifacts =
+            artifacts.execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues))?;
+
+        let result = utils::make_bcc_handover(
+            new_artifacts.cdi_attest(),
+            new_artifacts.cdi_seal(),
+            &new_artifacts.bcc(),
+        )?;
+
+        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 (cdi_attest, cdi_seal, bcc) = 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 {
+                cdi_attest: cdi_attest[..].try_into()?,
+                cdi_seal: cdi_seal[..].try_into()?,
+                bcc,
+            })
+        }
+        .expect("Failed to create ResidentHal.");
+
+        let bcc_handover = hal_impl
+            .derive(&[
+                make_input_values("component 1 code", "component 1", "component 1 authority")?,
+                make_input_values("component 2 code", "component 2", "component 2 authority")?,
+                make_input_values("component 3 code", "component 3", "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 (cdi_attest, cdi_seal, bcc) = 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 {
+                cdi_attest: cdi_attest[..].try_into()?,
+                cdi_seal: cdi_seal[..].try_into()?,
+                bcc,
+            })
+        }
+        .expect("Failed to create ResidentHal.");
+
+        hal_impl
+            .demote(&[
+                make_input_values("component 1 code", "component 1", "component 1 authority")?,
+                make_input_values("component 2 code", "component 2", "component 2 authority")?,
+            ])
+            .expect("Failed to demote implementation.");
+
+        let bcc_handover = hal_impl
+            .derive(&[make_input_values(
+                "component 3 code",
+                "component 3",
+                "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, 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
new file mode 100644
index 0000000..01c804b
--- /dev/null
+++ b/diced/src/lib_vendor.rs
@@ -0,0 +1,20 @@
+// 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_cbor as dice;
diff --git a/diced/src/utils.rs b/diced/src/utils.rs
index abb8a7b..3d3db55 100644
--- a/diced/src/utils.rs
+++ b/diced/src/utils.rs
@@ -146,6 +146,17 @@
         })
     }
 
+    /// 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()[..].try_into()?,
+            cdi_seal: artifacts.cdi_seal()[..].try_into()?,
+            bcc: artifacts.bcc(),
+        })
+    }
+
     /// Attempts to clone the artifacts. This operation is fallible due to the fallible
     /// nature of ZVec.
     pub fn try_clone(&self) -> Result<Self> {
@@ -200,6 +211,47 @@
     }
 }
 
+/// An object that implements this trait provides the typical DICE artifacts.
+/// CDI_ATTEST, CDI_SEAL, and a certificate chain up to the public key that
+/// can be derived from CDI_ATTEST. Implementations should check the length of
+/// the stored CDI_* secrets on creation so that any valid instance returns the
+/// correct secrets in an infallible way.
+pub trait DiceArtifacts {
+    /// Returns CDI_ATTEST.
+    fn cdi_attest(&self) -> &[u8; dice::CDI_SIZE];
+    /// Returns CDI_SEAL.
+    fn cdi_seal(&self) -> &[u8; dice::CDI_SIZE];
+    /// Returns the attestation certificate chain in BCC format.
+    fn bcc(&self) -> Vec<u8>;
+}
+
+/// 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) -> Vec<u8> {
+        self.bcc.clone()
+    }
+}
+
 /// 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 {