Merge "[dice] Move DiceKeypairFromSeed wrapper to diced_open_dice"
diff --git a/diced/Android.bp b/diced/Android.bp
index b640326a..6e857f4 100644
--- a/diced/Android.bp
+++ b/diced/Android.bp
@@ -59,7 +59,6 @@
         "android.hardware.security.dice-V1-rust",
         "libanyhow",
         "libdiced_open_dice",
-        "libdiced_open_dice_cbor",
         "libdiced_utils",
     ],
 }
@@ -74,7 +73,6 @@
         "android.hardware.security.dice-V1-rust",
         "libanyhow",
         "libdiced_open_dice",
-        "libdiced_open_dice_cbor",
         "libdiced_utils",
     ],
 }
@@ -88,7 +86,6 @@
     rustlibs: [
         "android.hardware.security.dice-V1-rust",
         "libdiced_open_dice",
-        "libdiced_open_dice_cbor",
         "libanyhow",
         "libbinder_rs",
         "libdiced_utils",
@@ -112,7 +109,6 @@
         "android.hardware.security.dice-V1-rust",
         "libanyhow",
         "libdiced_open_dice",
-        "libdiced_open_dice_cbor",
         "libdiced_sample_inputs",
         "libdiced_utils",
         "libbinder_rs",
@@ -143,7 +139,6 @@
         "libanyhow",
         "libbinder_rs",
         "libdiced_open_dice",
-        "libdiced_open_dice_cbor",
         "libdiced_sample_inputs",
         "libdiced_utils",
         "libnix",
diff --git a/diced/open_dice/src/dice.rs b/diced/open_dice/src/dice.rs
index f5e7f71..9266b6f 100644
--- a/diced/open_dice/src/dice.rs
+++ b/diced/open_dice/src/dice.rs
@@ -53,8 +53,6 @@
 pub type InlineConfig = [u8; INLINE_CONFIG_SIZE];
 /// Array type of CDIs.
 pub type Cdi = [u8; CDI_SIZE];
-/// Array type of private key seeds.
-pub type PrivateKeySeed = [u8; PRIVATE_KEY_SEED_SIZE];
 /// Array type of the public key.
 pub type PublicKey = [u8; PUBLIC_KEY_SIZE];
 /// Array type of the signature.
@@ -80,6 +78,8 @@
     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 {
@@ -89,6 +89,49 @@
     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> {
@@ -165,7 +208,7 @@
 
 /// 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 = [0u8; PRIVATE_KEY_SEED_SIZE];
+    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 {
diff --git a/diced/open_dice/src/lib.rs b/diced/open_dice/src/lib.rs
index 925b5e8..e7ec56b 100644
--- a/diced/open_dice/src/lib.rs
+++ b/diced/open_dice/src/lib.rs
@@ -33,11 +33,11 @@
 };
 pub use dice::{
     derive_cdi_certificate_id, derive_cdi_private_key_seed, dice_main_flow, Cdi, CdiValues, Config,
-    DiceArtifacts, DiceMode, Hash, Hidden, InlineConfig, InputValues, PrivateKeySeed, CDI_SIZE,
-    HASH_SIZE, HIDDEN_SIZE, ID_SIZE, PRIVATE_KEY_SEED_SIZE,
+    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, sign, verify};
+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,
diff --git a/diced/open_dice/src/ops.rs b/diced/open_dice/src/ops.rs
index 21b7d9e..8222b26 100644
--- a/diced/open_dice/src/ops.rs
+++ b/diced/open_dice/src/ops.rs
@@ -17,11 +17,13 @@
 //! main DICE functions depend on.
 
 use crate::dice::{
-    Hash, InputValues, PublicKey, Signature, HASH_SIZE, PRIVATE_KEY_SEED_SIZE, PRIVATE_KEY_SIZE,
-    SIGNATURE_SIZE,
+    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, DiceSign, DiceVerify};
+use open_dice_cbor_bindgen::{
+    DiceGenerateCertificate, DiceHash, DiceKdf, DiceKeypairFromSeed, DiceSign, DiceVerify,
+};
 use std::ptr;
 
 /// Hashes the provided input using DICE's hash function `DiceHash`.
@@ -60,6 +62,25 @@
     })
 }
 
+/// 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];
diff --git a/diced/open_dice_cbor/Android.bp b/diced/open_dice_cbor/Android.bp
index e52af7d..a2534dc 100644
--- a/diced/open_dice_cbor/Android.bp
+++ b/diced/open_dice_cbor/Android.bp
@@ -16,27 +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: [
-        "libdiced_open_dice",
-        // For ZVec
-        "libkeystore2_crypto_rust",
-        "libopen_dice_cbor_bindgen",
-    ],
-    static_libs: [
-        "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,10 +25,5 @@
     rustlibs: [
         "libdiced_open_dice",
         "libdiced_sample_inputs",
-        "libkeystore2_crypto_rust",
-        "libopen_dice_cbor_bindgen",
-    ],
-    static_libs: [
-        "libopen_dice_cbor",
     ],
 }
diff --git a/diced/open_dice_cbor/lib.rs b/diced/open_dice_cbor/lib.rs
index 0e68e70..95eb300 100644
--- a/diced/open_dice_cbor/lib.rs
+++ b/diced/open_dice_cbor/lib.rs
@@ -12,120 +12,9 @@
 // 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::InputValues::new(
-//!     [3u8, dice::HASH_SIZE], // code_hash
-//!     dice::Config::Descriptor(&"My descriptor".as_bytes().to_vec()),
-//!     [0u8, dice::HASH_SIZE], // authority_hash
-//!     dice::DiceMode::kDiceModeNormal,
-//!     [0u8, dice::HIDDEN_SIZE], // hidden
-//! };
-//! let (cdi_attest, cdi_seal, cert_chain) = context
-//!     .main_flow(&parent_cdi_attest, &parent_cdi_seal, &input_values)?;
-//! ```
-
-pub use diced_open_dice::{
-    check_result, derive_cdi_private_key_seed, hash, retry_bcc_format_config_descriptor,
-    retry_bcc_main_flow, retry_dice_main_flow, sign, Config, DiceError, Hash, Hidden, InputValues,
-    OwnedDiceArtifacts, Result, CDI_SIZE, HASH_SIZE, HIDDEN_SIZE, PRIVATE_KEY_SEED_SIZE,
-};
-use keystore2_crypto::ZVec;
-pub use open_dice_cbor_bindgen::DiceMode;
-use open_dice_cbor_bindgen::{DiceKeypairFromSeed, DICE_PRIVATE_KEY_SIZE, DICE_PUBLIC_KEY_SIZE};
-use std::ffi::c_void;
-
-/// 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;
-
-/// 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>;
-
-/// 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 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))
-    }
-}
-
+// 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;
@@ -172,32 +61,23 @@
 
     #[test]
     fn hash_derive_sign_verify() {
-        let mut ctx = OpenDiceCborContext::new();
         let seed = diced_open_dice::hash("MySeedString".as_bytes()).unwrap();
         assert_eq!(seed, SEED_TEST_VECTOR);
-        let cdi_attest = &seed[..CDI_SIZE];
+        let cdi_attest = &seed[..diced_open_dice::CDI_SIZE];
         assert_eq!(cdi_attest, CDI_ATTEST_TEST_VECTOR);
         let cdi_private_key_seed =
-            derive_cdi_private_key_seed(cdi_attest.try_into().unwrap()).unwrap();
-        assert_eq!(&cdi_private_key_seed[..], CDI_PRIVATE_KEY_SEED_TEST_VECTOR);
+            diced_open_dice::derive_cdi_private_key_seed(cdi_attest.try_into().unwrap()).unwrap();
+        assert_eq!(cdi_private_key_seed.as_array(), CDI_PRIVATE_KEY_SEED_TEST_VECTOR);
         let (pub_key, priv_key) =
-            ctx.keypair_from_seed(cdi_private_key_seed[..].try_into().unwrap()).unwrap();
+            diced_open_dice::keypair_from_seed(cdi_private_key_seed.as_array()).unwrap();
         assert_eq!(&pub_key, PUB_KEY_TEST_VECTOR);
-        assert_eq!(&priv_key[..], PRIV_KEY_TEST_VECTOR);
-        let mut signature =
-            diced_open_dice::sign(b"MyMessage", priv_key[..].try_into().unwrap()).unwrap();
+        assert_eq!(priv_key.as_array(), PRIV_KEY_TEST_VECTOR);
+        let mut signature = diced_open_dice::sign(b"MyMessage", priv_key.as_array()).unwrap();
         assert_eq!(&signature, SIGNATURE_TEST_VECTOR);
-        assert!(diced_open_dice::verify(b"MyMessage", &signature, pub_key[..].try_into().unwrap())
-            .is_ok());
-        assert!(diced_open_dice::verify(
-            b"MyMessage_fail",
-            &signature,
-            pub_key[..].try_into().unwrap()
-        )
-        .is_err());
+        assert!(diced_open_dice::verify(b"MyMessage", &signature, &pub_key).is_ok());
+        assert!(diced_open_dice::verify(b"MyMessage_fail", &signature, &pub_key).is_err());
         signature[0] += 1;
-        assert!(diced_open_dice::verify(b"MyMessage", &signature, pub_key[..].try_into().unwrap())
-            .is_err());
+        assert!(diced_open_dice::verify(b"MyMessage", &signature, &pub_key).is_err());
     }
 
     static SAMPLE_CDI_ATTEST_TEST_VECTOR: &[u8] = &[
diff --git a/diced/src/diced_client_test.rs b/diced/src/diced_client_test.rs
index 29d7295..7957f0a 100644
--- a/diced/src/diced_client_test.rs
+++ b/diced/src/diced_client_test.rs
@@ -19,8 +19,8 @@
 use android_security_dice::aidl::android::security::dice::IDiceMaintenance::IDiceMaintenance;
 use android_security_dice::aidl::android::security::dice::IDiceNode::IDiceNode;
 use binder::Strong;
+use diced_open_dice as dice;
 use diced_open_dice::DiceArtifacts;
-use diced_open_dice_cbor as dice;
 use nix::libc::uid_t;
 use std::convert::TryInto;
 use std::ffi::CString;
diff --git a/diced/src/hal_node.rs b/diced/src/hal_node.rs
index 04602bd..33aeb2b 100644
--- a/diced/src/hal_node.rs
+++ b/diced/src/hal_node.rs
@@ -34,9 +34,8 @@
 };
 use anyhow::{Context, Result};
 use binder::{BinderFeatures, Result as BinderResult, Strong};
-use dice::{ContextImpl, OpenDiceCborContext};
+use diced_open_dice as dice;
 pub use diced_open_dice::DiceArtifacts;
-use diced_open_dice_cbor as dice;
 use diced_utils as utils;
 use nix::sys::wait::{waitpid, WaitStatus};
 use nix::unistd::{
@@ -203,7 +202,6 @@
         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!(
@@ -213,24 +211,10 @@
                     })?,
                 )
                 .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()
-                        )
-                    })?)
+                let (_public_key, private_key) = dice::keypair_from_seed(seed.as_array())
                     .context("In ResidentHal::sign: Failed to derive keypair from seed.")?;
-                let signature = dice::sign(
-                    message,
-                    private_key[..].try_into().with_context(|| {
-                        format!(
-                            "In ResidentHal::sign: Failed to convert private_key (length: {}).",
-                            private_key.len()
-                        )
-                    })?,
-                )
-                .context("In ResidentHal::sign: Failed to sign.")?;
+                let signature = dice::sign(message, private_key.as_array())
+                    .context("In ResidentHal::sign: Failed to sign.")?;
                 Ok(signature.to_vec())
             })
             .context("In ResidentHal::sign:")?;
@@ -333,7 +317,7 @@
         InputValues::InputValues as BinderInputValues, Mode::Mode as BinderMode,
     };
     use anyhow::{anyhow, Context, Result};
-    use diced_open_dice_cbor as dice;
+    use diced_open_dice as dice;
     use diced_sample_inputs;
     use diced_utils as utils;
     use std::ffi::CStr;
diff --git a/diced/src/lib_vendor.rs b/diced/src/lib_vendor.rs
index 01c804b..a04bb80 100644
--- a/diced/src/lib_vendor.rs
+++ b/diced/src/lib_vendor.rs
@@ -17,4 +17,4 @@
 
 mod error_vendor;
 pub mod hal_node;
-pub use diced_open_dice_cbor as dice;
+pub use diced_open_dice as dice;
diff --git a/diced/src/sample_inputs.rs b/diced/src/sample_inputs.rs
index 824ee9e..6ad8ca9 100644
--- a/diced/src/sample_inputs.rs
+++ b/diced/src/sample_inputs.rs
@@ -19,9 +19,8 @@
     Config::Config as BinderConfig, InputValues::InputValues as BinderInputValues, Mode::Mode,
 };
 use anyhow::{anyhow, Context, Result};
-use dice::ContextImpl;
+use diced_open_dice as dice;
 use diced_open_dice::DiceArtifacts;
-use diced_open_dice_cbor as dice;
 use diced_utils::{cbor, to_dice_input_values};
 use std::ffi::CStr;
 use std::io::Write;
@@ -66,16 +65,11 @@
 /// Derives a tuple of (CDI_ATTEST, CDI_SEAL, BCC) derived of the vector of input values returned
 /// by `get_input_values_vector`.
 pub fn make_sample_bcc_and_cdis() -> Result<dice::OwnedDiceArtifacts> {
-    let mut dice_ctx = dice::OpenDiceCborContext::new();
     let private_key_seed = dice::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 (public_key, _) = dice::keypair_from_seed(private_key_seed.as_array())
+        .context("In make_sample_bcc_and_cids: Failed to generate key pair.")?;
 
     let input_values_vector = get_input_values_vector();