Browse Source

Finished integrating the Scheme trait.

Matthew Carr 2 years ago
parent
commit
ce9525ec95

+ 1 - 0
crates/btnode/Cargo.lock

@@ -62,6 +62,7 @@ dependencies = [
  "base64-url",
  "ctor",
  "env_logger",
+ "foreign-types",
  "harness",
  "log",
  "openssl",

+ 1 - 0
crates/btnode/Cargo.toml

@@ -19,6 +19,7 @@ env_logger = "0.9.0"
 log = "0.4.17"
 tss-esapi = "7.1.0"
 tss-esapi-sys = "0.3.0"
+foreign-types = "0.3.1"
 
 [dev-dependencies]
 tempdir = "0.3.7"

+ 252 - 146
crates/btnode/src/crypto/mod.rs

@@ -7,7 +7,7 @@ use super::*;
 use openssl::{
     error::ErrorStack,
     encrypt::{Encrypter as OsslEncrypter, Decrypter as OsslDecrypter},
-    pkey::{PKey, Public, Private},
+    pkey::{PKey, Public as OsslPublic, Private as OsslPrivate, HasPublic, HasPrivate},
     symm::{Cipher, encrypt as openssl_encrypt, decrypt as openssl_decrypt},
     rand::rand_bytes,
     rsa::{Rsa, Padding as OpensslPadding},
@@ -23,6 +23,7 @@ use std::{
     str::FromStr, num::TryFromIntError, marker::PhantomData,
 };
 use strum_macros::{EnumString, EnumDiscriminants, Display};
+use foreign_types::ForeignType;
 
 /// Data that may or may not be encrypted.
 #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
@@ -292,13 +293,29 @@ impl SymKey {
     }
 }
 
+impl Encrypter for SymKey {
+    fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
+        let SymParams { cipher, key, iv } = self.params();
+        openssl_encrypt(cipher, key, iv, slice).conv_err()
+    }
+}
+
+impl Decrypter for SymKey {
+    fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
+        let SymParams { cipher, key, iv } = self.params();
+        openssl_decrypt(cipher, key, iv, slice).conv_err()
+    }
+}
+
 pub trait Scheme: for<'de> Deserialize<'de> + Serialize + Copy + std::fmt::Debug + PartialEq {
-    type Kind;
+    type Kind: Scheme;
     fn kind(self) -> Self::Kind;
     fn as_enum(self) -> SchemeKind;
     fn message_digest(&self) -> MessageDigest;
     fn padding(&self) -> Option<OpensslPadding>;
-    fn public_from_der(self, der: &[u8]) -> Result<PKey<Public>>;
+    fn public_from_der(self, der: &[u8]) -> Result<PKey<OsslPublic>>;
+    fn private_from_der(self, der: &[u8]) -> Result<PKey<OsslPrivate>>;
+    fn generate(self) -> Result<AsymKeyPair<Self::Kind>>;
 }
 
 pub enum SchemeKind {
@@ -334,11 +351,23 @@ impl Scheme for Encrypt {
         }
     }
 
-    fn public_from_der(self, der: &[u8]) -> Result<PKey<Public>> {
+    fn public_from_der(self, der: &[u8]) -> Result<PKey<OsslPublic>> {
         match self {
             Encrypt::RsaEsOaep(inner) => inner.public_from_der(der),
         }
     }
+
+    fn private_from_der(self, der: &[u8]) -> Result<PKey<OsslPrivate>> {
+        match self {
+            Encrypt::RsaEsOaep(inner) => inner.private_from_der(der),
+        }
+    }
+
+    fn generate(self) -> Result<AsymKeyPair<Self::Kind>> {
+        match self {
+            Encrypt::RsaEsOaep(inner) => inner.generate(),
+        }
+    }
 }
 
 impl Encrypt {
@@ -376,11 +405,23 @@ impl Scheme for Sign {
         }
     }
 
-    fn public_from_der(self, der: &[u8]) -> Result<PKey<Public>> {
+    fn public_from_der(self, der: &[u8]) -> Result<PKey<OsslPublic>> {
         match self {
             Sign::RsaSsaPss(inner) => inner.public_from_der(der),
         }
     }
+
+    fn private_from_der(self, der: &[u8]) -> Result<PKey<OsslPrivate>> {
+        match self {
+            Sign::RsaSsaPss(inner) => inner.private_from_der(der),
+        }
+    }
+
+    fn generate(self) -> Result<AsymKeyPair<Self::Kind>> {
+        match self {
+            Sign::RsaSsaPss(inner) => inner.generate(),
+        }
+    }
 }
 
 impl Sign {
@@ -402,6 +443,17 @@ pub struct RsaEsOaep {
     hash_kind: HashKind,
 }
 
+fn generate_rsa<S: Scheme>(scheme: S) -> Result<AsymKeyPair<S>> {
+    let key_bits = 8 * u32::try_from(RSA_KEY_BYTES).conv_err()?;
+    let key = Rsa::generate(key_bits)?;
+    // TODO: Separating the keys this way seems inefficient. Investigate alternatives.
+    let public_der = key.public_key_to_der().conv_err()?;
+    let private_der = key.private_key_to_der().conv_err()?;
+    let public = AsymKey::<Public, S>::new(scheme, &public_der)?;
+    let private = AsymKey::<Private, S>::new(scheme, &private_der)?;
+    Ok(AsymKeyPair { public, private })
+}
+
 impl Scheme for RsaEsOaep {
     type Kind = Encrypt;
 
@@ -421,9 +473,23 @@ impl Scheme for RsaEsOaep {
         Some(OpensslPadding::PKCS1_OAEP)
     }
 
-    fn public_from_der(self, der: &[u8]) -> Result<PKey<Public>> {
+    fn public_from_der(self, der: &[u8]) -> Result<PKey<OsslPublic>> {
         PKey::public_key_from_der(der).conv_err()
     }
+
+    fn private_from_der(self, der: &[u8]) -> Result<PKey<OsslPrivate>> {
+        PKey::private_key_from_der(der).conv_err()
+    }
+
+    fn generate(self) -> Result<AsymKeyPair<Self::Kind>> {
+        generate_rsa(self.kind())
+    }
+}
+
+impl From<RsaEsOaep> for Encrypt {
+    fn from(scheme: RsaEsOaep) -> Self {
+        scheme.kind()
+    }
 }
 
 #[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Copy)]
@@ -451,23 +517,64 @@ impl Scheme for RsaSsaPss {
         Some(OpensslPadding::PKCS1_PSS)
     }
 
-    fn public_from_der(self, der: &[u8]) -> Result<PKey<Public>> {
+    fn public_from_der(self, der: &[u8]) -> Result<PKey<OsslPublic>> {
         PKey::public_key_from_der(der).conv_err()
     }
+
+    fn private_from_der(self, der: &[u8]) -> Result<PKey<OsslPrivate>> {
+        PKey::private_key_from_der(der).conv_err()
+    }
+
+    fn generate(self) -> Result<AsymKeyPair<Self::Kind>> {
+        generate_rsa(self.kind())
+    }
+}
+
+impl From<RsaSsaPss> for Sign {
+    fn from(scheme: RsaSsaPss) -> Self {
+        scheme.kind()
+    }
+}
+
+pub trait KeyPrivacy {}
+
+#[derive(Clone, Debug)]
+pub enum Public {}
+
+impl KeyPrivacy for Public {}
+
+unsafe impl HasPublic for Public {}
+
+pub enum Private {}
+
+impl KeyPrivacy for Private {}
+
+unsafe impl HasPrivate for Private {}
+
+fn conv_pkey<T, Q>(pkey: PKey<T>) -> PKey<Q> {
+    let ptr = pkey.as_ptr();
+    let new_pkey = unsafe { PKey::from_ptr(ptr) };
+    std::mem::forget(pkey);
+    new_pkey
+}
+
+fn conv_pkey_pub(pkey: PKey<OsslPublic>) -> PKey<Public> {
+    conv_pkey(pkey)
+}
+
+fn conv_pkey_priv(pkey: PKey<OsslPrivate>) -> PKey<Private> {
+    conv_pkey(pkey)
 }
 
 #[derive(Debug, Clone)]
-pub struct AsymKeyPub<S: Scheme> {
+pub struct AsymKey<P: KeyPrivacy, S: Scheme> {
     scheme: S,
-    pkey: PKey<Public>,
+    pkey: PKey<P>,
 }
 
-impl<S: Scheme> AsymKeyPub<S> {
-    pub(crate) fn new(scheme: S, der: &[u8]) -> Result<AsymKeyPub<S>> {
-        let pkey = scheme.public_from_der(der)?;
-        Ok(AsymKeyPub { scheme, pkey })
-    }
+pub type AsymKeyPub<S> = AsymKey<Public, S>;
 
+impl<P: KeyPrivacy, S: Scheme> AsymKey<P, S> {
     fn digest(&self) -> MessageDigest {
         self.scheme.message_digest()
     }
@@ -475,29 +582,43 @@ impl<S: Scheme> AsymKeyPub<S> {
     fn padding(&self) -> Option<OpensslPadding> {
         self.scheme.padding()
     }
+}
+
+impl<S: Scheme> AsymKey<Public, S> {
+    pub(crate) fn new(scheme: S, der: &[u8]) -> Result<AsymKey<Public, S>> {
+        let pkey = conv_pkey_pub(scheme.public_from_der(der)?);
+        Ok(AsymKey { scheme, pkey })
+    }
 
     fn to_der(&self) -> Result<Vec<u8>> {
         self.pkey.public_key_to_der().conv_err()
     }
 }
 
-impl AsymKeyPub<Sign> {
+impl<S: Scheme> AsymKey<Private, S> {
+    pub(crate) fn new(scheme: S, der: &[u8]) -> Result<AsymKey<Private, S>> {
+        let pkey = conv_pkey_priv(scheme.private_from_der(der)?);
+        Ok(AsymKey { scheme, pkey })
+    }
+}
+
+impl<P: KeyPrivacy> AsymKey<P, Sign> {
     fn signature_buf(&self) -> Signature {
         self.scheme.sig_buf()
     }
 }
 
-impl<'de, S: Scheme> Deserialize<'de> for AsymKeyPub<S> {
+impl<'de, S: Scheme> Deserialize<'de> for AsymKey<Public, S> {
     fn deserialize<D: Deserializer<'de>>(d: D) -> std::result::Result<Self, D::Error> {
         const FIELDS: &[&str] = &["scheme", "pkey"];
 
         struct StructVisitor<S: Scheme>(PhantomData<S>);
 
         impl<'de, S: Scheme> Visitor<'de> for StructVisitor<S> {
-            type Value = AsymKeyPub<S>;
+            type Value = AsymKey<Public, S>;
 
             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
-                formatter.write_fmt(format_args!("struct {}", stringify!(AsymKeyPub)))
+                formatter.write_fmt(format_args!("struct {}", stringify!(AsymKey)))
             }
 
             fn visit_seq<V: SeqAccess<'de>>(
@@ -507,18 +628,20 @@ impl<'de, S: Scheme> Deserialize<'de> for AsymKeyPub<S> {
                     .ok_or_else(|| de::Error::missing_field(FIELDS[0]))?;
                 let der: Vec<u8> = seq.next_element()?
                     .ok_or_else(|| de::Error::missing_field(FIELDS[1]))?;
-                AsymKeyPub::new(scheme, der.as_slice())
+                AsymKey::<Public, _>::new(scheme, der.as_slice())
                     .map_err(de::Error::custom)
             }
         }
 
-        d.deserialize_struct(stringify!(AsymKeyPub), FIELDS, StructVisitor(PhantomData))
+        d.deserialize_struct(
+            stringify!(AsymKey), FIELDS, StructVisitor(PhantomData)
+        )
     }
 }
 
-impl<S: Scheme> Serialize for AsymKeyPub<S> {
+impl<S: Scheme> Serialize for AsymKey<Public, S> {
     fn serialize<T: Serializer>(&self, s: T) -> std::result::Result<T::Ok, T::Error> {
-        let mut struct_s = s.serialize_struct(stringify!(AsymKeyPub), 2)?;
+        let mut struct_s = s.serialize_struct(stringify!(AsymKey), 2)?;
         struct_s.serialize_field("scheme", &self.scheme)?;
         let der = self.pkey.public_key_to_der().unwrap();
         struct_s.serialize_field("pkey", der.as_slice())?;
@@ -526,13 +649,13 @@ impl<S: Scheme> Serialize for AsymKeyPub<S> {
     }
 }
 
-impl<S: Scheme> PartialEq for AsymKeyPub<S> {
+impl<S: Scheme> PartialEq for AsymKey<Public, S> {
     fn eq(&self, other: &Self) -> bool {
         self.scheme == other.scheme && self.pkey.public_eq(&other.pkey)
     }
 }
 
-impl Owned for AsymKeyPub<Sign> {
+impl Owned for AsymKey<Public, Sign> {
     fn owner_of_kind(&self, kind: HashKind) -> Principal {
         match kind {
             HashKind::Sha2_256 => {
@@ -553,29 +676,34 @@ impl Owned for AsymKeyPub<Sign> {
     }
 }
 
-pub(crate) struct ConcreteCredsPriv {
-    pkey: PKey<Private>,
-}
-
-impl ConcreteCredsPriv {
-    pub(crate) fn new(der: &[u8]) -> Result<ConcreteCredsPriv> {
-        let rsa = Rsa::private_key_from_der(der).conv_err()?;
-        let pkey = PKey::from_rsa(rsa).conv_err()?;
-        Ok(ConcreteCredsPriv { pkey })
-    }
-
-    fn digest() -> MessageDigest {
-        MessageDigest::sha256()
-    }
-
-    fn signature_buf() -> Signature {
-        Signature::new(SignatureKind::Rsa)
+impl Encrypter for AsymKey<Public, Encrypt> {
+    fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
+        let mut encrypter = OsslEncrypter::new(&self.pkey)?;
+        if let Some(padding) = self.padding() {
+            encrypter.set_rsa_padding(padding)?;
+        }
+        {
+            let Encrypt::RsaEsOaep(inner) = self.scheme;
+            encrypter.set_rsa_oaep_md(inner.message_digest())?;
+        }
+        let buffer_len = encrypter.encrypt_len(slice)?;
+        let mut ciphertext = vec![0; buffer_len];
+        let ciphertext_len = encrypter.encrypt(slice, &mut ciphertext)?;
+        ciphertext.truncate(ciphertext_len);
+        Ok(ciphertext)
     }
 }
 
-impl Decrypter for ConcreteCredsPriv {
+impl Decrypter for AsymKey<Private, Encrypt> {
     fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
-        let decrypter = OsslDecrypter::new(&self.pkey).conv_err()?;
+        let mut decrypter = OsslDecrypter::new(&self.pkey).conv_err()?;
+        if let Some(padding) = self.padding() {
+            decrypter.set_rsa_padding(padding).conv_err()?;
+        }
+        {
+            let Encrypt::RsaEsOaep(inner) = self.scheme;
+            decrypter.set_rsa_oaep_md(inner.message_digest())?;
+        }
         let buffer_len = decrypter.decrypt_len(slice).conv_err()?;
         let mut plaintext = vec![0; buffer_len];
         let plaintext_len = decrypter.decrypt(slice, &mut plaintext).conv_err()?;
@@ -584,114 +712,131 @@ impl Decrypter for ConcreteCredsPriv {
     }
 }
 
-impl Signer for ConcreteCredsPriv {
+impl Signer for AsymKey<Private, Sign> {
     fn sign<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I) -> Result<Signature> {
-        let digest = ConcreteCredsPriv::digest();
-        let mut signature = ConcreteCredsPriv::signature_buf();
-
-        let mut signer = OsslSigner::new(digest, &self.pkey).conv_err()?;
+        let mut signer = OsslSigner::new(self.scheme.message_digest(), &self.pkey)?;
+        if let Some(padding) = self.scheme.padding() {
+            signer.set_rsa_padding(padding)?;
+        }
         for part in parts {
-            signer.update(part).conv_err()?;
+            signer.update(part)?;
         }
-        let buf = signature.as_mut_slice();
-        signer.sign(buf).conv_err()?;
+        let mut signature = self.scheme.sig_buf();
+        signer.sign(signature.as_mut_slice())?;
         Ok(signature)
     }
 }
 
-impl CredsPriv for ConcreteCredsPriv {}
+impl Verifier for AsymKey<Public, Sign> {
+    fn verify<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I, signature: &[u8]) -> Result<bool> {
+        let mut verifier = OsslVerifier::new(self.digest(), &self.pkey)?;
+        if let Some(padding) = self.scheme.padding() {
+            verifier.set_rsa_padding(padding)?;
+        }
+        for part in parts {
+            verifier.update(part)?;
+        }
+        Ok(verifier.verify(signature)?)
+    }
+}
 
-pub struct ConcreteCredsPub {
-    pub encrypt: AsymKeyPub<Encrypt>,
-    pub sign: AsymKeyPub<Sign>,
+pub struct AsymKeyPair<S: Scheme> {
+    public: AsymKey<Public, S>,
+    private: AsymKey<Private, S>,
 }
 
-impl Verifier for ConcreteCredsPub {
-    fn verify<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I, signature: &[u8]) -> Result<bool> {
-        self.sign.verify(parts, signature)
+impl<S: Scheme> AsymKeyPair<S> {
+    pub fn new(scheme: S, public_der: &[u8], private_der: &[u8]) -> Result<AsymKeyPair<S>> {
+        let public = AsymKey::<Public, _>::new(scheme, public_der)?;
+        let private = AsymKey::<Private, _>::new(scheme, private_der)?;
+        Ok(AsymKeyPair { public, private })
     }
 }
 
-impl Encrypter for ConcreteCredsPub {
-    fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
-        self.encrypt.encrypt(slice)
+impl Owned for AsymKeyPair<Sign> {
+    fn owner_of_kind(&self, kind: HashKind) -> Principal {
+        self.public.owner_of_kind(kind)
     }
 }
 
-impl Owned for ConcreteCredsPub {
-    fn owner_of_kind(&self, kind: HashKind) -> Principal {
-        self.sign.owner_of_kind(kind)
+impl Encrypter for AsymKeyPair<Encrypt> {
+    fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
+        self.public.encrypt(slice)
     }
 }
 
-impl CredsPub for ConcreteCredsPub {}
+impl Decrypter for AsymKeyPair<Encrypt> {
+    fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
+        self.private.decrypt(slice)
+    }
+}
 
-pub(crate) struct ConcreteCreds<T: CredsPriv> {
-    public: ConcreteCredsPub,
-    private: T,
+impl Signer for AsymKeyPair<Sign> {
+    fn sign<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I) -> Result<Signature> {
+        self.private.sign(parts)
+    }
 }
 
-impl<T: CredsPriv> ConcreteCreds<T> {
-    pub(crate) fn new(public: ConcreteCredsPub, private: T) -> ConcreteCreds<T> {
-        ConcreteCreds { public, private }
+impl Verifier for AsymKeyPair<Sign> {
+    fn verify<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I, signature: &[u8]) -> Result<bool> {
+        self.public.verify(parts, signature)
     }
 }
 
+pub struct ConcreteCreds {
+    sign: AsymKeyPair<Sign>,
+    encrypt: AsymKeyPair<Encrypt>,
+}
 
-impl ConcreteCreds<ConcreteCredsPriv> {
-    pub(crate) fn generate() -> Result<ConcreteCreds<ConcreteCredsPriv>> {
-        let key_bits = 8 * u32::try_from(RSA_KEY_BYTES).conv_err()?;
-        let key = Rsa::generate(key_bits)?;
-        // TODO: Separating the keys this way seems inefficient. Investigate alternatives.
-        let public_der = key.public_key_to_der().conv_err()?;
-        let private_der = key.private_key_to_der().conv_err()?;
-        Ok(ConcreteCreds {
-            public: ConcreteCredsPub {
-                encrypt: AsymKeyPub::new(Encrypt::RSA_OAEP_3072_SHA_256, public_der.as_slice())?,
-                sign: AsymKeyPub::new(Sign::RSA_PSS_3072_SHA_256, public_der.as_slice())?,
-            },
-            private: ConcreteCredsPriv::new(private_der.as_slice())?,
-        })
+impl ConcreteCreds {
+    pub(crate) fn new(sign: AsymKeyPair<Sign>, encrypt: AsymKeyPair<Encrypt>) -> ConcreteCreds {
+        ConcreteCreds { sign, encrypt }
+    }
+
+    pub(crate) fn generate() -> Result<ConcreteCreds> {
+        let encrypt = Encrypt::RSA_OAEP_3072_SHA_256.generate()?;
+        let sign = Sign::RSA_PSS_3072_SHA_256.generate()?;
+        Ok(ConcreteCreds { sign, encrypt })
     }
 }
 
-impl<T: CredsPriv> Verifier for ConcreteCreds<T> {
+impl Verifier for ConcreteCreds {
     fn verify<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I, signature: &[u8]) -> Result<bool> {
-        self.public.verify(parts, signature)
+        self.sign.verify(parts, signature)
     }
 }
 
-impl<T: CredsPriv> Encrypter for ConcreteCreds<T> {
+impl Encrypter for ConcreteCreds {
     fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
-        self.public.encrypt(slice)
+        self.encrypt.encrypt(slice)
     }
 }
 
-impl<T: CredsPriv> Owned for ConcreteCreds<T> {
+impl Owned for ConcreteCreds {
     fn owner_of_kind(&self, kind: HashKind) -> Principal {
-        self.public.owner_of_kind(kind)
+        self.sign.owner_of_kind(kind)
     }
 }
 
-impl<T: CredsPriv> CredsPub for ConcreteCreds<T> {}
+impl CredsPub for ConcreteCreds {}
 
-impl<T: CredsPriv> Signer for ConcreteCreds<T> {
+impl Signer for ConcreteCreds {
     fn sign<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I) -> Result<Signature> {
-        self.private.sign(parts)
+        self.sign.sign(parts)
     }
 }
 
-impl<T: CredsPriv> Decrypter for ConcreteCreds<T> {
+impl Decrypter for ConcreteCreds {
     fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
-        self.private.decrypt(slice)
+        self.encrypt.decrypt(slice)
     }
 }
 
-impl<T: CredsPriv> CredsPriv for ConcreteCreds<T> {}
+impl CredsPriv for ConcreteCreds {}
 
-impl<T: CredsPriv> Creds for ConcreteCreds<T> {
-    fn public(&self) -> &AsymKeyPub<Sign> {
-        &self.public.sign
+impl Creds for ConcreteCreds {
+    fn public(&self) -> &AsymKey<Public, Sign> {
+        &self.sign.public
     }
 }
 
@@ -699,39 +844,10 @@ pub(crate) trait Encrypter {
     fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>>;
 }
 
-impl Encrypter for SymKey {
-    fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
-        let SymParams { cipher, key, iv } = self.params();
-        openssl_encrypt(cipher, key, iv, slice).conv_err()
-    }
-}
-
-impl Encrypter for AsymKeyPub<Encrypt> {
-    fn encrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
-        let mut encrypter = OsslEncrypter::new(&self.pkey).conv_err()?;
-        if let Some(padding) = self.padding() {
-            encrypter.set_rsa_padding(padding).conv_err()?;
-        }
-        let buffer_len = encrypter.encrypt_len(slice).conv_err()?;
-        let mut ciphertext = vec![0; buffer_len];
-        let ciphertext_len = encrypter.encrypt(slice, &mut ciphertext)
-            .conv_err()?;
-        ciphertext.truncate(ciphertext_len);
-        Ok(ciphertext)
-    }
-}
-
 pub(crate) trait Decrypter {
     fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>>;
 }
 
-impl Decrypter for SymKey {
-    fn decrypt(&self, slice: &[u8]) -> Result<Vec<u8>> {
-        let SymParams { cipher, key, iv } = self.params();
-        openssl_decrypt(cipher, key, iv, slice).conv_err()
-    }
-}
-
 pub(crate) trait Signer {
     fn sign<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I) -> Result<Signature>;
 }
@@ -740,16 +856,6 @@ pub(crate) trait Verifier {
     fn verify<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I, signature: &[u8]) -> Result<bool>;
 }
 
-impl Verifier for AsymKeyPub<Sign> {
-    fn verify<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I, signature: &[u8]) -> Result<bool> {
-        let mut verifier = OsslVerifier::new(self.digest(), &self.pkey).conv_err()?;
-        for part in parts {
-            verifier.update(part).conv_err()?;
-        }
-        verifier.verify(signature).conv_err()
-    }
-}
-
 /// Trait for types which can be used as public credentials.
 pub(crate) trait CredsPub: Verifier + Encrypter + Owned {}
 
@@ -758,7 +864,7 @@ pub(crate) trait CredsPriv: Decrypter + Signer {}
 
 /// Trait for types which contain both public and private credentials.
 pub(crate) trait Creds: CredsPriv + CredsPub {
-    fn public(&self) -> &AsymKeyPub<Sign>;
+    fn public(&self) -> &AsymKey<Public, Sign>;
 }
 
 /// A trait for types which store credentials.
@@ -776,7 +882,7 @@ pub(crate) trait CredStore {
     fn gen_root_creds(&self, password: &str) -> Result<Self::CredHandle>;
 }
 
-pub(crate) fn encrypt_block<C: Creds>(
+pub(crate) fn encrypt_block<C: Encrypter + Decrypter>(
     mut block: Block, principal: &Principal, creds: &C
 ) -> Result<Block> {
     let body = match block.body {
@@ -792,8 +898,8 @@ pub(crate) fn encrypt_block<C: Creds>(
     Ok(block)
 }
 
-pub(crate) fn decrypt_block<K: CredsPriv>(
-    mut block: Block, principal: &Principal, key: &K
+pub(crate) fn decrypt_block<C: Decrypter>(
+    mut block: Block, principal: &Principal, creds: &C
 ) -> Result<Block> {
     let body = match block.body {
         Cryptotext::Plain(_) => return Ok(block),
@@ -801,7 +907,7 @@ pub(crate) fn decrypt_block<K: CredsPriv>(
     };
     let (principal_owned, read_cap) = block.readcaps.remove_entry(principal)
         .ok_or(Error::NoReadCap)?;
-    let block_key = decrypt(read_cap, key)?;
+    let block_key = decrypt(read_cap, creds)?;
     let new_body = block_key.decrypt(&body)?;
     block.body = Cryptotext::Plain(new_body);
     block.readcaps.insert(principal_owned, Cryptotext::Plain(block_key));
@@ -814,7 +920,7 @@ fn encrypt<T: Serialize, K: Encrypter>(value: &T, key: &K) -> Result<Cryptotext<
     Ok(Cryptotext::Cipher(vec?))
 }
 
-fn decrypt<T: Serialize + DeserializeOwned, K: CredsPriv>(
+fn decrypt<T: Serialize + DeserializeOwned, K: Decrypter>(
     cryptotext: Cryptotext<T>, key: &K
 ) -> Result<T> {
     let data = match cryptotext {
@@ -877,7 +983,7 @@ struct WritecapSigInput<'a> {
     issued_to: &'a Principal,
     path: &'a Path,
     expires: &'a Epoch,
-    signing_key: &'a AsymKeyPub<Sign>,
+    signing_key: &'a AsymKey<Public, Sign>,
 }
 
 impl<'a> From<&'a Writecap> for WritecapSigInput<'a> {

+ 30 - 19
crates/btnode/src/crypto/tpm.rs

@@ -413,17 +413,26 @@ impl KeyKind {
     }
 }
 
+impl From<HashKind> for HashingAlgorithm {
+    fn from(kind: HashKind) -> Self {
+        match kind {
+            HashKind::Sha2_256 => HashingAlgorithm::Sha256,
+            HashKind::Sha2_512 => HashingAlgorithm::Sha512,
+        }
+    }
+}
+
 impl TryInto<RsaScheme> for SchemeKind {
     type Error = Error;
     fn try_into(self) -> Result<RsaScheme> {
         match self {
             SchemeKind::Sign(sign) => match sign {
-                Sign::RsaSsaPss(_)
-                    => Ok(RsaScheme::RsaPss(HashScheme::new(HashingAlgorithm::Sha256))),
+                Sign::RsaSsaPss(inner)
+                    => Ok(RsaScheme::RsaPss(HashScheme::new(inner.hash_kind.into()))),
             },
             SchemeKind::Encrypt(encrypt) => match encrypt {
-                Encrypt::RsaEsOaep(_)
-                    => Ok(RsaScheme::Oaep(HashScheme::new(HashingAlgorithm::Sha256))),
+                Encrypt::RsaEsOaep(inner)
+                    => Ok(RsaScheme::Oaep(HashScheme::new(inner.hash_kind.into()))),
             }
         }
     }
@@ -589,7 +598,7 @@ impl TpmCredStore {
             )
             .conv_err()?
         };
-        let public = AsymKeyPub::try_from(result.out_public, params.scheme)?;
+        let public = AsymKey::try_from(result.out_public, params.scheme)?;
         Ok(KeyPair { public, private: result.key_handle })
     }
 
@@ -715,8 +724,8 @@ impl<S: Scheme> AsymKeyPub<S> {
                 let exponent = BigNum::from_u32(exponent_value).conv_err()?;
                 let modulus = BigNum::from_slice(unique.as_slice()).conv_err()?;
                 let rsa = Rsa::from_public_components(modulus, exponent).conv_err()?;
-                let pkey = PKey::from_rsa(rsa).conv_err()?;
-                Ok(AsymKeyPub { pkey, scheme })
+                let pkey = conv_pkey_pub(PKey::from_rsa(rsa).conv_err()?);
+                Ok(AsymKey { pkey, scheme })
             },
             _ => Err(Error::custom("Unsupported key type returned by TPM")),
         }
@@ -853,9 +862,8 @@ impl CredsPub for TpmCreds {}
 
 impl Signer for TpmCreds {
     fn sign<'a, I: Iterator<Item=&'a [u8]>>(&self, parts: I) -> Result<Signature> {
-        let msg_digest = self.sign.public.digest();
         let digest = {
-            let mut hasher = Hasher::new(msg_digest).conv_err()?;
+            let mut hasher = Hasher::new(self.sign.public.digest()).conv_err()?;
             for part in parts {
                 hasher.update(part).conv_err()?;
             }
@@ -864,23 +872,23 @@ impl Signer for TpmCreds {
             Digest::try_from(slice).conv_err()?
         };
         let validation = HashcheckTicket::null();
-        let scheme = SignatureScheme::RsaSsa { hash_scheme: msg_digest.hash_scheme()? };
+        let scheme = SignatureScheme::Null;
+
         let sig = {
             let mut guard = self.state.write().conv_err()?;
             guard.context.sign(self.sign.private, digest, scheme, validation)
                 .conv_err()?
         };
-        let buf = match sig {
-            tss_esapi::structures::Signature::RsaSsa(inner) => {
-                let mut buf = [0u8; RSA_KEY_BYTES];
-                let slice: &[u8] = inner.signature();
-                buf.as_mut_slice().write_all(slice).conv_err()?;
-                buf
-            },
-            _ => return Err(Error::custom(format!("Unexpected signature type: {:?}", sig))),
+        let slice: &[u8] = match &sig {
+            tss_esapi::structures::Signature::RsaSsa(inner) => inner.signature(),
+            tss_esapi::structures::Signature::RsaPss(inner) => inner.signature(),
+            _ => return Err(
+                Error::custom(format!("Unexpected signature type: {:?}", sig.algorithm()))),
         };
 
-        Ok(Signature::Rsa(buf))
+        let mut buf = self.sign.public.scheme.sig_buf();
+        buf.as_mut_slice().write_all(slice)?;
+        Ok(buf)
     }
 }
 
@@ -1049,6 +1057,9 @@ active_pcr_banks = sha256
                     format!("--tcti=swtpm:host={addr},port={port}").as_str(),
                 ])
                 .spawn()?;
+            // TODO: This wait is flakey and system-specific. I need to find a DBus library I can
+            // use to check when tpm2-abrmd has finished starting up and is accepting bus
+            //connections.
             std::thread::sleep(std::time::Duration::from_millis(50));
             Ok(SwtpmHarness { dir, swtpm, abrmd, bus_name, state_path })
         }

+ 1 - 1
crates/btnode/src/main.rs

@@ -11,7 +11,7 @@ mod serde_tests;
 use serde_block_tree::{self, read_from, write_to};
 use harness::Message;
 mod crypto;
-use crypto::{Hash, HashKind, Signature, SymKey, AsymKeyPub, Cryptotext, Sign};
+use crypto::{Hash, HashKind, Signature, SymKey, Cryptotext, Sign, AsymKeyPub};
 
 use std::{
     collections::HashMap,

+ 8 - 6
crates/btnode/src/test_helpers.rs

@@ -413,12 +413,14 @@ pub(crate) fn make_writecap_trusted_by<C: Creds>(
 }
 
 pub(crate) fn make_key_pair() -> impl Creds {
-    let public = ConcreteCredsPub {
-        sign: AsymKeyPub::new(Sign::RSA_PSS_3072_SHA_256, ROOT_PUBLIC_KEY.as_slice()).unwrap(),
-        encrypt : AsymKeyPub::new(Encrypt::RSA_OAEP_3072_SHA_256, ROOT_PUBLIC_KEY.as_slice()).unwrap(),
-    };
-    let private = ConcreteCredsPriv::new(ROOT_PRIVATE_KEY.as_slice()).unwrap();
-    ConcreteCreds::new(public, private)
+    let sign = AsymKeyPair::new(
+        Sign::RSA_PSS_3072_SHA_256, ROOT_PUBLIC_KEY.as_slice(), ROOT_PRIVATE_KEY.as_slice()
+    ).unwrap();
+    // Using the same key pair is terrible in production, but fine for testing.
+    let encrypt = AsymKeyPair::new(
+        Encrypt::RSA_OAEP_3072_SHA_256, ROOT_PUBLIC_KEY.as_slice(), ROOT_PRIVATE_KEY.as_slice(),
+    ).unwrap();
+    ConcreteCreds::new(sign, encrypt)
 }
 
 pub(crate) fn make_self_signed_writecap() -> Result<(Writecap, impl Creds)> {