From 02a44a5bc5dee7ea315d66fde6c4c5419c464efb Mon Sep 17 00:00:00 2001 From: Anderson Toshiyuki Sasaki Date: Thu, 25 Aug 2022 12:00:46 +0200 Subject: [PATCH] Update to upstream commit 0186093 Related: rhbz#2084552 Signed-off-by: Anderson Toshiyuki Sasaki --- .gitignore | 2 + keylime-agent-rust.spec | 199 ++-- rust-keylime-add-quote-serialization.patch | 217 ----- rust-keylime-adjust-features.patch | 14 +- rust-keylime-descriptive-error-messages.patch | 43 - rust-keylime-drop-dependencies.patch | 193 ---- ...keylime-ima-emulator-hash-algorithms.patch | 899 ------------------ rust-keylime-load-config-once.patch | 339 ------- rust-keylime-set-supplementary-groups.patch | 162 ---- rust-keylime-show-path-missing-cert.patch | 20 - sources | 4 +- 11 files changed, 112 insertions(+), 1980 deletions(-) delete mode 100644 rust-keylime-add-quote-serialization.patch delete mode 100644 rust-keylime-descriptive-error-messages.patch delete mode 100644 rust-keylime-drop-dependencies.patch delete mode 100644 rust-keylime-ima-emulator-hash-algorithms.patch delete mode 100644 rust-keylime-load-config-once.patch delete mode 100644 rust-keylime-set-supplementary-groups.patch delete mode 100644 rust-keylime-show-path-missing-cert.patch diff --git a/.gitignore b/.gitignore index b471783..127432b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ /rust-keylime-0.1.0~20220603gitaed51c7-vendor.tar.xz /rust-keylime-0.1.0~20220603gitaed51c7.tar.gz +/rust-keylime-0.1.0~20220805git0186093.tar.gz +/rust-keylime-0.1.0~20220805git0186093-vendor.tar.xz diff --git a/keylime-agent-rust.spec b/keylime-agent-rust.spec index 82e2d44..1383471 100644 --- a/keylime-agent-rust.spec +++ b/keylime-agent-rust.spec @@ -6,16 +6,16 @@ %global crate keylime_agent %global crate_version 0.1.0 -%global commit aed51c7c8c526953e945357594352c3df2ca4ace +%global commit 01860934f7308bc5ea1e68c8d858aea056620ce8 %global shortcommit %(c=%{commit}; echo ${c:0:7}) -%global commitdate 20220603 +%global commitdate 20220805 # RHEL: Use bundled deps as it doesn't ship Rust libraries %global bundled_rust_deps 1 Name: keylime-agent-rust Version: %{crate_version}~%{commitdate}git%{shortcommit} -Release: 4%{?dist} +Release: 1%{?dist} Summary: Rust agent for Keylime # Upstream license specification: Apache-2.0 @@ -40,28 +40,20 @@ URL: https://github.com/keylime/rust-keylime/ # The source tarball is downloaded using the following commands: # spectool -g keylime-agent-rust.spec Source0: %{url}/archive/%{commit}/rust-keylime-%{version}.tar.gz -# The vendor tarball is created using cargo vendor: +# The vendor tarball is created using cargo-vendor-filterer to remove Windows +# related files (https://github.com/cgwalters/cargo-vendor-filterer) # tar xf rust-keylime-%%{version}.tar.gz # cd rust-keylime-%%{version} -# cargo vendor +# cargo vendor-filterer --platform x86_64-unknown-linux-gnu \ +# --platform powerpc64le-unknown-linux-gnu \ +# --platform aarch64-unknown-linux-gnu \ +# --platform i686-unknown-linux-gnu \ +# --platform s390x-unknown-linux-gnu \ +# --exclude-crate-path "libloading#tests" # tar jcf rust-keylime-%%{version}-vendor.tar.xz vendor Source1: rust-keylime-%{version}-vendor.tar.xz # Drop dependencies and adjust the features -Patch0: rust-keylime-drop-dependencies.patch -# Add serialization functions to fix issue on big-endian arches -Patch1: rust-keylime-add-quote-serialization.patch -# Show path on missing mTLS certificate -Patch2: rust-keylime-show-path-missing-cert.patch -# Use more descriptive error messages for missing files errors -Patch3: rust-keylime-descriptive-error-messages.patch -# Set supplementary groups when dropping privileges -Patch4: rust-keylime-set-supplementary-groups.patch -# Adjust the supported and required features -Patch5: rust-keylime-adjust-features.patch -# Load configuration file only once during startup -Patch6: rust-keylime-load-config-once.patch -# Add support for PCR hash algorithms other than SHA-1 to the IMA emulator -Patch7: rust-keylime-ima-emulator-hash-algorithms.patch +Patch0: rust-keylime-adjust-features.patch ExclusiveArch: %{rust_arches} @@ -87,8 +79,8 @@ Provides: bundled(crate(actix-codec)) = 0.5.0 Provides: bundled(crate(actix-http)) = 3.0.4 Provides: bundled(crate(actix-macros)) = 0.2.3 Provides: bundled(crate(actix-router)) = 0.5.0 -Provides: bundled(crate(actix-rt)) = 2.6.0 -Provides: bundled(crate(actix-server)) = 2.0.0 +Provides: bundled(crate(actix-rt)) = 2.7.0 +Provides: bundled(crate(actix-server)) = 2.1.1 Provides: bundled(crate(actix-service)) = 2.0.2 Provides: bundled(crate(actix-tls)) = 3.0.3 Provides: bundled(crate(actix-utils)) = 3.0.0 @@ -108,36 +100,36 @@ Provides: bundled(crate(bindgen)) = 0.59.2 Provides: bundled(crate(bitfield)) = 0.13.2 Provides: bundled(crate(bitflags)) = 1.3.2 Provides: bundled(crate(block-buffer)) = 0.10.2 -Provides: bundled(crate(brotli)) = 3.3.3 +Provides: bundled(crate(brotli)) = 3.3.4 Provides: bundled(crate(brotli-decompressor)) = 2.3.2 Provides: bundled(crate(bytes)) = 1.1.0 Provides: bundled(crate(bytestring)) = 1.0.0 -Provides: bundled(crate(cc)) = 1.0.72 +Provides: bundled(crate(cc)) = 1.0.73 Provides: bundled(crate(cexpr)) = 0.6.0 Provides: bundled(crate(cfg-if)) = 1.0.0 Provides: bundled(crate(clang-sys)) = 1.3.3 Provides: bundled(crate(clap)) = 2.34.0 Provides: bundled(crate(clap)) = 3.1.18 Provides: bundled(crate(clap_derive)) = 3.1.18 -Provides: bundled(crate(clap_lex)) = 0.2.4 +Provides: bundled(crate(clap_lex)) = 0.2.0 Provides: bundled(crate(compress-tools)) = 0.12.2 Provides: bundled(crate(convert_case)) = 0.4.0 Provides: bundled(crate(cookie)) = 0.16.0 -Provides: bundled(crate(cpufeatures)) = 0.2.1 +Provides: bundled(crate(cpufeatures)) = 0.2.2 Provides: bundled(crate(crc32fast)) = 1.3.2 Provides: bundled(crate(crypto-common)) = 0.1.3 Provides: bundled(crate(derive_more)) = 0.99.17 Provides: bundled(crate(digest)) = 0.10.3 Provides: bundled(crate(dlv-list)) = 0.2.3 Provides: bundled(crate(either)) = 1.7.0 -Provides: bundled(crate(encoding_rs)) = 0.8.30 -Provides: bundled(crate(enumflags2)) = 0.7.3 -Provides: bundled(crate(enumflags2_derive)) = 0.7.3 +Provides: bundled(crate(encoding_rs)) = 0.8.31 +Provides: bundled(crate(enumflags2)) = 0.7.5 +Provides: bundled(crate(enumflags2_derive)) = 0.7.4 Provides: bundled(crate(env_logger)) = 0.7.1 Provides: bundled(crate(env_logger)) = 0.9.0 Provides: bundled(crate(fastrand)) = 1.7.0 -Provides: bundled(crate(firestorm)) = 0.5.0 -Provides: bundled(crate(flate2)) = 1.0.22 +Provides: bundled(crate(firestorm)) = 0.5.1 +Provides: bundled(crate(flate2)) = 1.0.24 Provides: bundled(crate(fnv)) = 1.0.7 Provides: bundled(crate(foreign-types)) = 0.3.2 Provides: bundled(crate(foreign-types-shared)) = 0.1.1 @@ -152,28 +144,26 @@ Provides: bundled(crate(futures-sink)) = 0.3.21 Provides: bundled(crate(futures-task)) = 0.3.21 Provides: bundled(crate(futures-util)) = 0.3.21 Provides: bundled(crate(generic-array)) = 0.14.5 -Provides: bundled(crate(getrandom)) = 0.2.4 +Provides: bundled(crate(getrandom)) = 0.2.6 Provides: bundled(crate(glob)) = 0.3.0 -Provides: bundled(crate(h2)) = 0.3.11 -Provides: bundled(crate(hamming)) = 0.1.3 +Provides: bundled(crate(h2)) = 0.3.13 Provides: bundled(crate(hashbrown)) = 0.9.1 Provides: bundled(crate(hashbrown)) = 0.11.2 Provides: bundled(crate(heck)) = 0.4.0 Provides: bundled(crate(hex)) = 0.4.3 -Provides: bundled(crate(hostname-validator)) = 1.1.0 -Provides: bundled(crate(http)) = 0.2.6 -Provides: bundled(crate(http-body)) = 0.4.4 -Provides: bundled(crate(httparse)) = 1.6.0 +Provides: bundled(crate(hostname-validator)) = 1.1.1 +Provides: bundled(crate(http)) = 0.2.8 +Provides: bundled(crate(http-body)) = 0.4.5 +Provides: bundled(crate(httparse)) = 1.7.1 Provides: bundled(crate(httpdate)) = 1.0.2 Provides: bundled(crate(humantime)) = 1.3.0 Provides: bundled(crate(humantime)) = 2.1.0 -Provides: bundled(crate(hyper)) = 0.14.17 +Provides: bundled(crate(hyper)) = 0.14.19 Provides: bundled(crate(hyper-tls)) = 0.5.0 Provides: bundled(crate(idna)) = 0.2.3 -Provides: bundled(crate(indexmap)) = 1.8.0 -Provides: bundled(crate(instant)) = 0.1.12 -Provides: bundled(crate(ipnet)) = 2.3.1 -Provides: bundled(crate(itoa)) = 1.0.1 +Provides: bundled(crate(indexmap)) = 1.8.2 +Provides: bundled(crate(ipnet)) = 2.5.0 +Provides: bundled(crate(itoa)) = 1.0.2 Provides: bundled(crate(jobserver)) = 0.1.24 Provides: bundled(crate(keylime_agent)) = 0.1.0 Provides: bundled(crate(language-tags)) = 0.3.2 @@ -181,124 +171,124 @@ Provides: bundled(crate(lazy_static)) = 1.4.0 Provides: bundled(crate(lazycell)) = 1.3.0 Provides: bundled(crate(libc)) = 0.2.126 Provides: bundled(crate(libloading)) = 0.7.3 -Provides: bundled(crate(local-channel)) = 0.1.2 -Provides: bundled(crate(local-waker)) = 0.1.2 -Provides: bundled(crate(lock_api)) = 0.4.6 -Provides: bundled(crate(log)) = 0.4.14 +Provides: bundled(crate(local-channel)) = 0.1.3 +Provides: bundled(crate(local-waker)) = 0.1.3 +Provides: bundled(crate(lock_api)) = 0.4.7 +Provides: bundled(crate(log)) = 0.4.17 Provides: bundled(crate(matches)) = 0.1.9 Provides: bundled(crate(mbox)) = 0.6.0 -Provides: bundled(crate(memchr)) = 2.4.1 +Provides: bundled(crate(memchr)) = 2.5.0 Provides: bundled(crate(mime)) = 0.3.16 Provides: bundled(crate(minimal-lexical)) = 0.2.1 -Provides: bundled(crate(miniz_oxide)) = 0.4.4 -Provides: bundled(crate(mio)) = 0.7.14 -Provides: bundled(crate(mio)) = 0.8.2 -Provides: bundled(crate(native-tls)) = 0.2.8 +Provides: bundled(crate(miniz_oxide)) = 0.5.3 +Provides: bundled(crate(mio)) = 0.8.3 +Provides: bundled(crate(native-tls)) = 0.2.10 Provides: bundled(crate(nom)) = 7.1.1 Provides: bundled(crate(num-derive)) = 0.3.3 -Provides: bundled(crate(num-integer)) = 0.1.44 -Provides: bundled(crate(num-traits)) = 0.2.14 +Provides: bundled(crate(num-traits)) = 0.2.15 Provides: bundled(crate(num_cpus)) = 1.13.1 -Provides: bundled(crate(num_threads)) = 0.1.5 -Provides: bundled(crate(once_cell)) = 1.9.0 -Provides: bundled(crate(openssl)) = 0.10.38 +Provides: bundled(crate(num_threads)) = 0.1.6 +Provides: bundled(crate(oid)) = 0.2.1 +Provides: bundled(crate(once_cell)) = 1.12.0 +Provides: bundled(crate(openssl)) = 0.10.40 +Provides: bundled(crate(openssl-macros)) = 0.1.0 Provides: bundled(crate(openssl-probe)) = 0.1.5 -Provides: bundled(crate(openssl-sys)) = 0.9.72 +Provides: bundled(crate(openssl-sys)) = 0.9.74 Provides: bundled(crate(ordered-multimap)) = 0.3.1 -Provides: bundled(crate(os_str_bytes)) = 6.0.0 -Provides: bundled(crate(parking_lot)) = 0.11.2 -Provides: bundled(crate(parking_lot_core)) = 0.8.5 +Provides: bundled(crate(os_str_bytes)) = 6.1.0 +Provides: bundled(crate(parking_lot)) = 0.12.1 +Provides: bundled(crate(parking_lot_core)) = 0.9.3 Provides: bundled(crate(paste)) = 1.0.7 Provides: bundled(crate(peeking_take_while)) = 0.1.2 Provides: bundled(crate(percent-encoding)) = 2.1.0 Provides: bundled(crate(pest)) = 2.1.3 -Provides: bundled(crate(pin-project-lite)) = 0.2.8 +Provides: bundled(crate(picky-asn1)) = 0.3.3 +Provides: bundled(crate(picky-asn1)) = 0.5.0 +Provides: bundled(crate(picky-asn1-der)) = 0.2.5 +Provides: bundled(crate(picky-asn1-der)) = 0.3.1 +Provides: bundled(crate(picky-asn1-x509)) = 0.6.1 +Provides: bundled(crate(pin-project-lite)) = 0.2.9 Provides: bundled(crate(pin-utils)) = 0.1.0 -Provides: bundled(crate(pkg-config)) = 0.3.24 +Provides: bundled(crate(pkg-config)) = 0.3.25 Provides: bundled(crate(ppv-lite86)) = 0.2.16 Provides: bundled(crate(pretty_env_logger)) = 0.4.0 -Provides: bundled(crate(primal)) = 0.3.0 -Provides: bundled(crate(primal-bit)) = 0.3.0 -Provides: bundled(crate(primal-check)) = 0.3.1 -Provides: bundled(crate(primal-estimate)) = 0.3.1 -Provides: bundled(crate(primal-sieve)) = 0.3.1 Provides: bundled(crate(proc-macro-error)) = 1.0.4 Provides: bundled(crate(proc-macro-error-attr)) = 1.0.4 -Provides: bundled(crate(proc-macro2)) = 1.0.36 +Provides: bundled(crate(proc-macro2)) = 1.0.39 Provides: bundled(crate(quick-error)) = 1.2.3 -Provides: bundled(crate(quote)) = 1.0.15 +Provides: bundled(crate(quote)) = 1.0.18 Provides: bundled(crate(rand)) = 0.8.5 Provides: bundled(crate(rand_chacha)) = 0.3.1 Provides: bundled(crate(rand_core)) = 0.6.3 -Provides: bundled(crate(regex)) = 1.5.4 -Provides: bundled(crate(regex-syntax)) = 0.6.25 +Provides: bundled(crate(regex)) = 1.5.6 +Provides: bundled(crate(regex-syntax)) = 0.6.26 Provides: bundled(crate(remove_dir_all)) = 0.5.3 Provides: bundled(crate(reqwest)) = 0.11.10 Provides: bundled(crate(rust-ini)) = 0.17.0 Provides: bundled(crate(rustc-hash)) = 1.1.0 Provides: bundled(crate(rustc_version)) = 0.3.3 Provides: bundled(crate(rustc_version)) = 0.4.0 -Provides: bundled(crate(ryu)) = 1.0.9 +Provides: bundled(crate(ryu)) = 1.0.10 Provides: bundled(crate(scopeguard)) = 1.1.0 Provides: bundled(crate(semver)) = 0.11.0 -Provides: bundled(crate(semver)) = 1.0.5 +Provides: bundled(crate(semver)) = 1.0.9 Provides: bundled(crate(semver-parser)) = 0.10.2 -Provides: bundled(crate(serde)) = 1.0.136 -Provides: bundled(crate(serde_derive)) = 1.0.136 -Provides: bundled(crate(serde_json)) = 1.0.79 +Provides: bundled(crate(serde)) = 1.0.137 +Provides: bundled(crate(serde_bytes)) = 0.11.6 +Provides: bundled(crate(serde_derive)) = 1.0.137 +Provides: bundled(crate(serde_json)) = 1.0.81 Provides: bundled(crate(serde_urlencoded)) = 0.7.1 Provides: bundled(crate(sha-1)) = 0.10.0 Provides: bundled(crate(shlex)) = 1.1.0 Provides: bundled(crate(signal-hook-registry)) = 1.4.0 -Provides: bundled(crate(slab)) = 0.4.5 +Provides: bundled(crate(slab)) = 0.4.6 Provides: bundled(crate(smallvec)) = 1.8.0 Provides: bundled(crate(socket2)) = 0.4.4 Provides: bundled(crate(stable_deref_trait)) = 1.2.0 Provides: bundled(crate(static_assertions)) = 1.1.0 Provides: bundled(crate(strsim)) = 0.8.0 Provides: bundled(crate(strsim)) = 0.10.0 -Provides: bundled(crate(syn)) = 1.0.86 +Provides: bundled(crate(syn)) = 1.0.96 Provides: bundled(crate(synstructure)) = 0.12.6 -Provides: bundled(crate(target-lexicon)) = 0.12.3 +Provides: bundled(crate(target-lexicon)) = 0.12.4 Provides: bundled(crate(tempfile)) = 3.3.0 -Provides: bundled(crate(termcolor)) = 1.1.2 +Provides: bundled(crate(termcolor)) = 1.1.3 Provides: bundled(crate(textwrap)) = 0.11.0 Provides: bundled(crate(textwrap)) = 0.15.0 -Provides: bundled(crate(thiserror)) = 1.0.30 -Provides: bundled(crate(thiserror-impl)) = 1.0.30 +Provides: bundled(crate(thiserror)) = 1.0.31 +Provides: bundled(crate(thiserror-impl)) = 1.0.31 Provides: bundled(crate(time)) = 0.3.9 Provides: bundled(crate(time-macros)) = 0.2.4 -Provides: bundled(crate(tinyvec)) = 1.5.1 +Provides: bundled(crate(tinyvec)) = 1.6.0 Provides: bundled(crate(tinyvec_macros)) = 0.1.0 -Provides: bundled(crate(tokio)) = 1.16.1 -Provides: bundled(crate(tokio-macros)) = 1.7.0 +Provides: bundled(crate(tokio)) = 1.19.2 +Provides: bundled(crate(tokio-macros)) = 1.8.0 Provides: bundled(crate(tokio-native-tls)) = 0.3.0 Provides: bundled(crate(tokio-openssl)) = 0.6.3 -Provides: bundled(crate(tokio-util)) = 0.6.9 -Provides: bundled(crate(tokio-util)) = 0.7.1 +Provides: bundled(crate(tokio-util)) = 0.7.3 Provides: bundled(crate(tower-service)) = 0.3.1 -Provides: bundled(crate(tracing)) = 0.1.30 -Provides: bundled(crate(tracing-attributes)) = 0.1.20 -Provides: bundled(crate(tracing-core)) = 0.1.22 +Provides: bundled(crate(tracing)) = 0.1.35 +Provides: bundled(crate(tracing-core)) = 0.1.27 Provides: bundled(crate(try-lock)) = 0.2.3 -Provides: bundled(crate(tss-esapi)) = 7.0.0 +Provides: bundled(crate(tss-esapi)) = 7.1.0 Provides: bundled(crate(tss-esapi-sys)) = 0.3.0 Provides: bundled(crate(typenum)) = 1.15.0 Provides: bundled(crate(ucd-trie)) = 0.1.3 -Provides: bundled(crate(unicode-bidi)) = 0.3.7 +Provides: bundled(crate(unicode-bidi)) = 0.3.8 +Provides: bundled(crate(unicode-ident)) = 1.0.0 Provides: bundled(crate(unicode-normalization)) = 0.1.19 Provides: bundled(crate(unicode-width)) = 0.1.9 -Provides: bundled(crate(unicode-xid)) = 0.2.2 +Provides: bundled(crate(unicode-xid)) = 0.2.3 Provides: bundled(crate(url)) = 2.2.2 Provides: bundled(crate(uuid)) = 0.8.2 Provides: bundled(crate(vec_map)) = 0.8.2 Provides: bundled(crate(version_check)) = 0.9.4 Provides: bundled(crate(want)) = 0.3.0 Provides: bundled(crate(which)) = 4.2.5 -Provides: bundled(crate(zeroize)) = 1.5.2 -Provides: bundled(crate(zeroize_derive)) = 1.3.1 -Provides: bundled(crate(zstd)) = 0.10.0 -Provides: bundled(crate(zstd-safe)) = 4.1.4 +Provides: bundled(crate(zeroize)) = 1.5.5 +Provides: bundled(crate(zeroize_derive)) = 1.3.2 +Provides: bundled(crate(zstd)) = 0.10.2 +Provides: bundled(crate(zstd-safe)) = 4.1.6 Provides: bundled(crate(zstd-sys)) = 1.6.3 %description @@ -329,6 +319,15 @@ install -Dpm 644 ./dist/systemd/system/keylime_agent.service \ install -Dpm 644 ./dist/systemd/system/var-lib-keylime-secure.mount \ %{buildroot}%{_unitdir}/var-lib-keylime-secure.mount +# Setting up the agent to use keylime:keylime user/group after dropping privileges. +sed -e 's/^run_as[[:space:]]*=.*/run_as = keylime:keylime/g' -i keylime-agent.conf + +# Using sha256 for tpm_hash_alg. +sed -e 's/^tpm_hash_alg[[:space:]]*=.*/tpm_hash_alg = sha256/g' -i keylime-agent.conf + +install -Dpm 600 keylime-agent.conf \ + %{buildroot}%{_sysconfdir}/keylime-agent.conf + %preun %systemd_preun keylime_agent.service %systemd_preun var-lib-keylime-secure.mount @@ -340,6 +339,7 @@ install -Dpm 644 ./dist/systemd/system/var-lib-keylime-secure.mount \ %files %license LICENSE %doc README.md +%config(noreplace) %attr(600,keylime,keylime) %{_sysconfdir}/keylime-agent.conf %{_unitdir}/keylime_agent.service %{_unitdir}/var-lib-keylime-secure.mount %attr(700,keylime,keylime) %dir %{_rundir}/keylime @@ -355,6 +355,9 @@ install -Dpm 644 ./dist/systemd/system/var-lib-keylime-secure.mount \ %endif %changelog +* Thu Aug 25 2022 Anderson Toshiyuki Sasaki - 0.1.0~20220805git0185093-1 +- Update to upstream commit 0186093 + * Mon Jul 18 2022 Anderson Toshiyuki Sasaki - 0.1.0~20220603gitaed51c7-4 - Remove vendored source files for non-Linux or unsupported platforms diff --git a/rust-keylime-add-quote-serialization.patch b/rust-keylime-add-quote-serialization.patch deleted file mode 100644 index 7401c2e..0000000 --- a/rust-keylime-add-quote-serialization.patch +++ /dev/null @@ -1,217 +0,0 @@ -From 423f7337d991ec5085914a361e68260bdd513ac6 Mon Sep 17 00:00:00 2001 -From: Anderson Toshiyuki Sasaki -Date: Mon, 20 Jun 2022 11:51:46 +0200 -Subject: [PATCH] tpm: Add serialization functions for structures in quotes - -Add serialization and deserialization functions for the data in quotes -to avoid endianness issues when the arch is big-endian. - -The added serialization and deserialization functions will convert the -data endianness as necessary. - -Note: the official marshalling and unmarshalling functions cannot be -used directly because the tpm2-tools uses a custom format. - -Fixes: #407 - -Signed-off-by: Anderson Toshiyuki Sasaki ---- - src/tpm.rs | 139 +++++++++++++++++++++++++++++++++++++++++------------ - 1 file changed, 107 insertions(+), 32 deletions(-) - -diff --git a/src/tpm.rs b/src/tpm.rs -index 9002c29..5521892 100644 ---- a/src/tpm.rs -+++ b/src/tpm.rs -@@ -52,15 +52,20 @@ use tss_esapi::{ - tss2_esys::{ - Tss2_MU_TPM2B_PUBLIC_Marshal, Tss2_MU_TPMS_ATTEST_Marshal, - Tss2_MU_TPMS_ATTEST_Unmarshal, Tss2_MU_TPMT_SIGNATURE_Marshal, -- TPM2B_ATTEST, TPM2B_PUBLIC, TPML_DIGEST, TPML_PCR_SELECTION, -- TPMS_ATTEST, TPMS_SCHEME_HASH, TPMT_SIGNATURE, TPMT_SIG_SCHEME, -- TPMU_SIG_SCHEME, -+ TPM2B_ATTEST, TPM2B_DIGEST, TPM2B_PUBLIC, TPML_DIGEST, -+ TPML_PCR_SELECTION, TPMS_ATTEST, TPMS_PCR_SELECTION, -+ TPMS_SCHEME_HASH, TPMT_SIGNATURE, TPMT_SIG_SCHEME, TPMU_SIG_SCHEME, - }, - utils::TpmsContext, - Context, - }; - - pub const MAX_NONCE_SIZE: usize = 64; -+pub const TPML_DIGEST_SIZE: usize = std::mem::size_of::(); -+pub const TPML_PCR_SELECTION_SIZE: usize = -+ std::mem::size_of::(); -+pub const TPMS_PCR_SELECTION_SIZE: usize = -+ std::mem::size_of::(); - - /* - * Input: None -@@ -123,6 +128,95 @@ pub(crate) fn create_ek( - assert_eq_size!(TPML_PCR_SELECTION, [u8; 132]); - assert_eq_size!(TPML_DIGEST, [u8; 532]); - -+// Serialize a TPML_PCR_SELECTION into a Vec -+// The serialization will adjust the data endianness as necessary and add paddings to keep the -+// memory aligment. -+pub(crate) fn serialize_pcrsel( -+ pcr_selection: &TPML_PCR_SELECTION, -+) -> Vec { -+ let mut output = Vec::with_capacity(TPML_PCR_SELECTION_SIZE); -+ output.extend(u32::to_le_bytes(pcr_selection.count)); -+ for selection in pcr_selection.pcrSelections.iter() { -+ output.extend(selection.hash.to_le_bytes()); -+ output.extend(selection.sizeofSelect.to_le_bytes()); -+ output.extend(selection.pcrSelect); -+ output.extend([0u8; 1]); // padding to keep the memory alignment -+ } -+ output -+} -+ -+// Deserialize a TPML_PCR_SELECTION from a &[u8] slice. -+// The deserialization will adjust the data endianness as necessary. -+pub(crate) fn deserialize_pcrsel( -+ pcrsel_vec: &[u8], -+) -> Result { -+ if pcrsel_vec.len() != TPML_PCR_SELECTION_SIZE { -+ return Err(KeylimeError::InvalidRequest); -+ } -+ -+ let mut reader = std::io::Cursor::new(pcrsel_vec); -+ let mut count_vec = [0u8; 4]; -+ reader.read_exact(&mut count_vec)?; -+ let count = u32::from_le_bytes(count_vec); -+ -+ let mut pcr_selections: [TPMS_PCR_SELECTION; 16] = -+ [TPMS_PCR_SELECTION::default(); 16]; -+ -+ for selection in &mut pcr_selections { -+ let mut hash_vec = [0u8; 2]; -+ reader.read_exact(&mut hash_vec)?; -+ selection.hash = u16::from_le_bytes(hash_vec); -+ -+ let mut size_vec = [0u8; 1]; -+ reader.read_exact(&mut size_vec)?; -+ selection.sizeofSelect = u8::from_le_bytes(size_vec); -+ -+ reader.read_exact(&mut selection.pcrSelect)?; -+ } -+ -+ Ok(TPML_PCR_SELECTION { -+ count, -+ pcrSelections: pcr_selections, -+ }) -+} -+ -+// Serialize a TPML_DIGEST into a Vec -+// The serialization will adjust the data endianness as necessary. -+pub(crate) fn serialize_digest(digest_list: &TPML_DIGEST) -> Vec { -+ let mut output = Vec::with_capacity(TPML_DIGEST_SIZE); -+ output.extend(u32::to_le_bytes(digest_list.count)); -+ for digest in digest_list.digests.iter() { -+ output.extend(digest.size.to_le_bytes()); -+ output.extend(digest.buffer); -+ } -+ output -+} -+ -+// Deserialize a TPML_DIGEST from a &[u8] slice. -+// The deserialization will adjust the data endianness as necessary. -+pub(crate) fn deserialize_digest(digest_vec: &[u8]) -> Result { -+ if digest_vec.len() != TPML_DIGEST_SIZE { -+ return Err(KeylimeError::InvalidRequest); -+ } -+ -+ let mut reader = std::io::Cursor::new(digest_vec); -+ let mut count_vec = [0u8; 4]; -+ -+ reader.read_exact(&mut count_vec)?; -+ let count = u32::from_le_bytes(count_vec); -+ -+ let mut digests: [TPM2B_DIGEST; 8] = [TPM2B_DIGEST::default(); 8]; -+ -+ for digest in &mut digests { -+ let mut size_vec = [0u8; 2]; -+ reader.read_exact(&mut size_vec)?; -+ digest.size = u16::from_le_bytes(size_vec); -+ reader.read_exact(&mut digest.buffer)?; -+ } -+ -+ Ok(TPML_DIGEST { count, digests }) -+} -+ - // Recreate how tpm2-tools creates the PCR out file. Roughly, this is a - // TPML_PCR_SELECTION + number of TPML_DIGESTS + TPML_DIGESTs. - // Reference: -@@ -140,16 +234,14 @@ pub(crate) fn pcrdata_to_vec( - const DIGEST_SIZE: usize = std::mem::size_of::(); - - let mut pcrsel: TPML_PCR_SELECTION = selection_list.into(); -- pcrsel.count = pcrsel.count.to_le(); -- let pcrsel_vec: [u8; PCRSEL_SIZE] = -- unsafe { std::mem::transmute(pcrsel) }; -+ let pcrsel_vec = serialize_pcrsel(&pcrsel); - - let digest: Vec = pcrdata.into(); - let num_tpml_digests = digest.len() as u32; - let mut digest_vec = Vec::with_capacity(digest.len() * DIGEST_SIZE); - - for d in digest { -- let vec: [u8; DIGEST_SIZE] = unsafe { std::mem::transmute(d) }; -+ let vec = serialize_digest(&d); - digest_vec.extend(vec); - } - -@@ -665,41 +757,24 @@ pub mod testing { - ); - - fn vec_to_pcrdata(val: &[u8]) -> Result<(PcrSelectionList, PcrData)> { -- const PCRSEL_SIZE: usize = std::mem::size_of::(); -- const DIGEST_SIZE: usize = std::mem::size_of::(); -- - let mut reader = std::io::Cursor::new(val); -- let mut pcrsel_vec = [0u8; PCRSEL_SIZE]; -- let len = reader.read(&mut pcrsel_vec)?; -- if len != pcrsel_vec.len() { -- return Err(KeylimeError::InvalidRequest); -- } -- let mut pcrsel = unsafe { -- std::mem::transmute::<[u8; PCRSEL_SIZE], TPML_PCR_SELECTION>( -- pcrsel_vec, -- ) -- }; -+ let mut pcrsel_vec = [0u8; TPML_PCR_SELECTION_SIZE]; -+ reader.read_exact(&mut pcrsel_vec)?; -+ -+ let pcrsel = deserialize_pcrsel(&pcrsel_vec)?; - let pcrlist: PcrSelectionList = pcrsel.try_into()?; - - let mut count_vec = [0u8; 4]; -- let len = reader.read(&mut count_vec)?; -- if len < count_vec.len() { -- return Err(KeylimeError::InvalidRequest); -- } -+ reader.read_exact(&mut count_vec)?; - let count = u32::from_le_bytes(count_vec); - // Always 1 PCR digest should follow - if count != 1 { - return Err(KeylimeError::InvalidRequest); - } - -- let mut digest_vec = [0u8; DIGEST_SIZE]; -- let len = reader.read(&mut digest_vec)?; -- if len != digest_vec.len() { -- return Err(KeylimeError::InvalidRequest); -- } -- let mut digest = unsafe { -- std::mem::transmute::<[u8; DIGEST_SIZE], TPML_DIGEST>(digest_vec) -- }; -+ let mut digest_vec = [0u8; TPML_DIGEST_SIZE]; -+ reader.read_exact(&mut digest_vec)?; -+ let digest = deserialize_digest(&digest_vec)?; - let mut digest_list = DigestList::new(); - for i in 0..digest.count { - digest_list.add(digest.digests[i as usize].try_into()?); --- -2.35.3 - diff --git a/rust-keylime-adjust-features.patch b/rust-keylime-adjust-features.patch index 8be3369..46f8566 100644 --- a/rust-keylime-adjust-features.patch +++ b/rust-keylime-adjust-features.patch @@ -1,11 +1,11 @@ ---- a/Cargo.toml 2022-07-04 14:30:04.244003909 +0200 -+++ b/Cargo.toml 2022-07-04 14:31:46.421291210 +0200 -@@ -37,28 +37,14 @@ +--- a/Cargo.toml 2022-08-25 12:16:51.789234342 +0200 ++++ b/Cargo.toml 2022-08-25 12:21:45.451435220 +0200 +@@ -39,28 +39,13 @@ static_assertions = "1" tempfile = "3.0.4" - tokio = {version = "1", features = ["full"]} --tss-esapi = "7.0.0" -+tss-esapi = {version = "7.0.0", features = ["generate-bindings"]} + tokio = {version = "1.13.1", features = ["full"]} +-tss-esapi = "7.1.0" ++tss-esapi = {version="7.1.0", features = ["generate-bindings"]} thiserror = "1.0" uuid = {version = "0.8", features = ["v4"]} -zmq = {version = "0.9.2", optional = true} @@ -18,7 +18,7 @@ actix-rt = "2" [features] - # The features enabled by default +-# The features enabled by default -default = ["with-zmq", "legacy-python-actions"] -# this should change to dev-dependencies when we have integration testing -testing = ["wiremock"] diff --git a/rust-keylime-descriptive-error-messages.patch b/rust-keylime-descriptive-error-messages.patch deleted file mode 100644 index 63172ef..0000000 --- a/rust-keylime-descriptive-error-messages.patch +++ /dev/null @@ -1,43 +0,0 @@ -From e20b936fc9d92ae05406cb86471d3e6fba823b7f Mon Sep 17 00:00:00 2001 -From: Anderson Toshiyuki Sasaki -Date: Tue, 28 Jun 2022 13:47:38 +0200 -Subject: [PATCH] main: Use more descriptive message for missing files error - -Use more descriptive message when required paths are missing instead of -the generic message. - -Signed-off-by: Anderson Toshiyuki Sasaki ---- - src/main.rs | 19 ++++++++++++++++--- - 1 file changed, 16 insertions(+), 3 deletions(-) - -diff --git a/src/main.rs b/src/main.rs -index 9404284..ef29eb2 100644 ---- a/src/main.rs -+++ b/src/main.rs -@@ -608,9 +608,22 @@ async fn main() -> Result<()> { - let payload = Arc::clone(&encr_payload_arc); - - let revocation_cert = revocation::get_revocation_cert_path(&config)?; -- let actions_dir = -- Path::new(&config.revocation_actions_dir).canonicalize()?; -- let work_dir = Path::new(&config.work_dir).canonicalize()?; -+ let actions_dir = Path::new(&config.revocation_actions_dir) -+ .canonicalize() -+ .map_err(|e| { -+ Error::Configuration(format!( -+ "Path {} set in revocation_actions_dir not found: {}", -+ &config.revocation_actions_dir, e -+ )) -+ })?; -+ -+ let work_dir = -+ Path::new(&config.work_dir).canonicalize().map_err(|e| { -+ Error::Configuration(format!( -+ "Path {} set in keylime_dir not found: {}", -+ &config.work_dir, e -+ )) -+ })?; - - let quotedata = web::Data::new(QuoteData { - tpmcontext: Mutex::new(ctx), diff --git a/rust-keylime-drop-dependencies.patch b/rust-keylime-drop-dependencies.patch deleted file mode 100644 index 9ff289d..0000000 --- a/rust-keylime-drop-dependencies.patch +++ /dev/null @@ -1,193 +0,0 @@ -From 9229cb4673aad2cae7605e66bdf2160716e1f694 Mon Sep 17 00:00:00 2001 -From: Anderson Toshiyuki Sasaki -Date: Thu, 9 Jun 2022 18:34:34 +0200 -Subject: [PATCH 1/4] Update clap dependency to 3.1.18 - -This change replaces clap::App with clap::Command in main.rs file. - -On commit f3fa925 the clap dependency in Cargo.lock file was updated -from version 3.0.14 to version 3.1.18. - -In clap version 3.1.0, clap::App was deprecated in favor of -clap::Command. This causes warnings during the Keylime agent build due -to the usage of the deprecated structure. - -To avoid similar issues in the future, use the tilde dependency version -requirement to allow versions >= 3.1.18 but < 3.2.0. - -Signed-off-by: Anderson Toshiyuki Sasaki ---- - Cargo.lock | 76 ++++++++++++++++++++++------------------------------- - Cargo.toml | 2 +- - src/main.rs | 2 +- - 3 files changed, 33 insertions(+), 47 deletions(-) - -diff --git a/Cargo.toml b/Cargo.toml -index 92f3974..f0c7d39 100644 ---- a/Cargo.toml -+++ b/Cargo.toml -@@ -21,7 +21,7 @@ doc = false - actix-web = { version = "4", features = ["openssl"] } - base64 = "0.13" - cfg-if = "1" --clap = { version = "3.0.14", features = ["derive"] } -+clap = { version = "~3.1.18", features = ["derive"] } - compress-tools = "0.12" - flate2 = "1.0.4" - futures = "0.3.6" -diff --git a/src/main.rs b/src/main.rs -index 1896104..8540597 100644 ---- a/src/main.rs -+++ b/src/main.rs -@@ -51,7 +51,7 @@ mod tpm; - mod version_handler; - - use actix_web::{dev::Service, http, middleware, rt, web, App, HttpServer}; --use clap::{App as ClapApp, Arg}; -+use clap::{Arg, Command as ClapApp}; - use common::*; - use compress_tools::*; - use error::{Error, Result}; --- -2.35.3 - - -From c61e3f389e4bde4d0a318a571c9b3dcf8a62749f Mon Sep 17 00:00:00 2001 -From: Anderson Toshiyuki Sasaki -Date: Tue, 17 May 2022 18:31:01 +0200 -Subject: [PATCH 2/4] Drop unused dependency rustc-serialize - -Signed-off-by: Anderson Toshiyuki Sasaki ---- - Cargo.lock | 7 ------- - Cargo.toml | 1 - - 2 files changed, 8 deletions(-) - -diff --git a/Cargo.toml b/Cargo.toml -index f0c7d39..0f4e4ab 100644 ---- a/Cargo.toml -+++ b/Cargo.toml -@@ -34,7 +34,6 @@ picky-asn1-x509 = "0.6.1" - pretty_env_logger = "0.4" - reqwest = {version = "0.11", features = ["json"]} - rust-ini = "0.17" --rustc-serialize = "0.3.24" - serde = "1.0.80" - serde_derive = "1.0.80" - serde_json = { version = "1.0", features = ["raw_value"] } --- -2.35.3 - - -From f7b59a6a7739d275ffe15a915eb48a36ceafccdd Mon Sep 17 00:00:00 2001 -From: Anderson Toshiyuki Sasaki -Date: Tue, 17 May 2022 18:56:50 +0200 -Subject: [PATCH 3/4] Drop unused dependency flate2 - -Signed-off-by: Anderson Toshiyuki Sasaki ---- - Cargo.lock | 1 - - Cargo.toml | 1 - - src/tpm.rs | 3 --- - 3 files changed, 5 deletions(-) - -diff --git a/Cargo.toml b/Cargo.toml -index 0f4e4ab..69d2eec 100644 ---- a/Cargo.toml -+++ b/Cargo.toml -@@ -23,7 +23,6 @@ base64 = "0.13" - cfg-if = "1" - clap = { version = "~3.1.18", features = ["derive"] } - compress-tools = "0.12" --flate2 = "1.0.4" - futures = "0.3.6" - hex = "0.4" - libc = "0.2.43" -diff --git a/src/tpm.rs b/src/tpm.rs -index 355dd0d..43129f1 100644 ---- a/src/tpm.rs -+++ b/src/tpm.rs -@@ -20,8 +20,6 @@ use openssl::{ - pkey::{Id, PKeyRef, Public}, - }; - --use flate2::{write::ZlibEncoder, Compression}; -- - use tss_esapi::{ - abstraction::{ - ak, -@@ -635,7 +633,6 @@ pub(crate) fn quote( - #[cfg(test)] - pub mod testing { - use super::*; -- use flate2::read::ZlibDecoder; - use tss_esapi::constants::structure_tags::StructureTag; - use tss_esapi::structures::{Attest, AttestBuffer, DigestList, Ticket}; - use tss_esapi::tss2_esys::Tss2_MU_TPMT_SIGNATURE_Unmarshal; --- -2.35.3 - - -From c3f0b4f603089d38715535f8e16b7a40f413e4de Mon Sep 17 00:00:00 2001 -From: Anderson Toshiyuki Sasaki -Date: Thu, 9 Jun 2022 16:21:06 +0200 -Subject: [PATCH 4/4] Make wiremock an optional dependency - -Make a wiremock optional, enabled when the 'testing' feature is enabled. -The goal is to reduce the number of dependencies, with the downside that -the test code coverage will drop. - -Wiremock is currently used only on 'registrar_agent' tests to mock -responses from the registrar service. - -Note: wiremock was moved to be an optional regular dependency because -optional dev-dependencies are not supported. -see: https://github.com/rust-lang/cargo/issues/1596 - -Signed-off-by: Anderson Toshiyuki Sasaki ---- - Cargo.toml | 7 +++++-- - src/registrar_agent.rs | 1 + - 2 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/Cargo.toml b/Cargo.toml -index 69d2eec..5052512 100644 ---- a/Cargo.toml -+++ b/Cargo.toml -@@ -43,16 +43,19 @@ tss-esapi = "7.1.0" - thiserror = "1.0" - uuid = {version = "0.8", features = ["v4"]} - zmq = {version = "0.9.2", optional = true} -+# wiremock was moved to be a regular dependency because optional -+# dev-dependencies are not supported -+# see: https://github.com/rust-lang/cargo/issues/1596 -+wiremock = {version = "0.5", optional = true} - - [dev-dependencies] - actix-rt = "2" --wiremock = "0.5" - - [features] - # The features enabled by default - default = ["with-zmq", "legacy-python-actions"] - # this should change to dev-dependencies when we have integration testing --testing = [] -+testing = ["wiremock"] - # Whether the agent should be compiled with support to listen for notification - # messages on ZeroMQ - with-zmq = ["zmq"] -diff --git a/src/registrar_agent.rs b/src/registrar_agent.rs -index 85b5931..b02ba48 100644 ---- a/src/registrar_agent.rs -+++ b/src/registrar_agent.rs -@@ -149,6 +149,7 @@ pub(crate) async fn do_register_agent( - } - } - -+#[cfg(feature = "testing")] - #[cfg(test)] - mod tests { - use super::*; --- -2.35.3 - diff --git a/rust-keylime-ima-emulator-hash-algorithms.patch b/rust-keylime-ima-emulator-hash-algorithms.patch deleted file mode 100644 index 66d21f7..0000000 --- a/rust-keylime-ima-emulator-hash-algorithms.patch +++ /dev/null @@ -1,899 +0,0 @@ -From d30000a1c3ae6cb8f6dc60c295e037614605b36e Mon Sep 17 00:00:00 2001 -From: Daiki Ueno -Date: Tue, 5 Jul 2022 16:24:32 +0900 -Subject: [PATCH 1/4] algorithms: Add conversion between our hash algorithms - and OpenSSL's - -Signed-off-by: Daiki Ueno ---- - src/algorithms.rs | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/src/algorithms.rs b/src/algorithms.rs -index 414ef100..019f9360 100644 ---- a/src/algorithms.rs -+++ b/src/algorithms.rs -@@ -1,5 +1,6 @@ - // SPDX-License-Identifier: Apache-2.0 - // Copyright 2021 Keylime Authors -+use openssl::hash::MessageDigest; - use serde::{Deserialize, Serialize}; - use std::convert::TryFrom; - use std::fmt; -@@ -74,6 +75,18 @@ impl From for HashingAlgorithm { - } - } - -+impl From for MessageDigest { -+ fn from(hash_algorithm: HashAlgorithm) -> Self { -+ match hash_algorithm { -+ HashAlgorithm::Sha1 => MessageDigest::sha1(), -+ HashAlgorithm::Sha256 => MessageDigest::sha256(), -+ HashAlgorithm::Sha384 => MessageDigest::sha384(), -+ HashAlgorithm::Sha512 => MessageDigest::sha512(), -+ HashAlgorithm::Sm3_256 => MessageDigest::sm3(), -+ } -+ } -+} -+ - #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] - pub enum EncryptionAlgorithm { - Rsa, - -From a90aa5b0852d587114aca7a8e79306987c562624 Mon Sep 17 00:00:00 2001 -From: Daiki Ueno -Date: Tue, 5 Jul 2022 15:43:42 +0900 -Subject: [PATCH 2/4] ima_entry: add IMA entry parser ported from Python - Keylime - -Signed-off-by: Daiki Ueno ---- - src/ima_entry.rs | 516 +++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 516 insertions(+) - create mode 100644 src/ima_entry.rs - -diff --git a/src/ima_entry.rs b/src/ima_entry.rs -new file mode 100644 -index 00000000..7bb4a970 ---- /dev/null -+++ b/src/ima_entry.rs -@@ -0,0 +1,516 @@ -+// SPDX-License-Identifier: Apache-2.0 -+// Copyright 2022 Keylime Authors -+ -+// Parser for IMA ASCII entries. -+// -+// Implements the templates (modes) and types as defined in: -+// https://elixir.bootlin.com/linux/latest/source/security/integrity/ima/ima_template.c -+// https://www.kernel.org/doc/html/v5.12/security/IMA-templates.html -+ -+use crate::algorithms::HashAlgorithm; -+use openssl::hash::MessageDigest; -+use std::convert::{TryFrom, TryInto}; -+use std::io::{Error, ErrorKind, Result, Write}; -+ -+pub trait Encode { -+ fn encode(&self, writer: &mut dyn Write) -> Result<()>; -+} -+ -+pub trait EncodeLegacy { -+ fn encode_legacy(&self, writer: &mut dyn Write) -> Result<()>; -+} -+ -+#[derive(PartialEq)] -+pub struct Digest { -+ pub algorithm: HashAlgorithm, -+ value: Vec, -+} -+ -+impl Digest { -+ pub fn new(algorithm: HashAlgorithm, value: &[u8]) -> Result { -+ let digest: MessageDigest = algorithm.into(); -+ if value.len() != digest.size() { -+ return Err(Error::new( -+ ErrorKind::InvalidInput, -+ "invalid digest value", -+ )); -+ } -+ let mut v = Vec::with_capacity(digest.size()); -+ v.extend_from_slice(value); -+ Ok(Self { -+ algorithm, -+ value: v, -+ }) -+ } -+ -+ pub fn value(&self) -> &[u8] { -+ &self.value -+ } -+ -+ pub fn start(algorithm: HashAlgorithm) -> Self { -+ let digest: MessageDigest = algorithm.into(); -+ Self { -+ algorithm, -+ value: vec![0x00u8; digest.size()], -+ } -+ } -+ -+ pub fn ff(algorithm: HashAlgorithm) -> Self { -+ let digest: MessageDigest = algorithm.into(); -+ Self { -+ algorithm, -+ value: vec![0xffu8; digest.size()], -+ } -+ } -+} -+ -+impl TryFrom<&str> for Digest { -+ type Error = std::io::Error; -+ -+ fn try_from(value: &str) -> std::result::Result { -+ let tokens: Vec<&str> = value.splitn(2, ':').collect(); -+ if tokens.len() == 1 { -+ Ok(Digest { -+ algorithm: HashAlgorithm::Sha1, -+ value: hex::decode(&tokens[0]).map_err(|_| { -+ Error::new( -+ ErrorKind::InvalidInput, -+ "invalid hex encoding", -+ ) -+ })?, -+ }) -+ } else { -+ Ok(Digest { -+ algorithm: tokens[0].try_into().map_err(|_| { -+ Error::new(ErrorKind::InvalidInput, "invalid algorithm") -+ })?, -+ value: hex::decode(&tokens[1]).map_err(|_| { -+ Error::new( -+ ErrorKind::InvalidInput, -+ "invalid hex encoding", -+ ) -+ })?, -+ }) -+ } -+ } -+} -+ -+impl Encode for Digest { -+ fn encode(&self, writer: &mut dyn Write) -> Result<()> { -+ if self.algorithm == HashAlgorithm::Sha1 { -+ writer.write_all(&(self.value.len() as u32).to_le_bytes())?; -+ writer.write_all(&self.value)?; -+ } else { -+ let algorithm = format!("{}", self.algorithm); -+ let total_len = algorithm.len() + 2 + self.value.len(); -+ writer.write_all(&(total_len as u32).to_le_bytes())?; -+ writer.write_all(algorithm.as_bytes())?; -+ writer.write_all(&[58u8, 0u8])?; -+ writer.write_all(&self.value)?; -+ } -+ Ok(()) -+ } -+} -+ -+impl EncodeLegacy for Digest { -+ fn encode_legacy(&self, writer: &mut dyn Write) -> Result<()> { -+ writer.write_all(&self.value)?; -+ Ok(()) -+ } -+} -+ -+struct Name { -+ name: String, -+} -+ -+impl TryFrom<&str> for Name { -+ type Error = std::io::Error; -+ -+ fn try_from(value: &str) -> std::result::Result { -+ Ok(Self { -+ name: value.to_string(), -+ }) -+ } -+} -+ -+const TCG_EVENT_NAME_LEN_MAX: usize = 255; -+ -+impl Encode for Name { -+ fn encode(&self, writer: &mut dyn Write) -> Result<()> { -+ let bytes = self.name.as_bytes(); -+ writer.write_all(&((bytes.len() + 1) as u32).to_le_bytes())?; -+ writer.write_all(bytes)?; -+ writer.write_all(&[0u8])?; // NUL -+ Ok(()) -+ } -+} -+ -+impl EncodeLegacy for Name { -+ fn encode_legacy(&self, writer: &mut dyn Write) -> Result<()> { -+ let bytes = self.name.as_bytes(); -+ writer.write_all(bytes)?; -+ writer.write_all(&vec![0u8; TCG_EVENT_NAME_LEN_MAX - bytes.len()])?; -+ Ok(()) -+ } -+} -+ -+struct Signature { -+ value: Vec, -+} -+ -+impl TryFrom<&str> for Signature { -+ type Error = std::io::Error; -+ -+ fn try_from(value: &str) -> std::result::Result { -+ let value = hex::decode(value).map_err(|_| { -+ Error::new(ErrorKind::InvalidInput, "invalid hex encoding") -+ })?; -+ // basic checks on signature -+ if value.len() < 9 { -+ return Err(Error::new( -+ ErrorKind::InvalidInput, -+ "invalid signature", -+ )); -+ } -+ let sig_size = u16::from_be_bytes(value[7..9].try_into().unwrap()); //#[allow_ci] -+ if (sig_size as usize) + 9 != value.len() { -+ return Err(Error::new( -+ ErrorKind::InvalidInput, -+ "invalid signature", -+ )); -+ } -+ Ok(Self { value }) -+ } -+} -+ -+impl Encode for Signature { -+ fn encode(&self, writer: &mut dyn Write) -> Result<()> { -+ writer.write_all(&(self.value.len() as u32).to_le_bytes())?; -+ writer.write_all(&self.value)?; -+ Ok(()) -+ } -+} -+ -+struct Buffer { -+ value: Vec, -+} -+ -+impl TryFrom<&str> for Buffer { -+ type Error = std::io::Error; -+ -+ fn try_from(value: &str) -> std::result::Result { -+ Ok(Self { -+ value: hex::decode(value).map_err(|_| { -+ Error::new(ErrorKind::InvalidInput, "invalid hex encoding") -+ })?, -+ }) -+ } -+} -+ -+impl Encode for Buffer { -+ fn encode(&self, writer: &mut dyn Write) -> Result<()> { -+ writer.write_all(&(self.value.len() as u32).to_le_bytes())?; -+ writer.write_all(&self.value)?; -+ Ok(()) -+ } -+} -+ -+pub trait EventData: Encode { -+ fn path(&self) -> &str; -+} -+ -+struct Ima { -+ digest: Digest, -+ path: Name, -+} -+ -+impl TryFrom<&str> for Ima { -+ type Error = std::io::Error; -+ -+ fn try_from(value: &str) -> std::result::Result { -+ let tokens: Vec<&str> = value.splitn(2, ' ').collect(); -+ if tokens.len() != 2 { -+ return Err(Error::new(ErrorKind::InvalidInput, value)); -+ } -+ Ok(Self { -+ digest: Digest::try_from(tokens[0])?, -+ path: Name::try_from(tokens[1])?, -+ }) -+ } -+} -+ -+impl EventData for Ima { -+ fn path(&self) -> &str { -+ &self.path.name -+ } -+} -+ -+impl Encode for Ima { -+ fn encode(&self, writer: &mut dyn Write) -> Result<()> { -+ self.digest.encode_legacy(writer)?; -+ self.path.encode_legacy(writer)?; -+ Ok(()) -+ } -+} -+ -+struct ImaNg { -+ digest: Digest, -+ path: Name, -+} -+ -+impl TryFrom<&str> for ImaNg { -+ type Error = std::io::Error; -+ -+ fn try_from(value: &str) -> std::result::Result { -+ let tokens: Vec<&str> = value.splitn(2, ' ').collect(); -+ if tokens.len() != 2 { -+ return Err(Error::new(ErrorKind::InvalidInput, value)); -+ } -+ -+ Ok(Self { -+ digest: Digest::try_from(tokens[0])?, -+ path: Name::try_from(tokens[1])?, -+ }) -+ } -+} -+ -+impl EventData for ImaNg { -+ fn path(&self) -> &str { -+ &self.path.name -+ } -+} -+ -+impl Encode for ImaNg { -+ fn encode(&self, writer: &mut dyn Write) -> Result<()> { -+ self.digest.encode(writer)?; -+ self.path.encode(writer)?; -+ Ok(()) -+ } -+} -+ -+struct ImaSig { -+ digest: Digest, -+ path: Name, -+ signature: Option, -+} -+ -+impl EventData for ImaSig { -+ fn path(&self) -> &str { -+ &self.path.name -+ } -+} -+ -+impl TryFrom<&str> for ImaSig { -+ type Error = std::io::Error; -+ -+ fn try_from(value: &str) -> std::result::Result { -+ // extract signature first -+ let (value, signature) = value -+ .rsplit_once(' ') -+ .ok_or_else(|| Error::new(ErrorKind::InvalidInput, value))?; -+ -+ // parse d-ng|n-ng as in ima-ng -+ let tokens: Vec<&str> = value.splitn(2, ' ').collect(); -+ if tokens.len() != 2 { -+ return Err(Error::new(ErrorKind::InvalidInput, value)); -+ } -+ -+ let digest = Digest::try_from(tokens[0])?; -+ let path = Name::try_from(tokens[1])?; -+ let signature = if !signature.is_empty() { -+ Some(Signature::try_from(signature)?) -+ } else { -+ None -+ }; -+ -+ Ok(Self { -+ digest, -+ path, -+ signature, -+ }) -+ } -+} -+ -+impl Encode for ImaSig { -+ fn encode(&self, writer: &mut dyn Write) -> Result<()> { -+ self.digest.encode(writer)?; -+ self.path.encode(writer)?; -+ if let Some(signature) = &self.signature { -+ signature.encode(writer)?; -+ } else { -+ writer.write_all(&0u32.to_le_bytes())?; -+ } -+ Ok(()) -+ } -+} -+ -+struct ImaBuf { -+ digest: Digest, -+ name: Name, -+ data: Buffer, -+} -+ -+impl TryFrom<&str> for ImaBuf { -+ type Error = std::io::Error; -+ -+ fn try_from(value: &str) -> std::result::Result { -+ let tokens: Vec<&str> = value.splitn(3, ' ').collect(); -+ if tokens.len() != 3 { -+ return Err(Error::new(ErrorKind::InvalidInput, value)); -+ } -+ Ok(Self { -+ digest: Digest::try_from(tokens[0])?, -+ name: Name::try_from(tokens[1])?, -+ data: Buffer::try_from(tokens[2])?, -+ }) -+ } -+} -+ -+impl EventData for ImaBuf { -+ fn path(&self) -> &str { -+ &self.name.name -+ } -+} -+ -+impl Encode for ImaBuf { -+ fn encode(&self, writer: &mut dyn Write) -> Result<()> { -+ self.digest.encode(writer)?; -+ self.name.encode(writer)?; -+ self.data.encode(writer)?; -+ Ok(()) -+ } -+} -+ -+pub struct Entry { -+ pub template_hash: Digest, -+ pub event_data: Box, -+} -+ -+impl TryFrom<&str> for Entry { -+ type Error = std::io::Error; -+ -+ fn try_from(value: &str) -> std::result::Result { -+ let tokens: Vec<&str> = value.splitn(4, ' ').collect(); -+ if tokens.len() != 4 { -+ return Err(Error::new(ErrorKind::InvalidInput, value)); -+ } -+ -+ let template_hash = Digest { -+ algorithm: HashAlgorithm::Sha1, -+ value: hex::decode(&tokens[1]).map_err(|_| { -+ Error::new(ErrorKind::InvalidInput, "invalid hex encoding") -+ })?, -+ }; -+ let mode = tokens[2]; -+ let event = tokens[3]; -+ -+ match mode { -+ "ima" => Ok(Self { -+ template_hash, -+ event_data: Box::new(Ima::try_from(event)?), -+ }), -+ "ima-ng" => Ok(Self { -+ template_hash, -+ event_data: Box::new(ImaNg::try_from(event)?), -+ }), -+ "ima-sig" => Ok(Self { -+ template_hash, -+ event_data: Box::new(ImaSig::try_from(event)?), -+ }), -+ "ima-buf" => Ok(Self { -+ template_hash, -+ event_data: Box::new(ImaBuf::try_from(event)?), -+ }), -+ template => Err(Error::new( -+ ErrorKind::Other, -+ format!("unrecognized template \"{}\"", template,), -+ )), -+ } -+ } -+} -+ -+// Unit Testing -+#[cfg(test)] -+mod tests { -+ use super::*; -+ -+ #[test] -+ fn test_parse_ima() { -+ let entry: Entry = "10 d7026dc672344d3ee372217bdbc7395947788671 ima 6f66d1d8e2fffcc12dfcb78c04b81fe5b8bbae4e /usr/bin/kmod" -+ .try_into().expect("unable to parse ima template"); -+ assert_eq!(entry.event_data.path(), "/usr/bin/kmod"); -+ let mut buf = vec![]; -+ entry -+ .event_data -+ .encode(&mut buf) -+ .expect("unable to encode event data"); -+ assert_eq!( -+ &buf, -+ &hex::decode("6f66d1d8e2fffcc12dfcb78c04b81fe5b8bbae4e2f7573722f62696e2f6b6d6f640000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap(), //#[allow_ci] -+ ); -+ } -+ -+ #[test] -+ fn test_parse_ima_ng() { -+ let entry: Entry = "10 7936eb315fb4e74b99e7d461bc5c96049e1ee092 ima-ng sha1:bc026ae66d81713e4e852465e980784dc96651f8 /usr/lib/systemd/systemd" -+ .try_into().expect("unable to parse ima-ng template"); -+ assert_eq!(entry.event_data.path(), "/usr/lib/systemd/systemd"); -+ let mut buf = vec![]; -+ entry -+ .event_data -+ .encode(&mut buf) -+ .expect("unable to encode event data"); -+ assert_eq!( -+ &buf, -+ &hex::decode("14000000bc026ae66d81713e4e852465e980784dc96651f8190000002f7573722f6c69622f73797374656d642f73797374656d6400").unwrap(), //#[allow_ci] -+ ); -+ } -+ -+ #[test] -+ fn test_parse_ima_sig() { -+ let entry: Entry = "10 06e804489a77ddab51b9ef27e17053c0e5d503bd ima-sig sha1:1cb84b12db45d7da8de58ba6744187db84082f0e /usr/bin/zmore 030202531f402500483046022100bff9c02dc7b270c83cc94bfec10eecd42831de2cdcb04f024369a14623bc3a91022100cc4d015ae932fb98d6846645ed7d1bb1afd4621ec9089bc087126f191886dd31" -+ .try_into().expect("unable to parse ima-sig template"); -+ assert_eq!(entry.event_data.path(), "/usr/bin/zmore"); -+ let mut buf = vec![]; -+ entry -+ .event_data -+ .encode(&mut buf) -+ .expect("unable to encode event data"); -+ assert_eq!( -+ &buf, -+ &hex::decode("140000001cb84b12db45d7da8de58ba6744187db84082f0e0f0000002f7573722f62696e2f7a6d6f72650051000000030202531f402500483046022100bff9c02dc7b270c83cc94bfec10eecd42831de2cdcb04f024369a14623bc3a91022100cc4d015ae932fb98d6846645ed7d1bb1afd4621ec9089bc087126f191886dd31").unwrap(), //#[allow_ci] -+ ); -+ } -+ -+ #[test] -+ fn test_parse_ima_sig_missing() { -+ let entry: Entry = "10 5426cf3031a43f5bfca183d79950698a95a728f6 ima-sig sha256:f1125b940480d20ad841d26d5ea253edc0704b5ec1548c891edf212cb1a9365e /lib/modules/5.4.48-openpower1/kernel/drivers/usb/common/usb-common.ko " -+ .try_into().expect("unable to parse ima-sig template without signature"); -+ assert_eq!(entry.event_data.path(), "/lib/modules/5.4.48-openpower1/kernel/drivers/usb/common/usb-common.ko"); -+ let mut buf = vec![]; -+ entry -+ .event_data -+ .encode(&mut buf) -+ .expect("unable to encode event data"); -+ assert_eq!( -+ &buf, -+ &hex::decode("280000007368613235363a00f1125b940480d20ad841d26d5ea253edc0704b5ec1548c891edf212cb1a9365e470000002f6c69622f6d6f64756c65732f352e342e34382d6f70656e706f776572312f6b65726e656c2f647269766572732f7573622f636f6d6d6f6e2f7573622d636f6d6d6f6e2e6b6f0000000000").unwrap(), //#[allow_ci] -+ ); -+ } -+ -+ #[test] -+ fn test_parse_ima_buf() { -+ let entry: Entry = "10 b7862dbbf1383ac6c7cca7f02d981a081aacb1f1 ima-buf sha1:6e0e6fc8a188ef4f059638949adca4d221946906 device_resume 6e616d653d544553543b757569643d43525950542d5645524954592d39656633326535623635623034343234613561386562343436636630653731332d544553543b63617061636974793d303b6d616a6f723d3235333b6d696e6f723d303b6d696e6f725f636f756e743d313b6e756d5f746172676574733d313b6163746976655f7461626c655f686173683d346565383065333365353635643336333430356634303238393436653837623365396563306335383661666639656630656436663561653762656237326431333b" -+ .try_into().expect("unable to parse ima-buf template"); -+ assert_eq!(entry.event_data.path(), "device_resume"); -+ let mut buf = vec![]; -+ entry -+ .event_data -+ .encode(&mut buf) -+ .expect("unable to encode event data"); -+ assert_eq!( -+ &buf, -+ &hex::decode("140000006e0e6fc8a188ef4f059638949adca4d2219469060e0000006465766963655f726573756d6500ce0000006e616d653d544553543b757569643d43525950542d5645524954592d39656633326535623635623034343234613561386562343436636630653731332d544553543b63617061636974793d303b6d616a6f723d3235333b6d696e6f723d303b6d696e6f725f636f756e743d313b6e756d5f746172676574733d313b6163746976655f7461626c655f686173683d346565383065333365353635643336333430356634303238393436653837623365396563306335383661666639656630656436663561653762656237326431333b").unwrap(), //#[allow_ci] -+ ); -+ } -+} - -From 7decf3b0985235e28f36c1b445def535d615c8df Mon Sep 17 00:00:00 2001 -From: Daiki Ueno -Date: Sun, 15 May 2022 17:46:36 +0200 -Subject: [PATCH 3/4] ima_emulator: Support PCR hash algorithms other than - SHA-1 - -This ports the recent changes to keylime_ima_emulator in the Python -stack, which allows PCR hash algorithms other than SHA-1 through the -command-line options. - -Signed-off-by: Daiki Ueno ---- - src/algorithms.rs | 1 - - src/ima_emulator.rs | 176 ++++++++++++++++++++++++++++++-------------- - 2 files changed, 122 insertions(+), 55 deletions(-) - -diff --git a/src/algorithms.rs b/src/algorithms.rs -index 019f9360..3386abd7 100644 ---- a/src/algorithms.rs -+++ b/src/algorithms.rs -@@ -10,7 +10,6 @@ use tss_esapi::{ - AsymmetricAlgorithm, HashingAlgorithm, SignatureSchemeAlgorithm, - }, - structures::{HashScheme, SignatureScheme}, -- tss2_esys::TPMT_SIG_SCHEME, - }; - - // This error needs to be public because we implement TryFrom for public types -diff --git a/src/ima_emulator.rs b/src/ima_emulator.rs -index ba590bbc..c09e41b6 100644 ---- a/src/ima_emulator.rs -+++ b/src/ima_emulator.rs -@@ -1,28 +1,32 @@ - // SPDX-License-Identifier: Apache-2.0 - // Copyright 2021 Keylime Authors - -+mod algorithms; -+use crate::algorithms::HashAlgorithm; -+mod ima_entry; -+use openssl::hash::{hash, MessageDigest}; -+ - use log::*; - --use std::convert::TryFrom; -+use clap::Parser; -+use std::collections::HashMap; -+use std::convert::{TryFrom, TryInto}; - use std::fs::File; - use std::io::prelude::*; - use std::io::BufReader; -+use std::path::{Path, PathBuf}; - - use thiserror::Error; - - use tss_esapi::{ - abstraction::pcr, - handles::PcrHandle, -- interface_types::algorithm::HashingAlgorithm, - structures::{Digest, DigestValues, PcrSelectionListBuilder, PcrSlot}, - Context, Tcti, - }; - - const IMA_ML: &str = "/sys/kernel/security/ima/ascii_runtime_measurements"; - --const START_HASH: &[u8; 20] = &[0u8; 20]; --const FF_HASH: &[u8; 20] = &[0xffu8; 20]; -- - #[derive(Error, Debug)] - enum ImaEmulatorError { - #[error("Invalid envvar")] -@@ -31,8 +35,14 @@ enum ImaEmulatorError { - TssEsapiError(#[from] tss_esapi::Error), - #[error("Decoding error")] - FromHexError(#[from] hex::FromHexError), -+ #[error("Algorithm error")] -+ AlgorithmError(#[from] algorithms::AlgorithmError), -+ #[error("OpenSSL error")] -+ OpenSSLError(#[from] openssl::error::ErrorStack), - #[error("I/O error")] - IoError(#[from] std::io::Error), -+ #[error("Integer parsing error")] -+ ParseInt(#[from] std::num::ParseIntError), - #[error("{0}")] - Other(String), - } -@@ -41,57 +51,75 @@ type Result = std::result::Result; - - fn ml_extend( - context: &mut Context, -- ml: &str, -+ ml: &Path, - mut position: usize, -+ ima_hash_alg: HashAlgorithm, -+ pcr_hash_alg: HashAlgorithm, - search_hash: Option<&Digest>, - ) -> Result { - let f = File::open(ml)?; - let mut reader = BufReader::new(f); -- let mut running_hash: Vec = Vec::from(&START_HASH[..]); -+ let ima_digest: MessageDigest = ima_hash_alg.into(); -+ let ima_start_hash = ima_entry::Digest::start(ima_hash_alg); -+ let pcr_digest: MessageDigest = pcr_hash_alg.into(); -+ let mut running_hash = ima_entry::Digest::start(pcr_hash_alg); -+ let ff_hash = ima_entry::Digest::ff(pcr_hash_alg); - for line in reader.by_ref().lines().skip(position) { - let line = line?; - if line.is_empty() { - continue; - } -- let tokens: Vec<&str> = line.splitn(5, ' ').collect(); -- if tokens.len() < 5 { -- error!("invalid measurement list file line: -{}-", line); -- } -+ -+ let entry: ima_entry::Entry = line.as_str().try_into()?; -+ - position += 1; - -- let path = tokens[4]; -- let template_hash = hex::decode(tokens[1])?; -- let template_hash = if template_hash == START_HASH { -- Digest::try_from(&FF_HASH[..]) -+ // Set correct hash for time of measure, time of use (ToMToU) errors -+ // and if a file is already opened for write. -+ // https://elixir.bootlin.com/linux/v5.12.12/source/security/integrity/ima/ima_main.c#L101 -+ let pcr_template_hash = if entry.template_hash == ima_start_hash { -+ Digest::try_from(ff_hash.value()) - } else { -- Digest::try_from(template_hash) -+ let mut event_data = vec![]; -+ entry.event_data.encode(&mut event_data)?; -+ let pcr_event_hash = hash(pcr_digest, &event_data)?; -+ let ima_event_hash = hash(ima_digest, &event_data)?; -+ if ima_event_hash.as_ref() != entry.template_hash.value() { -+ return Err(ImaEmulatorError::Other( -+ "IMA template hash doesn't match".to_string(), -+ )); -+ } -+ Digest::try_from(pcr_event_hash.as_ref()) - }?; - - match search_hash { - None => { - println!( - "extending hash {} for {}", -- hex::encode(template_hash.value()), -- &path -+ hex::encode(pcr_template_hash.value()), -+ entry.event_data.path(), - ); - let mut vals = DigestValues::new(); -- vals.set(HashingAlgorithm::Sha1, template_hash); -- // TODO: Add support for other hash algorithms -+ vals.set(pcr_hash_alg.into(), pcr_template_hash); - context.execute_with_nullauth_session(|ctx| { - ctx.pcr_extend(PcrHandle::Pcr10, vals) - })?; - } - Some(search_hash) => { -- let mut hasher = openssl::sha::Sha1::new(); -- hasher.update(&running_hash); -- hasher.update(&template_hash); -- running_hash = hasher.finish().into(); -- let digest = Digest::try_from(running_hash.as_slice())?; -+ let mut hasher = openssl::hash::Hasher::new(pcr_digest)?; -+ hasher.update(running_hash.value())?; -+ hasher.update(&pcr_template_hash)?; -+ running_hash = -+ ima_entry::Digest::new(pcr_hash_alg, &hasher.finish()?)?; -+ let digest = Digest::try_from(running_hash.value())?; - let mut vals = DigestValues::new(); -- vals.set(HashingAlgorithm::Sha1, digest.clone()); -+ vals.set(pcr_hash_alg.into(), digest.clone()); - - if digest == *search_hash { -- println!("Located last IMA file updated: {}", path); -+ println!( -+ "Located last IMA file updated: {}", -+ entry.event_data.path() -+ ); - return Ok(position); - } - } -@@ -106,7 +134,20 @@ fn ml_extend( - Ok(position) - } - -+#[derive(Parser)] -+#[clap(about)] -+struct Args { -+ #[clap(long = "hash_algs", short = 'a', default_value = "sha1")] -+ hash_algs: Vec, -+ #[clap(long, short = 'i', default_value = "sha1")] -+ ima_hash_alg: String, -+ #[clap(long, short = 'f', default_value = IMA_ML)] -+ ima_log: PathBuf, -+} -+ - fn main() -> std::result::Result<(), ImaEmulatorError> { -+ let args = Args::parse(); -+ - let tcti = - match Tcti::from_environment_variable() { - Ok(tcti) => tcti, -@@ -124,37 +165,64 @@ fn main() -> std::result::Result<(), ImaEmulatorError> { - )); - } - -- // check if pcr is clean -- let pcr_list = PcrSelectionListBuilder::new() -- .with_selection(HashingAlgorithm::Sha1, &[PcrSlot::Slot10]) -- .build()?; -- let pcr_data = context -- .execute_without_session(|ctx| pcr::read_all(ctx, pcr_list))?; -- let digest = pcr_data -- .pcr_bank(HashingAlgorithm::Sha1) -- .ok_or_else(|| { -- ImaEmulatorError::Other( -- "IMA slot does not have SHA-1 bank".to_string(), -- ) -- })? -- .get_digest(PcrSlot::Slot10) -- .ok_or_else(|| { -- ImaEmulatorError::Other( -- "could not read value from IMA PCR".to_string(), -- ) -- })?; -- -- let mut pos = 0; -- -- if digest.value() != START_HASH { -- log::warn!("IMA PCR is not empty, trying to find the last updated file in the measurement list..."); -- pos = ml_extend(&mut context, IMA_ML, 0, Some(digest))?; -+ let ima_hash_alg: HashAlgorithm = -+ args.ima_hash_alg.as_str().try_into()?; -+ let mut positions = HashMap::new(); -+ for pcr_hash_alg in args.hash_algs { -+ let pcr_hash_alg: HashAlgorithm = pcr_hash_alg.as_str().try_into()?; -+ positions.insert(pcr_hash_alg, 0usize); -+ } -+ -+ for (pcr_hash_alg, position) in positions.iter_mut() { -+ // check if pcr is clean -+ let pcr_list = PcrSelectionListBuilder::new() -+ .with_selection((*pcr_hash_alg).into(), &[PcrSlot::Slot10]) -+ .build()?; -+ let pcr_data = context -+ .execute_without_session(|ctx| pcr::read_all(ctx, pcr_list))?; -+ let digest = pcr_data -+ .pcr_bank((*pcr_hash_alg).into()) -+ .ok_or_else(|| { -+ ImaEmulatorError::Other(format!( -+ "IMA slot does not have {} bank", -+ *pcr_hash_alg, -+ )) -+ })? -+ .get_digest(PcrSlot::Slot10) -+ .ok_or_else(|| { -+ ImaEmulatorError::Other( -+ "could not read value from IMA PCR".to_string(), -+ ) -+ })?; -+ -+ let pcr_digest: MessageDigest = (*pcr_hash_alg).into(); -+ let pcr_start_hash = vec![0x00u8; pcr_digest.size()]; -+ if digest.value() != pcr_start_hash { -+ log::warn!("IMA PCR is not empty, trying to find the last updated file in the measurement list..."); -+ *position = ml_extend( -+ &mut context, -+ &args.ima_log, -+ *position, -+ ima_hash_alg, -+ *pcr_hash_alg, -+ Some(digest), -+ )?; -+ } - } - -- println!("Monitoring {}", IMA_ML); -+ println!("Monitoring {}", args.ima_log.display()); - - loop { -- pos = ml_extend(&mut context, IMA_ML, pos, None)?; -+ for (pcr_hash_alg, position) in positions.iter_mut() { -+ *position = ml_extend( -+ &mut context, -+ &args.ima_log, -+ *position, -+ ima_hash_alg, -+ *pcr_hash_alg, -+ None, -+ )?; -+ } - - // FIXME: We could poll IMA_ML as in the python implementation, though - // the file is not pollable: - -From d0e2dd7dc9f24df1eb5ff3f8cde95e5e561992d6 Mon Sep 17 00:00:00 2001 -From: Karel Srot -Date: Wed, 6 Jul 2022 22:02:53 +0200 -Subject: [PATCH 4/4] Enable usage of Rust IMA emulator in E2E tests. - -Instalation of Rust IMA emulator has been implemented in -https://github.com/RedHat-SP-Security/keylime-tests/pull/141 - -Signed-off-by: Karel Srot ---- - packit-ci.fmf | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/packit-ci.fmf b/packit-ci.fmf -index 9a9f9581..064bc0ae 100644 ---- a/packit-ci.fmf -+++ b/packit-ci.fmf -@@ -4,6 +4,7 @@ - - environment: - TPM_BINARY_MEASUREMENTS: /var/tmp/binary_bios_measurements -+ RUST_IMA_EMULATOR: 1 - - prepare: - how: shell diff --git a/rust-keylime-load-config-once.patch b/rust-keylime-load-config-once.patch deleted file mode 100644 index 9601438..0000000 --- a/rust-keylime-load-config-once.patch +++ /dev/null @@ -1,339 +0,0 @@ ---- a/src/common.rs 2022-06-03 17:28:38.000000000 +0200 -+++ b/src/common.rs 2022-07-04 13:48:28.257066939 +0200 -@@ -231,59 +231,122 @@ - - impl KeylimeConfig { - pub fn build() -> Result { -- let agent_ip = -- config_get_env("cloud_agent", "cloudagent_ip", "CLOUDAGENT_IP")?; -+ let conf_name = config_file_get(); -+ let conf = Ini::load_from_file(&conf_name)?; -+ -+ let agent_ip = config_get_env( -+ &conf_name, -+ &conf, -+ "cloud_agent", -+ "cloudagent_ip", -+ "CLOUDAGENT_IP", -+ )?; - let agent_port = config_get_env( -+ &conf_name, -+ &conf, - "cloud_agent", - "cloudagent_port", - "CLOUDAGENT_PORT", - )?; -- let registrar_ip = -- config_get_env("cloud_agent", "registrar_ip", "REGISTRAR_IP")?; -+ let registrar_ip = config_get_env( -+ &conf_name, -+ &conf, -+ "cloud_agent", -+ "registrar_ip", -+ "REGISTRAR_IP", -+ )?; - let registrar_port = config_get_env( -+ &conf_name, -+ &conf, - "cloud_agent", - "registrar_port", - "REGISTRAR_PORT", - )?; -- let agent_uuid_config = config_get("cloud_agent", "agent_uuid")?; -+ let agent_uuid_config = -+ config_get(&conf_name, &conf, "cloud_agent", "agent_uuid")?; - let agent_uuid = get_uuid(&agent_uuid_config); -- let agent_contact_ip = cloudagent_contact_ip_get(); -- let agent_contact_port = cloudagent_contact_port_get()?; -+ let agent_contact_ip = cloudagent_contact_ip_get(&conf_name, &conf); -+ let agent_contact_port = -+ cloudagent_contact_port_get(&conf_name, &conf)?; - let hash_alg = HashAlgorithm::try_from( -- config_get("cloud_agent", "tpm_hash_alg")?.as_str(), -+ config_get(&conf_name, &conf, "cloud_agent", "tpm_hash_alg")? -+ .as_str(), - )?; - let enc_alg = EncryptionAlgorithm::try_from( -- config_get("cloud_agent", "tpm_encryption_alg")?.as_str(), -+ config_get( -+ &conf_name, -+ &conf, -+ "cloud_agent", -+ "tpm_encryption_alg", -+ )? -+ .as_str(), - )?; - let sign_alg = SignAlgorithm::try_from( -- config_get("cloud_agent", "tpm_signing_alg")?.as_str(), -+ config_get(&conf_name, &conf, "cloud_agent", "tpm_signing_alg")? -+ .as_str(), - )?; - // There was a typo in Python Keylime and this accounts for having a version - // of Keylime installed that still has this typo. TODO: Remove later - let run_revocation = bool::from_str( -- &config_get("cloud_agent", "listen_notifications") -- .or_else(|_| { -- config_get("cloud_agent", "listen_notfications") -- })? -- .to_lowercase(), -- )?; -- let revocation_cert = config_get("cloud_agent", "revocation_cert")?; -- let revocation_ip = config_get("general", "receive_revocation_ip")?; -- let revocation_port = -- config_get("general", "receive_revocation_port")?; -+ &config_get( -+ &conf_name, -+ &conf, -+ "cloud_agent", -+ "listen_notifications", -+ ) -+ .or_else(|_| { -+ config_get( -+ &conf_name, -+ &conf, -+ "cloud_agent", -+ "listen_notfications", -+ ) -+ })? -+ .to_lowercase(), -+ )?; -+ let revocation_cert = -+ config_get(&conf_name, &conf, "cloud_agent", "revocation_cert")?; -+ let revocation_ip = config_get( -+ &conf_name, -+ &conf, -+ "general", -+ "receive_revocation_ip", -+ )?; -+ let revocation_port = config_get( -+ &conf_name, -+ &conf, -+ "general", -+ "receive_revocation_port", -+ )?; - -- let secure_size = config_get("cloud_agent", "secure_size")?; -- let payload_script = config_get("cloud_agent", "payload_script")?; -+ let secure_size = -+ config_get(&conf_name, &conf, "cloud_agent", "secure_size")?; -+ let payload_script = -+ config_get(&conf_name, &conf, "cloud_agent", "payload_script")?; - let dec_payload_filename = -- config_get("cloud_agent", "dec_payload_file")?; -- let key_filename = config_get("cloud_agent", "enc_keyname")?; -+ config_get(&conf_name, &conf, "cloud_agent", "dec_payload_file")?; -+ -+ let key_filename = -+ config_get(&conf_name, &conf, "cloud_agent", "enc_keyname")?; - let extract_payload_zip = bool::from_str( -- &config_get("cloud_agent", "extract_payload_zip")?.to_lowercase(), -+ &config_get( -+ &conf_name, -+ &conf, -+ "cloud_agent", -+ "extract_payload_zip", -+ )? -+ .to_lowercase(), - )?; - -- let work_dir = -- config_get_env("cloud_agent", "keylime_dir", "KEYLIME_DIR") -- .or_else::(|_| Ok(String::from(WORK_DIR)))?; -+ -+ let work_dir = config_get_env( -+ &conf_name, -+ &conf, -+ "cloud_agent", -+ "keylime_dir", -+ "KEYLIME_DIR", -+ ) -+ .or_else::(|_| Ok(String::from(WORK_DIR)))?; - - let tpm_data_path = PathBuf::from(&work_dir).join(TPM_DATA); - let tpm_data = if tpm_data_path.exists() { -@@ -302,20 +365,31 @@ - None - }; - -- let mut keylime_ca_path = config_get("cloud_agent", "keylime_ca")?; -+ let mut keylime_ca_path = -+ config_get(&conf_name, &conf, "cloud_agent", "keylime_ca")?; - if keylime_ca_path == "default" { - keylime_ca_path = Path::new(&work_dir) - .join(DEFAULT_CA_PATH) - .display() - .to_string(); - } -- let revocation_actions = -- config_get("cloud_agent", "revocation_actions") -- .or_else::(|_| Ok(String::from(REV_ACTIONS)))?; -- let revocation_actions_dir = -- config_get("cloud_agent", "revocation_actions_dir") -- .or_else::(|_| Ok(String::from(REV_ACTIONS_DIR)))?; -+ let revocation_actions = config_get( -+ &conf_name, -+ &conf, -+ "cloud_agent", -+ "revocation_actions", -+ ) -+ .or_else::(|_| Ok(String::from(REV_ACTIONS)))?; -+ let revocation_actions_dir = config_get( -+ &conf_name, -+ &conf, -+ "cloud_agent", -+ "revocation_actions_dir", -+ ) -+ .or_else::(|_| Ok(String::from(REV_ACTIONS_DIR)))?; - let allow_payload_revocation_actions = match config_get( -+ &conf_name, -+ &conf, - "cloud_agent", - "allow_payload_revocation_actions", - ) { -@@ -323,7 +397,7 @@ - Err(_) => ALLOW_PAYLOAD_REV_ACTIONS, - }; - let run_as = if permissions::get_euid() == 0 { -- match config_get("cloud_agent", "run_as") { -+ match config_get(&conf_name, &conf, "cloud_agent", "run_as") { - Ok(user_group) => Some(user_group), - Err(_) => { - warn!("Cannot drop privileges since 'run_as' is empty or missing in 'cloud_agent' section of keylime.conf."); -@@ -334,19 +408,27 @@ - None - }; - -- let mtls_enabled = -- match config_get("cloud_agent", "mtls_cert_enabled") { -- Ok(enabled) => bool::from_str(&enabled.to_lowercase()) -- .or::(Ok(MTLS_ENABLED))?, -- Err(_) => true, -- }; -- -- let enable_insecure_payload = -- match config_get("cloud_agent", "enable_insecure_payload") { -- Ok(allowed) => bool::from_str(&allowed.to_lowercase()) -- .or::(Ok(ALLOW_INSECURE_PAYLOAD))?, -- Err(_) => false, -- }; -+ let mtls_enabled = match config_get( -+ &conf_name, -+ &conf, -+ "cloud_agent", -+ "mtls_cert_enabled", -+ ) { -+ Ok(enabled) => bool::from_str(&enabled.to_lowercase()) -+ .or::(Ok(MTLS_ENABLED))?, -+ Err(_) => true, -+ }; -+ -+ let enable_insecure_payload = match config_get( -+ &conf_name, -+ &conf, -+ "cloud_agent", -+ "enable_insecure_payload", -+ ) { -+ Ok(allowed) => bool::from_str(&allowed.to_lowercase()) -+ .or::(Ok(ALLOW_INSECURE_PAYLOAD))?, -+ Err(_) => false, -+ }; - - Ok(KeylimeConfig { - agent_ip, -@@ -477,19 +559,11 @@ - } - } - --/// Returns revocation ip from keylime.conf if env var not present --fn revocation_ip_get() -> Result { -- config_get_env("general", "receive_revocation_ip", "REVOCATION_IP") --} -- --/// Returns revocation port from keylime.conf if env var not present --fn revocation_port_get() -> Result { -- config_get_env("general", "receive_revocation_port", "REVOCATION_PORT") --} -- - /// Returns the contact ip for the agent if set --fn cloudagent_contact_ip_get() -> Option { -+fn cloudagent_contact_ip_get(conf_name: &str, conf: &Ini) -> Option { - match config_get_env( -+ conf_name, -+ conf, - "cloud_agent", - "agent_contact_ip", - "KEYLIME_AGENT_CONTACT_IP", -@@ -500,8 +574,13 @@ - } - - /// Returns the contact ip for the agent if set --fn cloudagent_contact_port_get() -> Result> { -+fn cloudagent_contact_port_get( -+ conf_name: &str, -+ conf: &Ini, -+) -> Result> { - match config_get_env( -+ conf_name, -+ conf, - "cloud_agent", - "agent_contact_port", - "KEYLIME_AGENT_CONTACT_PORT", -@@ -518,15 +597,18 @@ - } - - /* -- * Input: [section] and key -+ * Input: conf_name, conf, [section] and key - * Return: Returns the matched key - * - * Example call: -- * let port = common::config_get("general","cloudagent_port"); -+ * let port = common::config_get(conf_file_name, file_Ini,"general","cloudagent_port"); - */ --fn config_get(section: &str, key: &str) -> Result { -- let conf_name = config_file_get(); -- let conf = Ini::load_from_file(&conf_name)?; -+fn config_get( -+ conf_name: &str, -+ conf: &Ini, -+ section: &str, -+ key: &str, -+) -> Result { - let section = match conf.section(Some(section.to_owned())) { - Some(section) => section, - None => -@@ -554,23 +636,29 @@ - } - - /* -- * Input: [section] and key and environment variable -+ * Input: conf_name, conf,[section] and key and environment variable - * Return: Returns the matched key - * - * Example call: -- * let port = common::config_get_env("general","cloudagent_port", "CLOUDAGENT_PORT"); -+ * let port = common::config_get_env(conf_file_name, file_Ini, "general","cloudagent_port", "CLOUDAGENT_PORT"); - */ --fn config_get_env(section: &str, key: &str, env: &str) -> Result { -+fn config_get_env( -+ conf_name: &str, -+ conf: &Ini, -+ section: &str, -+ key: &str, -+ env: &str, -+) -> Result { - match env::var(env) { - Ok(ip) => { - // The variable length must be larger than 0 to accept - if !ip.is_empty() { - Ok(ip) - } else { -- config_get(section, key) -+ config_get(conf_name, conf, section, key) - } - } -- _ => config_get(section, key), -+ _ => config_get(conf_name, conf, section, key), - } - } - diff --git a/rust-keylime-set-supplementary-groups.patch b/rust-keylime-set-supplementary-groups.patch deleted file mode 100644 index eba875a..0000000 --- a/rust-keylime-set-supplementary-groups.patch +++ /dev/null @@ -1,162 +0,0 @@ -From 4ec807b1bbcfaa67f85d0c2659b1f439c2f540b4 Mon Sep 17 00:00:00 2001 -From: Anderson Toshiyuki Sasaki -Date: Fri, 24 Jun 2022 16:25:54 +0200 -Subject: [PATCH] permissions: Set supplementary groups when dropping - privileges - -This allows the agent to run with the user primary group and have the -access given by the supplementary groups. - -Fixes: #414 - -Signed-off-by: Anderson Toshiyuki Sasaki ---- - src/permissions.rs | 70 ++++++++++++++++++++++++++++++++++------------ - 1 file changed, 52 insertions(+), 18 deletions(-) - -diff --git a/src/permissions.rs b/src/permissions.rs -index 279a6dd..86e3fae 100644 ---- a/src/permissions.rs -+++ b/src/permissions.rs -@@ -2,7 +2,7 @@ - // Copyright 2021 Keylime Authors - - use crate::error::{Error, Result}; --use libc::{gid_t, uid_t}; -+use libc::{c_char, c_int, gid_t, uid_t}; - use log::*; - use std::os::unix::ffi::OsStrExt; - use std::{ -@@ -13,10 +13,9 @@ use std::{ - ptr, - }; - --#[derive(Debug)] - pub(crate) struct UserIds { -- uid: uid_t, -- gid: gid_t, -+ passwd: libc::passwd, -+ group: libc::group, - } - - pub(crate) fn get_gid() -> gid_t { -@@ -47,14 +46,14 @@ impl TryFrom<&str> for UserIds { - let group = parts[1]; - - // Get gid from group name -- let gid = if let Ok(g_cstr) = CString::new(group.as_bytes()) { -+ let grnam = if let Ok(g_cstr) = CString::new(group.as_bytes()) { - let p = unsafe { libc::getgrnam(g_cstr.as_ptr()) }; - if p.is_null() { - let e = io::Error::last_os_error(); - error!("Could not get group {}: {}", group, e); - return Err(Error::Conversion(e.to_string())); - } -- unsafe { (*p).gr_gid } -+ unsafe { (*p) } - } else { - return Err(Error::Conversion(format!( - "Failed to convert {} to CString", -@@ -63,14 +62,14 @@ impl TryFrom<&str> for UserIds { - }; - - // Get uid from user name -- let uid = if let Ok(u_cstr) = CString::new(user.as_bytes()) { -+ let passwd = if let Ok(u_cstr) = CString::new(user.as_bytes()) { - let p = unsafe { libc::getpwnam(u_cstr.as_ptr()) }; - if p.is_null() { - let e = io::Error::last_os_error(); - error!("Could not get user {}: {}", user, e); - return Err(Error::Conversion(e.to_string())); - } -- unsafe { (*p).pw_uid } -+ unsafe { (*p) } - } else { - return Err(Error::Conversion(format!( - "Failed to convert {} to CString", -@@ -78,7 +77,10 @@ impl TryFrom<&str> for UserIds { - ))); - }; - -- Ok(UserIds { uid, gid }) -+ Ok(UserIds { -+ passwd, -+ group: grnam, -+ }) - } - } - -@@ -88,22 +90,51 @@ impl TryFrom<&str> for UserIds { - pub(crate) fn run_as(user_group: &str) -> Result<()> { - let ids: UserIds = user_group.try_into()?; - -- // Drop supplementary groups -- if unsafe { libc::setgroups(0, ptr::null()) } != 0 { -+ // Set gid -+ if unsafe { libc::setgid(ids.group.gr_gid) } != 0 { - let e = io::Error::last_os_error(); -- error!("Could not drop supplementary groups: {}", e); -+ error!("Could not set group id: {}", e); - return Err(Error::Permission); - } - -- // Set gid -- if unsafe { libc::setgid(ids.gid) } != 0 { -+ // Get list of supplementary groups -+ let mut sup_groups: [gid_t; 32] = [0u32; 32]; -+ let mut ngroups: c_int = 32; -+ if unsafe { -+ libc::getgrouplist( -+ ids.passwd.pw_name, -+ ids.group.gr_gid, -+ sup_groups.as_mut_ptr(), -+ &mut ngroups, -+ ) -+ } < 0 -+ { -+ // Allocate a Vec and try again -+ let mut sup_groups: Vec = Vec::with_capacity(ngroups as usize); -+ if unsafe { -+ libc::getgrouplist( -+ ids.passwd.pw_name, -+ ids.group.gr_gid, -+ sup_groups.as_mut_ptr(), -+ &mut ngroups, -+ ) -+ } < 0 -+ { -+ error!("Could not get list of supplementary groups"); -+ return Err(Error::Permission); -+ } -+ } -+ -+ // Set supplementary groups -+ if unsafe { libc::setgroups(ngroups as usize, sup_groups.as_ptr()) } != 0 -+ { - let e = io::Error::last_os_error(); -- error!("Could not set group id: {}", e); -+ error!("Could not set supplementary groups: {}", e); - return Err(Error::Permission); - } - - // Set uid -- if unsafe { libc::setuid(ids.uid) } != 0 { -+ if unsafe { libc::setuid(ids.passwd.pw_uid) } != 0 { - let e = io::Error::last_os_error(); - error!("Could not set user id: {}", e); - return Err(Error::Permission); -@@ -126,9 +157,12 @@ pub(crate) fn chown(user_group: &str, path: &Path) -> Result<()> { - return Err(Error::Permission); - } - -- // change directory owner to root -+ // change directory owner - let c_path = CString::new(path.as_os_str().as_bytes())?; -- if unsafe { libc::chown(c_path.as_ptr(), ids.uid, ids.gid) } != 0 { -+ if unsafe { -+ libc::chown(c_path.as_ptr(), ids.passwd.pw_uid, ids.group.gr_gid) -+ } != 0 -+ { - error!("Failed to change file {} owner.", path.display()); - return Err(Error::Permission); - } diff --git a/rust-keylime-show-path-missing-cert.patch b/rust-keylime-show-path-missing-cert.patch deleted file mode 100644 index 9ad01e7..0000000 --- a/rust-keylime-show-path-missing-cert.patch +++ /dev/null @@ -1,20 +0,0 @@ ---- a/src/main.rs 2022-06-28 16:54:37.559307146 +0200 -+++ b/src/main.rs 2022-06-28 17:37:39.512350575 +0200 -@@ -512,7 +512,16 @@ - let ssl_context; - if config.mtls_enabled { - let keylime_ca_cert = -- crypto::load_x509(Path::new(&config.keylime_ca_path))?; -+ match crypto::load_x509(Path::new(&config.keylime_ca_path)) { -+ Ok(t) => Ok(t), -+ Err(e) => { -+ error!( -+ "Certificate not installed: {}", -+ config.keylime_ca_path -+ ); -+ Err(e) -+ } -+ }?; - - cert = crypto::generate_x509(&nk_priv, &config.agent_uuid)?; - mtls_cert = Some(&cert); diff --git a/sources b/sources index 816b51c..70fca50 100644 --- a/sources +++ b/sources @@ -1,2 +1,2 @@ -SHA512 (rust-keylime-0.1.0~20220603gitaed51c7.tar.gz) = 0a045b0caa13a582a1270428edb49a7e20cc7df15b749458a9ddb2b84c05f240225d9e876a0cc082978dc5b52f7e0175cbbc3b937edd1ffed68e252be3ea17f8 -SHA512 (rust-keylime-0.1.0~20220603gitaed51c7-vendor.tar.xz) = 11bf0e27e5c94acddd04b9b17b2642f5a17a2ad13126075b93f964d07afec46fce2bf376f9bf74840a2c447b11b0e26a1ffe07c74a899685a67461c69254652e +SHA512 (rust-keylime-0.1.0~20220805git0186093.tar.gz) = bd5fc911b022938896bb26f2500338c4cf0fc623ab471c3a1e8f846448d5d7b19c9ceb953c63bd306b88d0c52430737ff04650829a8a8a28697647c5dd856445 +SHA512 (rust-keylime-0.1.0~20220805git0186093-vendor.tar.xz) = e1b810b08ce14aae664efcace9a984f7c7999c878704d7e0c93ca500e6bdf638e00ecec5bc6708ff6d69296c42a0bb29c6511ce7fa3f60d41d05a14e73ed8332