[go: up one dir, main page]

aes/
hazmat.rs

1//! ⚠️ Low-level "hazmat" AES functions.
2//!
3//! # ☢️️ WARNING: HAZARDOUS API ☢️
4//!
5//! This module contains an extremely low-level cryptographic primitive
6//! which is likewise extremely difficult to use correctly.
7//!
8//! There are very few valid uses cases for this API. It's intended to be used
9//! for implementing well-reviewed higher-level constructions.
10//!
11//! We do NOT recommend using it to implement any algorithm which has not
12//! received extensive peer review by cryptographers.
13
14use crate::{soft::fixslice::hazmat as soft, Block, Block8};
15
16#[cfg(all(target_arch = "aarch64", aes_armv8, not(aes_force_soft)))]
17use crate::armv8::hazmat as intrinsics;
18
19#[cfg(all(any(target_arch = "x86_64", target_arch = "x86"), not(aes_force_soft)))]
20use crate::ni::hazmat as intrinsics;
21
22#[cfg(all(
23    any(
24        target_arch = "x86",
25        target_arch = "x86_64",
26        all(target_arch = "aarch64", aes_armv8)
27    ),
28    not(aes_force_soft)
29))]
30cpufeatures::new!(aes_intrinsics, "aes");
31
32/// Execute the provided body if CPU intrinsics are available.
33// TODO(tarcieri): more `cfg-if`-like macro with an else branch?
34macro_rules! if_intrinsics_available {
35    ($body:expr) => {{
36        #[cfg(all(
37            any(
38                target_arch = "x86",
39                target_arch = "x86_64",
40                all(target_arch = "aarch64", aes_armv8)
41            ),
42            not(aes_force_soft)
43        ))]
44        if aes_intrinsics::get() {
45            unsafe { $body }
46            return;
47        }
48    }};
49}
50
51/// ⚠️ AES cipher (encrypt) round function.
52///
53/// This API performs the following steps as described in FIPS 197 Appendix C:
54///
55/// - `s_box`: state after `SubBytes()`
56/// - `s_row`: state after `ShiftRows()`
57/// - `m_col`: state after `MixColumns()`
58/// - `k_sch`: key schedule value for `round[r]`
59///
60/// This series of operations is equivalent to the Intel AES-NI `AESENC` instruction.
61///
62/// # ☢️️ WARNING: HAZARDOUS API ☢️
63///
64/// Use this function with great care! See the [module-level documentation][crate::hazmat]
65/// for more information.
66pub fn cipher_round(block: &mut Block, round_key: &Block) {
67    if_intrinsics_available! {
68        intrinsics::cipher_round(block, round_key)
69    }
70
71    soft::cipher_round(block, round_key);
72}
73
74/// ⚠️ AES cipher (encrypt) round function: parallel version.
75///
76/// Equivalent to [`cipher_round`], but acts on 8 blocks-at-a-time, applying
77/// the same number of round keys.
78///
79/// # ☢️️ WARNING: HAZARDOUS API ☢️
80///
81/// Use this function with great care! See the [module-level documentation][crate::hazmat]
82/// for more information.
83pub fn cipher_round_par(blocks: &mut Block8, round_keys: &Block8) {
84    if_intrinsics_available! {
85        intrinsics::cipher_round_par(blocks, round_keys)
86    }
87
88    soft::cipher_round_par(blocks, round_keys);
89}
90
91/// ⚠️ AES equivalent inverse cipher (decrypt) round function.
92///
93/// This API performs the following steps as described in FIPS 197 Appendix C:
94///
95/// - `is_box`: state after `InvSubBytes()`
96/// - `is_row`: state after `InvShiftRows()`
97/// - `im_col`: state after `InvMixColumns()`
98/// - `ik_sch`: key schedule value for `round[r]`
99///
100/// This series of operations is equivalent to the Intel AES-NI `AESDEC` instruction.
101///
102/// # ☢️️ WARNING: HAZARDOUS API ☢️
103///
104/// Use this function with great care! See the [module-level documentation][crate::hazmat]
105/// for more information.
106pub fn equiv_inv_cipher_round(block: &mut Block, round_key: &Block) {
107    if_intrinsics_available! {
108        intrinsics::equiv_inv_cipher_round(block, round_key)
109    }
110
111    soft::equiv_inv_cipher_round(block, round_key);
112}
113
114/// ⚠️ AES equivalent inverse cipher (decrypt) round function: parallel version.
115///
116/// Equivalent to [`equiv_inv_cipher_round`], but acts on 8 blocks-at-a-time,
117/// applying the same number of round keys.
118///
119/// # ☢️️ WARNING: HAZARDOUS API ☢️
120///
121/// Use this function with great care! See the [module-level documentation][crate::hazmat]
122/// for more information.
123pub fn equiv_inv_cipher_round_par(blocks: &mut Block8, round_keys: &Block8) {
124    if_intrinsics_available! {
125        intrinsics::equiv_inv_cipher_round_par(blocks, round_keys)
126    }
127
128    soft::equiv_inv_cipher_round_par(blocks, round_keys);
129}
130
131/// ⚠️ AES mix columns function.
132///
133/// # ☢️️ WARNING: HAZARDOUS API ☢️
134///
135/// Use this function with great care! See the [module-level documentation][crate::hazmat]
136/// for more information.
137pub fn mix_columns(block: &mut Block) {
138    if_intrinsics_available! {
139        intrinsics::mix_columns(block)
140    }
141
142    soft::mix_columns(block);
143}
144
145/// ⚠️ AES inverse mix columns function.
146///
147/// This function is equivalent to the Intel AES-NI `AESIMC` instruction.
148///
149/// # ☢️️ WARNING: HAZARDOUS API ☢️
150///
151/// Use this function with great care! See the [module-level documentation][crate::hazmat]
152/// for more information.
153pub fn inv_mix_columns(block: &mut Block) {
154    if_intrinsics_available! {
155        intrinsics::inv_mix_columns(block)
156    }
157
158    soft::inv_mix_columns(block);
159}