aes/
soft.rs

1//! AES block cipher constant-time implementation.
2//!
3//! The implementation uses a technique called [fixslicing][1], an improved
4//! form of bitslicing which represents ciphers in a way which enables
5//! very efficient constant-time implementations in software.
6//!
7//! [1]: https://eprint.iacr.org/2020/1123.pdf
8
9#![deny(unsafe_code)]
10
11#[cfg_attr(not(target_pointer_width = "64"), path = "soft/fixslice32.rs")]
12#[cfg_attr(target_pointer_width = "64", path = "soft/fixslice64.rs")]
13pub(crate) mod fixslice;
14
15#[cfg(feature = "ctr")]
16mod ctr;
17
18#[cfg(feature = "ctr")]
19pub use self::ctr::{Aes128Ctr, Aes192Ctr, Aes256Ctr};
20
21use crate::{Block, ParBlocks};
22use cipher::{
23    consts::{U16, U24, U32, U8},
24    generic_array::GenericArray,
25    BlockCipher, BlockDecrypt, BlockEncrypt, NewBlockCipher,
26};
27use fixslice::{FixsliceKeys128, FixsliceKeys192, FixsliceKeys256, FIXSLICE_BLOCKS};
28
29macro_rules! define_aes_impl {
30    (
31        $name:ident,
32        $key_size:ty,
33        $fixslice_keys:ty,
34        $fixslice_key_schedule:path,
35        $fixslice_decrypt:path,
36        $fixslice_encrypt:path,
37        $doc:expr
38    ) => {
39        #[doc=$doc]
40        #[derive(Clone)]
41        pub struct $name {
42            keys: $fixslice_keys,
43        }
44
45        impl NewBlockCipher for $name {
46            type KeySize = $key_size;
47
48            #[inline]
49            fn new(key: &GenericArray<u8, $key_size>) -> Self {
50                Self {
51                    keys: $fixslice_key_schedule(key),
52                }
53            }
54        }
55
56        impl BlockCipher for $name {
57            type BlockSize = U16;
58            type ParBlocks = U8;
59        }
60
61        impl BlockEncrypt for $name {
62            #[inline]
63            fn encrypt_block(&self, block: &mut Block) {
64                let mut blocks = [Block::default(); FIXSLICE_BLOCKS];
65                blocks[0].copy_from_slice(block);
66                $fixslice_encrypt(&self.keys, &mut blocks);
67                block.copy_from_slice(&blocks[0]);
68            }
69
70            #[inline]
71            fn encrypt_par_blocks(&self, blocks: &mut ParBlocks) {
72                for chunk in blocks.chunks_mut(FIXSLICE_BLOCKS) {
73                    $fixslice_encrypt(&self.keys, chunk);
74                }
75            }
76        }
77
78        impl BlockDecrypt for $name {
79            #[inline]
80            fn decrypt_block(&self, block: &mut Block) {
81                let mut blocks = [Block::default(); FIXSLICE_BLOCKS];
82                blocks[0].copy_from_slice(block);
83                $fixslice_decrypt(&self.keys, &mut blocks);
84                block.copy_from_slice(&blocks[0]);
85            }
86
87            #[inline]
88            fn decrypt_par_blocks(&self, blocks: &mut ParBlocks) {
89                for chunk in blocks.chunks_mut(FIXSLICE_BLOCKS) {
90                    $fixslice_decrypt(&self.keys, chunk);
91                }
92            }
93        }
94
95        opaque_debug::implement!($name);
96    };
97}
98
99define_aes_impl!(
100    Aes128,
101    U16,
102    FixsliceKeys128,
103    fixslice::aes128_key_schedule,
104    fixslice::aes128_decrypt,
105    fixslice::aes128_encrypt,
106    "AES-128 block cipher instance"
107);
108
109define_aes_impl!(
110    Aes192,
111    U24,
112    FixsliceKeys192,
113    fixslice::aes192_key_schedule,
114    fixslice::aes192_decrypt,
115    fixslice::aes192_encrypt,
116    "AES-192 block cipher instance"
117);
118
119define_aes_impl!(
120    Aes256,
121    U32,
122    FixsliceKeys256,
123    fixslice::aes256_key_schedule,
124    fixslice::aes256_decrypt,
125    fixslice::aes256_encrypt,
126    "AES-256 block cipher instance"
127);