• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::cbor::field_value::FieldValue;
2 use crate::rkp::{
3     DeviceInfo, DeviceInfoBootloaderState, DeviceInfoSecurityLevel, DeviceInfoVbState,
4     DeviceInfoVersion,
5 };
6 use anyhow::{bail, ensure, Result};
7 use chrono::NaiveDate;
8 use ciborium::value::Value;
9 
10 impl DeviceInfo {
11     /// Create a new DeviceInfo struct from Values parsed by ciborium
from_cbor_values( values: Vec<(Value, Value)>, device_info_version: Option<DeviceInfoVersion>, is_factory: bool, ) -> Result<Self>12     pub fn from_cbor_values(
13         values: Vec<(Value, Value)>,
14         device_info_version: Option<DeviceInfoVersion>,
15         is_factory: bool,
16     ) -> Result<Self> {
17         let mut brand = FieldValue::new("brand");
18         let mut manufacturer = FieldValue::new("manufacturer");
19         let mut product = FieldValue::new("product");
20         let mut model = FieldValue::new("model");
21         let mut device = FieldValue::new("device");
22         let mut vb_state = FieldValue::new("vb_state");
23         let mut bootloader_state = FieldValue::new("bootloader_state");
24         let mut vbmeta_digest = FieldValue::new("vbmeta_digest");
25         let mut os_version = FieldValue::new("os_version");
26         let mut system_patch_level = FieldValue::new("system_patch_level");
27         let mut boot_patch_level = FieldValue::new("boot_patch_level");
28         let mut vendor_patch_level = FieldValue::new("vendor_patch_level");
29         let mut security_level = FieldValue::new("security_level");
30         let mut version = FieldValue::new("version");
31         let mut fused = FieldValue::new("fused");
32 
33         for (key, value) in values {
34             let field_value = match key.as_text() {
35                 Some("brand") => &mut brand,
36                 Some("manufacturer") => &mut manufacturer,
37                 Some("product") => &mut product,
38                 Some("model") => &mut model,
39                 Some("device") => &mut device,
40                 Some("vb_state") => &mut vb_state,
41                 Some("bootloader_state") => &mut bootloader_state,
42                 Some("vbmeta_digest") => &mut vbmeta_digest,
43                 Some("os_version") => &mut os_version,
44                 Some("system_patch_level") => &mut system_patch_level,
45                 Some("boot_patch_level") => &mut boot_patch_level,
46                 Some("vendor_patch_level") => &mut vendor_patch_level,
47                 Some("security_level") => &mut security_level,
48                 Some("fused") => &mut fused,
49                 Some("version") => &mut version,
50                 _ => bail!("Unexpected DeviceInfo kv-pair: ({key:?},{value:?})"),
51             };
52             field_value.set_once(value)?;
53         }
54 
55         let parsed_version = match version.into_optional_u32() {
56             Ok(v) => v,
57             Err(e) => return Err(e.into()),
58         };
59 
60         let version = match device_info_version {
61             Some(DeviceInfoVersion::V3) => {
62                 ensure!(parsed_version.is_none(), "DeviceInfoV3 should not have version entry.");
63                 DeviceInfoVersion::V3
64             }
65             None => match parsed_version {
66                 Some(2) => DeviceInfoVersion::V2,
67                 Some(v) => bail!("Unexpected DeviceInfo version: {}", v),
68                 None => bail!("DeviceInfo requires a version entry."),
69             },
70             _ => bail!("Unexpected DeviceInfo version: {:?}", device_info_version.unwrap()),
71         };
72 
73         let info = DeviceInfo {
74             brand: brand.into_string()?,
75             manufacturer: manufacturer.into_string()?,
76             product: product.into_string()?,
77             model: model.into_string()?,
78             device: device.into_string()?,
79             vb_state: vb_state.into_string()?.as_str().try_into()?,
80             bootloader_state: bootloader_state.into_string()?.as_str().try_into()?,
81             vbmeta_digest: vbmeta_digest.into_bytes()?,
82             os_version: os_version.into_optional_string()?,
83             system_patch_level: system_patch_level.into_u32()?,
84             boot_patch_level: boot_patch_level.into_u32()?,
85             vendor_patch_level: vendor_patch_level.into_u32()?,
86             security_level: security_level.into_string()?.as_str().try_into()?,
87             fused: fused.into_u32()?,
88             version,
89         };
90         info.validate(is_factory)?;
91         Ok(info)
92     }
93 
validate(&self, is_factory: bool) -> Result<()>94     fn validate(&self, is_factory: bool) -> Result<()> {
95         if DeviceInfoSecurityLevel::Avf == self.security_level {
96             ensure!(
97                 self.bootloader_state == DeviceInfoBootloaderState::Avf
98                     && self.vb_state == DeviceInfoVbState::Avf
99                     && self.brand == "aosp-avf"
100                     && self.device == "avf"
101                     && self.model == "avf"
102                     && self.manufacturer == "aosp-avf"
103                     && self.product == "avf",
104                 "AVF security level requires AVF fields. Got: {:?}",
105                 self
106             );
107             return Ok(());
108         } else {
109             ensure!(
110                 self.bootloader_state != DeviceInfoBootloaderState::Avf
111                     && self.vb_state != DeviceInfoVbState::Avf
112                     && self.brand != "aosp-avf"
113                     && self.device != "avf"
114                     && self.model != "avf"
115                     && self.manufacturer != "aosp-avf"
116                     && self.product != "avf",
117                 "Non-AVF security level requires non-AVF fields. Got: {:?}",
118                 self
119             );
120         }
121 
122         ensure!(!self.manufacturer.is_empty(), "manufacturer must not be empty");
123 
124         if !is_factory {
125             self.check_entries()?;
126         }
127 
128         Ok(())
129     }
130 
check_patch_level(key: &str, level: String) -> Result<()>131     fn check_patch_level(key: &str, level: String) -> Result<()> {
132         let mut maybe_modified_level = level.clone();
133         if level.len() == 6 {
134             maybe_modified_level += "01";
135         }
136 
137         let string = maybe_modified_level.as_str();
138         match string.len() {
139             8 => match NaiveDate::parse_from_str(string, "%Y%m%d") {
140                 Ok(_) => Ok(()),
141                 Err(e) => bail!("Error parsing {key}:{level}: {}", e.to_string()),
142             },
143             _ => bail!("value for {key} must be in format YYYYMMDD or YYYYMM, found: '{level}'"),
144         }
145     }
146 
check_entries(&self) -> Result<()>147     fn check_entries(&self) -> Result<()> {
148         if self.version == DeviceInfoVersion::V3 {
149             Self::check_patch_level("system_patch_level", self.system_patch_level.to_string())?;
150             Self::check_patch_level("boot_patch_level", self.boot_patch_level.to_string())?;
151             Self::check_patch_level("vendor_patch_level", self.vendor_patch_level.to_string())?;
152         }
153         if self.version == DeviceInfoVersion::V3 || self.version == DeviceInfoVersion::V2 {
154             ensure!(!self.vbmeta_digest.is_empty(), "vbmeta_digest must not be empty");
155             ensure!(
156                 !self.vbmeta_digest.iter().all(|b| *b == 0u8),
157                 "vbmeta_digest must not be all zeros. Got {:?}",
158                 self.vbmeta_digest
159             );
160 
161             ensure!(
162                 self.vb_state != DeviceInfoVbState::Factory,
163                 "vb_state must be a valid production value"
164             );
165             ensure!(
166                 self.bootloader_state != DeviceInfoBootloaderState::Factory,
167                 "bootloader_state must be a valid production value"
168             );
169             ensure!(
170                 self.fused == 0 || self.fused == 1,
171                 "fused must be a valid production value {}",
172                 self.fused
173             );
174             ensure!(
175                 self.security_level != DeviceInfoSecurityLevel::Factory,
176                 "security_level must be a valid production value"
177             );
178             ensure!(
179                 self.security_level != DeviceInfoSecurityLevel::Tee || self.os_version.is_some(),
180                 "OS version is not optional with TEE"
181             );
182             ensure!(!self.brand.is_empty(), "brand must not be empty");
183             ensure!(!self.device.is_empty(), "device must not be empty");
184             ensure!(!self.model.is_empty(), "model must not be empty");
185             ensure!(!self.product.is_empty(), "product must not be empty");
186         }
187 
188         Ok(())
189     }
190 }
191 
192 #[cfg(test)]
193 mod tests {
194     use super::*;
195     use crate::rkp::DeviceInfoVersion;
196 
197     #[test]
device_info_from_cbor_values_optional_os_version()198     fn device_info_from_cbor_values_optional_os_version() {
199         let values: Vec<(Value, Value)> = get_valid_values_filtered(|x| x != "os_version");
200         let info = DeviceInfo::from_cbor_values(values, None, true).unwrap();
201         assert!(info.os_version.is_none());
202     }
203 
204     #[test]
device_info_from_cbor_values_optional_os_version_is_not_optional_with_tee()205     fn device_info_from_cbor_values_optional_os_version_is_not_optional_with_tee() {
206         let values: Vec<(Value, Value)> = get_valid_tee_values_filtered(|x| x != "os_version");
207         let err = DeviceInfo::from_cbor_values(values, None, false).unwrap_err();
208         assert!(err.to_string().contains("OS version is not optional with TEE"));
209     }
210 
211     #[test]
device_info_from_cbor_values_missing_required_field()212     fn device_info_from_cbor_values_missing_required_field() {
213         let values: Vec<(Value, Value)> = get_valid_values_filtered(|x| x != "brand");
214         let err = DeviceInfo::from_cbor_values(values, None, false).unwrap_err();
215         assert!(err.to_string().contains("brand"));
216     }
217 
218     #[test]
from_cbor_values_valid_v2()219     fn from_cbor_values_valid_v2() {
220         let actual = DeviceInfo::from_cbor_values(get_valid_values(), None, false).unwrap();
221         let expected = DeviceInfo {
222             brand: "generic".to_string(),
223             manufacturer: "acme".to_string(),
224             product: "phone".to_string(),
225             model: "the best one".to_string(),
226             device: "really the best".to_string(),
227             vb_state: DeviceInfoVbState::Green,
228             bootloader_state: DeviceInfoBootloaderState::Locked,
229             vbmeta_digest: b"abcdefg".to_vec(),
230             os_version: Some("dessert".to_string()),
231             system_patch_level: 303010,
232             boot_patch_level: 30300102,
233             vendor_patch_level: 30300304,
234             security_level: DeviceInfoSecurityLevel::StrongBox,
235             fused: 1,
236             version: DeviceInfoVersion::V2,
237         };
238         assert_eq!(actual, expected);
239     }
240 
241     #[test]
device_info_from_cbor_values_valid_v3()242     fn device_info_from_cbor_values_valid_v3() {
243         let values: Vec<(Value, Value)> = get_valid_values_filtered(|x| x != "version");
244         let actual =
245             DeviceInfo::from_cbor_values(values, Some(DeviceInfoVersion::V3), false).unwrap();
246         let expected = DeviceInfo {
247             brand: "generic".to_string(),
248             manufacturer: "acme".to_string(),
249             product: "phone".to_string(),
250             model: "the best one".to_string(),
251             device: "really the best".to_string(),
252             vb_state: DeviceInfoVbState::Green,
253             bootloader_state: DeviceInfoBootloaderState::Locked,
254             vbmeta_digest: b"abcdefg".to_vec(),
255             os_version: Some("dessert".to_string()),
256             system_patch_level: 303010,
257             boot_patch_level: 30300102,
258             vendor_patch_level: 30300304,
259             security_level: DeviceInfoSecurityLevel::StrongBox,
260             fused: 1,
261             version: DeviceInfoVersion::V3,
262         };
263         assert_eq!(actual, expected);
264     }
265 
266     #[test]
device_info_from_cbor_values_mismatched_version()267     fn device_info_from_cbor_values_mismatched_version() {
268         let values: Vec<(Value, Value)> = get_valid_values();
269         let err =
270             DeviceInfo::from_cbor_values(values, Some(DeviceInfoVersion::V3), false).unwrap_err();
271         println!("{err:?}");
272         assert!(err.to_string().contains("version"));
273     }
274 
275     #[test]
device_info_from_cbor_values_invalid_version_value()276     fn device_info_from_cbor_values_invalid_version_value() {
277         let values: Vec<(Value, Value)> = get_valid_values_filtered(|x| x != "version");
278         let err = DeviceInfo::from_cbor_values(values, None, false).unwrap_err();
279         println!("{err:?}");
280         assert!(err.to_string().contains("version"));
281     }
282 
283     #[test]
device_info_from_cbor_values_missing_version()284     fn device_info_from_cbor_values_missing_version() {
285         let values: Vec<(Value, Value)> = get_valid_values_filtered(|x| x != "version");
286         let err = DeviceInfo::from_cbor_values(values, None, false).unwrap_err();
287         println!("{err:?}");
288         assert!(err.to_string().contains("version"));
289     }
290 
291     #[test]
device_info_from_cbor_duplicate_values()292     fn device_info_from_cbor_duplicate_values() {
293         let mut values: Vec<(Value, Value)> = get_valid_values();
294         values.push(("brand".into(), "generic".into()));
295 
296         let err = DeviceInfo::from_cbor_values(values, None, false).unwrap_err();
297         println!("{err:?}");
298         assert!(err.to_string().contains("may be set only once"));
299     }
300 
301     #[test]
device_info_from_cbor_empty_vbmeta_digest()302     fn device_info_from_cbor_empty_vbmeta_digest() {
303         let mut values: Vec<(Value, Value)> = get_valid_values_filtered(|v| v != "vbmeta_digest");
304         values.push(("vbmeta_digest".into(), vec![0u8; 0].into()));
305 
306         let err = DeviceInfo::from_cbor_values(values, None, false).unwrap_err();
307         println!("{err:?}");
308         assert!(err.to_string().contains("vbmeta_digest must not be empty"), "{err:?}");
309     }
310 
311     #[test]
device_info_from_cbor_all_zero_vbmeta_digest()312     fn device_info_from_cbor_all_zero_vbmeta_digest() {
313         let mut values: Vec<(Value, Value)> = get_valid_values_filtered(|v| v != "vbmeta_digest");
314         values.push(("vbmeta_digest".into(), vec![0u8; 16].into()));
315 
316         let err = DeviceInfo::from_cbor_values(values, None, false).unwrap_err();
317         println!("{err:?}");
318         assert!(err.to_string().contains("vbmeta_digest must not be all zeros"), "{err:?}");
319     }
320 
321     #[test]
device_info_from_cbor_values_non_avf_security_level_has_avf_vb_state()322     fn device_info_from_cbor_values_non_avf_security_level_has_avf_vb_state() {
323         let mut values = get_valid_values_filtered(|x| x != "vb_state");
324         values.push(("vb_state".into(), "avf".into()));
325 
326         let err = DeviceInfo::from_cbor_values(values, None, false).unwrap_err();
327         assert!(err.to_string().contains("Non-AVF security level"), "{err:?}");
328     }
329 
330     #[test]
device_info_from_cbor_values_non_avf_security_level_has_avf_bootloader_state()331     fn device_info_from_cbor_values_non_avf_security_level_has_avf_bootloader_state() {
332         let mut values = get_valid_values_filtered(|x| x != "bootloader_state");
333         values.push(("bootloader_state".into(), "avf".into()));
334 
335         let err = DeviceInfo::from_cbor_values(values, None, false).unwrap_err();
336         assert!(err.to_string().contains("Non-AVF security level"), "{err:?}");
337     }
338 
339     #[test]
device_info_from_cbor_values_avf_security_level_has_non_avf_vb_state()340     fn device_info_from_cbor_values_avf_security_level_has_non_avf_vb_state() {
341         let values: Vec<(Value, Value)> = get_valid_avf_values()
342             .into_iter()
343             .filter(|(k, _v)| k.as_text().unwrap() != "vb_state")
344             .chain(vec![("vb_state".into(), "green".into())])
345             .collect();
346         let err =
347             DeviceInfo::from_cbor_values(values, Some(DeviceInfoVersion::V3), false).unwrap_err();
348         assert!(err.to_string().contains("AVF security level requires AVF fields"), "{err:?}");
349     }
350 
351     #[test]
device_info_from_cbor_values_avf_security_level_has_avf_fields()352     fn device_info_from_cbor_values_avf_security_level_has_avf_fields() {
353         let values = get_valid_avf_values();
354         let actual =
355             DeviceInfo::from_cbor_values(values, Some(DeviceInfoVersion::V3), false).unwrap();
356         let expected = DeviceInfo {
357             brand: "aosp-avf".to_string(),
358             manufacturer: "aosp-avf".to_string(),
359             product: "avf".to_string(),
360             model: "avf".to_string(),
361             device: "avf".to_string(),
362             vb_state: DeviceInfoVbState::Avf,
363             bootloader_state: DeviceInfoBootloaderState::Avf,
364             vbmeta_digest: b"abcdefg".to_vec(),
365             os_version: Some("dessert".to_string()),
366             system_patch_level: 303010,
367             boot_patch_level: 30300102,
368             vendor_patch_level: 30300304,
369             security_level: DeviceInfoSecurityLevel::Avf,
370             fused: 1,
371             version: DeviceInfoVersion::V3,
372         };
373         assert_eq!(expected, actual);
374     }
375 
get_valid_values() -> Vec<(Value, Value)>376     fn get_valid_values() -> Vec<(Value, Value)> {
377         vec![
378             ("brand".into(), "generic".into()),
379             ("manufacturer".into(), "acme".into()),
380             ("product".into(), "phone".into()),
381             ("model".into(), "the best one".into()),
382             ("device".into(), "really the best".into()),
383             ("vb_state".into(), "green".into()),
384             ("bootloader_state".into(), "locked".into()),
385             ("vbmeta_digest".into(), b"abcdefg".as_ref().into()),
386             ("os_version".into(), "dessert".into()),
387             ("system_patch_level".into(), 303010.into()),
388             ("boot_patch_level".into(), 30300102.into()),
389             ("vendor_patch_level".into(), 30300304.into()),
390             ("security_level".into(), "strongbox".into()),
391             ("fused".into(), 1.into()),
392             ("version".into(), 2.into()),
393         ]
394     }
395 
get_valid_tee_values() -> Vec<(Value, Value)>396     fn get_valid_tee_values() -> Vec<(Value, Value)> {
397         vec![
398             ("brand".into(), "generic".into()),
399             ("manufacturer".into(), "acme".into()),
400             ("product".into(), "phone".into()),
401             ("model".into(), "the best one".into()),
402             ("device".into(), "really the best".into()),
403             ("vb_state".into(), "green".into()),
404             ("bootloader_state".into(), "locked".into()),
405             ("vbmeta_digest".into(), b"abcdefg".as_ref().into()),
406             ("os_version".into(), "dessert".into()),
407             ("system_patch_level".into(), 303010.into()),
408             ("boot_patch_level".into(), 30300102.into()),
409             ("vendor_patch_level".into(), 30300304.into()),
410             ("security_level".into(), "tee".into()),
411             ("fused".into(), 1.into()),
412             ("version".into(), 2.into()),
413         ]
414     }
415 
get_valid_avf_values() -> Vec<(Value, Value)>416     fn get_valid_avf_values() -> Vec<(Value, Value)> {
417         vec![
418             ("brand".into(), "aosp-avf".into()),
419             ("manufacturer".into(), "aosp-avf".into()),
420             ("product".into(), "avf".into()),
421             ("model".into(), "avf".into()),
422             ("device".into(), "avf".into()),
423             ("vb_state".into(), "avf".into()),
424             ("bootloader_state".into(), "avf".into()),
425             ("vbmeta_digest".into(), b"abcdefg".as_ref().into()),
426             ("os_version".into(), "dessert".into()),
427             ("system_patch_level".into(), 303010.into()),
428             ("boot_patch_level".into(), 30300102.into()),
429             ("vendor_patch_level".into(), 30300304.into()),
430             ("security_level".into(), "avf".into()),
431             ("fused".into(), 1.into()),
432         ]
433     }
434 
get_valid_values_filtered<F: Fn(&str) -> bool>(filter: F) -> Vec<(Value, Value)>435     fn get_valid_values_filtered<F: Fn(&str) -> bool>(filter: F) -> Vec<(Value, Value)> {
436         get_valid_values().into_iter().filter(|x| filter(x.0.as_text().unwrap())).collect()
437     }
438 
get_valid_tee_values_filtered<F: Fn(&str) -> bool>(filter: F) -> Vec<(Value, Value)>439     fn get_valid_tee_values_filtered<F: Fn(&str) -> bool>(filter: F) -> Vec<(Value, Value)> {
440         get_valid_tee_values().into_iter().filter(|x| filter(x.0.as_text().unwrap())).collect()
441     }
442 }
443