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