1 use anyhow::anyhow; 2 use hex; 3 use std::fmt; 4 5 #[non_exhaustive] 6 #[derive(Clone, Eq, PartialEq)] 7 /// Describes a device that is registered with the RKP backend. This implementation contains fields 8 /// common to all versions defined in DeviceInfo.aidl. 9 pub struct DeviceInfo { 10 /// Version of this data structure. 11 pub version: DeviceInfoVersion, 12 /// The device's marketed brand. 13 pub brand: String, 14 /// The device maker. 15 pub manufacturer: String, 16 /// A variant of a device. Multiple products may be built off the same device. 17 pub product: String, 18 /// End-user-visible name of the product. 19 pub model: String, 20 /// The high-level industrial design. What makes up a "device" is generally hardware 21 /// characteristics like form factor, cpu, etc. Multiple products/models may be shipped on 22 /// the same underlying device. 23 pub device: String, 24 /// Verified boot state. 25 pub vb_state: DeviceInfoVbState, 26 /// Whether the bootloader is locked or not. 27 pub bootloader_state: DeviceInfoBootloaderState, 28 /// Digest of the verified boot metadata structures. 29 pub vbmeta_digest: Vec<u8>, 30 /// Partner-defined operating system version. 31 pub os_version: Option<String>, 32 /// Patch level of the system partition. 33 pub system_patch_level: u32, 34 /// Patch level of the kernel. 35 pub boot_patch_level: u32, 36 /// Patch level of the vendor partition. 37 pub vendor_patch_level: u32, 38 /// If backed by KeyMint, this is the security level of the HAL. 39 pub security_level: Option<DeviceInfoSecurityLevel>, 40 /// Whether or not secure boot is enforced/required by the SoC. 41 pub fused: bool, 42 } 43 44 impl fmt::Debug for DeviceInfo { fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result45 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { 46 let security_level: &dyn fmt::Debug = self.security_level.as_ref().map_or(&"<none>", |s| s); 47 let os_version: &dyn fmt::Debug = self.os_version.as_ref().map_or(&"<none>", |v| v); 48 49 fmt.debug_struct("DeviceInfo") 50 .field("version", &self.version) 51 .field("brand", &self.brand) 52 .field("manufacturer", &self.manufacturer) 53 .field("product", &self.product) 54 .field("model", &self.model) 55 .field("device", &self.device) 56 .field("vb_state", &self.vb_state) 57 .field("bootloader_state", &self.bootloader_state) 58 .field("vbmeta_digest", &hex::encode(&self.vbmeta_digest)) 59 .field("os_version", os_version) 60 .field("system_patch_level", &self.system_patch_level) 61 .field("boot_patch_level", &self.boot_patch_level) 62 .field("vendor_patch_level", &self.vendor_patch_level) 63 .field("security_level", security_level) 64 .field("fused", &self.fused) 65 .finish() 66 } 67 } 68 69 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 70 /// Whether the bootloader allows unsigned or third-party-signed images. 71 pub enum DeviceInfoBootloaderState { 72 /// The bootloader is locked, and will only allow signed images. 73 Locked, 74 /// The bootloader will load arbitrary images. 75 Unlocked, 76 /// This field is a placeholder for the AVF backend. 77 Avf, 78 } 79 80 impl TryFrom<&str> for DeviceInfoBootloaderState { 81 type Error = anyhow::Error; 82 try_from(s: &str) -> Result<Self, Self::Error>83 fn try_from(s: &str) -> Result<Self, Self::Error> { 84 match s.to_ascii_lowercase().as_str() { 85 "locked" => Ok(Self::Locked), 86 "unlocked" => Ok(Self::Unlocked), 87 "avf" => Ok(Self::Avf), 88 _ => Err(anyhow!("Invalid bootloader state: `{s}`")), 89 } 90 } 91 } 92 93 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 94 /// State of the verified boot validation. 95 pub enum DeviceInfoVbState { 96 /// The device booted an OEM-signed image. 97 Green, 98 /// The device booted an image signed by a key set by the end user. 99 Yellow, 100 /// The bootloader is unlocked, and no guarantees of image integrity are available. 101 Orange, 102 /// This field is a placeholder for the AVF backend. 103 Avf, 104 } 105 106 impl TryFrom<&str> for DeviceInfoVbState { 107 type Error = anyhow::Error; 108 try_from(s: &str) -> Result<Self, Self::Error>109 fn try_from(s: &str) -> Result<Self, Self::Error> { 110 match s.to_ascii_lowercase().as_str() { 111 "green" => Ok(Self::Green), 112 "yellow" => Ok(Self::Yellow), 113 "orange" => Ok(Self::Orange), 114 "avf" => Ok(Self::Avf), 115 _ => Err(anyhow!("Invalid VB state: `{s}`")), 116 } 117 } 118 } 119 120 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 121 /// The version of the DeviceInfo structure, which may updated with HAL changes. 122 pub enum DeviceInfoVersion { 123 /// First supported version. Prior to this (V1), almost all fields were optional. 124 V2, 125 /// Explicit version removed from the CBOR. Otherwise identical to V2. 126 V3, 127 } 128 129 impl TryFrom<u32> for DeviceInfoVersion { 130 type Error = anyhow::Error; 131 try_from(i: u32) -> Result<Self, Self::Error>132 fn try_from(i: u32) -> Result<Self, Self::Error> { 133 match i { 134 2 => Ok(Self::V2), 135 3 => Ok(Self::V3), 136 _ => Err(anyhow!("Invalid version: `{i}`")), 137 } 138 } 139 } 140 141 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 142 /// This corresponds with where KeyMint's backing service lives: a TEE or in a separate SE. 143 pub enum DeviceInfoSecurityLevel { 144 /// KeyMint's backend runs in a Trusted Execution Environment. 145 Tee, 146 /// KeyMint's backend runs in a Secure Element. 147 StrongBox, 148 /// AVF's backend. 149 Avf, 150 } 151 152 impl TryFrom<&str> for DeviceInfoSecurityLevel { 153 type Error = anyhow::Error; 154 try_from(s: &str) -> Result<Self, Self::Error>155 fn try_from(s: &str) -> Result<Self, Self::Error> { 156 match s.to_ascii_lowercase().as_str() { 157 "strongbox" => Ok(Self::StrongBox), 158 "tee" => Ok(Self::Tee), 159 "avf" => Ok(Self::Avf), 160 _ => Err(anyhow!("Invalid security level: `{s}`")), 161 } 162 } 163 } 164 165 #[cfg(test)] 166 mod tests { 167 use super::*; 168 169 #[test] bootloader_state_from_string()170 fn bootloader_state_from_string() { 171 assert_eq!( 172 DeviceInfoBootloaderState::try_from("LoCkEd").unwrap(), 173 DeviceInfoBootloaderState::Locked 174 ); 175 assert_eq!( 176 DeviceInfoBootloaderState::try_from("UNLocked").unwrap(), 177 DeviceInfoBootloaderState::Unlocked 178 ); 179 DeviceInfoBootloaderState::try_from("nope").unwrap_err(); 180 } 181 182 #[test] vb_state_from_string()183 fn vb_state_from_string() { 184 assert_eq!(DeviceInfoVbState::try_from("greEN").unwrap(), DeviceInfoVbState::Green); 185 assert_eq!(DeviceInfoVbState::try_from("YeLLoW").unwrap(), DeviceInfoVbState::Yellow); 186 assert_eq!(DeviceInfoVbState::try_from("ORange").unwrap(), DeviceInfoVbState::Orange); 187 DeviceInfoVbState::try_from("bad").unwrap_err(); 188 } 189 190 #[test] version_from_int()191 fn version_from_int() { 192 DeviceInfoVersion::try_from(1).unwrap_err(); 193 assert_eq!(DeviceInfoVersion::try_from(2).unwrap(), DeviceInfoVersion::V2); 194 assert_eq!(DeviceInfoVersion::try_from(3).unwrap(), DeviceInfoVersion::V3); 195 DeviceInfoVersion::try_from(4).unwrap_err(); 196 } 197 198 #[test] security_level_from_string()199 fn security_level_from_string() { 200 assert_eq!( 201 DeviceInfoSecurityLevel::try_from("StrongBOX").unwrap(), 202 DeviceInfoSecurityLevel::StrongBox 203 ); 204 assert_eq!(DeviceInfoSecurityLevel::try_from("TeE").unwrap(), DeviceInfoSecurityLevel::Tee); 205 DeviceInfoSecurityLevel::try_from("insecure").unwrap_err(); 206 } 207 } 208