askar_crypto/alg/aes/
key_wrap.rs

1//! AES key wrap
2
3use core::marker::PhantomData;
4
5use aes_core::{
6    cipher::{BlockCipher, BlockDecrypt, BlockEncrypt, KeyInit, KeySizeUser},
7    Aes128, Aes256,
8};
9use subtle::ConstantTimeEq;
10
11use super::{AesKey, AesType, NonceSize, TagSize};
12use crate::{
13    alg::AesTypes,
14    buffer::ResizeBuffer,
15    encrypt::{KeyAeadInPlace, KeyAeadMeta, KeyAeadParams},
16    error::Error,
17    generic_array::{
18        typenum::{consts, Unsigned},
19        GenericArray,
20    },
21};
22
23const AES_KW_DEFAULT_IV: [u8; 8] = [166, 166, 166, 166, 166, 166, 166, 166];
24
25/// 128 bit AES Key Wrap
26pub type A128Kw = AesKeyWrap<Aes128>;
27
28impl AesType for A128Kw {
29    type KeySize = <Aes128 as KeySizeUser>::KeySize;
30    const ALG_TYPE: AesTypes = AesTypes::A128Kw;
31    const JWK_ALG: &'static str = "A128KW";
32}
33
34/// 256 bit AES Key Wrap
35pub type A256Kw = AesKeyWrap<Aes256>;
36
37impl AesType for A256Kw {
38    type KeySize = <Aes256 as KeySizeUser>::KeySize;
39    const ALG_TYPE: AesTypes = AesTypes::A256Kw;
40    const JWK_ALG: &'static str = "A256KW";
41}
42
43/// AES Key Wrap implementation
44#[derive(Debug)]
45pub struct AesKeyWrap<C>(PhantomData<C>);
46
47impl<C> KeyAeadMeta for AesKey<AesKeyWrap<C>>
48where
49    AesKeyWrap<C>: AesType,
50{
51    type NonceSize = consts::U0;
52    type TagSize = consts::U8;
53}
54
55impl<C> KeyAeadInPlace for AesKey<AesKeyWrap<C>>
56where
57    AesKeyWrap<C>: AesType,
58    C: KeyInit
59        + KeySizeUser<KeySize = <AesKeyWrap<C> as AesType>::KeySize>
60        + BlockCipher<BlockSize = consts::U16>
61        + BlockDecrypt
62        + BlockEncrypt,
63{
64    fn encrypt_in_place(
65        &self,
66        buffer: &mut dyn ResizeBuffer,
67        nonce: &[u8],
68        aad: &[u8],
69    ) -> Result<usize, Error> {
70        if !nonce.is_empty() {
71            return Err(err_msg!(Unsupported, "Custom nonce not supported"));
72        }
73        if !aad.is_empty() {
74            return Err(err_msg!(Unsupported, "AAD not supported"));
75        }
76        let mut buf_len = buffer.as_ref().len();
77        if buf_len % 8 != 0 {
78            return Err(err_msg!(
79                Unsupported,
80                "Data length must be a multiple of 8 bytes"
81            ));
82        }
83        let blocks = buf_len / 8;
84
85        buffer.buffer_insert(0, &[0u8; 8])?;
86        buf_len += 8;
87
88        let aes = C::new(self.0.as_ref());
89        let mut iv = AES_KW_DEFAULT_IV;
90        let mut block = GenericArray::default();
91        for j in 0..6 {
92            for (i, chunk) in buffer.as_mut()[8..].chunks_exact_mut(8).enumerate() {
93                block[0..8].copy_from_slice(iv.as_ref());
94                block[8..16].copy_from_slice(chunk);
95                aes.encrypt_block(&mut block);
96                let t = (((blocks * j) + i + 1) as u64).to_be_bytes();
97                iv.copy_from_slice(&block[0..8]);
98                for (a, t) in iv.as_mut().iter_mut().zip(&t[..]) {
99                    *a ^= t;
100                }
101                chunk.copy_from_slice(&block[8..16]);
102            }
103        }
104        buffer.as_mut()[0..8].copy_from_slice(&iv[..]);
105        Ok(buf_len)
106    }
107
108    fn decrypt_in_place(
109        &self,
110        buffer: &mut dyn ResizeBuffer,
111        nonce: &[u8],
112        aad: &[u8],
113    ) -> Result<(), Error> {
114        if !nonce.is_empty() {
115            return Err(err_msg!(Unsupported, "Custom nonce not supported"));
116        }
117        if !aad.is_empty() {
118            return Err(err_msg!(Unsupported, "AAD not supported"));
119        }
120        if buffer.as_ref().len() % 8 != 0 {
121            return Err(err_msg!(
122                Encryption,
123                "Data length must be a multiple of 8 bytes"
124            ));
125        }
126        let mut blocks = buffer.as_ref().len() / 8;
127        if blocks < 1 {
128            return Err(err_msg!(Encryption));
129        }
130        blocks -= 1;
131
132        let aes = C::new(self.0.as_ref());
133        let mut iv = *TryInto::<&[u8; 8]>::try_into(&buffer.as_ref()[0..8]).unwrap();
134        buffer.buffer_remove(0..8)?;
135
136        let mut block = GenericArray::default();
137        for j in (0..6).rev() {
138            for (i, chunk) in buffer.as_mut().chunks_exact_mut(8).enumerate().rev() {
139                block[0..8].copy_from_slice(iv.as_ref());
140                let t = (((blocks * j) + i + 1) as u64).to_be_bytes();
141                for (a, t) in block[0..8].iter_mut().zip(&t[..]) {
142                    *a ^= t;
143                }
144                block[8..16].copy_from_slice(chunk);
145                aes.decrypt_block(&mut block);
146                iv.copy_from_slice(&block[0..8]);
147                chunk.copy_from_slice(&block[8..16]);
148            }
149        }
150
151        if iv.ct_eq(&AES_KW_DEFAULT_IV).unwrap_u8() == 1 {
152            Ok(())
153        } else {
154            Err(err_msg!(Encryption))
155        }
156    }
157
158    fn aead_params(&self) -> KeyAeadParams {
159        KeyAeadParams {
160            nonce_length: NonceSize::<Self>::USIZE,
161            tag_length: TagSize::<Self>::USIZE,
162        }
163    }
164}
165
166#[cfg(test)]
167mod tests {
168    use super::*;
169    use crate::buffer::SecretBytes;
170    use crate::repr::KeySecretBytes;
171    use std::string::ToString;
172
173    #[test]
174    // from RFC 3394 test vectors
175    fn key_wrap_128_expected() {
176        let key =
177            AesKey::<A128Kw>::from_secret_bytes(&hex!("000102030405060708090a0b0c0d0e0f")).unwrap();
178        let input = &hex!("00112233445566778899aabbccddeeff");
179        let mut buffer = SecretBytes::from_slice(input);
180        key.encrypt_in_place(&mut buffer, &[], &[]).unwrap();
181        assert_eq!(
182            buffer.as_hex().to_string(),
183            "1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5"
184        );
185        key.decrypt_in_place(&mut buffer, &[], &[]).unwrap();
186        assert_eq!(buffer, &input[..]);
187    }
188
189    #[test]
190    // from RFC 3394 test vectors
191    fn key_wrap_256_expected() {
192        let key = AesKey::<A256Kw>::from_secret_bytes(&hex!(
193            "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"
194        ))
195        .unwrap();
196        let input = &hex!("00112233445566778899aabbccddeeff");
197        let mut buffer = SecretBytes::from_slice(input);
198        key.encrypt_in_place(&mut buffer, &[], &[]).unwrap();
199        assert_eq!(
200            buffer.as_hex().to_string(),
201            "64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7"
202        );
203        key.decrypt_in_place(&mut buffer, &[], &[]).unwrap();
204        assert_eq!(buffer, &input[..]);
205    }
206}