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#[derive(Debug, Clone, PartialEq)]
8pub enum AesGcmAsyncError {
9    InvalidKeySize(usize),
11    InvalidIvSize(usize),
13    IoError(String),
15    AuthenticationFailed,
17    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#[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#[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
71const OPTIMAL_BUFFER_SIZE: usize = 64 * 1024; pub 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    validate_key_size(key)?;
155    validate_iv_size(iv)?;
156    
157    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    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        let mut chunk_counter = counter_block.clone();
173        let cipher_chunk = gctr(&mut chunk_counter, &buffer[..n], key);
174        
175        writer.write_all(&cipher_chunk).await
177            .map_err(|e| AesGcmAsyncError::IoError(format!("Failed to write data: {}", e)))?;
178        
179        cipher_text.extend_from_slice(&cipher_chunk);
181        
182        for _ in 0..((n + BLOCK_SIZE - 1) / BLOCK_SIZE) {
184            increment_32_least_bits(&mut counter_block);
185        }
186    }
187    
188    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
198pub 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    validate_key_size(key)?;
290    validate_iv_size(iv)?;
291    
292    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    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        cipher_text.extend_from_slice(&buffer[..n]);
308        
309        let mut chunk_counter = counter_block.clone();
311        let plain_chunk = gctr(&mut chunk_counter, &buffer[..n], key);
312        
313        writer.write_all(&plain_chunk).await
315            .map_err(|e| AesGcmAsyncError::IoError(format!("Failed to write data: {}", e)))?;
316        
317        for _ in 0..((n + BLOCK_SIZE - 1) / BLOCK_SIZE) {
319            increment_32_least_bits(&mut counter_block);
320        }
321    }
322    
323    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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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        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    #[test]
1809    fn test_input_validation_key_size() {
1810        let invalid_key = [0u8; 8]; 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]; 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]; 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()); }
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        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        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        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        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        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        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        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        ciphertext[0] ^= 1;
1915        
1916        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        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]; 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); 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