Revert "[attestation] Validate client VM's Microdroid kernel in service VM"
This reverts commit 73e72268769c51a9dd0f62e85dc3288a9e7202e2.
Reason for revert: Checking if reverting this CL fixes build breakage http://b/315936000
Change-Id: I21c9d089b54d3d40f8b5077646351695850545cc
diff --git a/service_vm/requests/Android.bp b/service_vm/requests/Android.bp
index 57da012..52b54b4 100644
--- a/service_vm/requests/Android.bp
+++ b/service_vm/requests/Android.bp
@@ -24,7 +24,6 @@
"libder_nostd",
"libdiced_open_dice_nostd",
"liblog_rust_nostd",
- "libmicrodroid_kernel_hashes",
"libserde_nostd",
"libservice_vm_comm_nostd",
"libspki_nostd",
diff --git a/service_vm/requests/src/client_vm.rs b/service_vm/requests/src/client_vm.rs
index 5b4735d..cfdac2d 100644
--- a/service_vm/requests/src/client_vm.rs
+++ b/service_vm/requests/src/client_vm.rs
@@ -16,20 +16,15 @@
//! client VM.
use crate::cert;
-use crate::dice::{
- validate_client_vm_dice_chain_prefix_match, ClientVmDiceChain, DiceChainEntryPayload,
-};
+use crate::dice::{validate_client_vm_dice_chain_prefix_match, ClientVmDiceChain};
use crate::keyblob::decrypt_private_key;
use alloc::vec::Vec;
-use bssl_avf::{rand_bytes, sha256, Digester, EcKey, PKey};
-use cbor_util::value_to_array;
-use ciborium::value::Value;
+use bssl_avf::{rand_bytes, sha256, EcKey, PKey};
use core::result;
-use coset::{AsCborValue, CborSerializable, CoseSign, CoseSign1};
+use coset::{CborSerializable, CoseSign};
use der::{Decode, Encode};
-use diced_open_dice::{DiceArtifacts, HASH_SIZE};
+use diced_open_dice::DiceArtifacts;
use log::error;
-use microdroid_kernel_hashes::{INITRD_DEBUG_HASH, INITRD_NORMAL_HASH, KERNEL_HASH};
use service_vm_comm::{ClientVmAttestationParams, Csr, CsrPayload, RequestProcessingError};
use x509_cert::{certificate::Certificate, name::Name};
@@ -52,22 +47,13 @@
// Validates the prefix of the Client VM DICE chain in the CSR.
let service_vm_dice_chain =
dice_artifacts.bcc().ok_or(RequestProcessingError::MissingDiceChain)?;
- let service_vm_dice_chain =
- value_to_array(Value::from_slice(service_vm_dice_chain)?, "service_vm_dice_chain")?;
let client_vm_dice_chain =
- value_to_array(Value::from_slice(&csr.dice_cert_chain)?, "client_vm_dice_chain")?;
- validate_client_vm_dice_chain_prefix_match(&client_vm_dice_chain, &service_vm_dice_chain)?;
+ validate_client_vm_dice_chain_prefix_match(&csr.dice_cert_chain, service_vm_dice_chain)?;
// Validates the signatures in the Client VM DICE chain and extracts the partially decoded
// DiceChainEntryPayloads.
let client_vm_dice_chain =
ClientVmDiceChain::validate_signatures_and_parse_dice_chain(client_vm_dice_chain)?;
- // The last entry in the service VM DICE chain describes the service VM, which should
- // be signed with the same key as the kernel image.
- let service_vm_entry = service_vm_dice_chain.last().unwrap();
- validate_kernel_authority_hash(client_vm_dice_chain.microdroid_kernel(), service_vm_entry)?;
- validate_kernel_code_hash(&client_vm_dice_chain)?;
-
// AAD is empty as defined in service_vm/comm/client_vm_csr.cddl.
let aad = &[];
@@ -135,60 +121,3 @@
let digest = sha256(message)?;
key.ecdsa_sign(&digest)
}
-
-/// Validates that the authority hash of the Microdroid kernel in the Client VM DICE chain
-/// matches the authority hash of the service VM entry in the service VM DICE chain, because
-/// the Microdroid kernel is signed with the same key as the one used for the service VM.
-fn validate_kernel_authority_hash(
- kernel: &DiceChainEntryPayload,
- service_vm_entry: &Value,
-) -> Result<()> {
- if expected_kernel_authority_hash(service_vm_entry)? == kernel.authority_hash {
- Ok(())
- } else {
- error!("The authority hash of the Microdroid kernel does not match the expected value");
- Err(RequestProcessingError::InvalidDiceChain)
- }
-}
-
-/// Validates that the kernel code hash in the Client VM DICE chain matches the code hashes
-/// embedded during the build time.
-fn validate_kernel_code_hash(dice_chain: &ClientVmDiceChain) -> Result<()> {
- let kernel = dice_chain.microdroid_kernel();
- if expected_kernel_code_hash_normal()? == kernel.code_hash {
- return Ok(());
- }
- if expected_kernel_code_hash_debug()? == kernel.code_hash {
- if dice_chain.all_entries_are_secure() {
- error!("The Microdroid kernel has debug initrd but the DICE chain is secure");
- return Err(RequestProcessingError::InvalidDiceChain);
- }
- return Ok(());
- }
- error!("The kernel code hash in the Client VM DICE chain does not match any expected values");
- Err(RequestProcessingError::InvalidDiceChain)
-}
-
-fn expected_kernel_code_hash_normal() -> bssl_avf::Result<Vec<u8>> {
- let mut code_hash = [0u8; 64];
- code_hash[0..32].copy_from_slice(KERNEL_HASH);
- code_hash[32..].copy_from_slice(INITRD_NORMAL_HASH);
- Digester::sha512().digest(&code_hash)
-}
-
-fn expected_kernel_code_hash_debug() -> bssl_avf::Result<Vec<u8>> {
- let mut code_hash = [0u8; 64];
- code_hash[0..32].copy_from_slice(KERNEL_HASH);
- code_hash[32..].copy_from_slice(INITRD_DEBUG_HASH);
- Digester::sha512().digest(&code_hash)
-}
-
-fn expected_kernel_authority_hash(service_vm_entry: &Value) -> Result<[u8; HASH_SIZE]> {
- let cose_sign1 = CoseSign1::from_cbor_value(service_vm_entry.clone())?;
- let payload = cose_sign1.payload.ok_or_else(|| {
- error!("No payload found in the service VM DICE chain entry");
- RequestProcessingError::InternalError
- })?;
- let service_vm = DiceChainEntryPayload::from_slice(&payload)?;
- Ok(service_vm.authority_hash)
-}
diff --git a/service_vm/requests/src/dice.rs b/service_vm/requests/src/dice.rs
index 8c804da..557b678 100644
--- a/service_vm/requests/src/dice.rs
+++ b/service_vm/requests/src/dice.rs
@@ -126,7 +126,7 @@
Ok(())
}
- pub(crate) fn microdroid_kernel(&self) -> &DiceChainEntryPayload {
+ fn microdroid_kernel(&self) -> &DiceChainEntryPayload {
&self.payloads[self.payloads.len() - 2]
}
@@ -147,11 +147,15 @@
/// Validates that the `client_vm_dice_chain` matches the `service_vm_dice_chain` up to the pvmfw
/// entry.
///
-/// Returns `Ok(())` if the verification succeeds.
+/// Returns a CBOR value array of the client VM's DICE chain if the verification succeeds.
pub(crate) fn validate_client_vm_dice_chain_prefix_match(
- client_vm_dice_chain: &[Value],
- service_vm_dice_chain: &[Value],
-) -> Result<()> {
+ client_vm_dice_chain: &[u8],
+ service_vm_dice_chain: &[u8],
+) -> Result<Vec<Value>> {
+ let client_vm_dice_chain =
+ value_to_array(Value::from_slice(client_vm_dice_chain)?, "client_vm_dice_chain")?;
+ let service_vm_dice_chain =
+ value_to_array(Value::from_slice(service_vm_dice_chain)?, "service_vm_dice_chain")?;
if service_vm_dice_chain.len() < 3 {
// The service VM's DICE chain must contain the root key and at least two other entries
// that describe:
@@ -176,7 +180,7 @@
);
return Err(RequestProcessingError::InvalidDiceChain);
}
- Ok(())
+ Ok(client_vm_dice_chain)
}
#[derive(Debug, Clone)]
@@ -204,8 +208,11 @@
#[allow(dead_code)]
subject_public_key: PublicKey,
mode: DiceMode,
- pub(crate) code_hash: [u8; HASH_SIZE],
- pub(crate) authority_hash: [u8; HASH_SIZE],
+ /// TODO(b/271275206): Verify Microdroid kernel authority and code hashes.
+ #[allow(dead_code)]
+ code_hash: [u8; HASH_SIZE],
+ #[allow(dead_code)]
+ authority_hash: [u8; HASH_SIZE],
config_descriptor: ConfigDescriptor,
}
@@ -223,42 +230,42 @@
error!("No payload found in the DICE chain entry");
RequestProcessingError::InvalidDiceChain
})?;
- Self::from_slice(&payload)
- }
-
- pub(crate) fn from_slice(data: &[u8]) -> Result<Self> {
- let entries = value_to_map(Value::from_slice(data)?, "DiceChainEntryPayload")?;
- let mut builder = PayloadBuilder::default();
- for (key, value) in entries.into_iter() {
- let key: i64 = value_to_num(key, "DiceChainEntryPayload key")?;
- match key {
- SUBJECT_PUBLIC_KEY => {
- let subject_public_key = value_to_bytes(value, "subject_public_key")?;
- let subject_public_key =
- CoseKey::from_slice(&subject_public_key)?.try_into()?;
- builder.subject_public_key(subject_public_key)?;
- }
- MODE => builder.mode(to_mode(value)?)?,
- CODE_HASH => {
- let code_hash = value_to_byte_array(value, "DiceChainEntryPayload code_hash")?;
- builder.code_hash(code_hash)?;
- }
- AUTHORITY_HASH => {
- let authority_hash =
- value_to_byte_array(value, "DiceChainEntryPayload authority_hash")?;
- builder.authority_hash(authority_hash)?;
- }
- CONFIG_DESC => {
- let config_descriptor = value_to_bytes(value, "config_descriptor")?;
- let config_descriptor = ConfigDescriptor::from_slice(&config_descriptor)?;
- builder.config_descriptor(config_descriptor)?;
- }
- _ => {}
- }
- }
- builder.build()
+ let entries = value_to_map(Value::from_slice(&payload)?, "DiceChainEntryPayload")?;
+ build_payload(entries)
}
}
+
+fn build_payload(entries: Vec<(Value, Value)>) -> Result<DiceChainEntryPayload> {
+ let mut builder = PayloadBuilder::default();
+ for (key, value) in entries.into_iter() {
+ let key: i64 = value_to_num(key, "DiceChainEntryPayload key")?;
+ match key {
+ SUBJECT_PUBLIC_KEY => {
+ let subject_public_key = value_to_bytes(value, "subject_public_key")?;
+ let subject_public_key = CoseKey::from_slice(&subject_public_key)?.try_into()?;
+ builder.subject_public_key(subject_public_key)?;
+ }
+ MODE => builder.mode(to_mode(value)?)?,
+ CODE_HASH => {
+ let code_hash = value_to_byte_array(value, "DiceChainEntryPayload code_hash")?;
+ builder.code_hash(code_hash)?;
+ }
+ AUTHORITY_HASH => {
+ let authority_hash =
+ value_to_byte_array(value, "DiceChainEntryPayload authority_hash")?;
+ builder.authority_hash(authority_hash)?;
+ }
+ CONFIG_DESC => {
+ let config_descriptor = value_to_bytes(value, "config_descriptor")?;
+ let config_descriptor = ConfigDescriptor::from_slice(&config_descriptor)?;
+ builder.config_descriptor(config_descriptor)?;
+ }
+ _ => {}
+ }
+ }
+ builder.build()
+}
+
/// Represents a partially decoded `ConfigurationDescriptor`.
///
/// The whole `ConfigurationDescriptor` is defined in: