Merge "[dice][microdroid] Refactor DiceDriver with the trait DiceArtifacts"
diff --git a/microdroid_manager/src/dice.rs b/microdroid_manager/src/dice.rs
index fd22198..c3136e8 100644
--- a/microdroid_manager/src/dice.rs
+++ b/microdroid_manager/src/dice.rs
@@ -17,8 +17,8 @@
use anyhow::{anyhow, bail, Context, Error, Result};
use byteorder::{NativeEndian, ReadBytesExt};
use diced_open_dice::{
- bcc_handover_parse, retry_bcc_main_flow, BccHandover, Cdi, Config, DiceMode, Hash, Hidden,
- InputValues, OwnedDiceArtifacts,
+ bcc_handover_parse, retry_bcc_main_flow, BccHandover, Config, DiceArtifacts, DiceMode, Hash,
+ Hidden, InputValues, OwnedDiceArtifacts,
};
use keystore2_crypto::ZVec;
use libc::{c_void, mmap, munmap, MAP_FAILED, MAP_PRIVATE, PROT_READ};
@@ -32,14 +32,12 @@
/// Derives a sealing key from the DICE sealing CDI.
pub fn derive_sealing_key(
- cdi_seal: &Cdi,
+ dice_artifacts: &dyn DiceArtifacts,
salt: &[u8],
info: &[u8],
- keysize: usize,
-) -> Result<ZVec> {
- let mut key = ZVec::new(keysize)?;
- hkdf(&mut key, Md::sha256(), cdi_seal, salt, info)?;
- Ok(key)
+ key: &mut [u8],
+) -> Result<()> {
+ Ok(hkdf(key, Md::sha256(), dice_artifacts.cdi_seal(), salt, info)?)
}
/// Artifacts that are mapped into the process address space from the driver.
@@ -54,6 +52,13 @@
}
impl DiceDriver<'_> {
+ fn dice_artifacts(&self) -> &dyn DiceArtifacts {
+ match self {
+ Self::Real { bcc_handover, .. } => bcc_handover,
+ Self::Fake(owned_dice_artifacts) => owned_dice_artifacts,
+ }
+ }
+
pub fn new(driver_path: &Path) -> Result<Self> {
if driver_path.exists() {
log::info!("Using DICE values from driver");
@@ -95,16 +100,15 @@
})
}
- pub fn get_sealing_key(&self, identifier: &[u8]) -> Result<ZVec> {
+ /// Derives a sealing key of `key_length` bytes from the DICE sealing CDI.
+ pub fn get_sealing_key(&self, identifier: &[u8], key_length: usize) -> Result<ZVec> {
// Deterministically derive a key to use for sealing data, rather than using the CDI
// directly, so we have the chance to rotate the key if needed. A salt isn't needed as the
// input key material is already cryptographically strong.
- let cdi_seal = match self {
- Self::Real { bcc_handover, .. } => bcc_handover.cdi_seal,
- Self::Fake(fake) => &fake.cdi_values.cdi_seal,
- };
+ let mut key = ZVec::new(key_length)?;
let salt = &[];
- derive_sealing_key(cdi_seal, salt, identifier, 32)
+ derive_sealing_key(self.dice_artifacts(), salt, identifier, &mut key)?;
+ Ok(key)
}
pub fn derive(
@@ -122,25 +126,21 @@
if debug { DiceMode::kDiceModeDebug } else { DiceMode::kDiceModeNormal },
hidden,
);
- let (cdi_attest, cdi_seal, bcc) = match &self {
- Self::Real { bcc_handover, .. } => (
- bcc_handover.cdi_attest,
- bcc_handover.cdi_seal,
- bcc_handover.bcc.ok_or_else(|| anyhow!("bcc is none"))?,
- ),
- Self::Fake(fake) => {
- (&fake.cdi_values.cdi_attest, &fake.cdi_values.cdi_seal, fake.bcc.as_slice())
- }
- };
- let dice_artifacts = retry_bcc_main_flow(cdi_attest, cdi_seal, bcc, &input_values)
- .context("DICE derive from driver")?;
+ let current_dice_artifacts = self.dice_artifacts();
+ let next_dice_artifacts = retry_bcc_main_flow(
+ current_dice_artifacts.cdi_attest(),
+ current_dice_artifacts.cdi_seal(),
+ current_dice_artifacts.bcc().ok_or_else(|| anyhow!("bcc is none"))?,
+ &input_values,
+ )
+ .context("DICE derive from driver")?;
if let Self::Real { driver_path, .. } = &self {
// Writing to the device wipes the artifacts. The string is ignored by the driver but
// included for documentation.
fs::write(driver_path, "wipe")
.map_err(|err| Error::new(err).context("Wiping driver"))?;
}
- Ok(dice_artifacts)
+ Ok(next_dice_artifacts)
}
}
diff --git a/microdroid_manager/src/instance.rs b/microdroid_manager/src/instance.rs
index 96e9360..6900ea5 100644
--- a/microdroid_manager/src/instance.rs
+++ b/microdroid_manager/src/instance.rs
@@ -142,9 +142,9 @@
self.file.read_exact(&mut header)?;
// Decrypt and authenticate the data (along with the header).
- let key = dice.get_sealing_key(INSTANCE_KEY_IDENTIFIER)?;
- let plaintext =
- decrypt_aead(Cipher::aes_256_gcm(), &key, Some(&nonce), &header, &data, &tag)?;
+ let cipher = Cipher::aes_256_gcm();
+ let key = dice.get_sealing_key(INSTANCE_KEY_IDENTIFIER, cipher.key_len())?;
+ let plaintext = decrypt_aead(cipher, &key, Some(&nonce), &header, &data, &tag)?;
let microdroid_data = serde_cbor::from_slice(plaintext.as_slice())?;
Ok(Some(microdroid_data))
@@ -188,10 +188,10 @@
self.file.write_all(nonce.as_ref())?;
// Then encrypt and sign the data.
- let key = dice.get_sealing_key(INSTANCE_KEY_IDENTIFIER)?;
+ let cipher = Cipher::aes_256_gcm();
+ let key = dice.get_sealing_key(INSTANCE_KEY_IDENTIFIER, cipher.key_len())?;
let mut tag = [0; AES_256_GCM_TAG_LENGTH];
- let ciphertext =
- encrypt_aead(Cipher::aes_256_gcm(), &key, Some(&nonce), &header, &data, &mut tag)?;
+ let ciphertext = encrypt_aead(cipher, &key, Some(&nonce), &header, &data, &mut tag)?;
// Persist the encrypted payload data and the tag.
self.file.write_all(&ciphertext)?;
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index 7ca0d3c..1148c31 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -40,6 +40,7 @@
use itertools::sorted;
use libc::VMADDR_CID_HOST;
use log::{error, info, warn};
+use keystore2_crypto::ZVec;
use microdroid_metadata::{write_metadata, Metadata, PayloadMetadata};
use microdroid_payload_config::{OsConfig, Task, TaskType, VmPayloadConfig};
use nix::fcntl::{fcntl, F_SETFD, FdFlag};
@@ -917,12 +918,8 @@
0x6F, 0xB3, 0xF9, 0x40, 0xCE, 0xDD, 0x99, 0x40, 0xAA, 0xA7, 0x0E, 0x92, 0x73, 0x90, 0x86,
0x4A, 0x75,
];
- let key = derive_sealing_key(
- &dice_artifacts.cdi_values.cdi_seal,
- &salt,
- ENCRYPTEDSTORE_KEY_IDENTIFIER.as_bytes(),
- ENCRYPTEDSTORE_KEYSIZE,
- )?;
+ let mut key = ZVec::new(ENCRYPTEDSTORE_KEYSIZE)?;
+ derive_sealing_key(dice_artifacts, &salt, ENCRYPTEDSTORE_KEY_IDENTIFIER.as_bytes(), &mut key)?;
let mut cmd = Command::new(ENCRYPTEDSTORE_BIN);
cmd.arg("--blkdevice")
diff --git a/microdroid_manager/src/vm_payload_service.rs b/microdroid_manager/src/vm_payload_service.rs
index ac8f60a..96f51f0 100644
--- a/microdroid_manager/src/vm_payload_service.rs
+++ b/microdroid_manager/src/vm_payload_service.rs
@@ -14,15 +14,14 @@
//! Implementation of the AIDL interface `IVmPayloadService`.
+use crate::dice::derive_sealing_key;
use android_system_virtualization_payload::aidl::android::system::virtualization::payload::IVmPayloadService::{
BnVmPayloadService, IVmPayloadService, VM_PAYLOAD_SERVICE_SOCKET_NAME};
use android_system_virtualmachineservice::aidl::android::system::virtualmachineservice::IVirtualMachineService::IVirtualMachineService;
use anyhow::Result;
use binder::{Interface, BinderFeatures, ExceptionCode, Status, Strong};
-use diced_open_dice::OwnedDiceArtifacts;
+use diced_open_dice::{DiceArtifacts, OwnedDiceArtifacts};
use log::{error, info};
-use openssl::hkdf::hkdf;
-use openssl::md::Md;
use rpcbinder::RpcServer;
/// Implementation of `IVmPayloadService`.
@@ -48,22 +47,25 @@
0xB7, 0xA8, 0x43, 0x92,
];
let mut secret = vec![0; size.try_into().unwrap()];
- hkdf(&mut secret, Md::sha256(), &self.dice.cdi_values.cdi_seal, &salt, identifier)
- .map_err(|e| {
- error!("Failed to derive VM instance secret: {:?}", e);
- Status::new_service_specific_error(-1, None)
- })?;
+ derive_sealing_key(&self.dice, &salt, identifier, &mut secret).map_err(|e| {
+ error!("Failed to derive VM instance secret: {:?}", e);
+ Status::new_service_specific_error(-1, None)
+ })?;
Ok(secret)
}
fn getDiceAttestationChain(&self) -> binder::Result<Vec<u8>> {
self.check_restricted_apis_allowed()?;
- Ok(self.dice.bcc.clone())
+ if let Some(bcc) = self.dice.bcc() {
+ Ok(bcc.to_vec())
+ } else {
+ Err(Status::new_exception_str(ExceptionCode::ILLEGAL_STATE, Some("bcc is none")))
+ }
}
fn getDiceAttestationCdi(&self) -> binder::Result<Vec<u8>> {
self.check_restricted_apis_allowed()?;
- Ok(self.dice.cdi_values.cdi_attest.to_vec())
+ Ok(self.dice.cdi_attest().to_vec())
}
}