aes/
lib.rs

1//! Pure Rust implementation of the [Advanced Encryption Standard][AES]
2//! (AES, a.k.a. Rijndael).
3//!
4//! # ⚠️ Security Warning: Hazmat!
5//!
6//! This crate implements only the low-level block cipher function, and is intended
7//! for use for implementing higher-level constructions *only*. It is NOT
8//! intended for direct use in applications.
9//!
10//! USE AT YOUR OWN RISK!
11//!
12//! # Supported backends
13//! This crate provides multiple backends including a portable pure Rust
14//! backend as well as ones based on CPU intrinsics.
15//!
16//! By default, it performs runtime detection of CPU intrinsics and uses them
17//! if they are available.
18//!
19//! ## "soft" portable backend
20//! As a baseline implementation, this crate provides a constant-time pure Rust
21//! implementation based on [fixslicing], a more advanced form of bitslicing
22//! implemented entirely in terms of bitwise arithmetic with no use of any
23//! lookup tables or data-dependent branches.
24//!
25//! Enabling the `aes_compact` configuration flag will reduce the code size of this
26//! backend at the cost of decreased performance (using a modified form of
27//! the fixslicing technique called "semi-fixslicing").
28//!
29//! ## ARMv8 intrinsics (Rust 1.61+)
30//! On `aarch64` targets including `aarch64-apple-darwin` (Apple M1) and Linux
31//! targets such as `aarch64-unknown-linux-gnu` and `aarch64-unknown-linux-musl`,
32//! support for using AES intrinsics provided by the ARMv8 Cryptography Extensions.
33//!
34//! On Linux and macOS, support for ARMv8 AES intrinsics is autodetected at
35//! runtime. On other platforms the `aes` target feature must be enabled via
36//! RUSTFLAGS.
37//!
38//! ## `x86`/`x86_64` intrinsics (AES-NI and VAES)
39//! By default this crate uses runtime detection on `i686`/`x86_64` targets
40//! in order to determine if AES-NI and VAES are available, and if they are
41//! not, it will fallback to using a constant-time software implementation.
42//!
43//! Passing `RUSTFLAGS=-Ctarget-feature=+aes,+ssse3` explicitly at
44//! compile-time will override runtime detection and ensure that AES-NI is
45//! used or passing `RUSTFLAGS=-Ctarget-feature=+aes,+avx512f,+ssse3,+vaes`
46//! will ensure that AESNI and VAES are always used.
47//!
48//! Note: Enabling VAES256 or VAES512 still requires specifying `--cfg
49//! aes_backend = "avx256"` or `--cfg aes_backend = "avx512"` explicitly.
50//!
51//! Programs built in this manner will crash with an illegal instruction on
52//! CPUs which do not have AES-NI and VAES enabled.
53//!
54//! Note: runtime detection is not possible on SGX targets. Please use the
55//! aforementioned `RUSTFLAGS` to leverage AES-NI and VAES on these targets.
56//!
57//! # Examples
58//! ```
59//! use aes::Aes128;
60//! use aes::cipher::{Array, BlockCipherEncrypt, BlockCipherDecrypt, KeyInit};
61//!
62//! let key = Array::from([0u8; 16]);
63//! let mut block = Array::from([42u8; 16]);
64//!
65//! // Initialize cipher
66//! let cipher = Aes128::new(&key);
67//!
68//! let block_copy = block;
69//!
70//! // Encrypt block in-place
71//! cipher.encrypt_block(&mut block);
72//!
73//! // And decrypt it back
74//! cipher.decrypt_block(&mut block);
75//! assert_eq!(block, block_copy);
76//!
77//! // Implementation supports parallel block processing. Number of blocks
78//! // processed in parallel depends in general on hardware capabilities.
79//! // This is achieved by instruction-level parallelism (ILP) on a single
80//! // CPU core, which is different from multi-threaded parallelism.
81//! let mut blocks = [block; 100];
82//! cipher.encrypt_blocks(&mut blocks);
83//!
84//! for block in blocks.iter_mut() {
85//!     cipher.decrypt_block(block);
86//!     assert_eq!(block, &block_copy);
87//! }
88//!
89//! // `decrypt_blocks` also supports parallel block processing.
90//! cipher.decrypt_blocks(&mut blocks);
91//!
92//! for block in blocks.iter_mut() {
93//!     cipher.encrypt_block(block);
94//!     assert_eq!(block, &block_copy);
95//! }
96//! ```
97//!
98//! For implementation of block cipher modes of operation see
99//! [`block-modes`] repository.
100//!
101//! # Configuration Flags
102//!
103//! You can modify crate using the following configuration flags:
104//!
105//! - `aes_backend`: explicitly select one of the following backends:
106//!   - `soft`: force software backend
107//!   - `avx256`: force AVX2 backend
108//!   - `avx512`: force AVX-512 backend
109//! - `aes_backend_soft`: modify software backend:
110//!   - `compact`: use compact implementation (less performant, but results in a smaller binary)
111//!
112//! It can be enabled using `RUSTFLAGS` environment variable
113//! (e.g. `RUSTFLAGS='--cfg aes_backend="soft"'`) or by modifying `.cargo/config`.
114//!
115//! [AES]: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
116//! [fixslicing]: https://eprint.iacr.org/2020/1123.pdf
117//! [AES-NI]: https://en.wikipedia.org/wiki/AES_instruction_set
118//! [`block-modes`]: https://github.com/RustCrypto/block-modes/
119
120#![no_std]
121#![doc(
122    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg",
123    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/26acc39f/logo.svg"
124)]
125#![cfg_attr(docsrs, feature(doc_cfg))]
126#![warn(missing_docs, rust_2018_idioms)]
127
128#[cfg(feature = "hazmat")]
129pub mod hazmat;
130
131#[macro_use]
132mod macros;
133mod soft;
134
135cpubits::cfg_if! {
136    if #[cfg(all(target_arch = "aarch64", not(aes_backend = "soft")))] {
137        mod armv8;
138        mod autodetect;
139        pub use autodetect::*;
140    } else if #[cfg(all(
141        any(target_arch = "x86", target_arch = "x86_64"),
142        not(aes_backend = "soft")
143    ))] {
144        mod x86;
145        mod autodetect;
146        pub use autodetect::*;
147    } else {
148        pub use soft::*;
149    }
150}
151
152pub use cipher;
153use cipher::{array::Array, consts::U16};
154
155/// 128-bit AES block
156pub type Block = Array<u8, U16>;