| 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 | |
| 14 | use crate::{soft::fixslice::hazmat as soft, Block, Block8}; |
| 15 | |
| 16 | #[cfg (all(target_arch = "aarch64" , aes_armv8, not(aes_force_soft)))] |
| 17 | use crate::armv8::hazmat as intrinsics; |
| 18 | |
| 19 | #[cfg (all(any(target_arch = "x86_64" , target_arch = "x86" ), not(aes_force_soft)))] |
| 20 | use 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 | ))] |
| 30 | cpufeatures::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? |
| 34 | macro_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. |
| 66 | pub 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. |
| 83 | pub 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. |
| 106 | pub 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. |
| 123 | pub 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. |
| 137 | pub 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. |
| 153 | pub 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 | } |
| 160 | |