sha3: align (*state).storage

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>
diff --git a/sha3/sha3.go b/sha3/sha3.go
index b12a35c..ba269a0 100644
--- a/sha3/sha3.go
+++ b/sha3/sha3.go
@@ -38,8 +38,9 @@
 	// [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
@@ -60,15 +61,15 @@
 		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
@@ -82,13 +83,13 @@
 		// 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)
 	}
 }
@@ -97,7 +98,7 @@
 // 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,
@@ -105,7 +106,7 @@
 	// 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
 	}
@@ -116,7 +117,7 @@
 	// 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)
 }
 
@@ -127,7 +128,7 @@
 		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)
 
diff --git a/sha3/xor.go b/sha3/xor.go
index 46a0d63..079b650 100644
--- a/sha3/xor.go
+++ b/sha3/xor.go
@@ -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
diff --git a/sha3/xor_unaligned.go b/sha3/xor_unaligned.go
index 929a486..a3d0686 100644
--- a/sha3/xor_unaligned.go
+++ b/sha3/xor_unaligned.go
@@ -9,9 +9,16 @@
 
 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]