• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2023, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14  */
15 
16 //! Advanced Encryption Standard.
17 //!
18 //! AES is a 128-bit block cipher that supports key sizes of 128, 192, or 256
19 //! bits. (Although 192 isn't supported here.)
20 //!
21 //! Each key defines a permutation of the set of 128-bit blocks and AES can
22 //! perform the forward and reverse permutation. (These directions are
23 //! arbitrarily labeled "encryption" and "decryption".)
24 //!
25 //! AES requires relatively expensive preprocessing of keys and thus the
26 //! processed form of the key is represented here using [`EncryptKey`] and
27 //! [`DecryptKey`].
28 //!
29 //! ```
30 //! use bssl_crypto::aes;
31 //!
32 //! let key_bytes = bssl_crypto::rand_array();
33 //! let enc_key = aes::EncryptKey::new_256(&key_bytes);
34 //! let block = [0u8; aes::BLOCK_SIZE];
35 //! let mut transformed_block = enc_key.encrypt(&block);
36 //!
37 //! let dec_key = aes::DecryptKey::new_256(&key_bytes);
38 //! dec_key.decrypt_in_place(&mut transformed_block);
39 //! assert_eq!(block, transformed_block);
40 //! ```
41 //!
42 //! AES is a low-level primitive and must be used in a more complex construction
43 //! in nearly every case. See the `aead` crate for usable encryption and
44 //! decryption primitives.
45 
46 use crate::{initialized_struct_fallible, FfiMutSlice, FfiSlice};
47 use core::ffi::c_uint;
48 
49 /// AES block size in bytes.
50 pub const BLOCK_SIZE: usize = bssl_sys::AES_BLOCK_SIZE as usize;
51 
52 /// A single AES block.
53 pub type Block = [u8; BLOCK_SIZE];
54 
55 /// An initialized key which can be used for encrypting.
56 pub struct EncryptKey(bssl_sys::AES_KEY);
57 
58 impl EncryptKey {
59     /// Initializes an encryption key from an appropriately sized array of bytes
60     // for AES-128 operations.
new_128(key: &[u8; 16]) -> Self61     pub fn new_128(key: &[u8; 16]) -> Self {
62         new_encrypt_key(key.as_slice())
63     }
64 
65     /// Initializes an encryption key from an appropriately sized array of bytes
66     // for AES-256 operations.
new_256(key: &[u8; 32]) -> Self67     pub fn new_256(key: &[u8; 32]) -> Self {
68         new_encrypt_key(key.as_slice())
69     }
70 
71     /// Return the encrypted version of the given block.
encrypt(&self, block: &Block) -> Block72     pub fn encrypt(&self, block: &Block) -> Block {
73         let mut ret = *block;
74         self.encrypt_in_place(&mut ret);
75         ret
76     }
77 
78     /// Replace `block` with its encrypted version.
encrypt_in_place(&self, block: &mut Block)79     pub fn encrypt_in_place(&self, block: &mut Block) {
80         // Safety:
81         // - block is always a valid size and key is guaranteed to already be initialized.
82         unsafe { bssl_sys::AES_encrypt(block.as_ffi_ptr(), block.as_mut_ffi_ptr(), &self.0) }
83     }
84 }
85 
86 /// An initialized key which can be used for decrypting
87 pub struct DecryptKey(bssl_sys::AES_KEY);
88 
89 impl DecryptKey {
90     /// Initializes a decryption key from an appropriately sized array of bytes for AES-128 operations.
new_128(key: &[u8; 16]) -> DecryptKey91     pub fn new_128(key: &[u8; 16]) -> DecryptKey {
92         new_decrypt_key(key.as_slice())
93     }
94 
95     /// Initializes a decryption key from an appropriately sized array of bytes for AES-256 operations.
new_256(key: &[u8; 32]) -> DecryptKey96     pub fn new_256(key: &[u8; 32]) -> DecryptKey {
97         new_decrypt_key(key.as_slice())
98     }
99 
100     /// Return the decrypted version of the given block.
decrypt(&self, block: &Block) -> Block101     pub fn decrypt(&self, block: &Block) -> Block {
102         let mut ret = *block;
103         self.decrypt_in_place(&mut ret);
104         ret
105     }
106 
107     /// Replace `block` with its decrypted version.
decrypt_in_place(&self, block: &mut Block)108     pub fn decrypt_in_place(&self, block: &mut Block) {
109         // Safety:
110         // - block is always a valid size and key is guaranteed to already be initialized.
111         unsafe { bssl_sys::AES_decrypt(block.as_ffi_ptr(), block.as_mut_ffi_ptr(), &self.0) }
112     }
113 }
114 
115 /// This should only be publicly exposed by wrapper types with the correct key lengths
116 #[allow(clippy::unwrap_used)]
new_encrypt_key(key: &[u8]) -> EncryptKey117 fn new_encrypt_key(key: &[u8]) -> EncryptKey {
118     EncryptKey(
119         unsafe {
120             initialized_struct_fallible(|aes_key| {
121                 // The return value of this function differs from the usual BoringSSL
122                 // convention.
123                 bssl_sys::AES_set_encrypt_key(key.as_ffi_ptr(), key.len() as c_uint * 8, aes_key)
124                     == 0
125             })
126         }
127         // unwrap: this function only fails if `key` is the wrong length, which
128         // must be prevented by the pub functions that call this.
129         .unwrap(),
130     )
131 }
132 
133 /// This should only be publicly exposed by wrapper types with the correct key lengths.
134 #[allow(clippy::unwrap_used)]
new_decrypt_key(key: &[u8]) -> DecryptKey135 fn new_decrypt_key(key: &[u8]) -> DecryptKey {
136     DecryptKey(
137         unsafe {
138             initialized_struct_fallible(|aes_key| {
139                 // The return value of this function differs from the usual BoringSSL
140                 // convention.
141                 bssl_sys::AES_set_decrypt_key(key.as_ffi_ptr(), key.len() as c_uint * 8, aes_key)
142                     == 0
143             })
144         }
145         // unwrap: this function only fails if `key` is the wrong length, which
146         // must be prevented by the pub functions that call this.
147         .unwrap(),
148     )
149 }
150 
151 #[cfg(test)]
152 mod tests {
153     use crate::{
154         aes::{DecryptKey, EncryptKey},
155         test_helpers::decode_hex,
156     };
157 
158     #[test]
aes_128()159     fn aes_128() {
160         // test data from https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.1.1
161         let key = decode_hex("2b7e151628aed2a6abf7158809cf4f3c");
162         let plaintext = decode_hex("6bc1bee22e409f96e93d7e117393172a");
163         let ciphertext = decode_hex("3ad77bb40d7a3660a89ecaf32466ef97");
164         assert_eq!(ciphertext, EncryptKey::new_128(&key).encrypt(&plaintext));
165         assert_eq!(plaintext, DecryptKey::new_128(&key).decrypt(&ciphertext));
166     }
167 
168     #[test]
aes_256()169     fn aes_256() {
170         // test data from https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf F.1.5
171         let key = decode_hex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
172         let plaintext = decode_hex("6bc1bee22e409f96e93d7e117393172a");
173         let ciphertext = decode_hex("f3eed1bdb5d2a03c064b5a7e3db181f8");
174         assert_eq!(ciphertext, EncryptKey::new_256(&key).encrypt(&plaintext));
175         assert_eq!(plaintext, DecryptKey::new_256(&key).decrypt(&ciphertext));
176     }
177 }
178