1use aes::cipher::{KeyIvInit, StreamCipher as _, StreamCipherSeek};
6use anyhow::anyhow;
7use async_trait::async_trait;
8use chacha20::{self, ChaCha20};
9use fprint::TypeFingerprint;
10use futures::TryStreamExt as _;
11use futures::stream::FuturesUnordered;
12use serde::de::{Error as SerdeError, Visitor};
13use serde::{Deserialize, Deserializer, Serialize, Serializer};
14use std::collections::BTreeMap;
15use zx_status as zx;
16
17mod cipher;
18pub mod ff1;
19
20pub use cipher::fscrypt_ino_lblk32::FscryptSoftwareInoLblk32FileCipher;
21pub use cipher::fxfs::FxfsCipher;
22pub use cipher::{Cipher, CipherSet, FindKeyResult};
23pub use fidl_fuchsia_fxfs::{
24 EmptyStruct, FscryptKeyIdentifier, FscryptKeyIdentifierAndNonce, ObjectType, WrappedKey,
25};
26
27pub use cipher::FSCRYPT_PADDING;
28pub const FXFS_KEY_SIZE: usize = 256 / 8;
29pub const FXFS_WRAPPED_KEY_SIZE: usize = FXFS_KEY_SIZE + 16;
30
31#[derive(Debug)]
34pub struct UnwrappedKey(Vec<u8>);
35impl UnwrappedKey {
36 pub fn new(key: Vec<u8>) -> Self {
37 UnwrappedKey(key)
38 }
39}
40impl std::ops::Deref for UnwrappedKey {
41 type Target = Vec<u8>;
42 fn deref(&self) -> &Self::Target {
43 &self.0
44 }
45}
46
47#[repr(transparent)]
49#[derive(Clone, Debug, PartialEq)]
50pub struct WrappedKeyBytes(pub [u8; FXFS_WRAPPED_KEY_SIZE]);
51impl Default for WrappedKeyBytes {
52 fn default() -> Self {
53 Self([0u8; FXFS_WRAPPED_KEY_SIZE])
54 }
55}
56impl TryFrom<Vec<u8>> for WrappedKeyBytes {
57 type Error = anyhow::Error;
58
59 fn try_from(buf: Vec<u8>) -> Result<Self, Self::Error> {
60 Ok(Self(buf.try_into().map_err(|_| anyhow!("wrapped key wrong length"))?))
61 }
62}
63impl From<[u8; FXFS_WRAPPED_KEY_SIZE]> for WrappedKeyBytes {
64 fn from(buf: [u8; FXFS_WRAPPED_KEY_SIZE]) -> Self {
65 Self(buf)
66 }
67}
68impl TypeFingerprint for WrappedKeyBytes {
69 fn fingerprint() -> String {
70 "WrappedKeyBytes".to_owned()
71 }
72}
73
74impl std::ops::Deref for WrappedKeyBytes {
75 type Target = [u8; FXFS_WRAPPED_KEY_SIZE];
76 fn deref(&self) -> &Self::Target {
77 &self.0
78 }
79}
80
81impl std::ops::DerefMut for WrappedKeyBytes {
82 fn deref_mut(&mut self) -> &mut Self::Target {
83 &mut self.0
84 }
85}
86
87impl Serialize for WrappedKeyBytes {
90 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
91 where
92 S: Serializer,
93 {
94 serializer.serialize_bytes(&self[..])
95 }
96}
97
98impl<'de> Deserialize<'de> for WrappedKeyBytes {
99 fn deserialize<D>(deserializer: D) -> Result<WrappedKeyBytes, D::Error>
100 where
101 D: Deserializer<'de>,
102 {
103 struct WrappedKeyVisitor;
104
105 impl<'d> Visitor<'d> for WrappedKeyVisitor {
106 type Value = WrappedKeyBytes;
107
108 fn expecting(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
109 formatter.write_str("Expected wrapped keys to be 48 bytes")
110 }
111
112 fn visit_bytes<E>(self, bytes: &[u8]) -> Result<WrappedKeyBytes, E>
113 where
114 E: SerdeError,
115 {
116 self.visit_byte_buf(bytes.to_vec())
117 }
118
119 fn visit_byte_buf<E>(self, bytes: Vec<u8>) -> Result<WrappedKeyBytes, E>
120 where
121 E: SerdeError,
122 {
123 let orig_len = bytes.len();
124 let bytes: [u8; FXFS_WRAPPED_KEY_SIZE] =
125 bytes.try_into().map_err(|_| SerdeError::invalid_length(orig_len, &self))?;
126 Ok(WrappedKeyBytes::from(bytes))
127 }
128 }
129 deserializer.deserialize_byte_buf(WrappedKeyVisitor)
130 }
131}
132
133#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, TypeFingerprint)]
135pub enum EncryptionKey {
136 Fxfs(FxfsKey),
137 FscryptInoLblk32File { key_identifier: [u8; 16] },
143 FscryptInoLblk32Dir { key_identifier: [u8; 16], nonce: [u8; 16] },
144}
145
146impl<'a> arbitrary::Arbitrary<'a> for EncryptionKey {
147 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
148 Ok(match u.int_in_range(0..=2)? {
149 0 => EncryptionKey::Fxfs(u.arbitrary()?),
150 1 => EncryptionKey::FscryptInoLblk32File { key_identifier: u.arbitrary()? },
151 2 => EncryptionKey::FscryptInoLblk32Dir {
152 key_identifier: u.arbitrary()?,
153 nonce: u.arbitrary()?,
154 },
155 _ => unreachable!(),
156 })
157 }
158}
159
160impl From<EncryptionKey> for WrappedKey {
161 fn from(value: EncryptionKey) -> Self {
162 match value {
163 EncryptionKey::Fxfs(key) => WrappedKey::Fxfs(key.into()),
164 EncryptionKey::FscryptInoLblk32File { key_identifier } => {
165 WrappedKey::FscryptInoLblk32File(FscryptKeyIdentifier { key_identifier })
166 }
167 EncryptionKey::FscryptInoLblk32Dir { key_identifier, nonce } => {
168 WrappedKey::FscryptInoLblk32Dir(FscryptKeyIdentifierAndNonce {
169 key_identifier,
170 nonce,
171 })
172 }
173 }
174 }
175}
176
177#[derive(Clone, Default, Debug, Serialize, Deserialize, TypeFingerprint, PartialEq)]
180pub struct FxfsKey {
181 pub wrapping_key_id: WrappingKeyId,
184 pub key: WrappedKeyBytes,
190}
191
192pub type WrappingKeyId = [u8; 16];
193
194impl From<FxfsKey> for fidl_fuchsia_fxfs::FxfsKey {
195 fn from(value: FxfsKey) -> Self {
196 fidl_fuchsia_fxfs::FxfsKey {
197 wrapping_key_id: value.wrapping_key_id,
198 wrapped_key: value.key.0,
199 }
200 }
201}
202
203impl<'a> arbitrary::Arbitrary<'a> for FxfsKey {
204 fn arbitrary(_u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
205 return Ok(FxfsKey::default());
207 }
208}
209
210pub struct StreamCipher(ChaCha20);
214
215impl StreamCipher {
216 pub fn new(key: &UnwrappedKey, offset: u64) -> Self {
217 let mut cipher =
218 Self(ChaCha20::new(chacha20::Key::from_slice(key), &[0; 12].into()));
219 cipher.0.seek(offset);
220 cipher
221 }
222
223 pub fn encrypt(&mut self, buffer: &mut [u8]) {
224 fxfs_trace::duration!(c"StreamCipher::encrypt", "len" => buffer.len());
225 self.0.apply_keystream(buffer);
226 }
227
228 pub fn decrypt(&mut self, buffer: &mut [u8]) {
229 fxfs_trace::duration!(c"StreamCipher::decrypt", "len" => buffer.len());
230 self.0.apply_keystream(buffer);
231 }
232
233 pub fn offset(&self) -> u64 {
234 self.0.current_pos()
235 }
236}
237
238pub enum KeyPurpose {
241 Data,
243 Metadata,
245}
246
247pub enum WrappingKey {
250 Aes256GcmSiv([u8; 32]),
252 Fscrypt([u8; 64]),
254}
255impl From<[u8; 32]> for WrappingKey {
256 fn from(value: [u8; 32]) -> Self {
257 WrappingKey::Aes256GcmSiv(value)
258 }
259}
260impl From<[u8; 64]> for WrappingKey {
261 fn from(value: [u8; 64]) -> Self {
262 WrappingKey::Fscrypt(value)
263 }
264}
265
266#[async_trait]
274pub trait Crypt: Send + Sync {
275 async fn create_key(
280 &self,
281 owner: u64,
282 purpose: KeyPurpose,
283 ) -> Result<(FxfsKey, UnwrappedKey), zx::Status>;
284
285 async fn create_key_with_id(
290 &self,
291 owner: u64,
292 wrapping_key_id: WrappingKeyId,
293 object_type: ObjectType,
294 ) -> Result<(EncryptionKey, UnwrappedKey), zx::Status>;
295
296 async fn unwrap_key(
302 &self,
303 wrapped_key: &WrappedKey,
304 owner: u64,
305 ) -> Result<UnwrappedKey, zx::Status>;
306
307 async fn unwrap_keys(
312 &self,
313 keys: &BTreeMap<u64, WrappedKey>,
314 owner: u64,
315 ) -> Result<CipherSet, zx::Status> {
316 let futures: FuturesUnordered<_> = keys
317 .iter()
318 .map(|(key_id, key)| {
319 let key_id = *key_id;
320 let owner = owner;
321 async move {
322 let unwrapped_key = match self.unwrap_key(&key, owner).await {
323 Ok(unwrapped_key) => unwrapped_key,
324 Err(zx::Status::UNAVAILABLE) => return Ok((key_id, None)),
325 Err(e) => return Err(e),
326 };
327
328 cipher::key_to_cipher(&key, &unwrapped_key).map(|c| (key_id, c))
329 }
330 })
331 .collect();
332 let result = futures.try_collect::<BTreeMap<u64, _>>().await?;
333 Ok(result.into())
334 }
335}
336
337#[cfg(test)]
338mod tests {
339 use super::{StreamCipher, UnwrappedKey};
340
341 #[test]
342 fn test_stream_cipher_offset() {
343 let key = UnwrappedKey::new(vec![
344 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
345 25, 26, 27, 28, 29, 30, 31, 32,
346 ]);
347 let mut cipher1 = StreamCipher::new(&key, 0);
348 let mut p1 = [1, 2, 3, 4];
349 let mut c1 = p1.clone();
350 cipher1.encrypt(&mut c1);
351
352 let mut cipher2 = StreamCipher::new(&key, 1);
353 let p2 = [5, 6, 7, 8];
354 let mut c2 = p2.clone();
355 cipher2.encrypt(&mut c2);
356
357 let xor_fn = |buf1: &mut [u8], buf2| {
358 for (b1, b2) in buf1.iter_mut().zip(buf2) {
359 *b1 ^= b2;
360 }
361 };
362
363 xor_fn(&mut c1, &c2);
366 xor_fn(&mut p1, &p2);
367 assert_ne!(c1, p1);
368 }
369}