// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// //! BoringSSL-based implementation for the AuthGraph AES traits. use crate::ossl; use authgraph_core::{ ag_err, error::Error, key::{AesKey, Nonce12}, traits::AesGcm, vec_try, FallibleAllocExt, }; use authgraph_wire::ErrorCode; use openssl::symm::{Cipher, Crypter, Mode}; /// Tag size for AES-GCM-256. const TAG_LEN: usize = 16; /// BoringSSL-based implementation of the [`AesGcm`] trait. #[derive(Clone)] pub struct BoringAes; impl AesGcm for BoringAes { fn encrypt( &self, key: &AesKey, payload: &[u8], aad: &[u8], nonce: &Nonce12, ) -> Result, Error> { let cipher = Cipher::aes_256_gcm(); let mut crypter = ossl!(Crypter::new(cipher, Mode::Encrypt, &key.0, Some(&nonce.0)))?; ossl!(crypter.aad_update(aad))?; let mut ct = vec_try![0; payload.len() + cipher.block_size()]?; let mut count = ossl!(crypter.update(payload, &mut ct))?; count += ossl!(crypter.finalize(&mut ct))?; ct.truncate(count); let mut tag = [0; TAG_LEN]; ossl!(crypter.get_tag(&mut tag))?; ct.try_extend_from_slice(&tag)?; Ok(ct) } fn decrypt( &self, key: &AesKey, ct: &[u8], aad: &[u8], nonce: &Nonce12, ) -> Result, Error> { let cipher = Cipher::aes_256_gcm(); let mut crypter = ossl!(Crypter::new(cipher, Mode::Decrypt, &key.0, Some(&nonce.0)))?; let split_idx = ct.len().checked_sub(TAG_LEN).ok_or_else(|| ag_err!(InternalError, "too short"))?; let (ct, tag) = ct.split_at(split_idx); ossl!(crypter.aad_update(aad))?; let mut pt = vec_try![0; ct.len() + cipher.block_size()]?; let mut count = ossl!(crypter.update(ct, &mut pt))?; ossl!(crypter.set_tag(tag))?; count += ossl!(crypter.finalize(&mut pt))?; pt.truncate(count); Ok(pt) } fn box_clone(&self) -> Box { Box::new(self.clone()) } }