diff --git a/Cargo.lock b/Cargo.lock
index 512dba96..a7d4f609 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -785,6 +785,12 @@ version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd"
+[[package]]
+name = "keccak"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9b7d56ba4a8344d6be9729995e6b06f928af29998cdf79fe390cbf6b1fee838"
+
[[package]]
name = "lazy_static"
version = "1.4.0"
@@ -890,6 +896,18 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882"
+[[package]]
+name = "merlin"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d"
+dependencies = [
+ "byteorder",
+ "keccak",
+ "rand_core",
+ "zeroize",
+]
+
[[package]]
name = "micromath"
version = "1.1.1"
@@ -955,6 +973,7 @@ dependencies = [
"hal-core",
"hal-x86_64",
"maitake",
+ "merlin",
"mycelium-alloc",
"mycelium-trace",
"mycelium-util",
@@ -1463,6 +1482,18 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8"
+[[package]]
+name = "synstructure"
+version = "0.12.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unicode-xid",
+]
+
[[package]]
name = "tempfile"
version = "3.3.0"
@@ -1847,6 +1878,12 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+[[package]]
+name = "unicode-xid"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
+
[[package]]
name = "valuable"
version = "0.1.0"
@@ -2078,3 +2115,24 @@ dependencies = [
"num-traits",
"yaxpeax-arch",
]
+
+[[package]]
+name = "zeroize"
+version = "1.5.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
+dependencies = [
+ "zeroize_derive",
+]
+
+[[package]]
+name = "zeroize_derive"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
diff --git a/Cargo.toml b/Cargo.toml
index 5418c5c4..f1e5188d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -47,6 +47,7 @@ rlibc = "1.0"
bootloader = { version = "0.10.13" }
embedded-graphics = "0.7"
mycotest = { path = "mycotest" }
+merlin = { version = "3.0", default_features = false }
futures-util = { version = "0.3", default-features = false, features = ["async-await", "async-await-macro"] }
# we don't depend on this directly, but we need to ensure that `tracing` uses a
# Miri-compatible version of `once_cell`.
diff --git a/src/arch/x86_64.rs b/src/arch/x86_64.rs
index d4e2e6d1..ab41922e 100644
--- a/src/arch/x86_64.rs
+++ b/src/arch/x86_64.rs
@@ -4,6 +4,7 @@ use hal_x86_64::{cpu, serial, vga};
pub use hal_x86_64::{cpu::entropy::seed_rng, mm, NAME};
use mycelium_util::sync::InitOnce;
+pub mod entropy;
mod framebuf;
pub mod interrupt;
mod oops;
diff --git a/src/arch/x86_64/entropy.rs b/src/arch/x86_64/entropy.rs
index 1e3dda80..4aa8e0a7 100644
--- a/src/arch/x86_64/entropy.rs
+++ b/src/arch/x86_64/entropy.rs
@@ -1 +1,91 @@
//! Hardware entropy sources.
+use hal_x86_64::cpu::entropy;
+use mycelium_util::sync::Lazy;
+
+/// This is a wrapper type so that we don't globally implement `rand::CryptoRng`
+/// for the `hal_core::cpu::entropy::PitEntropy` type, which is...Not a
+/// cryptographically secure RNG...
+///
+/// # Notes
+///
+/// Use this RNG **only** for calls to `TranscriptRngBuilder::finalize`! It is
+/// *not* actually cryptographically secure!
+pub(crate) struct RekeyRng(entropy::PitEntropy);
+
+pub(crate) fn fill_bytes(buf: &mut [u8]) -> usize {
+ static RDRAND: Lazy