diff options
Diffstat (limited to 'openssl/src/symm.rs')
| -rw-r--r-- | openssl/src/symm.rs | 457 |
1 files changed, 306 insertions, 151 deletions
diff --git a/openssl/src/symm.rs b/openssl/src/symm.rs index 5cf1ce0b..6aed21c5 100644 --- a/openssl/src/symm.rs +++ b/openssl/src/symm.rs @@ -164,11 +164,12 @@ impl Crypter { /// # Panics /// /// Panics if an IV is required by the cipher but not provided. - pub fn new(t: Cipher, - mode: Mode, - key: &[u8], - iv: Option<&[u8]>) - -> Result<Crypter, ErrorStack> { + pub fn new( + t: Cipher, + mode: Mode, + key: &[u8], + iv: Option<&[u8]>, + ) -> Result<Crypter, ErrorStack> { ffi::init(); unsafe { @@ -183,37 +184,46 @@ impl Crypter { Mode::Decrypt => 0, }; - try!(cvt(ffi::EVP_CipherInit_ex(crypter.ctx, - t.as_ptr(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - mode))); + try!(cvt(ffi::EVP_CipherInit_ex( + crypter.ctx, + t.as_ptr(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + mode, + ))); assert!(key.len() <= c_int::max_value() as usize); - try!(cvt(ffi::EVP_CIPHER_CTX_set_key_length(crypter.ctx, key.len() as c_int))); + try!(cvt(ffi::EVP_CIPHER_CTX_set_key_length( + crypter.ctx, + key.len() as c_int, + ))); let key = key.as_ptr() as *mut _; let iv = match (iv, t.iv_len()) { (Some(iv), Some(len)) => { if iv.len() != len { assert!(iv.len() <= c_int::max_value() as usize); - try!(cvt(ffi::EVP_CIPHER_CTX_ctrl(crypter.ctx, - ffi::EVP_CTRL_GCM_SET_IVLEN, - iv.len() as c_int, - ptr::null_mut()))); + try!(cvt(ffi::EVP_CIPHER_CTX_ctrl( + crypter.ctx, + ffi::EVP_CTRL_GCM_SET_IVLEN, + iv.len() as c_int, + ptr::null_mut(), + ))); } iv.as_ptr() as *mut _ } (Some(_), None) | (None, None) => ptr::null_mut(), (None, Some(_)) => panic!("an IV is required for this cipher"), }; - try!(cvt(ffi::EVP_CipherInit_ex(crypter.ctx, - ptr::null(), - ptr::null_mut(), - key, - iv, - mode))); + try!(cvt(ffi::EVP_CipherInit_ex( + crypter.ctx, + ptr::null(), + ptr::null_mut(), + key, + iv, + mode, + ))); Ok(crypter) } @@ -236,11 +246,12 @@ impl Crypter { unsafe { assert!(tag.len() <= c_int::max_value() as usize); // NB: this constant is actually more general than just GCM. - cvt(ffi::EVP_CIPHER_CTX_ctrl(self.ctx, - ffi::EVP_CTRL_GCM_SET_TAG, - tag.len() as c_int, - tag.as_ptr() as *mut _)) - .map(|_| ()) + cvt(ffi::EVP_CIPHER_CTX_ctrl( + self.ctx, + ffi::EVP_CTRL_GCM_SET_TAG, + tag.len() as c_int, + tag.as_ptr() as *mut _, + )).map(|_| ()) } } @@ -253,12 +264,13 @@ impl Crypter { unsafe { assert!(input.len() <= c_int::max_value() as usize); let mut len = 0; - cvt(ffi::EVP_CipherUpdate(self.ctx, - ptr::null_mut(), - &mut len, - input.as_ptr(), - input.len() as c_int)) - .map(|_| ()) + cvt(ffi::EVP_CipherUpdate( + self.ctx, + ptr::null_mut(), + &mut len, + input.as_ptr(), + input.len() as c_int, + )).map(|_| ()) } } @@ -280,11 +292,13 @@ impl Crypter { let mut outl = output.len() as c_int; let inl = input.len() as c_int; - try!(cvt(ffi::EVP_CipherUpdate(self.ctx, - output.as_mut_ptr(), - &mut outl, - input.as_ptr(), - inl))); + try!(cvt(ffi::EVP_CipherUpdate( + self.ctx, + output.as_mut_ptr(), + &mut outl, + input.as_ptr(), + inl, + ))); Ok(outl as usize) } @@ -305,7 +319,11 @@ impl Crypter { assert!(output.len() >= self.block_size); let mut outl = cmp::min(output.len(), c_int::max_value() as usize) as c_int; - try!(cvt(ffi::EVP_CipherFinal(self.ctx, output.as_mut_ptr(), &mut outl))); + try!(cvt(ffi::EVP_CipherFinal( + self.ctx, + output.as_mut_ptr(), + &mut outl, + ))); Ok(outl as usize) } @@ -322,11 +340,12 @@ impl Crypter { pub fn get_tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> { unsafe { assert!(tag.len() <= c_int::max_value() as usize); - cvt(ffi::EVP_CIPHER_CTX_ctrl(self.ctx, - ffi::EVP_CTRL_GCM_GET_TAG, - tag.len() as c_int, - tag.as_mut_ptr() as *mut _)) - .map(|_| ()) + cvt(ffi::EVP_CIPHER_CTX_ctrl( + self.ctx, + ffi::EVP_CTRL_GCM_GET_TAG, + tag.len() as c_int, + tag.as_mut_ptr() as *mut _, + )).map(|_| ()) } } } @@ -339,36 +358,39 @@ impl Drop for Crypter { } } -/** +#[doc = /** * Encrypts data, using the specified crypter type in encrypt mode with the * specified key and iv; returns the resulting (encrypted) data. - */ -pub fn encrypt(t: Cipher, - key: &[u8], - iv: Option<&[u8]>, - data: &[u8]) - -> Result<Vec<u8>, ErrorStack> { + */] +pub fn encrypt( + t: Cipher, + key: &[u8], + iv: Option<&[u8]>, + data: &[u8], +) -> Result<Vec<u8>, ErrorStack> { cipher(t, Mode::Encrypt, key, iv, data) } -/** +#[doc = /** * Decrypts data, using the specified crypter type in decrypt mode with the * specified key and iv; returns the resulting (decrypted) data. - */ -pub fn decrypt(t: Cipher, - key: &[u8], - iv: Option<&[u8]>, - data: &[u8]) - -> Result<Vec<u8>, ErrorStack> { + */] +pub fn decrypt( + t: Cipher, + key: &[u8], + iv: Option<&[u8]>, + data: &[u8], +) -> Result<Vec<u8>, ErrorStack> { cipher(t, Mode::Decrypt, key, iv, data) } -fn cipher(t: Cipher, - mode: Mode, - key: &[u8], - iv: Option<&[u8]>, - data: &[u8]) - -> Result<Vec<u8>, ErrorStack> { +fn cipher( + t: Cipher, + mode: Mode, + key: &[u8], + iv: Option<&[u8]>, + data: &[u8], +) -> Result<Vec<u8>, ErrorStack> { let mut c = try!(Crypter::new(t, mode, key, iv)); let mut out = vec![0; data.len() + t.block_size()]; let count = try!(c.update(data, &mut out)); @@ -385,13 +407,14 @@ fn cipher(t: Cipher, /// The size of the `tag` buffer indicates the required size of the tag. While some ciphers support /// a range of tag sizes, it is recommended to pick the maximum size. For AES GCM, this is 16 bytes, /// for example. -pub fn encrypt_aead(t: Cipher, - key: &[u8], - iv: Option<&[u8]>, - aad: &[u8], - data: &[u8], - tag: &mut [u8]) - -> Result<Vec<u8>, ErrorStack> { +pub fn encrypt_aead( + t: Cipher, + key: &[u8], + iv: Option<&[u8]>, + aad: &[u8], + data: &[u8], + tag: &mut [u8], +) -> Result<Vec<u8>, ErrorStack> { let mut c = try!(Crypter::new(t, Mode::Encrypt, key, iv)); let mut out = vec![0; data.len() + t.block_size()]; try!(c.aad_update(aad)); @@ -406,13 +429,14 @@ pub fn encrypt_aead(t: Cipher, /// /// Additional Authenticated Data can be provided in the `aad` field, and the authentication tag /// should be provided in the `tag` field. -pub fn decrypt_aead(t: Cipher, - key: &[u8], - iv: Option<&[u8]>, - aad: &[u8], - data: &[u8], - tag: &[u8]) - -> Result<Vec<u8>, ErrorStack> { +pub fn decrypt_aead( + t: Cipher, + key: &[u8], + iv: Option<&[u8]>, + aad: &[u8], + data: &[u8], + tag: &[u8], +) -> Result<Vec<u8>, ErrorStack> { let mut c = try!(Crypter::new(t, Mode::Decrypt, key, iv)); let mut out = vec![0; data.len() + t.block_size()]; try!(c.aad_update(aad)); @@ -456,19 +480,82 @@ mod tests { // http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf #[test] fn test_aes_256_ecb() { - let k0 = [0x00u8, 0x01u8, 0x02u8, 0x03u8, 0x04u8, 0x05u8, 0x06u8, 0x07u8, 0x08u8, 0x09u8, - 0x0au8, 0x0bu8, 0x0cu8, 0x0du8, 0x0eu8, 0x0fu8, 0x10u8, 0x11u8, 0x12u8, 0x13u8, - 0x14u8, 0x15u8, 0x16u8, 0x17u8, 0x18u8, 0x19u8, 0x1au8, 0x1bu8, 0x1cu8, 0x1du8, - 0x1eu8, 0x1fu8]; - let p0 = [0x00u8, 0x11u8, 0x22u8, 0x33u8, 0x44u8, 0x55u8, 0x66u8, 0x77u8, 0x88u8, 0x99u8, - 0xaau8, 0xbbu8, 0xccu8, 0xddu8, 0xeeu8, 0xffu8]; - let c0 = [0x8eu8, 0xa2u8, 0xb7u8, 0xcau8, 0x51u8, 0x67u8, 0x45u8, 0xbfu8, 0xeau8, 0xfcu8, - 0x49u8, 0x90u8, 0x4bu8, 0x49u8, 0x60u8, 0x89u8]; - let mut c = super::Crypter::new(super::Cipher::aes_256_ecb(), - super::Mode::Encrypt, - &k0, - None) - .unwrap(); + let k0 = [ + 0x00u8, + 0x01u8, + 0x02u8, + 0x03u8, + 0x04u8, + 0x05u8, + 0x06u8, + 0x07u8, + 0x08u8, + 0x09u8, + 0x0au8, + 0x0bu8, + 0x0cu8, + 0x0du8, + 0x0eu8, + 0x0fu8, + 0x10u8, + 0x11u8, + 0x12u8, + 0x13u8, + 0x14u8, + 0x15u8, + 0x16u8, + 0x17u8, + 0x18u8, + 0x19u8, + 0x1au8, + 0x1bu8, + 0x1cu8, + 0x1du8, + 0x1eu8, + 0x1fu8, + ]; + let p0 = [ + 0x00u8, + 0x11u8, + 0x22u8, + 0x33u8, + 0x44u8, + 0x55u8, + 0x66u8, + 0x77u8, + 0x88u8, + 0x99u8, + 0xaau8, + 0xbbu8, + 0xccu8, + 0xddu8, + 0xeeu8, + 0xffu8, + ]; + let c0 = [ + 0x8eu8, + 0xa2u8, + 0xb7u8, + 0xcau8, + 0x51u8, + 0x67u8, + 0x45u8, + 0xbfu8, + 0xeau8, + 0xfcu8, + 0x49u8, + 0x90u8, + 0x4bu8, + 0x49u8, + 0x60u8, + 0x89u8, + ]; + let mut c = super::Crypter::new( + super::Cipher::aes_256_ecb(), + super::Mode::Encrypt, + &k0, + None, + ).unwrap(); c.pad(false); let mut r0 = vec![0; c0.len() + super::Cipher::aes_256_ecb().block_size()]; let count = c.update(&p0, &mut r0).unwrap(); @@ -476,11 +563,12 @@ mod tests { r0.truncate(count + rest); assert_eq!(r0.to_hex(), c0.to_hex()); - let mut c = super::Crypter::new(super::Cipher::aes_256_ecb(), - super::Mode::Decrypt, - &k0, - None) - .unwrap(); + let mut c = super::Crypter::new( + super::Cipher::aes_256_ecb(), + super::Mode::Decrypt, + &k0, + None, + ).unwrap(); c.pad(false); let mut p1 = vec![0; r0.len() + super::Cipher::aes_256_ecb().block_size()]; let count = c.update(&r0, &mut p1).unwrap(); @@ -491,20 +579,82 @@ mod tests { #[test] fn test_aes_256_cbc_decrypt() { - let iv = [4_u8, 223_u8, 153_u8, 219_u8, 28_u8, 142_u8, 234_u8, 68_u8, 227_u8, 69_u8, - 98_u8, 107_u8, 208_u8, 14_u8, 236_u8, 60_u8]; - let data = [143_u8, 210_u8, 75_u8, 63_u8, 214_u8, 179_u8, 155_u8, 241_u8, 242_u8, 31_u8, - 154_u8, 56_u8, 198_u8, 145_u8, 192_u8, 64_u8, 2_u8, 245_u8, 167_u8, 220_u8, - 55_u8, 119_u8, 233_u8, 136_u8, 139_u8, 27_u8, 71_u8, 242_u8, 119_u8, 175_u8, - 65_u8, 207_u8]; - let ciphered_data = [0x4a_u8, 0x2e_u8, 0xe5_u8, 0x6_u8, 0xbf_u8, 0xcf_u8, 0xf2_u8, - 0xd7_u8, 0xea_u8, 0x2d_u8, 0xb1_u8, 0x85_u8, 0x6c_u8, 0x93_u8, - 0x65_u8, 0x6f_u8]; - let mut cr = super::Crypter::new(super::Cipher::aes_256_cbc(), - super::Mode::Decrypt, - &data, - Some(&iv)) - .unwrap(); + let iv = [ + 4_u8, + 223_u8, + 153_u8, + 219_u8, + 28_u8, + 142_u8, + 234_u8, + 68_u8, + 227_u8, + 69_u8, + 98_u8, + 107_u8, + 208_u8, + 14_u8, + 236_u8, + 60_u8, + ]; + let data = [ + 143_u8, + 210_u8, + 75_u8, + 63_u8, + 214_u8, + 179_u8, + 155_u8, + 241_u8, + 242_u8, + 31_u8, + 154_u8, + 56_u8, + 198_u8, + 145_u8, + 192_u8, + 64_u8, + 2_u8, + 245_u8, + 167_u8, + 220_u8, + 55_u8, + 119_u8, + 233_u8, + 136_u8, + 139_u8, + 27_u8, + 71_u8, + 242_u8, + 119_u8, + 175_u8, + 65_u8, + 207_u8, + ]; + let ciphered_data = [ + 0x4a_u8, + 0x2e_u8, + 0xe5_u8, + 0x6_u8, + 0xbf_u8, + 0xcf_u8, + 0xf2_u8, + 0xd7_u8, + 0xea_u8, + 0x2d_u8, + 0xb1_u8, + 0x85_u8, + 0x6c_u8, + 0x93_u8, + 0x65_u8, + 0x6f_u8, + ]; + let mut cr = super::Crypter::new( + super::Cipher::aes_256_cbc(), + super::Mode::Decrypt, + &data, + Some(&iv), + ).unwrap(); cr.pad(false); let mut unciphered_data = vec![0; data.len() + super::Cipher::aes_256_cbc().block_size()]; let count = cr.update(&ciphered_data, &mut unciphered_data).unwrap(); @@ -529,9 +679,11 @@ mod tests { println!("Computed: {}", computed.to_hex()); println!("Expected: {}", expected.to_hex()); if computed.len() != expected.len() { - println!("Lengths differ: {} in computed vs {} expected", - computed.len(), - expected.len()); + println!( + "Lengths differ: {} in computed vs {} expected", + computed.len(), + expected.len() + ); } panic!("test failure"); } @@ -558,9 +710,11 @@ mod tests { println!("Computed: {}", computed.to_hex()); println!("Expected: {}", expected.to_hex()); if computed.len() != expected.len() { - println!("Lengths differ: {} in computed vs {} expected", - computed.len(), - expected.len()); + println!( + "Lengths differ: {} in computed vs {} expected", + computed.len(), + expected.len() + ); } panic!("test failure"); } @@ -742,41 +896,40 @@ mod tests { #[test] fn test_aes128_gcm() { let key = "0e00c76561d2bd9b40c3c15427e2b08f"; - let iv = - "492cadaccd3ca3fbc9cf9f06eb3325c4e159850b0dbe98199b89b7af528806610b6f63998e1eae80c348e7\ + let iv = "492cadaccd3ca3fbc9cf9f06eb3325c4e159850b0dbe98199b89b7af528806610b6f63998e1eae80c348e7\ 4cbb921d8326631631fc6a5d304f39166daf7ea15fa1977f101819adb510b50fe9932e12c5a85aa3fd1e73\ d8d760af218be829903a77c63359d75edd91b4f6ed5465a72662f5055999e059e7654a8edc921aa0d496"; - let pt = - "fef03c2d7fb15bf0d2df18007d99f967c878ad59359034f7bb2c19af120685d78e32f6b8b83b032019956c\ + let pt = "fef03c2d7fb15bf0d2df18007d99f967c878ad59359034f7bb2c19af120685d78e32f6b8b83b032019956c\ a9c0195721476b85"; - let aad = - "d8f1163d8c840292a2b2dacf4ac7c36aff8733f18fabb4fa5594544125e03d1e6e5d6d0fd61656c8d8f327\ + let aad = "d8f1163d8c840292a2b2dacf4ac7c36aff8733f18fabb4fa5594544125e03d1e6e5d6d0fd61656c8d8f327\ c92839ae5539bb469c9257f109ebff85aad7bd220fdaa95c022dbd0c7bb2d878ad504122c943045d3c5eba\ 8f1f56c0"; - let ct = - "4f6cf471be7cbd2575cd5a1747aea8fe9dea83e51936beac3e68f66206922060c697ffa7af80ad6bb68f2c\ + let ct = "4f6cf471be7cbd2575cd5a1747aea8fe9dea83e51936beac3e68f66206922060c697ffa7af80ad6bb68f2c\ f4fc97416ee52abe"; let tag = "e20b6655"; // this tag is smaller than you'd normally want, but I pulled this test from the part of // the NIST test vectors that cover 4 byte tags. let mut actual_tag = [0; 4]; - let out = encrypt_aead(Cipher::aes_128_gcm(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(iv).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(pt).unwrap(), - &mut actual_tag) - .unwrap(); + let out = encrypt_aead( + Cipher::aes_128_gcm(), + &Vec::from_hex(key).unwrap(), + Some(&Vec::from_hex(iv).unwrap()), + &Vec::from_hex(aad).unwrap(), + &Vec::from_hex(pt).unwrap(), + &mut actual_tag, + ).unwrap(); assert_eq!(ct, out.to_hex()); assert_eq!(tag, actual_tag.to_hex()); - let out = decrypt_aead(Cipher::aes_128_gcm(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(iv).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(ct).unwrap(), - &Vec::from_hex(tag).unwrap()).unwrap(); + let out = decrypt_aead( + Cipher::aes_128_gcm(), + &Vec::from_hex(key).unwrap(), + Some(&Vec::from_hex(iv).unwrap()), + &Vec::from_hex(aad).unwrap(), + &Vec::from_hex(ct).unwrap(), + &Vec::from_hex(tag).unwrap(), + ).unwrap(); assert_eq!(pt, out.to_hex()); } @@ -808,23 +961,25 @@ mod tests { let tag = "1ae10b594f09e26a7e902ecbd0600691"; let mut actual_tag = [0; 16]; - let out = encrypt_aead(Cipher::chacha20_poly1305(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(iv).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(pt).unwrap(), - &mut actual_tag) - .unwrap(); + let out = encrypt_aead( + Cipher::chacha20_poly1305(), + &Vec::from_hex(key).unwrap(), + Some(&Vec::from_hex(iv).unwrap()), + &Vec::from_hex(aad).unwrap(), + &Vec::from_hex(pt).unwrap(), + &mut actual_tag, + ).unwrap(); assert_eq!(ct, out.to_hex()); assert_eq!(tag, actual_tag.to_hex()); - let out = decrypt_aead(Cipher::chacha20_poly1305(), - &Vec::from_hex(key).unwrap(), - Some(&Vec::from_hex(iv).unwrap()), - &Vec::from_hex(aad).unwrap(), - &Vec::from_hex(ct).unwrap(), - &Vec::from_hex(tag).unwrap()) - .unwrap(); + let out = decrypt_aead( + Cipher::chacha20_poly1305(), + &Vec::from_hex(key).unwrap(), + Some(&Vec::from_hex(iv).unwrap()), + &Vec::from_hex(aad).unwrap(), + &Vec::from_hex(ct).unwrap(), + &Vec::from_hex(tag).unwrap(), + ).unwrap(); assert_eq!(pt, out.to_hex()); } } |