Zeroize output buffers at the start of all _out functions (part of #16)#18
Conversation
- 출력 슬라이스를 받는 _out 계열 함수 진입부에서 out fill(0) 선-초기화 - 오버사이즈 버퍼 뒤쪽이나 조기 반환 시 남는 이전 데이터 노출 방지 - digest 출력 버퍼 뒤쪽까지 0이 되도록 sha3 테스트 1건 갱신 - 행 단위 부분 기록 함수는 다른 행을 지우므로 제외
There was a problem hiding this comment.
This is great, thanks!
I have left a few requests for changes.
Can you please also update the docstring in core/traits.rs for each *_out function to indicate that the entire output buffer will be zeroized.
This PR is marked Draft. Please let me know when you think it is ready to be merged.
If you have done a task from the todo list, can you please delete that line and move it to the changelog section at the bottom of that file?
| // let mut s = self.clone(); | ||
| // s.conditional_sub_q(); | ||
|
|
||
| out.fill(0); |
There was a problem hiding this comment.
This one should be removed -- this is not a public function, and this will have a performance impact on the mlkem algorithm.
| // each of the N i16's will take dv bits | ||
| debug_assert_eq!(out.len(), N * (dv as usize) / 8); | ||
|
|
||
| out.fill(0); |
There was a problem hiding this comment.
This one should be removed -- this is not a public function, and this will have a performance impact on the mlkem algorithm.
| // each of the N i16's will take dv bits | ||
| debug_assert_eq!(out.len(), N * (dv as usize) / 8); | ||
|
|
||
| out.fill(0); |
There was a problem hiding this comment.
This one should be removed -- this is not a public function, and this will have a performance impact on the mlkem algorithm.
| // Q. T. Felix NOTE: With the application of zeroize, the entire output buffer is pre-initialized to 0, | ||
| // so the bytes after the digest length are now also 0. | ||
| // Previously, the contract was to leave the trailing bytes untouched, | ||
| // but this has been changed to fill them with zeros to prevent exposure of stale data. |
There was a problem hiding this comment.
A comment to explain what is being tested by this line is good, but can you please remove your name, and can you please remove the description of what changed from one version to the next? (the change history will very quickly become meaningless)
| out: &mut [u8; LEN], | ||
| take_a: bool, | ||
| ) { | ||
| out.fill(0); |
There was a problem hiding this comment.
This needs to be removed as it may violate the constant-time assumption since over-writing a zero with a zero may take less time than overwriting a different value.
|
Yes, confirmed. Im working on it. |
|
Thanks for the review! All requested changes are in (commit c642ef6):
|
|
Amazing! Thank you so much! I will merge now. |
…ers' into release/0.1.2alpha. Closes #18
This zeroizes the caller-provided output buffer at the entry of every concrete function that writes into an output byte slice (the
*_outfamily, the dispatch wrappers in thefactorycrate, and the constant-time copy helper inutils). Each such function now starts without.fill(0)(oroutput.fill(0)) before it produces its result. 84 write sites in total.Motivation (from the 0.1.2alpha TODO)
The TODO states: anywhere you have an
_out(.. out: &mut [u8]), start by zeroizing it with.fill(0). Pre-zeroizing closes two leak paths:A representative change:
Scope
sha2,sha3(sha3/shake/keccak),hmac,rng(hash_drbg),hex,base64,factory(hash/xof/mac/rng),utils/ct, and the PQ cratesmlkem,mlkem_lowmemory,mldsa,mldsa_lowmemory(key-encode and sign paths).Behavior change (please note)
Digest, MAC, XOF and RNG output functions now zero the tail of an oversized output buffer instead of leaving it untouched. One existing
sha3unit test (test_static_hash) asserted the old "does not touch the extra bytes" contract and was updated to assert the new zeroed-tail contract. The sharedcore-test-frameworkhash and mac tests already use zero-initialized buffers and expect zeroed tails, so they were unaffected.Deliberately excluded
The row-wise partial writers in
mlkem_lowmemory(pack_t_hat_row,pack_s_hat_row,compress_u_row) were NOT changed. They write a sub-slice of a shared buffer that already holds other rows, so a blanketfill(0)would erase previously written data and corrupt the output. Trait declarations (no body),unimplemented!()stubs, andKeyMaterialTrait-typed outputs (zeroized transitively through the byte-slice writers) were left as-is.Merge conflict warning
This PR modifies
crypto/rng/src/hash_drbg80090a.rs(generate_out,next_bytes_out,hash_df,hashgen). PR #16 also touches that file, so expect a conflict when folding this into the roundup branch.Verification
The test run includes the ML-KEM / ML-DSA wycheproof KATs, which exercise the modified key-encode and sign paths.
Relationship
Part of #16. Intended to be folded into the 0.1.2alpha TODO roundup.