diff options
author | Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> | 2024-05-14 19:28:48 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-05-14 19:28:48 +0000 |
commit | a6552305233a2c32dfafea4715b01388e7af074d (patch) | |
tree | 408fed810fde5a0f009fa868314e2c47dc42be4f | |
parent | 3ff0458db68b2ddd1d6e309088eb1dac19666ebd (diff) | |
parent | 957d597fad6f7aecb8ddd108b027da9814296e35 (diff) | |
download | security-main.tar.gz |
* changes:
[hwtrust] Add avf field to CSR device info enums
Revert "[hwtrust] Add avf field placeholder in CSR device info parser"
-rw-r--r-- | remote_provisioning/hwtrust/src/cbor/rkp/csr.rs | 4 | ||||
-rw-r--r-- | remote_provisioning/hwtrust/src/cbor/rkp/device_info.rs | 137 | ||||
-rw-r--r-- | remote_provisioning/hwtrust/src/rkp/device_info.rs | 20 |
3 files changed, 131 insertions, 30 deletions
diff --git a/remote_provisioning/hwtrust/src/cbor/rkp/csr.rs b/remote_provisioning/hwtrust/src/cbor/rkp/csr.rs index a93b200..e621756 100644 --- a/remote_provisioning/hwtrust/src/cbor/rkp/csr.rs +++ b/remote_provisioning/hwtrust/src/cbor/rkp/csr.rs @@ -226,8 +226,8 @@ pub(crate) mod testutil { product: "pixel".to_string(), model: "model".to_string(), device: "device".to_string(), - vb_state: Some(DeviceInfoVbState::Green), - bootloader_state: Some(DeviceInfoBootloaderState::Locked), + vb_state: DeviceInfoVbState::Green, + bootloader_state: DeviceInfoBootloaderState::Locked, vbmeta_digest: b"\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff".to_vec(), os_version: Some("12".to_string()), system_patch_level: 20221025, diff --git a/remote_provisioning/hwtrust/src/cbor/rkp/device_info.rs b/remote_provisioning/hwtrust/src/cbor/rkp/device_info.rs index 4b26a48..09b2eca 100644 --- a/remote_provisioning/hwtrust/src/cbor/rkp/device_info.rs +++ b/remote_provisioning/hwtrust/src/cbor/rkp/device_info.rs @@ -1,6 +1,8 @@ use crate::cbor::field_value::FieldValue; -use crate::rkp::DeviceInfo; -use anyhow::{bail, Context, Result}; +use crate::rkp::{ + DeviceInfo, DeviceInfoBootloaderState, DeviceInfoSecurityLevel, DeviceInfoVbState, +}; +use anyhow::{bail, ensure, Context, Result}; use ciborium::value::Value; impl DeviceInfo { @@ -61,23 +63,15 @@ impl DeviceInfo { Some(s) => Some(s.as_str().try_into()?), None => None, }; - let bootloader_state = match bootloader_state.into_optional_string()? { - Some(s) => Some(s.as_str().try_into()?), - None => None, - }; - let vb_state = match vb_state.into_optional_string()? { - Some(s) => Some(s.as_str().try_into()?), - None => None, - }; - Ok(DeviceInfo { + let info = DeviceInfo { brand: brand.into_string()?, manufacturer: manufacturer.into_string()?, product: product.into_string()?, model: model.into_string()?, device: device.into_string()?, - vb_state, - bootloader_state, + vb_state: vb_state.into_string()?.as_str().try_into()?, + bootloader_state: bootloader_state.into_string()?.as_str().try_into()?, vbmeta_digest: vbmeta_digest.into_bytes()?, os_version: os_version.into_optional_string()?, system_patch_level: system_patch_level.into_u32()?, @@ -86,16 +80,45 @@ impl DeviceInfo { security_level, fused: fused.into_bool()?, version: version.try_into()?, - }) + }; + info.validate_avf_fields()?; + Ok(info) + } + + fn validate_avf_fields(&self) -> Result<()> { + if Some(DeviceInfoSecurityLevel::Avf) == self.security_level { + ensure!( + self.bootloader_state == DeviceInfoBootloaderState::Avf + && self.vb_state == DeviceInfoVbState::Avf + && self.brand == "aosp-avf" + && self.device == "avf" + && self.model == "avf" + && self.manufacturer == "aosp-avf" + && self.product == "avf", + "AVF security level requires AVF fields. Got: {:?}", + self + ); + } else { + ensure!( + self.bootloader_state != DeviceInfoBootloaderState::Avf + && self.vb_state != DeviceInfoVbState::Avf + && self.brand != "aosp-avf" + && self.device != "avf" + && self.model != "avf" + && self.manufacturer != "aosp-avf" + && self.product != "avf", + "Non-AVF security level requires non-AVF fields. Got: {:?}", + self + ); + } + Ok(()) } } #[cfg(test)] mod tests { use super::*; - use crate::rkp::{ - DeviceInfoBootloaderState, DeviceInfoSecurityLevel, DeviceInfoVbState, DeviceInfoVersion, - }; + use crate::rkp::DeviceInfoVersion; #[test] fn device_info_from_cbor_values_optional_os_version() { @@ -121,8 +144,8 @@ mod tests { product: "phone".to_string(), model: "the best one".to_string(), device: "really the best".to_string(), - vb_state: Some(DeviceInfoVbState::Green), - bootloader_state: Some(DeviceInfoBootloaderState::Locked), + vb_state: DeviceInfoVbState::Green, + bootloader_state: DeviceInfoBootloaderState::Locked, vbmeta_digest: b"abcdefg".to_vec(), os_version: Some("dessert".to_string()), system_patch_level: 303010, @@ -145,8 +168,8 @@ mod tests { product: "phone".to_string(), model: "the best one".to_string(), device: "really the best".to_string(), - vb_state: Some(DeviceInfoVbState::Green), - bootloader_state: Some(DeviceInfoBootloaderState::Locked), + vb_state: DeviceInfoVbState::Green, + bootloader_state: DeviceInfoBootloaderState::Locked, vbmeta_digest: b"abcdefg".to_vec(), os_version: Some("dessert".to_string()), system_patch_level: 303010, @@ -201,6 +224,59 @@ mod tests { assert!(err.to_string().contains("may be set only once")); } + #[test] + fn device_info_from_cbor_values_non_avf_security_level_has_avf_vb_state() { + let mut values = get_valid_values_filtered(|x| x != "vb_state"); + values.push(("vb_state".into(), "avf".into())); + + let err = DeviceInfo::from_cbor_values(values, None).unwrap_err(); + assert!(err.to_string().contains("Non-AVF security level"), "{err:?}"); + } + + #[test] + fn device_info_from_cbor_values_non_avf_security_level_has_avf_bootloader_state() { + let mut values = get_valid_values_filtered(|x| x != "bootloader_state"); + values.push(("bootloader_state".into(), "avf".into())); + + let err = DeviceInfo::from_cbor_values(values, None).unwrap_err(); + assert!(err.to_string().contains("Non-AVF security level"), "{err:?}"); + } + + #[test] + fn device_info_from_cbor_values_avf_security_level_has_non_avf_vb_state() { + let values: Vec<(Value, Value)> = get_valid_avf_values() + .into_iter() + .filter(|(k, _v)| k.as_text().unwrap() != "vb_state") + .chain(vec![("vb_state".into(), "green".into())]) + .collect(); + let err = DeviceInfo::from_cbor_values(values, Some(3)).unwrap_err(); + assert!(err.to_string().contains("AVF security level requires AVF fields"), "{err:?}"); + } + + #[test] + fn device_info_from_cbor_values_avf_security_level_has_avf_fields() { + let values = get_valid_avf_values(); + let actual = DeviceInfo::from_cbor_values(values, Some(3)).unwrap(); + let expected = DeviceInfo { + brand: "aosp-avf".to_string(), + manufacturer: "aosp-avf".to_string(), + product: "avf".to_string(), + model: "avf".to_string(), + device: "avf".to_string(), + vb_state: DeviceInfoVbState::Avf, + bootloader_state: DeviceInfoBootloaderState::Avf, + vbmeta_digest: b"abcdefg".to_vec(), + os_version: Some("dessert".to_string()), + system_patch_level: 303010, + boot_patch_level: 30300102, + vendor_patch_level: 30300304, + security_level: Some(DeviceInfoSecurityLevel::Avf), + fused: true, + version: DeviceInfoVersion::V3, + }; + assert_eq!(expected, actual); + } + fn get_valid_values() -> Vec<(Value, Value)> { vec![ ("brand".into(), "generic".into()), @@ -221,6 +297,25 @@ mod tests { ] } + fn get_valid_avf_values() -> Vec<(Value, Value)> { + vec![ + ("brand".into(), "aosp-avf".into()), + ("manufacturer".into(), "aosp-avf".into()), + ("product".into(), "avf".into()), + ("model".into(), "avf".into()), + ("device".into(), "avf".into()), + ("vb_state".into(), "avf".into()), + ("bootloader_state".into(), "avf".into()), + ("vbmeta_digest".into(), b"abcdefg".as_ref().into()), + ("os_version".into(), "dessert".into()), + ("system_patch_level".into(), 303010.into()), + ("boot_patch_level".into(), 30300102.into()), + ("vendor_patch_level".into(), 30300304.into()), + ("security_level".into(), "avf".into()), + ("fused".into(), 1.into()), + ] + } + fn get_valid_values_filtered<F: Fn(&str) -> bool>(filter: F) -> Vec<(Value, Value)> { get_valid_values().into_iter().filter(|x| filter(x.0.as_text().unwrap())).collect() } diff --git a/remote_provisioning/hwtrust/src/rkp/device_info.rs b/remote_provisioning/hwtrust/src/rkp/device_info.rs index a6fce2b..c99f74d 100644 --- a/remote_provisioning/hwtrust/src/rkp/device_info.rs +++ b/remote_provisioning/hwtrust/src/rkp/device_info.rs @@ -22,9 +22,9 @@ pub struct DeviceInfo { /// the same underlying device. pub device: String, /// Verified boot state. - pub vb_state: Option<DeviceInfoVbState>, + pub vb_state: DeviceInfoVbState, /// Whether the bootloader is locked or not. - pub bootloader_state: Option<DeviceInfoBootloaderState>, + pub bootloader_state: DeviceInfoBootloaderState, /// Digest of the verified boot metadata structures. pub vbmeta_digest: Vec<u8>, /// Partner-defined operating system version. @@ -45,9 +45,6 @@ impl fmt::Debug for DeviceInfo { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let security_level: &dyn fmt::Debug = self.security_level.as_ref().map_or(&"<none>", |s| s); let os_version: &dyn fmt::Debug = self.os_version.as_ref().map_or(&"<none>", |v| v); - let bootloader_state: &dyn fmt::Debug = - self.bootloader_state.as_ref().map_or(&"<none>", |v| v); - let vb_state: &dyn fmt::Debug = self.vb_state.as_ref().map_or(&"<none>", |v| v); fmt.debug_struct("DeviceInfo") .field("version", &self.version) @@ -56,8 +53,8 @@ impl fmt::Debug for DeviceInfo { .field("product", &self.product) .field("model", &self.model) .field("device", &self.device) - .field("vb_state", vb_state) - .field("bootloader_state", bootloader_state) + .field("vb_state", &self.vb_state) + .field("bootloader_state", &self.bootloader_state) .field("vbmeta_digest", &hex::encode(&self.vbmeta_digest)) .field("os_version", os_version) .field("system_patch_level", &self.system_patch_level) @@ -76,6 +73,8 @@ pub enum DeviceInfoBootloaderState { Locked, /// The bootloader will load arbitrary images. Unlocked, + /// This field is a placeholder for the AVF backend. + Avf, } impl TryFrom<&str> for DeviceInfoBootloaderState { @@ -85,6 +84,7 @@ impl TryFrom<&str> for DeviceInfoBootloaderState { match s.to_ascii_lowercase().as_str() { "locked" => Ok(Self::Locked), "unlocked" => Ok(Self::Unlocked), + "avf" => Ok(Self::Avf), _ => Err(anyhow!("Invalid bootloader state: `{s}`")), } } @@ -99,6 +99,8 @@ pub enum DeviceInfoVbState { Yellow, /// The bootloader is unlocked, and no guarantees of image integrity are available. Orange, + /// This field is a placeholder for the AVF backend. + Avf, } impl TryFrom<&str> for DeviceInfoVbState { @@ -109,6 +111,7 @@ impl TryFrom<&str> for DeviceInfoVbState { "green" => Ok(Self::Green), "yellow" => Ok(Self::Yellow), "orange" => Ok(Self::Orange), + "avf" => Ok(Self::Avf), _ => Err(anyhow!("Invalid VB state: `{s}`")), } } @@ -142,6 +145,8 @@ pub enum DeviceInfoSecurityLevel { Tee, /// KeyMint's backend runs in a Secure Element. StrongBox, + /// AVF's backend. + Avf, } impl TryFrom<&str> for DeviceInfoSecurityLevel { @@ -151,6 +156,7 @@ impl TryFrom<&str> for DeviceInfoSecurityLevel { match s.to_ascii_lowercase().as_str() { "strongbox" => Ok(Self::StrongBox), "tee" => Ok(Self::Tee), + "avf" => Ok(Self::Avf), _ => Err(anyhow!("Invalid security level: `{s}`")), } } |