#![allow(unsafe_code)]
use {aead, bssl, c, error, polyfill};
const AES_128_KEY_LEN: usize = 128 / 8;
const AES_256_KEY_LEN: usize = 32;
pub const AES_KEY_CTX_BUF_LEN: usize = AES_KEY_BUF_LEN + GCM128_SERIALIZED_LEN;
const AES_KEY_BUF_LEN: usize = (4 * 4 * (AES_MAX_ROUNDS + 1)) + 8;
const AES_MAX_ROUNDS: usize = 14;
const GCM128_SERIALIZED_LEN: usize = 16 * 16;
pub static AES_128_GCM: aead::Algorithm = aead::Algorithm {
key_len: AES_128_KEY_LEN,
init: aes_gcm_init,
seal: aes_gcm_seal,
open: aes_gcm_open,
};
pub static AES_256_GCM: aead::Algorithm = aead::Algorithm {
key_len: AES_256_KEY_LEN,
init: aes_gcm_init,
seal: aes_gcm_seal,
open: aes_gcm_open,
};
fn aes_gcm_init(ctx_buf: &mut [u8], key: &[u8])
-> Result<(), error::Unspecified> {
bssl::map_result(unsafe {
evp_aead_aes_gcm_init(ctx_buf.as_mut_ptr(),
ctx_buf.len(), key.as_ptr(), key.len())
})
}
fn aes_gcm_seal(ctx: &[u64; aead::KEY_CTX_BUF_ELEMS],
nonce: &[u8; aead::NONCE_LEN], in_out: &mut [u8],
tag: &mut [u8; aead::TAG_LEN], ad: &[u8])
-> Result<(), error::Unspecified> {
let ctx = polyfill::slice::u64_as_u8(ctx);
bssl::map_result(unsafe {
evp_aead_aes_gcm_seal(ctx.as_ptr(), in_out.as_mut_ptr(), in_out.len(),
tag.as_mut_ptr(), nonce.as_ptr(), ad.as_ptr(),
ad.len())
})
}
fn aes_gcm_open(ctx: &[u64; aead::KEY_CTX_BUF_ELEMS],
nonce: &[u8; aead::NONCE_LEN], in_out: &mut [u8],
in_prefix_len: usize, tag_out: &mut [u8; aead::TAG_LEN],
ad: &[u8]) -> Result<(), error::Unspecified> {
let ctx = polyfill::slice::u64_as_u8(ctx);
bssl::map_result(unsafe {
evp_aead_aes_gcm_open(ctx.as_ptr(), in_out.as_mut_ptr(),
in_out.len() - in_prefix_len,
tag_out.as_mut_ptr(), nonce.as_ptr(),
in_out[in_prefix_len..].as_ptr(), ad.as_ptr(),
ad.len())
})
}
extern {
fn evp_aead_aes_gcm_init(ctx_buf: *mut u8, ctx_buf_len: c::size_t,
key: *const u8, key_len: c::size_t) -> c::int;
fn evp_aead_aes_gcm_seal(ctx_buf: *const u8, in_out: *mut u8,
in_out_len: c::size_t,
tag_out: *mut u8,
nonce: *const u8, ad: *const u8,
ad_len: c::size_t) -> c::int;
fn evp_aead_aes_gcm_open(ctx_buf: *const u8, out: *mut u8,
in_out_len: c::size_t,
tag_out: *mut u8,
nonce: *const u8,
in_: *const u8, ad: *const u8, ad_len: c::size_t)
-> c::int;
}
#[cfg(test)]
mod tests {
use super::super::super::aead;
use super::super::tests::test_aead;
bssl_test!(test_aes, bssl_aes_test_main);
#[test]
pub fn test_aes_gcm_128() {
test_aead(&aead::AES_128_GCM,
"crypto/cipher/test/aes_128_gcm_tests.txt");
}
#[test]
pub fn test_aes_gcm_256() {
test_aead(&aead::AES_256_GCM,
"crypto/cipher/test/aes_256_gcm_tests.txt");
}
}