diff options
Diffstat (limited to 'openpgp/src/crypto/backend/cng/symmetric.rs')
-rw-r--r-- | openpgp/src/crypto/backend/cng/symmetric.rs | 180 |
1 files changed, 0 insertions, 180 deletions
diff --git a/openpgp/src/crypto/backend/cng/symmetric.rs b/openpgp/src/crypto/backend/cng/symmetric.rs index a4a140eb..7d8281e7 100644 --- a/openpgp/src/crypto/backend/cng/symmetric.rs +++ b/openpgp/src/crypto/backend/cng/symmetric.rs @@ -68,74 +68,6 @@ impl Mode for cng::SymmetricAlgorithmKey { } } -/// CTR mode using a block cipher. CNG doesn't implement one so roll our own -/// using CNG's ECB mode. -pub struct Ctr { - key: cng::SymmetricAlgorithmKey, - ctr: Option<Box<[u8]>>, -} - -impl Ctr { - pub fn with_cipher_and_iv(algo: cng::SymmetricAlgorithmId, key: &[u8], iv: &[u8]) -> Result<Ctr> { - let algo = cng::SymmetricAlgorithm::open(algo, cng::ChainingMode::Ecb)?; - let key = algo.new_key(key)?; - // TODO: Check iv len - Ok(Ctr { key, ctr: Some(iv.into()) }) - } - - pub fn encrypt(&mut self, dst: &mut [u8], src: &[u8]) -> Result<()> { - let mut ctr = self.ctr.take().unwrap(); - Mode::encrypt(self, &mut ctr, dst, src)?; - self.ctr = Some(ctr); - Ok(()) - } - - pub fn decrypt(&mut self, dst: &mut [u8], src: &[u8]) -> Result<()> { - let mut ctr = self.ctr.take().unwrap(); - Mode::decrypt(self, &mut ctr, dst, src)?; - self.ctr = Some(ctr); - Ok(()) - } -} - -impl Mode for Ctr { - fn block_size(&self) -> usize { - self.key.block_size().expect("CNG not to fail internally") - } - - fn encrypt(&mut self, iv: &mut [u8], dst: &mut [u8], src: &[u8]) -> Result<()> { - let block = self.block_size(); - - // Ciphertext_i <- BlockCipher(Counter_i) ⊕ Plaintext_i - for (dst, src) in dst.chunks_mut(block).zip(src.chunks(block)) { - let res = cng::SymmetricAlgorithmKey::encrypt(&self.key, None, iv, None)?; - wrapping_increment_be(iv.as_mut()); - - for (dst, (res, src)) in dst.iter_mut().zip(res.as_slice().iter().zip(src.iter())) { - *dst = res ^ src; - } - } - - Ok(()) - } - - fn decrypt(&mut self, iv: &mut [u8], dst: &mut [u8], src: &[u8]) -> Result<()> { - let block = self.block_size(); - - // Plaintext_i <- BlockCipher(Counter_i) ⊕ Ciphertext_i - for (dst, src) in dst.chunks_mut(block).zip(src.chunks(block)) { - let res = cng::SymmetricAlgorithmKey::encrypt(&self.key, None, iv, None)?; - wrapping_increment_be(iv.as_mut()); - - for (dst, (res, src)) in dst.iter_mut().zip(res.as_slice().iter().zip(src.iter())) { - *dst = res ^ src; - } - } - - Ok(()) - } -} - #[derive(Debug, thiserror::Error)] #[error("Unsupported algorithm: {0}")] pub struct UnsupportedAlgorithm(SymmetricAlgorithm); @@ -253,115 +185,3 @@ impl SymmetricAlgorithm { )) } } - -fn wrapping_increment_be(value: &mut [u8]) -> &mut [u8] { - for val in value.iter_mut().rev() { - *val = val.wrapping_add(1); - // Stop carryover - if *val != 0x00 { - break; - } - } - - value -} - -#[cfg(test)] -mod tests { - use super::*; - use std::borrow::Borrow; - - trait HexSlice: Borrow<str> { - fn as_hex(&self) -> Vec<u8> { - let res: Vec<u8> = self.borrow().as_bytes().rchunks(2) - .map(|slice| std::str::from_utf8(slice).unwrap()) - .map(|chr| u8::from_str_radix(chr, 16).unwrap()) - .rev() - .collect(); - res - } - } - impl<'a> HexSlice for &'a str {} - - #[test] - fn hex_slice() { - assert_eq!("0a".as_hex(), &[0x0A]); - assert_eq!("a".as_hex(), &[0x0A]); - assert_eq!("FE0a".as_hex(), &[0xFE, 0x0A]); - assert_eq!("E0a".as_hex(), &[0x0E, 0x0A]); - } - - #[test] - fn wrapping_increment_be() { - assert_eq!(super::wrapping_increment_be(&mut [0x00]), [0x01]); - assert_eq!(super::wrapping_increment_be(&mut [0xFF, 0xFF]), [0x00, 0x00]); - assert_eq!(super::wrapping_increment_be(&mut [0xFD, 0xFF]), [0xFE, 0x00]); - - let input = &mut "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff".as_hex(); - let expected = &"f0f1f2f3f4f5f6f7f8f9fafbfcfdff00".as_hex(); - - assert_eq!(super::wrapping_increment_be(input).as_ref(), expected.as_slice()); - } - - #[test] - fn ctr_aes_128() { - // NIST SP800-38a test vectors - // F.5.1 CTR-AES128.Encrypt - let key = &"2b7e151628aed2a6abf7158809cf4f3c".as_hex(); - assert_eq!(key.len(), 16); - let mut ctr = Ctr::with_cipher_and_iv( - cng::SymmetricAlgorithmId::Aes, - key, - &"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff".as_hex(), - ).unwrap(); - - let plain = &"6bc1bee22e409f96e93d7e117393172a".as_hex(); - let mut cipher = vec![0u8; 16]; - ctr.encrypt(&mut cipher, plain).unwrap(); - assert_eq!(&cipher, &"874d6191b620e3261bef6864990db6ce".as_hex()); - - let plain = &"ae2d8a571e03ac9c9eb76fac45af8e51".as_hex(); - let mut cipher = vec![0u8; 16]; - ctr.encrypt(&mut cipher, plain).unwrap(); - assert_eq!(&cipher, &"9806f66b7970fdff8617187bb9fffdff".as_hex()); - - let plain = &"30c81c46a35ce411e5fbc1191a0a52ef".as_hex(); - let mut cipher = vec![0u8; 16]; - ctr.encrypt(&mut cipher, plain).unwrap(); - assert_eq!(&cipher, &"5ae4df3edbd5d35e5b4f09020db03eab".as_hex()); - - let plain = &"f69f2445df4f9b17ad2b417be66c3710".as_hex(); - let mut cipher = vec![0u8; 16]; - ctr.encrypt(&mut cipher, plain).unwrap(); - assert_eq!(&cipher, &"1e031dda2fbe03d1792170a0f3009cee".as_hex()); - - // F.5.2 CTR-AES128.Decrypt - let key = &"2b7e151628aed2a6abf7158809cf4f3c".as_hex(); - assert_eq!(key.len(), 16); - let mut ctr = Ctr::with_cipher_and_iv( - cng::SymmetricAlgorithmId::Aes, - key, - &"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff".as_hex(), - ).unwrap(); - - let plain = &"874d6191b620e3261bef6864990db6ce".as_hex(); - let mut cipher = vec![0u8; 16]; - ctr.decrypt(&mut cipher, plain).unwrap(); - assert_eq!(&cipher, &"6bc1bee22e409f96e93d7e117393172a".as_hex()); - - let plain = &"9806f66b7970fdff8617187bb9fffdff".as_hex(); - let mut cipher = vec![0u8; 16]; - ctr.decrypt(&mut cipher, plain).unwrap(); - assert_eq!(&cipher, &"ae2d8a571e03ac9c9eb76fac45af8e51".as_hex()); - - let plain = &"5ae4df3edbd5d35e5b4f09020db03eab".as_hex(); - let mut cipher = vec![0u8; 16]; - ctr.decrypt(&mut cipher, plain).unwrap(); - assert_eq!(&cipher, &"30c81c46a35ce411e5fbc1191a0a52ef".as_hex()); - - let plain = &"1e031dda2fbe03d1792170a0f3009cee".as_hex(); - let mut cipher = vec![0u8; 16]; - ctr.decrypt(&mut cipher, plain).unwrap(); - assert_eq!(&cipher, &"f69f2445df4f9b17ad2b417be66c3710".as_hex()); - } -} |