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