[dice] Move DiceKeypairFromSeed wrapper to diced_open_dice
This cl moves DiceKeypairFromSeed wrapper to diced_open_dice
and removes the crate diced_open_dice_cbor as it doesn't have
any code after moving out the function.
This cl also sets the type of PrivateKey and PrivateKeySeed to
struct so that their memory will be zeroed out when the struct
variable is dropped for security consideration. This is not
a complete solution for securing the sensitive data access: we
will clean up the memory cache of the sensitive data in a
follow-up cl.
Bug: 267575445
Test: atest diced_utils_test diced_sample_inputs_test \
diced_vendor_test diced_open_dice_cbor_test \
libdiced_open_dice_nostd.integration_test \
libdiced_open_dice.integration_test diced_open_dice_cbor_test
Change-Id: I6c9b1190bfc4238adc59b88b6f3ee8fdd5cbd8f0
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();