1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ////////////////////////////////////////////////////////////////////////////////
16 
17 //! BoringSSL-based implementation for the AuthGraph AES traits.
18 use crate::ossl;
19 use authgraph_core::{
20     ag_err,
21     error::Error,
22     key::{AesKey, Nonce12},
23     traits::AesGcm,
24     vec_try, FallibleAllocExt,
25 };
26 use authgraph_wire::ErrorCode;
27 use openssl::symm::{Cipher, Crypter, Mode};
28 
29 /// Tag size for AES-GCM-256.
30 const TAG_LEN: usize = 16;
31 
32 /// BoringSSL-based implementation of the [`AesGcm`] trait.
33 #[derive(Clone)]
34 pub struct BoringAes;
35 
36 impl AesGcm for BoringAes {
encrypt( &self, key: &AesKey, payload: &[u8], aad: &[u8], nonce: &Nonce12, ) -> Result<Vec<u8>, Error>37     fn encrypt(
38         &self,
39         key: &AesKey,
40         payload: &[u8],
41         aad: &[u8],
42         nonce: &Nonce12,
43     ) -> Result<Vec<u8>, Error> {
44         let cipher = Cipher::aes_256_gcm();
45         let mut crypter = ossl!(Crypter::new(cipher, Mode::Encrypt, &key.0, Some(&nonce.0)))?;
46 
47         ossl!(crypter.aad_update(aad))?;
48         let mut ct = vec_try![0; payload.len() + cipher.block_size()]?;
49         let mut count = ossl!(crypter.update(payload, &mut ct))?;
50         count += ossl!(crypter.finalize(&mut ct))?;
51         ct.truncate(count);
52 
53         let mut tag = [0; TAG_LEN];
54         ossl!(crypter.get_tag(&mut tag))?;
55         ct.try_extend_from_slice(&tag)?;
56 
57         Ok(ct)
58     }
59 
decrypt( &self, key: &AesKey, ct: &[u8], aad: &[u8], nonce: &Nonce12, ) -> Result<Vec<u8>, Error>60     fn decrypt(
61         &self,
62         key: &AesKey,
63         ct: &[u8],
64         aad: &[u8],
65         nonce: &Nonce12,
66     ) -> Result<Vec<u8>, Error> {
67         let cipher = Cipher::aes_256_gcm();
68         let mut crypter = ossl!(Crypter::new(cipher, Mode::Decrypt, &key.0, Some(&nonce.0)))?;
69 
70         let split_idx =
71             ct.len().checked_sub(TAG_LEN).ok_or_else(|| ag_err!(InternalError, "too short"))?;
72         let (ct, tag) = ct.split_at(split_idx);
73 
74         ossl!(crypter.aad_update(aad))?;
75         let mut pt = vec_try![0; ct.len() + cipher.block_size()]?;
76         let mut count = ossl!(crypter.update(ct, &mut pt))?;
77 
78         ossl!(crypter.set_tag(tag))?;
79         count += ossl!(crypter.finalize(&mut pt))?;
80         pt.truncate(count);
81 
82         Ok(pt)
83     }
box_clone(&self) -> Box<dyn AesGcm>84     fn box_clone(&self) -> Box<dyn AesGcm> {
85         Box::new(self.clone())
86     }
87 }
88