blob: c4c0a4afaecc0952b48db14d4670ad5e7aabc11c [file] [log] [blame]
//! Module containing validation functions for CertificateRequest.DeviceInfo
use crate::valueas::ValueAs;
use anyhow::{anyhow, ensure, Context, Result};
use ciborium::value::Value;
mod val {
pub const BOOTLOADER_STATE: [&str; 2] = ["locked", "unlocked"];
pub const FUSED: [u64; 2] = [1, 0];
pub const SECURITY_LEVEL: [&str; 2] = ["tee", "strongbox"];
pub const VBSTATE: [&str; 3] = ["green", "yellow", "orange"];
}
/// Unwrap the DeviceInfo array containing VerifiedDeviceInfo
/// and UnverifiedDeviceInfo from DeviceInfo cbor.
pub fn extract(filevalue: &Value) -> Result<&[Value]> {
let filevalue = filevalue.as_array_of_len(2)?;
Ok(filevalue)
}
/// Perform validation on DeviceInfo.
pub fn check(deviceinfo: &[Value]) -> Result<()> {
let verified_info = &deviceinfo[0];
let unverified_info = &deviceinfo[1];
let version = verified_info.map_lookup(String::from("version"))?.as_i64()?;
verified_info.check_string_val_if_key_in_map(String::from("os_version"))?;
match version {
1 => {
verified_info.check_string_val_if_key_in_map(String::from("brand"))?;
verified_info.check_string_val_if_key_in_map(String::from("manufacturer"))?;
verified_info.check_string_val_if_key_in_map(String::from("product"))?;
verified_info.check_string_val_if_key_in_map(String::from("model"))?;
verified_info.check_string_val_if_key_in_map(String::from("board"))?;
verified_info.check_string_val_if_key_in_map(String::from("device"))?;
verified_info.check_arr_val_if_key_in_map(String::from("vb_state"), &val::VBSTATE)?;
verified_info.check_arr_val_if_key_in_map(
String::from("bootloader_state"),
&val::BOOTLOADER_STATE,
)?;
verified_info
.check_bytes_val_if_key_in_map(String::from("vbmeta_digest"))
.context("vbmeta_digest not bytes")?;
verified_info.check_date_val_if_key_in_map(String::from("system_patch_level"))?;
verified_info.check_date_val_if_key_in_map(String::from("boot_patch_level"))?;
verified_info.check_date_val_if_key_in_map(String::from("vendor_patch_level"))?;
}
2 => {
verified_info.map_lookup(String::from("brand"))?.as_string()?;
verified_info.map_lookup(String::from("manufacturer"))?.as_string()?;
verified_info.map_lookup(String::from("product"))?.as_string()?;
verified_info.map_lookup(String::from("model"))?.as_string()?;
verified_info.map_lookup(String::from("device"))?.as_string()?;
verified_info.check_arr_val_for_key_in_map(String::from("vb_state"), &val::VBSTATE)?;
verified_info.check_arr_val_for_key_in_map(
String::from("bootloader_state"),
&val::BOOTLOADER_STATE,
)?;
verified_info
.map_lookup(String::from("vbmeta_digest"))?
.as_bytes()
.ok_or_else(|| anyhow!("vbmeta_digest not bytes"))?;
verified_info.map_lookup(String::from("system_patch_level"))?.as_date()?;
verified_info.map_lookup(String::from("boot_patch_level"))?.as_date()?;
verified_info.map_lookup(String::from("vendor_patch_level"))?.as_date()?;
let fused = verified_info.map_lookup(String::from("fused"))?.as_u64()?;
ensure!(val::FUSED.iter().any(|&x| x == fused));
}
_ => return Err(anyhow!("Invalid version")),
}
let security_level = verified_info.map_lookup(String::from("security_level"))?.as_string()?;
ensure!(val::SECURITY_LEVEL.iter().any(|&x| x.eq(&security_level)));
unverified_info.check_string_val_if_key_in_map(String::from("fingerprint"))?;
Ok(())
}