aboutsummaryrefslogtreecommitdiff
path: root/openssl/src/symm.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openssl/src/symm.rs')
-rw-r--r--openssl/src/symm.rs457
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());
}
}