ct_aes/
lib.rs

1//! Constant time AES.
2//!
3//! # Warning
4//!
5//! This is low-level cryptography. It must only be used for
6//! implementing high-level constructions. It must only be used
7//! as a fallback for platforms without AES intrinsics. Do NOT
8//! use this code unless you know exactly what you are doing. If
9//! in doubt, use [`aes-gcm`] instead.
10//!
11//! [`aes-gcm`]: https://crates.io/crates/aes-gcm
12
13#![cfg_attr(docsrs, feature(doc_cfg))]
14#![cfg_attr(not(any(test, doctest, feature = "std")), no_std)]
15
16pub mod aes32;
17pub mod aes64;
18mod tests;
19
20/// The size in bytes of an AES block.
21pub const BLOCK_SIZE: usize = 16;
22
23/// An AES block.
24pub type Block = [u8; BLOCK_SIZE];
25
26cfg_if::cfg_if! {
27    if #[cfg(feature = "zeroize")] {
28        pub(crate) use zeroize::Zeroizing;
29    } else {
30        pub(crate) struct Zeroizing<T>(core::marker::PhantomData<T>);
31        impl<T> Zeroizing<T> {
32            #[inline(always)]
33            pub fn new(v: T) -> T {
34                v
35            }
36        }
37    }
38}
39
40pub(crate) const RCON: [u32; 10] = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36];
41
42// See https://doc.rust-lang.org/std/primitive.slice.html#method.as_chunks
43#[inline(always)]
44#[allow(clippy::arithmetic_side_effects)]
45pub(crate) const fn as_chunks_mut<T, const N: usize>(data: &mut [T]) -> (&mut [[T; N]], &mut [T]) {
46    const { assert!(N > 0) }
47
48    let len_rounded_down = (data.len() / N) * N;
49    // SAFETY: The rounded-down value is always the same or
50    // smaller than the original length, and thus must be
51    // in-bounds of the slice.
52    let (head, tail) = unsafe { data.split_at_mut_unchecked(len_rounded_down) };
53    let new_len = head.len() / N;
54    // SAFETY: We cast a slice of `new_len * N` elements into
55    // a slice of `new_len` many `N` elements chunks.
56    let head = unsafe { core::slice::from_raw_parts_mut(head.as_mut_ptr().cast(), new_len) };
57    (head, tail)
58}