1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//! AES-CTR stream cipher (wolfCrypt native API).
use super::*;
use crate::error::len_as_u32;
macro_rules! impl_aes_ctr {
($name:ident, $key_size:ty, $key_bytes:expr, $doc:expr) => {
#[doc = $doc]
pub struct $name {
aes: wolfcrypt_rs::WcAes,
}
// SAFETY: WcAes contains no thread-local state; safe to move to another thread.
unsafe impl Send for $name {}
impl Drop for $name {
fn drop(&mut self) {
// SAFETY: self.aes was initialised by wc_AesInit; we have &mut self.
unsafe {
wolfcrypt_rs::wc_AesFree(&mut self.aes as *mut wolfcrypt_rs::WcAes);
}
}
}
impl KeySizeUser for $name {
type KeySize = $key_size;
}
impl IvSizeUser for $name {
type IvSize = U16;
}
impl KeyIvInit for $name {
fn new(key: &GenericArray<u8, $key_size>, iv: &GenericArray<u8, U16>) -> Self {
let mut aes = wolfcrypt_rs::WcAes::zeroed();
// SAFETY: `aes` is freshly zeroed; null heap + INVALID_DEVID is standard.
let rc = unsafe {
wolfcrypt_rs::wc_AesInit(
&mut aes as *mut wolfcrypt_rs::WcAes,
core::ptr::null_mut(),
wolfcrypt_rs::INVALID_DEVID,
)
};
assert_eq!(rc, 0, "wc_AesInit failed (OOM or invalid device)");
// SAFETY: `aes` was initialised by wc_AesInit; key/iv are valid slices.
let rc = unsafe {
wolfcrypt_rs::wc_AesSetKey(
&mut aes as *mut wolfcrypt_rs::WcAes,
key.as_ptr(),
$key_bytes,
iv.as_ptr(),
wolfcrypt_rs::AES_ENCRYPT,
)
};
assert_eq!(rc, 0, "wc_AesSetKey failed (invalid key length or IV)");
Self { aes }
}
}
impl StreamCipher for $name {
fn try_apply_keystream_inout(
&mut self,
buf: cipher_trait::inout::InOutBuf<'_, '_, u8>,
) -> Result<(), StreamCipherError> {
let len = buf.len();
let (in_ptr, out_ptr) = buf.into_raw();
// SAFETY: `aes` is keyed; in_ptr/out_ptr from InOutBuf are valid.
let rc = unsafe {
wolfcrypt_rs::wc_AesCtrEncrypt(
&mut self.aes as *mut wolfcrypt_rs::WcAes,
out_ptr,
in_ptr,
len_as_u32(len),
)
};
if rc == 0 {
Ok(())
} else {
Err(StreamCipherError)
}
}
}
};
}
impl_aes_ctr!(
Aes128Ctr,
typenum::U16,
16u32,
"AES-128 in CTR mode, implementing `StreamCipher` and `KeyIvInit`."
);
#[cfg(wolfssl_aes_192)]
impl_aes_ctr!(
Aes192Ctr,
typenum::U24,
24u32,
"AES-192 in CTR mode, implementing `StreamCipher` and `KeyIvInit`."
);
impl_aes_ctr!(
Aes256Ctr,
typenum::U32,
32u32,
"AES-256 in CTR mode, implementing `StreamCipher` and `KeyIvInit`."
);