1use crate::{EncryptionKey, UnwrappedKey, WrappedKey};
5use anyhow::Error;
6use std::collections::BTreeMap;
7use std::sync::Arc;
8pub use storage_ptr_slice::MutPtrByteSlice;
9use zx_status as zx;
10
11pub mod fscrypt_ino_lblk32;
12#[cfg(test)]
13mod fscrypt_test_data;
14pub(crate) mod fxfs;
15
16pub const FSCRYPT_PADDING: usize = 16;
21const SECTOR_SIZE: u64 = 512;
24
25pub trait Cipher: std::fmt::Debug + Send + Sync {
27 fn encrypt(
34 &self,
35 ino: u64,
36 attribute_id: u64,
37 device_offset: u64,
38 file_offset: u64,
39 buffer: MutPtrByteSlice<'_>,
40 ) -> Result<(), Error>;
41
42 fn decrypt(
49 &self,
50 ino: u64,
51 attribute_id: u64,
52 device_offset: u64,
53 file_offset: u64,
54 buffer: MutPtrByteSlice<'_>,
55 ) -> Result<(), Error>;
56
57 fn encrypt_filename(&self, object_id: u64, buffer: &mut Vec<u8>) -> Result<(), Error>;
59
60 fn decrypt_filename(&self, object_id: u64, buffer: &mut Vec<u8>) -> Result<(), Error>;
62
63 fn encrypt_symlink(&self, object_id: u64, buffer: &mut Vec<u8>) -> Result<(), Error> {
65 self.encrypt_filename(object_id, buffer)
66 }
67
68 fn decrypt_symlink(&self, object_id: u64, buffer: &mut Vec<u8>) -> Result<(), Error> {
70 self.decrypt_filename(object_id, buffer)
71 }
72
73 fn hash_code(&self, _raw_filename: &[u8], filename: &str) -> Option<u32>;
76
77 fn hash_code_casefold(&self, _filename: &str) -> u32;
79
80 fn supports_inline_encryption(&self) -> bool;
82
83 fn crypt_ctx(&self, ino: u64, attribute_id: u64, file_offset: u64) -> Option<(u32, u8)>;
86}
87
88#[derive(Clone, Copy, Debug, PartialEq, Eq)]
89pub enum KeyType {
90 LegacyFxfs,
91 Fxfs,
92 FscryptInoLblk32Dir,
93 FscryptInoLblk32File,
94}
95
96pub trait ToKeyType {
97 fn to_key_type(&self) -> Option<KeyType>;
98}
99
100impl ToKeyType for WrappedKey {
101 fn to_key_type(&self) -> Option<KeyType> {
102 match self {
103 WrappedKey::Fxfs(_) => Some(KeyType::Fxfs),
104 WrappedKey::FscryptInoLblk32Dir { .. } => Some(KeyType::FscryptInoLblk32Dir),
105 WrappedKey::FscryptInoLblk32File { .. } => Some(KeyType::FscryptInoLblk32File),
106 _ => None,
107 }
108 }
109}
110
111impl ToKeyType for EncryptionKey {
112 fn to_key_type(&self) -> Option<KeyType> {
113 match self {
114 EncryptionKey::LegacyFxfs(_) => Some(KeyType::LegacyFxfs),
115 EncryptionKey::Fxfs(_) => Some(KeyType::Fxfs),
116 EncryptionKey::FscryptInoLblk32Dir { .. } => Some(KeyType::FscryptInoLblk32Dir),
117 EncryptionKey::FscryptInoLblk32File { .. } => Some(KeyType::FscryptInoLblk32File),
118 }
119 }
120}
121
122impl ToKeyType for KeyType {
123 fn to_key_type(&self) -> Option<KeyType> {
124 Some(*self)
125 }
126}
127
128#[inline]
132pub fn key_to_cipher(
133 key_type: &impl ToKeyType,
134 unwrapped_key: &UnwrappedKey,
135) -> Result<Arc<dyn Cipher>, zx::Status> {
136 key_type
137 .to_key_type()
138 .map(|key_type| match key_type {
139 KeyType::LegacyFxfs => {
140 Arc::new(fxfs::FxfsCipher::new_legacy(&unwrapped_key)) as Arc<dyn Cipher>
141 }
142 KeyType::Fxfs => Arc::new(fxfs::FxfsCipher::new(&unwrapped_key)) as Arc<dyn Cipher>,
143 KeyType::FscryptInoLblk32Dir => {
144 Arc::new(fscrypt_ino_lblk32::FscryptInoLblk32DirCipher::new(&unwrapped_key))
145 }
146 KeyType::FscryptInoLblk32File => {
147 Arc::new(fscrypt_ino_lblk32::FscryptInoLblk32FileCipher::new(&unwrapped_key))
148 }
149 })
150 .ok_or(zx::Status::NOT_SUPPORTED)
151}
152
153#[derive(Clone, Debug)]
154pub enum CipherHolder {
155 Cipher(Arc<dyn Cipher>),
156 Unavailable,
157}
158
159impl CipherHolder {
160 pub fn into_cipher(self) -> Option<Arc<dyn Cipher>> {
161 match self {
162 CipherHolder::Cipher(c) => Some(c),
163 _ => None,
164 }
165 }
166}
167
168#[derive(Clone, Debug, Default)]
170pub struct CipherSet(BTreeMap<u64, CipherHolder>);
171impl CipherSet {
172 pub fn find_key(self: &Arc<Self>, id: u64) -> FindKeyResult {
173 match self.0.get(&id) {
174 Some(CipherHolder::Cipher(cipher)) => FindKeyResult::Key(Arc::clone(cipher)),
175 Some(CipherHolder::Unavailable) => FindKeyResult::Unavailable,
176 None => FindKeyResult::NotFound,
177 }
178 }
179
180 pub fn add_key(&mut self, id: u64, cipher: CipherHolder) {
181 self.0.insert(id, cipher);
182 }
183}
184impl From<Vec<(u64, CipherHolder)>> for CipherSet {
185 fn from(keys: Vec<(u64, CipherHolder)>) -> Self {
186 Self(keys.into_iter().collect())
187 }
188}
189impl From<BTreeMap<u64, CipherHolder>> for CipherSet {
190 fn from(keys: BTreeMap<u64, CipherHolder>) -> Self {
191 Self(keys)
192 }
193}
194
195pub enum FindKeyResult {
196 NotFound,
198 Unavailable,
200 Key(Arc<dyn Cipher>),
201}
202
203pub use storage_xts::{Tweak, XtsProcessor};