Merge "Static link libcrypto into rkp_factory_extraction_tool" into main
diff --git a/diced/TEST_MAPPING b/diced/TEST_MAPPING
index caf847f..2f6be00 100644
--- a/diced/TEST_MAPPING
+++ b/diced/TEST_MAPPING
@@ -10,7 +10,7 @@
       "name": "libopen_dice_cbor_bindgen_test"
     },
     {
-      "name": "libopen_dice_bcc_bindgen_test"
+      "name": "libopen_dice_android_bindgen_test"
     },
     {
       "name": "libdiced_sample_inputs.integration_test"
diff --git a/diced/open_dice/Android.bp b/diced/open_dice/Android.bp
index c59419b..b87be7f 100644
--- a/diced/open_dice/Android.bp
+++ b/diced/open_dice/Android.bp
@@ -13,7 +13,7 @@
     name: "libdiced_open_dice_nostd",
     defaults: ["libdiced_open_dice_defaults"],
     rustlibs: [
-        "libopen_dice_bcc_bindgen_nostd",
+        "libopen_dice_android_bindgen_nostd",
         "libopen_dice_cbor_bindgen_nostd",
         "libzeroize_nostd",
     ],
@@ -31,7 +31,7 @@
     defaults: ["libdiced_open_dice_defaults"],
     vendor_available: true,
     rustlibs: [
-        "libopen_dice_bcc_bindgen",
+        "libopen_dice_android_bindgen",
         "libopen_dice_cbor_bindgen",
         "libzeroize",
     ],
@@ -45,7 +45,7 @@
         "libopen_dice_cbor",
     ],
     whole_static_libs: [
-        "libopen_dice_bcc",
+        "libopen_dice_android",
     ],
     visibility: [
         "//system/security/diced:__subpackages__",
@@ -172,22 +172,20 @@
 }
 
 rust_defaults {
-    name: "libopen_dice_bcc_bindgen.rust_defaults",
-    wrapper_src: "bindgen/android/bcc.h",
-    crate_name: "open_dice_bcc_bindgen",
+    name: "libopen_dice_android_bindgen.rust_defaults",
+    wrapper_src: "bindgen/android.h",
+    crate_name: "open_dice_android_bindgen",
     source_stem: "bindings",
     bindgen_flags: [
         // 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",
+        "--allowlist-function=DiceAndroidFormatConfigDescriptor",
+        "--allowlist-function=DiceAndroidMainFlow",
+        "--allowlist-function=DiceAndroidHandoverMainFlow",
+        "--allowlist-function=DiceAndroidHandoverParse",
 
         // 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",
+        "--allowlist-var=DICE_ANDROID_CONFIG_.*",
 
         // Prevent DiceInputValues from being generated a second time and
         // import it instead from open_dice_cbor_bindgen.
@@ -206,27 +204,27 @@
 }
 
 rust_bindgen {
-    name: "libopen_dice_bcc_bindgen",
+    name: "libopen_dice_android_bindgen",
     defaults: [
         "libopen_dice.rust_defaults",
-        "libopen_dice_bcc_bindgen.rust_defaults",
+        "libopen_dice_android_bindgen.rust_defaults",
     ],
     rustlibs: [
         "libopen_dice_cbor_bindgen",
     ],
-    whole_static_libs: ["libopen_dice_bcc"],
+    whole_static_libs: ["libopen_dice_android"],
 }
 
 rust_bindgen {
-    name: "libopen_dice_bcc_bindgen_nostd",
+    name: "libopen_dice_android_bindgen_nostd",
     defaults: [
-        "libopen_dice_bcc_bindgen.rust_defaults",
+        "libopen_dice_android_bindgen.rust_defaults",
         "libopen_dice_bindgen_nostd.rust_defaults",
     ],
     rustlibs: [
         "libopen_dice_cbor_bindgen_nostd",
     ],
-    whole_static_libs: ["libopen_dice_bcc_baremetal"],
+    whole_static_libs: ["libopen_dice_android_baremetal"],
 }
 
 rust_test {
@@ -242,11 +240,11 @@
 }
 
 rust_test {
-    name: "libopen_dice_bcc_bindgen_test",
+    name: "libopen_dice_android_bindgen_test",
     srcs: [
-        ":libopen_dice_bcc_bindgen",
+        ":libopen_dice_android_bindgen",
     ],
-    crate_name: "open_dice_bcc_bindgen_test",
+    crate_name: "open_dice_android_bindgen_test",
     rustlibs: [
         "libopen_dice_cbor_bindgen",
     ],
diff --git a/diced/open_dice/bindgen/android/bcc.h b/diced/open_dice/bindgen/android.h
similarity index 94%
rename from diced/open_dice/bindgen/android/bcc.h
rename to diced/open_dice/bindgen/android.h
index 4dfc862..18f6476 100644
--- a/diced/open_dice/bindgen/android/bcc.h
+++ b/diced/open_dice/bindgen/android.h
@@ -14,4 +14,4 @@
 
 #pragma once
 
-#include <dice/android/bcc.h>
+#include <dice/android.h>
diff --git a/diced/open_dice/src/bcc.rs b/diced/open_dice/src/bcc.rs
index ca2136f..199e1a9 100644
--- a/diced/open_dice/src/bcc.rs
+++ b/diced/open_dice/src/bcc.rs
@@ -12,134 +12,154 @@
 // 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
+//! This module mirrors the content in open-dice/include/dice/android.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 open_dice_android_bindgen::{
+    DiceAndroidConfigValues, DiceAndroidFormatConfigDescriptor, DiceAndroidHandoverMainFlow,
+    DiceAndroidHandoverParse, DiceAndroidMainFlow, DICE_ANDROID_CONFIG_COMPONENT_NAME,
+    DICE_ANDROID_CONFIG_COMPONENT_VERSION, DICE_ANDROID_CONFIG_RESETTABLE,
+    DICE_ANDROID_CONFIG_SECURITY_VERSION,
 };
 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;
-    }
+/// Contains the input values used to construct the Android Profile for DICE
+/// configuration descriptor.
+#[derive(Default, Debug)]
+pub struct DiceConfigValues<'a> {
+    /// Name of the component.
+    pub component_name: Option<&'a CStr>,
+    /// Version of the component.
+    pub component_version: Option<u64>,
+    /// Whether the key changes on factory reset.
+    pub resettable: bool,
+    /// Monotonically increasing version of the component.
+    pub security_version: Option<u64>,
+}
 
-    let values = BccConfigValues {
-        inputs,
-        component_name: name.map_or(ptr::null(), |p| p.as_ptr()),
-        component_version: version.unwrap_or(0),
-    };
+/// Formats a configuration descriptor following the Android Profile for DICE specification.
+/// See https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/android.md.
+pub fn bcc_format_config_descriptor(values: &DiceConfigValues, buffer: &mut [u8]) -> Result<usize> {
+    let mut configs = 0;
+
+    let component_name = values.component_name.map_or(ptr::null(), |name| {
+        configs |= DICE_ANDROID_CONFIG_COMPONENT_NAME;
+        name.as_ptr()
+    });
+    let component_version = values.component_version.map_or(0, |version| {
+        configs |= DICE_ANDROID_CONFIG_COMPONENT_VERSION;
+        version
+    });
+    if values.resettable {
+        configs |= DICE_ANDROID_CONFIG_RESETTABLE;
+    }
+    let security_version = values.security_version.map_or(0, |version| {
+        configs |= DICE_ANDROID_CONFIG_SECURITY_VERSION;
+        version
+    });
+
+    let values =
+        DiceAndroidConfigValues { configs, component_name, component_version, security_version };
 
     let mut buffer_size = 0;
     check_result(
         // SAFETY: The function writes to the buffer, within the given bounds, and only reads the
         // input values. It writes its result to buffer_size.
         unsafe {
-            BccFormatConfigDescriptor(&values, buffer.len(), buffer.as_mut_ptr(), &mut buffer_size)
+            DiceAndroidFormatConfigDescriptor(
+                &values,
+                buffer.len(),
+                buffer.as_mut_ptr(),
+                &mut buffer_size,
+            )
         },
         buffer_size,
     )?;
     Ok(buffer_size)
 }
 
-/// Executes the main BCC flow.
+/// Executes the main Android DICE 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.
+/// Given a full set of input values along with the current DICE chain and CDI values,
+/// computes the next CDI values and matching updated DICE chain.
 pub fn bcc_main_flow(
     current_cdi_attest: &Cdi,
     current_cdi_seal: &Cdi,
-    current_bcc: &[u8],
+    current_chain: &[u8],
     input_values: &InputValues,
     next_cdi_values: &mut CdiValues,
-    next_bcc: &mut [u8],
+    next_chain: &mut [u8],
 ) -> Result<usize> {
-    let mut next_bcc_size = 0;
+    let mut next_chain_size = 0;
     check_result(
-        // 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.
+        // SAFETY: `DiceAndroidMainFlow` only reads the `current_chain` and CDI values and writes
+        // to `next_chain` 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.
         unsafe {
-            BccMainFlow(
+            DiceAndroidMainFlow(
                 ptr::null_mut(), // context
                 current_cdi_attest.as_ptr(),
                 current_cdi_seal.as_ptr(),
-                current_bcc.as_ptr(),
-                current_bcc.len(),
+                current_chain.as_ptr(),
+                current_chain.len(),
                 input_values.as_ptr(),
-                next_bcc.len(),
-                next_bcc.as_mut_ptr(),
-                &mut next_bcc_size,
+                next_chain.len(),
+                next_chain.as_mut_ptr(),
+                &mut next_chain_size,
                 next_cdi_values.cdi_attest.as_mut_ptr(),
                 next_cdi_values.cdi_seal.as_mut_ptr(),
             )
         },
-        next_bcc_size,
+        next_chain_size,
     )?;
-    Ok(next_bcc_size)
+    Ok(next_chain_size)
 }
 
-/// Executes the main BCC handover flow.
+/// Executes the main Android DICE 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
+/// A handover combines the DICE chain and CDIs in a single CBOR object.
+/// This function takes the current boot stage's handover bundle and produces a
 /// bundle for the next stage.
 pub fn bcc_handover_main_flow(
-    current_bcc_handover: &[u8],
+    current_handover: &[u8],
     input_values: &InputValues,
-    next_bcc_handover: &mut [u8],
+    next_handover: &mut [u8],
 ) -> Result<usize> {
-    let mut next_bcc_handover_size = 0;
+    let mut next_handover_size = 0;
     check_result(
-        // SAFETY: The function only reads `current_bcc_handover` and writes to `next_bcc_handover`
+        // SAFETY: The function only reads `current_handover` and writes to `next_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.
         unsafe {
-            BccHandoverMainFlow(
+            DiceAndroidHandoverMainFlow(
                 ptr::null_mut(), // context
-                current_bcc_handover.as_ptr(),
-                current_bcc_handover.len(),
+                current_handover.as_ptr(),
+                current_handover.len(),
                 input_values.as_ptr(),
-                next_bcc_handover.len(),
-                next_bcc_handover.as_mut_ptr(),
-                &mut next_bcc_handover_size,
+                next_handover.len(),
+                next_handover.as_mut_ptr(),
+                &mut next_handover_size,
             )
         },
-        next_bcc_handover_size,
+        next_handover_size,
     )?;
 
-    Ok(next_bcc_handover_size)
+    Ok(next_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.
+/// An Android DICE handover object combines the DICE chain and CDIs in a single CBOR object.
+/// This struct is used as return of the function `android_dice_handover_parse`, its lifetime is
+/// tied to the lifetime of the raw 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.
+    /// DICE chain.
     bcc: Option<&'a [u8]>,
 }
 
@@ -157,32 +177,31 @@
     }
 }
 
-/// 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> {
+/// This function parses the `handover` to extracts the DICE chain and CDIs.
+/// The lifetime of the returned `DiceAndroidHandover` is tied to the given `handover` slice.
+pub fn bcc_handover_parse(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;
+    let mut chain: *const u8 = ptr::null();
+    let mut chain_size = 0;
     check_result(
-        // 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.
+        // SAFETY: The `handover` is only read and never stored and the returned pointers should
+        // all point within the address range of the `handover` or be NULL.
         unsafe {
-            BccHandoverParse(
-                bcc_handover.as_ptr(),
-                bcc_handover.len(),
+            DiceAndroidHandoverParse(
+                handover.as_ptr(),
+                handover.len(),
                 &mut cdi_attest,
                 &mut cdi_seal,
-                &mut bcc,
-                &mut bcc_size,
+                &mut chain,
+                &mut chain_size,
             )
         },
-        bcc_size,
+        chain_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();
+    let cdi_attest = sub_slice(handover, cdi_attest, CDI_SIZE)?;
+    let cdi_seal = sub_slice(handover, cdi_seal, CDI_SIZE)?;
+    let bcc = sub_slice(handover, chain, chain_size).ok();
     Ok(BccHandover {
         cdi_attest: cdi_attest.try_into().map_err(|_| DiceError::PlatformError)?,
         cdi_seal: cdi_seal.try_into().map_err(|_| DiceError::PlatformError)?,
diff --git a/diced/open_dice/src/lib.rs b/diced/open_dice/src/lib.rs
index 4a85a1e..6d082b8 100644
--- a/diced/open_dice/src/lib.rs
+++ b/diced/open_dice/src/lib.rs
@@ -29,7 +29,7 @@
 
 pub use bcc::{
     bcc_format_config_descriptor, bcc_handover_main_flow, bcc_handover_parse, bcc_main_flow,
-    BccHandover,
+    BccHandover, DiceConfigValues,
 };
 pub use dice::{
     derive_cdi_certificate_id, derive_cdi_private_key_seed, dice_main_flow, Cdi, CdiValues, Config,
diff --git a/diced/open_dice/src/retry.rs b/diced/open_dice/src/retry.rs
index 3db4781..84ca5f5 100644
--- a/diced/open_dice/src/retry.rs
+++ b/diced/open_dice/src/retry.rs
@@ -17,13 +17,12 @@
 //! 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::bcc::{bcc_format_config_descriptor, bcc_main_flow, DiceConfigValues};
 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.
@@ -69,14 +68,8 @@
 }
 
 /// 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_measured_buffer(|buffer| {
-        bcc_format_config_descriptor(name, version, resettable, buffer)
-    })
+pub fn retry_bcc_format_config_descriptor(values: &DiceConfigValues) -> Result<Vec<u8>> {
+    retry_with_measured_buffer(|buffer| bcc_format_config_descriptor(values, buffer))
 }
 
 /// Executes the main BCC flow.
diff --git a/diced/sample_inputs/src/sample_inputs.rs b/diced/sample_inputs/src/sample_inputs.rs
index c665eb3..6ad15cd 100644
--- a/diced/sample_inputs/src/sample_inputs.rs
+++ b/diced/sample_inputs/src/sample_inputs.rs
@@ -20,8 +20,8 @@
 use coset::{iana, Algorithm, AsCborValue, CoseKey, KeyOperation, KeyType, Label};
 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,
+    retry_bcc_main_flow, retry_dice_main_flow, Config, DiceArtifacts, DiceConfigValues, DiceMode,
+    InputValues, OwnedDiceArtifacts, CDI_SIZE, HASH_SIZE, HIDDEN_SIZE,
 };
 use std::ffi::CStr;
 
@@ -106,11 +106,13 @@
     let ed25519_public_key_value = ed25519_public_key_to_cbor_value(&public_key)?;
 
     // Gets the ABL certificate to as the root certificate of 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 config_values = DiceConfigValues {
+        component_name: Some(CStr::from_bytes_with_nul(b"ABL\0").unwrap()),
+        component_version: Some(1),
+        resettable: true,
+        ..Default::default()
+    };
+    let config_descriptor = retry_bcc_format_config_descriptor(&config_values)?;
     let input_values = InputValues::new(
         CODE_HASH_ABL,
         Config::Descriptor(config_descriptor.as_slice()),
@@ -128,11 +130,13 @@
     ser::into_writer(&bcc_value, &mut bcc)?;
 
     // 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 config_values = DiceConfigValues {
+        component_name: Some(CStr::from_bytes_with_nul(b"AVB\0").unwrap()),
+        component_version: Some(1),
+        resettable: true,
+        ..Default::default()
+    };
+    let config_descriptor = retry_bcc_format_config_descriptor(&config_values)?;
     let input_values = InputValues::new(
         CODE_HASH_AVB,
         Config::Descriptor(config_descriptor.as_slice()),
@@ -145,11 +149,13 @@
             .context("In make_sample_bcc_and_cdis: Trying to run first bcc main flow.")?;
 
     // Appends Android certificate to DICE chain.
-    let config_descriptor = retry_bcc_format_config_descriptor(
-        Some(CStr::from_bytes_with_nul(b"Android\0").unwrap()),
-        Some(12), // version
-        true,
-    )?;
+    let config_values = DiceConfigValues {
+        component_name: Some(CStr::from_bytes_with_nul(b"Android\0").unwrap()),
+        component_version: Some(12),
+        resettable: true,
+        ..Default::default()
+    };
+    let config_descriptor = retry_bcc_format_config_descriptor(&config_values)?;
     let input_values = InputValues::new(
         [0u8; HASH_SIZE], // code_hash
         Config::Descriptor(config_descriptor.as_slice()),
diff --git a/keystore/keystore_attestation_id.cpp b/keystore/keystore_attestation_id.cpp
index 75c62dd..8eade97 100644
--- a/keystore/keystore_attestation_id.cpp
+++ b/keystore/keystore_attestation_id.cpp
@@ -158,7 +158,7 @@
         return BAD_VALUE;
     }
 
-    std::string pkg_name(String8(*pinfo.package_name()).string());
+    std::string pkg_name(String8(*pinfo.package_name()).c_str());
     if (!ASN1_OCTET_STRING_set(attestation_package_info->package_name,
                                reinterpret_cast<const unsigned char*>(pkg_name.data()),
                                pkg_name.size())) {
@@ -209,7 +209,7 @@
             ALOGE("Key attestation package info lacks package name");
             return BAD_VALUE;
         }
-        std::string package_name(String8(*pinfo->package_name()).string());
+        std::string package_name(String8(*pinfo->package_name()).c_str());
         std::unique_ptr<KM_ATTESTATION_PACKAGE_INFO> attestation_package_info;
         auto rc = build_attestation_package_info(*pinfo, &attestation_package_info);
         if (rc != NO_ERROR) {
@@ -283,7 +283,7 @@
         // caller is unknown.
         if (!status.isOk()) {
             ALOGW("package manager request for key attestation ID failed with: %s %d",
-                  status.exceptionMessage().string(), status.exceptionCode());
+                  status.exceptionMessage().c_str(), status.exceptionCode());
             auto pinfo = std::make_optional<KeyAttestationPackageInfo>(
                 String16(kUnknownPackageName), 1 /* version code */,
                 std::make_shared<KeyAttestationPackageInfo::SignaturesVector>());
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index a47c2c2..b8db7c6 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -78,27 +78,6 @@
 }
 
 rust_library {
-    name: "libkeystore2_test_utils",
-    crate_name: "keystore2_test_utils",
-    srcs: ["test_utils/lib.rs"],
-    defaults: [
-        "keymint_use_latest_hal_aidl_rust",
-        "keystore2_use_latest_aidl_rust",
-    ],
-    rustlibs: [
-        "libbinder_rs",
-        "libkeystore2_selinux",
-        "liblog_rust",
-        "libnix",
-        "librand",
-        "libserde",
-        "libserde_cbor",
-        "libthiserror",
-        "libanyhow",
-    ],
-}
-
-rust_library {
     name: "libkeystore2_with_test_utils",
     defaults: ["libkeystore2_defaults"],
     features: [
@@ -112,30 +91,6 @@
 }
 
 rust_test {
-    name: "keystore2_test_utils_test",
-    srcs: ["test_utils/lib.rs"],
-    defaults: [
-        "keymint_use_latest_hal_aidl_rust",
-        "keystore2_use_latest_aidl_rust",
-    ],
-    test_suites: ["general-tests"],
-    require_root: true,
-    auto_gen_config: true,
-    compile_multilib: "first",
-    rustlibs: [
-        "libbinder_rs",
-        "libkeystore2_selinux",
-        "liblog_rust",
-        "libnix",
-        "librand",
-        "libserde",
-        "libserde_cbor",
-        "libthiserror",
-        "libanyhow",
-    ],
-}
-
-rust_test {
     name: "keystore2_test",
     crate_name: "keystore2",
     test_suites: ["general-tests"],
diff --git a/keystore2/OWNERS b/keystore2/OWNERS
new file mode 100644
index 0000000..6b1a95b
--- /dev/null
+++ b/keystore2/OWNERS
@@ -0,0 +1,9 @@
+set noparent
+# Bug component: 1084732
+eranm@google.com
+drysdale@google.com
+hasinitg@google.com
+jbires@google.com
+sethmo@google.com
+trong@google.com
+swillden@google.com
diff --git a/keystore2/apc_compat/apc_compat.cpp b/keystore2/apc_compat/apc_compat.cpp
index 9f60db2..ffe7595 100644
--- a/keystore2/apc_compat/apc_compat.cpp
+++ b/keystore2/apc_compat/apc_compat.cpp
@@ -118,8 +118,7 @@
                                                    hidl_ui_options);
         if (!rc.isOk()) {
             LOG(ERROR) << "Communication error: promptUserConfirmation: " << rc.description();
-        }
-        if (rc == ResponseCode::OK) {
+        } else if (rc == ResponseCode::OK) {
             callback_ = callback;
         }
         return responseCode2Compat(rc.withDefault(ResponseCode::SystemError));
diff --git a/keystore2/src/crypto/lib.rs b/keystore2/src/crypto/lib.rs
index f8fc574..8434651 100644
--- a/keystore2/src/crypto/lib.rs
+++ b/keystore2/src/crypto/lib.rs
@@ -489,8 +489,8 @@
         let input = vec![0; 16];
         let mut out = vec![0; 16];
         let mut out2 = vec![0; 16];
-        let key = vec![0; 16];
-        let iv = vec![0; 12];
+        let key = [0; 16];
+        let iv = [0; 12];
         let mut tag = vec![0; 16];
         // SAFETY: The various pointers are obtained from references so they are valid, and
         // `AES_gcm_encrypt` and `AES_gcm_decrypt` don't do anything with them after they return.
@@ -523,7 +523,7 @@
 
     #[test]
     fn test_create_key_id() {
-        let blob = vec![0; 16];
+        let blob = [0; 16];
         let mut out: u64 = 0;
         // SAFETY: The pointers are obtained from references so they are valid, the length matches
         // the length of the array, and `CreateKeyId` doesn't access them after it returns.
@@ -537,8 +537,8 @@
     #[test]
     fn test_generate_key_from_password() {
         let mut key = vec![0; 16];
-        let pw = vec![0; 16];
-        let salt = vec![0; 16];
+        let pw = [0; 16];
+        let salt = [0; 16];
         // SAFETY: The pointers are obtained from references so they are valid, the salt is the
         // expected length, the other lengths match the lengths of the arrays, and
         // `generateKeyFromPassword` doesn't access them after it returns.
diff --git a/keystore2/src/fuzzers/Android.bp b/keystore2/src/fuzzers/Android.bp
index 9f3e104..0809dc8 100644
--- a/keystore2/src/fuzzers/Android.bp
+++ b/keystore2/src/fuzzers/Android.bp
@@ -20,7 +20,6 @@
     name: "keystore2_unsafe_fuzzer",
     srcs: ["keystore2_unsafe_fuzzer.rs"],
     rustlibs: [
-        "libbinder_rs",
         "libkeystore2",
         "libkeystore2_crypto_rust",
         "libkeystore2_hal_names_rust",
diff --git a/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs b/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs
index b8259cf..8b8843d 100644
--- a/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs
+++ b/keystore2/src/fuzzers/keystore2_unsafe_fuzzer.rs
@@ -16,7 +16,6 @@
 
 #![no_main]
 
-use binder::get_declared_instances;
 use keystore2::{legacy_blob::LegacyBlobLoader, utils::ui_opts_2_compat};
 use keystore2_aaid::get_aaid;
 use keystore2_apc_compat::ApcHal;
@@ -94,10 +93,6 @@
         minor_version: usize,
         hidl_interface_name: &'a str,
     },
-    GetAidlInstances {
-        aidl_package: &'a str,
-        aidl_interface_name: &'a str,
-    },
     GetAaid {
         aaid_uid: u32,
     },
@@ -189,12 +184,6 @@
             } => {
                 get_hidl_instances(hidl_package, major_version, minor_version, hidl_interface_name);
             }
-            FuzzCommand::GetAidlInstances { aidl_package, aidl_interface_name } => {
-                get_declared_instances(
-                    format!("{}.{}", aidl_package, aidl_interface_name).as_str(),
-                )
-                .unwrap();
-            }
             FuzzCommand::GetAaid { aaid_uid } => {
                 let _res = get_aaid(aaid_uid);
             }
diff --git a/keystore2/src/km_compat/km_compat.cpp b/keystore2/src/km_compat/km_compat.cpp
index e27cd1c..6bfd47a 100644
--- a/keystore2/src/km_compat/km_compat.cpp
+++ b/keystore2/src/km_compat/km_compat.cpp
@@ -144,6 +144,11 @@
 //
 const uint8_t kKeyBlobMagic[7] = {'p', 'K', 'M', 'b', 'l', 'o', 'b'};
 
+// Per RFC 5280 4.1.2.5, an undefined expiration (not-after) field should be set
+// to 9999-12-31T23:59:59Z.
+//
+const uint64_t kUndefinedNotAfter = 253402300799000;
+
 // Prefixes a keyblob returned by e.g. generateKey() with information on whether it
 // originated from the real underlying KeyMaster HAL or from soft-KeyMint.
 //
@@ -260,6 +265,16 @@
     return result;
 }
 
+std::vector<KMV1::KeyParameter>
+extractCombinedParams(const std::vector<KMV1::KeyCharacteristics>& characteristics) {
+    std::vector<KMV1::KeyParameter> result;
+    for (auto characteristic : characteristics) {
+        std::copy(characteristic.authorizations.begin(), characteristic.authorizations.end(),
+                  std::back_inserter(result));
+    }
+    return result;
+}
+
 ScopedAStatus convertErrorCode(KMV1::ErrorCode result) {
     if (result == KMV1::ErrorCode::OK) {
         return ScopedAStatus::ok();
@@ -587,6 +602,15 @@
         LOG(ERROR) << __func__ << " transaction failed. " << result.description();
         return convertErrorCode(KMV1::ErrorCode::UNKNOWN_ERROR);
     }
+    if (errorCode == KMV1::ErrorCode::OK) {
+        auto params = extractCombinedParams(out_creationResult->keyCharacteristics);
+        auto cert = getCertificate(params, out_creationResult->keyBlob, true /* isWrappedKey */);
+        // importWrappedKey used to not generate a certificate. Ignore the error to preserve
+        // backwards compatibility with clients that can't successfully generate a certificate.
+        if (std::holds_alternative<std::vector<Certificate>>(cert)) {
+            out_creationResult->certificateChain = std::get<std::vector<Certificate>>(cert);
+        }
+    }
     return convertErrorCode(errorCode);
 }
 
@@ -1055,7 +1079,7 @@
 
 static std::variant<keystore::X509_Ptr, KMV1::ErrorCode>
 makeCert(::android::sp<Keymaster> mDevice, const std::vector<KeyParameter>& keyParams,
-         const std::vector<uint8_t>& keyBlob) {
+         const std::vector<uint8_t>& keyBlob, bool isWrappedKey) {
     // Start generating the certificate.
     // Get public key for makeCert.
     KMV1::ErrorCode errorCode;
@@ -1097,15 +1121,21 @@
         serial = *blob;
     }
 
+    // There is no way to specify CERTIFICATE_NOT_BEFORE and CERTIFICATE_NOT_AFTER for wrapped keys.
+    // So we provide default values.
     int64_t activation;
-    if (auto date = getParam(keyParams, KMV1::TAG_CERTIFICATE_NOT_BEFORE)) {
+    if (isWrappedKey) {
+        activation = 0;
+    } else if (auto date = getParam(keyParams, KMV1::TAG_CERTIFICATE_NOT_BEFORE)) {
         activation = static_cast<int64_t>(*date);
     } else {
         return KMV1::ErrorCode::MISSING_NOT_BEFORE;
     }
 
     int64_t expiration;
-    if (auto date = getParam(keyParams, KMV1::TAG_CERTIFICATE_NOT_AFTER)) {
+    if (isWrappedKey) {
+        expiration = kUndefinedNotAfter;
+    } else if (auto date = getParam(keyParams, KMV1::TAG_CERTIFICATE_NOT_AFTER)) {
         expiration = static_cast<int64_t>(*date);
     } else {
         return KMV1::ErrorCode::MISSING_NOT_AFTER;
@@ -1235,7 +1265,7 @@
 
 std::variant<std::vector<Certificate>, KMV1::ErrorCode>
 KeyMintDevice::getCertificate(const std::vector<KeyParameter>& keyParams,
-                              const std::vector<uint8_t>& prefixedKeyBlob) {
+                              const std::vector<uint8_t>& prefixedKeyBlob, bool isWrappedKey) {
     const std::vector<uint8_t>& keyBlob = prefixedKeyBlobRemovePrefix(prefixedKeyBlob);
 
     // There are no certificates for symmetric keys.
@@ -1278,7 +1308,7 @@
     }
 
     // makeCert
-    auto certOrError = makeCert(mDevice, keyParams, keyBlob);
+    auto certOrError = makeCert(mDevice, keyParams, keyBlob, isWrappedKey);
     if (std::holds_alternative<KMV1::ErrorCode>(certOrError)) {
         return std::get<KMV1::ErrorCode>(certOrError);
     }
diff --git a/keystore2/src/km_compat/km_compat.h b/keystore2/src/km_compat/km_compat.h
index 6654c4a..c4bcdaa 100644
--- a/keystore2/src/km_compat/km_compat.h
+++ b/keystore2/src/km_compat/km_compat.h
@@ -150,7 +150,8 @@
     // These are public to allow testing code to use them directly.
     // This class should not be used publicly anyway.
     std::variant<std::vector<Certificate>, KMV1_ErrorCode>
-    getCertificate(const std::vector<KeyParameter>& keyParams, const std::vector<uint8_t>& keyBlob);
+    getCertificate(const std::vector<KeyParameter>& keyParams, const std::vector<uint8_t>& keyBlob,
+                   bool isWrappedKey = false);
 
     void setNumFreeSlots(uint8_t numFreeSlots);
 
diff --git a/keystore2/src/maintenance.rs b/keystore2/src/maintenance.rs
index 73dc881..59f5d70 100644
--- a/keystore2/src/maintenance.rs
+++ b/keystore2/src/maintenance.rs
@@ -178,7 +178,7 @@
             (SecurityLevel::TRUSTED_ENVIRONMENT, "TRUSTED_ENVIRONMENT"),
             (SecurityLevel::STRONGBOX, "STRONGBOX"),
         ];
-        sec_levels.iter().fold(Ok(()), move |result, (sec_level, sec_level_string)| {
+        sec_levels.iter().try_fold((), |_result, (sec_level, sec_level_string)| {
             let curr_result = Maintenance::call_with_watchdog(*sec_level, name, &op);
             match curr_result {
                 Ok(()) => log::info!(
@@ -193,7 +193,7 @@
                     e
                 ),
             }
-            result.and(curr_result)
+            curr_result
         })
     }
 
@@ -279,21 +279,29 @@
 
 impl IKeystoreMaintenance for Maintenance {
     fn onUserPasswordChanged(&self, user_id: i32, password: Option<&[u8]>) -> BinderResult<()> {
+        log::info!(
+            "onUserPasswordChanged(user={}, password.is_some()={})",
+            user_id,
+            password.is_some()
+        );
         let _wp = wd::watch_millis("IKeystoreMaintenance::onUserPasswordChanged", 500);
         map_or_log_err(Self::on_user_password_changed(user_id, password.map(|pw| pw.into())), Ok)
     }
 
     fn onUserAdded(&self, user_id: i32) -> BinderResult<()> {
+        log::info!("onUserAdded(user={user_id})");
         let _wp = wd::watch_millis("IKeystoreMaintenance::onUserAdded", 500);
         map_or_log_err(self.add_or_remove_user(user_id), Ok)
     }
 
     fn onUserRemoved(&self, user_id: i32) -> BinderResult<()> {
+        log::info!("onUserRemoved(user={user_id})");
         let _wp = wd::watch_millis("IKeystoreMaintenance::onUserRemoved", 500);
         map_or_log_err(self.add_or_remove_user(user_id), Ok)
     }
 
     fn clearNamespace(&self, domain: Domain, nspace: i64) -> BinderResult<()> {
+        log::info!("clearNamespace({domain:?}, nspace={nspace})");
         let _wp = wd::watch_millis("IKeystoreMaintenance::clearNamespace", 500);
         map_or_log_err(self.clear_namespace(domain, nspace), Ok)
     }
@@ -304,11 +312,13 @@
     }
 
     fn earlyBootEnded(&self) -> BinderResult<()> {
+        log::info!("earlyBootEnded()");
         let _wp = wd::watch_millis("IKeystoreMaintenance::earlyBootEnded", 500);
         map_or_log_err(Self::early_boot_ended(), Ok)
     }
 
     fn onDeviceOffBody(&self) -> BinderResult<()> {
+        log::info!("onDeviceOffBody()");
         let _wp = wd::watch_millis("IKeystoreMaintenance::onDeviceOffBody", 500);
         map_or_log_err(Self::on_device_off_body(), Ok)
     }
@@ -318,11 +328,13 @@
         source: &KeyDescriptor,
         destination: &KeyDescriptor,
     ) -> BinderResult<()> {
+        log::info!("migrateKeyNamespace(src={source:?}, dest={destination:?})");
         let _wp = wd::watch_millis("IKeystoreMaintenance::migrateKeyNamespace", 500);
         map_or_log_err(Self::migrate_key_namespace(source, destination), Ok)
     }
 
     fn deleteAllKeys(&self) -> BinderResult<()> {
+        log::warn!("deleteAllKeys()");
         let _wp = wd::watch_millis("IKeystoreMaintenance::deleteAllKeys", 500);
         map_or_log_err(Self::delete_all_keys(), Ok)
     }
diff --git a/keystore2/src/super_key.rs b/keystore2/src/super_key.rs
index 7fc3ed4..5ee4f17 100644
--- a/keystore2/src/super_key.rs
+++ b/keystore2/src/super_key.rs
@@ -644,17 +644,17 @@
                 // super key is not unlocked or the LSKF is not setup, an error is returned.
                 match self
                     .get_user_state(db, legacy_importer, user_id)
-                    .context(ks_err!("Failed to get user state."))?
+                    .context(ks_err!("Failed to get user state for user {user_id}"))?
                 {
-                    UserState::LskfUnlocked(super_key) => {
-                        Self::encrypt_with_aes_super_key(key_blob, &super_key)
-                            .context(ks_err!("Failed to encrypt with LskfBound key."))
-                    }
+                    UserState::LskfUnlocked(super_key) => Self::encrypt_with_aes_super_key(
+                        key_blob, &super_key,
+                    )
+                    .context(ks_err!("Failed to encrypt with LskfBound key for user {user_id}")),
                     UserState::LskfLocked => {
                         Err(Error::Rc(ResponseCode::LOCKED)).context(ks_err!("Device is locked."))
                     }
                     UserState::Uninitialized => Err(Error::Rc(ResponseCode::UNINITIALIZED))
-                        .context(ks_err!("LSKF is not setup for the user.")),
+                        .context(ks_err!("LSKF is not setup for user {user_id}")),
                 }
             }
             SuperEncryptionType::ScreenLockBound => {
@@ -912,9 +912,11 @@
                 .context(ks_err!("load_key_entry failed"))?;
             let km_dev: KeyMintDevice = KeyMintDevice::get(SecurityLevel::TRUSTED_ENVIRONMENT)
                 .context(ks_err!("KeyMintDevice::get failed"))?;
+            let mut errs = vec![];
             for sid in &biometric.sids {
+                let sid = *sid;
                 if let Some((auth_token_entry, _)) = db.find_auth_token_entry(|entry| {
-                    entry.auth_token().userId == *sid || entry.auth_token().authenticatorId == *sid
+                    entry.auth_token().userId == sid || entry.auth_token().authenticatorId == sid
                 }) {
                     let res: Result<(Arc<SuperKey>, Arc<SuperKey>)> = (|| {
                         let slb = biometric.screen_lock_bound.decrypt(
@@ -941,15 +943,22 @@
                             entry.screen_lock_bound_private = Some(slbp.clone());
                             self.data.add_key_to_key_index(&slb)?;
                             self.data.add_key_to_key_index(&slbp)?;
-                            log::info!("Successfully unlocked with biometric");
+                            log::info!("Successfully unlocked user {user_id} with biometric {sid}",);
                             return Ok(());
                         }
                         Err(e) => {
-                            log::warn!("attempt failed: {:?}", e)
+                            // Don't log an error yet, as some other biometric SID might work.
+                            errs.push((sid, e));
                         }
                     }
                 }
             }
+            if !errs.is_empty() {
+                log::warn!("biometric unlock failed for all SIDs, with errors:");
+                for (sid, err) in errs {
+                    log::warn!("  biometric {sid}: {err}");
+                }
+            }
         }
         Ok(())
     }
@@ -988,6 +997,7 @@
         legacy_importer: &LegacyImporter,
         user_id: UserId,
     ) -> Result<()> {
+        log::info!("remove_user(user={user_id})");
         // Mark keys created on behalf of the user as unreferenced.
         legacy_importer
             .bulk_delete_user(user_id, false)
@@ -1008,6 +1018,7 @@
         legacy_importer: &LegacyImporter,
         user_id: UserId,
     ) -> Result<()> {
+        log::info!("reset_user(user={user_id})");
         match self.get_user_state(db, legacy_importer, user_id)? {
             UserState::Uninitialized => {
                 Err(Error::sys()).context(ks_err!("Tried to reset an uninitialized user!"))
@@ -1039,6 +1050,7 @@
         user_id: UserId,
         password: &Password,
     ) -> Result<()> {
+        log::info!("init_user(user={user_id})");
         match self.get_user_state(db, legacy_importer, user_id)? {
             UserState::LskfUnlocked(_) | UserState::LskfLocked => {
                 Err(Error::sys()).context(ks_err!("Tried to re-init an initialized user!"))
@@ -1091,6 +1103,7 @@
         user_id: UserId,
         password: &Password,
     ) -> Result<()> {
+        log::info!("unlock_user(user={user_id})");
         match self.get_user_state(db, legacy_importer, user_id)? {
             UserState::LskfUnlocked(_) => self.unlock_screen_lock_bound_key(db, user_id, password),
             UserState::Uninitialized => {
diff --git a/keystore2/test_utils/Android.bp b/keystore2/test_utils/Android.bp
new file mode 100644
index 0000000..eb04209
--- /dev/null
+++ b/keystore2/test_utils/Android.bp
@@ -0,0 +1,122 @@
+// 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.
+
+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"],
+}
+
+rust_defaults {
+    name: "libkeystore2_test_utils_defaults",
+    defaults: [
+        "keymint_use_latest_hal_aidl_rust",
+        "keystore2_use_latest_aidl_rust",
+    ],
+    rustlibs: [
+        "libanyhow",
+        "libbinder_rs",
+        "libcxx",
+        "libkeystore2_selinux",
+        "liblog_rust",
+        "libnix",
+        "librand",
+        "libserde",
+        "libserde_cbor",
+        "libthiserror",
+    ],
+    static_libs: [
+        "libgtest",
+        "libkeymint_vts_test_utils",
+        "libkeystore2_ffi_test_utils",
+    ],
+    shared_libs: [
+        // libkeymint_vts_test_utils needs to be static for atest,
+        // and that pulls in keymint shared lib dependency
+        "android.hardware.security.keymint-V3-ndk",
+        "libbase",
+        "libbinder",
+        "libbinder_ndk",
+        "libcppbor_external",
+        "libcppcose_rkp",
+        "libcrypto",
+        "libcutils",
+        "libkeymaster_messages",
+        "libkeymaster_portable",
+        "libkeymint_remote_prov_support",
+        "libkeymint_support",
+        "libkeystore-engine",
+        "libutils",
+        "packagemanager_aidl-cpp",
+    ],
+}
+
+rust_library {
+    name: "libkeystore2_test_utils",
+    crate_name: "keystore2_test_utils",
+    srcs: ["lib.rs"],
+    defaults: ["libkeystore2_test_utils_defaults"],
+}
+
+rust_test {
+    name: "keystore2_test_utils_test",
+    srcs: ["lib.rs"],
+    defaults: ["libkeystore2_test_utils_defaults"],
+    test_suites: ["general-tests"],
+    require_root: true,
+    auto_gen_config: true,
+    compile_multilib: "first",
+}
+
+cc_library_static {
+    name: "libkeystore2_ffi_test_utils",
+    srcs: ["ffi_test_utils.cpp"],
+    defaults: [
+        "keymint_vts_defaults",
+        "hidl_defaults",
+    ],
+    generated_headers: [
+        "cxx-bridge-header",
+        "libkeystore2_ffi_test_utils_bridge_header",
+    ],
+    generated_sources: ["libkeystore2_ffi_test_utils_bridge_code"],
+    static_libs: [
+        "libkeymint_vts_test_utils",
+    ],
+    shared_libs: [
+        "libcppbor_external",
+        "libkeymaster_messages",
+        "libkeymaster_portable",
+        "libkeystore-engine",
+    ],
+}
+
+genrule {
+    name: "libkeystore2_ffi_test_utils_bridge_code",
+    tools: ["cxxbridge"],
+    cmd: "$(location cxxbridge) $(in) >> $(out)",
+    srcs: ["ffi_test_utils.rs"],
+    out: ["libkeystore2_test_utils_cxx_generated.cc"],
+}
+
+genrule {
+    name: "libkeystore2_ffi_test_utils_bridge_header",
+    tools: ["cxxbridge"],
+    cmd: "$(location cxxbridge) $(in) --header >> $(out)",
+    srcs: ["ffi_test_utils.rs"],
+    out: ["ffi_test_utils.rs.h"],
+}
diff --git a/keystore2/tests/ffi_test_utils.cpp b/keystore2/test_utils/ffi_test_utils.cpp
similarity index 100%
rename from keystore2/tests/ffi_test_utils.cpp
rename to keystore2/test_utils/ffi_test_utils.cpp
diff --git a/keystore2/tests/ffi_test_utils.hpp b/keystore2/test_utils/ffi_test_utils.hpp
similarity index 100%
rename from keystore2/tests/ffi_test_utils.hpp
rename to keystore2/test_utils/ffi_test_utils.hpp
diff --git a/keystore2/tests/ffi_test_utils.rs b/keystore2/test_utils/ffi_test_utils.rs
similarity index 91%
rename from keystore2/tests/ffi_test_utils.rs
rename to keystore2/test_utils/ffi_test_utils.rs
index c652174..019c26b 100644
--- a/keystore2/tests/ffi_test_utils.rs
+++ b/keystore2/test_utils/ffi_test_utils.rs
@@ -12,8 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+//! This module implements helper methods to access the functionalities implemented in CPP.
+
+use crate::key_generations::Error;
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::Tag::Tag;
-use keystore2_test_utils::key_generations::Error;
 
 #[cxx::bridge]
 mod ffi {
@@ -46,6 +48,7 @@
     Err(Error::ValidateCertChainFailed)
 }
 
+/// Collect the result from CxxResult into a Rust supported structure.
 fn get_result(result: ffi::CxxResult) -> Result<Vec<u8>, Error> {
     if result.error == 0 && !result.data.is_empty() {
         Ok(result.data)
@@ -82,6 +85,7 @@
     get_result(ffi::buildAsn1DerEncodedWrappedKeyDescription())
 }
 
+/// Performs crypto operation using Keystore-Engine APIs.
 pub fn perform_crypto_op_using_keystore_engine(grant_id: i64) -> Result<bool, Error> {
     if ffi::performCryptoOpUsingKeystoreEngine(grant_id) {
         return Ok(true);
@@ -90,6 +94,7 @@
     Err(Error::Keystore2EngineOpFailed)
 }
 
+/// Get the value of the given `Tag` from attestation record.
 pub fn get_value_from_attest_record(cert_buf: &[u8], tag: Tag) -> Result<Vec<u8>, Error> {
     let result = ffi::getValueFromAttestRecord(cert_buf.to_vec(), tag.0);
     if result.error == 0 && !result.data.is_empty() {
diff --git a/keystore2/test_utils/lib.rs b/keystore2/test_utils/lib.rs
index c63bfac..a373a2f 100644
--- a/keystore2/test_utils/lib.rs
+++ b/keystore2/test_utils/lib.rs
@@ -22,6 +22,7 @@
 use android_system_keystore2::aidl::android::system::keystore2::IKeystoreService::IKeystoreService;
 
 pub mod authorizations;
+pub mod ffi_test_utils;
 pub mod key_generations;
 pub mod run_as;
 
diff --git a/keystore2/tests/Android.bp b/keystore2/tests/Android.bp
index 32c39dc..a574fa1 100644
--- a/keystore2/tests/Android.bp
+++ b/keystore2/tests/Android.bp
@@ -34,70 +34,13 @@
     test_config: "AndroidTest.xml",
 
     rustlibs: [
-        "librustutils",
-        "libkeystore2_test_utils",
-        "packagemanager_aidl-rust",
-        "libnix",
-        "libanyhow",
         "libbinder_rs",
-        "liblazy_static",
-        "liblibc",
-        "libserde",
-        "libthiserror",
-        "libcxx",
+        "libkeystore2_test_utils",
+        "libnix",
         "libopenssl",
-    ],
-    static_libs: [
-        "libkeystore2_ffi_test_utils",
-        "libgtest",
-        "libkeymint_vts_test_utils",
-    ],
-    shared_libs: [
-        "libcrypto",
-        "libkeymaster_portable",
-        "libkeymaster_messages",
-        "libcppbor_external",
-        "libkeystore-engine",
-        "libkeymint_support",
+        "librustutils",
+        "libserde",
+        "packagemanager_aidl-rust",
     ],
     require_root: true,
 }
-
-cc_library_static {
-    name: "libkeystore2_ffi_test_utils",
-    srcs: ["ffi_test_utils.cpp"],
-    defaults: [
-        "keymint_vts_defaults",
-        "hidl_defaults",
-    ],
-    generated_headers: [
-        "cxx-bridge-header",
-        "libkeystore2_ffi_test_utils_bridge_header",
-    ],
-    generated_sources: ["libkeystore2_ffi_test_utils_bridge_code"],
-    static_libs: [
-        "libkeymint_vts_test_utils",
-    ],
-    shared_libs: [
-        "libkeymaster_portable",
-        "libkeymaster_messages",
-        "libcppbor_external",
-        "libkeystore-engine",
-    ],
-}
-
-genrule {
-    name: "libkeystore2_ffi_test_utils_bridge_code",
-    tools: ["cxxbridge"],
-    cmd: "$(location cxxbridge) $(in) >> $(out)",
-    srcs: ["ffi_test_utils.rs"],
-    out: ["libkeystore2_test_utils_cxx_generated.cc"],
-}
-
-genrule {
-    name: "libkeystore2_ffi_test_utils_bridge_header",
-    tools: ["cxxbridge"],
-    cmd: "$(location cxxbridge) $(in) --header >> $(out)",
-    srcs: ["ffi_test_utils.rs"],
-    out: ["ffi_test_utils.rs.h"],
-}
diff --git a/keystore2/tests/keystore2_client_attest_key_tests.rs b/keystore2/tests/keystore2_client_attest_key_tests.rs
index b8ad90d..f3228ea 100644
--- a/keystore2/tests/keystore2_client_attest_key_tests.rs
+++ b/keystore2/tests/keystore2_client_attest_key_tests.rs
@@ -28,7 +28,7 @@
     authorizations, get_keystore_service, key_generations, key_generations::Error,
 };
 
-use crate::ffi_test_utils::{get_value_from_attest_record, validate_certchain};
+use keystore2_test_utils::ffi_test_utils::{get_value_from_attest_record, validate_certchain};
 
 use crate::{
     skip_test_if_no_app_attest_key_feature, skip_test_if_no_device_id_attestation_feature,
diff --git a/keystore2/tests/keystore2_client_import_keys_tests.rs b/keystore2/tests/keystore2_client_import_keys_tests.rs
index ecba402..3d108fe 100644
--- a/keystore2/tests/keystore2_client_import_keys_tests.rs
+++ b/keystore2/tests/keystore2_client_import_keys_tests.rs
@@ -32,7 +32,9 @@
     authorizations, get_keystore_service, key_generations, key_generations::Error,
 };
 
-use crate::ffi_test_utils::{create_wrapped_key, create_wrapped_key_additional_auth_data};
+use keystore2_test_utils::ffi_test_utils::{
+    create_wrapped_key, create_wrapped_key_additional_auth_data,
+};
 
 use crate::keystore2_client_test_utils::{
     encrypt_secure_key, encrypt_transport_key, has_default_keymint,
diff --git a/keystore2/tests/keystore2_client_keystore_engine_tests.rs b/keystore2/tests/keystore2_client_keystore_engine_tests.rs
index 339eb60..4651931 100644
--- a/keystore2/tests/keystore2_client_keystore_engine_tests.rs
+++ b/keystore2/tests/keystore2_client_keystore_engine_tests.rs
@@ -26,7 +26,7 @@
 
 use keystore2_test_utils::{authorizations::AuthSetBuilder, get_keystore_service, run_as};
 
-use crate::ffi_test_utils::perform_crypto_op_using_keystore_engine;
+use keystore2_test_utils::ffi_test_utils::perform_crypto_op_using_keystore_engine;
 
 use openssl::x509::X509;
 
diff --git a/keystore2/tests/keystore2_client_tests.rs b/keystore2/tests/keystore2_client_tests.rs
index 9be0bf8..3b6a78c 100644
--- a/keystore2/tests/keystore2_client_tests.rs
+++ b/keystore2/tests/keystore2_client_tests.rs
@@ -12,7 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-pub mod ffi_test_utils;
 pub mod keystore2_client_3des_key_tests;
 pub mod keystore2_client_aes_key_tests;
 pub mod keystore2_client_attest_key_tests;