Browse Source

Started writing a module for working with a TPM.

Matthew Carr 2 years ago
parent
commit
fdd5c086ec

+ 243 - 0
crates/btnode/Cargo.lock

@@ -43,6 +43,12 @@ dependencies = [
  "base64",
 ]
 
+[[package]]
+name = "bitfield"
+version = "0.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
+
 [[package]]
 name = "bitflags"
 version = "1.3.2"
@@ -63,6 +69,8 @@ dependencies = [
  "serde-block-tree",
  "strum",
  "strum_macros",
+ "tss-esapi",
+ "tss-esapi-sys",
 ]
 
 [[package]]
@@ -77,6 +85,26 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
+[[package]]
+name = "enumflags2"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb"
+dependencies = [
+ "enumflags2_derive",
+]
+
+[[package]]
+name = "enumflags2_derive"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "env_logger"
 version = "0.9.0"
@@ -129,6 +157,12 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "hostname-validator"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f558a64ac9af88b5ba400d99b579451af0d39c6d360980045b91aac966d705e2"
+
 [[package]]
 name = "humantime"
 version = "2.1.0"
@@ -150,12 +184,52 @@ dependencies = [
  "cfg-if",
 ]
 
+[[package]]
+name = "mbox"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f88d5c34d63aad11aa4321ef55ccb064af58b3ad8091079ae22bf83e5eb75d6"
+dependencies = [
+ "libc",
+ "rustc_version",
+ "stable_deref_trait",
+]
+
 [[package]]
 name = "memchr"
 version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 
+[[package]]
+name = "num-derive"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "oid"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c19903c598813dba001b53beeae59bb77ad4892c5c1b9b3500ce4293a0d06c2"
+dependencies = [
+ "serde",
+]
+
 [[package]]
 name = "once_cell"
 version = "1.13.0"
@@ -211,6 +285,50 @@ dependencies = [
  "vcpkg",
 ]
 
+[[package]]
+name = "pest"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
+dependencies = [
+ "ucd-trie",
+]
+
+[[package]]
+name = "picky-asn1"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "889bbb26c80acf919e89980dfc8e04eb19df272d8a9893ec9b748d3a1675abde"
+dependencies = [
+ "oid",
+ "serde",
+ "serde_bytes",
+]
+
+[[package]]
+name = "picky-asn1-der"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbbd5390ab967396cc7473e6e0848684aec7166e657c6088604e07b54a73dbe"
+dependencies = [
+ "picky-asn1",
+ "serde",
+ "serde_bytes",
+]
+
+[[package]]
+name = "picky-asn1-x509"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3033675030de806aba1d5470949701b7c9f1dbf77e3bb17bd12e5f945e560ba"
+dependencies = [
+ "base64",
+ "oid",
+ "picky-asn1",
+ "picky-asn1-der",
+ "serde",
+]
+
 [[package]]
 name = "pkg-config"
 version = "0.3.25"
@@ -252,12 +370,39 @@ version = "0.6.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
 
+[[package]]
+name = "rustc_version"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee"
+dependencies = [
+ "semver",
+]
+
 [[package]]
 name = "rustversion"
 version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a0a5f7c728f5d284929a1cccb5bc19884422bfe6ef4d6c409da2c41838983fcf"
 
+[[package]]
+name = "semver"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
+dependencies = [
+ "semver-parser",
+]
+
+[[package]]
+name = "semver-parser"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
+dependencies = [
+ "pest",
+]
+
 [[package]]
 name = "serde"
 version = "1.0.139"
@@ -284,6 +429,15 @@ dependencies = [
  "serde-big-array",
 ]
 
+[[package]]
+name = "serde_bytes"
+version = "0.11.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "212e73464ebcde48d723aa02eb270ba62eff38a9b732df31f33f1b4e145f3a54"
+dependencies = [
+ "serde",
+]
+
 [[package]]
 name = "serde_derive"
 version = "1.0.139"
@@ -295,6 +449,12 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
 [[package]]
 name = "strum"
 version = "0.24.1"
@@ -328,6 +488,24 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "synstructure"
+version = "0.12.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unicode-xid",
+]
+
+[[package]]
+name = "target-lexicon"
+version = "0.12.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c02424087780c9b71cc96799eaeddff35af2bc513278cda5c99fc1f5d026d3c1"
+
 [[package]]
 name = "termcolor"
 version = "1.1.3"
@@ -337,12 +515,56 @@ dependencies = [
  "winapi-util",
 ]
 
+[[package]]
+name = "tss-esapi"
+version = "7.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2cca751996d707a593074a115d40a285179f7929f912a4e81d2a8c2404c7e7c"
+dependencies = [
+ "bitfield",
+ "enumflags2",
+ "hostname-validator",
+ "log",
+ "mbox",
+ "num-derive",
+ "num-traits",
+ "oid",
+ "picky-asn1",
+ "picky-asn1-x509",
+ "regex",
+ "serde",
+ "tss-esapi-sys",
+ "zeroize",
+]
+
+[[package]]
+name = "tss-esapi-sys"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e2f37914ec4d494d145cfa18bb8429498b238d63c47a08b89d09c1ec2545ff0"
+dependencies = [
+ "pkg-config",
+ "target-lexicon",
+]
+
+[[package]]
+name = "ucd-trie"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c"
+
 [[package]]
 name = "unicode-ident"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
 
+[[package]]
+name = "unicode-xid"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
+
 [[package]]
 name = "vcpkg"
 version = "0.2.15"
@@ -379,3 +601,24 @@ name = "winapi-x86_64-pc-windows-gnu"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "zeroize"
+version = "1.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20b578acffd8516a6c3f2a1bdefc1ec37e547bb4e0fb8b6b01a4cafc886b4442"
+dependencies = [
+ "zeroize_derive",
+]
+
+[[package]]
+name = "zeroize_derive"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]

+ 2 - 0
crates/btnode/Cargo.toml

@@ -17,3 +17,5 @@ strum = { version = "^0.24.0", features = ["derive"] }
 strum_macros = { version = "^0.24.0" }
 env_logger = "0.9.0"
 log = "0.4.17"
+tss-esapi = "7.1.0"
+tss-esapi-sys = "0.3.0"

+ 3 - 1
crates/btnode/src/crypto.rs → crates/btnode/src/crypto/mod.rs

@@ -1,5 +1,7 @@
 /// Functions for performing cryptographic operations on the main data structures.
 
+mod tpm;
+
 use super::*;
 use openssl::{
     error::ErrorStack,
@@ -634,7 +636,7 @@ pub(crate) fn verify_block(block: &Block) -> Result<bool> {
     let header = to_vec(&sig_header)?;
     let verify_algo = VerifyAlgo::try_from(&block.writecap.signing_key)?;
     let parts = [header.as_slice(), body].into_iter();
-    Ok(verify_algo.verify(parts, block.signature.as_slice())?)
+    verify_algo.verify(parts, block.signature.as_slice())
 }
 
 #[derive(Serialize)]

+ 158 - 0
crates/btnode/src/crypto/tpm.rs

@@ -0,0 +1,158 @@
+
+use std::{
+    os::raw::c_char,
+    ffi::CStr,
+};
+use tss_esapi::constants::response_code::Tss2ResponseCode;
+use tss_esapi_sys::TSS2_RC;
+
+#[link(name = "tss2-rc")]
+extern {
+    fn Tss2_RC_Decode(rc: TSS2_RC) -> *const c_char;
+}
+
+trait HasResponseCode {
+    fn response_code(&self) -> TSS2_RC;
+}
+
+fn tss2_rc_decode<E: HasResponseCode>(err: E) -> &'static str {
+    let c_str = unsafe {
+        let ptr = Tss2_RC_Decode(err.response_code());
+        CStr::from_ptr(ptr)
+    };
+    // We're relying on Tss2_RC_Decode to return valid C strings.
+    c_str.to_str().unwrap()
+}
+
+impl HasResponseCode for Tss2ResponseCode {
+    fn response_code(&self) -> TSS2_RC {
+        match self {
+            Tss2ResponseCode::Success => 0,
+            Tss2ResponseCode::FormatZero(code) => code.0,
+            Tss2ResponseCode::FormatOne(code) => code.0,
+        }
+    }
+}
+
+trait Tss2Expect<T> {
+    /// Provides an enhanced error message for types which contain TSS2 response codes.
+    fn tss2_expect(self, err_msg: &str) -> T;
+}
+
+impl<T> Tss2Expect<T> for tss_esapi::Result<T> {
+    fn tss2_expect(self, err_msg: &str) -> T {
+        match self {
+            tss_esapi::Result::Ok(val) => val,
+            tss_esapi::Result::Err(err) => {
+                match err {
+                    tss_esapi::Error::WrapperError(err) => panic!("{}: {}", err_msg, err),
+                    tss_esapi::Error::Tss2Error(err) => {
+                        let rc = err.response_code();
+                        let text = tss2_rc_decode(err);
+                        panic!("{}, response code: {}, response text: {}", err_msg, rc, text);
+                    }
+                }
+            },
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use tss_esapi::{
+        Context,
+        constants::{
+            session_type::{SessionType},
+        },
+        tcti_ldr::{TabrmdConfig},
+        interface_types::{
+            resource_handles::{Hierarchy},
+            algorithm::{HashingAlgorithm},
+            ecc::{EccCurve},
+        },
+        structures::{
+            Digest,
+            EccPoint,
+            EccScheme,
+            KeyDerivationFunctionScheme,
+            HashScheme,
+            Public,
+            PublicEccParameters,
+            SymmetricDefinition,
+            SymmetricDefinitionObject,
+        },
+        attributes::{
+            object::{ObjectAttributes},
+        },
+    };
+
+    #[test]
+    fn create_context() {
+        let config = TabrmdConfig::default();
+        let mut context = Context::new_with_tabrmd(config).unwrap();
+        context.self_test(true).unwrap();
+    }
+
+    #[test]
+    fn create_primary_key() {
+        let config = TabrmdConfig::default();
+        let mut context = Context::new_with_tabrmd(config)
+            .expect("Failed to connect to tabrmd. Ensure that tpm2-abrmd is running");
+
+        let public = {
+            let object_attributes = ObjectAttributes::builder()
+                .with_fixed_tpm(true)
+                .with_fixed_parent(true)
+                .with_sensitive_data_origin(true)
+                .with_user_with_auth(true)
+                .with_decrypt(false)
+                .with_sign_encrypt(true)
+                .with_restricted(false)
+                .build()
+                .expect("ObjectAttributesBuilder failed");
+            let name_hashing_algorithm = HashingAlgorithm::Sha256;
+            let empty = [0u8; 0];
+            let auth_policy = Digest::try_from(empty.as_slice()).unwrap();
+            let parameters = PublicEccParameters::new(
+                SymmetricDefinitionObject::Null,
+                EccScheme::EcDsa(HashScheme::new(HashingAlgorithm::Sha256)),
+                EccCurve::NistP256,
+                KeyDerivationFunctionScheme::Null
+            );
+            Public::Ecc {
+                object_attributes,
+                name_hashing_algorithm,
+                auth_policy,
+                parameters,
+                unique: EccPoint::default(),
+            }
+        };
+
+        let session = context.start_auth_session(
+            None,
+            None,
+            None,
+            SessionType::Hmac,
+            SymmetricDefinition::AES_256_CFB,
+            HashingAlgorithm::Sha256,
+        )
+        .expect("Failed to create session")
+        .expect("Received invalid handle");
+
+        context.execute_with_session(Some(session), |ctx| {
+            let primary = ctx.create_primary(
+                Hierarchy::Null,
+                public,
+                None,
+                None,
+                None,
+                None,
+            )
+            .tss2_expect("create_primary failed")
+            .key_handle;
+
+            ctx.flush_context(primary.into()).expect("flush_context failed");
+        });
+    }
+}

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

@@ -13,8 +13,7 @@ use std::{
 };
 use serde::{Serialize, Deserialize};
 use serde_big_array::BigArray;
-use log::error;
-use env_logger;
+use log::{info, error};
 
 use serde_block_tree::{self, read_from, write_to};
 use harness::Message;
@@ -368,6 +367,7 @@ fn main() {
         };
         match message {
             Message::Echo(_) => {
+                info!("responding to echo request: {:?}", message);
                 if let Err(err) = write_to(&message, &mut out_lock) {
                     error!("Failed to serialize message {:?}", err);
                     return;

+ 1 - 1
crates/harness/src/lib.rs

@@ -8,7 +8,7 @@ use std::{
 use serde_block_tree::{self, write_to, read_from};
 use log::{error};
 
-#[derive(Serialize, Deserialize)]
+#[derive(Serialize, Deserialize, Debug)]
 pub enum Message {
     /// An echo request. This should elicit an identical reply.
     Echo(String),