Browse Source

Converted the EncryptionAlgo and DecryptionAlgo structs into traits.

Matthew Carr 2 years ago
parent
commit
d1f5c4a488
3 changed files with 89 additions and 126 deletions
  1. 14 0
      crates/btnode/notes.txt
  2. 17 0
      crates/btnode/src/crypto/key_store.rs
  3. 58 126
      crates/btnode/src/crypto/mod.rs

+ 14 - 0
crates/btnode/notes.txt

@@ -0,0 +1,14 @@
+Convert EncryptionAlgo, DecryptionAlgo, SignAlgo, VerifyAlgo to traits.
+
+Modify SymKey and AsymKey<T> to hold the state needed to perform these operations, rather than
+just buffers of serialized data, and implement these traits.
+
+Manually implement the Serialize and Deserialize traits for these types.
+
+Split AsymKey<T> into two types, one for private and on for public keys.
+
+The public part should be an enum, AsymKeyPublic, allowing operations to be performed in software.
+
+The private part should be a trait, AsymKeyPrivate, requiring all operations to be deferred to an
+implementation, which may use a hardware device to execute them.
+AsymKeyPrivate = DecryptionAlgo + SignAlgo

+ 17 - 0
crates/btnode/src/crypto/key_store.rs

@@ -0,0 +1,17 @@
+use super::*;
+
+pub(crate) trait KeyStore : std::fmt::Debug {
+    fn generate(&mut self, kind: AsymKeyKind) -> &KeyPair;
+    fn store<'a>(&'a mut self, pair: &KeyPair) -> Result<&'a KeyPair>;
+    fn duplicate(
+        &mut self, pair: &KeyPair, wrap_with: Option<&AsymKey<Public>>
+    ) -> Cryptotext<KeyPair>;
+    fn list<'a>(&'a self) -> Box<dyn Iterator<Item=&'a KeyPair>>; 
+    fn delete(&mut self, pair: &KeyPair) -> Result<()>;
+
+    fn sign(&self, pair: &KeyPair, data: &[u8]) -> Vec<u8>;
+    fn verify(&self, pair: &KeyPair, data: &[u8], sig: &[u8]) -> bool;
+
+    fn encrypt(&self, pair: &KeyPair, data: &[u8]) -> Vec<u8>;
+    fn decrypt(&self, pair: &KeyPair, data: &[u8]) -> Vec<u8>;
+}

+ 58 - 126
crates/btnode/src/crypto/mod.rs

@@ -239,6 +239,12 @@ pub(crate) enum SymKey {
     },
 }
 
+struct SymParams<'a> {
+    cipher: Cipher,
+    key: &'a [u8],
+    iv: Option<&'a [u8]>,
+}
+
 /// Returns an array of the given length filled with cryptographically random data.
 fn rand_array<const LEN: usize>() -> Result<[u8; LEN]> {
     let mut array = [0; LEN];
@@ -257,6 +263,14 @@ impl SymKey {
             },
         }
     }
+
+    fn params<'a>(&'a self) -> SymParams<'a> {
+        let (cipher, key, iv) = match self {
+            SymKey::Aes256Cbc { key, iv } => (Cipher::aes_256_cbc(), key, Some(iv.as_slice())),
+            SymKey::Aes256Ctr { key, iv } => (Cipher::aes_256_ctr(), key, Some(iv.as_slice())),
+        };
+        SymParams { cipher, key, iv }
+    }
 }
 
 #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
@@ -337,125 +351,59 @@ impl Owned for KeyPair {
     }
 }
 
-enum EncryptionAlgo<'a> {
-    Symmetric {
-        cipher: Cipher,
-        key: &'a [u8],
-        iv: Option<&'a [u8]>
-    },
-    Asymmetric {
-        key: PKey<OsslPublic>,
-        rsa_padding: Option<OpensslPadding>,
-    }
+trait Encryptor {
+    fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>>;
 }
 
-impl<'a> EncryptionAlgo<'a> {
+impl Encryptor for SymKey {
     fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
-        match self {
-            EncryptionAlgo::Symmetric { cipher, key, iv } => {
-                openssl_encrypt(*cipher, key, *iv, slice).map_err(Error::from)
-            },
-            EncryptionAlgo::Asymmetric { key, rsa_padding } => {
-                let mut encrypter = Encrypter::new(key).map_err(Error::from)?;
-                if let Some(padding) = rsa_padding {
-                    encrypter.set_rsa_padding(*padding).map_err(Error::from)?;
-                }
-                let buffer_len = encrypter.encrypt_len(slice).map_err(Error::from)?;
-                let mut ciphertext = vec![0; buffer_len];
-                let ciphertext_len = encrypter.encrypt(slice, &mut ciphertext)
-                    .map_err(Error::from)?;
-                ciphertext.truncate(ciphertext_len);
-                Ok(ciphertext)
-            }
-        }
+        let SymParams { cipher, key, iv } = self.params();
+        openssl_encrypt(cipher, key, iv, slice).map_err(Error::from)
     }
 }
 
-impl<'a> TryFrom<&'a SymKey> for EncryptionAlgo<'a> {
-    type Error = Error;
-    fn try_from(key: &'a SymKey) -> Result<EncryptionAlgo<'a>> {
-        match key {
-            SymKey::Aes256Cbc { key: key_slice, iv } => Ok(EncryptionAlgo::Symmetric {
-                cipher: Cipher::aes_256_cbc(),
-                key: key_slice,
-                iv: Some(iv),
-            }),
-            SymKey::Aes256Ctr { key: key_slice, iv } => Ok(EncryptionAlgo::Symmetric {
-                cipher: Cipher::aes_256_ctr(),
-                key: key_slice,
-                iv: Some(iv),
-            }),
+impl Encryptor for AsymKey<Public> {
+    fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
+        let (pkey, rsa_padding) = match self {
+            AsymKey::Rsa { der, padding, .. }
+                => (PKey::public_key_from_der(der.as_slice()).map_err(Error::from)?, Some(padding)),
+        };
+        let mut encrypter = Encrypter::new(&pkey).map_err(Error::from)?;
+        if let Some(padding) = rsa_padding {
+            encrypter.set_rsa_padding((*padding).into()).map_err(Error::from)?;
         }
+        let buffer_len = encrypter.encrypt_len(slice).map_err(Error::from)?;
+        let mut ciphertext = vec![0; buffer_len];
+        let ciphertext_len = encrypter.encrypt(slice, &mut ciphertext)
+            .map_err(Error::from)?;
+        ciphertext.truncate(ciphertext_len);
+        Ok(ciphertext)
     }
 }
 
-impl<'a> TryFrom<&'a AsymKey<Public>> for EncryptionAlgo<'a> {
-    type Error = Error;
-    fn try_from(key: &'a AsymKey<Public>) -> Result<EncryptionAlgo<'a>> {
-        match key {
-            AsymKey::Rsa { der, padding, .. } => {
-                let key = PKey::public_key_from_der(der.as_slice()).map_err(Error::from)?;
-                Ok(EncryptionAlgo::Asymmetric { key, rsa_padding: Some((*padding).into()) })
-            },
-        }
-    }
+trait Decryptor {
+    fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>>;
 }
 
-enum DecryptionAlgo<'a> {
-    Symmetric {
-        cipher: Cipher,
-        key: &'a [u8],
-        iv: Option<&'a [u8]>
-    },
-    Asymmetric(PKey<OsslPrivate>),
-}
-
-impl<'a> DecryptionAlgo<'a> {
+impl Decryptor for SymKey {
     fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
-        match self {
-            DecryptionAlgo::Symmetric { cipher, key, iv } => {
-                openssl_decrypt(*cipher, key, *iv, slice).map_err(Error::from)
-            },
-            DecryptionAlgo::Asymmetric(pkey) => {
-                let decrypter = Decrypter::new(pkey).map_err(Error::from)?;
-                let buffer_len = decrypter.decrypt_len(slice).map_err(Error::from)?;
-                let mut plaintext = vec![0; buffer_len];
-                let plaintext_len = decrypter.decrypt(slice, &mut plaintext)
-                    .map_err(Error::from)?;
-                plaintext.truncate(plaintext_len);
-                Ok(plaintext)
-            },
-        }
-    }
-}
-
-impl<'a> TryFrom<&'a SymKey> for DecryptionAlgo<'a> {
-    type Error = Error;
-    fn try_from(key: &'a SymKey) -> Result<DecryptionAlgo<'a>> {
-        match key {
-            SymKey::Aes256Cbc { key: key_slice, iv } => Ok(DecryptionAlgo::Symmetric {
-                cipher: Cipher::aes_256_cbc(),
-                key: key_slice,
-                iv: Some(iv),
-            }),
-            SymKey::Aes256Ctr { key: key_slice, iv } => Ok(DecryptionAlgo::Symmetric {
-                cipher: Cipher::aes_256_ctr(),
-                key: key_slice,
-                iv: Some(iv),
-            }),
-        }
+        let SymParams { cipher, key, iv } = self.params();
+        openssl_decrypt(cipher, key, iv, slice).map_err(Error::from)
     }
 }
 
-impl<'a> TryFrom<&'a AsymKey<Private>> for DecryptionAlgo<'a> {
-    type Error = Error;
-    fn try_from(key: &'a AsymKey<Private>) -> Result<DecryptionAlgo<'a>> {
-        match key {
-            AsymKey::Rsa { der, .. } => {
-                let pkey = PKey::private_key_from_der(der.as_slice()).map_err(Error::from);
-                Ok(DecryptionAlgo::Asymmetric(pkey?))
-            }
-        }
+impl Decryptor for AsymKey<Private> {
+    fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
+        let pkey = match self {
+            AsymKey::Rsa { der, .. }
+                => PKey::private_key_from_der(der.as_slice()).map_err(Error::from)?
+        };
+        let decrypter = Decrypter::new(&pkey).map_err(Error::from)?;
+        let buffer_len = decrypter.decrypt_len(slice).map_err(Error::from)?;
+        let mut plaintext = vec![0; buffer_len];
+        let plaintext_len = decrypter.decrypt(slice, &mut plaintext).map_err(Error::from)?;
+        plaintext.truncate(plaintext_len);
+        Ok(plaintext)
     }
 }
 
@@ -535,7 +483,7 @@ pub(crate) fn encrypt_block(
     let (principal_owned, read_cap) = block.readcaps.remove_entry(principal)
         .ok_or(Error::NoReadCap)?;
     let block_key = decrypt(read_cap, &key.private)?;
-    let new_body = encrypt_slice(&body, &block_key)?;
+    let new_body = block_key.encrypt(&body)?;
     block.body = Cryptotext::Cipher(new_body);
     block.readcaps.insert(principal_owned, encrypt(&block_key, &key.public)?);
     Ok(block)
@@ -551,45 +499,29 @@ pub(crate) fn decrypt_block(
     let (principal_owned, read_cap) = block.readcaps.remove_entry(principal)
         .ok_or(Error::NoReadCap)?;
     let block_key = decrypt(read_cap, key)?;
-    let new_body = decrypt_slice(&body, &block_key)?;
+    let new_body = block_key.decrypt(&body)?;
     block.body = Cryptotext::Plain(new_body);
     block.readcaps.insert(principal_owned, Cryptotext::Plain(block_key));
     Ok(block)
 }
 
-fn encrypt<'a, T: Serialize, K: TryInto<EncryptionAlgo<'a>, Error = Error>>(
-    value: &T, key: K
-) -> Result<Cryptotext<T>> {
+fn encrypt<'a, T: Serialize, K: Encryptor>(value: &T, key: &K) -> Result<Cryptotext<T>> {
     let data = to_vec(value).map_err(Error::from)?;
-    let vec = encrypt_slice(&data, key);
+    let vec = key.encrypt(&data);
     Ok(Cryptotext::Cipher(vec?))
 }
 
-fn decrypt<'a, T: Serialize + DeserializeOwned, K: TryInto<DecryptionAlgo<'a>, Error = Error>>(
-    cryptotext: Cryptotext<T>, key: K
+fn decrypt<'a, T: Serialize + DeserializeOwned, K: Decryptor>(
+    cryptotext: Cryptotext<T>, key: &K
 ) -> Result<T> {
     let data = match cryptotext {
         Cryptotext::Plain(value) => return Ok(value),
         Cryptotext::Cipher(data) => data
     };
-    let vec = decrypt_slice(&data, key);
+    let vec = key.decrypt(&data);
     from_vec(&vec?).map_err(Error::from)
 }
 
-fn encrypt_slice<'a, K: TryInto<EncryptionAlgo<'a>, Error = Error>>(
-    plaintext: &[u8], key: K
-) -> Result<Vec<u8>> {
-    let algo: EncryptionAlgo<'a> = key.try_into()?;
-    algo.encrypt(plaintext)
-}
-
-fn decrypt_slice<'a, K: TryInto<DecryptionAlgo<'a>, Error = Error>>(
-    ciphertext: &[u8], key: K
-) -> Result<Vec<u8>> {
-    let algo: DecryptionAlgo<'a> = key.try_into()?;
-    algo.decrypt(ciphertext)
-}
-
 #[derive(Serialize)]
 struct SigHeader<'a> {
     path: &'a Path,