From 071dac8a0884740cfe453fbe7962f4fafd003279 Mon Sep 17 00:00:00 2001 From: Ed Komp Date: Tue, 27 Aug 2024 14:28:47 -0500 Subject: [PATCH 01/11] Rust project setup for attestation_asps written in Rust this allows sharing of common crates including those we write to interface with copland includes two asps r_hashfile_id and r_uptime_id --- .gitignore | 3 +- attestation_asps/rust_asps/Cargo.lock | 414 ++++++++++++++++++ attestation_asps/rust_asps/Cargo.toml | 28 ++ .../rust_asps/src/bin/r_hashfile_id.rs | 56 +++ .../rust_asps/src/bin/r_uptime_id.rs | 63 +++ .../rust_asps/src/bin/sample.rs.txt | 82 ++++ attestation_asps/rust_asps/src/lib.rs | 5 + attestation_asps/rust_asps/src/lib/copland.rs | 173 ++++++++ attestation_asps/rust_asps/src/lib/json.rs | 22 + 9 files changed, 845 insertions(+), 1 deletion(-) create mode 100644 attestation_asps/rust_asps/Cargo.lock create mode 100644 attestation_asps/rust_asps/Cargo.toml create mode 100644 attestation_asps/rust_asps/src/bin/r_hashfile_id.rs create mode 100644 attestation_asps/rust_asps/src/bin/r_uptime_id.rs create mode 100644 attestation_asps/rust_asps/src/bin/sample.rs.txt create mode 100644 attestation_asps/rust_asps/src/lib.rs create mode 100644 attestation_asps/rust_asps/src/lib/copland.rs create mode 100644 attestation_asps/rust_asps/src/lib/json.rs diff --git a/.gitignore b/.gitignore index c5e82d7..d7b476e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -bin \ No newline at end of file +bin +!**/src/bin diff --git a/attestation_asps/rust_asps/Cargo.lock b/attestation_asps/rust_asps/Cargo.lock new file mode 100644 index 0000000..e24303b --- /dev/null +++ b/attestation_asps/rust_asps/Cargo.lock @@ -0,0 +1,414 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rust_asps" +version = "0.1.0" +dependencies = [ + "anyhow", + "data-encoding", + "serde", + "serde_json", + "sha2", + "sysinfo", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "serde" +version = "1.0.208" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.208" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "syn" +version = "2.0.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sysinfo" +version = "0.31.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b92e0bdf838cbc1c4c9ba14f9c97a7ec6cdcd1ae66b10e1e42775a25553f45d" +dependencies = [ + "core-foundation-sys", + "libc", + "memchr", + "ntapi", + "rayon", + "windows", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +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 = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result", + "windows-targets", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/attestation_asps/rust_asps/Cargo.toml b/attestation_asps/rust_asps/Cargo.toml new file mode 100644 index 0000000..8279512 --- /dev/null +++ b/attestation_asps/rust_asps/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "rust_asps" +version = "0.1.0" +edition = "2021" + +[lib] +name = "asp_library" +path = "src/lib.rs" + +[[bin]] +name = "r_hashfile_id" +path = "src/bin/r_hashfile_id.rs" +test = false +bench = false + +[[bin]] +name = "r_uptime_id" +path = "src/bin/r_uptime_id.rs" +test = false +bench = false + +[dependencies] +anyhow = "1.0.86" +data-encoding = "2.6.0" +serde = {version = "1.0.208", features = ["derive"]} +serde_json = "1.0.125" +sha2 = "0.10.8" +sysinfo = "0.31.3" diff --git a/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs b/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs new file mode 100644 index 0000000..1f2e536 --- /dev/null +++ b/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs @@ -0,0 +1,56 @@ +use asp_library::copland::*; +use data_encoding::BASE64; +use anyhow::{Context, Result}; +use std::env; + +use sha2::{Sha256, Digest}; + +fn body() -> Result { + + let args: Vec = env::args().collect(); + + if args.len() < 2 { + Err(anyhow::anyhow!("ASPRunRequest not supplied as command line argument")) + } else { + + let json_request = &args[1]; + + let req: ASPRunRequest = serde_json::from_str(json_request)?; + + let args_map = req.ASP_ARGS; + let filename = &args_map.get("filepath").context("filename argument not provided to ASP, hashfile_id")?; + + let bytes = std::fs::read(filename)?; // Vec + + let hash = Sha256::digest(&bytes); + + let hash_string = format!("{:?}", hash); + let hash_b64: String = BASE64.encode(&hash_string.into_bytes()); + + let evidence = RawEv::RawEv(vec![hash_b64]); + + let response = ASPRunResponse { TYPE: "RESPONSE".to_string(), + ACTION: "ASP_RUN".to_string(), + SUCCESS: true, + PAYLOAD: evidence}; + let response_json = serde_json::to_string(&response)?; + Ok (response_json) + } +} + +fn main() -> () { + + let response_json = match body() { + Ok(resp) => resp, + Err(_error) => { + let response = ASPRunResponse { TYPE: "RESPONSE".to_string(), + ACTION: "ASP_RUN".to_string(), + SUCCESS: false, + PAYLOAD: RawEv::RawEv(Vec::new())}; + serde_json::to_string(&response).unwrap_or_else(|error| {panic!("Failed to json.encode failure response: {error:?}");}) + } + }; + + println!("{response_json}"); + () +} diff --git a/attestation_asps/rust_asps/src/bin/r_uptime_id.rs b/attestation_asps/rust_asps/src/bin/r_uptime_id.rs new file mode 100644 index 0000000..1a46a5b --- /dev/null +++ b/attestation_asps/rust_asps/src/bin/r_uptime_id.rs @@ -0,0 +1,63 @@ +// Very simple use of the sysinfo crate. +// Returns seconds since most recent book. + +// The sysinfo crate provides access to a wide range of system information, +// including a variety of dynamic characteristics. + + +use asp_library::copland::*; +use data_encoding::BASE64; +use anyhow::{Result}; +use std::env; + +use sysinfo::System; + +fn body() -> Result { + + let args: Vec = env::args().collect(); + + if args.len() < 2 { + Err(anyhow::anyhow!("ASPRunRequest not supplied as command line argument")) + } else { + + let json_request = &args[1]; + + // decoding the ASPRunRequest just to confirm + // that we are being called as expected, even though + // no information in the request is required for execution. + let _req: ASPRunRequest = serde_json::from_str(json_request)?; + + // This ASP has no arguments. + // let args_map = req.ASP_ARGS; + + // returns seconds since last boot. + let up = System::uptime(); + let up_b64: String = BASE64.encode(&up.to_string().into_bytes()); + + let evidence = RawEv::RawEv(vec![up_b64]); + + let response = ASPRunResponse { TYPE: "RESPONSE".to_string(), + ACTION: "ASP_RUN".to_string(), + SUCCESS: true, + PAYLOAD: evidence}; + + let response_json = serde_json::to_string(&response)?; + Ok (response_json) + } +} +fn main() -> () { + + let response_json = match body() { + Ok(resp) => resp, + Err(_error) => { + let response = ASPRunResponse { TYPE: "RESPONSE".to_string(), + ACTION: "ASP_RUN".to_string(), + SUCCESS: false, + PAYLOAD: RawEv::RawEv(Vec::new())}; + serde_json::to_string(&response).unwrap_or_else(|error| {panic!("Failed to json.encode failure response: {error:?}");}) + } + }; + + println!("{response_json}"); + () +} diff --git a/attestation_asps/rust_asps/src/bin/sample.rs.txt b/attestation_asps/rust_asps/src/bin/sample.rs.txt new file mode 100644 index 0000000..7601fd0 --- /dev/null +++ b/attestation_asps/rust_asps/src/bin/sample.rs.txt @@ -0,0 +1,82 @@ +use asp_library::copland::*; +use data_encoding::BASE64; +use anyhow::{Context, Result}; +use std::env; + +// Include crates used to perform measurement +use sha2::{Sha256, Digest}; + +// Define functions used to perform measurement (optional) + + +fn body() -> Result { + +// Step 1. Parse the single command line argument, +// which must be a string containing a JSON encoded ASPRunRequest +// No specidialization required. + + let args: Vec = env::args().collect(); + + if args.len() < 2 { + Err(anyhow::anyhow!("ASPRunRequest not supplied as command line argument")) + } else { + + let json_request = &args[1]; + let req: ASPRunRequest = serde_json::from_str(json_request)?; + +// Step 2. Extract the argument(s) required by this ASP, +// from the ASPRunRequest.ASP_ARGS field + + let args_map = req.ASP_ARGS; + let filename = &args_map.get("filepath").context("filename argument not provided to ASP, hashfile_id")?; +// Step 3. Do the measurement for this ASP + + let bytes = std::fs::read(filename)?; // Vec + + let hash = Sha256::digest(&bytes); + +// Step 4. Place the measured value into an Evidence structure +// which is a Vector. +// The string must be BASE64 encoded + + let hash_string = format!("{:?}", hash); + let hash_b64: String = BASE64.encode(&hash_string.into_bytes()); + + let evidence = RawEv::RawEv(vec![hash_b64]); + +// Step 5. Construct the ASPRunResponse with this evidence, and +// generate a JSON encoding of this structure. +// No specidialization required. + + let response = ASPRunResponse { TYPE: "RESPONSE".to_string(), + ACTION: "ASP_RUN".to_string(), + SUCCESS: true, + PAYLOAD: evidence}; + let response_json = serde_json::to_string(&response)?; + Ok (response_json) + } +} + +fn main() -> () { + +// Step 6. Determine any error was generated performing the measurement. +// If an error occurred, create an ASPRunResponse with "SUCCESS: false" +// No specidialization required. + let response_json = match body() { + Ok(resp) => resp, + Err(_error) => { + let response = ASPRunResponse { TYPE: "RESPONSE".to_string(), + ACTION: "ASP_RUN".to_string(), + SUCCESS: false, + PAYLOAD: RawEv::RawEv(Vec::new())}; + serde_json::to_string(&response).unwrap_or_else(|error| {panic!("Failed to json.encode failure response: {error:?}");}) + } + }; + +// Step 7. Print the JSON encoded ASPRunResponse to stdout. +// The caller will capture stdout to receive the response from this ASP. +// No specidialization required. + + println!("{response_json}"); + () +} diff --git a/attestation_asps/rust_asps/src/lib.rs b/attestation_asps/rust_asps/src/lib.rs new file mode 100644 index 0000000..620cf8d --- /dev/null +++ b/attestation_asps/rust_asps/src/lib.rs @@ -0,0 +1,5 @@ +#[path = "lib/copland.rs"] +pub mod copland; + +#[path = "lib/json.rs"] +pub mod json; diff --git a/attestation_asps/rust_asps/src/lib/copland.rs b/attestation_asps/rust_asps/src/lib/copland.rs new file mode 100644 index 0000000..d6dd8f9 --- /dev/null +++ b/attestation_asps/rust_asps/src/lib/copland.rs @@ -0,0 +1,173 @@ +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +use std::collections::HashMap; +use serde::{Deserialize, Serialize}; + +pub type Plc = String; +type N_ID = String; +pub type ASP_ID = String; +pub type TARG_ID = String; +pub type ASP_ARGS = HashMap; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct ASP_PARAMS { + pub ASP_ID: ASP_ID, + pub ASP_ARGS: ASP_ARGS, + pub ASP_PLC: Plc, + pub ASP_TARG_ID: TARG_ID +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(tag = "FWD_CONSTRUCTOR", content = "FWD_BODY")] +pub enum FWD { + COMP, + ENCR, + EXTD(String), + KILL, + KEEP +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(tag = "EVIDENCE_CONSTRUCTOR", content = "EVIDENCE_BODY")] +pub enum Evidence { + mt, + nn(N_ID), + uu(Plc, FWD, ASP_PARAMS, Box), + ss(Box, Box) +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub enum SP { + ALL, + NONE +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(tag = "ASP_CONSTRUCTOR", content = "ASP_BODY")] +pub enum ASP { + NULL, + CPY, + ASPC(SP, FWD, ASP_PARAMS), + SIG, + HSH, + ENC(Plc) +} + + +/* +impl Serialize for ASP { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match *self { + ASP::NULL => serializer.serialize_unit_variant("ASP", 0, "NULL"), + ASP::CPY => serializer.serialize_unit_variant("ASP", 1, "CPY"), + _ => serializer.serialize_unit_variant("ASP", 0, "NULL") + } + } + } + + +impl Deserialize for ASP { + +} +*/ + +type Split = (SP, SP); + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(tag = "TERM_CONSTRUCTOR", content = "TERM_BODY")] +pub enum Term { + asp(ASP), + att(Plc, Box), + lseq(Box, Box), + bseq(Split, Box, Box), + bpar(Split, Box, Box) +} + +//type BS = bytestring::ByteString; + +type RawEvT = Vec; //Vec; + +#[derive(Serialize, Deserialize, Debug)] +//#[serde(untagged)] +//#[serde(tag = "RawEv_CONSTRUCTOR", content = "RawEv_BODY")] +pub enum RawEv { + RawEv(RawEvT) +} + +#[derive(Serialize, Deserialize, Debug)] +#[serde(tag = "AppResultC_CONSTRUCTOR", content = "AppResultC_BODY")] +pub enum AppResultC { + mtc_app, + nnc_app(N_ID, String), + ggc_app(Plc, ASP_PARAMS, RawEv, Box), + hhc_app(Plc, ASP_PARAMS, String, Box), + eecc_app(Plc, ASP_PARAMS, String, Box), + ssc_app(Box, Box) +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Attestation_Session { + pub Session_Plc: Plc, + pub Plc_Mapping: HashMap, + pub PubKey_Mapping: HashMap +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ProtocolRunRequest { + pub TYPE: String, + pub ACTION: String, + pub REQ_PLC: Plc, + pub TERM: Term, + pub RAWEV: RawEv, + pub ATTESTATION_SESSION: Attestation_Session +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ProtocolRunResponse { + pub TYPE: String, + pub ACTION: String, + pub SUCCESS: bool, + pub PAYLOAD: RawEv +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ProtocolAppraiseRequest { + pub TYPE: String, + pub ACTION: String, + pub ATTESTATION_SESSION: Attestation_Session, + pub TERM: Term, + pub REQ_PLC: Plc, + pub EVIDENCE: Evidence, + pub RAWEV: RawEv +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ProtocolAppraiseResponse { + pub TYPE: String, + pub ACTION: String, + pub SUCCESS: bool, + pub PAYLOAD: AppResultC +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ASPRunRequest { + pub TYPE: String, + pub ACTION: String, + pub ASP_ID: String, + pub ASP_ARGS: ASP_ARGS, + pub ASP_PLC: Plc, + pub ASP_TARG_ID: TARG_ID, + pub RAWEV: RawEv +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct ASPRunResponse { + pub TYPE: String, + pub ACTION: String, + pub SUCCESS: bool, + pub PAYLOAD: RawEv +} diff --git a/attestation_asps/rust_asps/src/lib/json.rs b/attestation_asps/rust_asps/src/lib/json.rs new file mode 100644 index 0000000..503be47 --- /dev/null +++ b/attestation_asps/rust_asps/src/lib/json.rs @@ -0,0 +1,22 @@ + +use serde::*; + +pub fn encode_gen(v: &T) -> std::io::Result + where T: ?Sized + Serialize + { + let maybe_string = serde_json::to_string(v); + match maybe_string { + Err (e) => {panic!("Error Encoding val: {e:?}")} + Ok (s) => Ok (s) + } + } + +pub fn decode_gen<'a, T>(s: &'a str) -> std::io::Result + where T: de::Deserialize<'a> + { + let maybe_val = serde_json::from_str(s); + match maybe_val { + Err (e) => {panic!("Error Decoding val: {e:?}")} + Ok (v) => Ok (v) + } + } From 11a2d9789104d124cd081d2b1a6addff502e7530 Mon Sep 17 00:00:00 2001 From: Ed Komp Date: Wed, 28 Aug 2024 09:40:22 -0500 Subject: [PATCH 02/11] git ignore target/ directories that Rust projects use for derived files. --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index d7b476e..c3a2923 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ bin +# in Rust projects, /src/bin/ holds source code !**/src/bin + +# in Rust projects, this directory contains only derived files. +target From 3d8460776557b2f07c65618f375062a1d314acdb Mon Sep 17 00:00:00 2001 From: Ed Komp Date: Thu, 29 Aug 2024 09:49:48 -0500 Subject: [PATCH 03/11] Makefile for Rust asps --- attestation_asps/rust_asps/Makefile | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 attestation_asps/rust_asps/Makefile diff --git a/attestation_asps/rust_asps/Makefile b/attestation_asps/rust_asps/Makefile new file mode 100644 index 0000000..8f168ab --- /dev/null +++ b/attestation_asps/rust_asps/Makefile @@ -0,0 +1,15 @@ +SRCDIR := src/bin/ +BINDIR := target/debug/ +DEST_BINDIR := ../bin/ + +SOURCES := $(wildcard $(SRCDIR)*.rs) +BASE_NAMES := $(patsubst src/bin/%,%, $(patsubst %.rs,%, $(SOURCES))) + +all: + for asp in $(BASE_NAMES); do \ + cargo build --bin $$asp; \ + cp $(BINDIR)/$$asp $(DEST_BINDIR); \ + done + +clean: + cargo clean From 72f87f5bfe0177c619a4d3943df65f49ae69fc98 Mon Sep 17 00:00:00 2001 From: Ed Komp Date: Tue, 3 Sep 2024 13:05:54 -0500 Subject: [PATCH 04/11] use an external library (rust_am_lib) instead of a local library for copland package --- attestation_asps/rust_asps/Cargo.toml | 8 +- .../rust_asps/src/bin/r_hashfile_id.rs | 2 +- .../rust_asps/src/bin/r_uptime_id.rs | 2 +- attestation_asps/rust_asps/src/lib.rs | 5 - attestation_asps/rust_asps/src/lib/copland.rs | 173 ------------------ attestation_asps/rust_asps/src/lib/json.rs | 22 --- 6 files changed, 4 insertions(+), 208 deletions(-) delete mode 100644 attestation_asps/rust_asps/src/lib.rs delete mode 100644 attestation_asps/rust_asps/src/lib/copland.rs delete mode 100644 attestation_asps/rust_asps/src/lib/json.rs diff --git a/attestation_asps/rust_asps/Cargo.toml b/attestation_asps/rust_asps/Cargo.toml index 8279512..536d556 100644 --- a/attestation_asps/rust_asps/Cargo.toml +++ b/attestation_asps/rust_asps/Cargo.toml @@ -3,10 +3,6 @@ name = "rust_asps" version = "0.1.0" edition = "2021" -[lib] -name = "asp_library" -path = "src/lib.rs" - [[bin]] name = "r_hashfile_id" path = "src/bin/r_hashfile_id.rs" @@ -20,9 +16,9 @@ test = false bench = false [dependencies] +rust_am_lib = { git = "https://github.com/ku-sldg/rust-am-lib.git" } +serde_json = "1.0.125" anyhow = "1.0.86" data-encoding = "2.6.0" -serde = {version = "1.0.208", features = ["derive"]} -serde_json = "1.0.125" sha2 = "0.10.8" sysinfo = "0.31.3" diff --git a/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs b/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs index 1f2e536..9d55b4c 100644 --- a/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs +++ b/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs @@ -1,4 +1,4 @@ -use asp_library::copland::*; +use rust_am_lib::copland::*; use data_encoding::BASE64; use anyhow::{Context, Result}; use std::env; diff --git a/attestation_asps/rust_asps/src/bin/r_uptime_id.rs b/attestation_asps/rust_asps/src/bin/r_uptime_id.rs index 1a46a5b..b84419e 100644 --- a/attestation_asps/rust_asps/src/bin/r_uptime_id.rs +++ b/attestation_asps/rust_asps/src/bin/r_uptime_id.rs @@ -5,7 +5,7 @@ // including a variety of dynamic characteristics. -use asp_library::copland::*; +use rust_am_lib::copland::*; use data_encoding::BASE64; use anyhow::{Result}; use std::env; diff --git a/attestation_asps/rust_asps/src/lib.rs b/attestation_asps/rust_asps/src/lib.rs deleted file mode 100644 index 620cf8d..0000000 --- a/attestation_asps/rust_asps/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[path = "lib/copland.rs"] -pub mod copland; - -#[path = "lib/json.rs"] -pub mod json; diff --git a/attestation_asps/rust_asps/src/lib/copland.rs b/attestation_asps/rust_asps/src/lib/copland.rs deleted file mode 100644 index d6dd8f9..0000000 --- a/attestation_asps/rust_asps/src/lib/copland.rs +++ /dev/null @@ -1,173 +0,0 @@ -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] - -use std::collections::HashMap; -use serde::{Deserialize, Serialize}; - -pub type Plc = String; -type N_ID = String; -pub type ASP_ID = String; -pub type TARG_ID = String; -pub type ASP_ARGS = HashMap; - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct ASP_PARAMS { - pub ASP_ID: ASP_ID, - pub ASP_ARGS: ASP_ARGS, - pub ASP_PLC: Plc, - pub ASP_TARG_ID: TARG_ID -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -#[serde(tag = "FWD_CONSTRUCTOR", content = "FWD_BODY")] -pub enum FWD { - COMP, - ENCR, - EXTD(String), - KILL, - KEEP -} - -#[derive(Serialize, Deserialize, Debug)] -#[serde(tag = "EVIDENCE_CONSTRUCTOR", content = "EVIDENCE_BODY")] -pub enum Evidence { - mt, - nn(N_ID), - uu(Plc, FWD, ASP_PARAMS, Box), - ss(Box, Box) -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub enum SP { - ALL, - NONE -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -#[serde(tag = "ASP_CONSTRUCTOR", content = "ASP_BODY")] -pub enum ASP { - NULL, - CPY, - ASPC(SP, FWD, ASP_PARAMS), - SIG, - HSH, - ENC(Plc) -} - - -/* -impl Serialize for ASP { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - match *self { - ASP::NULL => serializer.serialize_unit_variant("ASP", 0, "NULL"), - ASP::CPY => serializer.serialize_unit_variant("ASP", 1, "CPY"), - _ => serializer.serialize_unit_variant("ASP", 0, "NULL") - } - } - } - - -impl Deserialize for ASP { - -} -*/ - -type Split = (SP, SP); - -#[derive(Serialize, Deserialize, Debug, Clone)] -#[serde(tag = "TERM_CONSTRUCTOR", content = "TERM_BODY")] -pub enum Term { - asp(ASP), - att(Plc, Box), - lseq(Box, Box), - bseq(Split, Box, Box), - bpar(Split, Box, Box) -} - -//type BS = bytestring::ByteString; - -type RawEvT = Vec; //Vec; - -#[derive(Serialize, Deserialize, Debug)] -//#[serde(untagged)] -//#[serde(tag = "RawEv_CONSTRUCTOR", content = "RawEv_BODY")] -pub enum RawEv { - RawEv(RawEvT) -} - -#[derive(Serialize, Deserialize, Debug)] -#[serde(tag = "AppResultC_CONSTRUCTOR", content = "AppResultC_BODY")] -pub enum AppResultC { - mtc_app, - nnc_app(N_ID, String), - ggc_app(Plc, ASP_PARAMS, RawEv, Box), - hhc_app(Plc, ASP_PARAMS, String, Box), - eecc_app(Plc, ASP_PARAMS, String, Box), - ssc_app(Box, Box) -} - -#[derive(Serialize, Deserialize, Debug, Clone)] -pub struct Attestation_Session { - pub Session_Plc: Plc, - pub Plc_Mapping: HashMap, - pub PubKey_Mapping: HashMap -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct ProtocolRunRequest { - pub TYPE: String, - pub ACTION: String, - pub REQ_PLC: Plc, - pub TERM: Term, - pub RAWEV: RawEv, - pub ATTESTATION_SESSION: Attestation_Session -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct ProtocolRunResponse { - pub TYPE: String, - pub ACTION: String, - pub SUCCESS: bool, - pub PAYLOAD: RawEv -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct ProtocolAppraiseRequest { - pub TYPE: String, - pub ACTION: String, - pub ATTESTATION_SESSION: Attestation_Session, - pub TERM: Term, - pub REQ_PLC: Plc, - pub EVIDENCE: Evidence, - pub RAWEV: RawEv -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct ProtocolAppraiseResponse { - pub TYPE: String, - pub ACTION: String, - pub SUCCESS: bool, - pub PAYLOAD: AppResultC -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct ASPRunRequest { - pub TYPE: String, - pub ACTION: String, - pub ASP_ID: String, - pub ASP_ARGS: ASP_ARGS, - pub ASP_PLC: Plc, - pub ASP_TARG_ID: TARG_ID, - pub RAWEV: RawEv -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct ASPRunResponse { - pub TYPE: String, - pub ACTION: String, - pub SUCCESS: bool, - pub PAYLOAD: RawEv -} diff --git a/attestation_asps/rust_asps/src/lib/json.rs b/attestation_asps/rust_asps/src/lib/json.rs deleted file mode 100644 index 503be47..0000000 --- a/attestation_asps/rust_asps/src/lib/json.rs +++ /dev/null @@ -1,22 +0,0 @@ - -use serde::*; - -pub fn encode_gen(v: &T) -> std::io::Result - where T: ?Sized + Serialize - { - let maybe_string = serde_json::to_string(v); - match maybe_string { - Err (e) => {panic!("Error Encoding val: {e:?}")} - Ok (s) => Ok (s) - } - } - -pub fn decode_gen<'a, T>(s: &'a str) -> std::io::Result - where T: de::Deserialize<'a> - { - let maybe_val = serde_json::from_str(s); - match maybe_val { - Err (e) => {panic!("Error Decoding val: {e:?}")} - Ok (v) => Ok (v) - } - } From 2340bb48adec18bda46b978f1eb734f77ae176c3 Mon Sep 17 00:00:00 2001 From: Ed Komp Date: Thu, 19 Sep 2024 16:12:54 -0500 Subject: [PATCH 05/11] include a template for Rust ASPs, and update examples to follow the template --- attestation_asps/rust_asps/Cargo.toml | 4 +- .../rust_asps/src/bin/TEMPLATE.rs.txt | 92 +++++++++++++++++++ .../rust_asps/src/bin/r_hashfile_id.rs | 72 ++++++++++----- .../rust_asps/src/bin/r_uptime_id.rs | 47 +++++----- .../rust_asps/src/bin/sample.rs.txt | 82 ----------------- 5 files changed, 163 insertions(+), 134 deletions(-) create mode 100644 attestation_asps/rust_asps/src/bin/TEMPLATE.rs.txt delete mode 100644 attestation_asps/rust_asps/src/bin/sample.rs.txt diff --git a/attestation_asps/rust_asps/Cargo.toml b/attestation_asps/rust_asps/Cargo.toml index 536d556..7eba7ab 100644 --- a/attestation_asps/rust_asps/Cargo.toml +++ b/attestation_asps/rust_asps/Cargo.toml @@ -16,9 +16,9 @@ test = false bench = false [dependencies] -rust_am_lib = { git = "https://github.com/ku-sldg/rust-am-lib.git" } +rust_am_lib = { git = "https://github.com/ku-sldg/rust-am-lib.git", veersion = "0.1.1"} serde_json = "1.0.125" anyhow = "1.0.86" -data-encoding = "2.6.0" +base64 = "0.13" sha2 = "0.10.8" sysinfo = "0.31.3" diff --git a/attestation_asps/rust_asps/src/bin/TEMPLATE.rs.txt b/attestation_asps/rust_asps/src/bin/TEMPLATE.rs.txt new file mode 100644 index 0000000..e0e6df7 --- /dev/null +++ b/attestation_asps/rust_asps/src/bin/TEMPLATE.rs.txt @@ -0,0 +1,92 @@ +// TEMPLATE.txt +// General structure for ASP's written in rust + +// Common Packages +use rust_am_lib::copland::*; +use base64; +use anyhow::{Context, Result}; +use std::env; + +// Packages required to perform specific ASP action. +// e.g. +use sha2::{Sha256, Digest}; + +// function where the work of the ASP is performed. +// May signal an error which will be handled in main. +fn body() -> Result { + + // For every ASP, an ASPRunRequest appears as the single command-line argument + let args: Vec = env::args().collect(); + + if args.len() < 2 { + return Err(anyhow::anyhow!("ASPRunRequest not supplied as command line argument")); + } + + let json_request = &args[1]; + // May fail. If so, return an Err Result + let req: ASPRunRequest = serde_json::from_str(json_request)?; + + // Code for specific for this ASP. + // This example computes the HASH of the file named in an argument for the ASP. + // May return an Err Result, which will be captured in main. + let args_map = req.ASP_ARGS; + let filename = &args_map.get("filepath").context("filename argument not provided to ASP, hashfile_id")?; + + /* Code sample for accessing input evidence within the ASP. + + // Suppose the filename is to be extracted from evidence, instead of an ASP argument + + let evidence_in = match req.RAWEV {RawEv::RawEv(x) => x,}; + + let latest_evidence = &evidence_in[evidence_in.len() - 1]; + // Evidence is always base64 encoded, so decode this + let filename_bytes = base64::decode(latest_evidence)?; + let filename = String::from_utf8(filename_bytes)?; + */ + + let bytes = std::fs::read(filename)?; // Vec + + let hash = Sha256::digest(&bytes); + + // End of code specific for this ASP. + + // Common code to bundle computed value. + // Step 1: + // The return value for an ASP, must be + // encoded in BASE64, and converted to ascii for JSON transmission + let hash_b64: String = base64::encode(&hash); + + // Step 2: + // wrap the value as Evidence + let evidence = RawEv::RawEv(vec![hash_b64]); + + // Step 3: + // Construct the ASPRunResponse with this evidence. + let response = successfulASPRunResponse (evidence); + let response_json = serde_json::to_string(&response)?; + Ok (response_json) +} + +// Main simply invokes the body() funciton above, +// and checks for Err Result. +// If it detects an Err Result, this ASP will return +// an ASPRunResponse with SUCCESS = false, o/w uses +// ASPRunResponse returned from body() + +fn main() -> () { + + let response_json = match body() { + Ok(resp) => resp, + Err(_error) => { + let response = failureASPRunResponse (_error.to_string()); + // If an error occurs converting the failure response to JSON + // there is nothing else to do but panic. + // This should never happen. + serde_json::to_string(&response).unwrap_or_else(|error| {panic!("Failed to json.encode failure response: {error:?}");}) + } + }; + // The ASP output (ASPRunRequest) is written to stdout. + // The caller will capture stdout to receive the response from this ASP. + println!("{response_json}"); + () +} diff --git a/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs b/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs index 9d55b4c..b1dcf5a 100644 --- a/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs +++ b/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs @@ -1,56 +1,80 @@ +// TEMPLATE.txt +// General structure for ASP's written in rust + +// Common Packages use rust_am_lib::copland::*; -use data_encoding::BASE64; +use base64; use anyhow::{Context, Result}; use std::env; +// Packages required to perform specific ASP action. +// e.g. use sha2::{Sha256, Digest}; +// function where the work of the ASP is performed. +// May signal an error which will be handled in main. fn body() -> Result { + // For every ASP, an ASPRunRequest appears as the single command-line argument let args: Vec = env::args().collect(); if args.len() < 2 { - Err(anyhow::anyhow!("ASPRunRequest not supplied as command line argument")) - } else { + return Err(anyhow::anyhow!("ASPRunRequest not supplied as command line argument")); + } - let json_request = &args[1]; + let json_request = &args[1]; + // May fail. If so, return an Err Result + let req: ASPRunRequest = serde_json::from_str(json_request)?; - let req: ASPRunRequest = serde_json::from_str(json_request)?; + // Code for specific for this ASP. + // This example computes the HASH of the file named in an argument for the ASP. + // May return an Err Result, which will be captured in main. + let args_map = req.ASP_ARGS; + let filename = &args_map.get("filepath").context("filename argument not provided to ASP, hashfile_id")?; - let args_map = req.ASP_ARGS; - let filename = &args_map.get("filepath").context("filename argument not provided to ASP, hashfile_id")?; + let bytes = std::fs::read(filename)?; // Vec - let bytes = std::fs::read(filename)?; // Vec + let hash = Sha256::digest(&bytes); - let hash = Sha256::digest(&bytes); + // End of code specific for this ASP. - let hash_string = format!("{:?}", hash); - let hash_b64: String = BASE64.encode(&hash_string.into_bytes()); + // Common code to bundle computed value. + // Step 1: + // The return value for an ASP, must be + // encoded in BASE64, and converted to ascii for JSON transmission + let hash_b64: String = base64::encode(&hash); - let evidence = RawEv::RawEv(vec![hash_b64]); + // Step 2: + // wrap the value as Evidence + let evidence = RawEv::RawEv(vec![hash_b64]); - let response = ASPRunResponse { TYPE: "RESPONSE".to_string(), - ACTION: "ASP_RUN".to_string(), - SUCCESS: true, - PAYLOAD: evidence}; - let response_json = serde_json::to_string(&response)?; - Ok (response_json) - } + // Step 3: + // Construct the ASPRunResponse with this evidence. + let response = successfulASPRunResponse (evidence); + let response_json = serde_json::to_string(&response)?; + Ok (response_json) } +// Main simply invokes the body() funciton above, +// and checks for Err Result. +// If it detects an Err Result, this ASP will return +// an ASPRunResponse with SUCCESS = false, o/w uses +// ASPRunResponse returned from body() + fn main() -> () { let response_json = match body() { Ok(resp) => resp, Err(_error) => { - let response = ASPRunResponse { TYPE: "RESPONSE".to_string(), - ACTION: "ASP_RUN".to_string(), - SUCCESS: false, - PAYLOAD: RawEv::RawEv(Vec::new())}; + let response = failureASPRunResponse (_error.to_string()); + // If an error occurs converting the failure response to JSON + // there is nothing else to do but panic. + // This should never happen. serde_json::to_string(&response).unwrap_or_else(|error| {panic!("Failed to json.encode failure response: {error:?}");}) } }; - + // The ASP output (ASPRunRequest) is written to stdout. + // The caller will capture stdout to receive the response from this ASP. println!("{response_json}"); () } diff --git a/attestation_asps/rust_asps/src/bin/r_uptime_id.rs b/attestation_asps/rust_asps/src/bin/r_uptime_id.rs index b84419e..3205c55 100644 --- a/attestation_asps/rust_asps/src/bin/r_uptime_id.rs +++ b/attestation_asps/rust_asps/src/bin/r_uptime_id.rs @@ -6,7 +6,7 @@ use rust_am_lib::copland::*; -use data_encoding::BASE64; +use base64; use anyhow::{Result}; use std::env; @@ -17,47 +17,42 @@ fn body() -> Result { let args: Vec = env::args().collect(); if args.len() < 2 { - Err(anyhow::anyhow!("ASPRunRequest not supplied as command line argument")) - } else { - - let json_request = &args[1]; + return Err(anyhow::anyhow!("ASPRunRequest not supplied as command line argument")); + } + let json_request = &args[1]; - // decoding the ASPRunRequest just to confirm - // that we are being called as expected, even though - // no information in the request is required for execution. - let _req: ASPRunRequest = serde_json::from_str(json_request)?; + // decoding the ASPRunRequest just to confirm + // that we are being called as expected, even though + // no information in the request is required for execution. + let _req: ASPRunRequest = serde_json::from_str(json_request)?; - // This ASP has no arguments. - // let args_map = req.ASP_ARGS; + // This ASP has no arguments. + // let args_map = req.ASP_ARGS; - // returns seconds since last boot. - let up = System::uptime(); - let up_b64: String = BASE64.encode(&up.to_string().into_bytes()); + // returns seconds since last boot. + let up = System::uptime(); + let up_b64: String = base64::encode(&up.to_be_bytes()); - let evidence = RawEv::RawEv(vec![up_b64]); + let evidence = RawEv::RawEv(vec![up_b64]); - let response = ASPRunResponse { TYPE: "RESPONSE".to_string(), - ACTION: "ASP_RUN".to_string(), - SUCCESS: true, - PAYLOAD: evidence}; + let response = successfulASPRunResponse (evidence); - let response_json = serde_json::to_string(&response)?; - Ok (response_json) - } + let response_json = serde_json::to_string(&response)?; + Ok (response_json) } + fn main() -> () { let response_json = match body() { Ok(resp) => resp, Err(_error) => { - let response = ASPRunResponse { TYPE: "RESPONSE".to_string(), - ACTION: "ASP_RUN".to_string(), - SUCCESS: false, - PAYLOAD: RawEv::RawEv(Vec::new())}; + let response = failureASPRunResponse (_error.to_string()); serde_json::to_string(&response).unwrap_or_else(|error| {panic!("Failed to json.encode failure response: {error:?}");}) } }; + // The ASP output (ASPRunRequest) is written to stdout. + // The caller will capture stdout to receive the response from this ASP. println!("{response_json}"); () } diff --git a/attestation_asps/rust_asps/src/bin/sample.rs.txt b/attestation_asps/rust_asps/src/bin/sample.rs.txt deleted file mode 100644 index 7601fd0..0000000 --- a/attestation_asps/rust_asps/src/bin/sample.rs.txt +++ /dev/null @@ -1,82 +0,0 @@ -use asp_library::copland::*; -use data_encoding::BASE64; -use anyhow::{Context, Result}; -use std::env; - -// Include crates used to perform measurement -use sha2::{Sha256, Digest}; - -// Define functions used to perform measurement (optional) - - -fn body() -> Result { - -// Step 1. Parse the single command line argument, -// which must be a string containing a JSON encoded ASPRunRequest -// No specidialization required. - - let args: Vec = env::args().collect(); - - if args.len() < 2 { - Err(anyhow::anyhow!("ASPRunRequest not supplied as command line argument")) - } else { - - let json_request = &args[1]; - let req: ASPRunRequest = serde_json::from_str(json_request)?; - -// Step 2. Extract the argument(s) required by this ASP, -// from the ASPRunRequest.ASP_ARGS field - - let args_map = req.ASP_ARGS; - let filename = &args_map.get("filepath").context("filename argument not provided to ASP, hashfile_id")?; -// Step 3. Do the measurement for this ASP - - let bytes = std::fs::read(filename)?; // Vec - - let hash = Sha256::digest(&bytes); - -// Step 4. Place the measured value into an Evidence structure -// which is a Vector. -// The string must be BASE64 encoded - - let hash_string = format!("{:?}", hash); - let hash_b64: String = BASE64.encode(&hash_string.into_bytes()); - - let evidence = RawEv::RawEv(vec![hash_b64]); - -// Step 5. Construct the ASPRunResponse with this evidence, and -// generate a JSON encoding of this structure. -// No specidialization required. - - let response = ASPRunResponse { TYPE: "RESPONSE".to_string(), - ACTION: "ASP_RUN".to_string(), - SUCCESS: true, - PAYLOAD: evidence}; - let response_json = serde_json::to_string(&response)?; - Ok (response_json) - } -} - -fn main() -> () { - -// Step 6. Determine any error was generated performing the measurement. -// If an error occurred, create an ASPRunResponse with "SUCCESS: false" -// No specidialization required. - let response_json = match body() { - Ok(resp) => resp, - Err(_error) => { - let response = ASPRunResponse { TYPE: "RESPONSE".to_string(), - ACTION: "ASP_RUN".to_string(), - SUCCESS: false, - PAYLOAD: RawEv::RawEv(Vec::new())}; - serde_json::to_string(&response).unwrap_or_else(|error| {panic!("Failed to json.encode failure response: {error:?}");}) - } - }; - -// Step 7. Print the JSON encoded ASPRunResponse to stdout. -// The caller will capture stdout to receive the response from this ASP. -// No specidialization required. - - println!("{response_json}"); - () -} From 9ec33e345eef672e8d8c8f713c8d5c1e175ad594 Mon Sep 17 00:00:00 2001 From: Ed Komp Date: Mon, 23 Sep 2024 12:41:59 -0500 Subject: [PATCH 06/11] implemented code changes suggested by clippy --- attestation_asps/rust_asps/src/bin/r_hashfile_id.rs | 6 ++---- attestation_asps/rust_asps/src/bin/r_uptime_id.rs | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs b/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs index b1dcf5a..525fdaf 100644 --- a/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs +++ b/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs @@ -3,7 +3,6 @@ // Common Packages use rust_am_lib::copland::*; -use base64; use anyhow::{Context, Result}; use std::env; @@ -42,7 +41,7 @@ fn body() -> Result { // Step 1: // The return value for an ASP, must be // encoded in BASE64, and converted to ascii for JSON transmission - let hash_b64: String = base64::encode(&hash); + let hash_b64: String = base64::encode(hash); // Step 2: // wrap the value as Evidence @@ -61,7 +60,7 @@ fn body() -> Result { // an ASPRunResponse with SUCCESS = false, o/w uses // ASPRunResponse returned from body() -fn main() -> () { +fn main() { let response_json = match body() { Ok(resp) => resp, @@ -76,5 +75,4 @@ fn main() -> () { // The ASP output (ASPRunRequest) is written to stdout. // The caller will capture stdout to receive the response from this ASP. println!("{response_json}"); - () } diff --git a/attestation_asps/rust_asps/src/bin/r_uptime_id.rs b/attestation_asps/rust_asps/src/bin/r_uptime_id.rs index 3205c55..5210afa 100644 --- a/attestation_asps/rust_asps/src/bin/r_uptime_id.rs +++ b/attestation_asps/rust_asps/src/bin/r_uptime_id.rs @@ -6,7 +6,6 @@ use rust_am_lib::copland::*; -use base64; use anyhow::{Result}; use std::env; @@ -31,7 +30,7 @@ fn body() -> Result { // returns seconds since last boot. let up = System::uptime(); - let up_b64: String = base64::encode(&up.to_be_bytes()); + let up_b64: String = base64::encode(up.to_be_bytes()); let evidence = RawEv::RawEv(vec![up_b64]); @@ -41,7 +40,7 @@ fn body() -> Result { Ok (response_json) } -fn main() -> () { +fn main() { let response_json = match body() { Ok(resp) => resp, @@ -54,5 +53,4 @@ fn main() -> () { // The ASP output (ASPRunRequest) is written to stdout. // The caller will capture stdout to receive the response from this ASP. println!("{response_json}"); - () } From 7b42927cfed85ce1c73ef50ac3e8e398935637a7 Mon Sep 17 00:00:00 2001 From: Ed Komp Date: Mon, 23 Sep 2024 12:45:51 -0500 Subject: [PATCH 07/11] removed Cargo.lock from the repo. --- attestation_asps/rust_asps/Cargo.lock | 414 -------------------------- 1 file changed, 414 deletions(-) delete mode 100644 attestation_asps/rust_asps/Cargo.lock diff --git a/attestation_asps/rust_asps/Cargo.lock b/attestation_asps/rust_asps/Cargo.lock deleted file mode 100644 index e24303b..0000000 --- a/attestation_asps/rust_asps/Cargo.lock +++ /dev/null @@ -1,414 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "anyhow" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "cpufeatures" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51e852e6dc9a5bed1fae92dd2375037bf2b768725bf3be87811edee3249d09ad" -dependencies = [ - "libc", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "data-encoding" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "either" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "libc" -version = "0.2.158" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rayon" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "rust_asps" -version = "0.1.0" -dependencies = [ - "anyhow", - "data-encoding", - "serde", - "serde_json", - "sha2", - "sysinfo", -] - -[[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "serde" -version = "1.0.208" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.208" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.125" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "syn" -version = "2.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sysinfo" -version = "0.31.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b92e0bdf838cbc1c4c9ba14f9c97a7ec6cdcd1ae66b10e1e42775a25553f45d" -dependencies = [ - "core-foundation-sys", - "libc", - "memchr", - "ntapi", - "rayon", - "windows", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -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 = "windows" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" -dependencies = [ - "windows-core", - "windows-targets", -] - -[[package]] -name = "windows-core" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-result", - "windows-targets", -] - -[[package]] -name = "windows-implement" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-interface" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "windows-result" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" From 2e25a5d9bd29329b9b2ef3cb3e868f2cebaea1fc Mon Sep 17 00:00:00 2001 From: Ed Komp Date: Mon, 23 Sep 2024 14:55:18 -0500 Subject: [PATCH 08/11] Example of ASP written in Python --- attestation_asps/python_asps/.gitignore | 3 + attestation_asps/python_asps/Makefile | 20 ++++ attestation_asps/python_asps/TEMPLATE.py.txt | 71 +++++++++++ attestation_asps/python_asps/copland.py | 110 ++++++++++++++++++ attestation_asps/python_asps/p_hashfile_id.py | 51 ++++++++ 5 files changed, 255 insertions(+) create mode 100644 attestation_asps/python_asps/.gitignore create mode 100644 attestation_asps/python_asps/Makefile create mode 100644 attestation_asps/python_asps/TEMPLATE.py.txt create mode 100644 attestation_asps/python_asps/copland.py create mode 100644 attestation_asps/python_asps/p_hashfile_id.py diff --git a/attestation_asps/python_asps/.gitignore b/attestation_asps/python_asps/.gitignore new file mode 100644 index 0000000..f584da3 --- /dev/null +++ b/attestation_asps/python_asps/.gitignore @@ -0,0 +1,3 @@ +*.spec +build/ +dist/ diff --git a/attestation_asps/python_asps/Makefile b/attestation_asps/python_asps/Makefile new file mode 100644 index 0000000..7f462fa --- /dev/null +++ b/attestation_asps/python_asps/Makefile @@ -0,0 +1,20 @@ +# Expects that the Python package, pyinstaller, has been installed, +# and is in the search path. +# To install: +# python3 -m pip install pyinstaller + +SRCDIR := ./ +BINDIR := dist/ +DEST_BINDIR := ../bin/ + +SOURCE := p_hashfile_id.py +AUX_FILES := copland.py +EXE_NAME := $(patsubst %.py,%, $(SOURCE)) + +all: $(SOURCE) $(AUX_FILES) + pyinstaller $(SOURCE) --onefile + cp $(BINDIR)/$(EXE_NAME) $(DEST_BINDIR) + +clean: + rm -rf $(BINDIR) + rm -rf build/ diff --git a/attestation_asps/python_asps/TEMPLATE.py.txt b/attestation_asps/python_asps/TEMPLATE.py.txt new file mode 100644 index 0000000..3560899 --- /dev/null +++ b/attestation_asps/python_asps/TEMPLATE.py.txt @@ -0,0 +1,71 @@ +## TEMPLATE.txt +## General structure for ASP's written in rust + +import sys +import json +import hashlib +import binascii +import base64 + +import copland + +## function where the work of the ASP is performed. +## May raise exception(s) which will be handled in main. + +def body(): + + # For every ASP, an ASPRunRequest appears as the single command-line argument + numargs = len(sys.argv) + if (numargs == 1): + raise Exception("no ASPRunRequest provided to p_hashfile_id") + json_req = sys.argv[1] + request = json.loads(json_req, object_hook=copland.ASPRunRequest.from_json) + + # Code for specific for this ASP. + # This example computes the HASH of the file named in an argument for the ASP. + # May raise an exception, which will be captured in main. + + asp_args = request.ASP_ARGS + filename = asp_args['filepath'] + + with open(filename,"rb") as f: + bytes = f.read() + + hash_string = hashlib.sha256(bytes).hexdigest() + # evidence as bytes + hash_bytes = hash_string.encode() + + # End of code specific for this ASP. + + # Common code to bundle computed value. + # Step 1: + # The return value for an ASP, must be + # encoded in BASE64, and converted to ascii for JSON transmission + hash_b64 = base64.b64encode(hash_bytes).decode('ascii') + + # Step 2: + # wrap the value as Evidence + evidence = copland.RAWEV([hash_b64]) + + # Step 3: + # Construct the ASPRunResponse with this evidence. + response = copland.successfulASPRunResponse(evidence) + response_json = json.dumps(response, default=lambda o: o.__dict__) + return response_json + +# Main simply invokes the body() function above, +# and checks for exceptions. +# If it detects an exception, this ASP will return +# an ASPRunResponse with SUCCESS = false, o/w uses +# ASPRunResponse returned from body() + +if __name__ == "__main__": + try: + response_json = body() + except BaseException as e: + response = copland.failureASPRunResponse(str(e)) + response_json = json.dumps(response, default=lambda o: o.__dict__) + finally: + # The ASP output (ASPRunRequest) is written to stdout. + # The caller will capture stdout to receive the response from this ASP. + print(response_json) diff --git a/attestation_asps/python_asps/copland.py b/attestation_asps/python_asps/copland.py new file mode 100644 index 0000000..2518c29 --- /dev/null +++ b/attestation_asps/python_asps/copland.py @@ -0,0 +1,110 @@ +class ASP_PARAMS: + def __init__(self, asp_id, asp_args, plc, targ_id): + self.ASP_ID = asp_id + self.ASP_ARGS = asp_args + self.ASP_PLC = asp + self.ASP_TARG_ID = asp_targ_id + +class Attestation_Session: + def __init__(self, session_plc, plc_mapping, pubkey_mapping): + self.Session_Plc = session_plc + self.Plc_Mapping = plc_mapping + self.PubKey_Mapping = pubkey_mapping + +class ProtocolRunRequest: + def __init__(self, type, action, req_plc, term, rawev, attestation_session): + self.TYPE = type + self.ACTION = action + self.REQ_PLC = req_plc + self.TERM = term + self.RAWEV = rawev + self.ATTESTATION_SESSION = attestation_session + +class ProtocolRunResponse: + def __init__(self, type, action, success, payload): + self.TYPE = type + self.ACTION = action + self.SUCCESS = success, + self.PAYLOAD = payload + +class ProtocolAppraiseRequest: + def __init__(self, type, action, attestation_session, term, req_plc, evidence, rawev): + self.TYPE = type, + self.ACTION = action, + self.ATTESTATION_SESSION = attestation_session, + self.TERM = term, + self.REQ_PLC = req_plc, + self.EVIDENCE = evidence, + self.RAWEV: rawev + +class ProtocolAppraiseResponse: + def __init__(self, type, action, success, payload): + self.TYPE = type + self.ACTION = action + self.SUCCESS = success + self.PAYLOAD = payload + +class RAWEV: + def __init__(self, rawev): + self.RawEv = rawev + + @staticmethod + def from_json(dct): + keys = dct.keys() + if len(keys) == 1 and 'RawEv' in keys: + return RAWEV(dct['RawEv']) + else: + return dct + +class ASPRunRequest: + def __init__(self, type, action, asp_id, asp_args, asp_plc, asp_targ_id, rawev): + self.TYPE = type + self.ACTION = action + self.ASP_ID = asp_id + self.ASP_ARGS = asp_args + self.ASP_PLC = asp_plc + self.ASP_TARG_ID = asp_targ_id + self.RAWEV = rawev + + @staticmethod + def from_json(dct): + keys = dct.keys() + if 'TYPE' in keys and 'ACTION' in keys and 'ASP_ID' in keys and 'ASP_ARGS' in keys and 'ASP_PLC' in keys and 'ASP_TARG_ID' in keys and 'RAWEV' in keys: + return ASPRunRequest(dct['TYPE'], dct['ACTION'], dct['ASP_ID'], dct['ASP_ARGS'], dct['ASP_PLC'], dct['ASP_TARG_ID'], dct['RAWEV']) + elif len(keys) == 1 and 'RawEv' in keys: + return RAWEV.from_json(dct) + else: + return dct + +class ASPRunResponse: + def __init__(self, type, action, success, payload): + self.TYPE = type + self.ACTION = action + self.SUCCESS = success + self.PAYLOAD = payload + + @staticmethod + def from_json(dct): + keys = dct.keys() + if 'TYPE' in keys and 'ACTION' in keys and 'SUCCESS' in keys and 'PAYLOAD' in keys: + return ASPRunResponse(dct['TYPE'], dct['ACTION'], dct['SUCCESS'], dct['PAYLOAD']) + elif len(keys) == 1 and 'RawEv' in keys: + return RAWEV.from_json(dct) + else: + return dct + + +def failureASPRunResponse (error_msg): + empty_evidence = RAWEV([]) + response = ASPRunResponse("RESPONSE", + "ASP_RUN", + False, + empty_evidence) + return response + +def successfulASPRunResponse (evidence): + response = ASPRunResponse("RESPONSE", + "ASP_RUN", + True, + evidence) + return response diff --git a/attestation_asps/python_asps/p_hashfile_id.py b/attestation_asps/python_asps/p_hashfile_id.py new file mode 100644 index 0000000..a2611e5 --- /dev/null +++ b/attestation_asps/python_asps/p_hashfile_id.py @@ -0,0 +1,51 @@ +## TEMPLATE.txt +## General structure for ASP's written in rust + +import sys +import json +import hashlib +import binascii +import base64 + +import copland + +## ASP to compute the hash of the filenmae provided in the 'filepath' argument. + +def body(): + + # For every ASP, an ASPRunRequest appears as the single command-line argument + numargs = len(sys.argv) + if (numargs == 1): + raise Exception("no ASPRunRequest provided to p_hashfile_id") + json_req = sys.argv[1] + request = json.loads(json_req, object_hook=copland.ASPRunRequest.from_json) + + + asp_args = request.ASP_ARGS + filename = asp_args['filepath'] + + with open(filename,"rb") as f: + bytes = f.read() + + hash_string = hashlib.sha256(bytes).hexdigest() + # evidence as bytes + hash_bytes = hash_string.encode() + hash_b64 = base64.b64encode(hash_bytes).decode('ascii') + + evidence = copland.RAWEV([hash_b64]) + + response = copland.successfulASPRunResponse(evidence) + response_json = json.dumps(response, default=lambda o: o.__dict__) + return response_json + + +if __name__ == "__main__": + try: + response_json = body() + except BaseException as e: + response = copland.failureASPRunResponse(str(e)) + response_json = json.dumps(response, default=lambda o: o.__dict__) + finally: + # The ASP output (ASPRunRequest) is written to stdout. + # The caller will capture stdout to receive the response from this ASP. + print(response_json) From aa15b06f66b8fb28d228ed6f8ef2ce279b33b03f Mon Sep 17 00:00:00 2001 From: Ed Komp Date: Mon, 23 Sep 2024 14:56:00 -0500 Subject: [PATCH 09/11] corrected spelling error. --- attestation_asps/rust_asps/src/bin/r_hashfile_id.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs b/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs index 525fdaf..67cfa72 100644 --- a/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs +++ b/attestation_asps/rust_asps/src/bin/r_hashfile_id.rs @@ -54,7 +54,7 @@ fn body() -> Result { Ok (response_json) } -// Main simply invokes the body() funciton above, +// Main simply invokes the body() function above, // and checks for Err Result. // If it detects an Err Result, this ASP will return // an ASPRunResponse with SUCCESS = false, o/w uses From 9d68628b369616ff81f5c79ab3e2788b9afeaea3 Mon Sep 17 00:00:00 2001 From: Ed Komp Date: Wed, 16 Oct 2024 13:37:15 -0500 Subject: [PATCH 10/11] Rust ASP to read file and place contents in Evidence --- .../rust_asps/src/bin/r_readfile_id.rs | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 attestation_asps/rust_asps/src/bin/r_readfile_id.rs diff --git a/attestation_asps/rust_asps/src/bin/r_readfile_id.rs b/attestation_asps/rust_asps/src/bin/r_readfile_id.rs new file mode 100644 index 0000000..5afb663 --- /dev/null +++ b/attestation_asps/rust_asps/src/bin/r_readfile_id.rs @@ -0,0 +1,67 @@ +// Common Packages +use rust_am_lib::copland::*; +use anyhow::{Context, Result}; +use std::env; + +// function where the work of the ASP is performed. +// May signal an error which will be handled in main. +fn body() -> Result { + + // For every ASP, an ASPRunRequest appears as the single command-line argument + let args: Vec = env::args().collect(); + + if args.len() < 2 { + return Err(anyhow::anyhow!("ASPRunRequest not supplied as command line argument")); + } + + let json_request = &args[1]; + // May fail. If so, return an Err Result + let req: ASPRunRequest = serde_json::from_str(json_request)?; + + // Code for specific for this ASP. + // This example computes the HASH of the file named in an argument for the ASP. + // May return an Err Result, which will be captured in main. + let args_map = req.ASP_ARGS; + let filename = &args_map.get("filepath").context("filename argument not provided to ASP, hashfile_id")?; + + let bytes = std::fs::read(filename)?; // Vec + + // Common code to bundle computed value. + // Step 1: + // The return value for an ASP, must be + // encoded in BASE64, and converted to ascii for JSON transmission + let hash_b64: String = base64::encode(bytes); + + // Step 2: + // wrap the value as Evidence + let evidence = RawEv::RawEv(vec![hash_b64]); + + // Step 3: + // Construct the ASPRunResponse with this evidence. + let response = successfulASPRunResponse (evidence); + let response_json = serde_json::to_string(&response)?; + Ok (response_json) +} + +// Main simply invokes the body() function above, +// and checks for Err Result. +// If it detects an Err Result, this ASP will return +// an ASPRunResponse with SUCCESS = false, o/w uses +// ASPRunResponse returned from body() + +fn main() { + + let response_json = match body() { + Ok(resp) => resp, + Err(_error) => { + let response = failureASPRunResponse (_error.to_string()); + // If an error occurs converting the failure response to JSON + // there is nothing else to do but panic. + // This should never happen. + serde_json::to_string(&response).unwrap_or_else(|error| {panic!("Failed to json.encode failure response: {error:?}");}) + } + }; + // The ASP output (ASPRunRequest) is written to stdout. + // The caller will capture stdout to receive the response from this ASP. + println!("{response_json}"); +} From 4eb029d43da2c729be355ba1dce51ff89be28625 Mon Sep 17 00:00:00 2001 From: Adam Petz Date: Wed, 23 Oct 2024 12:07:18 -0500 Subject: [PATCH 11/11] gitignore Cargo.lock files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index c3a2923..842aa51 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ bin # in Rust projects, this directory contains only derived files. target + +# in Rust projects, lock files +Cargo.lock