[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/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];