Skip to content

Commit

Permalink
Align internal SHAKE buffer when using it as []uint64
Browse files Browse the repository at this point in the history
The Go runtime assumes that a pointer to a type is aligned on the size
of that type.  We cast a [N]byte to []uint64, which breaks this
assumption.  Thus allocate the original [N]byte as a [N/8]uint64 instead.

Fixes #89

Cf. the same issue and patch in upstream:

  patch https://go-review.googlesource.com/c/crypto/+/203837/
  issue golang/go#35173
  • Loading branch information
bwesterb authored and armfazh committed Mar 4, 2020
1 parent e1c2169 commit 0c5a078
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 10 deletions.
18 changes: 9 additions & 9 deletions internal/shake/sha3.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ type Shake struct {
// "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and
// Extendable-Output Functions (May 2014)"
dsbyte byte
storage [maxRate]byte
storage storageBuf

// Specific to SHA-3 and SHAKE.
outputLen int // the default output size in bytes
Expand Down Expand Up @@ -77,7 +77,7 @@ func (d *Shake) permute() {
case spongeAbsorbing:
// If we're absorbing, we need to xor the input into the state
// before applying the permutation.
xorIn(d, d.storage[d.bufo:d.bufe])
xorIn(d, d.storage.asBytes()[d.bufo:d.bufe])
d.bufe = 0
d.bufo = 0
keccakF1600(&d.a)
Expand All @@ -87,7 +87,7 @@ func (d *Shake) permute() {
keccakF1600(&d.a)
d.bufo = 0
d.bufe = d.rate
copyOut(d, d.storage[:d.rate])
copyOut(d, d.storage.asBytes()[:d.rate])
}
}

Expand All @@ -98,24 +98,24 @@ func (d *Shake) padAndPermute(dsbyte byte) {
// at least one byte of space in d.buf because, if it were full,
// permute would have been called to empty it. dsbyte also contains the
// first one bit for the padding. See the comment in the state struct.
d.storage[d.bufe] = dsbyte
d.storage.asBytes()[d.bufe] = dsbyte
d.bufe++
zerosStart := d.bufe - d.bufo
d.bufo = 0
d.bufe = d.rate
for i := zerosStart; i < d.rate; i++ {
d.storage[i] = 0
d.storage.asBytes()[i] = 0
}
// This adds the final one bit for the padding. Because of the way that
// bits are numbered from the LSB upwards, the final bit is the MSB of
// the last byte.
d.storage[d.rate-1] ^= 0x80
d.storage.asBytes()[d.rate-1] ^= 0x80
// Apply the permutation
d.permute()
d.state = spongeSqueezing
d.bufo = 0
d.bufe = d.rate
copyOut(d, d.storage[:d.rate])
copyOut(d, d.storage.asBytes()[:d.rate])
}

// Write absorbs more data into the hash's state. It produces an error
Expand All @@ -138,7 +138,7 @@ func (d *Shake) Write(p []byte) (int, error) {
if todo > len(p) {
todo = len(p)
}
copy(d.storage[d.bufe:], p[:todo])
copy(d.storage.asBytes()[d.bufe:], p[:todo])
d.bufe += todo
p = p[todo:]

Expand All @@ -163,7 +163,7 @@ func (d *Shake) Read(out []byte) (n int, err error) {

// Now, do the squeezing.
for len(out) > 0 {
n := copy(out, d.storage[d.bufo:d.bufe])
n := copy(out, d.storage.asBytes()[d.bufo:d.bufe])
d.bufo += n
out = out[n:]

Expand Down
6 changes: 6 additions & 0 deletions internal/shake/xor_generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ package shake

import "encoding/binary"

type storageBuf [maxRate]byte

func (b *storageBuf) asBytes() *[maxRate]byte {
return (*[maxRate]byte)(b)
}

// xorInGeneric xors the bytes in buf into the state; it
// makes no non-portable assumptions about memory layout
// or alignment.
Expand Down
8 changes: 7 additions & 1 deletion internal/shake/xor_unaligned.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@ package shake

import "unsafe"

type storageBuf [maxRate / 8]uint64

func (b *storageBuf) asBytes() *[maxRate]byte {
return (*[maxRate]byte)(unsafe.Pointer(b))
}

func xorIn(d *Shake, buf []byte) {
bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))
n := len(buf)
bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))[: n/8 : n/8]
if n >= 72 {
d.a[0] ^= bw[0]
d.a[1] ^= bw[1]
Expand Down

0 comments on commit 0c5a078

Please sign in to comment.