1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![doc = include_str!("../README.md")]
4#![doc(
5 html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
6 html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
7)]
8
9#![cfg_attr(feature = "getrandom", doc = "```")]
14#![cfg_attr(not(feature = "getrandom"), doc = "```ignore")]
15#![cfg_attr(all(feature = "getrandom", feature = "arrayvec"), doc = "```")]
54#![cfg_attr(
55 not(all(feature = "getrandom", feature = "arrayvec")),
56 doc = "```ignore"
57)]
58#[cfg(feature = "alloc")]
87extern crate alloc;
88
89pub mod siv;
90
91pub use aead::{self, AeadCore, AeadInOut, Error, Key, KeyInit, KeySizeUser};
92
93use crate::siv::Siv;
94use aead::{
95 TagPosition,
96 array::Array,
97 consts::{U1, U16, U32, U64},
98 inout::InOutBuf,
99};
100use aes::{Aes128, Aes256};
101use cipher::{BlockCipherEncrypt, BlockSizeUser, array::ArraySize, typenum::IsGreaterOrEqual};
102use cmac::Cmac;
103use core::{fmt, marker::PhantomData, ops::Add};
104use digest::{FixedOutputReset, Mac};
105
106#[cfg(feature = "pmac")]
107use pmac::Pmac;
108
109pub type Nonce<NonceSize = U16> = Array<u8, NonceSize>;
111
112pub type Tag = Array<u8, U16>;
114
115pub struct SivAead<C, M, NonceSize = U16>
122where
123 Self: KeySizeUser,
124 C: BlockSizeUser<BlockSize = U16> + BlockCipherEncrypt + KeyInit + KeySizeUser,
125 M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
126 <C as KeySizeUser>::KeySize: Add,
127 NonceSize: ArraySize + IsGreaterOrEqual<U1>,
128{
129 key: Array<u8, <Self as KeySizeUser>::KeySize>,
130 mac: PhantomData<M>, }
132
133pub type CmacSivAead<BlockCipher> = SivAead<BlockCipher, Cmac<BlockCipher>>;
135
136#[cfg(feature = "pmac")]
138#[cfg_attr(docsrs, doc(cfg(feature = "pmac")))]
139pub type PmacSivAead<BlockCipher> = SivAead<BlockCipher, Pmac<BlockCipher>>;
140
141pub type Aes128SivAead = CmacSivAead<Aes128>;
143
144pub type Aes256SivAead = CmacSivAead<Aes256>;
146
147#[cfg(feature = "pmac")]
149#[cfg_attr(docsrs, doc(cfg(feature = "pmac")))]
150pub type Aes128PmacSivAead = PmacSivAead<Aes128>;
151
152#[cfg(feature = "pmac")]
154#[cfg_attr(docsrs, doc(cfg(feature = "pmac")))]
155pub type Aes256PmacSivAead = PmacSivAead<Aes256>;
156
157impl<M, NonceSize> KeySizeUser for SivAead<Aes128, M, NonceSize>
158where
159 M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
160 NonceSize: ArraySize + IsGreaterOrEqual<U1>,
161{
162 type KeySize = U32;
163}
164
165impl<M, NonceSize> KeySizeUser for SivAead<Aes256, M, NonceSize>
166where
167 M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
168 NonceSize: ArraySize + IsGreaterOrEqual<U1>,
169{
170 type KeySize = U64;
171}
172
173impl<M, NonceSize> KeyInit for SivAead<Aes128, M, NonceSize>
174where
175 M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
176 NonceSize: ArraySize + IsGreaterOrEqual<U1>,
177{
178 fn new(key: &Array<u8, Self::KeySize>) -> Self {
179 Self {
180 key: *key,
181 mac: PhantomData,
182 }
183 }
184}
185
186impl<M, NonceSize> KeyInit for SivAead<Aes256, M, NonceSize>
187where
188 M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
189 NonceSize: ArraySize + IsGreaterOrEqual<U1>,
190{
191 fn new(key: &Array<u8, Self::KeySize>) -> Self {
192 Self {
193 key: *key,
194 mac: PhantomData,
195 }
196 }
197}
198
199impl<C, M, NonceSize> AeadCore for SivAead<C, M, NonceSize>
200where
201 Self: KeySizeUser,
202 C: BlockSizeUser<BlockSize = U16> + BlockCipherEncrypt + KeyInit + KeySizeUser,
203 M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
204 <C as KeySizeUser>::KeySize: Add,
205 NonceSize: ArraySize + IsGreaterOrEqual<U1>,
206{
207 type NonceSize = NonceSize;
212 type TagSize = U16;
213 const TAG_POSITION: TagPosition = TagPosition::Prefix;
214}
215
216impl<C, M, NonceSize> AeadInOut for SivAead<C, M, NonceSize>
217where
218 Self: KeySizeUser,
219 Siv<C, M>: KeyInit + KeySizeUser<KeySize = <Self as KeySizeUser>::KeySize>,
220 C: BlockSizeUser<BlockSize = U16> + BlockCipherEncrypt + KeyInit + KeySizeUser,
221 M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
222 <C as KeySizeUser>::KeySize: Add,
223 NonceSize: ArraySize + IsGreaterOrEqual<U1>,
224{
225 fn encrypt_inout_detached(
226 &self,
227 nonce: &Array<u8, Self::NonceSize>,
228 associated_data: &[u8],
229 buffer: InOutBuf<'_, '_, u8>,
230 ) -> Result<Array<u8, Self::TagSize>, Error> {
231 Siv::<C, M>::new(&self.key)
232 .encrypt_inout_detached([associated_data, nonce.as_slice()], buffer)
233 }
234
235 fn decrypt_inout_detached(
236 &self,
237 nonce: &Array<u8, Self::NonceSize>,
238 associated_data: &[u8],
239 buffer: InOutBuf<'_, '_, u8>,
240 tag: &Array<u8, Self::TagSize>,
241 ) -> Result<(), Error> {
242 Siv::<C, M>::new(&self.key).decrypt_inout_detached(
243 [associated_data, nonce.as_slice()],
244 buffer,
245 tag,
246 )
247 }
248}
249
250impl<C, M, NonceSize> fmt::Debug for SivAead<C, M, NonceSize>
251where
252 Self: KeySizeUser,
253 C: BlockSizeUser<BlockSize = U16> + BlockCipherEncrypt + KeyInit + KeySizeUser,
254 M: Mac<OutputSize = U16> + FixedOutputReset + KeyInit,
255 <C as KeySizeUser>::KeySize: Add,
256 NonceSize: ArraySize + IsGreaterOrEqual<U1>,
257{
258 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
259 f.debug_struct("SivAead").finish_non_exhaustive()
260 }
261}