summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWiktor Kwapisiewicz <wiktor@metacode.biz>2023-08-10 15:27:21 +0200
committerWiktor Kwapisiewicz <wiktor@metacode.biz>2023-08-10 15:27:21 +0200
commit79f051a80260cfb61cc0b67a644cb1899b11ad15 (patch)
tree5e00043bfa4102c62fad314542b36cfa3c389d1e
parent3f310d91e26f2459560d9ad6aff01ebd1f452fda (diff)
WIP: Implement symmetric ciphers
-rw-r--r--openpgp/src/crypto/backend/kernel/symmetric.rs109
-rw-r--r--openpgp/src/crypto/backend/openssl/symmetric.rs3
-rw-r--r--openpgp/src/packet/skesk.rs4
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())?;