192f3ab15Sopenharmony_ci//! Low level AES IGE and key wrapping functionality 292f3ab15Sopenharmony_ci//! 392f3ab15Sopenharmony_ci//! AES ECB, CBC, XTS, CTR, CFB, GCM and other conventional symmetric encryption 492f3ab15Sopenharmony_ci//! modes are found in [`symm`]. This is the implementation of AES IGE and key wrapping 592f3ab15Sopenharmony_ci//! 692f3ab15Sopenharmony_ci//! Advanced Encryption Standard (AES) provides symmetric key cipher that 792f3ab15Sopenharmony_ci//! the same key is used to encrypt and decrypt data. This implementation 892f3ab15Sopenharmony_ci//! uses 128, 192, or 256 bit keys. This module provides functions to 992f3ab15Sopenharmony_ci//! create a new key with [`new_encrypt`] and perform an encryption/decryption 1092f3ab15Sopenharmony_ci//! using that key with [`aes_ige`]. 1192f3ab15Sopenharmony_ci//! 1292f3ab15Sopenharmony_ci//! [`new_encrypt`]: struct.AesKey.html#method.new_encrypt 1392f3ab15Sopenharmony_ci//! [`aes_ige`]: fn.aes_ige.html 1492f3ab15Sopenharmony_ci//! 1592f3ab15Sopenharmony_ci//! The [`symm`] module should be used in preference to this module in most cases. 1692f3ab15Sopenharmony_ci//! The IGE block cipher is a non-traditional cipher mode. More traditional AES 1792f3ab15Sopenharmony_ci//! encryption methods are found in the [`Crypter`] and [`Cipher`] structs. 1892f3ab15Sopenharmony_ci//! 1992f3ab15Sopenharmony_ci//! [`symm`]: ../symm/index.html 2092f3ab15Sopenharmony_ci//! [`Crypter`]: ../symm/struct.Crypter.html 2192f3ab15Sopenharmony_ci//! [`Cipher`]: ../symm/struct.Cipher.html 2292f3ab15Sopenharmony_ci//! 2392f3ab15Sopenharmony_ci//! # Examples 2492f3ab15Sopenharmony_ci 2592f3ab15Sopenharmony_ci#![cfg_attr( 2692f3ab15Sopenharmony_ci all(not(boringssl), not(osslconf = "OPENSSL_NO_DEPRECATED_3_0")), 2792f3ab15Sopenharmony_ci doc = r#"\ 2892f3ab15Sopenharmony_ci## AES IGE 2992f3ab15Sopenharmony_ci```rust 3092f3ab15Sopenharmony_ciuse openssl::aes::{AesKey, aes_ige}; 3192f3ab15Sopenharmony_ciuse openssl::symm::Mode; 3292f3ab15Sopenharmony_ci 3392f3ab15Sopenharmony_cilet key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; 3492f3ab15Sopenharmony_cilet plaintext = b"\x12\x34\x56\x78\x90\x12\x34\x56\x12\x34\x56\x78\x90\x12\x34\x56"; 3592f3ab15Sopenharmony_cilet mut iv = *b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\ 3692f3ab15Sopenharmony_ci \x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"; 3792f3ab15Sopenharmony_ci 3892f3ab15Sopenharmony_ci let key = AesKey::new_encrypt(key).unwrap(); 3992f3ab15Sopenharmony_ci let mut output = [0u8; 16]; 4092f3ab15Sopenharmony_ci aes_ige(plaintext, &mut output, &key, &mut iv, Mode::Encrypt); 4192f3ab15Sopenharmony_ci assert_eq!(output, *b"\xa6\xad\x97\x4d\x5c\xea\x1d\x36\xd2\xf3\x67\x98\x09\x07\xed\x32"); 4292f3ab15Sopenharmony_ci```"# 4392f3ab15Sopenharmony_ci)] 4492f3ab15Sopenharmony_ci 4592f3ab15Sopenharmony_ci//! 4692f3ab15Sopenharmony_ci//! ## Key wrapping 4792f3ab15Sopenharmony_ci//! ```rust 4892f3ab15Sopenharmony_ci//! use openssl::aes::{AesKey, unwrap_key, wrap_key}; 4992f3ab15Sopenharmony_ci//! 5092f3ab15Sopenharmony_ci//! let kek = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; 5192f3ab15Sopenharmony_ci//! let key_to_wrap = b"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF"; 5292f3ab15Sopenharmony_ci//! 5392f3ab15Sopenharmony_ci//! let enc_key = AesKey::new_encrypt(kek).unwrap(); 5492f3ab15Sopenharmony_ci//! let mut ciphertext = [0u8; 24]; 5592f3ab15Sopenharmony_ci//! wrap_key(&enc_key, None, &mut ciphertext, &key_to_wrap[..]).unwrap(); 5692f3ab15Sopenharmony_ci//! let dec_key = AesKey::new_decrypt(kek).unwrap(); 5792f3ab15Sopenharmony_ci//! let mut orig_key = [0u8; 16]; 5892f3ab15Sopenharmony_ci//! unwrap_key(&dec_key, None, &mut orig_key, &ciphertext[..]).unwrap(); 5992f3ab15Sopenharmony_ci//! 6092f3ab15Sopenharmony_ci//! assert_eq!(&orig_key[..], &key_to_wrap[..]); 6192f3ab15Sopenharmony_ci//! ``` 6292f3ab15Sopenharmony_ci//! 6392f3ab15Sopenharmony_ciuse cfg_if::cfg_if; 6492f3ab15Sopenharmony_ciuse libc::{c_int, c_uint}; 6592f3ab15Sopenharmony_ciuse std::mem::MaybeUninit; 6692f3ab15Sopenharmony_ciuse std::ptr; 6792f3ab15Sopenharmony_ci 6892f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 6992f3ab15Sopenharmony_ciuse crate::symm::Mode; 7092f3ab15Sopenharmony_ciuse openssl_macros::corresponds; 7192f3ab15Sopenharmony_ci 7292f3ab15Sopenharmony_ci/// Provides Error handling for parsing keys. 7392f3ab15Sopenharmony_ci#[derive(Debug)] 7492f3ab15Sopenharmony_cipub struct KeyError(()); 7592f3ab15Sopenharmony_ci 7692f3ab15Sopenharmony_ci/// The key used to encrypt or decrypt cipher blocks. 7792f3ab15Sopenharmony_cipub struct AesKey(ffi::AES_KEY); 7892f3ab15Sopenharmony_ci 7992f3ab15Sopenharmony_cicfg_if! { 8092f3ab15Sopenharmony_ci if #[cfg(boringssl)] { 8192f3ab15Sopenharmony_ci type AesBitType = c_uint; 8292f3ab15Sopenharmony_ci type AesSizeType = usize; 8392f3ab15Sopenharmony_ci } else { 8492f3ab15Sopenharmony_ci type AesBitType = c_int; 8592f3ab15Sopenharmony_ci type AesSizeType = c_uint; 8692f3ab15Sopenharmony_ci } 8792f3ab15Sopenharmony_ci} 8892f3ab15Sopenharmony_ci 8992f3ab15Sopenharmony_ciimpl AesKey { 9092f3ab15Sopenharmony_ci /// Prepares a key for encryption. 9192f3ab15Sopenharmony_ci /// 9292f3ab15Sopenharmony_ci /// # Failure 9392f3ab15Sopenharmony_ci /// 9492f3ab15Sopenharmony_ci /// Returns an error if the key is not 128, 192, or 256 bits. 9592f3ab15Sopenharmony_ci #[corresponds(AES_set_encrypt_key)] 9692f3ab15Sopenharmony_ci pub fn new_encrypt(key: &[u8]) -> Result<AesKey, KeyError> { 9792f3ab15Sopenharmony_ci unsafe { 9892f3ab15Sopenharmony_ci assert!(key.len() <= c_int::max_value() as usize / 8); 9992f3ab15Sopenharmony_ci 10092f3ab15Sopenharmony_ci let mut aes_key = MaybeUninit::uninit(); 10192f3ab15Sopenharmony_ci let r = ffi::AES_set_encrypt_key( 10292f3ab15Sopenharmony_ci key.as_ptr() as *const _, 10392f3ab15Sopenharmony_ci key.len() as AesBitType * 8, 10492f3ab15Sopenharmony_ci aes_key.as_mut_ptr(), 10592f3ab15Sopenharmony_ci ); 10692f3ab15Sopenharmony_ci if r == 0 { 10792f3ab15Sopenharmony_ci Ok(AesKey(aes_key.assume_init())) 10892f3ab15Sopenharmony_ci } else { 10992f3ab15Sopenharmony_ci Err(KeyError(())) 11092f3ab15Sopenharmony_ci } 11192f3ab15Sopenharmony_ci } 11292f3ab15Sopenharmony_ci } 11392f3ab15Sopenharmony_ci 11492f3ab15Sopenharmony_ci /// Prepares a key for decryption. 11592f3ab15Sopenharmony_ci /// 11692f3ab15Sopenharmony_ci /// # Failure 11792f3ab15Sopenharmony_ci /// 11892f3ab15Sopenharmony_ci /// Returns an error if the key is not 128, 192, or 256 bits. 11992f3ab15Sopenharmony_ci #[corresponds(AES_set_decrypt_key)] 12092f3ab15Sopenharmony_ci pub fn new_decrypt(key: &[u8]) -> Result<AesKey, KeyError> { 12192f3ab15Sopenharmony_ci unsafe { 12292f3ab15Sopenharmony_ci assert!(key.len() <= c_int::max_value() as usize / 8); 12392f3ab15Sopenharmony_ci 12492f3ab15Sopenharmony_ci let mut aes_key = MaybeUninit::uninit(); 12592f3ab15Sopenharmony_ci let r = ffi::AES_set_decrypt_key( 12692f3ab15Sopenharmony_ci key.as_ptr() as *const _, 12792f3ab15Sopenharmony_ci key.len() as AesBitType * 8, 12892f3ab15Sopenharmony_ci aes_key.as_mut_ptr(), 12992f3ab15Sopenharmony_ci ); 13092f3ab15Sopenharmony_ci 13192f3ab15Sopenharmony_ci if r == 0 { 13292f3ab15Sopenharmony_ci Ok(AesKey(aes_key.assume_init())) 13392f3ab15Sopenharmony_ci } else { 13492f3ab15Sopenharmony_ci Err(KeyError(())) 13592f3ab15Sopenharmony_ci } 13692f3ab15Sopenharmony_ci } 13792f3ab15Sopenharmony_ci } 13892f3ab15Sopenharmony_ci} 13992f3ab15Sopenharmony_ci 14092f3ab15Sopenharmony_ci/// Performs AES IGE encryption or decryption 14192f3ab15Sopenharmony_ci/// 14292f3ab15Sopenharmony_ci/// AES IGE (Infinite Garble Extension) is a form of AES block cipher utilized in 14392f3ab15Sopenharmony_ci/// OpenSSL. Infinite Garble refers to propagating forward errors. IGE, like other 14492f3ab15Sopenharmony_ci/// block ciphers implemented for AES requires an initialization vector. The IGE mode 14592f3ab15Sopenharmony_ci/// allows a stream of blocks to be encrypted or decrypted without having the entire 14692f3ab15Sopenharmony_ci/// plaintext available. For more information, visit [AES IGE Encryption]. 14792f3ab15Sopenharmony_ci/// 14892f3ab15Sopenharmony_ci/// This block cipher uses 16 byte blocks. The rust implementation will panic 14992f3ab15Sopenharmony_ci/// if the input or output does not meet this 16-byte boundary. Attention must 15092f3ab15Sopenharmony_ci/// be made in this low level implementation to pad the value to the 128-bit boundary. 15192f3ab15Sopenharmony_ci/// 15292f3ab15Sopenharmony_ci/// [AES IGE Encryption]: http://www.links.org/files/openssl-ige.pdf 15392f3ab15Sopenharmony_ci/// 15492f3ab15Sopenharmony_ci/// # Panics 15592f3ab15Sopenharmony_ci/// 15692f3ab15Sopenharmony_ci/// Panics if `in_` is not the same length as `out`, if that length is not a multiple of 16, or if 15792f3ab15Sopenharmony_ci/// `iv` is not at least 32 bytes. 15892f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 15992f3ab15Sopenharmony_ci#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] 16092f3ab15Sopenharmony_ci#[corresponds(AES_ige_encrypt)] 16192f3ab15Sopenharmony_cipub fn aes_ige(in_: &[u8], out: &mut [u8], key: &AesKey, iv: &mut [u8], mode: Mode) { 16292f3ab15Sopenharmony_ci unsafe { 16392f3ab15Sopenharmony_ci assert!(in_.len() == out.len()); 16492f3ab15Sopenharmony_ci assert!(in_.len() % ffi::AES_BLOCK_SIZE as usize == 0); 16592f3ab15Sopenharmony_ci assert!(iv.len() >= ffi::AES_BLOCK_SIZE as usize * 2); 16692f3ab15Sopenharmony_ci 16792f3ab15Sopenharmony_ci let mode = match mode { 16892f3ab15Sopenharmony_ci Mode::Encrypt => ffi::AES_ENCRYPT, 16992f3ab15Sopenharmony_ci Mode::Decrypt => ffi::AES_DECRYPT, 17092f3ab15Sopenharmony_ci }; 17192f3ab15Sopenharmony_ci ffi::AES_ige_encrypt( 17292f3ab15Sopenharmony_ci in_.as_ptr() as *const _, 17392f3ab15Sopenharmony_ci out.as_mut_ptr() as *mut _, 17492f3ab15Sopenharmony_ci in_.len(), 17592f3ab15Sopenharmony_ci &key.0, 17692f3ab15Sopenharmony_ci iv.as_mut_ptr() as *mut _, 17792f3ab15Sopenharmony_ci mode, 17892f3ab15Sopenharmony_ci ); 17992f3ab15Sopenharmony_ci } 18092f3ab15Sopenharmony_ci} 18192f3ab15Sopenharmony_ci 18292f3ab15Sopenharmony_ci/// Wrap a key, according to [RFC 3394](https://tools.ietf.org/html/rfc3394) 18392f3ab15Sopenharmony_ci/// 18492f3ab15Sopenharmony_ci/// * `key`: The key-encrypting-key to use. Must be a encrypting key 18592f3ab15Sopenharmony_ci/// * `iv`: The IV to use. You must use the same IV for both wrapping and unwrapping 18692f3ab15Sopenharmony_ci/// * `out`: The output buffer to store the ciphertext 18792f3ab15Sopenharmony_ci/// * `in_`: The input buffer, storing the key to be wrapped 18892f3ab15Sopenharmony_ci/// 18992f3ab15Sopenharmony_ci/// Returns the number of bytes written into `out` 19092f3ab15Sopenharmony_ci/// 19192f3ab15Sopenharmony_ci/// # Panics 19292f3ab15Sopenharmony_ci/// 19392f3ab15Sopenharmony_ci/// Panics if either `out` or `in_` do not have sizes that are a multiple of 8, or if 19492f3ab15Sopenharmony_ci/// `out` is not 8 bytes longer than `in_` 19592f3ab15Sopenharmony_ci#[corresponds(AES_wrap_key)] 19692f3ab15Sopenharmony_cipub fn wrap_key( 19792f3ab15Sopenharmony_ci key: &AesKey, 19892f3ab15Sopenharmony_ci iv: Option<[u8; 8]>, 19992f3ab15Sopenharmony_ci out: &mut [u8], 20092f3ab15Sopenharmony_ci in_: &[u8], 20192f3ab15Sopenharmony_ci) -> Result<usize, KeyError> { 20292f3ab15Sopenharmony_ci unsafe { 20392f3ab15Sopenharmony_ci assert!(out.len() >= in_.len() + 8); // Ciphertext is 64 bits longer (see 2.2.1) 20492f3ab15Sopenharmony_ci 20592f3ab15Sopenharmony_ci let written = ffi::AES_wrap_key( 20692f3ab15Sopenharmony_ci &key.0 as *const _ as *mut _, // this is safe, the implementation only uses the key as a const pointer. 20792f3ab15Sopenharmony_ci iv.as_ref() 20892f3ab15Sopenharmony_ci .map_or(ptr::null(), |iv| iv.as_ptr() as *const _), 20992f3ab15Sopenharmony_ci out.as_ptr() as *mut _, 21092f3ab15Sopenharmony_ci in_.as_ptr() as *const _, 21192f3ab15Sopenharmony_ci in_.len() as AesSizeType, 21292f3ab15Sopenharmony_ci ); 21392f3ab15Sopenharmony_ci if written <= 0 { 21492f3ab15Sopenharmony_ci Err(KeyError(())) 21592f3ab15Sopenharmony_ci } else { 21692f3ab15Sopenharmony_ci Ok(written as usize) 21792f3ab15Sopenharmony_ci } 21892f3ab15Sopenharmony_ci } 21992f3ab15Sopenharmony_ci} 22092f3ab15Sopenharmony_ci 22192f3ab15Sopenharmony_ci/// Unwrap a key, according to [RFC 3394](https://tools.ietf.org/html/rfc3394) 22292f3ab15Sopenharmony_ci/// 22392f3ab15Sopenharmony_ci/// * `key`: The key-encrypting-key to decrypt the wrapped key. Must be a decrypting key 22492f3ab15Sopenharmony_ci/// * `iv`: The same IV used for wrapping the key 22592f3ab15Sopenharmony_ci/// * `out`: The buffer to write the unwrapped key to 22692f3ab15Sopenharmony_ci/// * `in_`: The input ciphertext 22792f3ab15Sopenharmony_ci/// 22892f3ab15Sopenharmony_ci/// Returns the number of bytes written into `out` 22992f3ab15Sopenharmony_ci/// 23092f3ab15Sopenharmony_ci/// # Panics 23192f3ab15Sopenharmony_ci/// 23292f3ab15Sopenharmony_ci/// Panics if either `out` or `in_` do not have sizes that are a multiple of 8, or 23392f3ab15Sopenharmony_ci/// if `in_` is not 8 bytes longer than `out` 23492f3ab15Sopenharmony_ci#[corresponds(AES_unwrap_key)] 23592f3ab15Sopenharmony_cipub fn unwrap_key( 23692f3ab15Sopenharmony_ci key: &AesKey, 23792f3ab15Sopenharmony_ci iv: Option<[u8; 8]>, 23892f3ab15Sopenharmony_ci out: &mut [u8], 23992f3ab15Sopenharmony_ci in_: &[u8], 24092f3ab15Sopenharmony_ci) -> Result<usize, KeyError> { 24192f3ab15Sopenharmony_ci unsafe { 24292f3ab15Sopenharmony_ci assert!(out.len() + 8 <= in_.len()); 24392f3ab15Sopenharmony_ci 24492f3ab15Sopenharmony_ci let written = ffi::AES_unwrap_key( 24592f3ab15Sopenharmony_ci &key.0 as *const _ as *mut _, // this is safe, the implementation only uses the key as a const pointer. 24692f3ab15Sopenharmony_ci iv.as_ref() 24792f3ab15Sopenharmony_ci .map_or(ptr::null(), |iv| iv.as_ptr() as *const _), 24892f3ab15Sopenharmony_ci out.as_ptr() as *mut _, 24992f3ab15Sopenharmony_ci in_.as_ptr() as *const _, 25092f3ab15Sopenharmony_ci in_.len() as AesSizeType, 25192f3ab15Sopenharmony_ci ); 25292f3ab15Sopenharmony_ci 25392f3ab15Sopenharmony_ci if written <= 0 { 25492f3ab15Sopenharmony_ci Err(KeyError(())) 25592f3ab15Sopenharmony_ci } else { 25692f3ab15Sopenharmony_ci Ok(written as usize) 25792f3ab15Sopenharmony_ci } 25892f3ab15Sopenharmony_ci } 25992f3ab15Sopenharmony_ci} 26092f3ab15Sopenharmony_ci 26192f3ab15Sopenharmony_ci#[cfg(test)] 26292f3ab15Sopenharmony_cimod test { 26392f3ab15Sopenharmony_ci use hex::FromHex; 26492f3ab15Sopenharmony_ci 26592f3ab15Sopenharmony_ci use super::*; 26692f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 26792f3ab15Sopenharmony_ci use crate::symm::Mode; 26892f3ab15Sopenharmony_ci 26992f3ab15Sopenharmony_ci // From https://www.mgp25.com/AESIGE/ 27092f3ab15Sopenharmony_ci #[test] 27192f3ab15Sopenharmony_ci #[cfg(not(boringssl))] 27292f3ab15Sopenharmony_ci #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] 27392f3ab15Sopenharmony_ci fn ige_vector_1() { 27492f3ab15Sopenharmony_ci let raw_key = "000102030405060708090A0B0C0D0E0F"; 27592f3ab15Sopenharmony_ci let raw_iv = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"; 27692f3ab15Sopenharmony_ci let raw_pt = "0000000000000000000000000000000000000000000000000000000000000000"; 27792f3ab15Sopenharmony_ci let raw_ct = "1A8519A6557BE652E9DA8E43DA4EF4453CF456B4CA488AA383C79C98B34797CB"; 27892f3ab15Sopenharmony_ci 27992f3ab15Sopenharmony_ci let key = AesKey::new_encrypt(&Vec::from_hex(raw_key).unwrap()).unwrap(); 28092f3ab15Sopenharmony_ci let mut iv = Vec::from_hex(raw_iv).unwrap(); 28192f3ab15Sopenharmony_ci let pt = Vec::from_hex(raw_pt).unwrap(); 28292f3ab15Sopenharmony_ci let ct = Vec::from_hex(raw_ct).unwrap(); 28392f3ab15Sopenharmony_ci 28492f3ab15Sopenharmony_ci let mut ct_actual = vec![0; ct.len()]; 28592f3ab15Sopenharmony_ci aes_ige(&pt, &mut ct_actual, &key, &mut iv, Mode::Encrypt); 28692f3ab15Sopenharmony_ci assert_eq!(ct_actual, ct); 28792f3ab15Sopenharmony_ci 28892f3ab15Sopenharmony_ci let key = AesKey::new_decrypt(&Vec::from_hex(raw_key).unwrap()).unwrap(); 28992f3ab15Sopenharmony_ci let mut iv = Vec::from_hex(raw_iv).unwrap(); 29092f3ab15Sopenharmony_ci let mut pt_actual = vec![0; pt.len()]; 29192f3ab15Sopenharmony_ci aes_ige(&ct, &mut pt_actual, &key, &mut iv, Mode::Decrypt); 29292f3ab15Sopenharmony_ci assert_eq!(pt_actual, pt); 29392f3ab15Sopenharmony_ci } 29492f3ab15Sopenharmony_ci 29592f3ab15Sopenharmony_ci // from the RFC https://tools.ietf.org/html/rfc3394#section-2.2.3 29692f3ab15Sopenharmony_ci #[test] 29792f3ab15Sopenharmony_ci fn test_wrap_unwrap() { 29892f3ab15Sopenharmony_ci let raw_key = Vec::from_hex("000102030405060708090A0B0C0D0E0F").unwrap(); 29992f3ab15Sopenharmony_ci let key_data = Vec::from_hex("00112233445566778899AABBCCDDEEFF").unwrap(); 30092f3ab15Sopenharmony_ci let expected_ciphertext = 30192f3ab15Sopenharmony_ci Vec::from_hex("1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5").unwrap(); 30292f3ab15Sopenharmony_ci 30392f3ab15Sopenharmony_ci let enc_key = AesKey::new_encrypt(&raw_key).unwrap(); 30492f3ab15Sopenharmony_ci let mut wrapped = [0; 24]; 30592f3ab15Sopenharmony_ci assert_eq!( 30692f3ab15Sopenharmony_ci wrap_key(&enc_key, None, &mut wrapped, &key_data).unwrap(), 30792f3ab15Sopenharmony_ci 24 30892f3ab15Sopenharmony_ci ); 30992f3ab15Sopenharmony_ci assert_eq!(&wrapped[..], &expected_ciphertext[..]); 31092f3ab15Sopenharmony_ci 31192f3ab15Sopenharmony_ci let dec_key = AesKey::new_decrypt(&raw_key).unwrap(); 31292f3ab15Sopenharmony_ci let mut unwrapped = [0; 16]; 31392f3ab15Sopenharmony_ci assert_eq!( 31492f3ab15Sopenharmony_ci unwrap_key(&dec_key, None, &mut unwrapped, &wrapped).unwrap(), 31592f3ab15Sopenharmony_ci 16 31692f3ab15Sopenharmony_ci ); 31792f3ab15Sopenharmony_ci assert_eq!(&unwrapped[..], &key_data[..]); 31892f3ab15Sopenharmony_ci } 31992f3ab15Sopenharmony_ci} 320