Merge "Remove unused code in Keystore2's vintf library"
diff --git a/diced/Android.bp b/diced/Android.bp
index e13d863..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_cbor",
-        "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_cbor",
-        "libkeystore2_crypto_rust",
     ],
 }
 
@@ -56,11 +50,9 @@
     vendor_available: true,
 
     rustlibs: [
-        "android.hardware.security.dice-V1-rust",
         "libanyhow",
-        "libdiced_open_dice_cbor",
+        "libdiced_open_dice",
         "libdiced_utils",
-        "libkeystore2_crypto_rust",
     ],
 }
 
@@ -71,158 +63,8 @@
     test_suites: ["general-tests"],
     auto_gen_config: true,
     rustlibs: [
-        "android.hardware.security.dice-V1-rust",
         "libanyhow",
-        "libdiced_open_dice_cbor",
+        "libdiced_open_dice",
         "libdiced_utils",
-        "libkeystore2_crypto_rust",
-    ],
-}
-
-rust_library {
-    name: "libdiced",
-    crate_name: "diced",
-    srcs: ["src/lib.rs"],
-
-    rustlibs: [
-        "android.hardware.security.dice-V1-rust",
-        "android.security.dice-rust",
-        "libdiced_open_dice_cbor",
-        "libanyhow",
-        "libbinder_rs",
-        "libdiced_utils",
-        "libkeystore2_crypto_rust",
-        "libkeystore2_selinux",
-        "liblibc",
-        "liblog_rust",
-        "libthiserror",
-    ],
-}
-
-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_cbor",
-        "libanyhow",
-        "libbinder_rs",
-        "libdiced_utils",
-        "libkeystore2_crypto_rust",
-        "liblibc",
-        "liblog_rust",
-        "libnix",
-        "libserde",
-        "libserde_cbor",
-        "libthiserror",
-    ],
-}
-
-rust_binary {
-    name: "diced",
-    srcs: ["src/diced_main.rs"],
-    prefer_rlib: true,
-    rustlibs: [
-        "android.hardware.security.dice-V1-rust",
-        "libandroid_logger",
-        "libbinder_rs",
-        "libdiced",
-        "libdiced_open_dice_cbor",
-        "libdiced_sample_inputs",
-        "libdiced_utils",
-        "liblog_rust",
-    ],
-    init_rc: ["diced.rc"],
-}
-
-rust_binary {
-    name: "diced.microdroid",
-    srcs: ["src/diced_main.rs"],
-    prefer_rlib: true,
-    rustlibs: [
-        "android.hardware.security.dice-V1-rust",
-        "libandroid_logger",
-        "libbinder_rs",
-        "libdiced",
-        "libdiced_open_dice_cbor",
-        "libdiced_sample_inputs",
-        "libdiced_utils",
-        "liblog_rust",
-    ],
-    init_rc: ["diced.microdroid.rc"],
-    bootstrap: true,
-}
-
-rust_test {
-    name: "diced_test",
-    crate_name: "diced_test",
-    srcs: ["src/lib.rs"],
-    test_suites: ["general-tests"],
-    auto_gen_config: true,
-    rustlibs: [
-        "android.hardware.security.dice-V1-rust",
-        "android.security.dice-rust",
-        "libanyhow",
-        "libbinder_rs",
-        "libdiced_open_dice_cbor",
-        "libdiced_utils",
-        "libkeystore2_crypto_rust",
-        "libkeystore2_selinux",
-        "libkeystore2_vintf_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_cbor",
-        "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_cbor",
-        "libdiced_sample_inputs",
-        "libdiced_utils",
-        "libnix",
     ],
 }
diff --git a/diced/OWNERS b/diced/OWNERS
new file mode 100644
index 0000000..387cd93
--- /dev/null
+++ b/diced/OWNERS
@@ -0,0 +1,3 @@
+alanstokes@google.com
+aliceywang@google.com
+ascull@google.com
diff --git a/diced/TEST_MAPPING b/diced/TEST_MAPPING
index d81efdd..1b078a4 100644
--- a/diced/TEST_MAPPING
+++ b/diced/TEST_MAPPING
@@ -1,16 +1,22 @@
 {
   "presubmit": [
     {
+      "name": "libdiced_open_dice.integration_test"
+    },
+    {
+      "name": "libdiced_open_dice_nostd.integration_test"
+    },
+    {
+      "name": "libopen_dice_cbor_bindgen_test"
+    },
+    {
+      "name": "libopen_dice_bcc_bindgen_test"
+    },
+    {
       "name": "diced_utils_test"
     },
     {
       "name": "diced_sample_inputs_test"
-    },
-    {
-      "name": "diced_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/diced.microdroid.rc b/diced/diced.microdroid.rc
deleted file mode 100644
index 2226f47..0000000
--- a/diced/diced.microdroid.rc
+++ /dev/null
@@ -1,13 +0,0 @@
-# Start the Diced service.
-#
-# See system/core/init/README.md for information on the init.rc language.
-
-service diced /system/bin/diced.microdroid
-    class main
-    user diced
-    group diced
-    # The diced service must not be allowed to restart.
-    # If it crashes for any reason security critical state is lost.
-    # The only remedy is to restart the device.
-    oneshot
-    writepid /dev/cpuset/foreground/tasks
diff --git a/diced/diced.rc b/diced/diced.rc
deleted file mode 100644
index 8c43fa5..0000000
--- a/diced/diced.rc
+++ /dev/null
@@ -1,13 +0,0 @@
-# Start the Diced service.
-#
-# See system/core/init/README.md for information on the init.rc language.
-
-service diced /system/bin/diced
-    class main
-    user diced
-    group diced
-    # The diced service must not be allowed to restart.
-    # If it crashes for any reason security critical state is lost.
-    # The only remedy is to restart the device.
-    oneshot
-    writepid /dev/cpuset/foreground/tasks
diff --git a/diced/open_dice/Android.bp b/diced/open_dice/Android.bp
new file mode 100644
index 0000000..2505b42
--- /dev/null
+++ b/diced/open_dice/Android.bp
@@ -0,0 +1,256 @@
+package {
+    default_visibility: [":__subpackages__"],
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_defaults {
+    name: "libdiced_open_dice_defaults",
+    crate_name: "diced_open_dice",
+    srcs: ["src/lib.rs"],
+    static_libs: [
+        "libopen_dice_cbor",
+    ],
+    vendor_available: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.virt",
+    ],
+}
+
+rust_library_rlib {
+    name: "libdiced_open_dice_nostd",
+    defaults: ["libdiced_open_dice_defaults"],
+    rustlibs: [
+        "libopen_dice_bcc_bindgen_nostd",
+        "libopen_dice_cbor_bindgen_nostd",
+        "libzeroize_nostd",
+    ],
+    whole_static_libs: [
+        "libopen_dice_cbor",
+        "libcrypto_baremetal",
+    ],
+    visibility: [
+        "//packages/modules/Virtualization:__subpackages__",
+    ],
+}
+
+rust_library {
+    name: "libdiced_open_dice",
+    defaults: ["libdiced_open_dice_defaults"],
+    rustlibs: [
+        "libopen_dice_bcc_bindgen",
+        "libopen_dice_cbor_bindgen",
+        "libzeroize",
+    ],
+    features: [
+        "std",
+    ],
+    shared_libs: [
+        "libcrypto",
+    ],
+    whole_static_libs: [
+        "libopen_dice_bcc",
+    ],
+    visibility: [
+        "//system/security/diced:__subpackages__",
+        "//packages/modules/Virtualization:__subpackages__",
+        "//hardware/interfaces/security/dice/aidl:__subpackages__",
+    ],
+}
+
+rust_defaults {
+    name: "libdiced_open_dice_test_defaults",
+    crate_name: "diced_open_dice_test",
+    srcs: ["tests/*.rs"],
+    test_suites: ["general-tests"],
+}
+
+rust_test {
+    name: "libdiced_open_dice.integration_test",
+    defaults: ["libdiced_open_dice_test_defaults"],
+    rustlibs: [
+        "libdiced_open_dice",
+    ],
+}
+
+rust_test {
+    name: "libdiced_open_dice_nostd.integration_test",
+    defaults: ["libdiced_open_dice_test_defaults"],
+    rustlibs: [
+        "libdiced_open_dice_nostd",
+    ],
+}
+
+rust_defaults {
+    name: "libopen_dice_bindgen_nostd.rust_defaults",
+    bindgen_flags: [
+        "--use-core",
+        "--ctypes-prefix=core::ffi",
+        "--raw-line=#![no_std]",
+    ],
+    no_stdlibs: true,
+    prefer_rlib: true,
+    stdlibs: [
+        "libcore.rust_sysroot",
+        "libcompiler_builtins.rust_sysroot",
+    ],
+    target: {
+        musl: {
+            enabled: false,
+        },
+        glibc: {
+            enabled: false,
+        },
+        darwin: {
+            enabled: false,
+        },
+    },
+}
+
+rust_defaults {
+    name: "libopen_dice.rust_defaults",
+    host_supported: true,
+    vendor_available: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.compos",
+        "com.android.virt",
+    ],
+}
+
+rust_defaults {
+    name: "libopen_dice_cbor_bindgen.rust_defaults",
+    defaults: ["libopen_dice.rust_defaults"],
+    wrapper_src: "bindgen/dice.h",
+    crate_name: "open_dice_cbor_bindgen",
+    source_stem: "bindings",
+    bindgen_flags: [
+        "--size_t-is-usize",
+        "--rustified-enum DiceConfigType",
+        "--rustified-enum DiceMode",
+        "--rustified-enum DiceResult",
+
+        // By generating only essential functions, we can make bindings concise and
+        // optimize compilation time.
+        "--allowlist-function=DiceDeriveCdiPrivateKeySeed",
+        "--allowlist-function=DiceDeriveCdiCertificateId",
+        "--allowlist-function=DiceMainFlow",
+        "--allowlist-function=DiceHash",
+        "--allowlist-function=DiceKdf",
+        "--allowlist-function=DiceKeypairFromSeed",
+        "--allowlist-function=DiceSign",
+        "--allowlist-function=DiceVerify",
+        "--allowlist-function=DiceGenerateCertificate",
+
+        // We also need some constants in addition to the functions.
+        "--allowlist-var=DICE_CDI_SIZE",
+        "--allowlist-var=DICE_HASH_SIZE",
+        "--allowlist-var=DICE_HIDDEN_SIZE",
+        "--allowlist-var=DICE_INLINE_CONFIG_SIZE",
+        "--allowlist-var=DICE_PRIVATE_KEY_SEED_SIZE",
+        "--allowlist-var=DICE_ID_SIZE",
+        "--allowlist-var=DICE_PUBLIC_KEY_SIZE",
+        "--allowlist-var=DICE_PRIVATE_KEY_SIZE",
+        "--allowlist-var=DICE_SIGNATURE_SIZE",
+    ],
+}
+
+rust_bindgen {
+    name: "libopen_dice_cbor_bindgen",
+    defaults: ["libopen_dice_cbor_bindgen.rust_defaults"],
+    whole_static_libs: ["libopen_dice_cbor"],
+}
+
+rust_bindgen {
+    name: "libopen_dice_cbor_bindgen_nostd",
+    defaults: [
+        "libopen_dice_cbor_bindgen.rust_defaults",
+        "libopen_dice_bindgen_nostd.rust_defaults",
+    ],
+    whole_static_libs: ["libopen_dice_cbor_baremetal"],
+}
+
+rust_defaults {
+    name: "libopen_dice_bcc_bindgen.rust_defaults",
+    defaults: ["libopen_dice.rust_defaults"],
+    wrapper_src: "bindgen/android/bcc.h",
+    crate_name: "open_dice_bcc_bindgen",
+    source_stem: "bindings",
+    bindgen_flags: [
+        "--size_t-is-usize",
+
+        // By generating only essential functions, we can make bindings concise and
+        // optimize compilation time.
+        "--allowlist-function=BccFormatConfigDescriptor",
+        "--allowlist-function=BccMainFlow",
+        "--allowlist-function=BccHandoverMainFlow",
+        "--allowlist-function=BccHandoverParse",
+
+        // We also need some constants in addition to the functions.
+        "--allowlist-var=BCC_INPUT_COMPONENT_NAME",
+        "--allowlist-var=BCC_INPUT_COMPONENT_VERSION",
+        "--allowlist-var=BCC_INPUT_RESETTABLE",
+
+        // Prevent DiceInputValues from being generated a second time and
+        // import it instead from open_dice_cbor_bindgen.
+        "--blocklist-type=DiceInputValues_",
+        "--blocklist-type=DiceInputValues",
+        "--raw-line",
+        "pub use open_dice_cbor_bindgen::DiceInputValues;",
+
+        // Prevent DiceResult from being generated a second time and
+        // import it instead from open_dice_cbor_bindgen.
+        "--blocklist-type=DiceResult",
+        "--raw-line",
+        "pub use open_dice_cbor_bindgen::DiceResult;",
+    ],
+
+}
+
+rust_bindgen {
+    name: "libopen_dice_bcc_bindgen",
+    defaults: ["libopen_dice_bcc_bindgen.rust_defaults"],
+    rustlibs: [
+        "libopen_dice_cbor_bindgen",
+    ],
+    whole_static_libs: ["libopen_dice_bcc"],
+}
+
+rust_bindgen {
+    name: "libopen_dice_bcc_bindgen_nostd",
+    defaults: [
+        "libopen_dice_bcc_bindgen.rust_defaults",
+        "libopen_dice_bindgen_nostd.rust_defaults",
+    ],
+    rustlibs: [
+        "libopen_dice_cbor_bindgen_nostd",
+    ],
+    whole_static_libs: ["libopen_dice_bcc_baremetal"],
+}
+
+rust_test {
+    name: "libopen_dice_cbor_bindgen_test",
+    srcs: [
+        ":libopen_dice_cbor_bindgen",
+    ],
+    crate_name: "open_dice_cbor_bindgen_test",
+    test_suites: ["general-tests"],
+    auto_gen_config: true,
+    clippy_lints: "none",
+    lints: "none",
+}
+
+rust_test {
+    name: "libopen_dice_bcc_bindgen_test",
+    srcs: [
+        ":libopen_dice_bcc_bindgen",
+    ],
+    crate_name: "open_dice_bcc_bindgen_test",
+    rustlibs: [
+        "libopen_dice_cbor_bindgen",
+    ],
+    test_suites: ["general-tests"],
+    auto_gen_config: true,
+    clippy_lints: "none",
+    lints: "none",
+}
diff --git a/diced/open_dice/bindgen/android/bcc.h b/diced/open_dice/bindgen/android/bcc.h
new file mode 100644
index 0000000..4dfc862
--- /dev/null
+++ b/diced/open_dice/bindgen/android/bcc.h
@@ -0,0 +1,17 @@
+// Copyright 2021 Google LLC
+//
+// 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
+//
+//     https://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.
+
+#pragma once
+
+#include <dice/android/bcc.h>
diff --git a/diced/open_dice/bindgen/dice.h b/diced/open_dice/bindgen/dice.h
new file mode 100644
index 0000000..47fe911
--- /dev/null
+++ b/diced/open_dice/bindgen/dice.h
@@ -0,0 +1,18 @@
+// Copyright 2021 Google LLC
+//
+// 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
+//
+//     https://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.
+
+#pragma once
+
+#include <dice/dice.h>
+#include <dice/ops.h>
diff --git a/diced/open_dice/src/bcc.rs b/diced/open_dice/src/bcc.rs
new file mode 100644
index 0000000..1575113
--- /dev/null
+++ b/diced/open_dice/src/bcc.rs
@@ -0,0 +1,192 @@
+// Copyright 2023, 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 mirrors the content in open-dice/include/dice/android/bcc.h
+
+use crate::dice::{Cdi, CdiValues, DiceArtifacts, InputValues, CDI_SIZE};
+use crate::error::{check_result, DiceError, Result};
+use open_dice_bcc_bindgen::{
+    BccConfigValues, BccFormatConfigDescriptor, BccHandoverMainFlow, BccHandoverParse, BccMainFlow,
+    BCC_INPUT_COMPONENT_NAME, BCC_INPUT_COMPONENT_VERSION, BCC_INPUT_RESETTABLE,
+};
+use std::{ffi::CStr, ptr};
+
+/// Formats a configuration descriptor following the BCC's specification.
+/// See https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/ProtectedData.aidl
+pub fn bcc_format_config_descriptor(
+    name: Option<&CStr>,
+    version: Option<u64>,
+    resettable: bool,
+    buffer: &mut [u8],
+) -> Result<usize> {
+    let mut inputs = 0;
+    if name.is_some() {
+        inputs |= BCC_INPUT_COMPONENT_NAME;
+    }
+    if version.is_some() {
+        inputs |= BCC_INPUT_COMPONENT_VERSION;
+    }
+    if resettable {
+        inputs |= BCC_INPUT_RESETTABLE;
+    }
+
+    let values = BccConfigValues {
+        inputs,
+        component_name: name.map_or(ptr::null(), |p| p.as_ptr()),
+        component_version: version.unwrap_or(0),
+    };
+
+    let mut buffer_size = 0;
+    // SAFETY: The function writes to the buffer, within the given bounds, and only reads the
+    // input values. It writes its result to buffer_size.
+    check_result(unsafe {
+        BccFormatConfigDescriptor(&values, buffer.len(), buffer.as_mut_ptr(), &mut buffer_size)
+    })?;
+    Ok(buffer_size)
+}
+
+/// Executes the main BCC flow.
+///
+/// Given a full set of input values along with the current BCC and CDI values,
+/// computes the next CDI values and matching updated BCC.
+pub fn bcc_main_flow(
+    current_cdi_attest: &Cdi,
+    current_cdi_seal: &Cdi,
+    current_bcc: &[u8],
+    input_values: &InputValues,
+    next_cdi_values: &mut CdiValues,
+    next_bcc: &mut [u8],
+) -> Result<usize> {
+    let mut next_bcc_size = 0;
+    // SAFETY: `BccMainFlow` only reads the current `bcc` and CDI values and writes
+    // to `next_bcc` and next CDI values within its bounds. It also reads
+    // `input_values` as a constant input and doesn't store any pointer.
+    // The first argument can be null and is not used in the current implementation.
+    check_result(unsafe {
+        BccMainFlow(
+            ptr::null_mut(), // context
+            current_cdi_attest.as_ptr(),
+            current_cdi_seal.as_ptr(),
+            current_bcc.as_ptr(),
+            current_bcc.len(),
+            input_values.as_ptr(),
+            next_bcc.len(),
+            next_bcc.as_mut_ptr(),
+            &mut next_bcc_size,
+            next_cdi_values.cdi_attest.as_mut_ptr(),
+            next_cdi_values.cdi_seal.as_mut_ptr(),
+        )
+    })?;
+    Ok(next_bcc_size)
+}
+
+/// Executes the main BCC handover flow.
+///
+/// A BCC handover combines the BCC and CDIs in a single CBOR object.
+/// This function takes the current boot stage's BCC handover bundle and produces a
+/// bundle for the next stage.
+pub fn bcc_handover_main_flow(
+    current_bcc_handover: &[u8],
+    input_values: &InputValues,
+    next_bcc_handover: &mut [u8],
+) -> Result<usize> {
+    let mut next_bcc_handover_size = 0;
+    // SAFETY - The function only reads `current_bcc_handover` and writes to `next_bcc_handover`
+    // within its bounds,
+    // It also reads `input_values` as a constant input and doesn't store any pointer.
+    // The first argument can be null and is not used in the current implementation.
+    check_result(unsafe {
+        BccHandoverMainFlow(
+            ptr::null_mut(), // context
+            current_bcc_handover.as_ptr(),
+            current_bcc_handover.len(),
+            input_values.as_ptr(),
+            next_bcc_handover.len(),
+            next_bcc_handover.as_mut_ptr(),
+            &mut next_bcc_handover_size,
+        )
+    })?;
+
+    Ok(next_bcc_handover_size)
+}
+
+/// A BCC handover combines the BCC and CDIs in a single CBOR object.
+/// This struct is used as return of the function `bcc_handover_parse`, its lifetime is tied
+/// to the lifetime of the raw BCC handover slice.
+#[derive(Debug)]
+pub struct BccHandover<'a> {
+    /// Attestation CDI.
+    cdi_attest: &'a [u8; CDI_SIZE],
+    /// Sealing CDI.
+    cdi_seal: &'a [u8; CDI_SIZE],
+    /// Boot Certificate Chain.
+    bcc: Option<&'a [u8]>,
+}
+
+impl<'a> DiceArtifacts for BccHandover<'a> {
+    fn cdi_attest(&self) -> &[u8; CDI_SIZE] {
+        self.cdi_attest
+    }
+
+    fn cdi_seal(&self) -> &[u8; CDI_SIZE] {
+        self.cdi_seal
+    }
+
+    fn bcc(&self) -> Option<&[u8]> {
+        self.bcc
+    }
+}
+
+/// A BCC handover combines the BCC and CDIs in a single CBOR object.
+/// This function parses the `bcc_handover` to extracts the BCC and CDIs.
+/// The lifetime of the returned `BccHandover` is tied to the given `bcc_handover` slice.
+pub fn bcc_handover_parse(bcc_handover: &[u8]) -> Result<BccHandover> {
+    let mut cdi_attest: *const u8 = ptr::null();
+    let mut cdi_seal: *const u8 = ptr::null();
+    let mut bcc: *const u8 = ptr::null();
+    let mut bcc_size = 0;
+    // SAFETY: The `bcc_handover` is only read and never stored and the returned pointers should all
+    // point within the address range of the `bcc_handover` or be NULL.
+    check_result(unsafe {
+        BccHandoverParse(
+            bcc_handover.as_ptr(),
+            bcc_handover.len(),
+            &mut cdi_attest,
+            &mut cdi_seal,
+            &mut bcc,
+            &mut bcc_size,
+        )
+    })?;
+    let cdi_attest = sub_slice(bcc_handover, cdi_attest, CDI_SIZE)?;
+    let cdi_seal = sub_slice(bcc_handover, cdi_seal, CDI_SIZE)?;
+    let bcc = sub_slice(bcc_handover, bcc, bcc_size).ok();
+    Ok(BccHandover {
+        cdi_attest: cdi_attest.try_into().map_err(|_| DiceError::PlatformError)?,
+        cdi_seal: cdi_seal.try_into().map_err(|_| DiceError::PlatformError)?,
+        bcc,
+    })
+}
+
+/// Gets a slice the `addr` points to and of length `len`.
+/// The slice should be contained in the buffer.
+fn sub_slice(buffer: &[u8], addr: *const u8, len: usize) -> Result<&[u8]> {
+    if addr.is_null() || !buffer.as_ptr_range().contains(&addr) {
+        return Err(DiceError::PlatformError);
+    }
+    // SAFETY: This is safe because addr is not null and is within the range of the buffer.
+    let start: usize = unsafe {
+        addr.offset_from(buffer.as_ptr()).try_into().map_err(|_| DiceError::PlatformError)?
+    };
+    start.checked_add(len).and_then(|end| buffer.get(start..end)).ok_or(DiceError::PlatformError)
+}
diff --git a/diced/open_dice/src/dice.rs b/diced/open_dice/src/dice.rs
new file mode 100644
index 0000000..9266b6f
--- /dev/null
+++ b/diced/open_dice/src/dice.rs
@@ -0,0 +1,270 @@
+// Copyright 2023, 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.
+
+//! Structs and functions about the types used in DICE.
+//! This module mirrors the content in open-dice/include/dice/dice.h
+
+use crate::error::{check_result, Result};
+pub use open_dice_cbor_bindgen::DiceMode;
+use open_dice_cbor_bindgen::{
+    DiceConfigType, DiceDeriveCdiCertificateId, DiceDeriveCdiPrivateKeySeed, DiceInputValues,
+    DiceMainFlow, DICE_CDI_SIZE, DICE_HASH_SIZE, DICE_HIDDEN_SIZE, DICE_ID_SIZE,
+    DICE_INLINE_CONFIG_SIZE, DICE_PRIVATE_KEY_SEED_SIZE, DICE_PRIVATE_KEY_SIZE,
+    DICE_PUBLIC_KEY_SIZE, DICE_SIGNATURE_SIZE,
+};
+use std::ptr;
+use zeroize::{Zeroize, ZeroizeOnDrop};
+
+/// The size of a DICE hash.
+pub const HASH_SIZE: usize = DICE_HASH_SIZE as usize;
+/// The size of the DICE hidden value.
+pub const HIDDEN_SIZE: usize = DICE_HIDDEN_SIZE as usize;
+/// The size of a DICE inline config.
+const INLINE_CONFIG_SIZE: usize = DICE_INLINE_CONFIG_SIZE as usize;
+/// The size of a CDI.
+pub const CDI_SIZE: usize = DICE_CDI_SIZE as usize;
+/// The size of a private key seed.
+pub const PRIVATE_KEY_SEED_SIZE: usize = DICE_PRIVATE_KEY_SEED_SIZE as usize;
+/// The size of a private key.
+pub const PRIVATE_KEY_SIZE: usize = DICE_PRIVATE_KEY_SIZE as usize;
+/// The size of a public key.
+pub const PUBLIC_KEY_SIZE: usize = DICE_PUBLIC_KEY_SIZE as usize;
+/// The size of a signature.
+pub const SIGNATURE_SIZE: usize = DICE_SIGNATURE_SIZE as usize;
+/// The size of an ID.
+pub const ID_SIZE: usize = DICE_ID_SIZE as usize;
+
+/// Array type of hashes used by DICE.
+pub type Hash = [u8; HASH_SIZE];
+/// Array type of additional input.
+pub type Hidden = [u8; HIDDEN_SIZE];
+/// Array type of inline configuration values.
+pub type InlineConfig = [u8; INLINE_CONFIG_SIZE];
+/// Array type of CDIs.
+pub type Cdi = [u8; CDI_SIZE];
+/// Array type of the public key.
+pub type PublicKey = [u8; PUBLIC_KEY_SIZE];
+/// Array type of the signature.
+pub type Signature = [u8; SIGNATURE_SIZE];
+/// Array type of DICE ID.
+pub type DiceId = [u8; ID_SIZE];
+
+/// A trait for types that represent Dice artifacts, which include:
+///
+/// - Attestation CDI
+/// - Sealing CDI
+/// - Boot Certificate Chain
+///
+/// Types that implement this trait provide an access these artifacts.
+pub trait DiceArtifacts {
+    /// Returns a reference to the attestation CDI.
+    fn cdi_attest(&self) -> &[u8; CDI_SIZE];
+
+    /// Returns a reference to the sealing CDI.
+    fn cdi_seal(&self) -> &[u8; CDI_SIZE];
+
+    /// Returns a reference to the Boot Certificate Chain, if present.
+    fn bcc(&self) -> Option<&[u8]>;
+}
+
+/// TODO(b/268587826): Clean up the memory cache after zeroing out the memory
+/// for sensitive data like CDI values and private key.
+/// CDI Values.
+#[derive(Debug, Zeroize, ZeroizeOnDrop, Default)]
+pub struct CdiValues {
+    /// Attestation CDI.
+    pub cdi_attest: [u8; CDI_SIZE],
+    /// Sealing CDI.
+    pub cdi_seal: [u8; CDI_SIZE],
+}
+
+/// Private key seed. The data is zeroed out when the struct is dropped.
+#[derive(Zeroize, ZeroizeOnDrop, Default)]
+pub struct PrivateKeySeed([u8; PRIVATE_KEY_SEED_SIZE]);
+
+impl PrivateKeySeed {
+    /// Returns an array reference of the private key seed.
+    pub fn as_array(&self) -> &[u8; PRIVATE_KEY_SEED_SIZE] {
+        &self.0
+    }
+
+    /// Returns a mutable pointer to the slice buffer of the private key seed.
+    pub fn as_mut_ptr(&mut self) -> *mut u8 {
+        self.0.as_mut_ptr()
+    }
+}
+
+/// Private key. The data is zeroed out when the struct is dropped.
+#[derive(Zeroize, ZeroizeOnDrop)]
+pub struct PrivateKey([u8; PRIVATE_KEY_SIZE]);
+
+impl Default for PrivateKey {
+    /// Creates a new `PrivateKey` instance with all bytes set to 0.
+    ///
+    /// Since the size of the private key array is too large to be initialized
+    /// with a default value, this implementation sets all the bytes in the array
+    /// to 0 using the `[0u8; PRIVATE_KEY_SIZE]` syntax.
+    fn default() -> Self {
+        Self([0u8; PRIVATE_KEY_SIZE])
+    }
+}
+
+impl PrivateKey {
+    /// Returns an array reference of the private key.
+    pub fn as_array(&self) -> &[u8; PRIVATE_KEY_SIZE] {
+        &self.0
+    }
+
+    /// Returns a mutable pointer to the slice buffer of the private key.
+    pub fn as_mut_ptr(&mut self) -> *mut u8 {
+        self.0.as_mut_ptr()
+    }
+}
+
+/// Configuration descriptor for DICE input values.
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum Config<'a> {
+    /// Reference to an inline descriptor.
+    Inline(&'a InlineConfig),
+    /// Reference to a free form descriptor that will be hashed by the implementation.
+    Descriptor(&'a [u8]),
+}
+
+impl Config<'_> {
+    fn dice_config_type(&self) -> DiceConfigType {
+        match self {
+            Self::Inline(_) => DiceConfigType::kDiceConfigTypeInline,
+            Self::Descriptor(_) => DiceConfigType::kDiceConfigTypeDescriptor,
+        }
+    }
+
+    fn inline_config(&self) -> InlineConfig {
+        match self {
+            Self::Inline(inline) => **inline,
+            Self::Descriptor(_) => [0u8; INLINE_CONFIG_SIZE],
+        }
+    }
+
+    fn descriptor_ptr(&self) -> *const u8 {
+        match self {
+            Self::Descriptor(descriptor) => descriptor.as_ptr(),
+            _ => ptr::null(),
+        }
+    }
+
+    fn descriptor_size(&self) -> usize {
+        match self {
+            Self::Descriptor(descriptor) => descriptor.len(),
+            _ => 0,
+        }
+    }
+}
+
+/// Wrap of `DiceInputValues`.
+#[derive(Clone, Debug)]
+pub struct InputValues(DiceInputValues);
+
+impl InputValues {
+    /// Creates a new `InputValues`.
+    pub fn new(
+        code_hash: Hash,
+        config: Config,
+        authority_hash: Hash,
+        mode: DiceMode,
+        hidden: Hidden,
+    ) -> Self {
+        Self(DiceInputValues {
+            code_hash,
+            code_descriptor: ptr::null(),
+            code_descriptor_size: 0,
+            config_type: config.dice_config_type(),
+            config_value: config.inline_config(),
+            config_descriptor: config.descriptor_ptr(),
+            config_descriptor_size: config.descriptor_size(),
+            authority_hash,
+            authority_descriptor: ptr::null(),
+            authority_descriptor_size: 0,
+            mode,
+            hidden,
+        })
+    }
+
+    /// Returns a raw pointer to the wrapped `DiceInputValues`.
+    pub fn as_ptr(&self) -> *const DiceInputValues {
+        &self.0 as *const DiceInputValues
+    }
+}
+
+/// Derives a CDI private key seed from a `cdi_attest` value.
+pub fn derive_cdi_private_key_seed(cdi_attest: &Cdi) -> Result<PrivateKeySeed> {
+    let mut seed = PrivateKeySeed::default();
+    // SAFETY: The function writes to the buffer within the given bounds, and only reads the
+    // input values. The first argument context is not used in this function.
+    check_result(unsafe {
+        DiceDeriveCdiPrivateKeySeed(
+            ptr::null_mut(), // context
+            cdi_attest.as_ptr(),
+            seed.as_mut_ptr(),
+        )
+    })?;
+    Ok(seed)
+}
+
+/// Derives an ID from the given `cdi_public_key` value.
+pub fn derive_cdi_certificate_id(cdi_public_key: &[u8]) -> Result<DiceId> {
+    let mut id = [0u8; ID_SIZE];
+    // SAFETY: The function writes to the buffer within the given bounds, and only reads the
+    // input values. The first argument context is not used in this function.
+    check_result(unsafe {
+        DiceDeriveCdiCertificateId(
+            ptr::null_mut(), // context
+            cdi_public_key.as_ptr(),
+            cdi_public_key.len(),
+            id.as_mut_ptr(),
+        )
+    })?;
+    Ok(id)
+}
+
+/// Executes the main DICE flow.
+///
+/// Given a full set of input values and the current CDI values, computes the
+/// next CDI values and a matching certificate.
+/// Returns the actual size of the next CDI certificate.
+pub fn dice_main_flow(
+    current_cdi_attest: &Cdi,
+    current_cdi_seal: &Cdi,
+    input_values: &InputValues,
+    next_cdi_certificate: &mut [u8],
+    next_cdi_values: &mut CdiValues,
+) -> Result<usize> {
+    let mut next_cdi_certificate_actual_size = 0;
+    // SAFETY: The function only reads the current CDI values and inputs and writes
+    // to `next_cdi_certificate` and next CDI values within its bounds.
+    // The first argument can be null and is not used in the current implementation.
+    check_result(unsafe {
+        DiceMainFlow(
+            ptr::null_mut(), // context
+            current_cdi_attest.as_ptr(),
+            current_cdi_seal.as_ptr(),
+            input_values.as_ptr(),
+            next_cdi_certificate.len(),
+            next_cdi_certificate.as_mut_ptr(),
+            &mut next_cdi_certificate_actual_size,
+            next_cdi_values.cdi_attest.as_mut_ptr(),
+            next_cdi_values.cdi_seal.as_mut_ptr(),
+        )
+    })?;
+    Ok(next_cdi_certificate_actual_size)
+}
diff --git a/diced/open_dice/src/error.rs b/diced/open_dice/src/error.rs
new file mode 100644
index 0000000..4c67335
--- /dev/null
+++ b/diced/open_dice/src/error.rs
@@ -0,0 +1,59 @@
+// Copyright 2023, 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.
+
+//! Errors and relating functions thrown in this library.
+
+use open_dice_cbor_bindgen::DiceResult;
+use std::{fmt, result};
+
+#[cfg(feature = "std")]
+use std::error::Error;
+
+/// Error type used by DICE.
+#[derive(Debug)]
+pub enum DiceError {
+    /// Provided input was invalid.
+    InvalidInput,
+    /// Provided buffer was too small.
+    BufferTooSmall,
+    /// Platform error.
+    PlatformError,
+}
+
+/// This makes `DiceError` accepted by anyhow.
+#[cfg(feature = "std")]
+impl Error for DiceError {}
+
+impl fmt::Display for DiceError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            Self::InvalidInput => write!(f, "invalid input"),
+            Self::BufferTooSmall => write!(f, "buffer too small"),
+            Self::PlatformError => write!(f, "platform error"),
+        }
+    }
+}
+
+/// DICE result type.
+pub type Result<T> = result::Result<T, DiceError>;
+
+/// Checks the given `DiceResult`. Returns an error if it's not OK.
+pub fn check_result(result: DiceResult) -> Result<()> {
+    match result {
+        DiceResult::kDiceResultOk => Ok(()),
+        DiceResult::kDiceResultInvalidInput => Err(DiceError::InvalidInput),
+        DiceResult::kDiceResultBufferTooSmall => Err(DiceError::BufferTooSmall),
+        DiceResult::kDiceResultPlatformError => Err(DiceError::PlatformError),
+    }
+}
diff --git a/diced/open_dice/src/lib.rs b/diced/open_dice/src/lib.rs
new file mode 100644
index 0000000..e7ec56b
--- /dev/null
+++ b/diced/open_dice/src/lib.rs
@@ -0,0 +1,45 @@
+// Copyright 2023, 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.
+
+//! Implements safe wrappers around the public API of libopen-dice for
+//! both std and nostd usages.
+
+#![cfg_attr(not(feature = "std"), no_std)]
+
+#[cfg(not(feature = "std"))]
+extern crate core as std;
+
+mod bcc;
+mod dice;
+mod error;
+mod ops;
+#[cfg(feature = "std")]
+mod retry;
+
+pub use bcc::{
+    bcc_format_config_descriptor, bcc_handover_main_flow, bcc_handover_parse, bcc_main_flow,
+    BccHandover,
+};
+pub use dice::{
+    derive_cdi_certificate_id, derive_cdi_private_key_seed, dice_main_flow, Cdi, CdiValues, Config,
+    DiceArtifacts, DiceMode, Hash, Hidden, InlineConfig, InputValues, PrivateKey, PrivateKeySeed,
+    PublicKey, Signature, CDI_SIZE, HASH_SIZE, HIDDEN_SIZE, ID_SIZE, PRIVATE_KEY_SEED_SIZE,
+};
+pub use error::{check_result, DiceError, Result};
+pub use ops::{generate_certificate, hash, kdf, keypair_from_seed, sign, verify};
+#[cfg(feature = "std")]
+pub use retry::{
+    retry_bcc_format_config_descriptor, retry_bcc_main_flow, retry_dice_main_flow,
+    retry_generate_certificate, OwnedDiceArtifacts,
+};
diff --git a/diced/open_dice/src/ops.rs b/diced/open_dice/src/ops.rs
new file mode 100644
index 0000000..8222b26
--- /dev/null
+++ b/diced/open_dice/src/ops.rs
@@ -0,0 +1,142 @@
+// Copyright 2023, 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 mirrors the content in open-dice/include/dice/ops.h
+//! It contains the set of functions that implement various operations that the
+//! main DICE functions depend on.
+
+use crate::dice::{
+    Hash, InputValues, PrivateKey, PublicKey, Signature, HASH_SIZE, PRIVATE_KEY_SEED_SIZE,
+    PRIVATE_KEY_SIZE, PUBLIC_KEY_SIZE, SIGNATURE_SIZE,
+};
+use crate::error::{check_result, Result};
+use open_dice_cbor_bindgen::{
+    DiceGenerateCertificate, DiceHash, DiceKdf, DiceKeypairFromSeed, DiceSign, DiceVerify,
+};
+use std::ptr;
+
+/// Hashes the provided input using DICE's hash function `DiceHash`.
+pub fn hash(input: &[u8]) -> Result<Hash> {
+    let mut output: Hash = [0; HASH_SIZE];
+    // SAFETY: DiceHash takes a sized input buffer and writes to a constant-sized output buffer.
+    // The first argument context is not used in this function.
+    check_result(unsafe {
+        DiceHash(
+            ptr::null_mut(), // context
+            input.as_ptr(),
+            input.len(),
+            output.as_mut_ptr(),
+        )
+    })?;
+    Ok(output)
+}
+
+/// An implementation of HKDF-SHA512. Derives a key of `derived_key.len()` bytes from `ikm`, `salt`,
+/// and `info`. The derived key is written to the `derived_key`.
+pub fn kdf(ikm: &[u8], salt: &[u8], info: &[u8], derived_key: &mut [u8]) -> Result<()> {
+    // SAFETY: The function writes to the `derived_key`, within the given bounds, and only reads the
+    // input values. The first argument context is not used in this function.
+    check_result(unsafe {
+        DiceKdf(
+            ptr::null_mut(), // context
+            derived_key.len(),
+            ikm.as_ptr(),
+            ikm.len(),
+            salt.as_ptr(),
+            salt.len(),
+            info.as_ptr(),
+            info.len(),
+            derived_key.as_mut_ptr(),
+        )
+    })
+}
+
+/// Deterministically generates a public and private key pair from `seed`.
+/// Since this is deterministic, `seed` is as sensitive as a private key and can
+/// be used directly as the private key.
+pub fn keypair_from_seed(seed: &[u8; PRIVATE_KEY_SEED_SIZE]) -> Result<(PublicKey, PrivateKey)> {
+    let mut public_key = [0u8; PUBLIC_KEY_SIZE];
+    let mut private_key = PrivateKey::default();
+    // SAFETY: The function writes to the `public_key` and `private_key` within the given bounds,
+    // and only reads the `seed`. The first argument context is not used in this function.
+    check_result(unsafe {
+        DiceKeypairFromSeed(
+            ptr::null_mut(), // context
+            seed.as_ptr(),
+            public_key.as_mut_ptr(),
+            private_key.as_mut_ptr(),
+        )
+    })?;
+    Ok((public_key, private_key))
+}
+
+/// Signs the `message` with the give `private_key` using `DiceSign`.
+pub fn sign(message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Signature> {
+    let mut signature = [0u8; SIGNATURE_SIZE];
+    // SAFETY: The function writes to the `signature` within the given bounds, and only reads the
+    // message and the private key. The first argument context is not used in this function.
+    check_result(unsafe {
+        DiceSign(
+            ptr::null_mut(), // context
+            message.as_ptr(),
+            message.len(),
+            private_key.as_ptr(),
+            signature.as_mut_ptr(),
+        )
+    })?;
+    Ok(signature)
+}
+
+/// Verifies the `signature` of the `message` with the given `public_key` using `DiceVerify`.
+pub fn verify(message: &[u8], signature: &Signature, public_key: &PublicKey) -> Result<()> {
+    // SAFETY: only reads the messages, signature and public key as constant values.
+    // The first argument context is not used in this function.
+    check_result(unsafe {
+        DiceVerify(
+            ptr::null_mut(), // context
+            message.as_ptr(),
+            message.len(),
+            signature.as_ptr(),
+            public_key.as_ptr(),
+        )
+    })
+}
+
+/// Generates an X.509 certificate from the given `subject_private_key_seed` and
+/// `input_values`, and signed by `authority_private_key_seed`.
+/// The subject private key seed is supplied here so the implementation can choose
+/// between asymmetric mechanisms, for example ECDSA vs Ed25519.
+/// Returns the actual size of the generated certificate.
+pub fn generate_certificate(
+    subject_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
+    authority_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
+    input_values: &InputValues,
+    certificate: &mut [u8],
+) -> Result<usize> {
+    let mut certificate_actual_size = 0;
+    // SAFETY: The function writes to the `certificate` within the given bounds, and only reads the
+    // input values and the key seeds. The first argument context is not used in this function.
+    check_result(unsafe {
+        DiceGenerateCertificate(
+            ptr::null_mut(), // context
+            subject_private_key_seed.as_ptr(),
+            authority_private_key_seed.as_ptr(),
+            input_values.as_ptr(),
+            certificate.len(),
+            certificate.as_mut_ptr(),
+            &mut certificate_actual_size,
+        )
+    })?;
+    Ok(certificate_actual_size)
+}
diff --git a/diced/open_dice/src/retry.rs b/diced/open_dice/src/retry.rs
new file mode 100644
index 0000000..76a214c
--- /dev/null
+++ b/diced/open_dice/src/retry.rs
@@ -0,0 +1,160 @@
+// Copyright 2023, 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 implements a retry version for multiple DICE functions that
+//! require preallocated output buffer. As the retry functions require
+//! memory allocation on heap, currently we only expose these functions in
+//! std environment.
+
+use crate::bcc::{bcc_format_config_descriptor, bcc_main_flow};
+use crate::dice::{
+    dice_main_flow, Cdi, CdiValues, DiceArtifacts, InputValues, CDI_SIZE, PRIVATE_KEY_SEED_SIZE,
+};
+use crate::error::{DiceError, Result};
+use crate::ops::generate_certificate;
+use std::ffi::CStr;
+
+/// Artifacts stores a set of dice artifacts comprising CDI_ATTEST, CDI_SEAL,
+/// and the BCC formatted attestation certificate chain.
+/// As we align with the DICE standards today, this is the certificate chain
+/// is also called DICE certificate chain.
+#[derive(Debug)]
+pub struct OwnedDiceArtifacts {
+    /// CDI Values.
+    cdi_values: CdiValues,
+    /// Boot Certificate Chain.
+    bcc: Vec<u8>,
+}
+
+impl DiceArtifacts for OwnedDiceArtifacts {
+    fn cdi_attest(&self) -> &[u8; CDI_SIZE] {
+        &self.cdi_values.cdi_attest
+    }
+
+    fn cdi_seal(&self) -> &[u8; CDI_SIZE] {
+        &self.cdi_values.cdi_seal
+    }
+
+    fn bcc(&self) -> Option<&[u8]> {
+        Some(&self.bcc)
+    }
+}
+
+/// Retries the given function with bigger output buffer size.
+fn retry_with_bigger_buffer<F>(mut f: F) -> Result<Vec<u8>>
+where
+    F: FnMut(&mut Vec<u8>) -> Result<usize>,
+{
+    const INITIAL_BUFFER_SIZE: usize = 256;
+    const MAX_BUFFER_SIZE: usize = 64 * 1024 * 1024;
+
+    let mut buffer = vec![0u8; INITIAL_BUFFER_SIZE];
+    while buffer.len() <= MAX_BUFFER_SIZE {
+        match f(&mut buffer) {
+            Err(DiceError::BufferTooSmall) => {
+                let new_size = buffer.len() * 2;
+                buffer.resize(new_size, 0);
+            }
+            Err(e) => return Err(e),
+            Ok(actual_size) => {
+                if actual_size > buffer.len() {
+                    panic!(
+                        "actual_size larger than buffer size: open-dice function
+                         may have written past the end of the buffer."
+                    );
+                }
+                buffer.truncate(actual_size);
+                return Ok(buffer);
+            }
+        }
+    }
+    Err(DiceError::PlatformError)
+}
+
+/// Formats a configuration descriptor following the BCC's specification.
+pub fn retry_bcc_format_config_descriptor(
+    name: Option<&CStr>,
+    version: Option<u64>,
+    resettable: bool,
+) -> Result<Vec<u8>> {
+    retry_with_bigger_buffer(|buffer| {
+        bcc_format_config_descriptor(name, version, resettable, buffer)
+    })
+}
+
+/// Executes the main BCC flow.
+///
+/// Given a full set of input values along with the current BCC and CDI values,
+/// computes the next CDI values and matching updated BCC.
+pub fn retry_bcc_main_flow(
+    current_cdi_attest: &Cdi,
+    current_cdi_seal: &Cdi,
+    bcc: &[u8],
+    input_values: &InputValues,
+) -> Result<OwnedDiceArtifacts> {
+    let mut next_cdi_values = CdiValues::default();
+    let next_bcc = retry_with_bigger_buffer(|next_bcc| {
+        bcc_main_flow(
+            current_cdi_attest,
+            current_cdi_seal,
+            bcc,
+            input_values,
+            &mut next_cdi_values,
+            next_bcc,
+        )
+    })?;
+    Ok(OwnedDiceArtifacts { cdi_values: next_cdi_values, bcc: next_bcc })
+}
+
+/// Executes the main DICE flow.
+///
+/// Given a full set of input values and the current CDI values, computes the
+/// next CDI values and a matching certificate.
+pub fn retry_dice_main_flow(
+    current_cdi_attest: &Cdi,
+    current_cdi_seal: &Cdi,
+    input_values: &InputValues,
+) -> Result<(CdiValues, Vec<u8>)> {
+    let mut next_cdi_values = CdiValues::default();
+    let next_cdi_certificate = retry_with_bigger_buffer(|next_cdi_certificate| {
+        dice_main_flow(
+            current_cdi_attest,
+            current_cdi_seal,
+            input_values,
+            next_cdi_certificate,
+            &mut next_cdi_values,
+        )
+    })?;
+    Ok((next_cdi_values, next_cdi_certificate))
+}
+
+/// Generates an X.509 certificate from the given `subject_private_key_seed` and
+/// `input_values`, and signed by `authority_private_key_seed`.
+/// The subject private key seed is supplied here so the implementation can choose
+/// between asymmetric mechanisms, for example ECDSA vs Ed25519.
+/// Returns the generated certificate.
+pub fn retry_generate_certificate(
+    subject_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
+    authority_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
+    input_values: &InputValues,
+) -> Result<Vec<u8>> {
+    retry_with_bigger_buffer(|certificate| {
+        generate_certificate(
+            subject_private_key_seed,
+            authority_private_key_seed,
+            input_values,
+            certificate,
+        )
+    })
+}
diff --git a/diced/open_dice/tests/api_test.rs b/diced/open_dice/tests/api_test.rs
new file mode 100644
index 0000000..a47265b
--- /dev/null
+++ b/diced/open_dice/tests/api_test.rs
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+use diced_open_dice::{
+    derive_cdi_certificate_id, derive_cdi_private_key_seed, hash, kdf, keypair_from_seed, sign,
+    verify, CDI_SIZE, HASH_SIZE, ID_SIZE, PRIVATE_KEY_SEED_SIZE,
+};
+
+#[test]
+fn hash_succeeds() {
+    const EXPECTED_HASH: [u8; HASH_SIZE] = [
+        0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02, 0xf2,
+        0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8, 0x6d, 0x4c,
+        0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda, 0x34, 0x25, 0x5b,
+        0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d, 0xc5, 0x54, 0x2e, 0x93,
+        0xae, 0x9c, 0xd7, 0x6f,
+    ];
+    assert_eq!(EXPECTED_HASH, hash(b"hello world").expect("hash failed"));
+}
+
+#[test]
+fn kdf_succeeds() {
+    let mut derived_key = [0u8; PRIVATE_KEY_SEED_SIZE];
+    kdf(b"myInitialKeyMaterial", b"mySalt", b"myInfo", &mut derived_key).unwrap();
+    const EXPECTED_DERIVED_KEY: [u8; PRIVATE_KEY_SEED_SIZE] = [
+        0x91, 0x9b, 0x8d, 0x29, 0xc4, 0x1b, 0x93, 0xd7, 0xeb, 0x09, 0xfa, 0xd7, 0xc9, 0x87, 0xb0,
+        0xd1, 0xcc, 0x26, 0xef, 0x07, 0x83, 0x42, 0xcf, 0xa3, 0x45, 0x0a, 0x57, 0xe9, 0x19, 0x86,
+        0xef, 0x48,
+    ];
+    assert_eq!(EXPECTED_DERIVED_KEY, derived_key);
+}
+
+#[test]
+fn derive_cdi_certificate_id_succeeds() {
+    const EXPECTED_ID: [u8; ID_SIZE] = [
+        0x7a, 0x36, 0x45, 0x2c, 0x02, 0xf6, 0x2b, 0xec, 0xf9, 0x80, 0x06, 0x75, 0x87, 0xa5, 0xc1,
+        0x44, 0x0c, 0xd3, 0xc0, 0x6d,
+    ];
+    assert_eq!(EXPECTED_ID, derive_cdi_certificate_id(b"MyPubKey").unwrap());
+}
+
+const EXPECTED_SEED: &[u8] = &[
+    0xfa, 0x3c, 0x2f, 0x58, 0x37, 0xf5, 0x8e, 0x96, 0x16, 0x09, 0xf5, 0x22, 0xa1, 0xf1, 0xba, 0xaa,
+    0x19, 0x95, 0x01, 0x79, 0x2e, 0x60, 0x56, 0xaf, 0xf6, 0x41, 0xe7, 0xff, 0x48, 0xf5, 0x3a, 0x08,
+    0x84, 0x8a, 0x98, 0x85, 0x6d, 0xf5, 0x69, 0x21, 0x03, 0xcd, 0x09, 0xc3, 0x28, 0xd6, 0x06, 0xa7,
+    0x57, 0xbd, 0x48, 0x4b, 0x0f, 0x79, 0x0f, 0xf8, 0x2f, 0xf0, 0x0a, 0x41, 0x94, 0xd8, 0x8c, 0xa8,
+];
+
+const EXPECTED_CDI_ATTEST: &[u8] = &[
+    0xfa, 0x3c, 0x2f, 0x58, 0x37, 0xf5, 0x8e, 0x96, 0x16, 0x09, 0xf5, 0x22, 0xa1, 0xf1, 0xba, 0xaa,
+    0x19, 0x95, 0x01, 0x79, 0x2e, 0x60, 0x56, 0xaf, 0xf6, 0x41, 0xe7, 0xff, 0x48, 0xf5, 0x3a, 0x08,
+];
+
+const EXPECTED_CDI_PRIVATE_KEY_SEED: &[u8] = &[
+    0x5f, 0xcc, 0x8e, 0x1a, 0xd1, 0xc2, 0xb3, 0xe9, 0xfb, 0xe1, 0x68, 0xf0, 0xf6, 0x98, 0xfe, 0x0d,
+    0xee, 0xd4, 0xb5, 0x18, 0xcb, 0x59, 0x70, 0x2d, 0xee, 0x06, 0xe5, 0x70, 0xf1, 0x72, 0x02, 0x6e,
+];
+
+const EXPECTED_PUB_KEY: &[u8] = &[
+    0x47, 0x42, 0x4b, 0xbd, 0xd7, 0x23, 0xb4, 0xcd, 0xca, 0xe2, 0x8e, 0xdc, 0x6b, 0xfc, 0x23, 0xc9,
+    0x21, 0x5c, 0x48, 0x21, 0x47, 0xee, 0x5b, 0xfa, 0xaf, 0x88, 0x9a, 0x52, 0xf1, 0x61, 0x06, 0x37,
+];
+const EXPECTED_PRIV_KEY: &[u8] = &[
+    0x5f, 0xcc, 0x8e, 0x1a, 0xd1, 0xc2, 0xb3, 0xe9, 0xfb, 0xe1, 0x68, 0xf0, 0xf6, 0x98, 0xfe, 0x0d,
+    0xee, 0xd4, 0xb5, 0x18, 0xcb, 0x59, 0x70, 0x2d, 0xee, 0x06, 0xe5, 0x70, 0xf1, 0x72, 0x02, 0x6e,
+    0x47, 0x42, 0x4b, 0xbd, 0xd7, 0x23, 0xb4, 0xcd, 0xca, 0xe2, 0x8e, 0xdc, 0x6b, 0xfc, 0x23, 0xc9,
+    0x21, 0x5c, 0x48, 0x21, 0x47, 0xee, 0x5b, 0xfa, 0xaf, 0x88, 0x9a, 0x52, 0xf1, 0x61, 0x06, 0x37,
+];
+
+const EXPECTED_SIGNATURE: &[u8] = &[
+    0x44, 0xae, 0xcc, 0xe2, 0xb9, 0x96, 0x18, 0x39, 0x0e, 0x61, 0x0f, 0x53, 0x07, 0xbf, 0xf2, 0x32,
+    0x3d, 0x44, 0xd4, 0xf2, 0x07, 0x23, 0x30, 0x85, 0x32, 0x18, 0xd2, 0x69, 0xb8, 0x29, 0x3c, 0x26,
+    0xe6, 0x0d, 0x9c, 0xa5, 0xc2, 0x73, 0xcd, 0x8c, 0xb8, 0x3c, 0x3e, 0x5b, 0xfd, 0x62, 0x8d, 0xf6,
+    0xc4, 0x27, 0xa6, 0xe9, 0x11, 0x06, 0x5a, 0xb2, 0x2b, 0x64, 0xf7, 0xfc, 0xbb, 0xab, 0x4a, 0x0e,
+];
+
+#[test]
+fn hash_derive_sign_verify() {
+    let seed = hash(b"MySeedString").unwrap();
+    assert_eq!(seed, EXPECTED_SEED);
+    let cdi_attest = &seed[..CDI_SIZE];
+    assert_eq!(cdi_attest, EXPECTED_CDI_ATTEST);
+    let cdi_private_key_seed = derive_cdi_private_key_seed(cdi_attest.try_into().unwrap()).unwrap();
+    assert_eq!(cdi_private_key_seed.as_array(), EXPECTED_CDI_PRIVATE_KEY_SEED);
+    let (pub_key, priv_key) = keypair_from_seed(cdi_private_key_seed.as_array()).unwrap();
+    assert_eq!(&pub_key, EXPECTED_PUB_KEY);
+    assert_eq!(priv_key.as_array(), EXPECTED_PRIV_KEY);
+    let mut signature = sign(b"MyMessage", priv_key.as_array()).unwrap();
+    assert_eq!(&signature, EXPECTED_SIGNATURE);
+    assert!(verify(b"MyMessage", &signature, &pub_key).is_ok());
+    assert!(verify(b"MyMessage_fail", &signature, &pub_key).is_err());
+    signature[0] += 1;
+    assert!(verify(b"MyMessage", &signature, &pub_key).is_err());
+}
diff --git a/diced/open_dice_cbor/Android.bp b/diced/open_dice_cbor/Android.bp
index a84190a..a2534dc 100644
--- a/diced/open_dice_cbor/Android.bp
+++ b/diced/open_dice_cbor/Android.bp
@@ -16,29 +16,6 @@
     default_applicable_licenses: ["system_security_license"],
 }
 
-rust_library {
-    name: "libdiced_open_dice_cbor",
-    crate_name: "diced_open_dice_cbor",
-    srcs: ["lib.rs"],
-
-    rustlibs: [
-        // For ZVec
-        "libkeystore2_crypto_rust",
-        "libopen_dice_bcc_bindgen",
-        "libopen_dice_cbor_bindgen",
-        "libthiserror",
-    ],
-    static_libs: [
-        "libopen_dice_bcc",
-        "libopen_dice_cbor",
-    ],
-    vendor_available: true,
-    apex_available: [
-        "//apex_available:platform",
-        "com.android.virt",
-    ],
-}
-
 rust_test {
     name: "diced_open_dice_cbor_test",
     crate_name: "diced_open_dice_cbor_test",
@@ -46,14 +23,7 @@
     test_suites: ["general-tests"],
     auto_gen_config: true,
     rustlibs: [
+        "libdiced_open_dice",
         "libdiced_sample_inputs",
-        "libkeystore2_crypto_rust",
-        "libopen_dice_bcc_bindgen",
-        "libopen_dice_cbor_bindgen",
-        "libthiserror",
-    ],
-    static_libs: [
-        "libopen_dice_bcc",
-        "libopen_dice_cbor",
     ],
 }
diff --git a/diced/open_dice_cbor/lib.rs b/diced/open_dice_cbor/lib.rs
index ffb8a48..1650d93 100644
--- a/diced/open_dice_cbor/lib.rs
+++ b/diced/open_dice_cbor/lib.rs
@@ -12,871 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//! Implements safe wrappers around the public API of libopen-dice.
-//! ## Example:
-//! ```
-//! use diced_open_dice_cbor as dice;
-//!
-//! let context = dice::dice::OpenDiceCborContext::new()
-//! let parent_cdi_attest = [1u8, dice::CDI_SIZE];
-//! let parent_cdi_seal = [2u8, dice::CDI_SIZE];
-//! let input_values = dice::InputValuesOwned {
-//!     code_hash: [3u8, dice::HASH_SIZE],
-//!     config: dice::ConfigOwned::Descriptor("My descriptor".as_bytes().to_vec()),
-//!     authority_hash: [0u8, dice::HASH_SIZE],
-//!     mode: dice::Mode::Normal,
-//!     hidden: [0u8, dice::HIDDEN_SIZE],
-//! };
-//! let (cdi_attest, cdi_seal, cert_chain) = context
-//!     .main_flow(&parent_cdi_attest, &parent_cdi_seal, &input_values)?;
-//! ```
-
-use keystore2_crypto::{zvec, ZVec};
-use open_dice_bcc_bindgen::BccMainFlow;
-use open_dice_cbor_bindgen::{
-    DiceConfigType, DiceDeriveCdiCertificateId, DiceDeriveCdiPrivateKeySeed,
-    DiceGenerateCertificate, DiceHash, DiceInputValues, DiceKdf, DiceKeypairFromSeed, DiceMainFlow,
-    DiceMode, DiceResult, DiceSign, DiceVerify, DICE_CDI_SIZE, DICE_HASH_SIZE, DICE_HIDDEN_SIZE,
-    DICE_ID_SIZE, DICE_INLINE_CONFIG_SIZE, DICE_PRIVATE_KEY_SEED_SIZE, DICE_PRIVATE_KEY_SIZE,
-    DICE_PUBLIC_KEY_SIZE, DICE_SIGNATURE_SIZE,
-};
-use open_dice_cbor_bindgen::{
-    DiceConfigType_kDiceConfigTypeDescriptor as DICE_CONFIG_TYPE_DESCRIPTOR,
-    DiceConfigType_kDiceConfigTypeInline as DICE_CONFIG_TYPE_INLINE,
-    DiceMode_kDiceModeDebug as DICE_MODE_DEBUG,
-    DiceMode_kDiceModeMaintenance as DICE_MODE_RECOVERY,
-    DiceMode_kDiceModeNormal as DICE_MODE_NORMAL,
-    DiceMode_kDiceModeNotInitialized as DICE_MODE_NOT_CONFIGURED,
-    DiceResult_kDiceResultBufferTooSmall as DICE_RESULT_BUFFER_TOO_SMALL,
-    DiceResult_kDiceResultInvalidInput as DICE_RESULT_INVALID_INPUT,
-    DiceResult_kDiceResultOk as DICE_RESULT_OK,
-    DiceResult_kDiceResultPlatformError as DICE_RESULT_PLATFORM_ERROR,
-};
-use std::ffi::{c_void, NulError};
-
-/// The size of a DICE hash.
-pub const HASH_SIZE: usize = DICE_HASH_SIZE as usize;
-/// The size of the DICE hidden value.
-pub const HIDDEN_SIZE: usize = DICE_HIDDEN_SIZE as usize;
-/// The size of a DICE inline config.
-pub const INLINE_CONFIG_SIZE: usize = DICE_INLINE_CONFIG_SIZE as usize;
-/// The size of a private key seed.
-pub const PRIVATE_KEY_SEED_SIZE: usize = DICE_PRIVATE_KEY_SEED_SIZE as usize;
-/// The size of a CDI.
-pub const CDI_SIZE: usize = DICE_CDI_SIZE as usize;
-/// The size of an ID.
-pub const ID_SIZE: usize = DICE_ID_SIZE as usize;
-/// The size of a private key.
-pub const PRIVATE_KEY_SIZE: usize = DICE_PRIVATE_KEY_SIZE as usize;
-/// The size of a public key.
-pub const PUBLIC_KEY_SIZE: usize = DICE_PUBLIC_KEY_SIZE as usize;
-/// The size of a signature.
-pub const SIGNATURE_SIZE: usize = DICE_SIGNATURE_SIZE as usize;
-
-/// Open dice wrapper error type.
-#[derive(Debug, thiserror::Error, PartialEq, Eq)]
-pub enum Error {
-    /// The libopen-dice backend reported InvalidInput.
-    #[error("Open dice backend: Invalid input")]
-    InvalidInput,
-    /// The libopen-dice backend reported BufferTooSmall.
-    #[error("Open dice backend: Buffer too small")]
-    BufferTooSmall,
-    /// The libopen-dice backend reported PlatformError.
-    #[error("Open dice backend: Platform error")]
-    PlatformError,
-    /// The libopen-dice backend reported an error that is outside of the defined range of errors.
-    /// The returned error code is embedded in this value.
-    #[error("Open dice backend returned an unexpected error code: {0:?}")]
-    Unexpected(u32),
-
-    /// The allocation of a ZVec failed. Most likely due to a failure during the call to mlock.
-    #[error("ZVec allocation failed")]
-    ZVec(#[from] zvec::Error),
-
-    /// Functions that have to convert str to CString may fail if the string has an interior
-    /// nul byte.
-    #[error("Input string has an interior nul byte.")]
-    CStrNulError(#[from] NulError),
-}
-
-/// Open dice result type.
-pub type Result<T> = std::result::Result<T, Error>;
-
-impl From<DiceResult> for Error {
-    fn from(result: DiceResult) -> Self {
-        match result {
-            DICE_RESULT_INVALID_INPUT => Error::InvalidInput,
-            DICE_RESULT_BUFFER_TOO_SMALL => Error::BufferTooSmall,
-            DICE_RESULT_PLATFORM_ERROR => Error::PlatformError,
-            r => Error::Unexpected(r),
-        }
-    }
-}
-
-fn check_result(result: DiceResult) -> Result<()> {
-    if result == DICE_RESULT_OK {
-        Ok(())
-    } else {
-        Err(result.into())
-    }
-}
-
-/// Configuration descriptor for dice input values.
-#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
-pub enum Config<'a> {
-    /// A reference to an inline descriptor.
-    Inline(&'a [u8; INLINE_CONFIG_SIZE]),
-    /// A reference to a free form descriptor that will be hashed by the implementation.
-    Descriptor(&'a [u8]),
-}
-
-enum ConfigOwned {
-    Inline([u8; INLINE_CONFIG_SIZE]),
-    Descriptor(Vec<u8>),
-}
-
-impl Config<'_> {
-    fn get_type(&self) -> DiceConfigType {
-        match self {
-            Self::Inline(_) => DICE_CONFIG_TYPE_INLINE,
-            Self::Descriptor(_) => DICE_CONFIG_TYPE_DESCRIPTOR,
-        }
-    }
-
-    fn get_inline(&self) -> [u8; INLINE_CONFIG_SIZE] {
-        match self {
-            Self::Inline(inline) => **inline,
-            _ => [0u8; INLINE_CONFIG_SIZE],
-        }
-    }
-
-    fn get_descriptor_as_ptr(&self) -> *const u8 {
-        match self {
-            Self::Descriptor(descriptor) => descriptor.as_ptr(),
-            _ => std::ptr::null(),
-        }
-    }
-
-    fn get_descriptor_size(&self) -> usize {
-        match self {
-            Self::Descriptor(descriptor) => descriptor.len(),
-            _ => 0,
-        }
-    }
-}
-
-impl From<Config<'_>> for ConfigOwned {
-    fn from(config: Config) -> Self {
-        match config {
-            Config::Inline(inline) => ConfigOwned::Inline(*inline),
-            Config::Descriptor(descriptor) => ConfigOwned::Descriptor(descriptor.to_owned()),
-        }
-    }
-}
-
-/// DICE modes as defined here:
-/// https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md#mode-value-details
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum Mode {
-    /// See documentation linked above.
-    NotConfigured = 0,
-    /// See documentation linked above.
-    Normal = 1,
-    /// See documentation linked above.
-    Debug = 2,
-    /// See documentation linked above.
-    Recovery = 3,
-}
-
-impl Mode {
-    fn get_internal(&self) -> DiceMode {
-        match self {
-            Self::NotConfigured => DICE_MODE_NOT_CONFIGURED,
-            Self::Normal => DICE_MODE_NORMAL,
-            Self::Debug => DICE_MODE_DEBUG,
-            Self::Recovery => DICE_MODE_RECOVERY,
-        }
-    }
-}
-
-/// This trait allows API users to supply DICE input values without copying.
-pub trait InputValues {
-    /// Returns the code hash.
-    fn code_hash(&self) -> &[u8; HASH_SIZE];
-    /// Returns the config.
-    fn config(&self) -> Config;
-    /// Returns the authority hash.
-    fn authority_hash(&self) -> &[u8; HASH_SIZE];
-    /// Returns the authority descriptor.
-    fn authority_descriptor(&self) -> Option<&[u8]>;
-    /// Returns the mode.
-    fn mode(&self) -> Mode;
-    /// Returns the hidden value.
-    fn hidden(&self) -> &[u8; HIDDEN_SIZE];
-}
-
-/// An owning convenience type implementing `InputValues`.
-pub struct InputValuesOwned {
-    code_hash: [u8; HASH_SIZE],
-    config: ConfigOwned,
-    authority_hash: [u8; HASH_SIZE],
-    authority_descriptor: Option<Vec<u8>>,
-    mode: Mode,
-    hidden: [u8; HIDDEN_SIZE],
-}
-
-impl InputValuesOwned {
-    /// Construct a new instance of InputValuesOwned.
-    pub fn new(
-        code_hash: [u8; HASH_SIZE],
-        config: Config,
-        authority_hash: [u8; HASH_SIZE],
-        authority_descriptor: Option<Vec<u8>>,
-        mode: Mode,
-        hidden: [u8; HIDDEN_SIZE],
-    ) -> Self {
-        Self {
-            code_hash,
-            config: config.into(),
-            authority_hash,
-            authority_descriptor,
-            mode,
-            hidden,
-        }
-    }
-}
-
-impl InputValues for InputValuesOwned {
-    fn code_hash(&self) -> &[u8; HASH_SIZE] {
-        &self.code_hash
-    }
-    fn config(&self) -> Config {
-        match &self.config {
-            ConfigOwned::Inline(inline) => Config::Inline(inline),
-            ConfigOwned::Descriptor(descriptor) => Config::Descriptor(descriptor.as_slice()),
-        }
-    }
-    fn authority_hash(&self) -> &[u8; HASH_SIZE] {
-        &self.authority_hash
-    }
-    fn authority_descriptor(&self) -> Option<&[u8]> {
-        self.authority_descriptor.as_deref()
-    }
-    fn mode(&self) -> Mode {
-        self.mode
-    }
-    fn hidden(&self) -> &[u8; HIDDEN_SIZE] {
-        &self.hidden
-    }
-}
-
-fn call_with_input_values<T: InputValues + ?Sized, F, R>(input_values: &T, f: F) -> Result<R>
-where
-    F: FnOnce(*const DiceInputValues) -> Result<R>,
-{
-    let input_values = DiceInputValues {
-        code_hash: *input_values.code_hash(),
-        code_descriptor: std::ptr::null(),
-        code_descriptor_size: 0,
-        config_type: input_values.config().get_type(),
-        config_value: input_values.config().get_inline(),
-        config_descriptor: input_values.config().get_descriptor_as_ptr(),
-        config_descriptor_size: input_values.config().get_descriptor_size(),
-        authority_hash: *input_values.authority_hash(),
-        authority_descriptor: input_values
-            .authority_descriptor()
-            .map_or_else(std::ptr::null, <[u8]>::as_ptr),
-        authority_descriptor_size: input_values.authority_descriptor().map_or(0, <[u8]>::len),
-        mode: input_values.mode().get_internal(),
-        hidden: *input_values.hidden(),
-    };
-
-    f(&input_values as *const DiceInputValues)
-}
-
-/// Multiple of the open dice function required preallocated output buffer
-/// which may be too small, this function implements the retry logic to handle
-/// too small buffer allocations.
-/// The callback `F` must expect a mutable reference to a buffer and a size hint
-/// field. The callback is called repeatedly as long as it returns
-/// `Err(Error::BufferTooSmall)`. If the size hint remains 0, the buffer size is
-/// doubled with each iteration. If the size hint is set by the callback, the buffer
-/// will be set to accommodate at least this many bytes.
-/// If the callback returns `Ok(())`, the buffer is truncated to the size hint
-/// exactly.
-/// The function panics if the callback returns `Ok(())` and the size hint is
-/// larger than the buffer size.
-fn retry_while_adjusting_output_buffer<F>(mut f: F) -> Result<Vec<u8>>
-where
-    F: FnMut(&mut Vec<u8>, &mut usize) -> Result<()>,
-{
-    let mut buffer = vec![0; INITIAL_OUT_BUFFER_SIZE];
-    let mut actual_size: usize = 0;
-    loop {
-        match f(&mut buffer, &mut actual_size) {
-            // If Error::BufferTooSmall was returned, the allocated certificate
-            // buffer was to small for the output. So the buffer is resized to the actual
-            // size, and a second attempt is made with the new buffer.
-            Err(Error::BufferTooSmall) => {
-                let new_size = if actual_size == 0 {
-                    // Due to an off spec implementation of open dice cbor, actual size
-                    // does not return the required size if the buffer was too small. So
-                    // we have to try and approach it gradually.
-                    buffer.len() * 2
-                } else {
-                    actual_size
-                };
-                buffer.resize(new_size, 0);
-                continue;
-            }
-            Err(e) => return Err(e),
-            Ok(()) => {
-                if actual_size > buffer.len() {
-                    panic!(
-                        "actual_size larger than buffer size: open-dice function
-                         may have written past the end of the buffer."
-                    );
-                }
-                // Truncate the certificate buffer to the actual size because it may be
-                // smaller than the original allocation.
-                buffer.truncate(actual_size);
-                return Ok(buffer);
-            }
-        }
-    }
-}
-
-/// Some libopen-dice variants use a context. Developers that want to customize these
-/// bindings may want to implement their own Context factory that creates a context
-/// useable by their preferred backend.
-pub trait Context {
-    /// # Safety
-    /// The return value of get_context is passed to any open dice function.
-    /// Implementations must explain why the context pointer returned is safe
-    /// to be used by the open dice library.
-    unsafe fn get_context(&mut self) -> *mut c_void;
-}
-
-impl<T: Context + Send> ContextImpl for T {}
-
-/// This represents a context for the open dice library. The wrapped open dice instance, which
-/// is based on boringssl and cbor, does not use a context, so that this type is empty.
-#[derive(Default)]
-pub struct OpenDiceCborContext();
-
-impl OpenDiceCborContext {
-    /// Construct a new instance of OpenDiceCborContext.
-    pub fn new() -> Self {
-        Default::default()
-    }
-}
-
-impl Context for OpenDiceCborContext {
-    unsafe fn get_context(&mut self) -> *mut c_void {
-        // # Safety
-        // The open dice cbor implementation does not use a context. It is safe
-        // to return NULL.
-        std::ptr::null_mut()
-    }
-}
-
-/// Type alias for ZVec indicating that it holds a CDI_ATTEST secret.
-pub type CdiAttest = ZVec;
-
-/// Type alias for ZVec indicating that it holds a CDI_SEAL secret.
-pub type CdiSeal = ZVec;
-
-/// Type alias for Vec<u8> indicating that it hold a DICE certificate.
-pub type Cert = Vec<u8>;
-
-/// Type alias for Vec<u8> indicating that it holds a BCC certificate chain.
-pub type Bcc = Vec<u8>;
-
-const INITIAL_OUT_BUFFER_SIZE: usize = 1024;
-
-/// ContextImpl is a mixin trait that implements the safe wrappers around the open dice
-/// library calls. Implementations must implement Context::get_context(). As of
-/// this writing, the only implementation is OpenDiceCborContext, which returns NULL.
-pub trait ContextImpl: Context + Send {
-    /// Safe wrapper around open-dice DiceDeriveCdiPrivateKeySeed, see open dice
-    /// documentation for details.
-    fn derive_cdi_private_key_seed(&mut self, cdi_attest: &[u8; CDI_SIZE]) -> Result<ZVec> {
-        let mut seed = ZVec::new(PRIVATE_KEY_SEED_SIZE)?;
-        // SAFETY:
-        // * The first context argument may be NULL and is unused by the wrapped
-        //   implementation.
-        // * The second argument is expected to be a const array of size CDI_SIZE.
-        // * The third argument is expected to be a non const array of size
-        //   PRIVATE_KEY_SEED_SIZE which is fulfilled if the call to ZVec::new above
-        //   succeeds.
-        // * No pointers are expected to be valid beyond the scope of the function
-        //   call.
-        check_result(unsafe {
-            DiceDeriveCdiPrivateKeySeed(self.get_context(), cdi_attest.as_ptr(), seed.as_mut_ptr())
-        })?;
-        Ok(seed)
-    }
-
-    /// Safe wrapper around open-dice DiceDeriveCdiCertificateId, see open dice
-    /// documentation for details.
-    fn derive_cdi_certificate_id(&mut self, cdi_public_key: &[u8]) -> Result<ZVec> {
-        let mut id = ZVec::new(ID_SIZE)?;
-        // SAFETY:
-        // * The first context argument may be NULL and is unused by the wrapped
-        //   implementation.
-        // * The second argument is expected to be a const array with a size given by the
-        //   third argument.
-        // * The fourth argument is expected to be a non const array of size
-        //   ID_SIZE which is fulfilled if the call to ZVec::new above succeeds.
-        // * No pointers are expected to be valid beyond the scope of the function
-        //   call.
-        check_result(unsafe {
-            DiceDeriveCdiCertificateId(
-                self.get_context(),
-                cdi_public_key.as_ptr(),
-                cdi_public_key.len(),
-                id.as_mut_ptr(),
-            )
-        })?;
-        Ok(id)
-    }
-
-    /// Safe wrapper around open-dice DiceMainFlow, see open dice
-    /// documentation for details.
-    /// Returns a tuple of:
-    ///  * The next attestation CDI,
-    ///  * the next seal CDI, and
-    ///  * the next attestation certificate.
-    /// `(next_attest_cdi, next_seal_cdi, next_attestation_cert)`
-    fn main_flow<T: InputValues + ?Sized>(
-        &mut self,
-        current_cdi_attest: &[u8; CDI_SIZE],
-        current_cdi_seal: &[u8; CDI_SIZE],
-        input_values: &T,
-    ) -> Result<(CdiAttest, CdiSeal, Cert)> {
-        let mut next_attest = CdiAttest::new(CDI_SIZE)?;
-        let mut next_seal = CdiSeal::new(CDI_SIZE)?;
-
-        // SAFETY (DiceMainFlow):
-        // * The first context argument may be NULL and is unused by the wrapped
-        //   implementation.
-        // * The second argument and the third argument are const arrays of size CDI_SIZE.
-        //   This is fulfilled as per the definition of the arguments `current_cdi_attest`
-        //   and `current_cdi_seal.
-        // * The fourth argument is a pointer to `DiceInputValues`. It, and its indirect
-        //   references must be valid for the duration of the function call which
-        //   is guaranteed by `call_with_input_values` which puts `DiceInputValues`
-        //   on the stack and initializes it from the `input_values` argument which
-        //   implements the `InputValues` trait.
-        // * The fifth and sixth argument are the length of and the pointer to the
-        //   allocated certificate buffer respectively. They are used to return
-        //   the generated certificate.
-        // * The seventh argument is a pointer to a mutable usize object. It is
-        //   used to return the actual size of the output certificate.
-        // * The eighth argument and the ninth argument are pointers to mutable buffers of size
-        //   CDI_SIZE. This is fulfilled if the allocation above succeeded.
-        // * No pointers are expected to be valid beyond the scope of the function
-        //   call.
-        call_with_input_values(input_values, |input_values| {
-            let cert = retry_while_adjusting_output_buffer(|cert, actual_size| {
-                check_result(unsafe {
-                    DiceMainFlow(
-                        self.get_context(),
-                        current_cdi_attest.as_ptr(),
-                        current_cdi_seal.as_ptr(),
-                        input_values,
-                        cert.len(),
-                        cert.as_mut_ptr(),
-                        actual_size as *mut _,
-                        next_attest.as_mut_ptr(),
-                        next_seal.as_mut_ptr(),
-                    )
-                })
-            })?;
-            Ok((next_attest, next_seal, cert))
-        })
-    }
-
-    /// Safe wrapper around open-dice DiceHash, see open dice
-    /// documentation for details.
-    fn hash(&mut self, input: &[u8]) -> Result<Vec<u8>> {
-        let mut output: Vec<u8> = vec![0; HASH_SIZE];
-
-        // SAFETY:
-        // * The first context argument may be NULL and is unused by the wrapped
-        //   implementation.
-        // * The second argument and the third argument are the pointer to and length of the given
-        //   input buffer respectively.
-        // * The fourth argument must be a pointer to a mutable buffer of size HASH_SIZE
-        //   which is fulfilled by the allocation above.
-        check_result(unsafe {
-            DiceHash(self.get_context(), input.as_ptr(), input.len(), output.as_mut_ptr())
-        })?;
-        Ok(output)
-    }
-
-    /// Safe wrapper around open-dice DiceKdf, see open dice
-    /// documentation for details.
-    fn kdf(&mut self, length: usize, input_key: &[u8], salt: &[u8], info: &[u8]) -> Result<ZVec> {
-        let mut output = ZVec::new(length)?;
-
-        // SAFETY:
-        // * The first context argument may be NULL and is unused by the wrapped
-        //   implementation.
-        // * The second argument is primitive.
-        // * The third argument and the fourth argument are the pointer to and length of the given
-        //   input key.
-        // * The fifth argument and the sixth argument are the pointer to and length of the given
-        //   salt.
-        // * The seventh argument and the eighth argument are the pointer to and length of the
-        //   given info field.
-        // * The ninth argument is a pointer to the output buffer which must have the
-        //   length given by the `length` argument (see second argument). This is
-        //   fulfilled if the allocation of `output` succeeds.
-        // * All pointers must be valid for the duration of the function call, but not
-        //   longer.
-        check_result(unsafe {
-            DiceKdf(
-                self.get_context(),
-                length,
-                input_key.as_ptr(),
-                input_key.len(),
-                salt.as_ptr(),
-                salt.len(),
-                info.as_ptr(),
-                info.len(),
-                output.as_mut_ptr(),
-            )
-        })?;
-        Ok(output)
-    }
-
-    /// Safe wrapper around open-dice DiceKeyPairFromSeed, see open dice
-    /// documentation for details.
-    fn keypair_from_seed(&mut self, seed: &[u8; PRIVATE_KEY_SEED_SIZE]) -> Result<(Vec<u8>, ZVec)> {
-        let mut private_key = ZVec::new(PRIVATE_KEY_SIZE)?;
-        let mut public_key = vec![0u8; PUBLIC_KEY_SIZE];
-
-        // SAFETY:
-        // * The first context argument may be NULL and is unused by the wrapped
-        //   implementation.
-        // * The second argument is a pointer to a const buffer of size `PRIVATE_KEY_SEED_SIZE`
-        //   fulfilled by the definition of the argument.
-        // * The third argument and the fourth argument are mutable buffers of size
-        //   `PRIVATE_KEY_SIZE` and `PUBLIC_KEY_SIZE` respectively. This is fulfilled by the
-        //   allocations above.
-        // * All pointers must be valid for the duration of the function call but not beyond.
-        check_result(unsafe {
-            DiceKeypairFromSeed(
-                self.get_context(),
-                seed.as_ptr(),
-                public_key.as_mut_ptr(),
-                private_key.as_mut_ptr(),
-            )
-        })?;
-        Ok((public_key, private_key))
-    }
-
-    /// Safe wrapper around open-dice DiceSign, see open dice
-    /// documentation for details.
-    fn sign(&mut self, message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Vec<u8>> {
-        let mut signature = vec![0u8; SIGNATURE_SIZE];
-
-        // SAFETY:
-        // * The first context argument may be NULL and is unused by the wrapped
-        //   implementation.
-        // * The second argument and the third argument are the pointer to and length of the given
-        //   message buffer.
-        // * The fourth argument is a const buffer of size `PRIVATE_KEY_SIZE`. This is fulfilled
-        //   by the definition of `private key`.
-        // * The fifth argument is mutable buffer of size `SIGNATURE_SIZE`. This is fulfilled
-        //   by the allocation above.
-        // * All pointers must be valid for the duration of the function call but not beyond.
-        check_result(unsafe {
-            DiceSign(
-                self.get_context(),
-                message.as_ptr(),
-                message.len(),
-                private_key.as_ptr(),
-                signature.as_mut_ptr(),
-            )
-        })?;
-        Ok(signature)
-    }
-
-    /// Safe wrapper around open-dice DiceVerify, see open dice
-    /// documentation for details.
-    fn verify(
-        &mut self,
-        message: &[u8],
-        signature: &[u8; SIGNATURE_SIZE],
-        public_key: &[u8; PUBLIC_KEY_SIZE],
-    ) -> Result<()> {
-        // SAFETY:
-        // * The first context argument may be NULL and is unused by the wrapped
-        //   implementation.
-        // * The second argument and the third argument are the pointer to and length of the given
-        //   message buffer.
-        // * The fourth argument is a const buffer of size `SIGNATURE_SIZE`. This is fulfilled
-        //   by the definition of `signature`.
-        // * The fifth argument is a const buffer of size `PUBLIC_KEY_SIZE`. This is fulfilled
-        //   by the definition of `public_key`.
-        // * All pointers must be valid for the duration of the function call but not beyond.
-        check_result(unsafe {
-            DiceVerify(
-                self.get_context(),
-                message.as_ptr(),
-                message.len(),
-                signature.as_ptr(),
-                public_key.as_ptr(),
-            )
-        })
-    }
-
-    /// Safe wrapper around open-dice DiceGenerateCertificate, see open dice
-    /// documentation for details.
-    fn generate_certificate<T: InputValues>(
-        &mut self,
-        subject_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
-        authority_private_key_seed: &[u8; PRIVATE_KEY_SEED_SIZE],
-        input_values: &T,
-    ) -> Result<Vec<u8>> {
-        // SAFETY (DiceMainFlow):
-        // * The first context argument may be NULL and is unused by the wrapped
-        //   implementation.
-        // * The second argument and the third argument are const arrays of size
-        //   `PRIVATE_KEY_SEED_SIZE`. This is fulfilled as per the definition of the arguments.
-        // * The fourth argument is a pointer to `DiceInputValues` it, and its indirect
-        //   references must be valid for the duration of the function call which
-        //   is guaranteed by `call_with_input_values` which puts `DiceInputValues`
-        //   on the stack and initializes it from the `input_values` argument which
-        //   implements the `InputValues` trait.
-        // * The fifth argument and the sixth argument are the length of and the pointer to the
-        //   allocated certificate buffer respectively. They are used to return
-        //   the generated certificate.
-        // * The seventh argument is a pointer to a mutable usize object. It is
-        //   used to return the actual size of the output certificate.
-        // * All pointers must be valid for the duration of the function call but not beyond.
-        call_with_input_values(input_values, |input_values| {
-            let cert = retry_while_adjusting_output_buffer(|cert, actual_size| {
-                check_result(unsafe {
-                    DiceGenerateCertificate(
-                        self.get_context(),
-                        subject_private_key_seed.as_ptr(),
-                        authority_private_key_seed.as_ptr(),
-                        input_values,
-                        cert.len(),
-                        cert.as_mut_ptr(),
-                        actual_size as *mut _,
-                    )
-                })
-            })?;
-            Ok(cert)
-        })
-    }
-
-    /// Safe wrapper around open-dice BccDiceMainFlow, see open dice
-    /// documentation for details.
-    /// Returns a tuple of:
-    ///  * The next attestation CDI,
-    ///  * the next seal CDI, and
-    ///  * the next bcc adding the new certificate to the given bcc.
-    /// `(next_attest_cdi, next_seal_cdi, next_bcc)`
-    fn bcc_main_flow<T: InputValues + ?Sized>(
-        &mut self,
-        current_cdi_attest: &[u8; CDI_SIZE],
-        current_cdi_seal: &[u8; CDI_SIZE],
-        bcc: &[u8],
-        input_values: &T,
-    ) -> Result<(CdiAttest, CdiSeal, Bcc)> {
-        let mut next_attest = CdiAttest::new(CDI_SIZE)?;
-        let mut next_seal = CdiSeal::new(CDI_SIZE)?;
-
-        // SAFETY (BccMainFlow):
-        // * The first context argument may be NULL and is unused by the wrapped
-        //   implementation.
-        // * The second argument and the third argument are const arrays of size CDI_SIZE.
-        //   This is fulfilled as per the definition of the arguments `current_cdi_attest`
-        //   and `current_cdi_seal`.
-        // * The fourth argument and the fifth argument are the pointer to and size of the buffer
-        //   holding the current bcc.
-        // * The sixth argument is a pointer to `DiceInputValues` it, and its indirect
-        //   references must be valid for the duration of the function call which
-        //   is guaranteed by `call_with_input_values` which puts `DiceInputValues`
-        //   on the stack and initializes it from the `input_values` argument which
-        //   implements the `InputValues` trait.
-        // * The seventh argument and the eighth argument are the length of and the pointer to the
-        //   allocated certificate buffer respectively. They are used to return the generated
-        //   certificate.
-        // * The ninth argument is a pointer to a mutable usize object. It is
-        //   used to return the actual size of the output certificate.
-        // * The tenth argument and the eleventh argument are pointers to mutable buffers of
-        //   size CDI_SIZE. This is fulfilled if the allocation above succeeded.
-        // * No pointers are expected to be valid beyond the scope of the function
-        //   call.
-        call_with_input_values(input_values, |input_values| {
-            let next_bcc = retry_while_adjusting_output_buffer(|next_bcc, actual_size| {
-                check_result(unsafe {
-                    BccMainFlow(
-                        self.get_context(),
-                        current_cdi_attest.as_ptr(),
-                        current_cdi_seal.as_ptr(),
-                        bcc.as_ptr(),
-                        bcc.len(),
-                        input_values,
-                        next_bcc.len(),
-                        next_bcc.as_mut_ptr(),
-                        actual_size as *mut _,
-                        next_attest.as_mut_ptr(),
-                        next_seal.as_mut_ptr(),
-                    )
-                })
-            })?;
-            Ok((next_attest, next_seal, next_bcc))
-        })
-    }
-}
-
-/// This submodule provides additional support for the Boot Certificate Chain (BCC)
-/// specification.
-/// See https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
-pub mod bcc {
-    use super::{check_result, retry_while_adjusting_output_buffer, Result};
-    use open_dice_bcc_bindgen::{
-        BccConfigValues, BccFormatConfigDescriptor, BCC_INPUT_COMPONENT_NAME,
-        BCC_INPUT_COMPONENT_VERSION, BCC_INPUT_RESETTABLE,
-    };
-    use std::ffi::CString;
-
-    /// Safe wrapper around BccFormatConfigDescriptor, see open dice documentation for details.
-    pub fn format_config_descriptor(
-        component_name: Option<&str>,
-        component_version: Option<u64>,
-        resettable: bool,
-    ) -> Result<Vec<u8>> {
-        let component_name = match component_name {
-            Some(n) => Some(CString::new(n)?),
-            None => None,
-        };
-        let input = BccConfigValues {
-            inputs: if component_name.is_some() { BCC_INPUT_COMPONENT_NAME } else { 0 }
-                | if component_version.is_some() { BCC_INPUT_COMPONENT_VERSION } else { 0 }
-                | if resettable { BCC_INPUT_RESETTABLE } else { 0 },
-            // SAFETY: The as_ref() in the line below is vital to keep the component_name object
-            //         alive. Removing as_ref will move the component_name and the pointer will
-            //         become invalid after this statement.
-            component_name: component_name.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
-            component_version: component_version.unwrap_or(0),
-        };
-
-        // SAFETY:
-        // * The first argument is a pointer to the BccConfigValues input assembled above.
-        //   It and its indirections must be valid for the duration of the function call.
-        // * The second argument and the third argument are the length of and the pointer to the
-        //   allocated output buffer respectively. The buffer must be at least as long
-        //   as indicated by the size argument.
-        // * The forth argument is a pointer to the actual size returned by the function.
-        // * All pointers must be valid for the duration of the function call but not beyond.
-        retry_while_adjusting_output_buffer(|config_descriptor, actual_size| {
-            check_result(unsafe {
-                BccFormatConfigDescriptor(
-                    &input as *const BccConfigValues,
-                    config_descriptor.len(),
-                    config_descriptor.as_mut_ptr(),
-                    actual_size as *mut _,
-                )
-            })
-        })
-    }
-}
-
+// TODO(b/267575445): Move the tests to other target and remove the folder `open_dice_cbor` completely.
 #[cfg(test)]
 mod test {
-    use super::*;
+    use diced_open_dice::DiceArtifacts;
     use diced_sample_inputs::make_sample_bcc_and_cdis;
-    use std::convert::TryInto;
-
-    static SEED_TEST_VECTOR: &[u8] = &[
-        0xfa, 0x3c, 0x2f, 0x58, 0x37, 0xf5, 0x8e, 0x96, 0x16, 0x09, 0xf5, 0x22, 0xa1, 0xf1, 0xba,
-        0xaa, 0x19, 0x95, 0x01, 0x79, 0x2e, 0x60, 0x56, 0xaf, 0xf6, 0x41, 0xe7, 0xff, 0x48, 0xf5,
-        0x3a, 0x08, 0x84, 0x8a, 0x98, 0x85, 0x6d, 0xf5, 0x69, 0x21, 0x03, 0xcd, 0x09, 0xc3, 0x28,
-        0xd6, 0x06, 0xa7, 0x57, 0xbd, 0x48, 0x4b, 0x0f, 0x79, 0x0f, 0xf8, 0x2f, 0xf0, 0x0a, 0x41,
-        0x94, 0xd8, 0x8c, 0xa8,
-    ];
-
-    static CDI_ATTEST_TEST_VECTOR: &[u8] = &[
-        0xfa, 0x3c, 0x2f, 0x58, 0x37, 0xf5, 0x8e, 0x96, 0x16, 0x09, 0xf5, 0x22, 0xa1, 0xf1, 0xba,
-        0xaa, 0x19, 0x95, 0x01, 0x79, 0x2e, 0x60, 0x56, 0xaf, 0xf6, 0x41, 0xe7, 0xff, 0x48, 0xf5,
-        0x3a, 0x08,
-    ];
-    static CDI_PRIVATE_KEY_SEED_TEST_VECTOR: &[u8] = &[
-        0x5f, 0xcc, 0x8e, 0x1a, 0xd1, 0xc2, 0xb3, 0xe9, 0xfb, 0xe1, 0x68, 0xf0, 0xf6, 0x98, 0xfe,
-        0x0d, 0xee, 0xd4, 0xb5, 0x18, 0xcb, 0x59, 0x70, 0x2d, 0xee, 0x06, 0xe5, 0x70, 0xf1, 0x72,
-        0x02, 0x6e,
-    ];
-
-    static PUB_KEY_TEST_VECTOR: &[u8] = &[
-        0x47, 0x42, 0x4b, 0xbd, 0xd7, 0x23, 0xb4, 0xcd, 0xca, 0xe2, 0x8e, 0xdc, 0x6b, 0xfc, 0x23,
-        0xc9, 0x21, 0x5c, 0x48, 0x21, 0x47, 0xee, 0x5b, 0xfa, 0xaf, 0x88, 0x9a, 0x52, 0xf1, 0x61,
-        0x06, 0x37,
-    ];
-    static PRIV_KEY_TEST_VECTOR: &[u8] = &[
-        0x5f, 0xcc, 0x8e, 0x1a, 0xd1, 0xc2, 0xb3, 0xe9, 0xfb, 0xe1, 0x68, 0xf0, 0xf6, 0x98, 0xfe,
-        0x0d, 0xee, 0xd4, 0xb5, 0x18, 0xcb, 0x59, 0x70, 0x2d, 0xee, 0x06, 0xe5, 0x70, 0xf1, 0x72,
-        0x02, 0x6e, 0x47, 0x42, 0x4b, 0xbd, 0xd7, 0x23, 0xb4, 0xcd, 0xca, 0xe2, 0x8e, 0xdc, 0x6b,
-        0xfc, 0x23, 0xc9, 0x21, 0x5c, 0x48, 0x21, 0x47, 0xee, 0x5b, 0xfa, 0xaf, 0x88, 0x9a, 0x52,
-        0xf1, 0x61, 0x06, 0x37,
-    ];
-
-    static SIGNATURE_TEST_VECTOR: &[u8] = &[
-        0x44, 0xae, 0xcc, 0xe2, 0xb9, 0x96, 0x18, 0x39, 0x0e, 0x61, 0x0f, 0x53, 0x07, 0xbf, 0xf2,
-        0x32, 0x3d, 0x44, 0xd4, 0xf2, 0x07, 0x23, 0x30, 0x85, 0x32, 0x18, 0xd2, 0x69, 0xb8, 0x29,
-        0x3c, 0x26, 0xe6, 0x0d, 0x9c, 0xa5, 0xc2, 0x73, 0xcd, 0x8c, 0xb8, 0x3c, 0x3e, 0x5b, 0xfd,
-        0x62, 0x8d, 0xf6, 0xc4, 0x27, 0xa6, 0xe9, 0x11, 0x06, 0x5a, 0xb2, 0x2b, 0x64, 0xf7, 0xfc,
-        0xbb, 0xab, 0x4a, 0x0e,
-    ];
-
-    #[test]
-    fn hash_derive_sign_verify() {
-        let mut ctx = OpenDiceCborContext::new();
-        let seed = ctx.hash("MySeedString".as_bytes()).unwrap();
-        assert_eq!(seed, SEED_TEST_VECTOR);
-        let cdi_attest = &seed[..CDI_SIZE];
-        assert_eq!(cdi_attest, CDI_ATTEST_TEST_VECTOR);
-        let cdi_private_key_seed =
-            ctx.derive_cdi_private_key_seed(cdi_attest.try_into().unwrap()).unwrap();
-        assert_eq!(&cdi_private_key_seed[..], CDI_PRIVATE_KEY_SEED_TEST_VECTOR);
-        let (pub_key, priv_key) =
-            ctx.keypair_from_seed(cdi_private_key_seed[..].try_into().unwrap()).unwrap();
-        assert_eq!(&pub_key, PUB_KEY_TEST_VECTOR);
-        assert_eq!(&priv_key[..], PRIV_KEY_TEST_VECTOR);
-        let mut signature =
-            ctx.sign("MyMessage".as_bytes(), priv_key[..].try_into().unwrap()).unwrap();
-        assert_eq!(&signature, SIGNATURE_TEST_VECTOR);
-        assert!(ctx
-            .verify(
-                "MyMessage".as_bytes(),
-                signature[..].try_into().unwrap(),
-                pub_key[..].try_into().unwrap()
-            )
-            .is_ok());
-        assert!(ctx
-            .verify(
-                "MyMessage_fail".as_bytes(),
-                signature[..].try_into().unwrap(),
-                pub_key[..].try_into().unwrap()
-            )
-            .is_err());
-        signature[0] += 1;
-        assert!(ctx
-            .verify(
-                "MyMessage".as_bytes(),
-                signature[..].try_into().unwrap(),
-                pub_key[..].try_into().unwrap()
-            )
-            .is_err());
-    }
 
     static SAMPLE_CDI_ATTEST_TEST_VECTOR: &[u8] = &[
         0x3e, 0x57, 0x65, 0x5d, 0x48, 0x02, 0xbd, 0x5c, 0x66, 0xcc, 0x1f, 0x0f, 0xbe, 0x5e, 0x32,
@@ -997,41 +137,9 @@
     // and changes in any of those functions.
     #[test]
     fn main_flow_and_bcc_main_flow() {
-        let (cdi_attest, cdi_seal, bcc) = make_sample_bcc_and_cdis().unwrap();
-        assert_eq!(&cdi_attest[..], SAMPLE_CDI_ATTEST_TEST_VECTOR);
-        assert_eq!(&cdi_seal[..], SAMPLE_CDI_SEAL_TEST_VECTOR);
-        assert_eq!(&bcc[..], SAMPLE_BCC_TEST_VECTOR);
-    }
-
-    static DERIVED_KEY_TEST_VECTOR: &[u8] = &[
-        0x0e, 0xd6, 0x07, 0x0e, 0x1c, 0x38, 0x2c, 0x76, 0x13, 0xc6, 0x76, 0x25, 0x7e, 0x07, 0x6f,
-        0xdb, 0x1d, 0xb1, 0x0f, 0x3f, 0xed, 0xc5, 0x2b, 0x95, 0xd1, 0x32, 0xf1, 0x63, 0x2f, 0x2a,
-        0x01, 0x5e,
-    ];
-
-    #[test]
-    fn kdf() {
-        let mut ctx = OpenDiceCborContext::new();
-        let derived_key = ctx
-            .kdf(
-                PRIVATE_KEY_SEED_SIZE,
-                "myKey".as_bytes(),
-                "mySalt".as_bytes(),
-                "myInfo".as_bytes(),
-            )
-            .unwrap();
-        assert_eq!(&derived_key[..], DERIVED_KEY_TEST_VECTOR);
-    }
-
-    static CERT_ID_TEST_VECTOR: &[u8] = &[
-        0x7a, 0x36, 0x45, 0x2c, 0x02, 0xf6, 0x2b, 0xec, 0xf9, 0x80, 0x06, 0x75, 0x87, 0xa5, 0xc1,
-        0x44, 0x0c, 0xd3, 0xc0, 0x6d,
-    ];
-
-    #[test]
-    fn derive_cdi_certificate_id() {
-        let mut ctx = OpenDiceCborContext::new();
-        let cert_id = ctx.derive_cdi_certificate_id("MyPubKey".as_bytes()).unwrap();
-        assert_eq!(&cert_id[..], CERT_ID_TEST_VECTOR);
+        let dice_artifacts = make_sample_bcc_and_cdis().unwrap();
+        assert_eq!(dice_artifacts.cdi_attest(), SAMPLE_CDI_ATTEST_TEST_VECTOR);
+        assert_eq!(dice_artifacts.cdi_seal(), SAMPLE_CDI_SEAL_TEST_VECTOR);
+        assert_eq!(dice_artifacts.bcc(), Some(SAMPLE_BCC_TEST_VECTOR));
     }
 }
diff --git a/diced/src/diced_client_test.rs b/diced/src/diced_client_test.rs
deleted file mode 100644
index 3915508..0000000
--- a/diced/src/diced_client_test.rs
+++ /dev/null
@@ -1,188 +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_cbor as dice;
-use nix::libc::uid_t;
-use std::convert::TryInto;
-
-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 input_values: Vec<diced_utils::InputValues> =
-        input_values.iter().map(|v| v.into()).collect();
-
-    let artifacts =
-        artifacts.execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues)).unwrap();
-    let (cdi_attest, cdi_seal, bcc) = artifacts.into_tuple();
-    let from_former = diced_utils::make_bcc_handover(
-        cdi_attest[..].try_into().unwrap(),
-        cdi_seal[..].try_into().unwrap(),
-        &bcc,
-    )
-    .unwrap();
-    // TODO 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 input_values: Vec<diced_utils::InputValues> =
-        input_values.iter().map(|v| v.into()).collect();
-
-    let artifacts =
-        artifacts.execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues)).unwrap();
-    let (cdi_attest, cdi_seal, bcc) = artifacts.into_tuple();
-    let from_former = diced_utils::make_bcc_handover(
-        cdi_attest[..].try_into().unwrap(),
-        cdi_seal[..].try_into().unwrap(),
-        &bcc,
-    )
-    .unwrap();
-    // TODO b/204938506 when we have a parser/verifier, check equivalence rather
-    // than bit by bit equality.
-    assert_eq!(latter, from_former);
-}
-
-fn client_input_values(uid: uid_t) -> BinderInputValues {
-    BinderInputValues {
-        codeHash: [0; dice::HASH_SIZE],
-        config: BinderConfig {
-            desc: dice::bcc::format_config_descriptor(Some(&format!("{}", uid)), 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 input_values: Vec<diced_utils::InputValues> =
-        input_values.iter().chain(client.iter()).map(|v| v.into()).collect();
-
-    let artifacts =
-        artifacts.execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues)).unwrap();
-    let (cdi_attest, cdi_seal, bcc) = artifacts.into_tuple();
-    let from_former = diced_utils::make_bcc_handover(
-        cdi_attest[..].try_into().unwrap(),
-        cdi_seal[..].try_into().unwrap(),
-        &bcc,
-    )
-    .unwrap();
-    // TODO b/204938506 when we have a parser/verifier, check equivalence rather
-    // than bit by bit equality.
-    assert_eq!(latter, from_former);
-}
-
-#[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/diced_main.rs b/diced/src/diced_main.rs
deleted file mode 100644
index c2cf02c..0000000
--- a/diced/src/diced_main.rs
+++ /dev/null
@@ -1,76 +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.
-
-//! Main entry point for diced, the friendly neighborhood DICE service.
-
-use binder::get_interface;
-use diced::{DiceMaintenance, DiceNode, DiceNodeImpl, ProxyNodeHal, ResidentNode};
-use std::convert::TryInto;
-use std::panic;
-use std::sync::Arc;
-
-static DICE_NODE_SERVICE_NAME: &str = "android.security.dice.IDiceNode";
-static DICE_MAINTENANCE_SERVICE_NAME: &str = "android.security.dice.IDiceMaintenance";
-static DICE_HAL_SERVICE_NAME: &str = "android.hardware.security.dice.IDiceDevice/default";
-
-fn main() {
-    android_logger::init_once(
-        android_logger::Config::default().with_tag("diced").with_min_level(log::Level::Debug),
-    );
-    // Redirect panic messages to logcat.
-    panic::set_hook(Box::new(|panic_info| {
-        log::error!("{}", panic_info);
-    }));
-
-    // Saying hi.
-    log::info!("Diced, your friendly neighborhood DICE service, is starting.");
-
-    let node_impl: Arc<dyn DiceNodeImpl + Send + Sync> = match get_interface(DICE_HAL_SERVICE_NAME)
-    {
-        Ok(dice_device) => {
-            Arc::new(ProxyNodeHal::new(dice_device).expect("Failed to construct a proxy node."))
-        }
-        Err(e) => {
-            log::warn!("Failed to connect to DICE HAL: {:?}", e);
-            log::warn!("Using sample dice artifacts.");
-            let (cdi_attest, cdi_seal, bcc) = diced_sample_inputs::make_sample_bcc_and_cdis()
-                .expect("Failed to create sample dice artifacts.");
-            Arc::new(
-                ResidentNode::new(
-                    cdi_attest[..]
-                        .try_into()
-                        .expect("Failed to convert cdi_attest into array ref."),
-                    cdi_seal[..].try_into().expect("Failed to convert cdi_seal into array ref."),
-                    bcc,
-                )
-                .expect("Failed to construct a resident node."),
-            )
-        }
-    };
-
-    let node = DiceNode::new_as_binder(node_impl.clone())
-        .expect("Failed to create IDiceNode service instance.");
-
-    let maintenance = DiceMaintenance::new_as_binder(node_impl)
-        .expect("Failed to create IDiceMaintenance service instance.");
-
-    binder::add_service(DICE_NODE_SERVICE_NAME, node.as_binder())
-        .expect("Failed to register IDiceNode Service");
-
-    binder::add_service(DICE_MAINTENANCE_SERVICE_NAME, maintenance.as_binder())
-        .expect("Failed to register IDiceMaintenance Service");
-
-    log::info!("Joining thread pool now.");
-    binder::ProcessState::join_thread_pool();
-}
diff --git a/diced/src/error.rs b/diced/src/error.rs
deleted file mode 100644
index 3e230e4..0000000
--- a/diced/src/error.rs
+++ /dev/null
@@ -1,123 +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_security_dice::aidl::android::security::dice::ResponseCode::ResponseCode;
-use anyhow::Result;
-use binder::{ExceptionCode, Result as BinderResult, Status as BinderStatus, StatusCode};
-use keystore2_selinux as selinux;
-use std::ffi::CString;
-
-/// This is the main Diced error type. It wraps the Diced `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 android.security.dice 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 => match root_cause.downcast_ref::<selinux::Error>() {
-            Some(selinux::Error::PermissionDenied) => ResponseCode::PERMISSION_DENIED.0,
-            _ => ResponseCode::SYSTEM_ERROR.0,
-        },
-    }
-}
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 69cf4ac..0000000
--- a/diced/src/hal_node.rs
+++ /dev/null
@@ -1,725 +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 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.into()).collect();
-            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.into()).collect();
-
-            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.")?
-                .as_slice()
-                .try_into()?,
-            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.")?
-                .as_slice()
-                .try_into()?,
-            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 (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.into()).collect();
-
-        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, 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.rs b/diced/src/lib.rs
deleted file mode 100644
index 50e0e96..0000000
--- a/diced/src/lib.rs
+++ /dev/null
@@ -1,203 +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.
-
-//! Implement the android.security.dice.IDiceNode service.
-
-mod error;
-mod permission;
-mod proxy_node_hal;
-mod resident_node;
-
-pub use crate::proxy_node_hal::ProxyNodeHal;
-pub use crate::resident_node::ResidentNode;
-use android_hardware_security_dice::aidl::android::hardware::security::dice::{
-    Bcc::Bcc, BccHandover::BccHandover, Config::Config as BinderConfig,
-    InputValues::InputValues as BinderInputValues, Mode::Mode, Signature::Signature,
-};
-use android_security_dice::aidl::android::security::dice::{
-    IDiceMaintenance::BnDiceMaintenance, IDiceMaintenance::IDiceMaintenance, IDiceNode::BnDiceNode,
-    IDiceNode::IDiceNode, ResponseCode::ResponseCode,
-};
-use anyhow::{Context, Result};
-use binder::{BinderFeatures, Result as BinderResult, Strong, ThreadState};
-pub use diced_open_dice_cbor as dice;
-use error::{map_or_log_err, Error};
-use keystore2_selinux as selinux;
-use libc::uid_t;
-use permission::Permission;
-use std::sync::Arc;
-
-/// A DiceNode backend implementation.
-/// All functions except demote_self derive effective dice artifacts staring from
-/// this node and iterating through `{ [client | demotion path], input_values }`
-/// in ascending order.
-pub trait DiceNodeImpl {
-    /// Signs the message using the effective dice artifacts and Ed25519Pure.
-    fn sign(
-        &self,
-        client: BinderInputValues,
-        input_values: &[BinderInputValues],
-        message: &[u8],
-    ) -> Result<Signature>;
-    /// Returns the effective attestation chain.
-    fn get_attestation_chain(
-        &self,
-        client: BinderInputValues,
-        input_values: &[BinderInputValues],
-    ) -> Result<Bcc>;
-    /// Returns the effective dice artifacts.
-    fn derive(
-        &self,
-        client: BinderInputValues,
-        input_values: &[BinderInputValues],
-    ) -> Result<BccHandover>;
-    /// Adds [ `client` | `input_values` ] to the demotion path of the given client.
-    /// This changes the effective dice artifacts for all subsequent API calls of the
-    /// given client.
-    fn demote(&self, client: BinderInputValues, input_values: &[BinderInputValues]) -> Result<()>;
-    /// This demotes the implementation itself. I.e. a resident node would replace its resident
-    /// 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(&self, input_values: &[BinderInputValues]) -> Result<()>;
-}
-
-/// Wraps a DiceNodeImpl and implements the actual IDiceNode AIDL API.
-pub struct DiceNode {
-    node_impl: Arc<dyn DiceNodeImpl + Sync + Send>,
-}
-
-/// This function uses its namesake in the permission module and in
-/// combination with with_calling_sid from the binder crate to check
-/// if the caller has the given keystore permission.
-pub fn check_caller_permission<T: selinux::ClassPermission>(perm: T) -> Result<()> {
-    ThreadState::with_calling_sid(|calling_sid| {
-        let target_context =
-            selinux::getcon().context("In check_caller_permission: getcon failed.")?;
-
-        selinux::check_permission(
-            calling_sid.ok_or(Error::Rc(ResponseCode::SYSTEM_ERROR)).context(
-                "In check_keystore_permission: Cannot check permission without calling_sid.",
-            )?,
-            &target_context,
-            perm,
-        )
-    })
-}
-
-fn client_input_values(uid: uid_t) -> Result<BinderInputValues> {
-    Ok(BinderInputValues {
-        codeHash: [0; dice::HASH_SIZE],
-        config: BinderConfig {
-            desc: dice::bcc::format_config_descriptor(Some(&format!("{}", uid)), None, false)
-                .context("In client_input_values: failed to format config descriptor")?,
-        },
-        authorityHash: [0; dice::HASH_SIZE],
-        authorityDescriptor: None,
-        hidden: [0; dice::HIDDEN_SIZE],
-        mode: Mode::NORMAL,
-    })
-}
-
-impl DiceNode {
-    /// Constructs an instance of DiceNode, wraps it with a BnDiceNode 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(
-        node_impl: Arc<dyn DiceNodeImpl + Sync + Send>,
-    ) -> Result<Strong<dyn IDiceNode>> {
-        let result = BnDiceNode::new_binder(
-            DiceNode { node_impl },
-            BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
-        );
-        Ok(result)
-    }
-
-    fn sign(&self, input_values: &[BinderInputValues], message: &[u8]) -> Result<Signature> {
-        check_caller_permission(Permission::UseSign).context("In DiceNode::sign:")?;
-        let client =
-            client_input_values(ThreadState::get_calling_uid()).context("In DiceNode::sign:")?;
-        self.node_impl.sign(client, input_values, message)
-    }
-    fn get_attestation_chain(&self, input_values: &[BinderInputValues]) -> Result<Bcc> {
-        check_caller_permission(Permission::GetAttestationChain)
-            .context("In DiceNode::get_attestation_chain:")?;
-        let client = client_input_values(ThreadState::get_calling_uid())
-            .context("In DiceNode::get_attestation_chain:")?;
-        self.node_impl.get_attestation_chain(client, input_values)
-    }
-    fn derive(&self, input_values: &[BinderInputValues]) -> Result<BccHandover> {
-        check_caller_permission(Permission::Derive).context("In DiceNode::derive:")?;
-        let client =
-            client_input_values(ThreadState::get_calling_uid()).context("In DiceNode::extend:")?;
-        self.node_impl.derive(client, input_values)
-    }
-    fn demote(&self, input_values: &[BinderInputValues]) -> Result<()> {
-        check_caller_permission(Permission::Demote).context("In DiceNode::demote:")?;
-        let client =
-            client_input_values(ThreadState::get_calling_uid()).context("In DiceNode::demote:")?;
-        self.node_impl.demote(client, input_values)
-    }
-}
-
-impl binder::Interface for DiceNode {}
-
-impl IDiceNode for DiceNode {
-    fn sign(&self, input_values: &[BinderInputValues], message: &[u8]) -> BinderResult<Signature> {
-        map_or_log_err(self.sign(input_values, message), Ok)
-    }
-    fn getAttestationChain(&self, input_values: &[BinderInputValues]) -> BinderResult<Bcc> {
-        map_or_log_err(self.get_attestation_chain(input_values), Ok)
-    }
-    fn derive(&self, input_values: &[BinderInputValues]) -> BinderResult<BccHandover> {
-        map_or_log_err(self.derive(input_values), Ok)
-    }
-    fn demote(&self, input_values: &[BinderInputValues]) -> BinderResult<()> {
-        map_or_log_err(self.demote(input_values), Ok)
-    }
-}
-
-/// Wraps a DiceNodeImpl and implements the IDiceMaintenance AIDL API.
-pub struct DiceMaintenance {
-    node_impl: Arc<dyn DiceNodeImpl + Sync + Send>,
-}
-
-impl DiceMaintenance {
-    /// Constructs an instance of DiceMaintenance, wraps it with a BnDiceMaintenance 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(
-        node_impl: Arc<dyn DiceNodeImpl + Sync + Send>,
-    ) -> Result<Strong<dyn IDiceMaintenance>> {
-        let result = BnDiceMaintenance::new_binder(
-            DiceMaintenance { node_impl },
-            BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
-        );
-        Ok(result)
-    }
-
-    fn demote_self(&self, input_values: &[BinderInputValues]) -> Result<()> {
-        check_caller_permission(Permission::DemoteSelf)
-            .context("In DiceMaintenance::demote_self:")?;
-        self.node_impl.demote_self(input_values)
-    }
-}
-
-impl binder::Interface for DiceMaintenance {}
-
-impl IDiceMaintenance for DiceMaintenance {
-    fn demoteSelf(&self, input_values: &[BinderInputValues]) -> BinderResult<()> {
-        map_or_log_err(self.demote_self(input_values), Ok)
-    }
-}
diff --git a/diced/src/lib_vendor.rs b/diced/src/lib_vendor.rs
deleted file mode 100644
index 01c804b..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_cbor as dice;
diff --git a/diced/src/permission.rs b/diced/src/permission.rs
deleted file mode 100644
index 62ca653..0000000
--- a/diced/src/permission.rs
+++ /dev/null
@@ -1,46 +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 provides convenience wrappers for the SELinux permission
-//! defined in the diced SELinux access class.
-
-use keystore2_selinux as selinux;
-use selinux::{implement_class, ClassPermission};
-
-implement_class!(
-    /// Permission provides a convenient abstraction from the SELinux class `diced`.
-    #[selinux(class_name = diced)]
-    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
-    pub enum Permission {
-        /// Checked when a client attempts to call seal or unseal.
-        #[selinux(name = use_seal)]
-        UseSeal,
-        /// Checked when a client attempts to call IDiceNode::sign.
-        #[selinux(name = use_sign)]
-        UseSign,
-        /// Checked when a client attempts to call IDiceNode::getAttestationChain.
-        #[selinux(name = get_attestation_chain)]
-        GetAttestationChain,
-        /// Checked when a client attempts to call IDiceNode::derive.
-        #[selinux(name = derive)]
-        Derive,
-        /// Checked when a client wants to demote itself by calling IDiceNode::demote.
-        #[selinux(name = demote)]
-        Demote,
-        /// Checked when a client calls IDiceMaintenance::demote in an attempt to
-        /// demote this dice node.
-        #[selinux(name = demote_self)]
-        DemoteSelf,
-    }
-);
diff --git a/diced/src/proxy_node_hal.rs b/diced/src/proxy_node_hal.rs
deleted file mode 100644
index 8d883d2..0000000
--- a/diced/src/proxy_node_hal.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.
-
-//! A proxy dice node delegates all accesses to CDI_attest and CDI_seal to a parent
-//! node, here an implementation of android.hardware.security.dice.IDiceDevice.
-
-#![allow(dead_code)]
-
-use crate::DiceNodeImpl;
-use android_hardware_security_dice::aidl::android::hardware::security::dice::{
-    Bcc::Bcc, BccHandover::BccHandover, IDiceDevice::IDiceDevice,
-    InputValues::InputValues as BinderInputValues, Signature::Signature,
-};
-use anyhow::{Context, Result};
-use binder::Strong;
-use std::collections::HashMap;
-use std::sync::RwLock;
-
-/// The ProxyNodeHal implements a IDiceNode backend delegating crypto operations
-/// to the corresponding HAL.
-pub struct ProxyNodeHal {
-    parent: Strong<dyn IDiceDevice>,
-    demotion_db: RwLock<HashMap<BinderInputValues, Vec<BinderInputValues>>>,
-}
-
-impl ProxyNodeHal {
-    /// Creates a new proxy node with a reference to the parent service.
-    pub fn new(parent: Strong<dyn IDiceDevice>) -> Result<Self> {
-        Ok(ProxyNodeHal { parent, demotion_db: Default::default() })
-    }
-
-    fn get_effective_input_values(
-        &self,
-        client: BinderInputValues,
-        input_values: &[BinderInputValues],
-    ) -> Vec<BinderInputValues> {
-        let demotion_db = self.demotion_db.read().unwrap();
-
-        let client_arr = [client];
-
-        demotion_db
-            .get(&client_arr[0])
-            .map(|v| v.iter())
-            .unwrap_or_else(|| client_arr.iter())
-            .chain(input_values.iter())
-            .cloned()
-            .collect()
-    }
-}
-
-impl DiceNodeImpl for ProxyNodeHal {
-    fn sign(
-        &self,
-        client: BinderInputValues,
-        input_values: &[BinderInputValues],
-        message: &[u8],
-    ) -> Result<Signature> {
-        self.parent
-            .sign(&self.get_effective_input_values(client, input_values), message)
-            .context("In ProxyNodeHal::sign:")
-    }
-
-    fn get_attestation_chain(
-        &self,
-        client: BinderInputValues,
-        input_values: &[BinderInputValues],
-    ) -> Result<Bcc> {
-        self.parent
-            .getAttestationChain(&self.get_effective_input_values(client, input_values))
-            .context("In ProxyNodeHal::get_attestation_chain:")
-    }
-
-    fn derive(
-        &self,
-        client: BinderInputValues,
-        input_values: &[BinderInputValues],
-    ) -> Result<BccHandover> {
-        self.parent
-            .derive(&self.get_effective_input_values(client, input_values))
-            .context("In ProxyNodeHal::derive:")
-    }
-
-    fn demote(&self, client: BinderInputValues, input_values: &[BinderInputValues]) -> Result<()> {
-        let mut demotion_db = self.demotion_db.write().unwrap();
-
-        let client_arr = [client];
-
-        // The following statement consults demotion database which yields an optional demotion
-        // path. It then constructs an iterator over the following elements, then clones and
-        // collects them into a new vector:
-        // [ demotion path | client ], input_values
-        let new_path: Vec<BinderInputValues> = demotion_db
-            .get(&client_arr[0])
-            .map(|v| v.iter())
-            .unwrap_or_else(|| client_arr.iter())
-            .chain(input_values)
-            .cloned()
-            .collect();
-
-        let [client] = client_arr;
-        demotion_db.insert(client, new_path);
-        Ok(())
-    }
-
-    fn demote_self(&self, input_values: &[BinderInputValues]) -> Result<()> {
-        self.parent.demote(input_values).context("In ProxyNodeHal::demote_self:")
-    }
-}
diff --git a/diced/src/resident_node.rs b/diced/src/resident_node.rs
deleted file mode 100644
index 99a6dc9..0000000
--- a/diced/src/resident_node.rs
+++ /dev/null
@@ -1,191 +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.
-
-//! A resident dice node keeps CDI_attest and CDI_seal memory resident and can serve
-//! its clients directly by performing all crypto operations including derivations and
-//! certificate generation itself.
-
-use crate::DiceNodeImpl;
-use android_hardware_security_dice::aidl::android::hardware::security::dice::{
-    Bcc::Bcc, BccHandover::BccHandover, InputValues::InputValues as BinderInputValues,
-    Signature::Signature,
-};
-use anyhow::{Context, Result};
-use dice::{ContextImpl, OpenDiceCborContext};
-use diced_open_dice_cbor as dice;
-use diced_utils::{self as utils, InputValues, ResidentArtifacts};
-use std::collections::HashMap;
-use std::convert::TryInto;
-use std::sync::RwLock;
-
-/// The ResidentNode implements a IDiceNode backend with memory resident DICE secrets.
-pub struct ResidentNode {
-    artifacts: RwLock<ResidentArtifacts>,
-    demotion_db: RwLock<HashMap<BinderInputValues, Vec<BinderInputValues>>>,
-}
-
-impl ResidentNode {
-    /// Creates a new Resident node with the given dice secrets and certificate chain.
-    pub fn new(
-        cdi_attest: &[u8; dice::CDI_SIZE],
-        cdi_seal: &[u8; dice::CDI_SIZE],
-        bcc: Vec<u8>,
-    ) -> Result<Self> {
-        Ok(ResidentNode {
-            artifacts: RwLock::new(
-                ResidentArtifacts::new(cdi_attest, cdi_seal, &bcc)
-                    .context("In ResidentNode::new: Trying to initialize ResidentArtifacts")?,
-            ),
-            demotion_db: Default::default(),
-        })
-    }
-
-    fn get_effective_artifacts(
-        &self,
-        client: BinderInputValues,
-        input_values: &[BinderInputValues],
-    ) -> Result<ResidentArtifacts> {
-        let artifacts = self.artifacts.read().unwrap().try_clone()?;
-        let demotion_db = self.demotion_db.read().unwrap();
-
-        let client_arr = [client];
-
-        let input_values: Vec<utils::InputValues> = demotion_db
-            .get(&client_arr[0])
-            .map(|v| v.iter())
-            .unwrap_or_else(|| client_arr.iter())
-            .chain(input_values.iter())
-            .map(|v| v.into())
-            .collect();
-
-        artifacts
-            .execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues))
-            .context("In get_effective_artifacts:")
-    }
-}
-
-impl DiceNodeImpl for ResidentNode {
-    fn sign(
-        &self,
-        client: BinderInputValues,
-        input_values: &[BinderInputValues],
-        message: &[u8],
-    ) -> Result<Signature> {
-        let (cdi_attest, _, _) = self
-            .get_effective_artifacts(client, input_values)
-            .context("In ResidentNode::sign: Failed to get effective_artifacts.")?
-            .into_tuple();
-        let mut dice = OpenDiceCborContext::new();
-        let seed = dice
-            .derive_cdi_private_key_seed(cdi_attest[..].try_into().with_context(|| {
-                format!(
-                    "In ResidentNode::sign: Failed to convert cdi_attest (length: {}).",
-                    cdi_attest.len()
-                )
-            })?)
-            .context("In ResidentNode::sign: Failed to derive seed from cdi_attest.")?;
-        let (_public_key, private_key) = dice
-            .keypair_from_seed(seed[..].try_into().with_context(|| {
-                format!("In ResidentNode::sign: Failed to convert seed (length: {}).", seed.len())
-            })?)
-            .context("In ResidentNode::sign: Failed to derive keypair from seed.")?;
-        Ok(Signature {
-            data: dice
-                .sign(
-                    message,
-                    private_key[..].try_into().with_context(|| {
-                        format!(
-                            "In ResidentNode::sign: Failed to convert private_key (length: {}).",
-                            private_key.len()
-                        )
-                    })?,
-                )
-                .context("In ResidentNode::sign: Failed to sign.")?,
-        })
-    }
-
-    fn get_attestation_chain(
-        &self,
-        client: BinderInputValues,
-        input_values: &[BinderInputValues],
-    ) -> Result<Bcc> {
-        let (_, _, bcc) = self
-            .get_effective_artifacts(client, input_values)
-            .context("In ResidentNode::get_attestation_chain: Failed to get effective_artifacts.")?
-            .into_tuple();
-
-        Ok(Bcc { data: bcc })
-    }
-
-    fn derive(
-        &self,
-        client: BinderInputValues,
-        input_values: &[BinderInputValues],
-    ) -> Result<BccHandover> {
-        let (cdi_attest, cdi_seal, bcc) =
-            self.get_effective_artifacts(client, input_values)?.into_tuple();
-
-        utils::make_bcc_handover(
-            &cdi_attest[..]
-                .try_into()
-                .context("In ResidentNode::derive: Trying to convert cdi_attest to sized array.")?,
-            &cdi_seal[..]
-                .try_into()
-                .context("In ResidentNode::derive: Trying to convert cdi_attest to sized array.")?,
-            &bcc,
-        )
-        .context("In ResidentNode::derive: Trying to format bcc handover.")
-    }
-
-    fn demote(&self, client: BinderInputValues, input_values: &[BinderInputValues]) -> Result<()> {
-        let mut demotion_db = self.demotion_db.write().unwrap();
-
-        let client_arr = [client];
-
-        // The following statement consults demotion database which yields an optional demotion
-        // path. It then constructs an iterator over the following elements, then clones and
-        // collects them into a new vector:
-        // [ demotion path | client ], input_values
-        let new_path: Vec<BinderInputValues> = demotion_db
-            .get(&client_arr[0])
-            .map(|v| v.iter())
-            .unwrap_or_else(|| client_arr.iter())
-            .chain(input_values)
-            .cloned()
-            .collect();
-
-        let [client] = client_arr;
-        demotion_db.insert(client, new_path);
-        Ok(())
-    }
-
-    fn demote_self(&self, input_values: &[BinderInputValues]) -> Result<()> {
-        let mut artifacts = self.artifacts.write().unwrap();
-
-        let input_values = input_values
-            .iter()
-            .map(|v| {
-                v.try_into().with_context(|| format!("Failed to convert input values: {:#?}", v))
-            })
-            .collect::<Result<Vec<InputValues>>>()
-            .context("In ResidentNode::demote_self:")?;
-
-        *artifacts = artifacts
-            .try_clone()
-            .context("In ResidentNode::demote_self: Failed to clone resident artifacts")?
-            .execute_steps(input_values.iter().map(|v| v as &dyn dice::InputValues))
-            .context("In ResidentNode::demote_self:")?;
-        Ok(())
-    }
-}
diff --git a/diced/src/sample_inputs.rs b/diced/src/sample_inputs.rs
index ff239ed..19200a5 100644
--- a/diced/src/sample_inputs.rs
+++ b/diced/src/sample_inputs.rs
@@ -15,24 +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::{
+    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 anyhow::{Context, Result};
-use dice::ContextImpl;
-use diced_open_dice_cbor as dice;
 use diced_utils::cbor;
-use diced_utils::InputValues;
-use keystore2_crypto::ZVec;
-use std::convert::{TryFrom, TryInto};
+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.")?;
@@ -64,185 +105,77 @@
     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<(ZVec, ZVec, Vec<u8>)> {
-    let mut dice_ctx = dice::OpenDiceCborContext::new();
-    let private_key_seed = dice_ctx
-        .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_ctx
-            .keypair_from_seed(&private_key_seed[..].try_into().context(
-                "In make_sample_bcc_and_cids: Failed to convert seed to array reference.",
-            )?)
-            .context("In make_sample_bcc_and_cids: Failed to generate key pair.")?;
-
-    let input_values_vector = get_input_values_vector();
-
-    let (cdi_attest, cdi_seal, mut cert) = dice_ctx
-        .main_flow(
-            UDS,
-            UDS,
-            &InputValues::try_from(&input_values_vector[0])
-                .context("In make_sample_bcc_and_cdis: Trying to convert input values. (0)")?,
-        )
-        .context("In make_sample_bcc_and_cdis: Trying to run first main flow.")?;
-
+    // 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 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 (cdi_attest, cdi_seal, bcc) = dice_ctx
-        .bcc_main_flow(
-            &cdi_attest[..].try_into().context(
-                "In make_sample_bcc_and_cdis: Failed to convert cdi_attest to array reference. (1)",
-            )?,
-            &cdi_seal[..].try_into().context(
-                "In make_sample_bcc_and_cdis: Failed to convert cdi_seal to array reference. (1)",
-            )?,
-            &bcc,
-            &InputValues::try_from(&input_values_vector[1])
-                .context("In make_sample_bcc_and_cdis: Trying to convert input values. (1)")?,
-        )
-        .context("In make_sample_bcc_and_cdis: Trying to run first bcc main flow.")?;
-    dice_ctx
-        .bcc_main_flow(
-            &cdi_attest[..].try_into().context(
-                "In make_sample_bcc_and_cdis: Failed to convert cdi_attest to array reference. (2)",
-            )?,
-            &cdi_seal[..].try_into().context(
-                "In make_sample_bcc_and_cdis: Failed to convert cdi_seal to array reference. (2)",
-            )?,
-            &bcc,
-            &InputValues::try_from(&input_values_vector[2])
-                .context("In make_sample_bcc_and_cdis: Trying to convert input values. (2)")?,
-        )
-        .context("In make_sample_bcc_and_cdis: Trying to run second 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.")?;
 
-fn make_input_values(
-    code_hash: &[u8; dice::HASH_SIZE],
-    authority_hash: &[u8; dice::HASH_SIZE],
-    config_name: &str,
-    config_version: u64,
-    config_resettable: bool,
-    mode: Mode,
-    hidden: &[u8; dice::HIDDEN_SIZE],
-) -> Result<BinderInputValues> {
-    Ok(BinderInputValues {
-        codeHash: *code_hash,
-        config: BinderConfig {
-            desc: dice::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: *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> {
-    vec![
-        make_input_values(
-            &[
-                // code hash
-                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,
-            ],
-            &[
-                // authority hash
-                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,
-            ],
-            "ABL", // config name
-            1,     // config version
-            true,  // resettable
-            Mode::NORMAL,
-            &[
-                // hidden
-                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,
-            ],
-        )
-        .unwrap(),
-        make_input_values(
-            &[
-                // code hash
-                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,
-            ],
-            &[
-                // authority hash
-                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,
-            ],
-            "AVB", // config name
-            1,     // config version
-            true,  // resettable
-            Mode::NORMAL,
-            &[
-                // hidden
-                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,
-            ],
-        )
-        .unwrap(),
-        make_input_values(
-            &[
-                // code hash
-                0; dice::HASH_SIZE
-            ],
-            &[
-                // authority hash
-                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,
-            ],
-            "Android", // config name
-            12,        // config version
-            true,      // resettable
-            Mode::NORMAL,
-            &[
-                // hidden
-                0; dice::HIDDEN_SIZE
-            ],
-        )
-        .unwrap(),
-    ]
+    // 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"))?,
+        &input_values,
+    )
+    .context("In make_sample_bcc_and_cdis: Trying to run second bcc main flow.")
 }
 
 #[cfg(test)]
@@ -250,7 +183,7 @@
     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 03e8969..0931e68 100644
--- a/diced/src/utils.rs
+++ b/diced/src/utils.rs
@@ -14,217 +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::{Context, Result};
-use dice::ContextImpl;
-use diced_open_dice_cbor as dice;
-use keystore2_crypto::ZVec;
-use std::convert::TryInto;
-
-/// This new type wraps a reference to BinderInputValues and implements the open dice
-/// InputValues trait.
-#[derive(Debug)]
-pub struct InputValues<'a>(&'a BinderInputValues);
-
-impl<'a> From<&'a BinderInputValues> for InputValues<'a> {
-    fn from(input_values: &'a BinderInputValues) -> InputValues<'a> {
-        Self(input_values)
-    }
-}
-
-impl From<&InputValues<'_>> for BinderInputValues {
-    fn from(input_values: &InputValues) -> BinderInputValues {
-        input_values.0.clone()
-    }
-}
-impl From<InputValues<'_>> for BinderInputValues {
-    fn from(input_values: InputValues) -> BinderInputValues {
-        input_values.0.clone()
-    }
-}
-
-impl dice::InputValues for InputValues<'_> {
-    fn code_hash(&self) -> &[u8; dice::HASH_SIZE] {
-        &self.0.codeHash
-    }
-
-    fn config(&self) -> dice::Config {
-        dice::Config::Descriptor(self.0.config.desc.as_slice())
-    }
-
-    fn authority_hash(&self) -> &[u8; dice::HASH_SIZE] {
-        &self.0.authorityHash
-    }
-
-    fn authority_descriptor(&self) -> Option<&[u8]> {
-        self.0.authorityDescriptor.as_deref()
-    }
-
-    fn mode(&self) -> dice::Mode {
-        match self.0.mode {
-            BinderMode::NOT_INITIALIZED => dice::Mode::NotConfigured,
-            BinderMode::NORMAL => dice::Mode::Normal,
-            BinderMode::DEBUG => dice::Mode::Debug,
-            BinderMode::RECOVERY => dice::Mode::Recovery,
-            _ => dice::Mode::NotConfigured,
-        }
-    }
-
-    fn hidden(&self) -> &[u8; dice::HIDDEN_SIZE] {
-        // If `self` was created using try_from the length was checked and this cannot panic.
-        &self.0.hidden
-    }
-}
-
-/// 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.
-pub struct ResidentArtifacts {
-    cdi_attest: ZVec,
-    cdi_seal: ZVec,
-    bcc: Vec<u8>,
-}
-
-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()[..].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> {
-        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: &dyn dice::InputValues) -> Result<Self> {
-        let ResidentArtifacts { cdi_attest, cdi_seal, bcc } = self;
-
-        let (cdi_attest, cdi_seal, bcc) = dice::OpenDiceCborContext::new()
-            .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,
-                input_values,
-            )
-            .context("In ResidentArtifacts::execute_step:")?;
-        Ok(ResidentArtifacts { cdi_attest, cdi_seal, bcc })
-    }
-
-    /// Iterate through the iterator of dice input values performing one
-    /// BCC main flow step on each element.
-    pub fn execute_steps<'a, Iter>(self, input_values: Iter) -> Result<Self>
-    where
-        Iter: IntoIterator<Item = &'a dyn dice::InputValues>,
-    {
-        input_values
-            .into_iter()
-            .try_fold(self, |acc, input_values| acc.execute_step(input_values))
-            .context("In ResidentArtifacts::execute_step:")
-    }
-}
-
-/// 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 {
@@ -256,18 +45,17 @@
     pub fn encode_header(t: u8, n: u64, buffer: &mut dyn Write) -> Result<()> {
         match n {
             n if n < 24 => {
-                let written = buffer
-                    .write(&u8::to_be_bytes(((t as u8) << 5) | (n as u8 & 0x1F)))
-                    .with_context(|| {
-                    format!("In encode_header: Failed to write header ({}, {})", t, n)
-                })?;
+                let written =
+                    buffer.write(&u8::to_be_bytes((t << 5) | (n as u8 & 0x1F))).with_context(
+                        || format!("In encode_header: Failed to write header ({}, {})", t, n),
+                    )?;
                 if written != 1 {
                     return Err(anyhow!("In encode_header: Buffer to small. ({}, {})", t, n));
                 }
             }
             n if n <= 0xFF => {
                 let written =
-                    buffer.write(&u8::to_be_bytes(((t as u8) << 5) | (24u8 & 0x1F))).with_context(
+                    buffer.write(&u8::to_be_bytes((t << 5) | (24u8 & 0x1F))).with_context(
                         || format!("In encode_header: Failed to write header ({}, {})", t, n),
                     )?;
                 if written != 1 {
@@ -286,7 +74,7 @@
             }
             n if n <= 0xFFFF => {
                 let written =
-                    buffer.write(&u8::to_be_bytes(((t as u8) << 5) | (25u8 & 0x1F))).with_context(
+                    buffer.write(&u8::to_be_bytes((t << 5) | (25u8 & 0x1F))).with_context(
                         || format!("In encode_header: Failed to write header ({}, {})", t, n),
                     )?;
                 if written != 1 {
@@ -305,7 +93,7 @@
             }
             n if n <= 0xFFFFFFFF => {
                 let written =
-                    buffer.write(&u8::to_be_bytes(((t as u8) << 5) | (26u8 & 0x1F))).with_context(
+                    buffer.write(&u8::to_be_bytes((t << 5) | (26u8 & 0x1F))).with_context(
                         || format!("In encode_header: Failed to write header ({}, {})", t, n),
                     )?;
                 if written != 1 {
@@ -324,13 +112,13 @@
             }
             n => {
                 let written =
-                    buffer.write(&u8::to_be_bytes(((t as u8) << 5) | (27u8 & 0x1F))).with_context(
+                    buffer.write(&u8::to_be_bytes((t << 5) | (27u8 & 0x1F))).with_context(
                         || format!("In encode_header: Failed to write header ({}, {})", t, n),
                     )?;
                 if written != 1 {
                     return Err(anyhow!("In encode_header: Buffer to small. ({}, {})", t, n));
                 }
-                let written = buffer.write(&u64::to_be_bytes(n as u64)).with_context(|| {
+                let written = buffer.write(&u64::to_be_bytes(n)).with_context(|| {
                     format!("In encode_header: Failed to write size ({}, {})", t, n)
                 })?;
                 if written != 8 {
diff --git a/identity/Android.bp b/identity/Android.bp
index 7b81685..4f203e6 100644
--- a/identity/Android.bp
+++ b/identity/Android.bp
@@ -47,7 +47,7 @@
         "android.hardware.identity-support-lib",
         "android.hardware.keymaster@4.0",
         "android.security.authorization-ndk",
-	"android.security.remoteprovisioning-cpp",
+        "android.security.remoteprovisioning-cpp",
         "libbase",
         "libbinder",
         "libbinder_ndk",
@@ -59,7 +59,6 @@
         "libutils",
         "libutilscallstack",
         "libvintf",
-	"server_configurable_flags",
     ],
     static_libs: [
         "android.hardware.security.rkp-V3-cpp",
diff --git a/identity/CredentialData.cpp b/identity/CredentialData.cpp
index fb08333..1bf1527 100644
--- a/identity/CredentialData.cpp
+++ b/identity/CredentialData.cpp
@@ -581,13 +581,17 @@
 
     vector<vector<uint8_t>> keysNeedingCert;
 
-    int64_t nowMilliSeconds =
-        std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) * 1000;
+    time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
+    int64_t nowMilliseconds;
+    if (__builtin_mul_overflow(int64_t(now), int64_t(1000), &nowMilliseconds)) {
+        LOG(ERROR) << "Overflow converting " << now << " to milliseconds";
+        return {};
+    }
 
     for (AuthKeyData& data : authKeyDatas_) {
         bool keyExceedUseCount = (data.useCount >= maxUsesPerKey_);
         int64_t expirationDateAdjusted = data.expirationDateMillisSinceEpoch - minValidTimeMillis_;
-        bool keyBeyondAdjustedExpirationDate = (nowMilliSeconds > expirationDateAdjusted);
+        bool keyBeyondAdjustedExpirationDate = (nowMilliseconds > expirationDateAdjusted);
         bool newKeyNeeded =
             (data.certificate.size() == 0) || keyExceedUseCount || keyBeyondAdjustedExpirationDate;
         bool certificationPending = (data.pendingCertificate.size() > 0);
diff --git a/identity/CredentialStore.cpp b/identity/CredentialStore.cpp
index eb9bdb6..e2b3cf4 100644
--- a/identity/CredentialStore.cpp
+++ b/identity/CredentialStore.cpp
@@ -20,18 +20,19 @@
 #include <optional>
 
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 #include <android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
 #include <android/hardware/security/keymint/RpcHardwareInfo.h>
 #include <android/security/remoteprovisioning/IRemotelyProvisionedKeyPool.h>
 #include <android/security/remoteprovisioning/RemotelyProvisionedKey.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
-#include <server_configurable_flags/get_flags.h>
 #include <vintf/VintfObject.h>
 
 #include "Credential.h"
 #include "CredentialData.h"
 #include "CredentialStore.h"
+#include "RemotelyProvisionedKey.h"
 #include "Session.h"
 #include "Util.h"
 #include "WritableCredential.h"
@@ -45,10 +46,8 @@
 using ::android::security::rkp::IRemoteProvisioning;
 
 bool useRkpd() {
-    std::string useRkpdFlagValue = server_configurable_flags::GetServerConfigurableFlag(
-        "remote_key_provisioning_native", "enable_rkpd",
-        /*default_value=*/"false");
-    return useRkpdFlagValue == "true";
+    return android::base::GetBoolProperty("remote_provisioning.enable_rkpd",
+                                          /*default_value=*/true);
 }
 
 }  // namespace
@@ -70,31 +69,14 @@
             LOG(ERROR) << "Error getting remotely provisioned component: " << status;
             return false;
         }
-        useRkpd_ = useRkpd();
-
-        if (useRkpd_) {
-            uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
-            auto rpcKeyFuture = getRpcKeyFuture(rpc_, callingUid);
-            if (!rpcKeyFuture) {
-                LOG(ERROR) << "Error in getRpcKeyFuture()";
-                return false;
-            }
-            rpcKeyFuture_ = std::move(*rpcKeyFuture);
-        } else {
-            keyPool_ = android::waitForService<IRemotelyProvisionedKeyPool>(
-                IRemotelyProvisionedKeyPool::descriptor);
-            if (!keyPool_) {
-                LOG(ERROR) << "Error getting IRemotelyProvisionedKeyPool HAL with service name '"
-                           << IRemotelyProvisionedKeyPool::descriptor << "'";
-                return false;
-            }
-        }
     }
 
     LOG(INFO) << "Connected to Identity Credential HAL with API version " << halApiVersion_
               << " and name '" << hwInfo_.credentialStoreName << "' authored by '"
               << hwInfo_.credentialStoreAuthorName << "' with chunk size " << hwInfo_.dataChunkSize
-              << " and directoAccess set to " << (hwInfo_.isDirectAccess ? "true" : "false");
+              << " directoAccess set to " << (hwInfo_.isDirectAccess ? "true" : "false")
+              << " and remote key provisioning support "
+              << (hwInfo_.isRemoteKeyProvisioningSupported ? "enabled" : "disabled");
     return true;
 }
 
@@ -140,7 +122,9 @@
     if (hwInfo_.isRemoteKeyProvisioningSupported) {
         status = setRemotelyProvisionedAttestationKey(halWritableCredential.get());
         if (!status.isOk()) {
-            return halStatusToGenericError(status);
+            LOG(WARNING) << status.toString8()
+                         << "\nUnable to fetch remotely provisioned attestation key, falling back "
+                         << "to the factory-provisioned attestation key.";
         }
     }
 
@@ -205,13 +189,21 @@
     std::vector<uint8_t> encodedCertChain;
     Status status;
 
-    if (useRkpd_) {
-        if (rpcKeyFuture_.wait_for(std::chrono::seconds(10)) != std::future_status::ready) {
+    if (useRkpd()) {
+        LOG(INFO) << "Fetching attestation key from RKPD";
+
+        uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
+        auto rpcKeyFuture = getRpcKeyFuture(rpc_, callingUid);
+        if (!rpcKeyFuture) {
+            return Status::fromServiceSpecificError(ERROR_GENERIC, "Error in getRpcKeyFuture()");
+        }
+
+        if (rpcKeyFuture->wait_for(std::chrono::seconds(10)) != std::future_status::ready) {
             return Status::fromServiceSpecificError(
                 ERROR_GENERIC, "Waiting for remotely provisioned attestation key timed out");
         }
 
-        std::optional<::android::security::rkp::RemotelyProvisionedKey> key = rpcKeyFuture_.get();
+        std::optional<::android::security::rkp::RemotelyProvisionedKey> key = rpcKeyFuture->get();
         if (!key) {
             return Status::fromServiceSpecificError(
                 ERROR_GENERIC, "Failed to get remotely provisioned attestation key");
@@ -225,6 +217,16 @@
         keyBlob = std::move(key->keyBlob);
         encodedCertChain = std::move(key->encodedCertChain);
     } else {
+        LOG(INFO) << "Fetching attestation key from remotely provisioned key pool.";
+
+        sp<IRemotelyProvisionedKeyPool> keyPool =
+            android::waitForService<IRemotelyProvisionedKeyPool>(
+                IRemotelyProvisionedKeyPool::descriptor);
+        if (!keyPool) {
+            return Status::fromServiceSpecificError(
+                ERROR_GENERIC, "Error getting IRemotelyProvisionedKeyPool HAL");
+        }
+
         std::optional<std::string> rpcId = getRpcId(rpc_);
         if (!rpcId) {
             return Status::fromServiceSpecificError(
@@ -233,11 +235,9 @@
 
         uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
         ::android::security::remoteprovisioning::RemotelyProvisionedKey key;
-        Status status = keyPool_->getAttestationKey(callingUid, *rpcId, &key);
+        Status status = keyPool->getAttestationKey(callingUid, *rpcId, &key);
         if (!status.isOk()) {
-            LOG(WARNING) << "Unable to fetch remotely provisioned attestation key, falling back "
-                         << "to the factory-provisioned attestation key.";
-            return Status::ok();
+            return status;
         }
 
         keyBlob = std::move(key.keyBlob);
diff --git a/identity/CredentialStore.h b/identity/CredentialStore.h
index 495841b..57c94e0 100644
--- a/identity/CredentialStore.h
+++ b/identity/CredentialStore.h
@@ -17,7 +17,6 @@
 #ifndef SYSTEM_SECURITY_CREDENTIAL_STORE_H_
 #define SYSTEM_SECURITY_CREDENTIAL_STORE_H_
 
-#include <future>
 #include <string>
 #include <vector>
 
@@ -26,8 +25,6 @@
 #include <android/security/remoteprovisioning/IRemotelyProvisionedKeyPool.h>
 #include <android/security/rkp/IRemoteProvisioning.h>
 
-#include "RemotelyProvisionedKey.h"
-
 namespace android {
 namespace security {
 namespace identity {
@@ -80,10 +77,7 @@
 
     HardwareInformation hwInfo_;
 
-    bool useRkpd_;
     sp<IRemotelyProvisionedComponent> rpc_;
-    sp<IRemotelyProvisionedKeyPool> keyPool_;
-    std::future<std::optional<RemotelyProvisionedKey>> rpcKeyFuture_;
 };
 
 }  // namespace identity
diff --git a/identity/RemotelyProvisionedKey.cpp b/identity/RemotelyProvisionedKey.cpp
index 46a42f4..784a680 100644
--- a/identity/RemotelyProvisionedKey.cpp
+++ b/identity/RemotelyProvisionedKey.cpp
@@ -21,6 +21,7 @@
 #include <android-base/logging.h>
 #include <android/security/rkp/BnGetKeyCallback.h>
 #include <android/security/rkp/BnGetRegistrationCallback.h>
+#include <android/security/rkp/IGetKeyCallback.h>
 #include <android/security/rkp/IRemoteProvisioning.h>
 #include <binder/IServiceManager.h>
 #include <binder/Status.h>
@@ -38,10 +39,13 @@
 using ::android::hardware::security::keymint::RpcHardwareInfo;
 using ::android::security::rkp::BnGetKeyCallback;
 using ::android::security::rkp::BnGetRegistrationCallback;
+using ::android::security::rkp::IGetKeyCallback;
 using ::android::security::rkp::IRegistration;
 using ::android::security::rkp::IRemoteProvisioning;
 using ::android::security::rkp::RemotelyProvisionedKey;
 
+constexpr const char* kRemoteProvisioningServiceName = "remote_provisioning";
+
 std::optional<String16> findRpcNameById(std::string_view targetRpcId) {
     auto deviceManifest = vintf::VintfObject::GetDeviceHalManifest();
     auto instances = deviceManifest->getAidlInstances("android.hardware.security.keymint",
@@ -94,11 +98,11 @@
         keyPromise_.set_value(std::nullopt);
         return Status::ok();
     }
-    Status onError(const String16& error) override {
+    Status onError(IGetKeyCallback::ErrorCode error, const String16& description) override {
         if (called_.test_and_set()) {
             return Status::ok();
         }
-        LOG(ERROR) << "GetKeyCallback failed: " << error;
+        LOG(ERROR) << "GetKeyCallback failed: " << static_cast<int>(error) << ", " << description;
         keyPromise_.set_value(std::nullopt);
         return Status::ok();
     }
@@ -122,7 +126,8 @@
         auto cb = sp<GetKeyCallback>::make(std::move(keyPromise_));
         auto status = registration->getKey(keyId_, cb);
         if (!status.isOk()) {
-            cb->onError(String16("Failed to register GetKeyCallback"));
+            cb->onError(IGetKeyCallback::ErrorCode::ERROR_UNKNOWN,
+                        String16("Failed to register GetKeyCallback"));
         }
         return Status::ok();
     }
@@ -182,7 +187,7 @@
     }
 
     sp<IRemoteProvisioning> remoteProvisioning =
-        android::waitForService<IRemoteProvisioning>(IRemoteProvisioning::descriptor);
+        android::waitForService<IRemoteProvisioning>(String16(kRemoteProvisioningServiceName));
     if (!remoteProvisioning) {
         LOG(ERROR) << "Failed to get IRemoteProvisioning HAL";
         return std::nullopt;
diff --git a/identity/main.cpp b/identity/main.cpp
index 2559789..b3a41ec 100644
--- a/identity/main.cpp
+++ b/identity/main.cpp
@@ -23,6 +23,7 @@
 #include <android-base/logging.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
 
 #include "CredentialStoreFactory.h"
 
@@ -32,6 +33,7 @@
 
 using ::android::IPCThreadState;
 using ::android::IServiceManager;
+using ::android::ProcessState;
 using ::android::sp;
 using ::android::String16;
 using ::android::base::InitLogging;
@@ -53,8 +55,10 @@
     CHECK(ret == ::android::OK) << "Couldn't register binder service";
     LOG(INFO) << "Registered binder service";
 
-    // Credstore is a single-threaded process. So devote the main thread
-    // to handling binder messages.
+    // Credstore needs one thread to handle binder messages and one to handle
+    // asynchronous responses from RKPD.
+    ProcessState::self()->setThreadPoolMaxThreadCount(2);
+    ProcessState::self()->startThreadPool();
     IPCThreadState::self()->joinThreadPool();
 
     return 0;
diff --git a/keystore-engine/keystore2_engine.cpp b/keystore-engine/keystore2_engine.cpp
index 69caf51..dc90be3 100644
--- a/keystore-engine/keystore2_engine.cpp
+++ b/keystore-engine/keystore2_engine.cpp
@@ -146,11 +146,13 @@
         return nullptr;
     }
 
-    rsa->n = BN_dup(public_rsa->n);
-    rsa->e = BN_dup(public_rsa->e);
-    if (rsa->n == nullptr || rsa->e == nullptr) {
+    bssl::UniquePtr<BIGNUM> n(BN_dup(RSA_get0_n(public_rsa)));
+    bssl::UniquePtr<BIGNUM> e(BN_dup(RSA_get0_e(public_rsa)));
+    if (n == nullptr || e == nullptr || !RSA_set0_key(rsa.get(), n.get(), e.get(), nullptr)) {
         return nullptr;
     }
+    OWNERSHIP_TRANSFERRED(n);
+    OWNERSHIP_TRANSFERRED(e);
 
     bssl::UniquePtr<EVP_PKEY> result(EVP_PKEY_new());
     if (result.get() == nullptr || !EVP_PKEY_assign_RSA(result.get(), rsa.get())) {
@@ -420,19 +422,19 @@
         Keystore2KeyBackend{response.metadata.key, response.iSecurityLevel});
 
     bssl::UniquePtr<EVP_PKEY> result;
-    switch (EVP_PKEY_type(pkey->type)) {
+    switch (EVP_PKEY_id(pkey.get())) {
     case EVP_PKEY_RSA: {
-        bssl::UniquePtr<RSA> public_rsa(EVP_PKEY_get1_RSA(pkey.get()));
-        result = wrap_rsa(key_backend, public_rsa.get());
+        RSA* public_rsa = EVP_PKEY_get0_RSA(pkey.get());
+        result = wrap_rsa(key_backend, public_rsa);
         break;
     }
     case EVP_PKEY_EC: {
-        bssl::UniquePtr<EC_KEY> public_ecdsa(EVP_PKEY_get1_EC_KEY(pkey.get()));
-        result = wrap_ecdsa(key_backend, public_ecdsa.get());
+        EC_KEY* public_ecdsa = EVP_PKEY_get0_EC_KEY(pkey.get());
+        result = wrap_ecdsa(key_backend, public_ecdsa);
         break;
     }
     default:
-        LOG(ERROR) << AT << "Unsupported key type " << EVP_PKEY_type(pkey->type);
+        LOG(ERROR) << AT << "Unsupported key type " << EVP_PKEY_id(pkey.get());
         return nullptr;
     }
 
diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp
index d01c67d..ab3e22c 100644
--- a/keystore/keystore_cli_v2.cpp
+++ b/keystore/keystore_cli_v2.cpp
@@ -59,6 +59,16 @@
 
 constexpr const char keystore2_service_name[] = "android.system.keystore2.IKeystoreService/default";
 
+std::string string_replace_all(std::string str, const std::string& from,
+                                      const std::string& to) {
+    size_t start = 0;
+    while ((start = str.find(from, start)) != std::string::npos) {
+        str.replace(start, from.length(), to);
+        start += to.length();
+    }
+    return str;
+}
+
 int unwrapError(const ndk::ScopedAStatus& status) {
     if (status.isOk()) return 0;
     if (status.getExceptionCode() == EX_SERVICE_SPECIFIC) {
@@ -1028,7 +1038,8 @@
     auto listener = ndk::SharedRefBase::make<ConfirmationListener>();
 
     auto future = listener->get_future();
-    auto rc = apcService->presentPrompt(listener, promptText, extraData, locale, uiOptionsAsFlags);
+    auto rc = apcService->presentPrompt(listener, string_replace_all(promptText, "\\n", "\n"),
+                                        extraData, locale, uiOptionsAsFlags);
 
     if (!rc.isOk()) {
         std::cerr << "Presenting confirmation prompt failed: " << rc.getDescription() << std::endl;
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index fa80563..d8c0081 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -44,7 +44,6 @@
         "android.security.rkp_aidl-rust",
         "libanyhow",
         "libbinder_rs",
-        "libfutures",
         "libkeystore2_aaid-rust",
         "libkeystore2_apc_compat-rust",
         "libkeystore2_crypto_rust",
@@ -60,6 +59,7 @@
         "libserde",
         "libserde_cbor",
         "libthiserror",
+        "libtokio",
     ],
     shared_libs: [
         "libcutils",
@@ -158,6 +158,7 @@
         "watchdog",
         "keystore2_blob_test_utils",
     ],
+    require_root: true,
 }
 
 rust_defaults {
diff --git a/keystore2/aaid/lib.rs b/keystore2/aaid/lib.rs
index 3187198..8f6a09e 100644
--- a/keystore2/aaid/lib.rs
+++ b/keystore2/aaid/lib.rs
@@ -29,7 +29,7 @@
     // in the second pointer argument.
     let status = unsafe { aaid_keystore_attestation_id(uid, buffer.as_mut_ptr(), &mut size) };
     match status {
-        0 => Ok(buffer[0..size as usize].to_vec()),
+        0 => Ok(buffer[0..size].to_vec()),
         status => Err(status),
     }
 }
diff --git a/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl b/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl
index 3f33431..e3b7d11 100644
--- a/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl
+++ b/keystore2/aidl/android/security/authorization/IKeystoreAuthorization.aidl
@@ -41,8 +41,26 @@
 
     /**
      * Unlocks the keystore for the given user id.
+     *
      * Callers require 'Unlock' permission.
-     * If a password was set, a password must be given on unlock or the operation fails.
+     *
+     * Super-Encryption Key:
+     * When the device is unlocked (and password is non-null), Keystore stores in memory
+     * a super-encryption key derived from the password that protects UNLOCKED_DEVICE_REQUIRED
+     * keys; this key is wiped from memory when the device is locked.
+     *
+     * If unlockingSids is non-empty on lock, then before the super-encryption key is wiped from
+     * memory, a copy of it is stored in memory encrypted with a fresh AES key. This key is then
+     * imported into KM, tagged such that it can be used given a valid, recent auth token for any
+     * of the unlockingSids.
+     *
+     * Options for unlock:
+     *  - If the password is non-null, the super-encryption key is re-derived as above.
+     *  - If the password is null, then if a suitable auth token to access the encrypted
+     *    Super-encryption key stored in KM has been sent to keystore (via addAuthToken), the
+     *    encrypted super-encryption key is recovered so that UNLOCKED_DEVICE_REQUIRED keys can
+     *    be used once again.
+     *  - If neither of these are met, then the operation fails.
      *
      * ## Error conditions:
      * `ResponseCode::PERMISSION_DENIED` - if the callers do not have the 'Unlock' permission.
@@ -50,33 +68,10 @@
      * `ResponseCode::VALUE_CORRUPTED` - if the super key can not be decrypted.
      * `ResponseCode::KEY_NOT_FOUND` - if the super key is not found.
      *
-     * @lockScreenEvent - Indicates what happened.
-     *                    * LockScreenEvent.UNLOCK if the screen was unlocked.
-     *                    * LockScreenEvent.LOCK if the screen was locked.
-     *
-     * @param userId - Android user id
-     *
-     * @param password - synthetic password derived by the user denoted by the user id
-     *
-     * @param unlockingSids - list of biometric SIDs for this user. This will be null when
-     *                        lockScreenEvent is UNLOCK, but may be non-null when
-     *                        lockScreenEvent is LOCK.
-     *
-     *                        When the device is unlocked, Keystore stores in memory
-     *                        a super-encryption key that protects UNLOCKED_DEVICE_REQUIRED
-     *                        keys; this key is wiped from memory when the device is locked.
-     *
-     *                        If unlockingSids is non-empty on lock, then before the
-     *                        super-encryption key is wiped from memory, a copy of it
-     *                        is stored in memory encrypted with a fresh AES key.
-     *                        This key is then imported into KM, tagged such that it can be
-     *                        used given a valid, recent auth token for any of the
-     *                        unlockingSids.
-     *
-     *                        Then, when the device is unlocked again, if a suitable auth token
-     *                        has been sent to keystore, it is used to recover the
-     *                        super-encryption key, so that UNLOCKED_DEVICE_REQUIRED keys can
-     *                        be used once again.
+     * @param lockScreenEvent whether the lock screen locked or unlocked
+     * @param userId android user id
+     * @param password synthetic password derived from the user's LSKF, must be null on lock
+     * @param unlockingSids list of biometric SIDs for this user, ignored on unlock
      */
     void onLockScreenEvent(in LockScreenEvent lockScreenEvent, in int userId,
                            in @nullable byte[] password, in @nullable long[] unlockingSids);
diff --git a/keystore2/apc_compat/apc_compat.rs b/keystore2/apc_compat/apc_compat.rs
index 9f44927..480f14d 100644
--- a/keystore2/apc_compat/apc_compat.rs
+++ b/keystore2/apc_compat/apc_compat.rs
@@ -94,7 +94,7 @@
             // If the pointer and size is not nullptr and not 0 respectively, the C/C++
             // implementation must pass a valid pointer to an allocation of at least size bytes,
             // and the pointer must be valid until this function returns.
-            unsafe { slice::from_raw_parts(tbs_message, s as usize) },
+            unsafe { slice::from_raw_parts(tbs_message, s) },
         ),
     };
     let confirmation_token = match (confirmation_token.is_null(), confirmation_token_size) {
@@ -104,7 +104,7 @@
             // If the pointer and size is not nullptr and not 0 respectively, the C/C++
             // implementation must pass a valid pointer to an allocation of at least size bytes,
             // and the pointer must be valid until this function returns.
-            unsafe { slice::from_raw_parts(confirmation_token, s as usize) },
+            unsafe { slice::from_raw_parts(confirmation_token, s) },
         ),
     };
     hal_cb(rc, tbs_message, confirmation_token)
@@ -178,7 +178,7 @@
                 cb,
                 prompt_text.as_ptr(),
                 extra_data.as_ptr(),
-                extra_data.len() as usize,
+                extra_data.len(),
                 locale.as_ptr(),
                 ui_opts,
             )
diff --git a/keystore2/legacykeystore/lib.rs b/keystore2/legacykeystore/lib.rs
index ed5bd4f..464f0a2 100644
--- a/keystore2/legacykeystore/lib.rs
+++ b/keystore2/legacykeystore/lib.rs
@@ -502,10 +502,8 @@
     ) -> Result<bool> {
         let blob = legacy_loader
             .read_legacy_keystore_entry(uid, alias, |ciphertext, iv, tag, _salt, _key_size| {
-                if let Some(key) = SUPER_KEY
-                    .read()
-                    .unwrap()
-                    .get_per_boot_key_by_user_id(uid_to_android_user(uid as u32))
+                if let Some(key) =
+                    SUPER_KEY.read().unwrap().get_per_boot_key_by_user_id(uid_to_android_user(uid))
                 {
                     key.decrypt(ciphertext, iv, tag)
                 } else {
diff --git a/keystore2/src/async_task.rs b/keystore2/src/async_task.rs
index 0515c8f..6548445 100644
--- a/keystore2/src/async_task.rs
+++ b/keystore2/src/async_task.rs
@@ -67,7 +67,7 @@
     pub fn get_mut<T: Any + Send + Default>(&mut self) -> &mut T {
         self.0
             .entry(TypeId::of::<T>())
-            .or_insert_with(|| Box::new(T::default()) as Box<dyn Any + Send>)
+            .or_insert_with(|| Box::<T>::default() as Box<dyn Any + Send>)
             .downcast_mut::<T>()
             .unwrap()
     }
diff --git a/keystore2/src/attestation_key_utils.rs b/keystore2/src/attestation_key_utils.rs
index d01cf86..8c4cdea 100644
--- a/keystore2/src/attestation_key_utils.rs
+++ b/keystore2/src/attestation_key_utils.rs
@@ -30,6 +30,7 @@
 };
 use anyhow::{Context, Result};
 use keystore2_crypto::parse_subject_from_certificate;
+use rustutils::system_properties;
 
 /// KeyMint takes two different kinds of attestation keys. Remote provisioned keys
 /// and those that have been generated by the user. Unfortunately, they need to be
@@ -53,9 +54,9 @@
 }
 
 fn use_rkpd() -> bool {
-    let property_name = "persist.device_config.remote_key_provisioning_native.enable_rkpd";
-    let default_value = false;
-    rustutils::system_properties::read_bool(property_name, default_value).unwrap_or(default_value)
+    let property = "remote_provisioning.enable_rkpd";
+    let default_value = true;
+    system_properties::read_bool(property, default_value).unwrap_or(default_value)
 }
 
 /// This function loads and, optionally, assigns the caller's remote provisioned
diff --git a/keystore2/src/crypto/lib.rs b/keystore2/src/crypto/lib.rs
index 7ba47c8..08b7589 100644
--- a/keystore2/src/crypto/lib.rs
+++ b/keystore2/src/crypto/lib.rs
@@ -360,8 +360,7 @@
     // Safety: the key is valid.
     // This will not write past the specified length of the buffer; if the
     // len above is too short, it returns 0.
-    let written_len =
-        unsafe { ECKEYMarshalPrivateKey(key.0, buf.as_mut_ptr(), buf.len()) } as usize;
+    let written_len = unsafe { ECKEYMarshalPrivateKey(key.0, buf.as_mut_ptr(), buf.len()) };
     if written_len == len {
         Ok(buf)
     } else {
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index 62fd579..c9c28f6 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -830,7 +830,7 @@
     pub fn satisfies(&self, user_secure_ids: &[i64], auth_type: HardwareAuthenticatorType) -> bool {
         user_secure_ids.iter().any(|&sid| {
             (sid == self.auth_token.userId || sid == self.auth_token.authenticatorId)
-                && (((auth_type.0 as i32) & (self.auth_token.authenticatorType.0 as i32)) != 0)
+                && ((auth_type.0 & self.auth_token.authenticatorType.0) != 0)
         })
     }
 
@@ -1859,7 +1859,8 @@
                 let (_, hw_info) = get_keymint_dev_by_uuid(km_uuid)
                     .context("Error in retrieving keymint device by UUID.")?;
                 log_rkp_error_stats(MetricsRkpError::OUT_OF_KEYS, &hw_info.securityLevel);
-                return Err(KsError::Rc(ResponseCode::OUT_OF_KEYS)).context("Out of keys.");
+                return Err(KsError::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR))
+                    .context("Out of keys.");
             } else if result > 1 {
                 return Err(KsError::sys())
                     .context(format!("Expected to update 1 entry, instead updated {}", result));
@@ -4562,7 +4563,7 @@
                 DESTINATION_UID,
                 |k, av| {
                     assert_eq!(Domain::SELINUX, k.domain);
-                    assert_eq!(DESTINATION_NAMESPACE as i64, k.nspace);
+                    assert_eq!(DESTINATION_NAMESPACE, k.nspace);
                     assert!(av.is_none());
                     Ok(())
                 },
diff --git a/keystore2/src/error.rs b/keystore2/src/error.rs
index b60b64f..3ca3942 100644
--- a/keystore2/src/error.rs
+++ b/keystore2/src/error.rs
@@ -71,11 +71,6 @@
     pub fn perm() -> Self {
         Error::Rc(ResponseCode::PERMISSION_DENIED)
     }
-
-    /// Short hand for `Error::Rc(ResponseCode::OUT_OF_KEYS)`
-    pub fn out_of_keys() -> Self {
-        Error::Rc(ResponseCode::OUT_OF_KEYS)
-    }
 }
 
 /// Helper function to map the binder status we get from calls into KeyMint
diff --git a/keystore2/src/fuzzers/Android.bp b/keystore2/src/fuzzers/Android.bp
index 3adb922..9a2d98d 100644
--- a/keystore2/src/fuzzers/Android.bp
+++ b/keystore2/src/fuzzers/Android.bp
@@ -37,3 +37,30 @@
         componentid: 155276,
     },
 }
+
+
+rust_fuzz {
+    name: "authorization_service_fuzzer",
+    srcs: ["aidl-fuzzers/authorization_service_fuzzer.rs"],
+    rustlibs: [
+        "libkeystore2",
+        "libkeystore2_crypto_rust",
+        "libkeystore2_vintf_rust",
+        "libkeystore2_aaid-rust",
+        "libkeystore2_apc_compat-rust",
+        "libkeystore2_selinux",
+        "libbinder_rs",
+        "libbinder_random_parcel_rs",
+    ],
+    fuzz_config: {
+        fuzz_on_haiku_device: true,
+        fuzz_on_haiku_host: false,
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+            "smoreland@google.com",
+            "waghpawan@google.com"
+        ],
+        // Adds bugs to hotlist "AIDL fuzzers bugs" on buganizer
+        hotlists: ["4637097"],
+    },
+}
diff --git a/keystore2/src/fuzzers/aidl-fuzzers/authorization_service_fuzzer.rs b/keystore2/src/fuzzers/aidl-fuzzers/authorization_service_fuzzer.rs
new file mode 100644
index 0000000..c1b2098
--- /dev/null
+++ b/keystore2/src/fuzzers/aidl-fuzzers/authorization_service_fuzzer.rs
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#![allow(missing_docs)]
+#![no_main]
+#[macro_use]
+extern crate libfuzzer_sys;
+
+use binder_random_parcel_rs::fuzz_service;
+use keystore2::authorization::AuthorizationManager;
+
+fuzz_target!(|data: &[u8]| {
+    let authorization_service = AuthorizationManager::new_native_binder().unwrap_or_else(|e| {
+        panic!("Failed to create android.security.authorization service because of {:?}", e);
+    });
+    fuzz_service(&mut authorization_service.as_binder(), data);
+});
diff --git a/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs b/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs
index 4c2419a..1a385e7 100644
--- a/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs
+++ b/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs
@@ -16,8 +16,6 @@
 
 #![feature(slice_internals)]
 #![no_main]
-#[macro_use]
-extern crate libfuzzer_sys;
 
 use core::slice::memchr;
 use keystore2::{legacy_blob::LegacyBlobLoader, utils::ui_opts_2_compat};
@@ -31,7 +29,7 @@
 };
 use keystore2_selinux::{check_access, getpidcon, setcon, Backend, Context, KeystoreKeyBackend};
 use keystore2_vintf::{get_aidl_instances, get_hidl_instances};
-use libfuzzer_sys::arbitrary::Arbitrary;
+use libfuzzer_sys::{arbitrary::Arbitrary, fuzz_target};
 use std::{ffi::CString, sync::Arc};
 
 // Avoid allocating too much memory and crashing the fuzzer.
diff --git a/keystore2/src/legacy_blob.rs b/keystore2/src/legacy_blob.rs
index 7cf1819..2ffcc71 100644
--- a/keystore2/src/legacy_blob.rs
+++ b/keystore2/src/legacy_blob.rs
@@ -321,7 +321,7 @@
                     acc.push(c as char);
                 }
                 c => {
-                    acc.push((b'+' + (c as u8 >> 6)) as char);
+                    acc.push((b'+' + (c >> 6)) as char);
                     acc.push((b'0' + (c & 0x3F)) as char);
                 }
             };
diff --git a/keystore2/src/remote_provisioning.rs b/keystore2/src/remote_provisioning.rs
index cb2962a..1a83339 100644
--- a/keystore2/src/remote_provisioning.rs
+++ b/keystore2/src/remote_provisioning.rs
@@ -138,8 +138,8 @@
     /// (2) if remote provisioning is present and enabled on the system. If these conditions are
     /// met, it makes an attempt to fetch the attestation key assigned to the `caller_uid`.
     ///
-    /// It returns the ResponseCode `OUT_OF_KEYS` if there is not one key currently assigned to the
-    /// `caller_uid` and there are none available to assign.
+    /// It returns the ResponseCode `OUT_OF_KEYS_TRANSIENT_ERROR` if there is not one key currently
+    /// assigned to the `caller_uid` and there are none available to assign.
     pub fn get_remotely_provisioned_attestation_key_and_certs(
         &self,
         key: &KeyDescriptor,
@@ -490,7 +490,7 @@
 /// Fetches a remote provisioning attestation key and certificate chain inside of the
 /// returned `CertificateChain` struct if one exists for the given caller_uid. If one has not
 /// been assigned, this function will assign it. If there are no signed attestation keys
-/// available to be assigned, it will return the ResponseCode `OUT_OF_KEYS`
+/// available to be assigned, it will return the ResponseCode `OUT_OF_KEYS_TRANSIENT_ERROR`
 fn get_rem_prov_attest_key(
     domain: Domain,
     caller_uid: u32,
@@ -645,7 +645,7 @@
     /// Fetches a remotely provisioned certificate chain and key for the given client uid that
     /// was provisioned using the IRemotelyProvisionedComponent with the given id. The same key
     /// will be returned for a given caller_uid on every request. If there are no attestation keys
-    /// available, `OUT_OF_KEYS` is returned.
+    /// available, `OUT_OF_KEYS_TRANSIENT_ERROR` is returned.
     fn get_attestation_key(
         &self,
         db: &mut KeystoreDB,
@@ -671,7 +671,7 @@
             }),
             // It should be impossible to get `None`, but handle it just in case as a
             // precaution against future behavioral changes in `get_rem_prov_attest_key`.
-            None => Err(error::Error::Rc(ResponseCode::OUT_OF_KEYS))
+            None => Err(error::Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR))
                 .context(ks_err!("No available attestation keys")),
         }
     }
@@ -958,7 +958,7 @@
                 .unwrap_err()
                 .downcast::<error::Error>()
                 .unwrap(),
-            error::Error::Rc(ResponseCode::OUT_OF_KEYS)
+            error::Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR)
         );
     }
 
@@ -1023,7 +1023,7 @@
                 .unwrap_err()
                 .downcast::<error::Error>()
                 .unwrap(),
-            error::Error::Rc(ResponseCode::OUT_OF_KEYS)
+            error::Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR)
         );
     }
 
diff --git a/keystore2/src/rkpd_client.rs b/keystore2/src/rkpd_client.rs
index b426440..0ea2d39 100644
--- a/keystore2/src/rkpd_client.rs
+++ b/keystore2/src/rkpd_client.rs
@@ -14,14 +14,14 @@
 
 //! Helper wrapper around RKPD interface.
 
-use crate::error::{map_binder_status_code, Error, ErrorCode};
+use crate::error::{map_binder_status_code, Error, ResponseCode};
 use crate::globals::get_remotely_provisioned_component_name;
 use crate::ks_err;
 use crate::utils::watchdog as wd;
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel::SecurityLevel;
 use android_security_rkp_aidl::aidl::android::security::rkp::{
-    IGetKeyCallback::BnGetKeyCallback, IGetKeyCallback::IGetKeyCallback,
-    IGetRegistrationCallback::BnGetRegistrationCallback,
+    IGetKeyCallback::BnGetKeyCallback, IGetKeyCallback::ErrorCode::ErrorCode as GetKeyErrorCode,
+    IGetKeyCallback::IGetKeyCallback, IGetRegistrationCallback::BnGetRegistrationCallback,
     IGetRegistrationCallback::IGetRegistrationCallback, IRegistration::IRegistration,
     IRemoteProvisioning::IRemoteProvisioning,
     IStoreUpgradedKeyCallback::BnStoreUpgradedKeyCallback,
@@ -30,9 +30,19 @@
 };
 use android_security_rkp_aidl::binder::{BinderFeatures, Interface, Strong};
 use anyhow::{Context, Result};
-use futures::channel::oneshot;
-use futures::executor::block_on;
 use std::sync::Mutex;
+use std::time::Duration;
+use tokio::sync::oneshot;
+use tokio::time::timeout;
+
+// Normally, we block indefinitely when making calls outside of keystore and rely on watchdog to
+// report deadlocks. However, RKPD is mainline updatable. Also, calls to RKPD may wait on network
+// for certificates. So, we err on the side of caution and timeout instead.
+static RKPD_TIMEOUT: Duration = Duration::from_secs(10);
+
+fn tokio_rt() -> tokio::runtime::Runtime {
+    tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap()
+}
 
 /// Thread-safe channel for sending a value once and only once. If a value has
 /// already been send, subsequent calls to send will noop.
@@ -47,8 +57,11 @@
 
     fn send(&self, value: T) {
         if let Some(inner) = self.inner.lock().unwrap().take() {
-            // assert instead of unwrap, because on failure send returns Err(value)
-            assert!(inner.send(value).is_ok(), "thread state is terminally broken");
+            // It's possible for the corresponding receiver to time out and be dropped. In this
+            // case send() will fail. This error is not actionable though, so only log the error.
+            if inner.send(value).is_err() {
+                log::error!("SafeSender::send() failed");
+            }
         }
     }
 }
@@ -79,17 +92,17 @@
         let _wp = wd::watch_millis("IGetRegistrationCallback::onCancel", 500);
         log::warn!("IGetRegistrationCallback cancelled");
         self.registration_tx.send(
-            Err(Error::Km(ErrorCode::OPERATION_CANCELLED))
+            Err(Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR))
                 .context(ks_err!("GetRegistrationCallback cancelled.")),
         );
         Ok(())
     }
-    fn onError(&self, error: &str) -> binder::Result<()> {
+    fn onError(&self, description: &str) -> binder::Result<()> {
         let _wp = wd::watch_millis("IGetRegistrationCallback::onError", 500);
-        log::error!("IGetRegistrationCallback failed: '{error}'");
+        log::error!("IGetRegistrationCallback failed: '{description}'");
         self.registration_tx.send(
-            Err(Error::Km(ErrorCode::UNKNOWN_ERROR))
-                .context(ks_err!("GetRegistrationCallback failed: {:?}", error)),
+            Err(Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR))
+                .context(ks_err!("GetRegistrationCallback failed: {:?}", description)),
         );
         Ok(())
     }
@@ -113,7 +126,12 @@
         .getRegistration(&rpc_name, &cb)
         .context(ks_err!("Trying to get registration."))?;
 
-    rx.await.unwrap()
+    match timeout(RKPD_TIMEOUT, rx).await {
+        Err(e) => {
+            Err(Error::Rc(ResponseCode::SYSTEM_ERROR)).context(ks_err!("Waiting for RKPD: {:?}", e))
+        }
+        Ok(v) => v.unwrap(),
+    }
 }
 
 struct GetKeyCallback {
@@ -144,22 +162,61 @@
         let _wp = wd::watch_millis("IGetKeyCallback::onCancel", 500);
         log::warn!("IGetKeyCallback cancelled");
         self.key_tx.send(
-            Err(Error::Km(ErrorCode::OPERATION_CANCELLED))
+            Err(Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR))
                 .context(ks_err!("GetKeyCallback cancelled.")),
         );
         Ok(())
     }
-    fn onError(&self, error: &str) -> binder::Result<()> {
+    fn onError(&self, error: GetKeyErrorCode, description: &str) -> binder::Result<()> {
         let _wp = wd::watch_millis("IGetKeyCallback::onError", 500);
-        log::error!("IGetKeyCallback failed: {error}");
-        self.key_tx.send(
-            Err(Error::Km(ErrorCode::UNKNOWN_ERROR))
-                .context(ks_err!("GetKeyCallback failed: {:?}", error)),
-        );
+        log::error!("IGetKeyCallback failed: {description}");
+        let rc = match error {
+            GetKeyErrorCode::ERROR_UNKNOWN => ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR,
+            GetKeyErrorCode::ERROR_PERMANENT => ResponseCode::OUT_OF_KEYS_PERMANENT_ERROR,
+            GetKeyErrorCode::ERROR_PENDING_INTERNET_CONNECTIVITY => {
+                ResponseCode::OUT_OF_KEYS_PENDING_INTERNET_CONNECTIVITY
+            }
+            GetKeyErrorCode::ERROR_REQUIRES_SECURITY_PATCH => {
+                ResponseCode::OUT_OF_KEYS_REQUIRES_SYSTEM_UPGRADE
+            }
+            _ => {
+                log::error!("Unexpected error from rkpd: {error:?}");
+                ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR
+            }
+        };
+        self.key_tx.send(Err(Error::Rc(rc)).context(ks_err!(
+            "GetKeyCallback failed: {:?} {:?}",
+            error,
+            description
+        )));
         Ok(())
     }
 }
 
+async fn get_rkpd_attestation_key_from_registration_async(
+    registration: &Strong<dyn IRegistration>,
+    caller_uid: u32,
+) -> Result<RemotelyProvisionedKey> {
+    let (tx, rx) = oneshot::channel();
+    let cb = GetKeyCallback::new_native_binder(tx);
+
+    registration
+        .getKey(caller_uid.try_into().unwrap(), &cb)
+        .context(ks_err!("Trying to get key."))?;
+
+    match timeout(RKPD_TIMEOUT, rx).await {
+        Err(e) => {
+            // Make a best effort attempt to cancel the timed out request.
+            if let Err(e) = registration.cancelGetKey(&cb) {
+                log::error!("IRegistration::cancelGetKey failed: {:?}", e);
+            }
+            Err(Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR))
+                .context(ks_err!("Waiting for RKPD key timed out: {:?}", e))
+        }
+        Ok(v) => v.unwrap(),
+    }
+}
+
 async fn get_rkpd_attestation_key_async(
     security_level: &SecurityLevel,
     caller_uid: u32,
@@ -167,15 +224,7 @@
     let registration = get_rkpd_registration(security_level)
         .await
         .context(ks_err!("Trying to get to IRegistration service."))?;
-
-    let (tx, rx) = oneshot::channel();
-    let cb = GetKeyCallback::new_native_binder(tx);
-
-    registration
-        .getKey(caller_uid.try_into().unwrap(), &cb)
-        .context(ks_err!("Trying to get key."))?;
-
-    rx.await.unwrap()
+    get_rkpd_attestation_key_from_registration_async(&registration, caller_uid).await
 }
 
 struct StoreUpgradedKeyCallback {
@@ -204,13 +253,32 @@
         let _wp = wd::watch_millis("IGetRegistrationCallback::onError", 500);
         log::error!("IGetRegistrationCallback failed: {error}");
         self.completer.send(
-            Err(Error::Km(ErrorCode::UNKNOWN_ERROR))
+            Err(Error::Rc(ResponseCode::SYSTEM_ERROR))
                 .context(ks_err!("Failed to store upgraded key: {:?}", error)),
         );
         Ok(())
     }
 }
 
+async fn store_rkpd_attestation_key_with_registration_async(
+    registration: &Strong<dyn IRegistration>,
+    key_blob: &[u8],
+    upgraded_blob: &[u8],
+) -> Result<()> {
+    let (tx, rx) = oneshot::channel();
+    let cb = StoreUpgradedKeyCallback::new_native_binder(tx);
+
+    registration
+        .storeUpgradedKeyAsync(key_blob, upgraded_blob, &cb)
+        .context(ks_err!("Failed to store upgraded blob with RKPD."))?;
+
+    match timeout(RKPD_TIMEOUT, rx).await {
+        Err(e) => Err(Error::Rc(ResponseCode::SYSTEM_ERROR))
+            .context(ks_err!("Waiting for RKPD to complete storing key: {:?}", e)),
+        Ok(v) => v.unwrap(),
+    }
+}
+
 async fn store_rkpd_attestation_key_async(
     security_level: &SecurityLevel,
     key_blob: &[u8],
@@ -219,15 +287,7 @@
     let registration = get_rkpd_registration(security_level)
         .await
         .context(ks_err!("Trying to get to IRegistration service."))?;
-
-    let (tx, rx) = oneshot::channel();
-    let cb = StoreUpgradedKeyCallback::new_native_binder(tx);
-
-    registration
-        .storeUpgradedKeyAsync(key_blob, upgraded_blob, &cb)
-        .context(ks_err!("Failed to store upgraded blob with RKPD."))?;
-
-    rx.await.unwrap()
+    store_rkpd_attestation_key_with_registration_async(&registration, key_blob, upgraded_blob).await
 }
 
 /// Get attestation key from RKPD.
@@ -236,7 +296,7 @@
     caller_uid: u32,
 ) -> Result<RemotelyProvisionedKey> {
     let _wp = wd::watch_millis("Calling get_rkpd_attestation_key()", 500);
-    block_on(get_rkpd_attestation_key_async(security_level, caller_uid))
+    tokio_rt().block_on(get_rkpd_attestation_key_async(security_level, caller_uid))
 }
 
 /// Store attestation key in RKPD.
@@ -246,63 +306,132 @@
     upgraded_blob: &[u8],
 ) -> Result<()> {
     let _wp = wd::watch_millis("Calling store_rkpd_attestation_key()", 500);
-    block_on(store_rkpd_attestation_key_async(security_level, key_blob, upgraded_blob))
+    tokio_rt().block_on(store_rkpd_attestation_key_async(security_level, key_blob, upgraded_blob))
 }
 
 #[cfg(test)]
 mod tests {
     use super::*;
+    use crate::error::map_km_error;
+    use crate::globals::get_keymint_device;
+    use crate::utils::upgrade_keyblob_if_required_with;
+    use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+        Algorithm::Algorithm, AttestationKey::AttestationKey, KeyParameter::KeyParameter,
+        KeyParameterValue::KeyParameterValue, Tag::Tag,
+    };
     use android_security_rkp_aidl::aidl::android::security::rkp::IRegistration::BnRegistration;
-    use std::sync::Arc;
+    use keystore2_crypto::parse_subject_from_certificate;
+    use std::collections::HashMap;
+    use std::sync::atomic::{AtomicU32, Ordering};
+    use std::sync::{Arc, Mutex};
 
-    #[derive(Default)]
     struct MockRegistrationValues {
-        _key: RemotelyProvisionedKey,
+        key: RemotelyProvisionedKey,
+        latency: Option<Duration>,
+        thread_join_handles: Vec<Option<std::thread::JoinHandle<()>>>,
     }
 
-    #[derive(Default)]
     struct MockRegistration(Arc<Mutex<MockRegistrationValues>>);
 
     impl MockRegistration {
-        pub fn new_native_binder() -> Strong<dyn IRegistration> {
-            let result: Self = Default::default();
+        pub fn new_native_binder(
+            key: &RemotelyProvisionedKey,
+            latency: Option<Duration>,
+        ) -> Strong<dyn IRegistration> {
+            let result = Self(Arc::new(Mutex::new(MockRegistrationValues {
+                key: RemotelyProvisionedKey {
+                    keyBlob: key.keyBlob.clone(),
+                    encodedCertChain: key.encodedCertChain.clone(),
+                },
+                latency,
+                thread_join_handles: Vec::new(),
+            })));
             BnRegistration::new_binder(result, BinderFeatures::default())
         }
     }
 
+    impl Drop for MockRegistration {
+        fn drop(&mut self) {
+            let mut values = self.0.lock().unwrap();
+            for handle in values.thread_join_handles.iter_mut() {
+                // These are test threads. So, no need to worry too much about error handling.
+                handle.take().unwrap().join().unwrap();
+            }
+        }
+    }
+
     impl Interface for MockRegistration {}
 
     impl IRegistration for MockRegistration {
-        fn getKey(&self, _: i32, _: &Strong<dyn IGetKeyCallback>) -> binder::Result<()> {
-            todo!()
+        fn getKey(&self, _: i32, cb: &Strong<dyn IGetKeyCallback>) -> binder::Result<()> {
+            let mut values = self.0.lock().unwrap();
+            let key = RemotelyProvisionedKey {
+                keyBlob: values.key.keyBlob.clone(),
+                encodedCertChain: values.key.encodedCertChain.clone(),
+            };
+            let latency = values.latency;
+            let get_key_cb = cb.clone();
+
+            // Need a separate thread to trigger timeout in the caller.
+            let join_handle = std::thread::spawn(move || {
+                if let Some(duration) = latency {
+                    std::thread::sleep(duration);
+                }
+                get_key_cb.onSuccess(&key).unwrap();
+            });
+            values.thread_join_handles.push(Some(join_handle));
+            Ok(())
         }
 
         fn cancelGetKey(&self, _: &Strong<dyn IGetKeyCallback>) -> binder::Result<()> {
-            todo!()
+            Ok(())
         }
 
         fn storeUpgradedKeyAsync(
             &self,
             _: &[u8],
             _: &[u8],
-            _: &Strong<dyn IStoreUpgradedKeyCallback>,
+            cb: &Strong<dyn IStoreUpgradedKeyCallback>,
         ) -> binder::Result<()> {
-            todo!()
+            // We are primarily concerned with timing out correctly. Storing the key in this mock
+            // registration isn't particularly interesting, so skip that part.
+            let values = self.0.lock().unwrap();
+            let store_cb = cb.clone();
+            let latency = values.latency;
+
+            std::thread::spawn(move || {
+                if let Some(duration) = latency {
+                    std::thread::sleep(duration);
+                }
+                store_cb.onSuccess().unwrap();
+            });
+            Ok(())
         }
     }
 
-    fn get_mock_registration() -> Result<binder::Strong<dyn IRegistration>> {
+    fn get_mock_registration(
+        key: &RemotelyProvisionedKey,
+        latency: Option<Duration>,
+    ) -> Result<binder::Strong<dyn IRegistration>> {
         let (tx, rx) = oneshot::channel();
         let cb = GetRegistrationCallback::new_native_binder(tx);
-        let mock_registration = MockRegistration::new_native_binder();
+        let mock_registration = MockRegistration::new_native_binder(key, latency);
 
         assert!(cb.onSuccess(&mock_registration).is_ok());
-        block_on(rx).unwrap()
+        tokio_rt().block_on(rx).unwrap()
+    }
+
+    // Using the same key ID makes test cases race with each other. So, we use separate key IDs for
+    // different test cases.
+    fn get_next_key_id() -> u32 {
+        static ID: AtomicU32 = AtomicU32::new(0);
+        ID.fetch_add(1, Ordering::Relaxed)
     }
 
     #[test]
     fn test_get_registration_cb_success() {
-        let registration = get_mock_registration();
+        let key: RemotelyProvisionedKey = Default::default();
+        let registration = get_mock_registration(&key, /*latency=*/ None);
         assert!(registration.is_ok());
     }
 
@@ -312,10 +441,10 @@
         let cb = GetRegistrationCallback::new_native_binder(tx);
         assert!(cb.onCancel().is_ok());
 
-        let result = block_on(rx).unwrap();
+        let result = tokio_rt().block_on(rx).unwrap();
         assert_eq!(
             result.unwrap_err().downcast::<Error>().unwrap(),
-            Error::Km(ErrorCode::OPERATION_CANCELLED)
+            Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR)
         );
     }
 
@@ -325,10 +454,10 @@
         let cb = GetRegistrationCallback::new_native_binder(tx);
         assert!(cb.onError("error").is_ok());
 
-        let result = block_on(rx).unwrap();
+        let result = tokio_rt().block_on(rx).unwrap();
         assert_eq!(
             result.unwrap_err().downcast::<Error>().unwrap(),
-            Error::Km(ErrorCode::UNKNOWN_ERROR)
+            Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR)
         );
     }
 
@@ -340,7 +469,7 @@
         let cb = GetKeyCallback::new_native_binder(tx);
         assert!(cb.onSuccess(&mock_key).is_ok());
 
-        let key = block_on(rx).unwrap().unwrap();
+        let key = tokio_rt().block_on(rx).unwrap().unwrap();
         assert_eq!(key, mock_key);
     }
 
@@ -350,24 +479,41 @@
         let cb = GetKeyCallback::new_native_binder(tx);
         assert!(cb.onCancel().is_ok());
 
-        let result = block_on(rx).unwrap();
+        let result = tokio_rt().block_on(rx).unwrap();
         assert_eq!(
             result.unwrap_err().downcast::<Error>().unwrap(),
-            Error::Km(ErrorCode::OPERATION_CANCELLED)
+            Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR)
         );
     }
 
     #[test]
     fn test_get_key_cb_error() {
-        let (tx, rx) = oneshot::channel();
-        let cb = GetKeyCallback::new_native_binder(tx);
-        assert!(cb.onError("error").is_ok());
+        let error_mapping = HashMap::from([
+            (GetKeyErrorCode::ERROR_UNKNOWN, ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR),
+            (GetKeyErrorCode::ERROR_PERMANENT, ResponseCode::OUT_OF_KEYS_PERMANENT_ERROR),
+            (
+                GetKeyErrorCode::ERROR_PENDING_INTERNET_CONNECTIVITY,
+                ResponseCode::OUT_OF_KEYS_PENDING_INTERNET_CONNECTIVITY,
+            ),
+            (
+                GetKeyErrorCode::ERROR_REQUIRES_SECURITY_PATCH,
+                ResponseCode::OUT_OF_KEYS_REQUIRES_SYSTEM_UPGRADE,
+            ),
+        ]);
 
-        let result = block_on(rx).unwrap();
-        assert_eq!(
-            result.unwrap_err().downcast::<Error>().unwrap(),
-            Error::Km(ErrorCode::UNKNOWN_ERROR)
-        );
+        // Loop over the generated list of enum values to better ensure this test stays in
+        // sync with the AIDL.
+        for get_key_error in GetKeyErrorCode::enum_values() {
+            let (tx, rx) = oneshot::channel();
+            let cb = GetKeyCallback::new_native_binder(tx);
+            assert!(cb.onError(get_key_error, "error").is_ok());
+
+            let result = tokio_rt().block_on(rx).unwrap();
+            assert_eq!(
+                result.unwrap_err().downcast::<Error>().unwrap(),
+                Error::Rc(error_mapping[&get_key_error]),
+            );
+        }
     }
 
     #[test]
@@ -376,7 +522,7 @@
         let cb = StoreUpgradedKeyCallback::new_native_binder(tx);
         assert!(cb.onSuccess().is_ok());
 
-        block_on(rx).unwrap().unwrap();
+        tokio_rt().block_on(rx).unwrap().unwrap();
     }
 
     #[test]
@@ -385,17 +531,73 @@
         let cb = StoreUpgradedKeyCallback::new_native_binder(tx);
         assert!(cb.onError("oh no! it failed").is_ok());
 
-        let result = block_on(rx).unwrap();
+        let result = tokio_rt().block_on(rx).unwrap();
         assert_eq!(
             result.unwrap_err().downcast::<Error>().unwrap(),
-            Error::Km(ErrorCode::UNKNOWN_ERROR)
+            Error::Rc(ResponseCode::SYSTEM_ERROR)
+        );
+    }
+
+    #[test]
+    fn test_get_mock_key_success() {
+        let mock_key =
+            RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
+        let registration = get_mock_registration(&mock_key, /*latency=*/ None).unwrap();
+
+        let key = tokio_rt()
+            .block_on(get_rkpd_attestation_key_from_registration_async(&registration, 0))
+            .unwrap();
+        assert_eq!(key, mock_key);
+    }
+
+    #[test]
+    fn test_get_mock_key_timeout() {
+        let mock_key =
+            RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
+        let latency = RKPD_TIMEOUT + Duration::from_secs(1);
+        let registration = get_mock_registration(&mock_key, Some(latency)).unwrap();
+
+        let result =
+            tokio_rt().block_on(get_rkpd_attestation_key_from_registration_async(&registration, 0));
+        assert_eq!(
+            result.unwrap_err().downcast::<Error>().unwrap(),
+            Error::Rc(ResponseCode::OUT_OF_KEYS_TRANSIENT_ERROR)
+        );
+    }
+
+    #[test]
+    fn test_store_mock_key_success() {
+        let mock_key =
+            RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
+        let registration = get_mock_registration(&mock_key, /*latency=*/ None).unwrap();
+        tokio_rt()
+            .block_on(store_rkpd_attestation_key_with_registration_async(&registration, &[], &[]))
+            .unwrap();
+    }
+
+    #[test]
+    fn test_store_mock_key_timeout() {
+        let mock_key =
+            RemotelyProvisionedKey { keyBlob: vec![1, 2, 3], encodedCertChain: vec![4, 5, 6] };
+        let latency = RKPD_TIMEOUT + Duration::from_secs(1);
+        let registration = get_mock_registration(&mock_key, Some(latency)).unwrap();
+
+        let result = tokio_rt().block_on(store_rkpd_attestation_key_with_registration_async(
+            &registration,
+            &[],
+            &[],
+        ));
+        assert_eq!(
+            result.unwrap_err().downcast::<Error>().unwrap(),
+            Error::Rc(ResponseCode::SYSTEM_ERROR)
         );
     }
 
     #[test]
     fn test_get_rkpd_attestation_key() {
         binder::ProcessState::start_thread_pool();
-        let key = get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, 0).unwrap();
+        let key_id = get_next_key_id();
+        let key = get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, key_id).unwrap();
         assert!(!key.keyBlob.is_empty());
         assert!(!key.encodedCertChain.is_empty());
     }
@@ -404,11 +606,11 @@
     fn test_get_rkpd_attestation_key_same_caller() {
         binder::ProcessState::start_thread_pool();
         let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
-        let caller_uid = 0;
+        let key_id = get_next_key_id();
 
         // Multiple calls should return the same key.
-        let first_key = get_rkpd_attestation_key(&sec_level, caller_uid).unwrap();
-        let second_key = get_rkpd_attestation_key(&sec_level, caller_uid).unwrap();
+        let first_key = get_rkpd_attestation_key(&sec_level, key_id).unwrap();
+        let second_key = get_rkpd_attestation_key(&sec_level, key_id).unwrap();
 
         assert_eq!(first_key.keyBlob, second_key.keyBlob);
         assert_eq!(first_key.encodedCertChain, second_key.encodedCertChain);
@@ -418,21 +620,120 @@
     fn test_get_rkpd_attestation_key_different_caller() {
         binder::ProcessState::start_thread_pool();
         let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
+        let first_key_id = get_next_key_id();
+        let second_key_id = get_next_key_id();
 
         // Different callers should be getting different keys.
-        let first_key = get_rkpd_attestation_key(&sec_level, 1).unwrap();
-        let second_key = get_rkpd_attestation_key(&sec_level, 2).unwrap();
+        let first_key = get_rkpd_attestation_key(&sec_level, first_key_id).unwrap();
+        let second_key = get_rkpd_attestation_key(&sec_level, second_key_id).unwrap();
 
         assert_ne!(first_key.keyBlob, second_key.keyBlob);
         assert_ne!(first_key.encodedCertChain, second_key.encodedCertChain);
     }
 
     #[test]
+    // Couple of things to note:
+    // 1. This test must never run with UID of keystore. Otherwise, it can mess up keys stored by
+    //    keystore.
+    // 2. Storing and reading the stored key is prone to race condition. So, we only do this in one
+    //    test case.
     fn test_store_rkpd_attestation_key() {
         binder::ProcessState::start_thread_pool();
         let sec_level = SecurityLevel::TRUSTED_ENVIRONMENT;
-        let key = get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, 0).unwrap();
+        let key_id = get_next_key_id();
+        let key = get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, key_id).unwrap();
+        let new_blob: [u8; 8] = rand::random();
 
-        assert!(store_rkpd_attestation_key(&sec_level, &key.keyBlob, &key.keyBlob).is_ok());
+        assert!(store_rkpd_attestation_key(&sec_level, &key.keyBlob, &new_blob).is_ok());
+
+        let new_key =
+            get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, key_id).unwrap();
+
+        // Restore original key so that we don't leave RKPD with invalid blobs.
+        assert!(store_rkpd_attestation_key(&sec_level, &new_blob, &key.keyBlob).is_ok());
+        assert_eq!(new_key.keyBlob, new_blob);
+    }
+
+    #[test]
+    // This is a helper for a manual test. We want to check that after a system upgrade RKPD
+    // attestation keys can also be upgraded and stored again with RKPD. The steps are:
+    // 1. Run this test and check in stdout that no key upgrade happened.
+    // 2. Perform a system upgrade.
+    // 3. Run this test and check in stdout that key upgrade did happen.
+    //
+    // Note that this test must be run with that same UID every time. Running as root, i.e. UID 0,
+    // should do the trick. Also, use "--nocapture" flag to get stdout.
+    fn test_rkpd_attestation_key_upgrade() {
+        binder::ProcessState::start_thread_pool();
+        let security_level = SecurityLevel::TRUSTED_ENVIRONMENT;
+        let (keymint, _, _) = get_keymint_device(&security_level).unwrap();
+        let key_id = get_next_key_id();
+        let mut key_upgraded = false;
+
+        let key = get_rkpd_attestation_key(&security_level, key_id).unwrap();
+        assert!(!key.keyBlob.is_empty());
+        assert!(!key.encodedCertChain.is_empty());
+
+        upgrade_keyblob_if_required_with(
+            &*keymint,
+            &key.keyBlob,
+            /*upgrade_params=*/ &[],
+            /*km_op=*/
+            |blob| {
+                let params = vec![
+                    KeyParameter {
+                        tag: Tag::ALGORITHM,
+                        value: KeyParameterValue::Algorithm(Algorithm::AES),
+                    },
+                    KeyParameter { tag: Tag::KEY_SIZE, value: KeyParameterValue::Integer(128) },
+                ];
+                let attestation_key = AttestationKey {
+                    keyBlob: blob.to_vec(),
+                    attestKeyParams: vec![],
+                    issuerSubjectName: parse_subject_from_certificate(&key.encodedCertChain)
+                        .unwrap(),
+                };
+
+                map_km_error(keymint.generateKey(&params, Some(&attestation_key)))
+            },
+            /*new_blob_handler=*/
+            |new_blob| {
+                // This handler is only executed if a key upgrade was performed.
+                key_upgraded = true;
+                store_rkpd_attestation_key(&security_level, &key.keyBlob, new_blob).unwrap();
+                Ok(())
+            },
+        )
+        .unwrap();
+
+        if key_upgraded {
+            println!("RKPD key was upgraded and stored with RKPD.");
+        } else {
+            println!("RKPD key was NOT upgraded.");
+        }
+    }
+
+    #[test]
+    fn test_stress_get_rkpd_attestation_key() {
+        binder::ProcessState::start_thread_pool();
+        let key_id = get_next_key_id();
+        let mut threads = vec![];
+        const NTHREADS: u32 = 10;
+        const NCALLS: u32 = 1000;
+
+        for _ in 0..NTHREADS {
+            threads.push(std::thread::spawn(move || {
+                for _ in 0..NCALLS {
+                    let key = get_rkpd_attestation_key(&SecurityLevel::TRUSTED_ENVIRONMENT, key_id)
+                        .unwrap();
+                    assert!(!key.keyBlob.is_empty());
+                    assert!(!key.encodedCertChain.is_empty());
+                }
+            }));
+        }
+
+        for t in threads {
+            assert!(t.join().is_ok());
+        }
     }
 }
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index b928fb0..cc1f816 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -612,7 +612,7 @@
                         })
                     },
                 )
-                .context("While generating Key with remote provisioned attestation key.")
+                .context(ks_err!("While generating Key with remote provisioned attestation key."))
                 .map(|(mut result, _)| {
                     result.certificateChain.push(attestation_certs);
                     result
@@ -635,7 +635,7 @@
                         self.keymint.generateKey(&params, dynamic_attest_key.as_ref())
                     })
                 })
-                .context("While generating Key with remote provisioned attestation key.")
+                .context(ks_err!("While generating Key with remote provisioned attestation key."))
                 .map(|(mut result, _)| {
                     result.certificateChain.push(attestation_certs);
                     result
@@ -651,7 +651,7 @@
                 );
                 self.keymint.generateKey(&params, None)
             })
-            .context("While generating Key without explicit attestation key."),
+            .context(ks_err!("While generating Key without explicit attestation key.")),
         }
         .context(ks_err!())?;
 
@@ -684,7 +684,7 @@
         };
 
         // import_key requires the rebind permission.
-        check_key_permission(KeyPerm::Rebind, &key, &None).context("In import_key.")?;
+        check_key_permission(KeyPerm::Rebind, &key, &None).context(ks_err!("In import_key."))?;
 
         let params = self
             .add_required_parameters(caller_uid, params, &key)
@@ -694,7 +694,7 @@
             .iter()
             .find(|p| p.tag == Tag::ALGORITHM)
             .ok_or(error::Error::Km(ErrorCode::INVALID_ARGUMENT))
-            .context("No KeyParameter 'Algorithm'.")
+            .context(ks_err!("No KeyParameter 'Algorithm'."))
             .and_then(|p| match &p.value {
                 KeyParameterValue::Algorithm(Algorithm::AES)
                 | KeyParameterValue::Algorithm(Algorithm::HMAC)
@@ -780,7 +780,7 @@
                     )
                 })
             })
-            .context("Failed to load wrapping key.")?;
+            .context(ks_err!("Failed to load wrapping key."))?;
 
         let (wrapping_key_blob, wrapping_blob_metadata) =
             wrapping_key_entry.take_key_blob_info().ok_or_else(error::Error::sys).context(
diff --git a/keystore2/src/service.rs b/keystore2/src/service.rs
index f43ba5c..1040228 100644
--- a/keystore2/src/service.rs
+++ b/keystore2/src/service.rs
@@ -205,17 +205,18 @@
             let mut db = db.borrow_mut();
             if let Some((key_id_guard, _key_entry)) = entry {
                 db.set_blob(&key_id_guard, SubComponentType::CERT, public_cert, None)
-                    .context("Failed to update cert subcomponent.")?;
+                    .context(ks_err!("Failed to update cert subcomponent."))?;
 
                 db.set_blob(&key_id_guard, SubComponentType::CERT_CHAIN, certificate_chain, None)
-                    .context("Failed to update cert chain subcomponent.")?;
+                    .context(ks_err!("Failed to update cert chain subcomponent."))?;
                 return Ok(());
             }
 
             // If we reach this point we have to check the special condition where a certificate
             // entry may be made.
             if !(public_cert.is_none() && certificate_chain.is_some()) {
-                return Err(Error::Rc(ResponseCode::KEY_NOT_FOUND)).context("No key to update.");
+                return Err(Error::Rc(ResponseCode::KEY_NOT_FOUND))
+                    .context(ks_err!("No key to update."));
             }
 
             // So we know that we have a certificate chain and no public cert.
@@ -230,13 +231,13 @@
                 (Domain::SELINUX, Some(_)) => key.clone(),
                 _ => {
                     return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT))
-                        .context("Domain must be APP or SELINUX to insert a certificate.")
+                        .context(ks_err!("Domain must be APP or SELINUX to insert a certificate."))
                 }
             };
 
             // Security critical: This must return on failure. Do not remove the `?`;
             check_key_permission(KeyPerm::Rebind, &key, &None)
-                .context("Caller does not have permission to insert this certificate.")?;
+                .context(ks_err!("Caller does not have permission to insert this certificate."))?;
 
             db.store_new_certificate(
                 &key,
@@ -244,7 +245,7 @@
                 certificate_chain.unwrap(),
                 &KEYSTORE_UUID,
             )
-            .context("Failed to insert new certificate.")?;
+            .context(ks_err!("Failed to insert new certificate."))?;
             Ok(())
         })
         .context(ks_err!())
@@ -295,7 +296,8 @@
         DB.with(|db| {
             LEGACY_IMPORTER.with_try_import(key, caller_uid, super_key, || {
                 db.borrow_mut().unbind_key(key, KeyType::Client, caller_uid, |k, av| {
-                    check_key_permission(KeyPerm::Delete, k, &av).context("During delete_key.")
+                    check_key_permission(KeyPerm::Delete, k, &av)
+                        .context(ks_err!("During delete_key."))
                 })
             })
         })
diff --git a/keystore2/src/utils.rs b/keystore2/src/utils.rs
index 75d98e2..7bc548e 100644
--- a/keystore2/src/utils.rs
+++ b/keystore2/src/utils.rs
@@ -209,6 +209,7 @@
     parameters.into_iter().map(|p| p.into_authorization()).collect()
 }
 
+#[allow(clippy::unnecessary_cast)]
 /// This returns the current time (in milliseconds) as an instance of a monotonic clock,
 /// by invoking the system call since Rust does not support getting monotonic time instance
 /// as an integer.
@@ -276,7 +277,40 @@
     );
     result.sort_unstable();
     result.dedup();
-    Ok(result)
+
+    let mut items_to_return = 0;
+    let mut returned_bytes: usize = 0;
+    const RESPONSE_SIZE_LIMIT: usize = 358400;
+    // Estimate the transaction size to avoid returning more items than what
+    // could fit in a binder transaction.
+    for kd in result.iter() {
+        // 4 bytes for the Domain enum
+        // 8 bytes for the Namespace long.
+        returned_bytes += 4 + 8;
+        // Size of the alias string. Includes 4 bytes for length encoding.
+        if let Some(alias) = &kd.alias {
+            returned_bytes += 4 + alias.len();
+        }
+        // Size of the blob. Includes 4 bytes for length encoding.
+        if let Some(blob) = &kd.blob {
+            returned_bytes += 4 + blob.len();
+        }
+        // The binder transaction size limit is 1M. Empirical measurements show
+        // that the binder overhead is 60% (to be confirmed). So break after
+        // 350KB and return a partial list.
+        if returned_bytes > RESPONSE_SIZE_LIMIT {
+            log::warn!(
+                "Key descriptors list ({} items) may exceed binder \
+                       size, returning {} items est {} bytes.",
+                result.len(),
+                items_to_return,
+                returned_bytes
+            );
+            break;
+        }
+        items_to_return += 1;
+    }
+    Ok(result[..items_to_return].to_vec())
 }
 
 /// This module provides helpers for simplified use of the watchdog module.
diff --git a/keystore2/src/watchdog.rs b/keystore2/src/watchdog.rs
index a26b632..01043c5 100644
--- a/keystore2/src/watchdog.rs
+++ b/keystore2/src/watchdog.rs
@@ -141,7 +141,7 @@
             },
         );
         // Put the groups back into a vector.
-        let mut groups: Vec<Vec<(&Index, &Record)>> = groups.into_iter().map(|(_, v)| v).collect();
+        let mut groups: Vec<Vec<(&Index, &Record)>> = groups.into_values().collect();
         // Sort the groups by start time of the most recent (.last()) of each group.
         // It is panic safe to use unwrap() here because we never add empty vectors to
         // the map.
diff --git a/keystore2/test_utils/key_generations.rs b/keystore2/test_utils/key_generations.rs
index f9aaabb..e4c4968 100644
--- a/keystore2/test_utils/key_generations.rs
+++ b/keystore2/test_utils/key_generations.rs
@@ -1047,3 +1047,38 @@
         transport_key,
     )
 }
+
+/// Generate EC key with purpose AGREE_KEY.
+pub fn generate_ec_agree_key(
+    sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+    ec_curve: EcCurve,
+    digest: Digest,
+    domain: Domain,
+    nspace: i64,
+    alias: Option<String>,
+) -> binder::Result<KeyMetadata> {
+    let gen_params = AuthSetBuilder::new()
+        .no_auth_required()
+        .algorithm(Algorithm::EC)
+        .purpose(KeyPurpose::AGREE_KEY)
+        .digest(digest)
+        .ec_curve(ec_curve);
+
+    match sec_level.generateKey(
+        &KeyDescriptor { domain, nspace, alias, blob: None },
+        None,
+        &gen_params,
+        0,
+        b"entropy",
+    ) {
+        Ok(key_metadata) => {
+            assert!(key_metadata.certificate.is_some());
+            if domain == Domain::BLOB {
+                assert!(key_metadata.key.blob.is_some());
+            }
+
+            Ok(key_metadata)
+        }
+        Err(e) => Err(e),
+    }
+}
diff --git a/keystore2/tests/ffi_test_utils.cpp b/keystore2/tests/ffi_test_utils.cpp
index 45ce02c..de20d83 100644
--- a/keystore2/tests/ffi_test_utils.cpp
+++ b/keystore2/tests/ffi_test_utils.cpp
@@ -237,7 +237,7 @@
     }
 
     // Perform ASN.1 DER encoding of KeyDescription.
-    size_t asn1_data_len = i2d_TEST_KEY_DESCRIPTION(key_description.get(), nullptr);
+    int asn1_data_len = i2d_TEST_KEY_DESCRIPTION(key_description.get(), nullptr);
     if (asn1_data_len < 0) {
         cxx_result.error = keymaster::TranslateLastOpenSslError();
         return cxx_result;
@@ -341,7 +341,7 @@
     }
 
     // ASN.1 DER-encoding of secure key wrapper.
-    size_t asn1_data_len = i2d_TEST_SECURE_KEY_WRAPPER(sec_key_wrapper.get(), nullptr);
+    int asn1_data_len = i2d_TEST_SECURE_KEY_WRAPPER(sec_key_wrapper.get(), nullptr);
     if (asn1_data_len < 0) {
         cxx_result.error = keymaster::TranslateLastOpenSslError();
         return cxx_result;
diff --git a/keystore2/tests/keystore2_client_attest_key_tests.rs b/keystore2/tests/keystore2_client_attest_key_tests.rs
index 2d44753..4febd9b 100644
--- a/keystore2/tests/keystore2_client_attest_key_tests.rs
+++ b/keystore2/tests/keystore2_client_attest_key_tests.rs
@@ -149,9 +149,7 @@
         let mut cert_chain: Vec<u8> = Vec::new();
         cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
         cert_chain.extend(attestation_key_metadata.certificateChain.as_ref().unwrap());
-        // The server seems to be issuing test certs with invalid subject names.
-        // Re-enable when b/263254184 is fixed
-        // validate_certchain(&cert_chain).expect("Error while validating cert chain.");
+        validate_certchain(&cert_chain).expect("Error while validating cert chain.");
 
         // Create EC key and use attestation key to sign it.
         let ec_key_alias = format!("ks_ec_attested_test_key_{}", getuid());
@@ -168,9 +166,7 @@
         cert_chain.extend(attestation_key_metadata.certificate.as_ref().unwrap());
         cert_chain.extend(attestation_key_metadata.certificateChain.as_ref().unwrap());
 
-        // The server seems to be issuing test certs with invalid subject names.
-        // Re-enable when b/263254184 is fixed
-        // validate_certchain(&cert_chain).expect("Error while validating cert chain.");
+        validate_certchain(&cert_chain).expect("Error while validating cert chain.");
     }
 }
 
diff --git a/keystore2/tests/keystore2_client_delete_key_tests.rs b/keystore2/tests/keystore2_client_delete_key_tests.rs
new file mode 100644
index 0000000..2a06edb
--- /dev/null
+++ b/keystore2/tests/keystore2_client_delete_key_tests.rs
@@ -0,0 +1,150 @@
+// Copyright 2022, 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 nix::unistd::getuid;
+
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+    ErrorCode::ErrorCode, SecurityLevel::SecurityLevel,
+};
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Domain::Domain, KeyDescriptor::KeyDescriptor, ResponseCode::ResponseCode,
+};
+
+use keystore2_test_utils::{get_keystore_service, key_generations, key_generations::Error};
+
+/// Generate a key and delete it using keystore2 service `deleteKey` API. Test should successfully
+/// delete the generated key.
+#[test]
+fn keystore2_delete_key_success() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let alias = "delete_key_success_key";
+
+    let key_metadata = key_generations::generate_ec_p256_signing_key(
+        &sec_level,
+        Domain::APP,
+        -1,
+        Some(alias.to_string()),
+        None,
+    )
+    .unwrap();
+
+    keystore2.deleteKey(&key_metadata.key).expect("Failed to delete a key.");
+
+    // Check wehther deleted key is removed from keystore.
+    let result = key_generations::map_ks_error(keystore2.getKeyEntry(&key_metadata.key));
+    assert!(result.is_err());
+    assert_eq!(Error::Rc(ResponseCode::KEY_NOT_FOUND), result.unwrap_err());
+}
+
+/// Try to delete non-existing key with domain other than BLOB using keystore2 service `deleteKey`
+/// API. Test should fail with an error code `KEY_NOT_FOUND`.
+#[test]
+fn keystore2_delete_key_fail() {
+    let test_alias = "delete_key_failure_key";
+    let keystore2 = get_keystore_service();
+
+    let result = key_generations::map_ks_error(keystore2.deleteKey(&KeyDescriptor {
+        domain: Domain::SELINUX,
+        nspace: key_generations::SELINUX_SHELL_NAMESPACE,
+        alias: Some(test_alias.to_string()),
+        blob: None,
+    }));
+    assert!(result.is_err());
+    assert_eq!(Error::Rc(ResponseCode::KEY_NOT_FOUND), result.unwrap_err());
+}
+
+/// Generate a key with `Domain::BLOB`. Try to delete a key with `Domain::BLOB` using keystore2
+/// service `deleteKey` API. Test should fail to delete a key with domain BLOB with an error code
+/// `INVALID_ARGUMENT`.
+#[test]
+fn keystore2_delete_key_with_blob_domain_fail() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let alias = "delete_key_blob_fail_key";
+
+    let key_metadata = key_generations::generate_ec_p256_signing_key(
+        &sec_level,
+        Domain::BLOB,
+        key_generations::SELINUX_SHELL_NAMESPACE,
+        Some(alias.to_string()),
+        None,
+    )
+    .unwrap();
+
+    let result = key_generations::map_ks_error(keystore2.deleteKey(&key_metadata.key));
+    assert!(result.is_err());
+    assert_eq!(Error::Rc(ResponseCode::INVALID_ARGUMENT), result.unwrap_err());
+}
+
+/// Generate a key with `Domain::BLOB`. Delete generated key with `Domain::BLOB` using underlying
+/// security level `deleteKey` API. Test should delete the key successfully.
+#[test]
+fn keystore2_delete_key_blob_success() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let alias = "delete_key_blob_success_key";
+
+    let key_metadata = key_generations::generate_ec_p256_signing_key(
+        &sec_level,
+        Domain::BLOB,
+        key_generations::SELINUX_SHELL_NAMESPACE,
+        Some(alias.to_string()),
+        None,
+    )
+    .unwrap();
+
+    let result = sec_level.deleteKey(&key_metadata.key);
+    assert!(result.is_ok());
+}
+
+/// Try to delete a key with `Domain::BLOB` without providing key-blob. Test should fail to delete a
+/// key with error code `INVALID_ARGUMENT`.
+#[test]
+fn keystore2_delete_key_fails_with_missing_key_blob() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let result = key_generations::map_ks_error(sec_level.deleteKey(&KeyDescriptor {
+        domain: Domain::BLOB,
+        nspace: key_generations::SELINUX_SHELL_NAMESPACE,
+        alias: None,
+        blob: None,
+    }));
+    assert!(result.is_err());
+    assert_eq!(Error::Km(ErrorCode::INVALID_ARGUMENT), result.unwrap_err());
+}
+
+/// Try to delete a key with domain other than `Domain::BLOB` using underlying security-level
+/// `deleteKey` API. Test should fail to delete a key-blob from underlying security-level backend
+/// with error code `INVALID_ARGUMENT`.
+#[test]
+fn keystore2_delete_key_blob_fail() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let alias = format!("ks_delete_keyblob_test_key_{}", getuid());
+
+    let key_metadata = key_generations::generate_ec_p256_signing_key(
+        &sec_level,
+        Domain::APP,
+        -1,
+        Some(alias),
+        None,
+    )
+    .unwrap();
+
+    let result = key_generations::map_ks_error(sec_level.deleteKey(&key_metadata.key));
+    assert!(result.is_err());
+    assert_eq!(Error::Km(ErrorCode::INVALID_ARGUMENT), result.unwrap_err());
+}
diff --git a/keystore2/tests/keystore2_client_grant_key_tests.rs b/keystore2/tests/keystore2_client_grant_key_tests.rs
index 7c75734..bde872d 100644
--- a/keystore2/tests/keystore2_client_grant_key_tests.rs
+++ b/keystore2/tests/keystore2_client_grant_key_tests.rs
@@ -19,7 +19,8 @@
     Digest::Digest, KeyPurpose::KeyPurpose, SecurityLevel::SecurityLevel,
 };
 use android_system_keystore2::aidl::android::system::keystore2::{
-    Domain::Domain, KeyDescriptor::KeyDescriptor, KeyPermission::KeyPermission,
+    Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel,
+    IKeystoreService::IKeystoreService, KeyDescriptor::KeyDescriptor, KeyPermission::KeyPermission,
     ResponseCode::ResponseCode,
 };
 
@@ -27,7 +28,9 @@
     authorizations, get_keystore_service, key_generations, key_generations::Error, run_as,
 };
 
-use crate::keystore2_client_test_utils::perform_sample_sign_operation;
+use crate::keystore2_client_test_utils::{
+    generate_ec_key_and_grant_to_users, perform_sample_sign_operation,
+};
 
 /// Generate an EC signing key and grant it to the user with given access vector.
 fn generate_ec_key_and_grant_to_user(
@@ -50,6 +53,36 @@
     keystore2.grant(&key_metadata.key, grantee_uid, access_vector)
 }
 
+fn load_grant_key_and_perform_sign_operation(
+    keystore2: &binder::Strong<dyn IKeystoreService>,
+    sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+    grant_key_nspace: i64,
+) -> Result<(), binder::Status> {
+    let key_entry_response = keystore2.getKeyEntry(&KeyDescriptor {
+        domain: Domain::GRANT,
+        nspace: grant_key_nspace,
+        alias: None,
+        blob: None,
+    })?;
+
+    // Perform sample crypto operation using granted key.
+    let op_response = sec_level.createOperation(
+        &key_entry_response.metadata.key,
+        &authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN).digest(Digest::SHA_2_256),
+        false,
+    )?;
+
+    assert!(op_response.iOperation.is_some());
+    assert_eq!(
+        Ok(()),
+        key_generations::map_ks_error(perform_sample_sign_operation(
+            &op_response.iOperation.unwrap()
+        ))
+    );
+
+    Ok(())
+}
+
 /// Try to grant a key with permission that does not map to any of the `KeyPermission` values.
 /// An error is expected with values that does not map to set of permissions listed in
 /// `KeyPermission`.
@@ -203,3 +236,520 @@
         )
     };
 }
+
+/// Grant a key to the user with DELETE access. In grantee context load the key and delete it.
+/// Verify that grantee should succeed in deleting the granted key and in grantor context test
+/// should fail to find the key with error response `KEY_NOT_FOUND`.
+#[test]
+fn keystore2_grant_delete_key_success() {
+    static GRANTOR_SU_CTX: &str = "u:r:su:s0";
+    static GRANTEE_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+    const USER_ID: u32 = 99;
+    const APPLICATION_ID: u32 = 10001;
+    static GRANTEE_UID: u32 = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
+    static GRANTEE_GID: u32 = GRANTEE_UID;
+    static ALIAS: &str = "ks_grant_key_delete_success";
+
+    // Generate a key and grant it to a user with DELETE permission.
+    let grant_key_nspace = unsafe {
+        run_as::run_as(GRANTOR_SU_CTX, Uid::from_raw(0), Gid::from_raw(0), || {
+            let keystore2 = get_keystore_service();
+            let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+            let access_vector = KeyPermission::DELETE.0;
+            let mut grant_keys = generate_ec_key_and_grant_to_users(
+                &keystore2,
+                &sec_level,
+                Some(ALIAS.to_string()),
+                vec![GRANTEE_UID.try_into().unwrap()],
+                access_vector,
+            )
+            .unwrap();
+
+            grant_keys.remove(0)
+        })
+    };
+
+    // Grantee context, delete the key.
+    unsafe {
+        run_as::run_as(
+            GRANTEE_CTX,
+            Uid::from_raw(GRANTEE_UID),
+            Gid::from_raw(GRANTEE_GID),
+            move || {
+                let keystore2 = get_keystore_service();
+                keystore2
+                    .deleteKey(&KeyDescriptor {
+                        domain: Domain::GRANT,
+                        nspace: grant_key_nspace,
+                        alias: None,
+                        blob: None,
+                    })
+                    .unwrap();
+            },
+        )
+    };
+
+    // Verify whether key got deleted in grantor's context.
+    unsafe {
+        run_as::run_as(GRANTOR_SU_CTX, Uid::from_raw(0), Gid::from_raw(0), move || {
+            let keystore2_inst = get_keystore_service();
+            let result =
+                key_generations::map_ks_error(keystore2_inst.getKeyEntry(&KeyDescriptor {
+                    domain: Domain::APP,
+                    nspace: -1,
+                    alias: Some(ALIAS.to_string()),
+                    blob: None,
+                }));
+            assert!(result.is_err());
+            assert_eq!(Error::Rc(ResponseCode::KEY_NOT_FOUND), result.unwrap_err());
+        })
+    };
+}
+
+/// Grant a key to the user. In grantee context load the granted key and try to grant it to second
+/// user. Test should fail with a response code `PERMISSION_DENIED` to grant a key to second user
+/// from grantee context. Test should make sure second grantee should not have a access to granted
+/// key.
+#[test]
+fn keystore2_grant_key_fails_with_permission_denied() {
+    static GRANTOR_SU_CTX: &str = "u:r:su:s0";
+    static GRANTEE_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+    const USER_ID: u32 = 99;
+    const APPLICATION_ID: u32 = 10001;
+    static GRANTEE_UID: u32 = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
+    static GRANTEE_GID: u32 = GRANTEE_UID;
+
+    const SEC_USER_ID: u32 = 98;
+    const SEC_APPLICATION_ID: u32 = 10001;
+    static SEC_GRANTEE_UID: u32 = SEC_USER_ID * AID_USER_OFFSET + SEC_APPLICATION_ID;
+    static SEC_GRANTEE_GID: u32 = SEC_GRANTEE_UID;
+
+    // Generate a key and grant it to a user with GET_INFO permission.
+    let grant_key_nspace = unsafe {
+        run_as::run_as(GRANTOR_SU_CTX, Uid::from_raw(0), Gid::from_raw(0), || {
+            let keystore2 = get_keystore_service();
+            let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+            let access_vector = KeyPermission::GET_INFO.0;
+            let alias = format!("ks_grant_perm_denied_key_{}", getuid());
+            let mut grant_keys = generate_ec_key_and_grant_to_users(
+                &keystore2,
+                &sec_level,
+                Some(alias),
+                vec![GRANTEE_UID.try_into().unwrap()],
+                access_vector,
+            )
+            .unwrap();
+
+            grant_keys.remove(0)
+        })
+    };
+
+    // Grantee context, load the granted key and try to grant it to `SEC_GRANTEE_UID` grantee.
+    unsafe {
+        run_as::run_as(
+            GRANTEE_CTX,
+            Uid::from_raw(GRANTEE_UID),
+            Gid::from_raw(GRANTEE_GID),
+            move || {
+                let keystore2 = get_keystore_service();
+                let access_vector = KeyPermission::GET_INFO.0;
+
+                let key_entry_response = keystore2
+                    .getKeyEntry(&KeyDescriptor {
+                        domain: Domain::GRANT,
+                        nspace: grant_key_nspace,
+                        alias: None,
+                        blob: None,
+                    })
+                    .unwrap();
+
+                let result = key_generations::map_ks_error(keystore2.grant(
+                    &key_entry_response.metadata.key,
+                    SEC_GRANTEE_UID.try_into().unwrap(),
+                    access_vector,
+                ));
+                assert!(result.is_err());
+                assert_eq!(Error::Rc(ResponseCode::PERMISSION_DENIED), result.unwrap_err());
+            },
+        )
+    };
+
+    // Make sure second grantee shouldn't have access to the above granted key.
+    unsafe {
+        run_as::run_as(
+            GRANTEE_CTX,
+            Uid::from_raw(SEC_GRANTEE_UID),
+            Gid::from_raw(SEC_GRANTEE_GID),
+            move || {
+                let keystore2 = get_keystore_service();
+
+                let result = key_generations::map_ks_error(keystore2.getKeyEntry(&KeyDescriptor {
+                    domain: Domain::GRANT,
+                    nspace: grant_key_nspace,
+                    alias: None,
+                    blob: None,
+                }));
+
+                assert!(result.is_err());
+                assert_eq!(Error::Rc(ResponseCode::KEY_NOT_FOUND), result.unwrap_err());
+            },
+        )
+    };
+}
+
+/// Try to grant a key with `GRANT` access. Keystore2 system shouldn't allow to grant a key with
+/// `GRANT` access. Test should fail to grant a key with `PERMISSION_DENIED` error response code.
+#[test]
+fn keystore2_grant_key_fails_with_grant_perm_expect_perm_denied() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let access_vector = KeyPermission::GRANT.0;
+    let alias = format!("ks_grant_access_vec_key_{}", getuid());
+    let user_id = 98;
+    let application_id = 10001;
+    let grantee_uid = user_id * AID_USER_OFFSET + application_id;
+
+    let result = key_generations::map_ks_error(generate_ec_key_and_grant_to_users(
+        &keystore2,
+        &sec_level,
+        Some(alias),
+        vec![grantee_uid.try_into().unwrap()],
+        access_vector,
+    ));
+    assert!(result.is_err());
+    assert_eq!(Error::Rc(ResponseCode::PERMISSION_DENIED), result.unwrap_err());
+}
+
+/// Try to grant a non-existing key to the user. Test should fail with `KEY_NOT_FOUND` error
+/// response.
+#[test]
+fn keystore2_grant_fails_with_non_existing_key_expect_key_not_found_err() {
+    let keystore2 = get_keystore_service();
+    let alias = format!("ks_grant_test_non_existing_key_5_{}", getuid());
+    let user_id = 98;
+    let application_id = 10001;
+    let grantee_uid = user_id * AID_USER_OFFSET + application_id;
+    let access_vector = KeyPermission::GET_INFO.0;
+
+    let result = key_generations::map_ks_error(keystore2.grant(
+        &KeyDescriptor {
+            domain: Domain::SELINUX,
+            nspace: key_generations::SELINUX_SHELL_NAMESPACE,
+            alias: Some(alias),
+            blob: None,
+        },
+        grantee_uid.try_into().unwrap(),
+        access_vector,
+    ));
+    assert!(result.is_err());
+    assert_eq!(Error::Rc(ResponseCode::KEY_NOT_FOUND), result.unwrap_err());
+}
+
+/// Grant a key to the user and immediately ungrant the granted key. In grantee context try to load
+/// the key. Grantee should fail to load the ungranted key with `KEY_NOT_FOUND` error response.
+#[test]
+fn keystore2_ungrant_key_success() {
+    static GRANTOR_SU_CTX: &str = "u:r:su:s0";
+    static GRANTEE_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+    const USER_ID: u32 = 99;
+    const APPLICATION_ID: u32 = 10001;
+    static GRANTEE_UID: u32 = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
+    static GRANTEE_GID: u32 = GRANTEE_UID;
+
+    // Generate a key and grant it to a user with GET_INFO permission.
+    let grant_key_nspace = unsafe {
+        run_as::run_as(GRANTOR_SU_CTX, Uid::from_raw(0), Gid::from_raw(0), || {
+            let keystore2 = get_keystore_service();
+            let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+            let alias = format!("ks_ungrant_test_key_1{}", getuid());
+            let access_vector = KeyPermission::GET_INFO.0;
+            let mut grant_keys = generate_ec_key_and_grant_to_users(
+                &keystore2,
+                &sec_level,
+                Some(alias.to_string()),
+                vec![GRANTEE_UID.try_into().unwrap()],
+                access_vector,
+            )
+            .unwrap();
+
+            let grant_key_nspace = grant_keys.remove(0);
+
+            //Ungrant above granted key.
+            keystore2
+                .ungrant(
+                    &KeyDescriptor {
+                        domain: Domain::APP,
+                        nspace: -1,
+                        alias: Some(alias),
+                        blob: None,
+                    },
+                    GRANTEE_UID.try_into().unwrap(),
+                )
+                .unwrap();
+
+            grant_key_nspace
+        })
+    };
+
+    // Grantee context, try to load the ungranted key.
+    unsafe {
+        run_as::run_as(
+            GRANTEE_CTX,
+            Uid::from_raw(GRANTEE_UID),
+            Gid::from_raw(GRANTEE_GID),
+            move || {
+                let keystore2 = get_keystore_service();
+                let result = key_generations::map_ks_error(keystore2.getKeyEntry(&KeyDescriptor {
+                    domain: Domain::GRANT,
+                    nspace: grant_key_nspace,
+                    alias: None,
+                    blob: None,
+                }));
+                assert!(result.is_err());
+                assert_eq!(Error::Rc(ResponseCode::KEY_NOT_FOUND), result.unwrap_err());
+            },
+        )
+    };
+}
+
+/// Generate a key, grant it to the user and then delete the granted key. Try to ungrant
+/// a deleted key. Test should fail to ungrant a non-existing key with `KEY_NOT_FOUND` error
+/// response. Generate a new key with the same alias and try to access the previously granted
+/// key in grantee context. Test should fail to load the granted key in grantee context as the
+/// associated key is deleted from grantor context.
+#[test]
+fn keystore2_ungrant_fails_with_non_existing_key_expect_key_not_found_error() {
+    static GRANTOR_SU_CTX: &str = "u:r:su:s0";
+    static GRANTEE_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+
+    const APPLICATION_ID: u32 = 10001;
+    const USER_ID: u32 = 99;
+    static GRANTEE_UID: u32 = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
+    static GRANTEE_GID: u32 = GRANTEE_UID;
+
+    let grant_key_nspace = unsafe {
+        run_as::run_as(GRANTOR_SU_CTX, Uid::from_raw(0), Gid::from_raw(0), || {
+            let keystore2 = get_keystore_service();
+            let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+            let alias = format!("{}{}", "ks_grant_delete_ungrant_test_key_1", getuid());
+
+            let key_metadata = key_generations::generate_ec_p256_signing_key(
+                &sec_level,
+                Domain::SELINUX,
+                key_generations::SELINUX_SHELL_NAMESPACE,
+                Some(alias.to_string()),
+                None,
+            )
+            .unwrap();
+
+            let access_vector = KeyPermission::GET_INFO.0;
+            let grant_key = keystore2
+                .grant(&key_metadata.key, GRANTEE_UID.try_into().unwrap(), access_vector)
+                .unwrap();
+            assert_eq!(grant_key.domain, Domain::GRANT);
+
+            // Delete above granted key.
+            keystore2.deleteKey(&key_metadata.key).unwrap();
+
+            // Try to ungrant above granted key.
+            let result = key_generations::map_ks_error(
+                keystore2.ungrant(&key_metadata.key, GRANTEE_UID.try_into().unwrap()),
+            );
+            assert!(result.is_err());
+            assert_eq!(Error::Rc(ResponseCode::KEY_NOT_FOUND), result.unwrap_err());
+
+            // Generate a new key with the same alias and try to access the earlier granted key
+            // in grantee context.
+            let result = key_generations::generate_ec_p256_signing_key(
+                &sec_level,
+                Domain::SELINUX,
+                key_generations::SELINUX_SHELL_NAMESPACE,
+                Some(alias),
+                None,
+            );
+            assert!(result.is_ok());
+
+            grant_key.nspace
+        })
+    };
+
+    // Make sure grant did not persist, try to access the earlier granted key in grantee context.
+    // Grantee context should fail to load the granted key as its associated key is deleted in
+    // grantor context.
+    unsafe {
+        run_as::run_as(
+            GRANTEE_CTX,
+            Uid::from_raw(GRANTEE_UID),
+            Gid::from_raw(GRANTEE_GID),
+            move || {
+                let keystore2 = get_keystore_service();
+
+                let result = key_generations::map_ks_error(keystore2.getKeyEntry(&KeyDescriptor {
+                    domain: Domain::GRANT,
+                    nspace: grant_key_nspace,
+                    alias: None,
+                    blob: None,
+                }));
+                assert!(result.is_err());
+                assert_eq!(Error::Rc(ResponseCode::KEY_NOT_FOUND), result.unwrap_err());
+            },
+        )
+    };
+}
+
+/// Grant a key to multiple users. Verify that all grantees should succeed in loading the key and
+/// use it for performing an operation successfully.
+#[test]
+fn keystore2_grant_key_to_multi_users_success() {
+    static GRANTOR_SU_CTX: &str = "u:r:su:s0";
+    static GRANTEE_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+
+    const APPLICATION_ID: u32 = 10001;
+    const USER_ID_1: u32 = 99;
+    static GRANTEE_1_UID: u32 = USER_ID_1 * AID_USER_OFFSET + APPLICATION_ID;
+    static GRANTEE_1_GID: u32 = GRANTEE_1_UID;
+
+    const USER_ID_2: u32 = 98;
+    static GRANTEE_2_UID: u32 = USER_ID_2 * AID_USER_OFFSET + APPLICATION_ID;
+    static GRANTEE_2_GID: u32 = GRANTEE_2_UID;
+
+    // Generate a key and grant it to multiple users with GET_INFO|USE permissions.
+    let mut grant_keys = unsafe {
+        run_as::run_as(GRANTOR_SU_CTX, Uid::from_raw(0), Gid::from_raw(0), || {
+            let keystore2 = get_keystore_service();
+            let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+            let alias = format!("ks_grant_test_key_2{}", getuid());
+            let access_vector = KeyPermission::GET_INFO.0 | KeyPermission::USE.0;
+
+            generate_ec_key_and_grant_to_users(
+                &keystore2,
+                &sec_level,
+                Some(alias),
+                vec![GRANTEE_1_UID.try_into().unwrap(), GRANTEE_2_UID.try_into().unwrap()],
+                access_vector,
+            )
+            .unwrap()
+        })
+    };
+
+    for (grantee_uid, grantee_gid) in
+        &[(GRANTEE_1_UID, GRANTEE_1_GID), (GRANTEE_2_UID, GRANTEE_2_GID)]
+    {
+        let grant_key_nspace = grant_keys.remove(0);
+        unsafe {
+            run_as::run_as(
+                GRANTEE_CTX,
+                Uid::from_raw(*grantee_uid),
+                Gid::from_raw(*grantee_gid),
+                move || {
+                    let keystore2 = get_keystore_service();
+                    let sec_level =
+                        keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+                    assert_eq!(
+                        Ok(()),
+                        key_generations::map_ks_error(load_grant_key_and_perform_sign_operation(
+                            &keystore2,
+                            &sec_level,
+                            grant_key_nspace
+                        ))
+                    );
+                },
+            )
+        };
+    }
+}
+
+/// Grant a key to multiple users with GET_INFO|DELETE permissions. In one of the grantee context
+/// use the key and delete it. Try to load the granted key in another grantee context. Test should
+/// fail to load the granted key with `KEY_NOT_FOUND` error response.
+#[test]
+fn keystore2_grant_key_to_multi_users_delete_fails_with_key_not_found_error() {
+    static GRANTOR_SU_CTX: &str = "u:r:su:s0";
+    static GRANTEE_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+
+    const USER_ID_1: u32 = 99;
+    const APPLICATION_ID: u32 = 10001;
+    static GRANTEE_1_UID: u32 = USER_ID_1 * AID_USER_OFFSET + APPLICATION_ID;
+    static GRANTEE_1_GID: u32 = GRANTEE_1_UID;
+
+    const USER_ID_2: u32 = 98;
+    static GRANTEE_2_UID: u32 = USER_ID_2 * AID_USER_OFFSET + APPLICATION_ID;
+    static GRANTEE_2_GID: u32 = GRANTEE_2_UID;
+
+    // Generate a key and grant it to multiple users with GET_INFO permission.
+    let mut grant_keys = unsafe {
+        run_as::run_as(GRANTOR_SU_CTX, Uid::from_raw(0), Gid::from_raw(0), || {
+            let keystore2 = get_keystore_service();
+            let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+            let alias = format!("ks_grant_test_key_2{}", getuid());
+            let access_vector =
+                KeyPermission::GET_INFO.0 | KeyPermission::USE.0 | KeyPermission::DELETE.0;
+
+            generate_ec_key_and_grant_to_users(
+                &keystore2,
+                &sec_level,
+                Some(alias),
+                vec![GRANTEE_1_UID.try_into().unwrap(), GRANTEE_2_UID.try_into().unwrap()],
+                access_vector,
+            )
+            .unwrap()
+        })
+    };
+
+    // Grantee #1 context
+    let grant_key1_nspace = grant_keys.remove(0);
+    unsafe {
+        run_as::run_as(
+            GRANTEE_CTX,
+            Uid::from_raw(GRANTEE_1_UID),
+            Gid::from_raw(GRANTEE_1_GID),
+            move || {
+                let keystore2 = get_keystore_service();
+                let sec_level =
+                    keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+                assert_eq!(
+                    Ok(()),
+                    key_generations::map_ks_error(load_grant_key_and_perform_sign_operation(
+                        &keystore2,
+                        &sec_level,
+                        grant_key1_nspace
+                    ))
+                );
+
+                // Delete the granted key.
+                keystore2
+                    .deleteKey(&KeyDescriptor {
+                        domain: Domain::GRANT,
+                        nspace: grant_key1_nspace,
+                        alias: None,
+                        blob: None,
+                    })
+                    .unwrap();
+            },
+        )
+    };
+
+    // Grantee #2 context
+    let grant_key2_nspace = grant_keys.remove(0);
+    unsafe {
+        run_as::run_as(
+            GRANTEE_CTX,
+            Uid::from_raw(GRANTEE_2_UID),
+            Gid::from_raw(GRANTEE_2_GID),
+            move || {
+                let keystore2 = get_keystore_service();
+
+                let result = key_generations::map_ks_error(keystore2.getKeyEntry(&KeyDescriptor {
+                    domain: Domain::GRANT,
+                    nspace: grant_key2_nspace,
+                    alias: None,
+                    blob: None,
+                }));
+                assert!(result.is_err());
+                assert_eq!(Error::Rc(ResponseCode::KEY_NOT_FOUND), result.unwrap_err());
+            },
+        )
+    };
+}
diff --git a/keystore2/tests/keystore2_client_key_agreement_tests.rs b/keystore2/tests/keystore2_client_key_agreement_tests.rs
new file mode 100644
index 0000000..6b2e3c2
--- /dev/null
+++ b/keystore2/tests/keystore2_client_key_agreement_tests.rs
@@ -0,0 +1,179 @@
+// Copyright 2022, 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 nix::unistd::getuid;
+
+use openssl::ec::{EcGroup, EcKey};
+use openssl::error::ErrorStack;
+use openssl::nid::Nid;
+use openssl::pkey::{PKey, PKeyRef, Private, Public};
+use openssl::pkey_ctx::PkeyCtx;
+use openssl::x509::X509;
+
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+    Digest::Digest, EcCurve::EcCurve, ErrorCode::ErrorCode, KeyPurpose::KeyPurpose,
+    SecurityLevel::SecurityLevel,
+};
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
+    KeyMetadata::KeyMetadata,
+};
+
+use keystore2_test_utils::{
+    authorizations, get_keystore_service, key_generations, key_generations::Error,
+};
+
+/// This macro is used to verify that the key agreement works for the given curve.
+macro_rules! test_ec_key_agree {
+    ( $test_name:ident, $ec_curve:expr ) => {
+        #[test]
+        fn $test_name() {
+            perform_ec_key_agreement($ec_curve);
+        }
+    };
+}
+
+// Get the KeyMint key's public part.
+fn get_keymint_public_key(keymint_key: &KeyMetadata) -> Result<PKey<Public>, ErrorStack> {
+    let cert_bytes = keymint_key.certificate.as_ref().unwrap();
+    let cert = X509::from_der(cert_bytes.as_ref()).unwrap();
+    cert.public_key()
+}
+
+// Perform local ECDH between the two keys and check the derived secrets are the same.
+fn check_agreement(
+    sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+    keymint_key: &KeyDescriptor,
+    keymint_pub_key: &PKey<Public>,
+    local_key: &PKeyRef<Private>,
+    local_pub_key: &[u8],
+) {
+    let authorizations = authorizations::AuthSetBuilder::new().purpose(KeyPurpose::AGREE_KEY);
+    let key_agree_op = sec_level.createOperation(keymint_key, &authorizations, false).unwrap();
+    assert!(key_agree_op.iOperation.is_some());
+
+    let op = key_agree_op.iOperation.unwrap();
+    let secret = op.finish(Some(local_pub_key), None).unwrap();
+    assert!(secret.is_some());
+
+    let mut ctx = PkeyCtx::new(local_key).unwrap();
+    ctx.derive_init().unwrap();
+    ctx.derive_set_peer(keymint_pub_key).unwrap();
+    let mut peer_secret = vec![];
+    ctx.derive_to_vec(&mut peer_secret).unwrap();
+
+    assert_eq!(secret.unwrap(), peer_secret);
+}
+
+fn ec_curve_to_openrssl_curve_name(ec_curve: &EcCurve) -> Nid {
+    match *ec_curve {
+        EcCurve::P_224 => Nid::SECP224R1,
+        EcCurve::P_256 => Nid::X9_62_PRIME256V1,
+        EcCurve::P_384 => Nid::SECP384R1,
+        EcCurve::P_521 => Nid::SECP521R1,
+        _ => Nid::UNDEF,
+    }
+}
+
+/// Generate two EC keys with given curve from KeyMint and OpeanSSL. Perform local ECDH between
+/// them and verify that the derived secrets are the same.
+fn perform_ec_key_agreement(ec_curve: EcCurve) {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let openssl_ec_curve = ec_curve_to_openrssl_curve_name(&ec_curve);
+
+    let alias = format!("ks_ec_test_key_agree_{}", getuid());
+    let keymint_key = key_generations::generate_ec_agree_key(
+        &sec_level,
+        ec_curve,
+        Digest::SHA_2_256,
+        Domain::APP,
+        -1,
+        Some(alias),
+    )
+    .unwrap();
+
+    let keymint_pub_key = get_keymint_public_key(&keymint_key).unwrap();
+
+    let group = EcGroup::from_curve_name(openssl_ec_curve).unwrap();
+    let ec_key = EcKey::generate(&group).unwrap();
+    let local_key = PKey::from_ec_key(ec_key).unwrap();
+    let local_pub_key = local_key.public_key_to_der().unwrap();
+
+    check_agreement(&sec_level, &keymint_key.key, &keymint_pub_key, &local_key, &local_pub_key);
+}
+
+test_ec_key_agree!(test_ec_p224_key_agreement, EcCurve::P_224);
+test_ec_key_agree!(test_ec_p256_key_agreement, EcCurve::P_256);
+test_ec_key_agree!(test_ec_p384_key_agreement, EcCurve::P_384);
+test_ec_key_agree!(test_ec_p521_key_agreement, EcCurve::P_521);
+
+/// Generate two EC keys with curve `CURVE_25519` from KeyMint and OpeanSSL.
+/// Perform local ECDH between them and verify that the derived secrets are the same.
+#[test]
+fn keystore2_ec_25519_agree_key_success() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let alias = format!("ks_ec_25519_test_key_agree_{}", getuid());
+    let keymint_key = key_generations::generate_ec_agree_key(
+        &sec_level,
+        EcCurve::CURVE_25519,
+        Digest::NONE,
+        Domain::APP,
+        -1,
+        Some(alias),
+    )
+    .unwrap();
+
+    let keymint_pub_key = get_keymint_public_key(&keymint_key).unwrap();
+
+    let local_key = PKey::generate_x25519().unwrap();
+    let local_pub_key = local_key.public_key_to_der().unwrap();
+
+    check_agreement(&sec_level, &keymint_key.key, &keymint_pub_key, &local_key, &local_pub_key);
+}
+
+/// Generate two EC keys with different curves and try to perform local ECDH. Since keys are using
+/// different curves operation should fail with `ErrorCode:INVALID_ARGUMENT`.
+#[test]
+fn keystore2_ec_agree_key_with_different_curves_fail() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let alias = format!("ks_test_key_agree_fail{}", getuid());
+    let keymint_key = key_generations::generate_ec_agree_key(
+        &sec_level,
+        EcCurve::P_256,
+        Digest::SHA_2_256,
+        Domain::APP,
+        -1,
+        Some(alias),
+    )
+    .unwrap();
+
+    let local_key = PKey::generate_x25519().unwrap();
+    let local_pub_key = local_key.public_key_to_der().unwrap();
+
+    // If the keys are using different curves KeyMint should fail with
+    // ErrorCode:INVALID_ARGUMENT.
+    let authorizations = authorizations::AuthSetBuilder::new().purpose(KeyPurpose::AGREE_KEY);
+    let key_agree_op = sec_level.createOperation(&keymint_key.key, &authorizations, false).unwrap();
+    assert!(key_agree_op.iOperation.is_some());
+
+    let op = key_agree_op.iOperation.unwrap();
+    let result = key_generations::map_ks_error(op.finish(Some(&local_pub_key), None));
+    assert!(result.is_err());
+    assert_eq!(Error::Km(ErrorCode::INVALID_ARGUMENT), result.unwrap_err());
+}
diff --git a/keystore2/tests/keystore2_client_list_entries_tests.rs b/keystore2/tests/keystore2_client_list_entries_tests.rs
index 62e3dd0..3b656c3 100644
--- a/keystore2/tests/keystore2_client_list_entries_tests.rs
+++ b/keystore2/tests/keystore2_client_list_entries_tests.rs
@@ -14,6 +14,8 @@
 
 use nix::unistd::{getuid, Gid, Uid};
 use rustutils::users::AID_USER_OFFSET;
+use std::collections::HashSet;
+use std::fmt::Write;
 
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel::SecurityLevel;
 use android_system_keystore2::aidl::android::system::keystore2::{
@@ -21,6 +23,7 @@
     KeyPermission::KeyPermission, ResponseCode::ResponseCode,
 };
 
+use crate::keystore2_client_test_utils::delete_app_key;
 use keystore2_test_utils::{get_keystore_service, key_generations, key_generations::Error, run_as};
 
 /// Try to find a key with given key parameters using `listEntries` API.
@@ -183,3 +186,68 @@
     assert!(result.is_err());
     assert_eq!(Error::Rc(ResponseCode::INVALID_ARGUMENT), result.unwrap_err());
 }
+
+/// Import large number of Keystore entries with long aliases and try to list aliases
+/// of all the entries in the keystore.
+#[test]
+fn keystore2_list_entries_with_long_aliases_success() {
+    static CLIENT_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+
+    const USER_ID: u32 = 92;
+    const APPLICATION_ID: u32 = 10002;
+    static CLIENT_UID: u32 = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
+    static CLIENT_GID: u32 = CLIENT_UID;
+
+    unsafe {
+        run_as::run_as(CLIENT_CTX, Uid::from_raw(CLIENT_UID), Gid::from_raw(CLIENT_GID), || {
+            let keystore2 = get_keystore_service();
+            let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+            // Make sure there are no keystore entries exist before adding new entries.
+            let key_descriptors = keystore2.listEntries(Domain::APP, -1).unwrap();
+            if !key_descriptors.is_empty() {
+                key_descriptors.into_iter().map(|key| key.alias.unwrap()).for_each(|alias| {
+                    delete_app_key(&keystore2, &alias).unwrap();
+                });
+            }
+
+            let mut imported_key_aliases = HashSet::new();
+
+            // Import 100 keys with aliases of length 6000.
+            for count in 1..101 {
+                let mut alias = String::new();
+                write!(alias, "{}_{}", "X".repeat(6000), count).unwrap();
+                imported_key_aliases.insert(alias.clone());
+
+                let result =
+                    key_generations::import_aes_key(&sec_level, Domain::APP, -1, Some(alias));
+                assert!(result.is_ok());
+            }
+
+            // b/222287335 Limiting Keystore `listEntries` API to return subset of the Keystore
+            // entries to avoid running out of binder buffer space.
+            // To verify that all the imported key aliases are present in Keystore,
+            //  - get the list of entries from Keystore
+            //  - check whether the retrieved key entries list is a subset of imported key aliases
+            //  - delete this subset of keystore entries from Keystore as well as from imported
+            //    list of key aliases
+            //  - continue above steps till it cleanup all the imported keystore entries.
+            while !imported_key_aliases.is_empty() {
+                let key_descriptors = keystore2.listEntries(Domain::APP, -1).unwrap();
+
+                // Check retrieved key entries list is a subset of imported keys list.
+                assert!(key_descriptors
+                    .iter()
+                    .all(|key| imported_key_aliases.contains(key.alias.as_ref().unwrap())));
+
+                // Delete the listed key entries from Keystore as well as from imported keys list.
+                key_descriptors.into_iter().map(|key| key.alias.unwrap()).for_each(|alias| {
+                    delete_app_key(&keystore2, &alias).unwrap();
+                    assert!(imported_key_aliases.remove(&alias));
+                });
+            }
+
+            assert!(imported_key_aliases.is_empty());
+        })
+    };
+}
diff --git a/keystore2/tests/keystore2_client_test_utils.rs b/keystore2/tests/keystore2_client_test_utils.rs
index 56995e4..58e6b7d 100644
--- a/keystore2/tests/keystore2_client_test_utils.rs
+++ b/keystore2/tests/keystore2_client_test_utils.rs
@@ -90,6 +90,29 @@
         .expect("Could not check for declared keymint interface")
 }
 
+/// Generate EC key and grant it to the list of users with given access vector.
+/// Returns the list of granted keys `nspace` values in the order of given grantee uids.
+pub fn generate_ec_key_and_grant_to_users(
+    keystore2: &binder::Strong<dyn IKeystoreService>,
+    sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
+    alias: Option<String>,
+    grantee_uids: Vec<i32>,
+    access_vector: i32,
+) -> Result<Vec<i64>, binder::Status> {
+    let key_metadata =
+        key_generations::generate_ec_p256_signing_key(sec_level, Domain::APP, -1, alias, None)?;
+
+    let mut granted_keys = Vec::new();
+
+    for uid in grantee_uids {
+        let granted_key = keystore2.grant(&key_metadata.key, uid, access_vector)?;
+        assert_eq!(granted_key.domain, Domain::GRANT);
+        granted_keys.push(granted_key.nspace);
+    }
+
+    Ok(granted_keys)
+}
+
 /// Generate a EC_P256 key using given domain, namespace and alias.
 /// Create an operation using the generated key and perform sample signing operation.
 pub fn create_signing_operation(
diff --git a/keystore2/tests/keystore2_client_tests.rs b/keystore2/tests/keystore2_client_tests.rs
index d705aa4..07a298a 100644
--- a/keystore2/tests/keystore2_client_tests.rs
+++ b/keystore2/tests/keystore2_client_tests.rs
@@ -16,12 +16,15 @@
 pub mod keystore2_client_3des_key_tests;
 pub mod keystore2_client_aes_key_tests;
 pub mod keystore2_client_attest_key_tests;
+pub mod keystore2_client_delete_key_tests;
 pub mod keystore2_client_ec_key_tests;
 pub mod keystore2_client_grant_key_tests;
 pub mod keystore2_client_hmac_key_tests;
 pub mod keystore2_client_import_keys_tests;
+pub mod keystore2_client_key_agreement_tests;
 pub mod keystore2_client_key_id_domain_tests;
 pub mod keystore2_client_list_entries_tests;
 pub mod keystore2_client_operation_tests;
 pub mod keystore2_client_rsa_key_tests;
 pub mod keystore2_client_test_utils;
+pub mod keystore2_client_update_subcomponent_tests;
diff --git a/keystore2/tests/keystore2_client_update_subcomponent_tests.rs b/keystore2/tests/keystore2_client_update_subcomponent_tests.rs
new file mode 100644
index 0000000..c987f22
--- /dev/null
+++ b/keystore2/tests/keystore2_client_update_subcomponent_tests.rs
@@ -0,0 +1,230 @@
+// Copyright 2022, 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 nix::unistd::{getuid, Gid, Uid};
+use rustutils::users::AID_USER_OFFSET;
+
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+    ErrorCode::ErrorCode, SecurityLevel::SecurityLevel,
+};
+use android_system_keystore2::aidl::android::system::keystore2::{
+    Domain::Domain, KeyDescriptor::KeyDescriptor, KeyPermission::KeyPermission,
+    ResponseCode::ResponseCode,
+};
+
+use keystore2_test_utils::{get_keystore_service, key_generations, key_generations::Error, run_as};
+
+/// Generate a key and update its public certificate and certificate chain. Test should be able to
+/// load the key and able to verify whether its certificate and cert-chain are updated successfully.
+#[test]
+fn keystore2_update_subcomponent_success() {
+    let alias = "update_subcomponent_success_key";
+
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    let key_metadata = key_generations::generate_ec_p256_signing_key(
+        &sec_level,
+        Domain::SELINUX,
+        key_generations::SELINUX_SHELL_NAMESPACE,
+        Some(alias.to_string()),
+        None,
+    )
+    .unwrap();
+
+    let other_cert: [u8; 32] = [123; 32];
+    let other_cert_chain: [u8; 32] = [12; 32];
+
+    keystore2
+        .updateSubcomponent(&key_metadata.key, Some(&other_cert), Some(&other_cert_chain))
+        .expect("updateSubcomponent should have succeeded.");
+
+    let key_entry_response = keystore2.getKeyEntry(&key_metadata.key).unwrap();
+    assert_eq!(Some(other_cert.to_vec()), key_entry_response.metadata.certificate);
+    assert_eq!(Some(other_cert_chain.to_vec()), key_entry_response.metadata.certificateChain);
+}
+
+/// Try to update non-existing asymmetric key public cert and certificate chain. Test should fail
+/// to update with error response code `KEY_NOT_FOUND`.
+#[test]
+fn keystore2_update_subcomponent_fail() {
+    let alias = "update_component_failure_key";
+
+    let keystore2 = get_keystore_service();
+
+    let other_cert: [u8; 32] = [123; 32];
+    let other_cert_chain: [u8; 32] = [12; 32];
+
+    let result = key_generations::map_ks_error(keystore2.updateSubcomponent(
+        &KeyDescriptor {
+            domain: Domain::SELINUX,
+            nspace: key_generations::SELINUX_SHELL_NAMESPACE,
+            alias: Some(alias.to_string()),
+            blob: None,
+        },
+        Some(&other_cert),
+        Some(&other_cert_chain),
+    ));
+    assert!(result.is_err());
+    assert_eq!(Error::Rc(ResponseCode::KEY_NOT_FOUND), result.unwrap_err());
+}
+
+/// Generate a key and grant it to two users. For one user grant it with only `GET_INFO` access
+/// permission and for another user grant it with GET_INFO and UPDATE access permissions. In a
+/// grantee context where key is granted with only GET_INFO access permission, try to update
+/// key's public certificate and certificate chain. Test should fail to update with error response
+/// code `PERMISSION_DENIED` because grantee does not possess UPDATE access permission for the
+/// specified key. In a grantee context where key is granted with UPDATE and GET_INFO access
+/// permissions, test should be able to update public certificate and cert-chain successfully.
+#[test]
+fn keystore2_update_subcomponent_fails_permission_denied() {
+    static GRANTOR_SU_CTX: &str = "u:r:su:s0";
+    static GRANTEE_CTX: &str = "u:r:untrusted_app:s0:c91,c256,c10,c20";
+
+    const USER_ID_1: u32 = 99;
+    const APPLICATION_ID: u32 = 10001;
+    static GRANTEE_1_UID: u32 = USER_ID_1 * AID_USER_OFFSET + APPLICATION_ID;
+    static GRANTEE_1_GID: u32 = GRANTEE_1_UID;
+
+    const USER_ID_2: u32 = 98;
+    static GRANTEE_2_UID: u32 = USER_ID_2 * AID_USER_OFFSET + APPLICATION_ID;
+    static GRANTEE_2_GID: u32 = GRANTEE_2_UID;
+
+    // Generate a key and grant it to multiple users with different access permissions.
+    let mut granted_keys = unsafe {
+        run_as::run_as(GRANTOR_SU_CTX, Uid::from_raw(0), Gid::from_raw(0), || {
+            let keystore2 = get_keystore_service();
+            let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+            let alias = format!("ks_update_subcompo_test_1_{}", getuid());
+            let mut granted_keys = Vec::new();
+
+            let key_metadata = key_generations::generate_ec_p256_signing_key(
+                &sec_level,
+                Domain::APP,
+                -1,
+                Some(alias),
+                None,
+            )
+            .unwrap();
+
+            // Grant a key without update permission.
+            let access_vector = KeyPermission::GET_INFO.0;
+            let granted_key = keystore2
+                .grant(&key_metadata.key, GRANTEE_1_UID.try_into().unwrap(), access_vector)
+                .unwrap();
+            assert_eq!(granted_key.domain, Domain::GRANT);
+            granted_keys.push(granted_key.nspace);
+
+            // Grant a key with update permission.
+            let access_vector = KeyPermission::GET_INFO.0 | KeyPermission::UPDATE.0;
+            let granted_key = keystore2
+                .grant(&key_metadata.key, GRANTEE_2_UID.try_into().unwrap(), access_vector)
+                .unwrap();
+            assert_eq!(granted_key.domain, Domain::GRANT);
+            granted_keys.push(granted_key.nspace);
+
+            granted_keys
+        })
+    };
+
+    // Grantee context, try to update the key public certs, permission denied error is expected.
+    let granted_key1_nspace = granted_keys.remove(0);
+    unsafe {
+        run_as::run_as(
+            GRANTEE_CTX,
+            Uid::from_raw(GRANTEE_1_UID),
+            Gid::from_raw(GRANTEE_1_GID),
+            move || {
+                let keystore2 = get_keystore_service();
+
+                let other_cert: [u8; 32] = [123; 32];
+                let other_cert_chain: [u8; 32] = [12; 32];
+
+                let result = key_generations::map_ks_error(keystore2.updateSubcomponent(
+                    &KeyDescriptor {
+                        domain: Domain::GRANT,
+                        nspace: granted_key1_nspace,
+                        alias: None,
+                        blob: None,
+                    },
+                    Some(&other_cert),
+                    Some(&other_cert_chain),
+                ));
+                assert!(result.is_err());
+                assert_eq!(Error::Rc(ResponseCode::PERMISSION_DENIED), result.unwrap_err());
+            },
+        )
+    };
+
+    // Grantee context, update granted key public certs. Update should happen successfully.
+    let granted_key2_nspace = granted_keys.remove(0);
+    unsafe {
+        run_as::run_as(
+            GRANTEE_CTX,
+            Uid::from_raw(GRANTEE_2_UID),
+            Gid::from_raw(GRANTEE_2_GID),
+            move || {
+                let keystore2 = get_keystore_service();
+
+                let other_cert: [u8; 32] = [124; 32];
+                let other_cert_chain: [u8; 32] = [13; 32];
+
+                keystore2
+                    .updateSubcomponent(
+                        &KeyDescriptor {
+                            domain: Domain::GRANT,
+                            nspace: granted_key2_nspace,
+                            alias: None,
+                            blob: None,
+                        },
+                        Some(&other_cert),
+                        Some(&other_cert_chain),
+                    )
+                    .expect("updateSubcomponent should have succeeded.");
+
+                let key_entry_response = keystore2
+                    .getKeyEntry(&KeyDescriptor {
+                        domain: Domain::GRANT,
+                        nspace: granted_key2_nspace,
+                        alias: None,
+                        blob: None,
+                    })
+                    .unwrap();
+                assert_eq!(Some(other_cert.to_vec()), key_entry_response.metadata.certificate);
+                assert_eq!(
+                    Some(other_cert_chain.to_vec()),
+                    key_entry_response.metadata.certificateChain
+                );
+            },
+        )
+    };
+}
+
+#[test]
+fn keystore2_get_security_level_success() {
+    let keystore2 = get_keystore_service();
+    assert!(
+        keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).is_ok(),
+        "getSecurityLevel with SecurityLevel::TRUSTED_ENVIRONMENT should have succeeded."
+    );
+}
+
+#[test]
+fn keystore2_get_security_level_failure() {
+    let keystore2 = get_keystore_service();
+    let result = key_generations::map_ks_error(keystore2.getSecurityLevel(SecurityLevel::SOFTWARE));
+
+    assert!(result.is_err());
+    assert_eq!(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE), result.unwrap_err());
+}
diff --git a/prng_seeder/Android.bp b/prng_seeder/Android.bp
index 292535a..763aaa0 100644
--- a/prng_seeder/Android.bp
+++ b/prng_seeder/Android.bp
@@ -63,3 +63,20 @@
     installable: false,
     prefer_rlib: true,
 }
+
+rust_test {
+    name: "prng_seeder.test",
+    edition: "2021",
+    srcs: ["src/main.rs"],
+    rustlibs: [
+        "libanyhow",
+        "libbssl_ffi",
+        "libclap",
+        "libcutils_socket_bindgen",
+        "liblogger",
+        "liblog_rust",
+        "libnix",
+        "libtokio",
+    ],
+    test_suites: ["general-tests"],
+}
diff --git a/prng_seeder/src/main.rs b/prng_seeder/src/main.rs
index 3f698f6..924481a 100644
--- a/prng_seeder/src/main.rs
+++ b/prng_seeder/src/main.rs
@@ -37,7 +37,7 @@
 
 use crate::conditioner::ConditionerBuilder;
 
-#[derive(Debug, clap::Parser)]
+#[derive(Debug, Parser)]
 struct Cli {
     #[clap(long, default_value = "/dev/hw_random")]
     source: PathBuf,
@@ -135,3 +135,14 @@
     println!("prng_seeder: launch terminated: {:?}", e);
     std::process::exit(-1);
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use clap::CommandFactory;
+
+    #[test]
+    fn verify_cli() {
+        Cli::command().debug_assert();
+    }
+}