Skip to content

Commit

Permalink
sha3: align (*state).storage
Browse files Browse the repository at this point in the history
Even on platforms that allow unaligned reads, the Go runtime assumes
that a pointer to a given type has the alignment required by that
type.

Fixes golang/go#35173
Updates golang/go#34972
Updates golang/go#34964

Change-Id: I90361e096e59162e42ebde2914985af92f777ece
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/203837
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
  • Loading branch information
Bryan C. Mills authored and bradfitz committed Nov 5, 2019
1 parent f155a23 commit 35d7367
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 12 deletions.
23 changes: 12 additions & 11 deletions sha3/sha3.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ type state struct {
// [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf
// "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and
// Extendable-Output Functions (May 2014)"
dsbyte byte
storage [maxRate]byte
dsbyte byte

storage storageBuf

// Specific to SHA-3 and SHAKE.
outputLen int // the default output size in bytes
Expand All @@ -60,15 +61,15 @@ func (d *state) Reset() {
d.a[i] = 0
}
d.state = spongeAbsorbing
d.buf = d.storage[:0]
d.buf = d.storage.asBytes()[:0]
}

func (d *state) clone() *state {
ret := *d
if ret.state == spongeAbsorbing {
ret.buf = ret.storage[:len(ret.buf)]
ret.buf = ret.storage.asBytes()[:len(ret.buf)]
} else {
ret.buf = ret.storage[d.rate-cap(d.buf) : d.rate]
ret.buf = ret.storage.asBytes()[d.rate-cap(d.buf) : d.rate]
}

return &ret
Expand All @@ -82,13 +83,13 @@ func (d *state) permute() {
// If we're absorbing, we need to xor the input into the state
// before applying the permutation.
xorIn(d, d.buf)
d.buf = d.storage[:0]
d.buf = d.storage.asBytes()[:0]
keccakF1600(&d.a)
case spongeSqueezing:
// If we're squeezing, we need to apply the permutatin before
// copying more output.
keccakF1600(&d.a)
d.buf = d.storage[:d.rate]
d.buf = d.storage.asBytes()[:d.rate]
copyOut(d, d.buf)
}
}
Expand All @@ -97,15 +98,15 @@ func (d *state) permute() {
// the multi-bitrate 10..1 padding rule, and permutes the state.
func (d *state) padAndPermute(dsbyte byte) {
if d.buf == nil {
d.buf = d.storage[:0]
d.buf = d.storage.asBytes()[:0]
}
// Pad with this instance's domain-separator bits. We know that there's
// 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.buf = append(d.buf, dsbyte)
zerosStart := len(d.buf)
d.buf = d.storage[:d.rate]
d.buf = d.storage.asBytes()[:d.rate]
for i := zerosStart; i < d.rate; i++ {
d.buf[i] = 0
}
Expand All @@ -116,7 +117,7 @@ func (d *state) padAndPermute(dsbyte byte) {
// Apply the permutation
d.permute()
d.state = spongeSqueezing
d.buf = d.storage[:d.rate]
d.buf = d.storage.asBytes()[:d.rate]
copyOut(d, d.buf)
}

Expand All @@ -127,7 +128,7 @@ func (d *state) Write(p []byte) (written int, err error) {
panic("sha3: write to sponge after read")
}
if d.buf == nil {
d.buf = d.storage[:0]
d.buf = d.storage.asBytes()[:0]
}
written = len(p)

Expand Down
7 changes: 7 additions & 0 deletions sha3/xor.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@

package sha3

// A storageBuf is an aligned array of maxRate bytes.
type storageBuf [maxRate]byte

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

var (
xorIn = xorInGeneric
copyOut = copyOutGeneric
Expand Down
9 changes: 8 additions & 1 deletion sha3/xor_unaligned.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,16 @@ package sha3

import "unsafe"

// A storageBuf is an aligned array of maxRate bytes.
type storageBuf [maxRate / 8]uint64

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

func xorInUnaligned(d *state, 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 35d7367

Please sign in to comment.