1use anyhow::{Context, Error};
6use fidl_fuchsia_fxfs::{
7 CryptCreateKeyResult, CryptManagementAddWrappingKeyResult,
8 CryptManagementForgetWrappingKeyResult, CryptManagementRequest, CryptManagementRequestStream,
9 CryptManagementSetActiveKeyResult, CryptRequest, CryptRequestStream, KeyPurpose,
10 ObjectType as FxfsFidlObjectType, WrappedKey,
11};
12
13use futures::stream::TryStreamExt;
14
15pub mod log;
16use log::*;
17
18use fxfs_crypt_common::CryptBase;
19use fxfs_crypto::Crypt as _;
20
21pub enum Services {
22 Crypt(CryptRequestStream),
23 CryptManagement(CryptManagementRequestStream),
24}
25
26pub struct CryptService {
27 inner: CryptBase,
28}
29
30impl CryptService {
31 pub fn new() -> Self {
32 Self { inner: CryptBase::new() }
33 }
34
35 async fn create_key(&self, owner: u64, purpose: KeyPurpose) -> CryptCreateKeyResult {
36 let purpose = purpose.try_into().map_err(zx::Status::into_raw)?;
37 let (fxfs_key, unwrapped_key) =
38 self.inner.create_key(owner, purpose).await.map_err(|e| e.into_raw())?;
39 Ok((fxfs_key.wrapping_key_id, (*fxfs_key.key).to_vec(), (*unwrapped_key).to_vec()))
40 }
41
42 async fn create_key_with_id(
43 &self,
44 owner: u64,
45 wrapping_key_id: u128,
46 object_type: FxfsFidlObjectType,
47 _flags: fidl_fuchsia_io::FscryptPolicyFlags,
48 ) -> Result<(WrappedKey, Vec<u8>), i32> {
49 let (encryption_key, unwrapped_key) = self
50 .inner
51 .create_key_with_id(owner, wrapping_key_id.to_le_bytes(), object_type)
52 .await
53 .map_err(|e| e.into_raw())?;
54
55 Ok((WrappedKey::from(encryption_key), (*unwrapped_key).to_vec()))
56 }
57
58 async fn unwrap_key(&self, owner: u64, wrapped_key: WrappedKey) -> Result<Vec<u8>, i32> {
59 let unwrapped_key =
60 self.inner.unwrap_key(&wrapped_key, owner).await.map_err(|e| e.into_raw())?;
61 Ok((*unwrapped_key).to_vec())
62 }
63
64 pub fn add_wrapping_key(
65 &self,
66 wrapping_key_id: u128,
67 key: Vec<u8>,
68 ) -> CryptManagementAddWrappingKeyResult {
69 let key: [u8; 32] = key.try_into().map_err(|_| zx::Status::INVALID_ARGS.into_raw())?;
70 self.inner.add_wrapping_key(wrapping_key_id.to_le_bytes(), key).map_err(|e| e.into_raw())
71 }
72
73 pub fn set_active_key(
74 &self,
75 purpose: KeyPurpose,
76 wrapping_key_id: u128,
77 ) -> CryptManagementSetActiveKeyResult {
78 let purpose = purpose.try_into().map_err(zx::Status::into_raw)?;
79 self.inner.set_active_key(purpose, wrapping_key_id.to_le_bytes()).map_err(|e| e.into_raw())
80 }
81
82 fn forget_wrapping_key(&self, wrapping_key_id: u128) -> CryptManagementForgetWrappingKeyResult {
83 self.inner.forget_wrapping_key(&wrapping_key_id.to_le_bytes()).map_err(|e| e.into_raw())
84 }
85
86 pub async fn handle_request(&self, stream: Services) -> Result<(), Error> {
87 match stream {
88 Services::Crypt(mut stream) => {
89 while let Some(request) = stream.try_next().await.context("Reading request")? {
90 match request {
91 CryptRequest::CreateKey { owner, purpose, responder } => {
92 responder
93 .send(match &self.create_key(owner, purpose).await {
94 Ok((id, wrapped, key)) => Ok((id, wrapped, key)),
95 Err(e) => Err(*e),
96 })
97 .unwrap_or_else(|e| {
98 error!(
101 error:? = e;
102 "Failed to send CreateKey response"
103 )
104 });
105 }
106 CryptRequest::CreateKeyWithId {
107 owner,
108 wrapping_key_id,
109 object_type,
110 flags,
111 responder,
112 } => {
113 responder
114 .send(
115 match self
116 .create_key_with_id(
117 owner,
118 u128::from_le_bytes(wrapping_key_id),
119 object_type,
120 flags,
121 )
122 .await
123 {
124 Ok((ref wrapped, ref key)) => Ok((wrapped, key, None)),
125 Err(e) => Err(e),
126 },
127 )
128 .unwrap_or_else(|e| {
129 error!(
132 error:? = e;
133 "Failed to send CreateKeyWithId response"
134 )
135 });
136 }
137 CryptRequest::UnwrapKey { owner, wrapped_key, responder } => {
138 let response;
139 responder
140 .send({
141 response = self.unwrap_key(owner, wrapped_key).await;
142 match &response {
143 Ok(v) => Ok((&v[..], None)),
144 Err(e) => Err(*e),
145 }
146 })
147 .unwrap_or_else(|e| {
148 error!(
151 error:? = e;
152 "Failed to send UnwrapKey response"
153 )
154 });
155 }
156 }
157 }
158 }
159 Services::CryptManagement(mut stream) => {
160 while let Some(request) = stream.try_next().await.context("Reading request")? {
161 match request {
162 CryptManagementRequest::AddWrappingKey {
163 wrapping_key_id,
164 key,
165 responder,
166 } => {
167 let response =
168 self.add_wrapping_key(u128::from_le_bytes(wrapping_key_id), key);
169 responder.send(response).unwrap_or_else(|e| {
170 error!(
173 error:? = e;
174 "Failed to send AddWrappingKey response"
175 )
176 });
177 }
178 CryptManagementRequest::SetActiveKey {
179 purpose,
180 wrapping_key_id,
181 responder,
182 } => {
183 let response =
184 self.set_active_key(purpose, u128::from_le_bytes(wrapping_key_id));
185 responder.send(response).unwrap_or_else(
186 |e| error!(error:? = e;"Failed to send SetActiveKey response"),
189 );
190 }
191 CryptManagementRequest::ForgetWrappingKey {
192 wrapping_key_id,
193 responder,
194 } => {
195 let response =
196 self.forget_wrapping_key(u128::from_le_bytes(wrapping_key_id));
197 responder.send(response).unwrap_or_else(|e| {
198 error!(
201 error:? = e;
202 "Failed to send ForgetWrappingKey response"
203 )
204 });
205 }
206 }
207 }
208 }
209 }
210 Ok(())
211 }
212}
213
214#[cfg(test)]
215mod tests {
216 use super::CryptService;
217 use fidl_fuchsia_fxfs::{FxfsKey, KeyPurpose, ObjectType, WrappedKey};
218
219 #[fuchsia::test]
220 async fn wrap_unwrap_key() {
221 let service = CryptService::new();
222 let key = vec![0xABu8; 32];
223 service.add_wrapping_key(1, key.clone()).expect("add_key failed");
224 service.set_active_key(KeyPurpose::Data, 1).expect("set_active_key failed");
225
226 let (wrapping_key_id, wrapped_key, unwrapped_key) =
227 service.create_key(0, KeyPurpose::Data).await.expect("create_key failed");
228 let wrapping_key_id_int = u128::from_le_bytes(wrapping_key_id);
229 assert_eq!(wrapping_key_id_int, 1);
230 let unwrap_result = service
231 .unwrap_key(
232 0,
233 WrappedKey::Fxfs(FxfsKey {
234 wrapping_key_id,
235 wrapped_key: wrapped_key.try_into().unwrap(),
236 }),
237 )
238 .await
239 .expect("unwrap_key failed");
240 assert_eq!(unwrap_result, unwrapped_key);
241
242 let (wrapping_key_id, wrapped_key, unwrapped_key) =
244 service.create_key(1, KeyPurpose::Data).await.expect("create_key failed");
245 let wrapping_key_id_int = u128::from_le_bytes(wrapping_key_id);
246 assert_eq!(wrapping_key_id_int, 1);
247 let unwrap_result = service
248 .unwrap_key(
249 1,
250 WrappedKey::Fxfs(FxfsKey {
251 wrapping_key_id,
252 wrapped_key: wrapped_key.try_into().unwrap(),
253 }),
254 )
255 .await
256 .expect("unwrap_key failed");
257 assert_eq!(unwrap_result, unwrapped_key);
258 }
259
260 #[fuchsia::test]
261 async fn wrap_unwrap_key_with_arbitrary_wrapping_key() {
262 let service = CryptService::new();
263 let key = vec![0xABu8; 32];
264 service.add_wrapping_key(2, key.clone()).expect("add_key failed");
265
266 let (wrapped_key, unwrapped_key) = service
267 .create_key_with_id(
268 0,
269 2,
270 ObjectType::File,
271 fidl_fuchsia_io::FscryptPolicyFlags::empty(),
272 )
273 .await
274 .expect("create_key_with_id failed");
275 let unwrap_result = service.unwrap_key(0, wrapped_key).await.expect("unwrap_key failed");
276 assert_eq!(unwrap_result, unwrapped_key);
277
278 let (wrapped_key, unwrapped_key) = service
280 .create_key_with_id(
281 1,
282 2,
283 ObjectType::File,
284 fidl_fuchsia_io::FscryptPolicyFlags::empty(),
285 )
286 .await
287 .expect("create_key_with_id failed");
288 let unwrap_result = service.unwrap_key(1, wrapped_key).await.expect("unwrap_key failed");
289 assert_eq!(unwrap_result, unwrapped_key);
290 }
291
292 #[fuchsia::test]
293 async fn create_key_with_wrapping_key_that_does_not_exist() {
294 let service = CryptService::new();
295 service
296 .create_key_with_id(
297 0,
298 2,
299 ObjectType::File,
300 fidl_fuchsia_io::FscryptPolicyFlags::empty(),
301 )
302 .await
303 .expect_err("create_key_with_id should fail if the wrapping key does not exist");
304
305 let wrapping_key = vec![0xABu8; 32];
306 service.add_wrapping_key(2, wrapping_key.clone()).expect("add_key failed");
307
308 let (wrapped_key, unwrapped_key) = service
309 .create_key_with_id(
310 0,
311 2,
312 ObjectType::File,
313 fidl_fuchsia_io::FscryptPolicyFlags::empty(),
314 )
315 .await
316 .expect("create_key_with_id failed");
317 let unwrap_result = service.unwrap_key(0, wrapped_key).await.expect("unwrap_key failed");
318 assert_eq!(unwrap_result, unwrapped_key);
319 }
320
321 #[fuchsia::test]
322 async fn unwrap_key_wrong_key() {
323 let service = CryptService::new();
324 let key = vec![0xABu8; 32];
325 service.add_wrapping_key(0, key.clone()).expect("add_key failed");
326 service.set_active_key(KeyPurpose::Data, 0).expect("set_active_key failed");
327
328 let (wrapping_key_id, mut wrapped_key, _) =
329 service.create_key(0, KeyPurpose::Data).await.expect("create_key failed");
330 for byte in &mut wrapped_key {
331 *byte ^= 0xff;
332 }
333 service
334 .unwrap_key(
335 0,
336 WrappedKey::Fxfs(FxfsKey {
337 wrapping_key_id,
338 wrapped_key: wrapped_key.try_into().unwrap(),
339 }),
340 )
341 .await
342 .expect_err("unwrap_key should fail");
343 }
344
345 #[fuchsia::test]
346 async fn unwrap_key_wrong_owner() {
347 let service = CryptService::new();
348 let key = vec![0xABu8; 32];
349 service.add_wrapping_key(0, key.clone()).expect("add_key failed");
350 service.set_active_key(KeyPurpose::Data, 0).expect("set_active_key failed");
351
352 let (wrapping_key_id, wrapped_key, _) =
353 service.create_key(0, KeyPurpose::Data).await.expect("create_key failed");
354 service
355 .unwrap_key(
356 1,
357 WrappedKey::Fxfs(FxfsKey {
358 wrapping_key_id,
359 wrapped_key: wrapped_key.try_into().unwrap(),
360 }),
361 )
362 .await
363 .expect_err("unwrap_key should fail");
364 }
365
366 #[test]
367 fn add_forget_key() {
368 let service = CryptService::new();
369 let key = vec![0xABu8; 32];
370 service.add_wrapping_key(0, key.clone()).expect("add_key failed");
371 service.add_wrapping_key(0, key.clone()).expect_err("add_key should fail on a used slot");
372 service.add_wrapping_key(1, key.clone()).expect("add_key failed");
373
374 service.forget_wrapping_key(0).expect("forget_key failed");
375
376 service.add_wrapping_key(0, key.clone()).expect("add_key failed");
377 }
378
379 #[test]
380 fn set_active_key() {
381 let service = CryptService::new();
382 let key = vec![0xABu8; 32];
383
384 service
385 .set_active_key(KeyPurpose::Data, 0)
386 .expect_err("set_active_key should fail when targeting nonexistent keys");
387
388 service.add_wrapping_key(0, key.clone()).expect("add_key failed");
389 service.add_wrapping_key(1, key.clone()).expect("add_key failed");
390
391 service.set_active_key(KeyPurpose::Data, 0).expect("set_active_key failed");
392 service.set_active_key(KeyPurpose::Metadata, 1).expect("set_active_key failed");
393
394 service.forget_wrapping_key(0).expect_err("forget_key should fail on an active key");
395 service.forget_wrapping_key(1).expect_err("forget_key should fail on an active key");
396 }
397}