xref: /aosp_15_r20/tools/security/remote_provisioning/hwtrust/src/rkp/device_info.rs (revision d9ecfb0f4d734c9ce41cde8ac4d585b094fd4222)
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