diff options
author | Wiktor Kwapisiewicz <wiktor@metacode.biz> | 2023-08-10 15:27:21 +0200 |
---|---|---|
committer | Wiktor Kwapisiewicz <wiktor@metacode.biz> | 2023-08-10 15:27:21 +0200 |
commit | 79f051a80260cfb61cc0b67a644cb1899b11ad15 (patch) | |
tree | 5e00043bfa4102c62fad314542b36cfa3c389d1e | |
parent | 3f310d91e26f2459560d9ad6aff01ebd1f452fda (diff) |
WIP: Implement symmetric ciphers
-rw-r--r-- | openpgp/src/crypto/backend/kernel/symmetric.rs | 109 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/openssl/symmetric.rs | 3 | ||||
-rw-r--r-- | openpgp/src/packet/skesk.rs | 4 |
3 files changed, 105 insertions, 11 deletions
diff --git a/openpgp/src/crypto/backend/kernel/symmetric.rs b/openpgp/src/crypto/backend/kernel/symmetric.rs index 9647a0f3..d3e7f3dc 100644 --- a/openpgp/src/crypto/backend/kernel/symmetric.rs +++ b/openpgp/src/crypto/backend/kernel/symmetric.rs @@ -4,25 +4,116 @@ use crate::types::SymmetricAlgorithm; use crate::{Error, Result}; use unimpl::unimpl; +use kcapi::{INIT_AIO, ACCESS_HEURISTIC}; +use kcapi::skcipher::KcapiSKCipher; +use std::sync::Mutex; + +fn symmetric_algo_to_skcipher(sk_algo: SymmetricAlgorithm) -> Result<&'static str> { + Ok(match sk_algo { + SymmetricAlgorithm::TripleDES => "des3", + SymmetricAlgorithm::AES128 | SymmetricAlgorithm::AES192 | SymmetricAlgorithm::AES256 => "aes", + _ => return Err(Error::UnsupportedSymmetricAlgorithm(sk_algo).into()), + }) +} + +struct KernelCipher { + cipher: Option<Mutex<KcapiSKCipher>>, + block_size: usize, + iv: Vec<u8>, + key: Vec<u8>, + mode: String, + sk_algo: SymmetricAlgorithm, +} + +impl KernelCipher { + fn new(mode: &str, sk_algo: SymmetricAlgorithm) -> Result<Self> { + Ok(Self { + cipher: None, + block_size: sk_algo.block_size()?, + sk_algo, + mode: mode.into(), + iv: vec![0; sk_algo.block_size()?], + key: vec![0; sk_algo.block_size()?], + }) + } + + fn set_key(&mut self, key: &[u8]) { + self.key = key.into(); + } + + fn set_iv(&mut self, iv: Vec<u8>) { + self.iv = iv; + } +} + +impl Mode for KernelCipher { + fn block_size(&self) -> usize { + self.block_size + } + + fn encrypt(&mut self, dst: &mut [u8], src: &[u8]) -> Result<()> { + if let Some(cipher) = &self.cipher { + let mut cipher = cipher.lock().expect("not to be poisoned"); + if src.len() < self.block_size { + cipher.stream_update_last(vec![src.into()])?; + } else { + cipher.stream_update(vec![src.into()])?; + } + dst.copy_from_slice(&cipher.stream_op()?[0]); + } else { + let mut cipher = KcapiSKCipher::new_enc_stream(&format!("{}({})", self.mode, symmetric_algo_to_skcipher(self.sk_algo)?), self.key.clone(), self.iv.clone(), vec![src.into()])?; + dst.copy_from_slice(&cipher.stream_op()?[0]); + self.cipher = Some(Mutex::new(cipher)); + } + Ok(()) + } + + fn decrypt(&mut self, dst: &mut [u8], src: &[u8]) -> Result<()> { + if let Some(cipher) = &self.cipher { + let mut cipher = cipher.lock().expect("not to be poisoned"); + if src.len() < self.block_size { + cipher.stream_update_last(vec![src.into()])?; + } else { + cipher.stream_update(vec![src.into()])?; + } + dst.copy_from_slice(&cipher.stream_op()?[0]); + } else { + let mut cipher = KcapiSKCipher::new_dec_stream(&format!("{}({})", self.mode, symmetric_algo_to_skcipher(self.sk_algo)?), self.key.clone(), self.iv.clone(), vec![src.into()])?; + dst.copy_from_slice(&cipher.stream_op()?[0]); + self.cipher = Some(Mutex::new(cipher)); + } + Ok(()) + } +} + impl SymmetricAlgorithm { /// Returns whether this algorithm is supported by the crypto backend. pub(crate) fn is_supported_by_backend(&self) -> bool { - false + KernelCipher::new("ecb", *self).is_ok() } /// Creates a OpenSSL context for encrypting in CFB mode. - #[unimpl] - pub(crate) fn make_encrypt_cfb(self, key: &[u8], iv: Vec<u8>) -> Result<Box<dyn Mode>>; + pub(crate) fn make_encrypt_cfb(self, key: &[u8], iv: Vec<u8>) -> Result<Box<dyn Mode>> { + let mut cipher = KernelCipher::new("cfb", self)?; + cipher.set_key(key); + cipher.set_iv(iv); + Ok(Box::new(cipher)) + } /// Creates a OpenSSL context for decrypting in CFB mode. - #[unimpl] - pub(crate) fn make_decrypt_cfb(self, key: &[u8], iv: Vec<u8>) -> Result<Box<dyn Mode>>; + pub(crate) fn make_decrypt_cfb(self, key: &[u8], iv: Vec<u8>) -> Result<Box<dyn Mode>> { + self.make_encrypt_cfb(key, iv) + } /// Creates a OpenSSL context for encrypting in ECB mode. - #[unimpl] - pub(crate) fn make_encrypt_ecb(self, key: &[u8]) -> Result<Box<dyn Mode>>; + pub(crate) fn make_encrypt_ecb(self, key: &[u8]) -> Result<Box<dyn Mode>> { + let mut cipher = KernelCipher::new("ecb", self)?; + cipher.set_key(key); + Ok(Box::new(cipher)) + } /// Creates a OpenSSL context for decrypting in ECB mode. - #[unimpl] - pub(crate) fn make_decrypt_ecb(self, key: &[u8]) -> Result<Box<dyn Mode>>; + pub(crate) fn make_decrypt_ecb(self, key: &[u8]) -> Result<Box<dyn Mode>> { + self.make_encrypt_ecb(key) + } } diff --git a/openpgp/src/crypto/backend/openssl/symmetric.rs b/openpgp/src/crypto/backend/openssl/symmetric.rs index 60522a32..479e470c 100644 --- a/openpgp/src/crypto/backend/openssl/symmetric.rs +++ b/openpgp/src/crypto/backend/openssl/symmetric.rs @@ -50,6 +50,7 @@ impl Mode for OpenSslMode { unsafe { self.ctx.cipher_update_unchecked(src, Some(dst))?; } + eprintln!("src = {src:?}, dst = {dst:?}"); Ok(()) } @@ -87,6 +88,8 @@ impl SymmetricAlgorithm { pub(crate) fn make_decrypt_cfb(self, key: &[u8], iv: Vec<u8>) -> Result<Box<dyn Mode>> { let cipher = self.make_cfb_cipher()?; let mut ctx = CipherCtx::new()?; + eprintln!("IV = ({}) {:?}", iv.len(), iv); + eprintln!("Key = ({}) {:?}", key.len(), key); ctx.decrypt_init(Some(cipher), Some(key), Some(&iv))?; Ok(Box::new(OpenSslMode::new(ctx))) } diff --git a/openpgp/src/packet/skesk.rs b/openpgp/src/packet/skesk.rs index 6dab9d8a..10672f05 100644 --- a/openpgp/src/packet/skesk.rs +++ b/openpgp/src/packet/skesk.rs @@ -687,7 +687,7 @@ mod test { let (cipher, sk) = skesks[0].decrypt(&"password".into())?; assert_eq!(cipher, SymmetricAlgorithm::AES256); let r = decrypt(cipher, &sk); - assert!(r); + assert!(r, "Decryption succeeded"); Ok(None) } } @@ -696,7 +696,7 @@ mod test { for variant in &["simple", "salted", "iterated.min", "iterated.max"] { for esk in &["", ".esk"] { let name = format!("s2k/{}{}.pgp", variant, esk); - eprintln!("{}", name); + eprintln!("Testing <{}>", name); let mut verifier = DecryptorBuilder::from_bytes( crate::tests::message(&name))? .with_policy(p, None, H())?; |