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. Currently, this is the same as the HAL version. 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: DeviceInfoSecurityLevel, 40 /// Whether secure boot is enforced/required by the SoC. 41 pub fused: u32, 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 os_version: &dyn fmt::Debug = self.os_version.as_ref().map_or(&"<none>", |v| v); 47 48 fmt.debug_struct("DeviceInfo") 49 .field("version", &self.version) 50 .field("brand", &self.brand) 51 .field("manufacturer", &self.manufacturer) 52 .field("product", &self.product) 53 .field("model", &self.model) 54 .field("device", &self.device) 55 .field("vb_state", &self.vb_state) 56 .field("bootloader_state", &self.bootloader_state) 57 .field("vbmeta_digest", &hex::encode(&self.vbmeta_digest)) 58 .field("os_version", os_version) 59 .field("system_patch_level", &self.system_patch_level) 60 .field("boot_patch_level", &self.boot_patch_level) 61 .field("vendor_patch_level", &self.vendor_patch_level) 62 .field("security_level", &self.security_level) 63 .field("fused", &self.fused) 64 .finish() 65 } 66 } 67 68 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 69 /// Whether the bootloader allows unsigned or third-party-signed images. 70 pub enum DeviceInfoBootloaderState { 71 /// The bootloader is locked, and will only allow signed images. 72 Locked, 73 /// The bootloader will load arbitrary images. 74 Unlocked, 75 /// This field is a placeholder for the AVF backend. 76 Avf, 77 /// This field is a placeholder for a Factory CSR 78 Factory, 79 } 80 81 impl TryFrom<&str> for DeviceInfoBootloaderState { 82 type Error = anyhow::Error; 83 try_from(s: &str) -> Result<Self, Self::Error>84 fn try_from(s: &str) -> Result<Self, Self::Error> { 85 match s.to_ascii_lowercase().as_str() { 86 "locked" => Ok(Self::Locked), 87 "unlocked" => Ok(Self::Unlocked), 88 "avf" => Ok(Self::Avf), 89 _ => Ok(Self::Factory), 90 } 91 } 92 } 93 94 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 95 /// State of the verified boot validation. 96 pub enum DeviceInfoVbState { 97 /// The device booted an OEM-signed image. 98 Green, 99 /// The device booted an image signed by a key set by the end user. 100 Yellow, 101 /// The bootloader is unlocked, and no guarantees of image integrity are available. 102 Orange, 103 /// This field is a placeholder for the AVF backend. 104 Avf, 105 /// This field is a placeholder for a Factory CSR 106 Factory, 107 } 108 109 impl TryFrom<&str> for DeviceInfoVbState { 110 type Error = anyhow::Error; 111 try_from(s: &str) -> Result<Self, Self::Error>112 fn try_from(s: &str) -> Result<Self, Self::Error> { 113 match s.to_ascii_lowercase().as_str() { 114 "green" => Ok(Self::Green), 115 "yellow" => Ok(Self::Yellow), 116 "orange" => Ok(Self::Orange), 117 "avf" => Ok(Self::Avf), 118 _ => Ok(Self::Factory), 119 } 120 } 121 } 122 123 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 124 /// The version of the DeviceInfo structure, which may update with HAL changes. 125 /// Currently, this is the same as the HAL version. 126 pub enum DeviceInfoVersion { 127 /// First supported version. Prior to this (V1), almost all fields were optional. 128 V2, 129 /// Explicit version removed from the CBOR. Otherwise, identical to V2. 130 V3, 131 } 132 133 impl TryFrom<u32> for DeviceInfoVersion { 134 type Error = anyhow::Error; 135 try_from(i: u32) -> Result<Self, Self::Error>136 fn try_from(i: u32) -> Result<Self, Self::Error> { 137 match i { 138 2 => Ok(Self::V2), 139 3 => Ok(Self::V3), 140 _ => Err(anyhow!("Invalid DeviceInfo version: `{i}`")), 141 } 142 } 143 } 144 145 #[derive(Copy, Clone, Debug, Eq, PartialEq)] 146 /// This corresponds with where KeyMint's backing service lives: a TEE or in a separate SE. 147 pub enum DeviceInfoSecurityLevel { 148 /// KeyMint's backend runs in a Trusted Execution Environment. 149 Tee, 150 /// KeyMint's backend runs in a Secure Element. 151 StrongBox, 152 /// AVF's backend. 153 Avf, 154 /// This field is a placeholder for a Factory CSR 155 Factory, 156 } 157 158 impl TryFrom<&str> for DeviceInfoSecurityLevel { 159 type Error = anyhow::Error; 160 try_from(s: &str) -> Result<Self, Self::Error>161 fn try_from(s: &str) -> Result<Self, Self::Error> { 162 match s.to_ascii_lowercase().as_str() { 163 "strongbox" => Ok(Self::StrongBox), 164 "tee" => Ok(Self::Tee), 165 "avf" => Ok(Self::Avf), 166 _ => Ok(Self::Factory), 167 } 168 } 169 } 170 171 #[cfg(test)] 172 mod tests { 173 use super::*; 174 175 #[test] bootloader_state_from_string()176 fn bootloader_state_from_string() { 177 assert_eq!( 178 DeviceInfoBootloaderState::try_from("LoCkEd").unwrap(), 179 DeviceInfoBootloaderState::Locked 180 ); 181 assert_eq!( 182 DeviceInfoBootloaderState::try_from("UNLocked").unwrap(), 183 DeviceInfoBootloaderState::Unlocked 184 ); 185 assert_eq!( 186 DeviceInfoBootloaderState::try_from("nope").unwrap(), 187 DeviceInfoBootloaderState::Factory 188 ); 189 } 190 191 #[test] vb_state_from_string()192 fn vb_state_from_string() { 193 assert_eq!(DeviceInfoVbState::try_from("greEN").unwrap(), DeviceInfoVbState::Green); 194 assert_eq!(DeviceInfoVbState::try_from("YeLLoW").unwrap(), DeviceInfoVbState::Yellow); 195 assert_eq!(DeviceInfoVbState::try_from("ORange").unwrap(), DeviceInfoVbState::Orange); 196 assert_eq!(DeviceInfoVbState::try_from("bad").unwrap(), DeviceInfoVbState::Factory); 197 } 198 199 #[test] version_from_int()200 fn version_from_int() { 201 DeviceInfoVersion::try_from(1).unwrap_err(); 202 assert_eq!(DeviceInfoVersion::try_from(2).unwrap(), DeviceInfoVersion::V2); 203 assert_eq!(DeviceInfoVersion::try_from(3).unwrap(), DeviceInfoVersion::V3); 204 DeviceInfoVersion::try_from(4).unwrap_err(); 205 } 206 207 #[test] security_level_from_string()208 fn security_level_from_string() { 209 assert_eq!( 210 DeviceInfoSecurityLevel::try_from("StrongBOX").unwrap(), 211 DeviceInfoSecurityLevel::StrongBox 212 ); 213 assert_eq!(DeviceInfoSecurityLevel::try_from("TeE").unwrap(), DeviceInfoSecurityLevel::Tee); 214 assert_eq!( 215 DeviceInfoSecurityLevel::try_from("insecure").unwrap(), 216 DeviceInfoSecurityLevel::Factory 217 ); 218 } 219 } 220