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