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();