lib/crypto/sha256: restore faithful re-entrant sum() (#265 unblocked)
The port shipped sum() single-shot — mutating the live hash state —
because Hare's state snapshot `let copy = *h; let h = ©` (a
deref-rhs aggregate let-init of an array-containing struct) miscompiled
in cgen. #265 fold-1 (master 4d3f846) landed the full-size aggregate
copy for that axis, so restore the faithful form: pad+finalize the
snapshot, leave the live state untouched, close() the copy.
sum() is now non-destructive — summing twice yields the same digest and
writing after a sum() continues the stream. Pinned by a new reentrant()
@test (sum-twice identical + write-after-sum continuity). NIST vectors
unchanged.
This commit is contained in:
@@ -91,6 +91,34 @@ fn check(msg: []u8, want: str) void = {
|
||||
"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
|
||||
};
|
||||
|
||||
// reentrant — sum() is non-destructive: it pads+finalizes a snapshot, so
|
||||
// the live hash survives. Summing twice yields the same digest, and a
|
||||
// write after a sum() continues the same stream. Pins the faithful
|
||||
// state-snapshot restored once #265 fold-1 unblocked the deref-rhs
|
||||
// aggregate copy `let copy = *h` (see sha256.ww [[sumfn]]).
|
||||
@test fn reentrant() void = {
|
||||
let st: sha256.state = sha256.sha256();
|
||||
let h: *hash.hash = (&st): *hash.hash;
|
||||
hash.write(h, strings.toutf8("abc"));
|
||||
|
||||
let out1: [32]u8;
|
||||
let out2: [32]u8;
|
||||
hash.sum(h, out1[0:32]);
|
||||
hash.sum(h, out2[0:32]);
|
||||
if (!bytes.equal(out1[0:32], out2[0:32])) { fail(); };
|
||||
checkbytes(out1[0:32],
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
|
||||
|
||||
// Write more after the sum(): the post-sum stream is uncorrupted, so
|
||||
// the running digest of "abc"+"def" matches a one-shot hash of "abcdef".
|
||||
hash.write(h, strings.toutf8("def"));
|
||||
let out3: [32]u8;
|
||||
hash.sum(h, out3[0:32]);
|
||||
let want: [32]u8;
|
||||
dohash(strings.toutf8("abcdef"), want[0:32]);
|
||||
if (!bytes.equal(out3[0:32], want[0:32])) { fail(); };
|
||||
};
|
||||
|
||||
// sz()/bsz() report the SHA-256 constants regardless of state.
|
||||
@test fn sizes() void = {
|
||||
let st: sha256.state = sha256.sha256();
|
||||
@@ -104,6 +132,7 @@ export fn main() i32 = {
|
||||
signalled = 2; abc();
|
||||
signalled = 3; twoblockpad();
|
||||
signalled = 4; millionas();
|
||||
signalled = 5; sizes();
|
||||
signalled = 5; reentrant();
|
||||
signalled = 6; sizes();
|
||||
return 0;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user