mirror of
https://github.com/AntelopeIO/boringssl.git
synced 2026-07-21 14:43:53 +00:00
Add Rust bindings to AES-GCM through the EVP_AEAD_* APIs
Change-Id: I295b0142b4448a5ee10ca9b092a2c3eaa1fffc86 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60405 Reviewed-by: David Benjamin <davidben@google.com> Reviewed-by: Bob Beck <bbe@google.com> Commit-Queue: Bob Beck <bbe@google.com>
This commit is contained in:
committed by
Boringssl LUCI CQ
parent
5d2a41d869
commit
f896fbd7a9
@@ -66,11 +66,6 @@ impl Aead for AesGcmSiv {
|
||||
}
|
||||
}
|
||||
|
||||
// Private implementation of an AEAD which is generic over Nonce size and Tag size. This should
|
||||
// only be exposed publicly by wrapper types which provide the correctly sized const generics for
|
||||
// the given aead algorithm.
|
||||
struct AeadImpl<const N: usize, const T: usize>(*mut EVP_AEAD_CTX);
|
||||
|
||||
trait EvpAeadType {
|
||||
type Key: AsRef<[u8]>;
|
||||
fn evp_aead() -> *const EVP_AEAD;
|
||||
@@ -98,6 +93,59 @@ impl EvpAeadType for EvpAes256GcmSiv {
|
||||
}
|
||||
}
|
||||
|
||||
/// AES-GCM implementation.
|
||||
pub struct AesGcm(AeadImpl<12, 16>);
|
||||
|
||||
/// Instantiates a new AES-128-GCM instance from key material.
|
||||
pub fn new_aes_128_gcm(key: &[u8; 16]) -> AesGcm {
|
||||
AesGcm(AeadImpl::new::<EvpAes128Gcm>(key))
|
||||
}
|
||||
|
||||
/// Instantiates a new AES-256-GCM instance from key material.
|
||||
pub fn new_aes_256_gcm(key: &[u8; 32]) -> AesGcm {
|
||||
AesGcm(AeadImpl::new::<EvpAes256Gcm>(key))
|
||||
}
|
||||
|
||||
impl Aead for AesGcm {
|
||||
const TAG_SIZE: usize = 16;
|
||||
type Nonce = [u8; 12];
|
||||
|
||||
fn encrypt(&self, msg: &[u8], aad: &[u8], nonce: &[u8; 12]) -> Result<Vec<u8>, AeadError> {
|
||||
self.0.encrypt(msg, aad, nonce)
|
||||
}
|
||||
|
||||
fn decrypt(&self, msg: &[u8], aad: &[u8], nonce: &[u8; 12]) -> Result<Vec<u8>, AeadError> {
|
||||
self.0.decrypt(msg, aad, nonce)
|
||||
}
|
||||
}
|
||||
|
||||
struct EvpAes128Gcm;
|
||||
impl EvpAeadType for EvpAes128Gcm {
|
||||
type Key = [u8; 16];
|
||||
|
||||
fn evp_aead() -> *const EVP_AEAD {
|
||||
// Safety:
|
||||
// - this just returns a constant value
|
||||
unsafe { bssl_sys::EVP_aead_aes_128_gcm() }
|
||||
}
|
||||
}
|
||||
|
||||
struct EvpAes256Gcm;
|
||||
impl EvpAeadType for EvpAes256Gcm {
|
||||
type Key = [u8; 32];
|
||||
|
||||
fn evp_aead() -> *const EVP_AEAD {
|
||||
// Safety:
|
||||
// - this just returns a constant value
|
||||
unsafe { bssl_sys::EVP_aead_aes_256_gcm() }
|
||||
}
|
||||
}
|
||||
|
||||
// Private implementation of an AEAD which is generic over Nonce size and Tag size. This should
|
||||
// only be exposed publicly by wrapper types which provide the correctly sized const generics for
|
||||
// the given aead algorithm.
|
||||
struct AeadImpl<const N: usize, const T: usize>(*mut EVP_AEAD_CTX);
|
||||
|
||||
impl<const N: usize, const T: usize> AeadImpl<N, T> {
|
||||
// Create a new AeadImpl instance from key material and for a supported AeadType.
|
||||
fn new<A: EvpAeadType>(key: &A::Key) -> Self {
|
||||
@@ -157,6 +205,9 @@ impl<const N: usize, const T: usize> AeadImpl<N, T> {
|
||||
// Decrypts msg in-place, on success msg will contain the plain text alone, without the auth
|
||||
// tag.
|
||||
fn decrypt(&self, msg: &[u8], aad: &[u8], nonce: &[u8; N]) -> Result<Vec<u8>, AeadError> {
|
||||
if msg.len() < T {
|
||||
return Err(AeadError);
|
||||
}
|
||||
let mut out = Vec::new();
|
||||
out.resize(msg.len() - T, 0u8);
|
||||
|
||||
@@ -192,6 +243,14 @@ impl<const N: usize, const T: usize> AeadImpl<N, T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, const T: usize> Drop for AeadImpl<N, T> {
|
||||
fn drop(&mut self) {
|
||||
// Safety:
|
||||
// - `self.0` was allocated by `EVP_AEAD_CTX_new` and has not yet been freed.
|
||||
unsafe { bssl_sys::EVP_AEAD_CTX_free(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
@@ -285,4 +344,78 @@ mod test {
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(&result.unwrap(), &msg);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aes_128_gcm_tests() {
|
||||
// TC 1 from crypto/cipher_extra/test/aes_128_gcm_tests.txt
|
||||
let key = decode_hex("d480429666d48b400633921c5407d1d1");
|
||||
let nonce = decode_hex("3388c676dc754acfa66e172a");
|
||||
let tag: [u8; 16] = decode_hex("7d7daf44850921a34e636b01adeb104f");
|
||||
let mut buf = Vec::from(&[] as &[u8]);
|
||||
let aes = new_aes_128_gcm(&key);
|
||||
let result = aes.encrypt(&mut buf, b"", &nonce);
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap(), &tag);
|
||||
|
||||
// TC2
|
||||
let key = decode_hex("3881e7be1bb3bbcaff20bdb78e5d1b67");
|
||||
let nonce = decode_hex("dcf5b7ae2d7552e2297fcfa9");
|
||||
let msg: [u8; 5] = decode_hex("0a2714aa7d");
|
||||
let ad: [u8; 5] = decode_hex("c60c64bbf7");
|
||||
let ct: [u8; 5] = decode_hex("5626f96ecb");
|
||||
let tag: [u8; 16] = decode_hex("ff4c4f1d92b0abb1d0820833d9eb83c7");
|
||||
|
||||
let mut buf = Vec::from(msg.as_slice());
|
||||
let aes = new_aes_128_gcm(&key);
|
||||
let result = aes.encrypt(&mut buf, &ad, &nonce);
|
||||
assert!(result.is_ok());
|
||||
let mut data = result.unwrap();
|
||||
assert_eq!(&data[..5], &ct);
|
||||
assert_eq!(&data[5..], &tag);
|
||||
let result = aes.decrypt(data.as_mut_slice(), &ad, &nonce);
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap(), &msg);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn aes_256_gcm_tests() {
|
||||
// TC 1 from crypto/cipher_extra/test/aes_256_gcm_tests.txt
|
||||
let key = decode_hex("e5ac4a32c67e425ac4b143c83c6f161312a97d88d634afdf9f4da5bd35223f01");
|
||||
let nonce = decode_hex("5bf11a0951f0bfc7ea5c9e58");
|
||||
let tag: [u8; 16] = decode_hex("d7cba289d6d19a5af45dc13857016bac");
|
||||
let mut buf = Vec::from(&[] as &[u8]);
|
||||
let aes = new_aes_256_gcm(&key);
|
||||
let result = aes.encrypt(&mut buf, b"", &nonce);
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap(), &tag);
|
||||
|
||||
// TC2
|
||||
let key = decode_hex("73ad7bbbbc640c845a150f67d058b279849370cd2c1f3c67c4dd6c869213e13a");
|
||||
let nonce = decode_hex("a330a184fc245812f4820caa");
|
||||
let msg: [u8; 5] = decode_hex("f0535fe211");
|
||||
let ad: [u8; 5] = decode_hex("e91428be04");
|
||||
let ct: [u8; 5] = decode_hex("e9b8a896da");
|
||||
let tag: [u8; 16] = decode_hex("9115ed79f26a030c14947b3e454db9e7");
|
||||
|
||||
let mut buf = Vec::from(msg.as_slice());
|
||||
let aes = new_aes_256_gcm(&key);
|
||||
let result = aes.encrypt(&mut buf, &ad, &nonce);
|
||||
assert!(result.is_ok());
|
||||
let mut data = result.unwrap();
|
||||
assert_eq!(&data[..5], &ct);
|
||||
assert_eq!(&data[5..], &tag);
|
||||
let result = aes.decrypt(data.as_mut_slice(), &ad, &nonce);
|
||||
assert!(result.is_ok());
|
||||
assert_eq!(result.unwrap(), &msg);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_data_length_decrypt() {
|
||||
let key = decode_hex("00000000000000000000000000000000");
|
||||
let nonce = decode_hex("000000000000000000000000");
|
||||
let buf = Vec::from(&[] as &[u8]);
|
||||
let aes = new_aes_128_gcm_siv(&key);
|
||||
let result = aes.decrypt(&buf, b"", &nonce);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user