From b3aa7ef26008481609838457ce6a6e46067f2272 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Thu, 30 Apr 2026 09:27:27 -0400 Subject: [PATCH] Rust wrapper: add Aes192Ccm and Aes192Gcm --- wrapper/rust/wolfssl-wolfcrypt/src/aes.rs | 111 +++++++++++++++++- .../rust/wolfssl-wolfcrypt/tests/test_aes.rs | 46 ++++++++ 2 files changed, 152 insertions(+), 5 deletions(-) diff --git a/wrapper/rust/wolfssl-wolfcrypt/src/aes.rs b/wrapper/rust/wolfssl-wolfcrypt/src/aes.rs index 9aede17418..7d954d2164 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/src/aes.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/src/aes.rs @@ -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 { + 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, + associated_data: &[u8], + buffer: &mut [u8], + ) -> Result, aead::Error> { + let mut tag = aead::Tag::::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, + associated_data: &[u8], + buffer: &mut [u8], + tag: &aead::Tag, + ) -> 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 { + 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, + associated_data: &[u8], + buffer: &mut [u8], + ) -> Result, aead::Error> { + let mut tag = aead::Tag::::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, + associated_data: &[u8], + buffer: &mut [u8], + tag: &aead::Tag, + ) -> 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)] diff --git a/wrapper/rust/wolfssl-wolfcrypt/tests/test_aes.rs b/wrapper/rust/wolfssl-wolfcrypt/tests/test_aes.rs index e215891691..d5a171fd9e 100644 --- a/wrapper/rust/wolfssl-wolfcrypt/tests/test_aes.rs +++ b/wrapper/rust/wolfssl-wolfcrypt/tests/test_aes.rs @@ -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 = 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 = 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))]