aes/
lib.rs

1//! Pure Rust implementation of the Advanced Encryption Standard
2//! (a.k.a. Rijndael)
3//!
4//! # Supported backends
5//! This crate provides multiple backends including a portable pure Rust
6//! backend as well as ones based on CPU intrinsics.
7//!
8//! By default, it performs runtime detection of CPU intrinsics and uses them
9//! if they are available.
10//!
11//! ## "soft" portable backend
12//! As a baseline implementation, this crate provides a constant-time pure Rust
13//! implementation based on [fixslicing], a more advanced form of bitslicing
14//! implemented entirely in terms of bitwise arithmetic with no use of any
15//! lookup tables or data-dependent branches.
16//!
17//! Enabling the `compact` Cargo feature will reduce the code size of this
18//! backend at the cost of decreased performance (using a modified form of
19//! the fixslicing technique called "semi-fixslicing").
20//!
21//! ## ARMv8 intrinsics (nightly-only)
22//! On `aarch64` targets including `aarch64-apple-darwin` (Apple M1) and Linux
23//! targets such as `aarch64-unknown-linux-gnu` and `aarch64-unknown-linux-musl`,
24//! support for using AES intrinsics provided by the ARMv8 Cryptography Extensions
25//! is available when using the nightly compiler, and can be enabled using the
26//! `armv8` crate feature.
27//!
28//! On Linux and macOS, when the `armv8` feature is enabled support for AES
29//! intrinsics is autodetected at runtime. On other platforms the `aes`
30//! target feature must be enabled via RUSTFLAGS.
31//!
32//! ## `x86`/`x86_64` intrinsics (AES-NI)
33//! By default this crate uses runtime detection on `i686`/`x86_64` targets
34//! in order to determine if AES-NI is available, and if it is not, it will
35//! fallback to using a constant-time software implementation.
36//!
37//! Passing `RUSTFLAGS=-Ctarget-feature=+aes,+ssse3` explicitly at compile-time
38//! will override runtime detection and ensure that AES-NI is always used.
39//! Programs built in this manner will crash with an illegal instruction on
40//! CPUs which do not have AES-NI enabled.
41//!
42//! Note: runtime detection is not possible on SGX targets. Please use the
43//! afforementioned `RUSTFLAGS` to leverage AES-NI on these targets.
44//!
45//! # Usage example
46//! ```
47//! use aes::{Aes128, Block, ParBlocks};
48//! use aes::cipher::{
49//!     BlockCipher, BlockEncrypt, BlockDecrypt, NewBlockCipher,
50//!     generic_array::GenericArray,
51//! };
52//!
53//! let key = GenericArray::from_slice(&[0u8; 16]);
54//! let mut block = Block::default();
55//! let mut block8 = ParBlocks::default();
56//!
57//! // Initialize cipher
58//! let cipher = Aes128::new(&key);
59//!
60//! let block_copy = block.clone();
61//!
62//! // Encrypt block in-place
63//! cipher.encrypt_block(&mut block);
64//!
65//! // And decrypt it back
66//! cipher.decrypt_block(&mut block);
67//! assert_eq!(block, block_copy);
68//!
69//! // We can encrypt 8 blocks simultaneously using
70//! // instruction-level parallelism
71//! let block8_copy = block8.clone();
72//! cipher.encrypt_par_blocks(&mut block8);
73//! cipher.decrypt_par_blocks(&mut block8);
74//! assert_eq!(block8, block8_copy);
75//! ```
76//!
77//! For implementations of block cipher modes of operation see
78//! [`block-modes`] crate.
79//!
80//! [fixslicing]: https://eprint.iacr.org/2020/1123.pdf
81//! [AES-NI]: https://en.wikipedia.org/wiki/AES_instruction_set
82//! [`block-modes`]: https://docs.rs/block-modes
83
84#![no_std]
85#![cfg_attr(
86    all(feature = "armv8", target_arch = "aarch64"),
87    feature(stdsimd, aarch64_target_feature)
88)]
89#![cfg_attr(docsrs, feature(doc_cfg))]
90#![doc(
91    html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg",
92    html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg"
93)]
94#![warn(missing_docs, rust_2018_idioms)]
95
96#[cfg(feature = "hazmat")]
97pub mod hazmat;
98
99mod soft;
100
101use cfg_if::cfg_if;
102
103cfg_if! {
104    if #[cfg(all(target_arch = "aarch64", feature = "armv8", not(feature = "force-soft")))] {
105        mod armv8;
106        mod autodetect;
107        pub use autodetect::{Aes128, Aes192, Aes256};
108
109        #[cfg(feature = "ctr")]
110        pub use autodetect::ctr::{Aes128Ctr, Aes192Ctr, Aes256Ctr};
111    } else if #[cfg(all(
112        any(target_arch = "x86", target_arch = "x86_64"),
113        not(feature = "force-soft")
114    ))] {
115        mod autodetect;
116        mod ni;
117        pub use autodetect::{Aes128, Aes192, Aes256};
118
119        #[cfg(feature = "ctr")]
120        pub use autodetect::ctr::{Aes128Ctr, Aes192Ctr, Aes256Ctr};
121    } else {
122        pub use soft::{Aes128, Aes192, Aes256};
123
124        #[cfg(feature = "ctr")]
125        pub use soft::{Aes128Ctr, Aes192Ctr, Aes256Ctr};
126    }
127}
128
129pub use cipher::{self, BlockCipher, BlockDecrypt, BlockEncrypt, NewBlockCipher};
130
131/// 128-bit AES block
132pub type Block = cipher::generic_array::GenericArray<u8, cipher::consts::U16>;
133
134/// 8 x 128-bit AES blocks to be processed in parallel
135pub type ParBlocks = cipher::generic_array::GenericArray<Block, cipher::consts::U8>;
136
137/// Size of an AES block (128-bits; 16-bytes)
138pub const BLOCK_SIZE: usize = 16;