]> git.proxmox.com Git - cargo.git/blob - vendor/openssl-0.9.23/src/aes.rs
New upstream version 0.24.0
[cargo.git] / vendor / openssl-0.9.23 / src / aes.rs
1 //! Low level AES IGE functionality
2 //!
3 //! AES ECB, CBC, XTS, CTR, CFB, GCM and other conventional symmetric encryption
4 //! modes are found in [`symm`]. This is the implementation of AES IGE.
5 //!
6 //! Advanced Encryption Standard (AES) provides symmetric key cipher that
7 //! the same key is used to encrypt and decrypt data. This implementation
8 //! uses 128, 192, or 256 bit keys. This module provides functions to
9 //! create a new key with [`new_encrypt`] and perform an encryption/decryption
10 //! using that key with [`aes_ige`].
11 //!
12 //! [`new_encrypt`]: struct.AesKey.html#method.new_encrypt
13 //! [`aes_ige`]: fn.aes_ige.html
14 //!
15 //! The [`symm`] module should be used in preference to this module in most cases.
16 //! The IGE block cypher is a non-traditional cipher mode. More traditional AES
17 //! encryption methods are found in the [`Crypter`] and [`Cipher`] structs.
18 //!
19 //! [`symm`]: ../symm/index.html
20 //! [`Crypter`]: ../symm/struct.Crypter.html
21 //! [`Cipher`]: ../symm/struct.Cipher.html
22 //!
23 //! # Examples
24 //!
25 //! ```rust
26 //! # extern crate openssl;
27 //! extern crate hex;
28 //! use openssl::aes::{AesKey, KeyError, aes_ige};
29 //! use openssl::symm::Mode;
30 //! use hex::{FromHex, ToHex};
31 //!
32 //! fn decrypt() -> Result<(), KeyError> {
33 //! let raw_key = "000102030405060708090A0B0C0D0E0F";
34 //! let hex_cipher = "12345678901234561234567890123456";
35 //! let randomness = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F";
36 //! if let (Ok(key_as_u8), Ok(cipher_as_u8), Ok(mut iv_as_u8)) =
37 //! (Vec::from_hex(raw_key), Vec::from_hex(hex_cipher), Vec::from_hex(randomness)) {
38 //! let key = AesKey::new_encrypt(&key_as_u8)?;
39 //! let mut output = vec![0u8; cipher_as_u8.len()];
40 //! aes_ige(&cipher_as_u8, &mut output, &key, &mut iv_as_u8, Mode::Encrypt);
41 //! assert_eq!(output.to_hex(), "a6ad974d5cea1d36d2f367980907ed32");
42 //! }
43 //! Ok(())
44 //! }
45 //!
46 //! # fn main() {
47 //! # decrypt();
48 //! # }
49 use ffi;
50 use std::mem;
51 use libc::c_int;
52
53 use symm::Mode;
54
55 /// Provides Error handling for parsing keys.
56 #[derive(Debug)]
57 pub struct KeyError(());
58
59 /// The key used to encrypt or decrypt cipher blocks.
60 pub struct AesKey(ffi::AES_KEY);
61
62 impl AesKey {
63 /// Prepares a key for encryption.
64 ///
65 /// # Failure
66 ///
67 /// Returns an error if the key is not 128, 192, or 256 bits.
68 pub fn new_encrypt(key: &[u8]) -> Result<AesKey, KeyError> {
69 unsafe {
70 assert!(key.len() <= c_int::max_value() as usize / 8);
71
72 let mut aes_key = mem::uninitialized();
73 let r = ffi::AES_set_encrypt_key(
74 key.as_ptr() as *const _,
75 key.len() as c_int * 8,
76 &mut aes_key,
77 );
78 if r == 0 {
79 Ok(AesKey(aes_key))
80 } else {
81 Err(KeyError(()))
82 }
83 }
84 }
85
86 /// Prepares a key for decryption.
87 ///
88 /// # Failure
89 ///
90 /// Returns an error if the key is not 128, 192, or 256 bits.
91 pub fn new_decrypt(key: &[u8]) -> Result<AesKey, KeyError> {
92 unsafe {
93 assert!(key.len() <= c_int::max_value() as usize / 8);
94
95 let mut aes_key = mem::uninitialized();
96 let r = ffi::AES_set_decrypt_key(
97 key.as_ptr() as *const _,
98 key.len() as c_int * 8,
99 &mut aes_key,
100 );
101
102 if r == 0 {
103 Ok(AesKey(aes_key))
104 } else {
105 Err(KeyError(()))
106 }
107 }
108 }
109 }
110
111 /// Performs AES IGE encryption or decryption
112 ///
113 /// AES IGE (Infinite Garble Extension) is a form of AES block cipher utilized in
114 /// OpenSSL. Infinite Garble referes to propogating forward errors. IGE, like other
115 /// block ciphers implemented for AES requires an initalization vector. The IGE mode
116 /// allows a stream of blocks to be encrypted or decrypted without having the entire
117 /// plaintext available. For more information, visit [AES IGE Encryption].
118 ///
119 /// This block cipher uses 16 byte blocks. The rust implmentation will panic
120 /// if the input or output does not meet this 16-byte boundry. Attention must
121 /// be made in this low level implementation to pad the value to the 128-bit boundry.
122 ///
123 /// [AES IGE Encryption]: http://www.links.org/files/openssl-ige.pdf
124 ///
125 /// # Panics
126 ///
127 /// Panics if `in_` is not the same length as `out`, if that length is not a multiple of 16, or if
128 /// `iv` is not at least 32 bytes.
129 pub fn aes_ige(in_: &[u8], out: &mut [u8], key: &AesKey, iv: &mut [u8], mode: Mode) {
130 unsafe {
131 assert!(in_.len() == out.len());
132 assert!(in_.len() % ffi::AES_BLOCK_SIZE as usize == 0);
133 assert!(iv.len() >= ffi::AES_BLOCK_SIZE as usize * 2);
134
135 let mode = match mode {
136 Mode::Encrypt => ffi::AES_ENCRYPT,
137 Mode::Decrypt => ffi::AES_DECRYPT,
138 };
139 ffi::AES_ige_encrypt(
140 in_.as_ptr() as *const _,
141 out.as_mut_ptr() as *mut _,
142 in_.len(),
143 &key.0,
144 iv.as_mut_ptr() as *mut _,
145 mode,
146 );
147 }
148 }
149
150 #[cfg(test)]
151 mod test {
152 use hex::FromHex;
153
154 use symm::Mode;
155 use super::*;
156
157 // From https://www.mgp25.com/AESIGE/
158 #[test]
159 fn ige_vector_1() {
160 let raw_key = "000102030405060708090A0B0C0D0E0F";
161 let raw_iv = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F";
162 let raw_pt = "0000000000000000000000000000000000000000000000000000000000000000";
163 let raw_ct = "1A8519A6557BE652E9DA8E43DA4EF4453CF456B4CA488AA383C79C98B34797CB";
164
165 let key = AesKey::new_encrypt(&Vec::from_hex(raw_key).unwrap()).unwrap();
166 let mut iv = Vec::from_hex(raw_iv).unwrap();
167 let pt = Vec::from_hex(raw_pt).unwrap();
168 let ct = Vec::from_hex(raw_ct).unwrap();
169
170 let mut ct_actual = vec![0; ct.len()];
171 aes_ige(&pt, &mut ct_actual, &key, &mut iv, Mode::Encrypt);
172 assert_eq!(ct_actual, ct);
173
174 let key = AesKey::new_decrypt(&Vec::from_hex(raw_key).unwrap()).unwrap();
175 let mut iv = Vec::from_hex(raw_iv).unwrap();
176 let mut pt_actual = vec![0; pt.len()];
177 aes_ige(&ct, &mut pt_actual, &key, &mut iv, Mode::Decrypt);
178 assert_eq!(pt_actual, pt);
179 }
180 }