Rust wrapper: add Aes192Ccm and Aes192Gcm

This commit is contained in:
Josh Holtrop
2026-04-30 09:27:27 -04:00
parent 4ed0a0a90d
commit b3aa7ef260
2 changed files with 152 additions and 5 deletions
+106 -5
View File
@@ -33,13 +33,10 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
use aead::{AeadCore, AeadInPlace, KeyInit, KeySizeUser};
#[cfg(feature = "aead")]
use aead::generic_array::typenum::{U0, U12, U16, U32};
use aead::generic_array::typenum::{U0, U12, U16, U24, U32};
#[cfg(all(feature = "cipher", not(feature = "aead")))]
use cipher::typenum::consts::{U16, U32};
#[cfg(feature = "cipher")]
use cipher::typenum::consts::U24;
use cipher::typenum::consts::{U16, U24, U32};
#[cfg(feature = "cipher")]
use cipher::{
@@ -557,6 +554,58 @@ impl AeadInPlace for Aes128Ccm {
}
}
/// AES-192-CCM authenticated encryption (12-byte nonce, 16-byte tag).
#[cfg(all(aes_ccm, feature = "aead"))]
#[derive(Zeroize, ZeroizeOnDrop)]
pub struct Aes192Ccm {
key: [u8; 24],
}
#[cfg(all(aes_ccm, feature = "aead"))]
impl KeySizeUser for Aes192Ccm {
type KeySize = U24;
}
#[cfg(all(aes_ccm, feature = "aead"))]
impl AeadCore for Aes192Ccm {
type NonceSize = U12;
type TagSize = U16;
type CiphertextOverhead = U0;
}
#[cfg(all(aes_ccm, feature = "aead"))]
impl KeyInit for Aes192Ccm {
fn new(key: &aead::Key<Self>) -> Self {
let mut k = [0u8; 24];
k.copy_from_slice(key.as_ref());
Aes192Ccm { key: k }
}
}
#[cfg(all(aes_ccm, feature = "aead"))]
impl AeadInPlace for Aes192Ccm {
fn encrypt_in_place_detached(
&self,
nonce: &aead::Nonce<Self>,
associated_data: &[u8],
buffer: &mut [u8],
) -> Result<aead::Tag<Self>, aead::Error> {
let mut tag = aead::Tag::<Self>::default();
ccm_encrypt_in_place(&self.key, nonce.as_ref(), associated_data, buffer, tag.as_mut())?;
Ok(tag)
}
fn decrypt_in_place_detached(
&self,
nonce: &aead::Nonce<Self>,
associated_data: &[u8],
buffer: &mut [u8],
tag: &aead::Tag<Self>,
) -> Result<(), aead::Error> {
ccm_decrypt_in_place(&self.key, nonce.as_ref(), associated_data, buffer, tag.as_ref())
}
}
/// AES-256-CCM authenticated encryption (12-byte nonce, 16-byte tag).
#[cfg(all(aes_ccm, feature = "aead"))]
#[derive(Zeroize, ZeroizeOnDrop)]
@@ -1713,6 +1762,58 @@ impl AeadInPlace for Aes128Gcm {
}
}
/// AES-192-GCM authenticated encryption (12-byte nonce, 16-byte tag).
#[cfg(all(aes_gcm, feature = "aead"))]
#[derive(Zeroize, ZeroizeOnDrop)]
pub struct Aes192Gcm {
key: [u8; 24],
}
#[cfg(all(aes_gcm, feature = "aead"))]
impl KeySizeUser for Aes192Gcm {
type KeySize = U24;
}
#[cfg(all(aes_gcm, feature = "aead"))]
impl AeadCore for Aes192Gcm {
type NonceSize = U12;
type TagSize = U16;
type CiphertextOverhead = U0;
}
#[cfg(all(aes_gcm, feature = "aead"))]
impl KeyInit for Aes192Gcm {
fn new(key: &aead::Key<Self>) -> Self {
let mut k = [0u8; 24];
k.copy_from_slice(key.as_ref());
Aes192Gcm { key: k }
}
}
#[cfg(all(aes_gcm, feature = "aead"))]
impl AeadInPlace for Aes192Gcm {
fn encrypt_in_place_detached(
&self,
nonce: &aead::Nonce<Self>,
associated_data: &[u8],
buffer: &mut [u8],
) -> Result<aead::Tag<Self>, aead::Error> {
let mut tag = aead::Tag::<Self>::default();
gcm_encrypt_in_place(&self.key, nonce.as_ref(), associated_data, buffer, tag.as_mut())?;
Ok(tag)
}
fn decrypt_in_place_detached(
&self,
nonce: &aead::Nonce<Self>,
associated_data: &[u8],
buffer: &mut [u8],
tag: &aead::Tag<Self>,
) -> Result<(), aead::Error> {
gcm_decrypt_in_place(&self.key, nonce.as_ref(), associated_data, buffer, tag.as_ref())
}
}
/// AES-256-GCM authenticated encryption (12-byte nonce, 16-byte tag).
#[cfg(all(aes_gcm, feature = "aead"))]
#[derive(Zeroize, ZeroizeOnDrop)]
@@ -1030,6 +1030,29 @@ fn test_aes256gcm_nist_tc14_encrypt() {
assert_eq!(&tag[..], &expected_tag);
}
/// Roundtrip test for AES-192-GCM using `aead::Aead`.
#[test]
#[cfg(all(feature = "aead", aes_gcm))]
fn test_aes192gcm_aead_roundtrip() {
let key = [0x77u8; 24];
let nonce_bytes = [0x88u8; 12];
let aad = b"aes-192-gcm test";
let plaintext = b"AES-192-GCM roundtrip test";
let cipher = Aes192Gcm::new_from_slice(&key).unwrap();
let nonce: aead::Nonce<Aes192Gcm> = nonce_bytes.into();
let ciphertext = cipher
.encrypt(&nonce, Payload { msg: plaintext, aad })
.expect("AES-192-GCM encrypt failed");
let recovered = cipher
.decrypt(&nonce, Payload { msg: &ciphertext, aad })
.expect("AES-192-GCM decrypt failed");
assert_eq!(recovered, plaintext);
}
/// Roundtrip test for AES-256-GCM using `aead::Aead`.
#[test]
#[cfg(all(feature = "aead", aes_gcm))]
@@ -1092,6 +1115,29 @@ fn test_aes128ccm_reject_tampered() {
assert!(cipher.decrypt(&nonce, ct.as_slice()).is_err());
}
/// Roundtrip test for AES-192-CCM using `aead::Aead`.
#[test]
#[cfg(all(feature = "aead", aes_ccm))]
fn test_aes192ccm_aead_roundtrip() {
let key = [0x33u8; 24];
let nonce_bytes = [0x44u8; 12];
let aad = b"aes-192-ccm test";
let plaintext = b"AES-192-CCM plaintext data";
let cipher = Aes192Ccm::new_from_slice(&key).unwrap();
let nonce: aead::Nonce<Aes192Ccm> = nonce_bytes.into();
let ciphertext = cipher
.encrypt(&nonce, Payload { msg: plaintext, aad })
.expect("AES-192-CCM encrypt failed");
let recovered = cipher
.decrypt(&nonce, Payload { msg: &ciphertext, aad })
.expect("AES-192-CCM decrypt failed");
assert_eq!(recovered, plaintext);
}
/// Roundtrip test for AES-256-CCM using `aead::Aead`.
#[test]
#[cfg(all(feature = "aead", aes_ccm))]