• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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