1use std::collections::BTreeMap;
9
10use anyhow::{Context, Error, anyhow, bail};
11
12#[derive(Clone, Copy, Debug, PartialEq)]
13pub enum Policy {
14 Null,
15 TeeRequired,
16 TeeTransitional,
17 TeeOpportunistic,
18 Keymint,
19}
20
21impl TryFrom<String> for Policy {
22 type Error = Error;
23
24 fn try_from(value: String) -> Result<Self, Self::Error> {
25 match value.as_ref() {
26 "null" => Ok(Policy::Null),
27 "tee" => Ok(Policy::TeeRequired),
28 "tee-transitional" => Ok(Policy::TeeTransitional),
29 "tee-opportunistic" => Ok(Policy::TeeOpportunistic),
30 "keymint" => Ok(Policy::Keymint),
31 p => bail!("unrecognized key source policy: '{p}'"),
32 }
33 }
34}
35
36impl std::fmt::Display for Policy {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 match self {
39 Self::Null => f.write_str("null"),
40 Self::TeeRequired => f.write_str("tee"),
41 Self::TeeTransitional => f.write_str("tee-transitional"),
42 Self::TeeOpportunistic => f.write_str("tee-opportunistic"),
43 Self::Keymint => f.write_str("keymint"),
44 }
45 }
46}
47
48pub async fn get_policy() -> Result<Policy, Error> {
50 fuchsia_fs::file::read_in_namespace_to_string("/boot/config/zxcrypt").await?.try_into()
51}
52
53#[derive(Clone, Copy, Debug)]
56pub enum KeyConsumer {
57 Fxfs,
62 Zxcrypt,
64}
65
66#[derive(Debug)]
67pub struct NullKeySource;
68
69impl NullKeySource {
70 pub fn get_key(&self, consumer: KeyConsumer) -> Vec<u8> {
71 match consumer {
72 KeyConsumer::Fxfs => {
73 let mut key = b"zxcrypt".to_vec();
74 key.resize(16, 0);
75 key
76 }
77 KeyConsumer::Zxcrypt => vec![0u8; 32],
78 }
79 }
80}
81
82#[derive(Debug)]
83pub struct TeeDerivedKeySource;
84
85impl TeeDerivedKeySource {
86 pub async fn get_key(&self) -> Result<Vec<u8>, Error> {
87 kms_stateless::get_hardware_derived_key(kms_stateless::KeyInfo::new_zxcrypt())
91 .await
92 .context("failed to get hardware key")
93 }
94}
95
96pub struct KeymintSealedData {
104 pub sealing_key_info: Vec<u8>,
105 pub sealing_key_blob: Vec<u8>,
106 pub sealed_keys: BTreeMap<String, Vec<u8>>,
107}
108
109impl KeymintSealedData {
110 pub async fn new() -> Result<Self, Error> {
116 let mut sealing_key_info = vec![0u8; 32];
117 zx::cprng_draw(&mut sealing_key_info[..]);
118 let sealing_key_blob = kms_stateless::create_sealing_key(&sealing_key_info[..])
119 .await
120 .context("Failed to create sealing key")?;
121 Ok(Self { sealing_key_info, sealing_key_blob, sealed_keys: BTreeMap::default() })
122 }
123
124 pub async fn create_key(&mut self, label: &str) -> Result<Vec<u8>, Error> {
127 let mut key = vec![0u8; 32];
128 zx::cprng_draw(&mut key[..]);
129 let sealed_data =
130 kms_stateless::seal(&self.sealing_key_info[..], &self.sealing_key_blob[..], &key[..])
131 .await
132 .context("Failed to seal keymint key")?;
133 self.sealed_keys.insert(label.to_string(), sealed_data);
134 Ok(key)
135 }
136
137 pub async fn unseal_key(&self, label: &str) -> Result<Vec<u8>, Error> {
139 let sealed = self.sealed_keys.get(label).ok_or_else(|| anyhow!("Key not found"))?;
140 Ok(kms_stateless::unseal(
141 &self.sealing_key_info[..],
142 &self.sealing_key_blob[..],
143 &sealed[..],
144 )
145 .await?)
146 }
147}
148
149#[derive(Debug)]
150pub enum KeySource {
151 Null(NullKeySource),
153 TeeDerived(TeeDerivedKeySource),
156 KeymintSealed,
160}
161
162pub fn format_sources(policy: Policy) -> Vec<KeySource> {
164 match policy {
165 Policy::Null => vec![KeySource::Null(NullKeySource)],
166 Policy::TeeRequired => vec![KeySource::TeeDerived(TeeDerivedKeySource)],
167 Policy::TeeTransitional => vec![KeySource::TeeDerived(TeeDerivedKeySource)],
168 Policy::TeeOpportunistic => {
169 vec![KeySource::TeeDerived(TeeDerivedKeySource), KeySource::Null(NullKeySource)]
170 }
171 Policy::Keymint => vec![KeySource::KeymintSealed],
172 }
173}
174
175pub fn unseal_sources(policy: Policy) -> Vec<KeySource> {
177 match policy {
178 Policy::Null => vec![KeySource::Null(NullKeySource)],
179 Policy::TeeRequired => vec![KeySource::TeeDerived(TeeDerivedKeySource)],
180 Policy::TeeTransitional => {
181 vec![KeySource::TeeDerived(TeeDerivedKeySource), KeySource::Null(NullKeySource)]
182 }
183 Policy::TeeOpportunistic => {
184 vec![KeySource::TeeDerived(TeeDerivedKeySource), KeySource::Null(NullKeySource)]
185 }
186 Policy::Keymint => vec![KeySource::KeymintSealed],
187 }
188}