1use anyhow::{bail, Context, Error};
9
10#[derive(Clone, Copy, PartialEq)]
11pub enum Policy {
12 Null,
13 TeeRequired,
14 TeeTransitional,
15 TeeOpportunistic,
16}
17
18impl TryFrom<String> for Policy {
19 type Error = Error;
20
21 fn try_from(value: String) -> Result<Self, Self::Error> {
22 match value.as_ref() {
23 "null" => Ok(Policy::Null),
24 "tee" => Ok(Policy::TeeRequired),
25 "tee-transitional" => Ok(Policy::TeeTransitional),
26 "tee-opportunistic" => Ok(Policy::TeeOpportunistic),
27 p => bail!("unrecognized key source policy: '{p}'"),
28 }
29 }
30}
31
32pub async fn get_policy() -> Result<Policy, Error> {
34 fuchsia_fs::file::read_in_namespace_to_string("/boot/config/zxcrypt").await?.try_into()
35}
36
37#[derive(Debug)]
38pub enum KeySource {
39 Null,
40 Tee,
41}
42
43pub enum KeyConsumer {
46 Fxfs,
51 Zxcrypt,
53}
54
55impl KeySource {
56 pub async fn get_key(&self, consumer: KeyConsumer) -> Result<Vec<u8>, Error> {
57 match self {
58 KeySource::Null => match consumer {
59 KeyConsumer::Fxfs => {
60 let mut key = b"zxcrypt".to_vec();
61 key.resize(16, 0);
62 Ok(key)
63 }
64 KeyConsumer::Zxcrypt => Ok(vec![0u8; 32]),
65 },
66 KeySource::Tee => {
67 kms_stateless::get_hardware_derived_key(kms_stateless::KeyInfo::new_zxcrypt())
71 .await
72 .context("failed to get hardware key")
73 }
74 }
75 }
76}
77
78pub fn format_sources(policy: Policy) -> Vec<KeySource> {
80 match policy {
81 Policy::Null => vec![KeySource::Null],
82 Policy::TeeRequired => vec![KeySource::Tee],
83 Policy::TeeTransitional => vec![KeySource::Tee],
84 Policy::TeeOpportunistic => vec![KeySource::Tee, KeySource::Null],
85 }
86}
87
88pub fn unseal_sources(policy: Policy) -> Vec<KeySource> {
90 match policy {
91 Policy::Null => vec![KeySource::Null],
92 Policy::TeeRequired => vec![KeySource::Tee],
93 Policy::TeeTransitional => vec![KeySource::Tee, KeySource::Null],
94 Policy::TeeOpportunistic => vec![KeySource::Tee, KeySource::Null],
95 }
96}