1
0
mirror of https://github.com/henrydcase/nobs.git synced 2024-11-26 09:01:20 +00:00

SHA-3: Fixes crash when cloning Shake state

This commit is contained in:
Henry Case 2019-05-26 16:39:29 +01:00
parent 9b3c0190b0
commit 15f6ee16b9
3 changed files with 35 additions and 10 deletions

View File

@ -65,15 +65,15 @@ func (d *state) Reset() {
d.buf = d.storage[:0] d.buf = d.storage[:0]
} }
func (d *state) clone() *state { func (d *state) clone(ret *state) {
ret := *d // shallow copy
*ret = *d
// deep copy for a buf
if ret.state == spongeAbsorbing { if ret.state == spongeAbsorbing {
ret.buf = ret.storage[:len(ret.buf)] ret.buf = ret.storage[:len(d.buf)]
} else { } else {
ret.buf = ret.storage[d.rate-cap(d.buf) : d.rate] ret.buf = ret.storage[d.rate-len(d.buf) : d.rate]
} }
return &ret
} }
// permute applies the KeccakF-1600 permutation. It handles // permute applies the KeccakF-1600 permutation. It handles
@ -187,7 +187,8 @@ func (d *state) Read(out []byte) (n int, err error) {
func (d *state) Sum(in []byte) []byte { func (d *state) Sum(in []byte) []byte {
// Make a copy of the original hash so that caller can keep writing // Make a copy of the original hash so that caller can keep writing
// and summing. // and summing.
dup := d.clone() var dup state
d.clone(&dup)
hash := make([]byte, dup.outputLen) hash := make([]byte, dup.outputLen)
dup.Read(hash) dup.Read(hash)
return append(in, hash...) return append(in, hash...)

View File

@ -284,6 +284,28 @@ func TestClone(t *testing.T) {
} }
} }
// Checks wether reset works correctly after clone
func TestCloneAndReset(t *testing.T) {
// Shake 256, uses SHA-3 with rate = 136
d1 := NewShake256()
buf1 := make([]byte, 28, 28)
buf2 := make([]byte, 28, 28)
d1.Write([]byte{0xcc})
// Reading x bytes where x<168-136. This makes capability
// of the state buffer shorter.
d1.Read(buf1)
// This will crash if sha-3 code uses cap() instead
// of len() when calculating length of state buffer
d2 := d1.Clone()
d2.Reset()
d2.Write([]byte{0xcc})
d2.Read(buf2)
if !bytes.Equal(buf1, buf2) {
t.Error("Different value when reading after reset")
}
}
// BenchmarkPermutationFunction measures the speed of the permutation function // BenchmarkPermutationFunction measures the speed of the permutation function
// with no input data. // with no input data.
func BenchmarkPermutationFunction(b *testing.B) { func BenchmarkPermutationFunction(b *testing.B) {

View File

@ -86,9 +86,11 @@ func (c *CShake) Reset() {
// Clone returns copy of a cSHAKE context within its current state. // Clone returns copy of a cSHAKE context within its current state.
func (c *CShake) Clone() CShake { func (c *CShake) Clone() CShake {
b := make([]byte, len(c.initBlock)) var ret CShake
copy(b, c.initBlock) c.clone(&ret.state)
return CShake{state: *c.clone(), initBlock: b} ret.initBlock = make([]byte, len(c.initBlock))
copy(ret.initBlock, c.initBlock)
return ret
} }
// NewShake128 creates a new SHAKE128 variable-output-length CShake. // NewShake128 creates a new SHAKE128 variable-output-length CShake.