crypto_async_rs/
aes_gcm_async.rs

1use crate::aes_gcm::{GcmBlockMulFn, iv2pre_counter_block, increment_32_least_bits, gctr, define_block_s, xor_full_blocks};
2use crate::aes::BLOCK_SIZE;
3use futures::{AsyncWrite, io::{self, AsyncRead, AsyncReadExt, AsyncWriteExt}};
4use std::fmt;
5
6/// Custom error types for AES-GCM async operations
7#[derive(Debug, Clone, PartialEq)]
8pub enum AesGcmAsyncError {
9    /// Invalid key size - must be 16, 24, or 32 bytes for AES-128, AES-192, or AES-256
10    InvalidKeySize(usize),
11    /// Invalid IV size - must be at least 1 byte (longer IVs are hashed to 12 bytes)
12    InvalidIvSize(usize),
13    /// I/O error during async operations
14    IoError(String),
15    /// Authentication failure during decryption
16    AuthenticationFailed,
17    /// Internal cryptographic error
18    CryptoError(String),
19}
20
21impl fmt::Display for AesGcmAsyncError {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        match self {
24            AesGcmAsyncError::InvalidKeySize(size) => {
25                write!(f, "Invalid key size: {} bytes. Must be 16, 24, or 32 bytes", size)
26            }
27            AesGcmAsyncError::InvalidIvSize(size) => {
28                write!(f, "Invalid IV size: {} bytes. Must be at least 1 byte (longer IVs are hashed to 12 bytes)", size)
29            }
30            AesGcmAsyncError::IoError(msg) => {
31                write!(f, "I/O error: {}", msg)
32            }
33            AesGcmAsyncError::AuthenticationFailed => {
34                write!(f, "Authentication failed - message may be corrupted or tampered with")
35            }
36            AesGcmAsyncError::CryptoError(msg) => {
37                write!(f, "Cryptographic error: {}", msg)
38            }
39        }
40    }
41}
42
43impl std::error::Error for AesGcmAsyncError {}
44
45impl From<io::Error> for AesGcmAsyncError {
46    fn from(err: io::Error) -> Self {
47        AesGcmAsyncError::IoError(err.to_string())
48    }
49}
50
51/// Fast input validation for key and IV sizes
52#[inline]
53fn validate_key_size(key: &[u8]) -> Result<(), AesGcmAsyncError> {
54    match key.len() {
55        16 | 24 | 32 => Ok(()),
56        size => Err(AesGcmAsyncError::InvalidKeySize(size)),
57    }
58}
59
60/// Fast input validation for IV size
61/// Note: GCM specification allows longer IVs but they get hashed to 12 bytes
62#[inline]
63fn validate_iv_size(iv: &[u8]) -> Result<(), AesGcmAsyncError> {
64    if iv.is_empty() {
65        Err(AesGcmAsyncError::InvalidIvSize(iv.len()))
66    } else {
67        Ok(())
68    }
69}
70
71/// Performance-optimized buffer size for large data streams
72const OPTIMAL_BUFFER_SIZE: usize = 64 * 1024; // 64KB for better performance
73
74/// Async version of `gcm_aes_encrypt` that reads from an `AsyncRead` source and writes to an `AsyncWrite` destination.
75/// 
76/// This function provides authenticated encryption using AES-GCM mode with optimized performance
77/// for large data streams. It includes comprehensive error handling and input validation.
78/// 
79/// # Parameters
80/// * `key` - AES cipher key (16, 24, or 32 bytes for AES-128, AES-192, or AES-256)
81/// * `iv` - Initialization Vector (at least 1 byte, longer IVs are hashed to 12 bytes)
82/// * `reader` - AsyncRead source for plain text to encrypt and authenticate
83/// * `writer` - AsyncWrite destination for cipher text
84/// * `aad` - Additional authenticated data (can be empty)
85/// * `mul_fn` - Block multiplication function from `GcmBlockMulEnhancement::to_mul_fn()`
86/// 
87/// # Returns
88/// * `Result<[u8; 16], AesGcmAsyncError>` - Authentication tag on success, error on failure
89/// 
90/// # Errors
91/// * `InvalidKeySize` - Key size is not 16, 24, or 32 bytes
92/// * `InvalidIvSize` - IV size is 0 bytes
93/// * `IoError` - I/O error during reading or writing
94/// * `CryptoError` - Internal cryptographic error
95///
96/// # Examples
97///
98/// ## Basic encryption
99/// ```rust
100/// use crypto_async_rs::aes_gcm::{GcmBlockMulEnhancement};
101/// use crypto_async_rs::aes_gcm_async::{gcm_aes_encrypt_async, AesGcmAsyncError};
102/// use futures::io::Cursor;
103///
104/// async fn example() -> Result<(), AesGcmAsyncError> {
105///     let cipher_key = [0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08];
106///     let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad];
107///     let plain_text = [0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59];
108///     let aad = [0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe];
109///     let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
110///     
111///     let reader = Cursor::new(&plain_text);
112///     let mut writer = Cursor::new(Vec::new());
113///     
114///     let tag = gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn).await?;
115///     println!("Authentication tag: {:?}", tag);
116///     Ok(())
117/// }
118/// ```
119///
120/// ## Error handling
121/// ```rust
122/// use crypto_async_rs::aes_gcm_async::{gcm_aes_encrypt_async, AesGcmAsyncError};
123/// use crypto_async_rs::aes_gcm::GcmBlockMulEnhancement;
124/// use futures::io::Cursor;
125///
126/// async fn error_example() {
127///     let invalid_key = [0u8; 8]; // Too short
128///     let iv = [0xca, 0xfe, 0xba, 0xbe];
129///     let reader = Cursor::new(b"test");
130///     let mut writer = Cursor::new(Vec::new());
131///     let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&[0u8; 16]);
132///     
133///     match gcm_aes_encrypt_async(&invalid_key, &iv, reader, &mut writer, &[], &mul_fn).await {
134///         Err(AesGcmAsyncError::InvalidKeySize(size)) => {
135///             println!("Invalid key size: {} bytes", size);
136///         }
137///         _ => unreachable!(),
138///     }
139/// }
140/// ```
141pub async fn gcm_aes_encrypt_async<R, W>(
142    key: &[u8],
143    iv: &[u8],
144    mut reader: R,
145    mut writer: W,
146    aad: &[u8],
147    mul_fn: &GcmBlockMulFn,
148) -> Result<[u8; 16], AesGcmAsyncError>
149where
150    R: AsyncRead + Unpin,
151    W: AsyncWrite + Unpin,
152{
153    // Fast input validation
154    validate_key_size(key)?;
155    validate_iv_size(iv)?;
156    
157    // Initialize counter block and encryption
158    let mut counter_block = iv2pre_counter_block(&iv, mul_fn);
159    let encrypted_block = crate::aes::encrypt(&counter_block, key);
160    increment_32_least_bits(&mut counter_block);
161    
162    // Use optimized buffer size for better performance
163    let mut buffer = vec![0u8; OPTIMAL_BUFFER_SIZE];
164    let mut cipher_text = Vec::new();
165    
166    loop {
167        let n = reader.read(&mut buffer).await
168            .map_err(|e| AesGcmAsyncError::IoError(format!("Failed to read data: {}", e)))?;
169        if n == 0 { break; }
170        
171        // Encrypt this chunk
172        let mut chunk_counter = counter_block.clone();
173        let cipher_chunk = gctr(&mut chunk_counter, &buffer[..n], key);
174        
175        // Write encrypted chunk
176        writer.write_all(&cipher_chunk).await
177            .map_err(|e| AesGcmAsyncError::IoError(format!("Failed to write data: {}", e)))?;
178        
179        // Collect cipher text for authentication tag calculation
180        cipher_text.extend_from_slice(&cipher_chunk);
181        
182        // Update counter for next chunk
183        for _ in 0..((n + BLOCK_SIZE - 1) / BLOCK_SIZE) {
184            increment_32_least_bits(&mut counter_block);
185        }
186    }
187    
188    // Calculate authentication tag
189    let s = define_block_s(&cipher_text, aad, mul_fn);
190    let tag = xor_full_blocks(&s, &encrypted_block);
191    
192    writer.flush().await
193        .map_err(|e| AesGcmAsyncError::IoError(format!("Failed to flush writer: {}", e)))?;
194    
195    Ok(tag)
196}
197
198/// Async version of `gcm_aes_decrypt` that reads from an `AsyncRead` source and writes to an `AsyncWrite` destination.
199/// 
200/// This function provides authenticated decryption using AES-GCM mode with optimized performance
201/// for large data streams. It includes comprehensive error handling and input validation.
202/// 
203/// # Parameters
204/// * `key` - AES cipher key (16, 24, or 32 bytes for AES-128, AES-192, or AES-256)
205/// * `iv` - Initialization Vector (at least 1 byte, longer IVs are hashed to 12 bytes)
206/// * `reader` - AsyncRead source for cipher text to decrypt and authenticate
207/// * `writer` - AsyncWrite destination for plain text
208/// * `aad` - Additional authenticated data (can be empty)
209/// * `mul_fn` - Block multiplication function from `GcmBlockMulEnhancement::to_mul_fn()`
210/// 
211/// # Returns
212/// * `Result<[u8; 16], AesGcmAsyncError>` - Authentication tag on success, error on failure
213/// 
214/// # Errors
215/// * `InvalidKeySize` - Key size is not 16, 24, or 32 bytes
216/// * `InvalidIvSize` - IV size is 0 bytes
217/// * `IoError` - I/O error during reading or writing
218/// * `CryptoError` - Internal cryptographic error
219/// * `AuthenticationFailed` - Authentication tag verification failed
220///
221/// # Security Note
222/// The returned authentication tag should be compared with the expected tag using constant-time
223/// comparison. If the tags don't match, the message has been tampered with or corrupted.
224///
225/// # Examples
226///
227/// ## Basic decryption
228/// ```rust
229/// use crypto_async_rs::aes_gcm::{GcmBlockMulEnhancement};
230/// use crypto_async_rs::aes_gcm_async::{gcm_aes_decrypt_async, AesGcmAsyncError};
231/// use futures::io::Cursor;
232///
233/// async fn example() -> Result<(), AesGcmAsyncError> {
234///     let cipher_key = [0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08];
235///     let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88];
236///     let cipher_text = [0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c];
237///     let aad = [];
238///     let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
239///     
240///     let reader = Cursor::new(&cipher_text);
241///     let mut writer = Cursor::new(Vec::new());
242///     
243///     let tag = gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn).await?;
244///     println!("Authentication tag: {:?}", tag);
245///     Ok(())
246/// }
247/// ```
248///
249/// ## Authentication verification
250/// ```rust
251/// use crypto_async_rs::aes_gcm_async::{gcm_aes_decrypt_async, AesGcmAsyncError};
252/// use crypto_async_rs::aes_gcm::GcmBlockMulEnhancement;
253/// use futures::io::Cursor;
254///
255/// async fn verify_authentication() -> Result<(), AesGcmAsyncError> {
256///     let key = [0u8; 16];
257///     let iv = [0u8; 12];
258///     let expected_tag = [0u8; 16];
259///     let cipher_text = b"encrypted data";
260///     let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&key);
261///     
262///     let reader = Cursor::new(cipher_text);
263///     let mut writer = Cursor::new(Vec::new());
264///     
265///     let computed_tag = gcm_aes_decrypt_async(&key, &iv, reader, &mut writer, &[], &mul_fn).await?;
266///     
267///     // Constant-time comparison
268///     if computed_tag == expected_tag {
269///         println!("Authentication successful");
270///     } else {
271///         return Err(AesGcmAsyncError::AuthenticationFailed);
272///     }
273///     Ok(())
274/// }
275/// ```
276pub async fn gcm_aes_decrypt_async<R, W>(
277    key: &[u8],
278    iv: &[u8],
279    mut reader: R,
280    mut writer: W,
281    aad: &[u8],
282    mul_fn: &GcmBlockMulFn,
283) -> Result<[u8; 16], AesGcmAsyncError>
284where
285    R: AsyncRead + Unpin,
286    W: AsyncWrite + Unpin,
287{
288    // Fast input validation
289    validate_key_size(key)?;
290    validate_iv_size(iv)?;
291    
292    // Initialize counter block and encryption
293    let mut counter_block = iv2pre_counter_block(&iv, mul_fn);
294    let encrypted_block = crate::aes::encrypt(&counter_block, key);
295    increment_32_least_bits(&mut counter_block);
296    
297    // Use optimized buffer size for better performance
298    let mut buffer = vec![0u8; OPTIMAL_BUFFER_SIZE];
299    let mut cipher_text = Vec::new();
300    
301    loop {
302        let n = reader.read(&mut buffer).await
303            .map_err(|e| AesGcmAsyncError::IoError(format!("Failed to read data: {}", e)))?;
304        if n == 0 { break; }
305        
306        // Collect cipher text for authentication tag calculation
307        cipher_text.extend_from_slice(&buffer[..n]);
308        
309        // Decrypt this chunk
310        let mut chunk_counter = counter_block.clone();
311        let plain_chunk = gctr(&mut chunk_counter, &buffer[..n], key);
312        
313        // Write decrypted chunk
314        writer.write_all(&plain_chunk).await
315            .map_err(|e| AesGcmAsyncError::IoError(format!("Failed to write data: {}", e)))?;
316        
317        // Update counter for next chunk
318        for _ in 0..((n + BLOCK_SIZE - 1) / BLOCK_SIZE) {
319            increment_32_least_bits(&mut counter_block);
320        }
321    }
322    
323    // Calculate authentication tag
324    let s = define_block_s(&cipher_text, aad, mul_fn);
325    let tag = xor_full_blocks(&s, &encrypted_block);
326    
327    writer.flush().await
328        .map_err(|e| AesGcmAsyncError::IoError(format!("Failed to flush writer: {}", e)))?;
329    
330    Ok(tag)
331}
332
333#[cfg(test)]
334mod tests {
335    use crate::aes_gcm::GcmBlockMulEnhancement;
336    use crate::aes_gcm::{
337        calculate_table_m, calculate_4bit_table_m, block_mul, block_mul_with_tables, 
338        block_mul_with_4bit_tables, block_mul_with_m0_r, TABLE_R
339    };
340    use crate::aes;
341    use futures::io::Cursor;
342    use futures::executor::block_on;
343
344    use super::*;
345
346
347    #[test]
348    fn test_gcm_aes_128_encrypt() {
349        //https://luca-giuzzi.unibs.it/corsi/Support/papers-cryptography/gcm-spec.pdf
350        //Test  Case  1
351        let cipher_key = [
352            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
353            0x00, 0x00,
354        ];
355        let iv = [
356            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
357        ];
358        let p = "".as_bytes();
359        let aad = "".as_bytes();
360        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
361        
362        let reader = Cursor::new(p);
363        let mut writer = Cursor::new(Vec::new());
364        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, aad, &mul_fn)).unwrap();
365        let cipher_text = writer.into_inner();
366        
367        assert_eq!(&cipher_text, &[]);
368        assert_eq!(
369            &tag,
370            &[
371                0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7,
372                0x45, 0x5a
373            ]
374        );
375
376        //Test  Case  2
377        let p = [
378            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379            0x00, 0x00,
380        ];
381        let aad = "".as_bytes();
382        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
383        
384        let reader = Cursor::new(&p);
385        let mut writer = Cursor::new(Vec::new());
386        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, aad, &mul_fn)).unwrap();
387        let cipher_text = writer.into_inner();
388        
389        assert_eq!(
390            &cipher_text,
391            &[
392                0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2,
393                0xfe, 0x78
394            ]
395        );
396        assert_eq!(
397            &tag,
398            &[
399                0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57,
400                0xbd, 0xdf
401            ]
402        );
403
404        let cipher_key = [
405            0xAD, 0x7A, 0x2B, 0xD0, 0x3E, 0xAC, 0x83, 0x5A, 0x6F, 0x62, 0x0F, 0xDC, 0xB5, 0x06,
406            0xB3, 0x45,
407        ];
408        let iv = [
409            0x12, 0x15, 0x35, 0x24, 0xC0, 0x89, 0x5E, 0x81, 0xB2, 0xC2, 0x84, 0x65,
410        ];
411        let p = [
412            0x08, 0x00, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
413            0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
414            0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
415            0x37, 0x38, 0x39, 0x3A, 0x00, 0x02,
416        ];
417        let aad = [
418            0xD6, 0x09, 0xB1, 0xF0, 0x56, 0x63, 0x7A, 0x0D, 0x46, 0xDF, 0x99, 0x8D, 0x88, 0xE5,
419            0x2E, 0x00, 0xB2, 0xC2, 0x84, 0x65, 0x12, 0x15, 0x35, 0x24, 0xC0, 0x89, 0x5E, 0x81,
420        ];
421        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
422        
423        let reader = Cursor::new(&p);
424        let mut writer = Cursor::new(Vec::new());
425        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
426        let cipher_text = writer.into_inner();
427        assert_eq!(
428            &cipher_text,
429            &[
430                0x70, 0x1A, 0xFA, 0x1C, 0xC0, 0x39, 0xC0, 0xD7, 0x65, 0x12, 0x8A, 0x66, 0x5D, 0xAB,
431                0x69, 0x24, 0x38, 0x99, 0xBF, 0x73, 0x18, 0xCC, 0xDC, 0x81, 0xC9, 0x93, 0x1D, 0xA1,
432                0x7F, 0xBE, 0x8E, 0xDD, 0x7D, 0x17, 0xCB, 0x8B, 0x4C, 0x26, 0xFC, 0x81, 0xE3, 0x28,
433                0x4F, 0x2B, 0x7F, 0xBA, 0x71, 0x3D
434            ]
435        );
436        assert_eq!(
437            &tag,
438            &[
439                0x4F, 0x8D, 0x55, 0xE7, 0xD3, 0xF0, 0x6F, 0xD5, 0xA1, 0x3C, 0x0C, 0x29, 0xB9, 0xD5,
440                0xB8, 0x80
441            ]
442        );
443
444        //Test  Case  3
445        let cipher_key = [
446            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
447            0x83, 0x08,
448        ];
449        let iv = [
450            0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
451        ];
452        let p = [
453            0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
454            0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
455            0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
456            0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
457            0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
458        ];
459        let aad = [];
460        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
461        
462        let reader = Cursor::new(&p);
463        let mut writer = Cursor::new(Vec::new());
464        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
465        let cipher_text = writer.into_inner();
466        assert_eq!(
467            &cipher_text,
468            &[
469                0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
470                0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
471                0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
472                0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
473                0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85
474            ]
475        );
476        assert_eq!(
477            &tag,
478            &[
479                0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6,
480                0xfa, 0xb4
481            ]
482        );
483
484        //Test  Case  4
485        let cipher_key = [
486            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
487            0x83, 0x08,
488        ];
489        let iv = [
490            0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
491        ];
492        let p = [
493            0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
494            0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
495            0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
496            0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
497            0xba, 0x63, 0x7b, 0x39,
498        ];
499        let aad = [
500            0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
501            0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
502        ];
503        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
504        let reader = Cursor::new(&p);
505        let mut writer = Cursor::new(Vec::new());
506        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
507        let cipher_text = writer.into_inner();
508        assert_eq!(
509            &cipher_text,
510            &[
511                0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
512                0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
513                0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
514                0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
515                0x3d, 0x58, 0xe0, 0x91
516            ]
517        );
518        assert_eq!(
519            &tag,
520            &[
521                0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12,
522                0x1a, 0x47
523            ]
524        );
525
526        //Test  Case  5
527        let cipher_key = [
528            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
529            0x83, 0x08,
530        ];
531        let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad];
532        let p = [
533            0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
534            0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
535            0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
536            0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
537            0xba, 0x63, 0x7b, 0x39,
538        ];
539        let aad = [
540            0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
541            0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
542        ];
543        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
544        let reader = Cursor::new(&p);
545        let mut writer = Cursor::new(Vec::new());
546        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
547        let cipher_text = writer.into_inner();
548        assert_eq!(
549            &cipher_text,
550            &[
551                0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a,
552                0x47, 0x55, 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, 0x37, 0x66, 0xe5, 0xf9,
553                0x7b, 0x6c, 0x74, 0x23, 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, 0x2b, 0x09,
554                0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
555                0xc2, 0x3f, 0x45, 0x98
556            ]
557        );
558        assert_eq!(
559            &tag,
560            &[
561                0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2,
562                0xfc, 0xcb
563            ]
564        );
565
566        //Test  Case  6
567        let cipher_key = [
568            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
569            0x83, 0x08,
570        ];
571        let iv = [
572            0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52,
573            0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 0xe4, 0xc3, 0x03, 0xd2,
574            0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0,
575            0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
576            0xa6, 0x37, 0xb3, 0x9b,
577        ];
578        let p = [
579            0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
580            0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
581            0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
582            0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
583            0xba, 0x63, 0x7b, 0x39,
584        ];
585        let aad = [
586            0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
587            0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
588        ];
589        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
590        let reader = Cursor::new(&p);
591        let mut writer = Cursor::new(Vec::new());
592        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
593        let cipher_text = writer.into_inner();
594        assert_eq!(
595            &cipher_text,
596            &[
597                0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f,
598                0xb8, 0x94, 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, 0xba, 0x26, 0x2a, 0x3c,
599                0xca, 0x7e, 0x2c, 0xa7, 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, 0xcc, 0xdc,
600                0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
601                0x4c, 0x34, 0xae, 0xe5
602            ]
603        );
604        assert_eq!(
605            &tag,
606            &[
607                0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99,
608                0xd0, 0x50
609            ]
610        );
611    }
612
613    #[test]
614    fn test_gcm_aes_192_encrypt() {
615        //https://luca-giuzzi.unibs.it/corsi/Support/papers-cryptography/gcm-spec.pdf
616        //Test  Case  7
617        let cipher_key = [
618            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
620        ];
621        let iv = [
622            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623        ];
624        let p = [];
625        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
626        let reader = Cursor::new(&p);
627        let mut writer = Cursor::new(Vec::new());
628        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &"".as_bytes(), &mul_fn)).unwrap();
629        let cipher_text = writer.into_inner();
630        assert_eq!(&cipher_text, &[]);
631        assert_eq!(
632            &tag,
633            &[
634                0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57,
635                0x24, 0x35
636            ]
637        );
638
639        //Test  Case  8
640        let cipher_key = [
641            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643        ];
644        let iv = [
645            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646        ];
647        let p = [
648            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649            0x00, 0x00,
650        ];
651        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
652        let reader = Cursor::new(&p);
653        let mut writer = Cursor::new(Vec::new());
654        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &"".as_bytes(), &mul_fn)).unwrap();
655        let cipher_text = writer.into_inner();
656        assert_eq!(
657            &cipher_text,
658            &[
659                0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0,
660                0xf6, 0x00
661            ]
662        );
663        assert_eq!(
664            &tag,
665            &[
666                0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14,
667                0xf0, 0xfb
668            ]
669        );
670
671        //Test  Case  9
672        let cipher_key = [
673            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
674            0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
675        ];
676        let iv = [
677            0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
678        ];
679        let p = [
680            0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
681            0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
682            0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
683            0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
684            0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
685        ];
686        let aad = [];
687        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
688        let reader = Cursor::new(&p);
689        let mut writer = Cursor::new(Vec::new());
690        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
691        let cipher_text = writer.into_inner();
692        assert_eq!(
693            &cipher_text,
694            &[
695                0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a,
696                0x27, 0x57, 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 0x62, 0x85, 0x93, 0xb4,
697                0x0c, 0xa1, 0xe1, 0x9c, 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 0xac, 0x61,
698                0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
699                0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56
700            ]
701        );
702        assert_eq!(
703            &tag,
704            &[
705                0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67,
706                0x4a, 0x14
707            ]
708        );
709
710        //Test  Case  10
711        let cipher_key = [
712            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
713            0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
714        ];
715        let iv = [
716            0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
717        ];
718        let p = [
719            0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
720            0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
721            0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
722            0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
723            0xba, 0x63, 0x7b, 0x39,
724        ];
725        let aad = [
726            0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
727            0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
728        ];
729        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
730        let reader = Cursor::new(&p);
731        let mut writer = Cursor::new(Vec::new());
732        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
733        let cipher_text = writer.into_inner();
734        assert_eq!(
735            &cipher_text,
736            &[
737                0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a,
738                0x27, 0x57, 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, 0x62, 0x85, 0x93, 0xb4,
739                0x0c, 0xa1, 0xe1, 0x9c, 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, 0xac, 0x61,
740                0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
741                0xcc, 0xda, 0x27, 0x10
742            ]
743        );
744        assert_eq!(
745            &tag,
746            &[
747                0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27,
748                0x61, 0x8c
749            ]
750        );
751
752        //Test  Case  11
753        let cipher_key = [
754            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
755            0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
756        ];
757        let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad];
758        let p = [
759            0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
760            0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
761            0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
762            0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
763            0xba, 0x63, 0x7b, 0x39,
764        ];
765        let aad = [
766            0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
767            0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
768        ];
769        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
770        let reader = Cursor::new(&p);
771        let mut writer = Cursor::new(Vec::new());
772        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
773        let cipher_text = writer.into_inner();
774        assert_eq!(
775            &cipher_text,
776            &[
777                0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32,
778                0x4d, 0xb8, 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, 0x83, 0x47, 0x28, 0x0f,
779                0xc4, 0x50, 0x70, 0x57, 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, 0xc6, 0x65,
780                0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f,
781                0xa0, 0xf0, 0x62, 0xf7
782            ]
783        );
784        assert_eq!(
785            &tag,
786            &[
787                0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35,
788                0x33, 0xf8
789            ]
790        );
791
792        //Test  Case  12
793        let cipher_key = [
794            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
795            0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
796        ];
797        let iv = [
798            0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52,
799            0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 0xe4, 0xc3, 0x03, 0xd2,
800            0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0,
801            0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
802            0xa6, 0x37, 0xb3, 0x9b,
803        ];
804        let p = [
805            0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
806            0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
807            0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
808            0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
809            0xba, 0x63, 0x7b, 0x39,
810        ];
811        let aad = [
812            0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
813            0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
814        ];
815        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
816        let reader = Cursor::new(&p);
817        let mut writer = Cursor::new(Vec::new());
818        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
819        let cipher_text = writer.into_inner();
820        assert_eq!(
821            &cipher_text,
822            &[
823                0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc,
824                0xf9, 0xff, 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, 0x6e, 0xf7, 0xb7, 0x98,
825                0x28, 0x66, 0x6e, 0x45, 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, 0xe2, 0xf0,
826                0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7,
827                0xe9, 0xb7, 0x37, 0x3b
828            ]
829        );
830        assert_eq!(
831            &tag,
832            &[
833                0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76,
834                0xa6, 0xd9
835            ]
836        );
837    }
838
839    #[test]
840    fn test_gcm_aes_256_encrypt() {
841        //https://luca-giuzzi.unibs.it/corsi/Support/papers-cryptography/gcm-spec.pdf
842        //Test  Case  13
843        let cipher_key = [
844            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
845            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
846            0x00, 0x00, 0x00, 0x00,
847        ];
848        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
849        let iv = [
850            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
851        ];
852        let p = [];
853        let reader = Cursor::new(&p);
854        let mut writer = Cursor::new(Vec::new());
855        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &"".as_bytes(), &mul_fn)).unwrap();
856        let cipher_text = writer.into_inner();
857        assert_eq!(&cipher_text, &[]);
858        assert_eq!(
859            &tag,
860            &[
861                0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb,
862                0x73, 0x8b
863            ]
864        );
865
866        //Test  Case  14
867        let cipher_key = [
868            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
869            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
870            0x00, 0x00, 0x00, 0x00,
871        ];
872        let iv = [
873            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
874        ];
875        let p = [
876            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
877            0x00, 0x00,
878        ];
879        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
880        let reader = Cursor::new(&p);
881        let mut writer = Cursor::new(Vec::new());
882        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &"".as_bytes(), &mul_fn)).unwrap();
883        let cipher_text = writer.into_inner();
884        assert_eq!(
885            &cipher_text,
886            &[
887                0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3,
888                0x9d, 0x18
889            ]
890        );
891        assert_eq!(
892            &tag,
893            &[
894                0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a,
895                0xb9, 0x19
896            ]
897        );
898
899        //Test  Case  15
900        let cipher_key = [
901            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
902            0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
903            0x67, 0x30, 0x83, 0x08,
904        ];
905        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
906        let iv = [
907            0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
908        ];
909        let p = [
910            0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
911            0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
912            0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
913            0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
914            0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
915        ];
916        let aad = [];
917        let reader = Cursor::new(&p);
918        let mut writer = Cursor::new(Vec::new());
919        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
920        let cipher_text = writer.into_inner();
921        assert_eq!(
922            &cipher_text,
923            &[
924                0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84,
925                0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd,
926                0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0,
927                0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
928                0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad
929            ]
930        );
931        assert_eq!(
932            &tag,
933            &[
934                0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3,
935                0xcc, 0x6c
936            ]
937        );
938
939        //Test  Case  16
940        let cipher_key = [
941            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
942            0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
943            0x67, 0x30, 0x83, 0x08,
944        ];
945        let iv = [
946            0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
947        ];
948        let p = [
949            0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
950            0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
951            0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
952            0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
953            0xba, 0x63, 0x7b, 0x39,
954        ];
955        let aad = [
956            0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
957            0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
958        ];
959        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
960        let reader = Cursor::new(&p);
961        let mut writer = Cursor::new(Vec::new());
962        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
963        let cipher_text = writer.into_inner();
964        assert_eq!(
965            &cipher_text,
966            &[
967                0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84,
968                0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd,
969                0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0,
970                0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
971                0xbc, 0xc9, 0xf6, 0x62
972            ]
973        );
974        assert_eq!(
975            &tag,
976            &[
977                0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d,
978                0x55, 0x1b
979            ]
980        );
981
982        //Test  Case  17
983        let cipher_key = [
984            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
985            0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
986            0x67, 0x30, 0x83, 0x08,
987        ];
988        let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad];
989        let p = [
990            0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
991            0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
992            0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
993            0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
994            0xba, 0x63, 0x7b, 0x39,
995        ];
996        let aad = [
997            0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
998            0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
999        ];
1000        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
1001        let reader = Cursor::new(&p);
1002        let mut writer = Cursor::new(Vec::new());
1003        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
1004        let cipher_text = writer.into_inner();
1005        assert_eq!(
1006            &cipher_text,
1007            &[
1008                0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98,
1009                0x44, 0xcb, 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, 0xc5, 0x2f, 0xf7, 0xd7,
1010                0x9b, 0xba, 0x9d, 0xe0, 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, 0x95, 0x4c,
1011                0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
1012                0xf4, 0x7c, 0x9b, 0x1f
1013            ]
1014        );
1015        assert_eq!(
1016            &tag,
1017            &[
1018                0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e,
1019                0xa8, 0xf2
1020            ]
1021        );
1022
1023        //Test  Case  18
1024        let cipher_key = [
1025            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
1026            0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
1027            0x67, 0x30, 0x83, 0x08,
1028        ];
1029        let iv = [
1030            0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52,
1031            0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 0xe4, 0xc3, 0x03, 0xd2,
1032            0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0,
1033            0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
1034            0xa6, 0x37, 0xb3, 0x9b,
1035        ];
1036        let p = [
1037            0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
1038            0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
1039            0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
1040            0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
1041            0xba, 0x63, 0x7b, 0x39,
1042        ];
1043        let aad = [
1044            0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
1045            0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
1046        ];
1047        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
1048        let reader = Cursor::new(&p);
1049        let mut writer = Cursor::new(Vec::new());
1050        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
1051        let cipher_text = writer.into_inner();
1052        assert_eq!(
1053            &cipher_text,
1054            &[
1055                0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e,
1056                0x2a, 0x20, 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, 0xa0, 0x58, 0xab, 0x4f,
1057                0x6f, 0x74, 0x6b, 0xf4, 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, 0x2d, 0xa3,
1058                0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
1059                0x44, 0xae, 0x7e, 0x3f
1060            ]
1061        );
1062        assert_eq!(
1063            &tag,
1064            &[
1065                0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9,
1066                0xf1, 0x9a
1067            ]
1068        );
1069    }
1070
1071    #[test]
1072    fn test_calculate_m() {
1073        let cipher_key = [
1074            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1075            0x00, 0x00,
1076        ];
1077        let h_block = aes::encrypt(&[0u8; BLOCK_SIZE], &cipher_key);
1078        let h = u128::from_be_bytes(h_block);
1079        let m0 = calculate_table_m(h, 0);
1080        assert_eq!(
1081            block_mul(h, 254u128.reverse_bits()),
1082            m0[254u8.reverse_bits() as usize]
1083        );
1084        assert_eq!(
1085            block_mul(h, 1u128.reverse_bits()),
1086            m0[1u8.reverse_bits() as usize]
1087        );
1088        assert_eq!(
1089            block_mul(h, 0u128.reverse_bits()),
1090            m0[0u8.reverse_bits() as usize]
1091        );
1092        assert_eq!(
1093            block_mul(h, 2u128.reverse_bits()),
1094            m0[2u8.reverse_bits() as usize]
1095        );
1096        assert_eq!(
1097            block_mul(h, 4u128.reverse_bits()),
1098            m0[4u8.reverse_bits() as usize]
1099        );
1100        assert_eq!(
1101            block_mul(h, 37u128.reverse_bits()),
1102            m0[37u8.reverse_bits() as usize]
1103        );
1104
1105        let m1 = calculate_table_m(h, 1);
1106        assert_eq!(block_mul(m0[254], 1u128.reverse_bits() >> 8), m1[254]);
1107        assert_eq!(block_mul(m0[1], 1u128.reverse_bits() >> 8), m1[1]);
1108        assert_eq!(block_mul(m0[4], 1u128.reverse_bits() >> 8), m1[4]);
1109        assert_eq!(block_mul(m0[0], 1u128.reverse_bits() >> 8), m1[0]);
1110        assert_eq!(block_mul(m0[2], 1u128.reverse_bits() >> 8), m1[2]);
1111        assert_eq!(block_mul(m0[37], 1u128.reverse_bits() >> 8), m1[37]);
1112
1113        let m2 = calculate_table_m(h, 2);
1114        assert_eq!(block_mul(m1[254], 1u128.reverse_bits() >> 8), m2[254]);
1115        assert_eq!(block_mul(m1[1], 1u128.reverse_bits() >> 8), m2[1]);
1116        assert_eq!(block_mul(m1[4], 1u128.reverse_bits() >> 8), m2[4]);
1117        assert_eq!(block_mul(m1[0], 1u128.reverse_bits() >> 8), m2[0]);
1118        assert_eq!(block_mul(m1[2], 1u128.reverse_bits() >> 8), m2[2]);
1119        assert_eq!(block_mul(m1[37], 1u128.reverse_bits() >> 8), m2[37]);
1120        assert_eq!(block_mul(m0[37], 1u128.reverse_bits() >> 16), m2[37]);
1121
1122        let m3 = calculate_table_m(h, 3);
1123        assert_eq!(block_mul(m2[255], 1u128.reverse_bits() >> 8), m3[255]);
1124        assert_eq!(block_mul(m2[11], 1u128.reverse_bits() >> 8), m3[11]);
1125        assert_eq!(block_mul(m2[8], 1u128.reverse_bits() >> 8), m3[8]);
1126        assert_eq!(block_mul(m2[15], 1u128.reverse_bits() >> 8), m3[15]);
1127        assert_eq!(block_mul(m2[3], 1u128.reverse_bits() >> 8), m3[3]);
1128        assert_eq!(block_mul(m2[33], 1u128.reverse_bits() >> 8), m3[33]);
1129        assert_eq!(block_mul(m0[77], 1u128.reverse_bits() >> 24), m3[77]);
1130
1131        let m4 = calculate_table_m(h, 4);
1132        assert_eq!(block_mul(m3[64], 1u128.reverse_bits() >> 8), m4[64]);
1133        assert_eq!(block_mul(m3[32], 1u128.reverse_bits() >> 8), m4[32]);
1134        assert_eq!(block_mul(m3[192], 1u128.reverse_bits() >> 8), m4[192]);
1135        assert_eq!(block_mul(m3[12], 1u128.reverse_bits() >> 8), m4[12]);
1136        assert_eq!(block_mul(m3[128], 1u128.reverse_bits() >> 8), m4[128]);
1137        assert_eq!(block_mul(m3[129], 1u128.reverse_bits() >> 8), m4[129]);
1138        assert_eq!(block_mul(m0[211], 1u128.reverse_bits() >> 32), m4[211]);
1139
1140        let m5 = calculate_table_m(h, 5);
1141        assert_eq!(block_mul(m0[12], 1u128.reverse_bits() >> 40), m5[12]);
1142        assert_eq!(block_mul(m1[15], 1u128.reverse_bits() >> 32), m5[15]);
1143        assert_eq!(block_mul(m2[16], 1u128.reverse_bits() >> 24), m5[16]);
1144        assert_eq!(block_mul(m3[128], 1u128.reverse_bits() >> 16), m5[128]);
1145
1146        let m6 = calculate_table_m(h, 6);
1147        let m7 = calculate_table_m(h, 7);
1148        let m8 = calculate_table_m(h, 8);
1149        let m9 = calculate_table_m(h, 9);
1150        let m10 = calculate_table_m(h, 10);
1151        let m11 = calculate_table_m(h, 11);
1152        let m12 = calculate_table_m(h, 12);
1153        let m13 = calculate_table_m(h, 13);
1154        let m14 = calculate_table_m(h, 14);
1155        let m15 = calculate_table_m(h, 15);
1156        assert_eq!(block_mul(m0[2], 1u128.reverse_bits() >> 120), m15[2]);
1157        assert_eq!(block_mul(m1[3], 1u128.reverse_bits() >> 112), m15[3]);
1158        assert_eq!(block_mul(m2[4], 1u128.reverse_bits() >> 104), m15[4]);
1159        assert_eq!(block_mul(m3[5], 1u128.reverse_bits() >> 96), m15[5]);
1160        assert_eq!(block_mul(m4[6], 1u128.reverse_bits() >> 88), m15[6]);
1161        assert_eq!(block_mul(m5[7], 1u128.reverse_bits() >> 80), m15[7]);
1162        assert_eq!(block_mul(m6[8], 1u128.reverse_bits() >> 72), m15[8]);
1163        assert_eq!(block_mul(m7[9], 1u128.reverse_bits() >> 64), m15[9]);
1164        assert_eq!(block_mul(m8[1], 1u128.reverse_bits() >> 56), m15[1]);
1165        assert_eq!(block_mul(m9[255], 1u128.reverse_bits() >> 48), m15[255]);
1166        assert_eq!(block_mul(m10[232], 1u128.reverse_bits() >> 40), m15[232]);
1167        assert_eq!(block_mul(m11[192], 1u128.reverse_bits() >> 32), m15[192]);
1168        assert_eq!(block_mul(m12[64], 1u128.reverse_bits() >> 24), m15[64]);
1169        assert_eq!(block_mul(m13[17], 1u128.reverse_bits() >> 16), m15[17]);
1170        assert_eq!(block_mul(m14[93], 1u128.reverse_bits() >> 8), m15[93]);
1171    }
1172
1173    #[test]
1174    fn test_gcm_aes_block_mul_with_tables() {
1175        let cipher_key = [
1176            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1177            0x00, 0x00,
1178        ];
1179        let h_block = aes::encrypt(&[0u8; BLOCK_SIZE], &cipher_key);
1180        let h = u128::from_be_bytes(h_block);
1181        let mut m = [[0u128; 256]; BLOCK_SIZE];
1182        for i in 0..BLOCK_SIZE {
1183            m[i] = calculate_table_m(h, i);
1184        }
1185        let x_block = [
1186            0x2fu8, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14,
1187            0xf0, 0xfb,
1188        ];
1189        let x = u128::from_be_bytes(x_block);
1190        let r1 = block_mul_with_tables(&m, x);
1191        let r2 = block_mul(x, h);
1192        assert_eq!(r1, r2);
1193
1194        let cipher_key = [
1195            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
1196            0x83, 0x08,
1197        ];
1198        let iv = [
1199            0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
1200        ];
1201        let p = [
1202            0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
1203            0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
1204            0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
1205            0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
1206            0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
1207        ];
1208        let aad = [];
1209        let mul_fn = GcmBlockMulEnhancement::MTables.to_mul_fn(&cipher_key);
1210        let reader = Cursor::new(&p);
1211        let mut writer = Cursor::new(Vec::new());
1212        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
1213        let cipher_text = writer.into_inner();
1214        assert_eq!(
1215            &cipher_text,
1216            &[
1217                0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
1218                0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
1219                0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
1220                0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
1221                0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85
1222            ]
1223        );
1224        assert_eq!(
1225            &tag,
1226            &[
1227                0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6,
1228                0xfa, 0xb4
1229            ]
1230        );
1231    }
1232
1233    #[test]
1234    fn test_gcm_aes_block_mul_with_4bit_tables() {
1235        let cipher_key = [
1236            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1237            0x00, 0x00,
1238        ];
1239        let h_block = aes::encrypt(&[0u8; BLOCK_SIZE], &cipher_key);
1240        let h = u128::from_be_bytes(h_block);
1241        let mut m = [[0u128; 16]; BLOCK_SIZE << 1];
1242        for i in 0..m.len() {
1243            m[i] = calculate_4bit_table_m(h, i);
1244        }
1245        let x_block = [
1246            0x2fu8, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14,
1247            0xf0, 0xfb,
1248        ];
1249        let x = u128::from_be_bytes(x_block);
1250        let r1 = block_mul_with_4bit_tables(&m, x);
1251        let r2 = block_mul(x, h);
1252        assert_eq!(r1, r2);
1253
1254        let cipher_key = [
1255            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
1256            0x83, 0x08,
1257        ];
1258        let iv = [
1259            0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
1260        ];
1261        let p = [
1262            0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
1263            0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
1264            0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
1265            0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
1266            0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
1267        ];
1268        let aad = [];
1269        let mul_fn = GcmBlockMulEnhancement::M4BitTables.to_mul_fn(&cipher_key);
1270        let reader = Cursor::new(&p);
1271        let mut writer = Cursor::new(Vec::new());
1272        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
1273        let cipher_text = writer.into_inner();
1274        assert_eq!(
1275            &cipher_text,
1276            &[
1277                0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
1278                0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
1279                0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
1280                0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
1281                0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85
1282            ]
1283        );
1284        assert_eq!(
1285            &tag,
1286            &[
1287                0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6,
1288                0xfa, 0xb4
1289            ]
1290        );
1291    }
1292
1293    #[test]
1294    fn test_gcm_aes_calculate_r_table() {
1295        assert_eq!(TABLE_R[0x80], 0xe100);
1296    }
1297
1298    #[test]
1299    fn test_gcm_aes_block_mul_with_m0_r() {
1300        let cipher_key = [
1301            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1302            0x00, 0x00,
1303        ];
1304        let h_block = aes::encrypt(&[0u8; BLOCK_SIZE], &cipher_key);
1305        let h = u128::from_be_bytes(h_block);
1306        let m0 = calculate_table_m(h, 0);
1307        let x_block = [
1308            0x2fu8, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14,
1309            0xf0, 0xfb,
1310        ];
1311        let x = u128::from_be_bytes(x_block);
1312        let r1 = block_mul_with_m0_r(&m0, x);
1313        let r2 = block_mul(h, x);
1314        assert_eq!(r1, r2);
1315
1316        let cipher_key = [
1317            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
1318            0x83, 0x08,
1319        ];
1320        let iv = [
1321            0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
1322        ];
1323        let p = [
1324            0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
1325            0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
1326            0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
1327            0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
1328            0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55,
1329        ];
1330        let aad = [];
1331        let mul_fn = GcmBlockMulEnhancement::M0TableAndRTable.to_mul_fn(&cipher_key);
1332        let reader = Cursor::new(&p);
1333        let mut writer = Cursor::new(Vec::new());
1334        let tag = block_on(gcm_aes_encrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
1335        let cipher_text = writer.into_inner();
1336        assert_eq!(
1337            &cipher_text,
1338            &[
1339                0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
1340                0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
1341                0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
1342                0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
1343                0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85
1344            ]
1345        );
1346        assert_eq!(
1347            &tag,
1348            &[
1349                0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6,
1350                0xfa, 0xb4
1351            ]
1352        );
1353    }
1354
1355    #[test]
1356    fn test_gcm_aes_128_decrypt() {
1357        //https://luca-giuzzi.unibs.it/corsi/Support/papers-cryptography/gcm-spec.pdf
1358        //Test  Case  1
1359        let cipher_key = [
1360            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1361            0x00, 0x00,
1362        ];
1363        let iv = [
1364            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1365        ];
1366        let cipher_text = [];
1367        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
1368        let reader = Cursor::new(&cipher_text);
1369        let mut writer = Cursor::new(Vec::new());
1370        let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &[], &mul_fn)).unwrap();
1371        let p = writer.into_inner();
1372        assert_eq!(&p, &[]);
1373        assert_eq!(
1374            &tag,
1375            &[
1376                0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7,
1377                0x45, 0x5a
1378            ]
1379        );
1380
1381        //Test  Case  2
1382        let cipher_text = [
1383            0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2,
1384            0xfe, 0x78,
1385        ];
1386        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
1387        let reader = Cursor::new(&cipher_text);
1388        let mut writer = Cursor::new(Vec::new());
1389        let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &[], &mul_fn)).unwrap();
1390        let p = writer.into_inner();
1391        assert_eq!(
1392            &p,
1393            &[
1394                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1395                0x00, 0x00
1396            ]
1397        );
1398        assert_eq!(
1399            &tag,
1400            &[
1401                0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57,
1402                0xbd, 0xdf
1403            ]
1404        );
1405
1406        //Test  Case  3
1407        let cipher_key = [
1408            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
1409            0x83, 0x08,
1410        ];
1411        let iv = [
1412            0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
1413        ];
1414        let cipher_text = [
1415            0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
1416            0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
1417            0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
1418            0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
1419            0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85,
1420        ];
1421        let aad = [];
1422        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
1423        let reader = Cursor::new(&cipher_text);
1424        let mut writer = Cursor::new(Vec::new());
1425        let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
1426        let p = writer.into_inner();
1427        assert_eq!(
1428            &p,
1429            &[
1430                0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
1431                0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
1432                0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
1433                0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
1434                0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55
1435            ]
1436        );
1437        assert_eq!(
1438            &tag,
1439            &[
1440                0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6,
1441                0xfa, 0xb4
1442            ]
1443        );
1444
1445        //Test  Case  4
1446        let cipher_key = [
1447            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
1448            0x83, 0x08,
1449        ];
1450        let iv = [
1451            0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
1452        ];
1453        let cipher_text = [
1454            0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0,
1455            0xd4, 0x9c, 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, 0x35, 0xc1, 0x7e, 0x23,
1456            0x29, 0xac, 0xa1, 0x2e, 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, 0x7d, 0x8f,
1457            0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
1458            0x3d, 0x58, 0xe0, 0x91,
1459        ];
1460        let aad = [
1461            0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
1462            0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
1463        ];
1464        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
1465        let reader = Cursor::new(&cipher_text);
1466        let mut writer = Cursor::new(Vec::new());
1467        let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
1468        let p = writer.into_inner();
1469        assert_eq!(
1470            &p,
1471            &[
1472                0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
1473                0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
1474                0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
1475                0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
1476                0xba, 0x63, 0x7b, 0x39
1477            ]
1478        );
1479        assert_eq!(
1480            &tag,
1481            &[
1482                0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12,
1483                0x1a, 0x47
1484            ]
1485        );
1486
1487        //Test  Case  5
1488        let cipher_key = [
1489            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
1490            0x83, 0x08,
1491        ];
1492        let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad];
1493        let cipher_text = [
1494            0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a,
1495            0x47, 0x55, 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, 0x37, 0x66, 0xe5, 0xf9,
1496            0x7b, 0x6c, 0x74, 0x23, 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, 0x2b, 0x09,
1497            0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07,
1498            0xc2, 0x3f, 0x45, 0x98,
1499        ];
1500        let aad = [
1501            0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
1502            0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
1503        ];
1504        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
1505        let reader = Cursor::new(&cipher_text);
1506        let mut writer = Cursor::new(Vec::new());
1507        let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
1508        let p = writer.into_inner();
1509        assert_eq!(
1510            &p,
1511            &[
1512                0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
1513                0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
1514                0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
1515                0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
1516                0xba, 0x63, 0x7b, 0x39
1517            ]
1518        );
1519        assert_eq!(
1520            &tag,
1521            &[
1522                0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2,
1523                0xfc, 0xcb
1524            ]
1525        );
1526
1527        //Test  Case  6
1528        let cipher_key = [
1529            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
1530            0x83, 0x08,
1531        ];
1532        let iv = [
1533            0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52,
1534            0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 0xe4, 0xc3, 0x03, 0xd2,
1535            0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0,
1536            0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
1537            0xa6, 0x37, 0xb3, 0x9b,
1538        ];
1539        let cipher_text = [
1540            0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f,
1541            0xb8, 0x94, 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, 0xba, 0x26, 0x2a, 0x3c,
1542            0xca, 0x7e, 0x2c, 0xa7, 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, 0xcc, 0xdc,
1543            0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
1544            0x4c, 0x34, 0xae, 0xe5,
1545        ];
1546        let aad = [
1547            0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
1548            0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
1549        ];
1550        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
1551        let reader = Cursor::new(&cipher_text);
1552        let mut writer = Cursor::new(Vec::new());
1553        let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
1554        let p = writer.into_inner();
1555        assert_eq!(
1556            &p,
1557            &[
1558                0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
1559                0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
1560                0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
1561                0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
1562                0xba, 0x63, 0x7b, 0x39
1563            ]
1564        );
1565        assert_eq!(
1566            &tag,
1567            &[
1568                0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99,
1569                0xd0, 0x50
1570            ]
1571        );
1572    }
1573
1574    #[test]
1575    fn test_gcm_aes_256_decrypt() {
1576        //https://luca-giuzzi.unibs.it/corsi/Support/papers-cryptography/gcm-spec.pdf
1577        //Test  Case  13
1578        let cipher_key = [
1579            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1580            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1581            0x00, 0x00, 0x00, 0x00,
1582        ];
1583        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
1584        let iv = [
1585            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1586        ];
1587        let cipher_text = [];
1588        let reader = Cursor::new(&cipher_text);
1589        let mut writer = Cursor::new(Vec::new());
1590        let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &[], &mul_fn)).unwrap();
1591        let p = writer.into_inner();
1592        assert_eq!(&p, &[]);
1593        assert_eq!(
1594            &tag,
1595            &[
1596                0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb,
1597                0x73, 0x8b
1598            ]
1599        );
1600
1601        //Test  Case  14
1602        let cipher_key = [
1603            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1604            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1605            0x00, 0x00, 0x00, 0x00,
1606        ];
1607        let iv = [
1608            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1609        ];
1610        let cipher_text = [
1611            0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3,
1612            0x9d, 0x18,
1613        ];
1614        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
1615        let reader = Cursor::new(&cipher_text);
1616        let mut writer = Cursor::new(Vec::new());
1617        let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &"".as_bytes(), &mul_fn)).unwrap();
1618        let p = writer.into_inner();
1619        assert_eq!(
1620            &p,
1621            &[
1622                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1623                0x00, 0x00
1624            ]
1625        );
1626        assert_eq!(
1627            &tag,
1628            &[
1629                0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a,
1630                0xb9, 0x19
1631            ]
1632        );
1633
1634        //Test  Case  15
1635        let cipher_key = [
1636            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
1637            0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
1638            0x67, 0x30, 0x83, 0x08,
1639        ];
1640        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
1641        let iv = [
1642            0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
1643        ];
1644        let cipher_text = [
1645            0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84,
1646            0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd,
1647            0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0,
1648            0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
1649            0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad,
1650        ];
1651        let aad = [];
1652        let reader = Cursor::new(&cipher_text);
1653        let mut writer = Cursor::new(Vec::new());
1654        let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
1655        let p = writer.into_inner();
1656        assert_eq!(
1657            &p,
1658            &[
1659                0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
1660                0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
1661                0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
1662                0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
1663                0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55
1664            ]
1665        );
1666        assert_eq!(
1667            &tag,
1668            &[
1669                0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3,
1670                0xcc, 0x6c
1671            ]
1672        );
1673
1674        //Test  Case  16
1675        let cipher_key = [
1676            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
1677            0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
1678            0x67, 0x30, 0x83, 0x08,
1679        ];
1680        let iv = [
1681            0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88,
1682        ];
1683        let cipher_text = [
1684            0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84,
1685            0x42, 0x7d, 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, 0x75, 0x98, 0xa2, 0xbd,
1686            0x25, 0x55, 0xd1, 0xaa, 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, 0xa7, 0xb0,
1687            0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
1688            0xbc, 0xc9, 0xf6, 0x62,
1689        ];
1690        let aad = [
1691            0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
1692            0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
1693        ];
1694        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
1695        let reader = Cursor::new(&cipher_text);
1696        let mut writer = Cursor::new(Vec::new());
1697        let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
1698        let p = writer.into_inner();
1699        assert_eq!(
1700            &p,
1701            &[
1702                0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
1703                0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
1704                0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
1705                0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
1706                0xba, 0x63, 0x7b, 0x39
1707            ]
1708        );
1709        assert_eq!(
1710            &tag,
1711            &[
1712                0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d,
1713                0x55, 0x1b
1714            ]
1715        );
1716
1717        //Test  Case  17
1718        let cipher_key = [
1719            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
1720            0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
1721            0x67, 0x30, 0x83, 0x08,
1722        ];
1723        let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad];
1724        let cipher_text = [
1725            0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98,
1726            0x44, 0xcb, 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, 0xc5, 0x2f, 0xf7, 0xd7,
1727            0x9b, 0xba, 0x9d, 0xe0, 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, 0x95, 0x4c,
1728            0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99,
1729            0xf4, 0x7c, 0x9b, 0x1f,
1730        ];
1731        let aad = [
1732            0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
1733            0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
1734        ];
1735        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
1736        let reader = Cursor::new(&cipher_text);
1737        let mut writer = Cursor::new(Vec::new());
1738        let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
1739        let p = writer.into_inner();
1740        assert_eq!(
1741            &p,
1742            &[
1743                0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
1744                0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
1745                0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
1746                0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
1747                0xba, 0x63, 0x7b, 0x39
1748            ]
1749        );
1750        assert_eq!(
1751            &tag,
1752            &[
1753                0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e,
1754                0xa8, 0xf2
1755            ]
1756        );
1757
1758        //Test  Case  18
1759        let cipher_key = [
1760            0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30,
1761            0x83, 0x08, 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94,
1762            0x67, 0x30, 0x83, 0x08,
1763        ];
1764        let iv = [
1765            0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52,
1766            0x69, 0xaa, 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, 0xe4, 0xc3, 0x03, 0xd2,
1767            0xa3, 0x18, 0xa7, 0x28, 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, 0xfc, 0xf0,
1768            0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57,
1769            0xa6, 0x37, 0xb3, 0x9b,
1770        ];
1771        let cipher_text = [
1772            0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e,
1773            0x2a, 0x20, 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, 0xa0, 0x58, 0xab, 0x4f,
1774            0x6f, 0x74, 0x6b, 0xf4, 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, 0x2d, 0xa3,
1775            0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
1776            0x44, 0xae, 0x7e, 0x3f,
1777        ];
1778        let aad = [
1779            0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad,
1780            0xbe, 0xef, 0xab, 0xad, 0xda, 0xd2,
1781        ];
1782        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&cipher_key);
1783        let reader = Cursor::new(&cipher_text);
1784        let mut writer = Cursor::new(Vec::new());
1785        let tag = block_on(gcm_aes_decrypt_async(&cipher_key, &iv, reader, &mut writer, &aad, &mul_fn)).unwrap();
1786        let p = writer.into_inner();
1787        assert_eq!(
1788            &p,
1789            &[
1790                0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5,
1791                0x26, 0x9a, 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, 0x2e, 0x4c, 0x30, 0x3d,
1792                0x8a, 0x31, 0x8a, 0x72, 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2f, 0xcf,
1793                0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
1794                0xba, 0x63, 0x7b, 0x39
1795            ]
1796        );
1797        assert_eq!(
1798            &tag,
1799            &[
1800                0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9,
1801                0xf1, 0x9a
1802            ]
1803        );
1804    }
1805
1806    // ===== NEW COMPREHENSIVE TESTS =====
1807
1808    #[test]
1809    fn test_input_validation_key_size() {
1810        let invalid_key = [0u8; 8]; // Too short
1811        let iv = [0xca, 0xfe, 0xba, 0xbe];
1812        let reader = Cursor::new(b"test");
1813        let mut writer = Cursor::new(Vec::new());
1814        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&[0u8; 16]);
1815        
1816        let result = block_on(gcm_aes_encrypt_async(&invalid_key, &iv, reader, &mut writer, &[], &mul_fn));
1817        assert!(matches!(result, Err(AesGcmAsyncError::InvalidKeySize(8))));
1818    }
1819
1820    #[test]
1821    fn test_input_validation_iv_size() {
1822        let key = [0u8; 16];
1823        let invalid_iv = [0u8; 0]; // Empty IV
1824        let reader = Cursor::new(b"test");
1825        let mut writer = Cursor::new(Vec::new());
1826        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&key);
1827        
1828        let result = block_on(gcm_aes_encrypt_async(&key, &invalid_iv, reader, &mut writer, &[], &mul_fn));
1829        assert!(matches!(result, Err(AesGcmAsyncError::InvalidIvSize(0))));
1830    }
1831
1832    #[test]
1833    fn test_input_validation_iv_large_allowed() {
1834        let key = [0u8; 16];
1835        let large_iv = [0u8; 60]; // Large IV should be allowed
1836        let reader = Cursor::new(b"test");
1837        let mut writer = Cursor::new(Vec::new());
1838        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&key);
1839        
1840        let result = block_on(gcm_aes_encrypt_async(&key, &large_iv, reader, &mut writer, &[], &mul_fn));
1841        assert!(result.is_ok()); // Large IVs should be allowed
1842    }
1843
1844    #[test]
1845    fn test_valid_key_sizes() {
1846        let iv = [0xca, 0xfe, 0xba, 0xbe];
1847        let plaintext = b"test data";
1848        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&[0u8; 16]);
1849        
1850        // Test AES-128 (16 bytes)
1851        let key_128 = [0u8; 16];
1852        let reader = Cursor::new(plaintext);
1853        let mut writer = Cursor::new(Vec::new());
1854        let result = block_on(gcm_aes_encrypt_async(&key_128, &iv, reader, &mut writer, &[], &mul_fn));
1855        assert!(result.is_ok());
1856        
1857        // Test AES-192 (24 bytes)
1858        let key_192 = [0u8; 24];
1859        let mul_fn_192 = GcmBlockMulEnhancement::None.to_mul_fn(&key_192);
1860        let reader = Cursor::new(plaintext);
1861        let mut writer = Cursor::new(Vec::new());
1862        let result = block_on(gcm_aes_encrypt_async(&key_192, &iv, reader, &mut writer, &[], &mul_fn_192));
1863        assert!(result.is_ok());
1864        
1865        // Test AES-256 (32 bytes)
1866        let key_256 = [0u8; 32];
1867        let mul_fn_256 = GcmBlockMulEnhancement::None.to_mul_fn(&key_256);
1868        let reader = Cursor::new(plaintext);
1869        let mut writer = Cursor::new(Vec::new());
1870        let result = block_on(gcm_aes_encrypt_async(&key_256, &iv, reader, &mut writer, &[], &mul_fn_256));
1871        assert!(result.is_ok());
1872    }
1873
1874    #[test]
1875    fn test_encrypt_decrypt_roundtrip() {
1876        let key = [0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08];
1877        let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad];
1878        let plaintext = b"Hello, World! This is a test message for AES-GCM encryption.";
1879        let aad = b"additional authenticated data";
1880        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&key);
1881        
1882        // Encrypt
1883        let reader = Cursor::new(plaintext);
1884        let mut writer = Cursor::new(Vec::new());
1885        let tag = block_on(gcm_aes_encrypt_async(&key, &iv, reader, &mut writer, aad, &mul_fn)).unwrap();
1886        let ciphertext = writer.into_inner();
1887        
1888        // Decrypt
1889        let reader = Cursor::new(&ciphertext);
1890        let mut writer = Cursor::new(Vec::new());
1891        let computed_tag = block_on(gcm_aes_decrypt_async(&key, &iv, reader, &mut writer, aad, &mul_fn)).unwrap();
1892        let decrypted = writer.into_inner();
1893        
1894        // Verify
1895        assert_eq!(plaintext, &decrypted[..]);
1896        assert_eq!(tag, computed_tag);
1897    }
1898
1899    #[test]
1900    fn test_authentication_failure() {
1901        let key = [0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08];
1902        let iv = [0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad];
1903        let plaintext = b"test message";
1904        let aad = b"aad";
1905        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&key);
1906        
1907        // Encrypt
1908        let reader = Cursor::new(plaintext);
1909        let mut writer = Cursor::new(Vec::new());
1910        let tag = block_on(gcm_aes_encrypt_async(&key, &iv, reader, &mut writer, aad, &mul_fn)).unwrap();
1911        let mut ciphertext = writer.into_inner();
1912        
1913        // Tamper with ciphertext
1914        ciphertext[0] ^= 1;
1915        
1916        // Try to decrypt tampered data
1917        let reader = Cursor::new(&ciphertext);
1918        let mut writer = Cursor::new(Vec::new());
1919        let computed_tag = block_on(gcm_aes_decrypt_async(&key, &iv, reader, &mut writer, aad, &mul_fn)).unwrap();
1920        
1921        // Tags should be different (authentication failure)
1922        assert_ne!(tag, computed_tag);
1923    }
1924
1925    #[test]
1926    fn test_large_data_performance() {
1927        let key = [0u8; 16];
1928        let iv = [0xca, 0xfe, 0xba, 0xbe];
1929        let plaintext = vec![0x42u8; 1024 * 1024]; // 1MB of data
1930        let aad = b"large data test";
1931        let mul_fn = GcmBlockMulEnhancement::None.to_mul_fn(&key);
1932        
1933        let reader = Cursor::new(&plaintext);
1934        let mut writer = Cursor::new(Vec::new());
1935        let start = std::time::Instant::now();
1936        let result = block_on(gcm_aes_encrypt_async(&key, &iv, reader, &mut writer, aad, &mul_fn));
1937        let duration = start.elapsed();
1938        
1939        assert!(result.is_ok());
1940        assert!(duration.as_millis() < 5000); // Should complete in less than 5 seconds (debug mode)
1941        assert_eq!(writer.into_inner().len(), plaintext.len());
1942    }
1943
1944    #[test]
1945    fn test_error_display_formatting() {
1946        let key_error = AesGcmAsyncError::InvalidKeySize(8);
1947        assert_eq!(format!("{}", key_error), "Invalid key size: 8 bytes. Must be 16, 24, or 32 bytes");
1948        
1949        let iv_error = AesGcmAsyncError::InvalidIvSize(0);
1950        assert_eq!(format!("{}", iv_error), "Invalid IV size: 0 bytes. Must be at least 1 byte (longer IVs are hashed to 12 bytes)");
1951        
1952        let auth_error = AesGcmAsyncError::AuthenticationFailed;
1953        assert_eq!(format!("{}", auth_error), "Authentication failed - message may be corrupted or tampered with");
1954    }
1955}
1956
1957