Skip to content

make read_entropy forward-secure - #2662

Merged
mkroening merged 1 commit into
hermit-os:mainfrom
joboet:forward-key-erasure
Aug 21, 2026
Merged

make read_entropy forward-secure#2662
mkroening merged 1 commit into
hermit-os:mainfrom
joboet:forward-key-erasure

Conversation

@joboet

@joboet joboet commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

This makes the RNG used for read_entropy forwards-secure by employing J.D. Bernstein's fast-key-erasure construction while keeping ChaCha20 as the primitive. The blog post contains a more detailed description, but simply put the problem with the current RNG is that it is possible to reconstruct past outputs (and not just future ones) by looking at the current RNG state. The fast-key-erasure RNG prevents this while preserving the performance of the underlying cryptographic primitive.

The other change introduced here is that read_entropy will not ever fail once the initial seed is available. The only consequence of this is that the RNG will not be able to recover from state compromise if the hardware or hypervisor source becomes inaccessible.

@joboet
joboet force-pushed the forward-key-erasure branch from 5ad5627 to 65f2e2c Compare August 18, 2026 11:12
@mkroening mkroening self-assigned this Aug 18, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark Results

Details
Benchmark Current: 9795b17 Previous: 2e23902 Performance Ratio
startup_benchmark Build Time 92.58 s 80.34 s 1.15
startup_benchmark File Size 0.78 MB 0.80 MB 0.98
Startup Time - 1 core 0.76 s (±0.01 s) 0.75 s (±0.02 s) 1.02
Startup Time - 2 cores 0.77 s (±0.02 s) 0.74 s (±0.02 s) 1.04
Startup Time - 4 cores 0.76 s (±0.01 s) 0.74 s (±0.02 s) 1.03
multithreaded_benchmark Build Time 92.05 s 82.11 s 1.12
multithreaded_benchmark File Size 0.88 MB 0.86 MB 1.03
Multithreaded Pi Efficiency - 2 Threads 66.73 % (±6.85 %) 85.89 % (±6.61 %) 0.78
Multithreaded Pi Efficiency - 4 Threads 40.81 % (±2.59 %) 43.43 % (±2.56 %) 0.94
Multithreaded Pi Efficiency - 8 Threads 19.74 % (±1.46 %) 25.76 % (±1.53 %) 0.77
micro_benchmarks Build Time 217.83 s 80.40 s 2.71
micro_benchmarks File Size 0.89 MB 0.86 MB 1.03
Scheduling time - 1 thread 185.84 ticks (±29.83 ticks) 62.65 ticks (±4.06 ticks) 2.97
Scheduling time - 2 threads 103.97 ticks (±21.10 ticks) 34.08 ticks (±4.10 ticks) 3.05
Micro - Time for syscall (getpid) 9.33 ticks (±4.59 ticks) 3.45 ticks (±0.58 ticks) 2.70
Memcpy speed - (built_in) block size 4096 57611.31 MByte/s (±40747.58 MByte/s) 82448.38 MByte/s (±56997.13 MByte/s) 0.70
Memcpy speed - (built_in) block size 1048576 13893.20 MByte/s (±11266.95 MByte/s) 30585.98 MByte/s (±24707.84 MByte/s) 0.45
Memcpy speed - (built_in) block size 16777216 12197.16 MByte/s (±10106.53 MByte/s) 26340.06 MByte/s (±21720.96 MByte/s) 0.46
Memset speed - (built_in) block size 4096 57674.32 MByte/s (±40794.31 MByte/s) 82292.76 MByte/s (±56891.50 MByte/s) 0.70
Memset speed - (built_in) block size 1048576 14281.00 MByte/s (±11503.10 MByte/s) 31323.85 MByte/s (±25145.86 MByte/s) 0.46
Memset speed - (built_in) block size 16777216 12520.27 MByte/s (±10291.95 MByte/s) 27104.68 MByte/s (±22209.94 MByte/s) 0.46
Memcpy speed - (rust) block size 4096 50929.35 MByte/s (±37484.53 MByte/s) 74097.96 MByte/s (±51811.44 MByte/s) 0.69
Memcpy speed - (rust) block size 1048576 13859.40 MByte/s (±11328.97 MByte/s) 30361.60 MByte/s (±24602.37 MByte/s) 0.46
Memcpy speed - (rust) block size 16777216 12611.25 MByte/s (±10568.92 MByte/s) 27625.34 MByte/s (±22806.88 MByte/s) 0.46
Memset speed - (rust) block size 4096 51462.15 MByte/s (±37912.11 MByte/s) 74373.47 MByte/s (±51976.48 MByte/s) 0.69
Memset speed - (rust) block size 1048576 14403.15 MByte/s (±11746.65 MByte/s) 31110.89 MByte/s (±25033.24 MByte/s) 0.46
Memset speed - (rust) block size 16777216 13008.05 MByte/s (±10820.13 MByte/s) 28386.93 MByte/s (±23265.03 MByte/s) 0.46
alloc_benchmarks Build Time 214.58 s 74.76 s 2.87
alloc_benchmarks File Size 0.86 MB 0.87 MB 0.98
Allocations - Allocation success 91.38 % 91.31 % 1.00
Allocations - Deallocation success 100.00 % 100.00 % 1
Allocations - Pre-fail Allocations 61.60 % 61.44 % 1.00
Allocations - Average Allocation time 24102.93 Ticks (±1486.18 Ticks) 5860.58 Ticks (±98.43 Ticks) 4.11
Allocations - Average Allocation time (no fail) 24905.68 Ticks (±2199.88 Ticks) 6554.81 Ticks (±92.86 Ticks) 3.80
Allocations - Average Deallocation time 6645.11 Ticks (±2095.72 Ticks) 1805.01 Ticks (±250.35 Ticks) 3.68
mutex_benchmark Build Time 213.03 s 79.82 s 2.67
mutex_benchmark File Size 0.89 MB 0.86 MB 1.03
Mutex Stress Test Average Time per Iteration - 1 Threads 37.44 ns (±6.65 ns) 12.10 ns (±0.41 ns) 3.09
Mutex Stress Test Average Time per Iteration - 2 Threads 34.94 ns (±10.95 ns) 40.26 ns (±1.68 ns) 0.87

This comment was automatically generated by workflow using github-action-benchmark.

@mkroening mkroening left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good to me! Could you take care of Clippy? :)

@joboet
joboet force-pushed the forward-key-erasure branch from 65f2e2c to 9795b17 Compare August 21, 2026 15:57
@joboet

joboet commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

Sure, done! I had to switch back to rand_chacha since chacha20 doesn't compile with SSE2 disabled (LLVM returns "Do not know how to split the result of this operator!", see rust-lang/rust#158532) – unfortunately that means the RNG has to be zeroised manually. Also, rand_chacha doesn't have set_block_pos, only set_word_pos, so I've emulated that.

@mkroening

Copy link
Copy Markdown
Member

Sure, done! I had to switch back to rand_chacha since chacha20 doesn't compile with SSE2 disabled (LLVM returns "Do not know how to split the result of this operator!", see rust-lang/rust#158532) – unfortunately that means the RNG has to be zeroised manually. Also, rand_chacha doesn't have set_block_pos, only set_word_pos, so I've emulated that.

Thanks! :)

@mkroening
mkroening added this pull request to the merge queue Aug 21, 2026
Merged via the queue into hermit-os:main with commit b0678ba Aug 21, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants