1 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 2 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 3 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 4 // option. This file may not be copied, modified, or distributed 5 // except according to those terms. 6 7 use aes::{ctr, KeySize}; 8 use aead::{AeadEncryptor,AeadDecryptor}; 9 use cryptoutil::copy_memory; 10 use symmetriccipher::SynchronousStreamCipher; 11 use ghash::{Ghash}; 12 use util::fixed_time_eq; 13 14 pub struct AesGcm<'a> { 15 cipher: Box<SynchronousStreamCipher + 'a>, 16 mac: Ghash, 17 finished: bool, 18 end_tag: [u8; 16] 19 } 20 21 impl<'a> AesGcm<'a> { new(key_size: KeySize, key: &[u8], nonce: &[u8], aad: &[u8]) -> AesGcm<'a>22 pub fn new (key_size: KeySize, key: &[u8], nonce: &[u8], aad: &[u8]) -> AesGcm<'a> { 23 assert!(key.len() == 16 || key.len() == 24 || key.len() == 32); 24 assert!(nonce.len() == 12); 25 26 // GCM technically differs from CTR mode in how role overs are handled 27 // GCM only touches the right most 4 bytes while CTR roles all 16 over 28 // when the iv is only 96 bits (12 bytes) then 4 bytes of zeros are 29 // appended to it meaning you have to encrypt 2^37 bytes (256 gigabytes) 30 // of data before a difference crops up. 31 // The GCM handles nonces of other lengths by hashing them once with ghash 32 // this would cause the roleover behavior to potentially be triggered much 33 // earlier preventing the use of generic CTR mode. 34 35 let mut iv = [0u8; 16]; 36 copy_memory(nonce, &mut iv); 37 iv[15] = 1u8; 38 let mut cipher = ctr(key_size,key,&iv); 39 let temp_block = [0u8; 16]; 40 let mut final_block = [0u8; 16]; 41 cipher.process(&temp_block, &mut final_block); 42 let mut hash_key = [0u8; 16]; 43 let mut encryptor = ctr(key_size,key,&temp_block); 44 encryptor.process(&temp_block, &mut hash_key); 45 AesGcm { 46 cipher: cipher, 47 mac: Ghash::new(&hash_key).input_a(aad), 48 finished: false, 49 end_tag: final_block 50 } 51 } 52 53 } 54 55 impl<'a> AeadEncryptor for AesGcm<'static> { encrypt(&mut self, input: &[u8], output: &mut [u8], tag: &mut [u8])56 fn encrypt(&mut self, input: &[u8], output: &mut [u8], tag: &mut [u8]) { 57 assert!(input.len() == output.len()); 58 assert!(!self.finished); 59 self.cipher.process(input, output); 60 let result = self.mac.input_c(output).result(); 61 self.finished = true; 62 for i in 0..16 { 63 tag[i] = result[i] ^ self.end_tag[i]; 64 } 65 } 66 } 67 68 impl<'a> AeadDecryptor for AesGcm<'static> { decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> bool69 fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> bool { 70 assert!(input.len() == output.len()); 71 assert!(!self.finished); 72 self.finished = true; 73 let mut calc_tag = self.mac.input_c(input).result(); 74 for i in 0..16 { 75 calc_tag[i] ^= self.end_tag[i]; 76 } 77 if fixed_time_eq(&calc_tag, tag) { 78 self.cipher.process(input, output); 79 true 80 } else { 81 false 82 } 83 } 84 } 85 86 #[cfg(test)] 87 mod test { 88 use aes::KeySize; 89 use aes_gcm::AesGcm; 90 use aead::{AeadEncryptor, AeadDecryptor}; 91 use serialize::hex::FromHex; 92 use std::iter::repeat; hex_to_bytes(raw_hex: &str) -> Vec<u8>93 fn hex_to_bytes(raw_hex: &str) -> Vec<u8> { 94 raw_hex.from_hex().ok().unwrap() 95 } 96 struct TestVector { 97 key: Vec<u8>, 98 iv: Vec<u8>, 99 plain_text: Vec<u8>, 100 cipher_text: Vec<u8>, 101 aad: Vec<u8>, 102 tag: Vec<u8>, 103 } 104 get_test_vectors()-> [TestVector; 5]105 fn get_test_vectors()-> [TestVector; 5]{ 106 [ 107 TestVector { 108 key: hex_to_bytes("00000000000000000000000000000000"), 109 iv: hex_to_bytes("000000000000000000000000"), 110 plain_text: hex_to_bytes(""), 111 cipher_text: hex_to_bytes(""), 112 aad: hex_to_bytes(""), 113 tag: hex_to_bytes("58e2fccefa7e3061367f1d57a4e7455a") 114 }, 115 TestVector { 116 key: hex_to_bytes("00000000000000000000000000000000"), 117 iv: hex_to_bytes("000000000000000000000000"), 118 plain_text: hex_to_bytes("00000000000000000000000000000000"), 119 cipher_text: hex_to_bytes("0388dace60b6a392f328c2b971b2fe78"), 120 aad: hex_to_bytes(""), 121 tag: hex_to_bytes("ab6e47d42cec13bdf53a67b21257bddf") 122 }, 123 TestVector { 124 key: hex_to_bytes("feffe9928665731c6d6a8f9467308308"), 125 iv: hex_to_bytes("cafebabefacedbaddecaf888"), 126 plain_text: hex_to_bytes("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"), 127 cipher_text: hex_to_bytes("42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091"), 128 aad: hex_to_bytes("feedfacedeadbeeffeedfacedeadbeefabaddad2"), 129 tag: hex_to_bytes("5bc94fbc3221a5db94fae95ae7121a47") 130 }, 131 TestVector { 132 key: hex_to_bytes("feffe9928665731c6d6a8f9467308308feffe9928665731c"), 133 iv: hex_to_bytes("cafebabefacedbaddecaf888"), 134 plain_text: hex_to_bytes("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"), 135 cipher_text: hex_to_bytes("3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710"), 136 aad: hex_to_bytes("feedfacedeadbeeffeedfacedeadbeefabaddad2"), 137 tag: hex_to_bytes("2519498e80f1478f37ba55bd6d27618c") 138 }, 139 TestVector { 140 key: hex_to_bytes("feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308"), 141 iv: hex_to_bytes("cafebabefacedbaddecaf888"), 142 plain_text: hex_to_bytes("d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"), 143 cipher_text: hex_to_bytes("522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662"), 144 aad: hex_to_bytes("feedfacedeadbeeffeedfacedeadbeefabaddad2"), 145 tag: hex_to_bytes("76fc6ece0f4e1768cddf8853bb2d551b") 146 }, 147 ] 148 } 149 #[test] aes_gcm_test()150 fn aes_gcm_test() { 151 152 for item in get_test_vectors().iter() { 153 let key_size = match item.key.len() { 154 16 => KeySize::KeySize128, 155 24 => KeySize::KeySize192, 156 32 => KeySize::KeySize256, 157 _ => unreachable!() 158 }; 159 let mut cipher = AesGcm::new(key_size, &item.key[..], &item.iv[..], &item.aad[..]); 160 let mut out: Vec<u8> = repeat(0).take(item.plain_text.len()).collect(); 161 162 let mut out_tag: Vec<u8> = repeat(0).take(16).collect(); 163 164 cipher.encrypt(&item.plain_text[..], &mut out[..],&mut out_tag[..]); 165 assert_eq!(out, item.cipher_text); 166 assert_eq!(out_tag, item.tag); 167 } 168 } 169 170 #[test] aes_gcm_decrypt_test()171 fn aes_gcm_decrypt_test() { 172 173 for item in get_test_vectors().iter() { 174 let key_size = match item.key.len() { 175 16 => KeySize::KeySize128, 176 24 => KeySize::KeySize192, 177 32 => KeySize::KeySize256, 178 _ => unreachable!() 179 }; 180 let mut decipher = AesGcm::new(key_size, &item.key[..], &item.iv[..], &item.aad[..]); 181 let mut out: Vec<u8> = repeat(0).take(item.plain_text.len()).collect(); 182 183 let result = decipher.decrypt(&item.cipher_text[..], &mut out[..], &item.tag[..]); 184 assert_eq!(out, item.plain_text); 185 assert!(result); 186 } 187 } 188 #[test] aes_gcm_decrypt_fail_test()189 fn aes_gcm_decrypt_fail_test() { 190 191 for item in get_test_vectors().iter() { 192 let key_size = match item.key.len() { 193 16 => KeySize::KeySize128, 194 24 => KeySize::KeySize192, 195 32 => KeySize::KeySize256, 196 _ => unreachable!() 197 }; 198 let mut decipher = AesGcm::new(key_size, &item.key[..], &item.iv[..], &item.aad[..]); 199 let tag: Vec<u8> = repeat(0).take(16).collect(); 200 let mut out1: Vec<u8> = repeat(0).take(item.plain_text.len()).collect(); 201 let out2: Vec<u8> = repeat(0).take(item.plain_text.len()).collect(); 202 let result = decipher.decrypt(&item.cipher_text[..], &mut out1[..], &tag[..]); 203 assert_eq!(out1, out2); 204 assert!(!result); 205 } 206 } 207 208 } 209 210 #[cfg(all(test, feature = "with-bench"))] 211 mod bench { 212 use test::Bencher; 213 use aes::KeySize; 214 use aes_gcm::AesGcm; 215 use aead::{AeadEncryptor, AeadDecryptor}; 216 217 #[bench] gsm_10(bh: & mut Bencher)218 pub fn gsm_10(bh: & mut Bencher) { 219 let input = [1u8; 10]; 220 let aad = [3u8; 10]; 221 bh.iter( || { 222 let mut cipher = AesGcm::new(KeySize::KeySize256, &[0; 32], &[0; 12], &aad); 223 let mut decipher = AesGcm::new(KeySize::KeySize256, &[0; 32], &[0; 12], &aad); 224 225 let mut output = [0u8; 10]; 226 let mut tag = [0u8; 16]; 227 let mut output2 = [0u8; 10]; 228 cipher.encrypt(&input, &mut output, &mut tag); 229 decipher.decrypt(&output, &mut output2, &tag); 230 231 }); 232 bh.bytes = 10u64; 233 } 234 235 236 #[bench] gsm_1k(bh: & mut Bencher)237 pub fn gsm_1k(bh: & mut Bencher) { 238 let input = [1u8; 1024]; 239 let aad = [3u8; 1024]; 240 bh.iter( || { 241 let mut cipher = AesGcm::new(KeySize::KeySize256, &[0; 32], &[0; 12], &aad); 242 let mut decipher = AesGcm::new(KeySize::KeySize256, &[0; 32], &[0; 12], &aad); 243 244 let mut output = [0u8; 1024]; 245 let mut tag = [0u8; 16]; 246 let mut output2 = [0u8; 1024]; 247 248 cipher.encrypt(&input, &mut output, &mut tag); 249 decipher.decrypt(&output, &mut output2, &tag); 250 }); 251 bh.bytes = 1024u64; 252 253 } 254 255 #[bench] gsm_64k(bh: & mut Bencher)256 pub fn gsm_64k(bh: & mut Bencher) { 257 let input = [1u8; 65536]; 258 let aad = [3u8; 65536]; 259 bh.iter( || { 260 let mut cipher = AesGcm::new(KeySize::KeySize256, &[0; 32], &[0; 12], &aad); 261 let mut decipher = AesGcm::new(KeySize::KeySize256, &[0; 32], &[0; 12], &aad); 262 263 let mut output = [0u8; 65536]; 264 let mut tag = [0u8; 16]; 265 let mut output2 = [0u8; 65536]; 266 267 cipher.encrypt(&input, &mut output, &mut tag); 268 decipher.decrypt(&output, &mut output2, &tag); 269 270 }); 271 bh.bytes = 65536u64; 272 273 } 274 } 275