Skip to content

Commit d75fb40

Browse files
FiloSottilegopherbot
authored andcommitted
crypto/internal/fips/sha3: reduce s390x divergence
It's a little annoying, but we can fit the IBM instructions on top of the regular state, avoiding more intrusive interventions. Going forward we should not accept assembly that replaces the whole implementation, because it doubles the work to do any refactoring like the one in this chain. Also, it took me a while to find the specification of these instructions, which should have been linked from the source for the next person who'd have to touch this. Finally, it's really painful to test this without a LUCI TryBot, per #67307. For #69536 Change-Id: I90632a90f06b2aa2e863967de972b12dbaa5b2ae Reviewed-on: https://go-review.googlesource.com/c/go/+/617359 LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Filippo Valsorda <[email protected]> Reviewed-by: Carlos Amedee <[email protected]> Reviewed-by: Daniel McCarney <[email protected]> Reviewed-by: Roland Shoemaker <[email protected]>
1 parent 312e7e9 commit d75fb40

12 files changed

+198
-344
lines changed

src/crypto/internal/fips/sha3/_asm/keccakf_amd64_asm.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ const (
101101

102102
func main() {
103103
Package("golang.org/x/crypto/sha3")
104-
ConstraintExpr("amd64,!purego,gc")
104+
ConstraintExpr("!purego")
105105
keccakF1600()
106106
Generate()
107107
}

src/crypto/internal/fips/sha3/hashes.go

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@ package sha3
66

77
// New224 returns a new Digest computing the SHA3-224 hash.
88
func New224() *Digest {
9-
return new224()
9+
return &Digest{rate: rateK448, outputLen: 28, dsbyte: dsbyteSHA3}
1010
}
1111

1212
// New256 returns a new Digest computing the SHA3-256 hash.
1313
func New256() *Digest {
14-
return new256()
14+
return &Digest{rate: rateK512, outputLen: 32, dsbyte: dsbyteSHA3}
1515
}
1616

1717
// New384 returns a new Digest computing the SHA3-384 hash.
1818
func New384() *Digest {
19-
return new384()
19+
return &Digest{rate: rateK768, outputLen: 48, dsbyte: dsbyteSHA3}
2020
}
2121

2222
// New512 returns a new Digest computing the SHA3-512 hash.
2323
func New512() *Digest {
24-
return new512()
24+
return &Digest{rate: rateK1024, outputLen: 64, dsbyte: dsbyteSHA3}
2525
}
2626

2727
// TODO(fips): do this in the stdlib crypto/sha3 package.
@@ -46,22 +46,6 @@ const (
4646
rateK1024 = (1600 - 1024) / 8
4747
)
4848

49-
func new224Generic() *Digest {
50-
return &Digest{rate: rateK448, outputLen: 28, dsbyte: dsbyteSHA3}
51-
}
52-
53-
func new256Generic() *Digest {
54-
return &Digest{rate: rateK512, outputLen: 32, dsbyte: dsbyteSHA3}
55-
}
56-
57-
func new384Generic() *Digest {
58-
return &Digest{rate: rateK768, outputLen: 48, dsbyte: dsbyteSHA3}
59-
}
60-
61-
func new512Generic() *Digest {
62-
return &Digest{rate: rateK1024, outputLen: 64, dsbyte: dsbyteSHA3}
63-
}
64-
6549
// NewLegacyKeccak256 returns a new Digest computing the legacy, non-standard
6650
// Keccak-256 hash.
6751
func NewLegacyKeccak256() *Digest {

src/crypto/internal/fips/sha3/keccakf.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
//go:build !amd64 || purego || !gc
6-
75
package sha3
86

9-
import "math/bits"
7+
import (
8+
"internal/byteorder"
9+
"internal/goarch"
10+
"math/bits"
11+
"unsafe"
12+
)
1013

1114
// rc stores the round constants for use in the ι step.
1215
var rc = [24]uint64{
@@ -36,9 +39,23 @@ var rc = [24]uint64{
3639
0x8000000080008008,
3740
}
3841

39-
// keccakF1600 applies the Keccak permutation to a 1600b-wide
40-
// state represented as a slice of 25 uint64s.
41-
func keccakF1600(a *[25]uint64) {
42+
// keccakF1600Generic applies the Keccak permutation.
43+
func keccakF1600Generic(da *[200]byte) {
44+
var a *[25]uint64
45+
if goarch.BigEndian {
46+
a = new([25]uint64)
47+
for i := range a {
48+
a[i] = byteorder.LeUint64(da[i*8:])
49+
}
50+
defer func() {
51+
for i := range a {
52+
byteorder.LePutUint64(da[i*8:], a[i])
53+
}
54+
}()
55+
} else {
56+
a = (*[25]uint64)(unsafe.Pointer(da))
57+
}
58+
4259
// Implementation translated from Keccak-inplace.c
4360
// in the keccak reference code.
4461
var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64

src/crypto/internal/fips/sha3/keccakf_amd64.go

Lines changed: 0 additions & 13 deletions
This file was deleted.

src/crypto/internal/fips/sha3/sha3.go

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ package sha3
1313
import (
1414
"crypto/internal/fips/subtle"
1515
"errors"
16-
"internal/byteorder"
17-
"internal/goarch"
18-
"unsafe"
1916
)
2017

2118
// spongeDirection indicates the direction bytes are flowing through the sponge.
@@ -77,24 +74,8 @@ func (d *Digest) Clone() *Digest {
7774

7875
// permute applies the KeccakF-1600 permutation.
7976
func (d *Digest) permute() {
80-
var a *[25]uint64
81-
if goarch.BigEndian {
82-
a = new([25]uint64)
83-
for i := range a {
84-
a[i] = byteorder.LeUint64(d.a[i*8:])
85-
}
86-
} else {
87-
a = (*[25]uint64)(unsafe.Pointer(&d.a))
88-
}
89-
90-
keccakF1600(a)
77+
keccakF1600(&d.a)
9178
d.n = 0
92-
93-
if goarch.BigEndian {
94-
for i := range a {
95-
byteorder.LePutUint64(d.a[i*8:], a[i])
96-
}
97-
}
9879
}
9980

10081
// padAndPermute appends the domain separation bits in dsbyte, applies
@@ -115,7 +96,8 @@ func (d *Digest) padAndPermute() {
11596
}
11697

11798
// Write absorbs more data into the hash's state.
118-
func (d *Digest) Write(p []byte) (n int, err error) {
99+
func (d *Digest) Write(p []byte) (n int, err error) { return d.write(p) }
100+
func (d *Digest) writeGeneric(p []byte) (n int, err error) {
119101
if d.state != spongeAbsorbing {
120102
panic("sha3: Write after Read")
121103
}
@@ -137,7 +119,7 @@ func (d *Digest) Write(p []byte) (n int, err error) {
137119
}
138120

139121
// read squeezes an arbitrary number of bytes from the sponge.
140-
func (d *Digest) read(out []byte) (n int, err error) {
122+
func (d *Digest) readGeneric(out []byte) (n int, err error) {
141123
// If we're still absorbing, pad and apply the permutation.
142124
if d.state == spongeAbsorbing {
143125
d.padAndPermute()
@@ -162,7 +144,8 @@ func (d *Digest) read(out []byte) (n int, err error) {
162144

163145
// Sum appends the current hash to b and returns the resulting slice.
164146
// It does not change the underlying hash state.
165-
func (d *Digest) Sum(b []byte) []byte {
147+
func (d *Digest) Sum(b []byte) []byte { return d.sum(b) }
148+
func (d *Digest) sumGeneric(b []byte) []byte {
166149
if d.state != spongeAbsorbing {
167150
panic("sha3: Sum after Read")
168151
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2015 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build !purego
6+
7+
package sha3
8+
9+
//go:noescape
10+
func keccakF1600(a *[200]byte)
11+
12+
func (d *Digest) write(p []byte) (n int, err error) {
13+
return d.writeGeneric(p)
14+
}
15+
func (d *Digest) read(out []byte) (n int, err error) {
16+
return d.readGeneric(out)
17+
}
18+
func (d *Digest) sum(b []byte) []byte {
19+
return d.sumGeneric(b)
20+
}

src/crypto/internal/fips/sha3/keccakf_amd64.s renamed to src/crypto/internal/fips/sha3/sha3_amd64.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// Code generated by command: go run keccakf_amd64_asm.go -out ../keccakf_amd64.s -pkg sha3. DO NOT EDIT.
22

3-
//go:build amd64 && !purego && gc
3+
//go:build !purego
44

5-
// func keccakF1600(a *[25]uint64)
5+
// func keccakF1600(a *[200]byte)
66
TEXT ·keccakF1600(SB), $200-8
77
MOVQ a+0(FP), DI
88

src/crypto/internal/fips/sha3/sha3_noasm.go

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,20 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
//go:build !gc || purego || !s390x || !ignore
5+
//go:build (!amd64 && !s390x) || purego
66

77
package sha3
88

9-
func new224() *Digest {
10-
return new224Generic()
9+
func keccakF1600(a *[200]byte) {
10+
keccakF1600Generic(a)
1111
}
1212

13-
func new256() *Digest {
14-
return new256Generic()
13+
func (d *Digest) write(p []byte) (n int, err error) {
14+
return d.writeGeneric(p)
1515
}
16-
17-
func new384() *Digest {
18-
return new384Generic()
19-
}
20-
21-
func new512() *Digest {
22-
return new512Generic()
16+
func (d *Digest) read(out []byte) (n int, err error) {
17+
return d.readGeneric(out)
2318
}
24-
25-
func newShake128() *SHAKE {
26-
return newShake128Generic()
27-
}
28-
29-
func newShake256() *SHAKE {
30-
return newShake256Generic()
19+
func (d *Digest) sum(b []byte) []byte {
20+
return d.sumGeneric(b)
3121
}

0 commit comments

Comments
 (0)