Browse Source

SHA-3: Fixes crash when cloning Shake state

pull/29/head
Henry Case 5 years ago
parent
commit
15f6ee16b9
3 changed files with 35 additions and 10 deletions
  1. +8
    -7
      hash/shake/sha3.go
  2. +22
    -0
      hash/shake/sha3_test.go
  3. +5
    -3
      hash/shake/shake.go

+ 8
- 7
hash/shake/sha3.go View File

@@ -65,15 +65,15 @@ func (d *state) Reset() {
d.buf = d.storage[:0]
}

func (d *state) clone() *state {
ret := *d
func (d *state) clone(ret *state) {
// shallow copy
*ret = *d
// deep copy for a buf
if ret.state == spongeAbsorbing {
ret.buf = ret.storage[:len(ret.buf)]
ret.buf = ret.storage[:len(d.buf)]
} 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
@@ -187,7 +187,8 @@ func (d *state) Read(out []byte) (n int, err error) {
func (d *state) Sum(in []byte) []byte {
// Make a copy of the original hash so that caller can keep writing
// and summing.
dup := d.clone()
var dup state
d.clone(&dup)
hash := make([]byte, dup.outputLen)
dup.Read(hash)
return append(in, hash...)


+ 22
- 0
hash/shake/sha3_test.go 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
// with no input data.
func BenchmarkPermutationFunction(b *testing.B) {


+ 5
- 3
hash/shake/shake.go View File

@@ -86,9 +86,11 @@ func (c *CShake) Reset() {

// Clone returns copy of a cSHAKE context within its current state.
func (c *CShake) Clone() CShake {
b := make([]byte, len(c.initBlock))
copy(b, c.initBlock)
return CShake{state: *c.clone(), initBlock: b}
var ret CShake
c.clone(&ret.state)
ret.initBlock = make([]byte, len(c.initBlock))
copy(ret.initBlock, c.initBlock)
return ret
}

// NewShake128 creates a new SHAKE128 variable-output-length CShake.


Loading…
Cancel
Save