fxfs_crypt/
lib.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use aes_gcm_siv::aead::Aead;
6use aes_gcm_siv::{Aes256GcmSiv, Key, KeyInit as _, Nonce};
7use anyhow::{Context, Error};
8use fidl_fuchsia_fxfs::{
9    CryptCreateKeyResult, CryptCreateKeyWithIdResult, CryptManagementAddWrappingKeyResult,
10    CryptManagementForgetWrappingKeyResult, CryptManagementRequest, CryptManagementRequestStream,
11    CryptManagementSetActiveKeyResult, CryptRequest, CryptRequestStream, CryptUnwrapKeyResult,
12    KeyPurpose,
13};
14
15use fuchsia_sync::Mutex;
16use futures::stream::TryStreamExt;
17use std::collections::hash_map::{Entry, HashMap};
18
19pub mod log;
20use log::*;
21
22pub enum Services {
23    Crypt(CryptRequestStream),
24    CryptManagement(CryptManagementRequestStream),
25}
26
27#[derive(Default)]
28struct CryptServiceInner {
29    ciphers: HashMap<u128, Aes256GcmSiv>,
30    active_data_key: Option<u128>,
31    active_metadata_key: Option<u128>,
32}
33
34pub struct CryptService {
35    inner: Mutex<CryptServiceInner>,
36}
37
38fn zero_extended_nonce(val: u64) -> Nonce {
39    let mut nonce = Nonce::default();
40    nonce.as_mut_slice()[..8].copy_from_slice(&val.to_le_bytes());
41    nonce
42}
43
44impl CryptService {
45    pub fn new() -> Self {
46        Self { inner: Mutex::new(CryptServiceInner::default()) }
47    }
48
49    fn create_key(&self, owner: u64, purpose: KeyPurpose) -> CryptCreateKeyResult {
50        let inner = self.inner.lock();
51        let wrapping_key_id = match purpose {
52            KeyPurpose::Data => inner.active_data_key.as_ref(),
53            KeyPurpose::Metadata => inner.active_metadata_key.as_ref(),
54            _ => return Err(zx::Status::INVALID_ARGS.into_raw()),
55        }
56        .ok_or_else(|| zx::Status::BAD_STATE.into_raw())?;
57        let cipher =
58            inner.ciphers.get(wrapping_key_id).ok_or_else(|| zx::Status::BAD_STATE.into_raw())?;
59        let nonce = zero_extended_nonce(owner);
60
61        let mut key = [0u8; 32];
62        zx::cprng_draw(&mut key);
63
64        let wrapped = cipher.encrypt(&nonce, &key[..]).map_err(|e| {
65            error!(error:? = e; "Failed to wrap key");
66            zx::Status::INTERNAL.into_raw()
67        })?;
68
69        Ok((wrapping_key_id.to_le_bytes(), wrapped.into(), key.into()))
70    }
71
72    fn create_key_with_id(&self, owner: u64, wrapping_key_id: u128) -> CryptCreateKeyWithIdResult {
73        let inner = self.inner.lock();
74        let cipher =
75            inner.ciphers.get(&wrapping_key_id).ok_or_else(|| zx::Status::NOT_FOUND.into_raw())?;
76        let nonce = zero_extended_nonce(owner);
77
78        let mut key = [0u8; 32];
79        zx::cprng_draw(&mut key);
80
81        let wrapped = cipher.encrypt(&nonce, &key[..]).map_err(|error| {
82            error!(error:?; "Failed to wrap key");
83            zx::Status::INTERNAL.into_raw()
84        })?;
85
86        Ok((wrapped.into(), key.into()))
87    }
88
89    fn unwrap_key(&self, wrapping_key_id: u128, owner: u64, key: Vec<u8>) -> CryptUnwrapKeyResult {
90        let inner = self.inner.lock();
91        let cipher =
92            inner.ciphers.get(&wrapping_key_id).ok_or_else(|| zx::Status::NOT_FOUND.into_raw())?;
93        let nonce = zero_extended_nonce(owner);
94
95        cipher.decrypt(&nonce, &key[..]).map_err(|_| zx::Status::IO_DATA_INTEGRITY.into_raw())
96    }
97
98    pub fn add_wrapping_key(
99        &self,
100        wrapping_key_id: u128,
101        key: Vec<u8>,
102    ) -> CryptManagementAddWrappingKeyResult {
103        let mut inner = self.inner.lock();
104        match inner.ciphers.entry(wrapping_key_id) {
105            Entry::Occupied(_) => Err(zx::Status::ALREADY_EXISTS.into_raw()),
106            Entry::Vacant(vacant) => {
107                info!(wrapping_key_id; "Adding wrapping key");
108                vacant.insert(Aes256GcmSiv::new(Key::<Aes256GcmSiv>::from_slice(&key[..])));
109                Ok(())
110            }
111        }
112    }
113
114    pub fn set_active_key(
115        &self,
116        purpose: KeyPurpose,
117        wrapping_key_id: u128,
118    ) -> CryptManagementSetActiveKeyResult {
119        let mut inner = self.inner.lock();
120        if !inner.ciphers.contains_key(&wrapping_key_id) {
121            return Err(zx::Status::NOT_FOUND.into_raw());
122        }
123        match purpose {
124            KeyPurpose::Data => inner.active_data_key = Some(wrapping_key_id),
125            KeyPurpose::Metadata => inner.active_metadata_key = Some(wrapping_key_id),
126            _ => return Err(zx::Status::INVALID_ARGS.into_raw()),
127        }
128        Ok(())
129    }
130
131    fn forget_wrapping_key(&self, wrapping_key_id: u128) -> CryptManagementForgetWrappingKeyResult {
132        info!(wrapping_key_id; "Removing wrapping key");
133        let mut inner = self.inner.lock();
134        if let Some(id) = &inner.active_data_key {
135            if *id == wrapping_key_id {
136                return Err(zx::Status::INVALID_ARGS.into_raw());
137            }
138        }
139        if let Some(id) = &inner.active_metadata_key {
140            if *id == wrapping_key_id {
141                return Err(zx::Status::INVALID_ARGS.into_raw());
142            }
143        }
144        inner.ciphers.remove(&wrapping_key_id);
145        Ok(())
146    }
147
148    pub async fn handle_request(&self, stream: Services) -> Result<(), Error> {
149        match stream {
150            Services::Crypt(mut stream) => {
151                while let Some(request) = stream.try_next().await.context("Reading request")? {
152                    match request {
153                        CryptRequest::CreateKey { owner, purpose, responder } => {
154                            responder
155                                .send(match &self.create_key(owner, purpose) {
156                                    Ok((id, ref wrapped, ref key)) => Ok((id, wrapped, key)),
157                                    Err(e) => Err(*e),
158                                })
159                                .unwrap_or_else(|e| {
160                                    // TODO(https://fxbug.dev/360919323): we can use `:err` when we
161                                    // enable the log kv_std feature.
162                                    error!(
163                                        error:? = e;
164                                        "Failed to send CreateKey response"
165                                    )
166                                });
167                        }
168                        CryptRequest::CreateKeyWithId { owner, wrapping_key_id, responder } => {
169                            responder
170                                .send(
171                                    match self.create_key_with_id(
172                                        owner,
173                                        u128::from_le_bytes(wrapping_key_id),
174                                    ) {
175                                        Ok((ref wrapped, ref key)) => Ok((wrapped, key)),
176                                        Err(e) => Err(e),
177                                    },
178                                )
179                                .unwrap_or_else(|e| {
180                                    // TODO(https://fxbug.dev/360919323): we can use `:err` when we
181                                    // enable the log kv_std feature.
182                                    error!(
183                                        error:? = e;
184                                        "Failed to send CreateKeyWithId response"
185                                    )
186                                });
187                        }
188                        CryptRequest::UnwrapKey { wrapping_key_id, owner, key, responder } => {
189                            responder
190                                .send(
191                                    match self.unwrap_key(
192                                        u128::from_le_bytes(wrapping_key_id),
193                                        owner,
194                                        key,
195                                    ) {
196                                        Ok(ref unwrapped) => Ok(unwrapped),
197                                        Err(e) => Err(e),
198                                    },
199                                )
200                                .unwrap_or_else(|e| {
201                                    // TODO(https://fxbug.dev/360919323): we can use `:err` when we
202                                    // enable the log kv_std feature.
203                                    error!(
204                                        error:? = e;
205                                        "Failed to send UnwrapKey response"
206                                    )
207                                });
208                        }
209                    }
210                }
211            }
212            Services::CryptManagement(mut stream) => {
213                while let Some(request) = stream.try_next().await.context("Reading request")? {
214                    match request {
215                        CryptManagementRequest::AddWrappingKey {
216                            wrapping_key_id,
217                            key,
218                            responder,
219                        } => {
220                            let response =
221                                self.add_wrapping_key(u128::from_le_bytes(wrapping_key_id), key);
222                            responder.send(response).unwrap_or_else(|e| {
223                                // TODO(https://fxbug.dev/360919323): we can use `:err` when we
224                                // enable the log kv_std feature.
225                                error!(
226                                    error:? = e;
227                                    "Failed to send AddWrappingKey response"
228                                )
229                            });
230                        }
231                        CryptManagementRequest::SetActiveKey {
232                            purpose,
233                            wrapping_key_id,
234                            responder,
235                        } => {
236                            let response =
237                                self.set_active_key(purpose, u128::from_le_bytes(wrapping_key_id));
238                            responder.send(response).unwrap_or_else(
239                                // TODO(https://fxbug.dev/360919323): we can use `:err` when we
240                                // enable the log kv_std feature.
241                                |e| error!(error:? = e;"Failed to send SetActiveKey response"),
242                            );
243                        }
244                        CryptManagementRequest::ForgetWrappingKey {
245                            wrapping_key_id,
246                            responder,
247                        } => {
248                            let response =
249                                self.forget_wrapping_key(u128::from_le_bytes(wrapping_key_id));
250                            responder.send(response).unwrap_or_else(|e| {
251                                // TODO(https://fxbug.dev/360919323): we can use `:err` when we
252                                // enable the log kv_std feature.
253                                error!(
254                                    error:? = e;
255                                    "Failed to send ForgetWrappingKey response"
256                                )
257                            });
258                        }
259                    }
260                }
261            }
262        }
263        Ok(())
264    }
265}
266
267#[cfg(test)]
268mod tests {
269    use super::CryptService;
270    use fidl_fuchsia_fxfs::KeyPurpose;
271
272    #[test]
273    fn wrap_unwrap_key() {
274        let service = CryptService::new();
275        let key = vec![0xABu8; 32];
276        service.add_wrapping_key(1, key.clone()).expect("add_key failed");
277        service.set_active_key(KeyPurpose::Data, 1).expect("set_active_key failed");
278
279        let (wrapping_key_id, wrapped, unwrapped) =
280            service.create_key(0, KeyPurpose::Data).expect("create_key failed");
281        let wrapping_key_id_int = u128::from_le_bytes(wrapping_key_id);
282        assert_eq!(wrapping_key_id_int, 1);
283        let unwrap_result =
284            service.unwrap_key(wrapping_key_id_int, 0, wrapped).expect("unwrap_key failed");
285        assert_eq!(unwrap_result, unwrapped);
286
287        // Do it twice to make sure the service can use the same key repeatedly.
288        let (wrapping_key_id, wrapped, unwrapped) =
289            service.create_key(1, KeyPurpose::Data).expect("create_key failed");
290        let wrapping_key_id_int = u128::from_le_bytes(wrapping_key_id);
291        assert_eq!(wrapping_key_id_int, 1);
292        let unwrap_result =
293            service.unwrap_key(wrapping_key_id_int, 1, wrapped).expect("unwrap_key failed");
294        assert_eq!(unwrap_result, unwrapped);
295    }
296
297    #[test]
298    fn wrap_unwrap_key_with_arbitrary_wrapping_key() {
299        let service = CryptService::new();
300        let key = vec![0xABu8; 32];
301        service.add_wrapping_key(2, key.clone()).expect("add_key failed");
302
303        let (wrapped, unwrapped) =
304            service.create_key_with_id(0, 2).expect("create_key_with_id failed");
305        let unwrap_result = service.unwrap_key(2, 0, wrapped).expect("unwrap_key failed");
306        assert_eq!(unwrap_result, unwrapped);
307
308        // Do it twice to make sure the service can use the same key repeatedly.
309        let (wrapped, unwrapped) =
310            service.create_key_with_id(1, 2).expect("create_key_with_id failed");
311        let unwrap_result = service.unwrap_key(2, 1, wrapped).expect("unwrap_key failed");
312        assert_eq!(unwrap_result, unwrapped);
313    }
314
315    #[test]
316    fn create_key_with_wrapping_key_that_does_not_exist() {
317        let service = CryptService::new();
318        service
319            .create_key_with_id(0, 2)
320            .expect_err("create_key_with_id should fail if the wrapping key does not exist");
321
322        let wrapping_key = vec![0xABu8; 32];
323        service.add_wrapping_key(2, wrapping_key.clone()).expect("add_key failed");
324
325        let (wrapped, unwrapped) =
326            service.create_key_with_id(0, 2).expect("create_key_with_id failed");
327        let unwrap_result = service.unwrap_key(2, 0, wrapped).expect("unwrap_key failed");
328        assert_eq!(unwrap_result, unwrapped);
329    }
330
331    #[test]
332    fn unwrap_key_wrong_key() {
333        let service = CryptService::new();
334        let key = vec![0xABu8; 32];
335        service.add_wrapping_key(0, key.clone()).expect("add_key failed");
336        service.set_active_key(KeyPurpose::Data, 0).expect("set_active_key failed");
337
338        let (wrapping_key_id, mut wrapped, _) =
339            service.create_key(0, KeyPurpose::Data).expect("create_key failed");
340        for byte in &mut wrapped {
341            *byte ^= 0xff;
342        }
343        service
344            .unwrap_key(u128::from_le_bytes(wrapping_key_id), 0, wrapped)
345            .expect_err("unwrap_key should fail");
346    }
347
348    #[test]
349    fn unwrap_key_wrong_owner() {
350        let service = CryptService::new();
351        let key = vec![0xABu8; 32];
352        service.add_wrapping_key(0, key.clone()).expect("add_key failed");
353        service.set_active_key(KeyPurpose::Data, 0).expect("set_active_key failed");
354
355        let (wrapping_key_id, wrapped, _) =
356            service.create_key(0, KeyPurpose::Data).expect("create_key failed");
357        service
358            .unwrap_key(u128::from_le_bytes(wrapping_key_id), 1, wrapped)
359            .expect_err("unwrap_key should fail");
360    }
361
362    #[test]
363    fn add_forget_key() {
364        let service = CryptService::new();
365        let key = vec![0xABu8; 32];
366        service.add_wrapping_key(0, key.clone()).expect("add_key failed");
367        service.add_wrapping_key(0, key.clone()).expect_err("add_key should fail on a used slot");
368        service.add_wrapping_key(1, key.clone()).expect("add_key failed");
369
370        service.forget_wrapping_key(0).expect("forget_key failed");
371
372        service.add_wrapping_key(0, key.clone()).expect("add_key failed");
373    }
374
375    #[test]
376    fn set_active_key() {
377        let service = CryptService::new();
378        let key = vec![0xABu8; 32];
379
380        service
381            .set_active_key(KeyPurpose::Data, 0)
382            .expect_err("set_active_key should fail when targeting nonexistent keys");
383
384        service.add_wrapping_key(0, key.clone()).expect("add_key failed");
385        service.add_wrapping_key(1, key.clone()).expect("add_key failed");
386
387        service.set_active_key(KeyPurpose::Data, 0).expect("set_active_key failed");
388        service.set_active_key(KeyPurpose::Metadata, 1).expect("set_active_key failed");
389
390        service.forget_wrapping_key(0).expect_err("forget_key should fail on an active key");
391        service.forget_wrapping_key(1).expect_err("forget_key should fail on an active key");
392    }
393}