Skip to content

Commit 57d0551

Browse files
rscgopherbot
authored andcommitted
crypto/subtle: add XORBytes
Export cipher.xorBytes as subtle.XORBytes, for proposal #53021, to provide fast XOR to cryptography libraries outside crypto/cipher. Along with the move, implement the alignment check TODO in xor_generic.go, so that systems with neither unaligned accesses nor custom assembly can still XOR a word at a time in word-based algorithms like GCM. This removes the need for the separate cipher.xorWords. Fixes #53021. Change-Id: I58f80a922f1cff671b5ebc6168eb046e702b5a4c Reviewed-on: https://go-review.googlesource.com/c/go/+/421435 TryBot-Result: Gopher Robot <[email protected]> Auto-Submit: Russ Cox <[email protected]> Run-TryBot: Russ Cox <[email protected]> Reviewed-by: Alan Donovan <[email protected]> Reviewed-by: Filippo Valsorda <[email protected]>
1 parent 90466e1 commit 57d0551

21 files changed

+255
-272
lines changed

api/next/53021.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pkg crypto/subtle, func XORBytes([]uint8, []uint8, []uint8) int #53021

src/crypto/cipher/cbc.go

+7-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111

1212
package cipher
1313

14-
import "crypto/internal/alias"
14+
import (
15+
"crypto/internal/alias"
16+
"crypto/subtle"
17+
)
1518

1619
type cbc struct {
1720
b Block
@@ -80,7 +83,7 @@ func (x *cbcEncrypter) CryptBlocks(dst, src []byte) {
8083

8184
for len(src) > 0 {
8285
// Write the xor to dst, then encrypt in place.
83-
xorBytes(dst[:x.blockSize], src[:x.blockSize], iv)
86+
subtle.XORBytes(dst[:x.blockSize], src[:x.blockSize], iv)
8487
x.b.Encrypt(dst[:x.blockSize], dst[:x.blockSize])
8588

8689
// Move to the next block with this block as the next iv.
@@ -162,7 +165,7 @@ func (x *cbcDecrypter) CryptBlocks(dst, src []byte) {
162165
// Loop over all but the first block.
163166
for start > 0 {
164167
x.b.Decrypt(dst[start:end], src[start:end])
165-
xorBytes(dst[start:end], dst[start:end], src[prev:start])
168+
subtle.XORBytes(dst[start:end], dst[start:end], src[prev:start])
166169

167170
end = start
168171
start = prev
@@ -171,7 +174,7 @@ func (x *cbcDecrypter) CryptBlocks(dst, src []byte) {
171174

172175
// The first block is special because it uses the saved iv.
173176
x.b.Decrypt(dst[start:end], src[start:end])
174-
xorBytes(dst[start:end], dst[start:end], x.iv)
177+
subtle.XORBytes(dst[start:end], dst[start:end], x.iv)
175178

176179
// Set the new iv to the first block we copied earlier.
177180
x.iv, x.tmp = x.tmp, x.iv

src/crypto/cipher/cfb.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66

77
package cipher
88

9-
import "crypto/internal/alias"
9+
import (
10+
"crypto/internal/alias"
11+
"crypto/subtle"
12+
)
1013

1114
type cfb struct {
1215
b Block
@@ -37,7 +40,7 @@ func (x *cfb) XORKeyStream(dst, src []byte) {
3740
// able to match CTR/OFB performance.
3841
copy(x.next[x.outUsed:], src)
3942
}
40-
n := xorBytes(dst, src, x.out[x.outUsed:])
43+
n := subtle.XORBytes(dst, src, x.out[x.outUsed:])
4144
if !x.decrypt {
4245
copy(x.next[x.outUsed:], dst)
4346
}

src/crypto/cipher/ctr.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212

1313
package cipher
1414

15-
import "crypto/internal/alias"
15+
import (
16+
"crypto/internal/alias"
17+
"crypto/subtle"
18+
)
1619

1720
type ctr struct {
1821
b Block
@@ -83,7 +86,7 @@ func (x *ctr) XORKeyStream(dst, src []byte) {
8386
if x.outUsed >= len(x.out)-x.b.BlockSize() {
8487
x.refill()
8588
}
86-
n := xorBytes(dst, src, x.out[x.outUsed:])
89+
n := subtle.XORBytes(dst, src, x.out[x.outUsed:])
8790
dst = dst[n:]
8891
src = src[n:]
8992
x.outUsed += n

src/crypto/cipher/export_test.go

-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@
55
package cipher
66

77
// Export internal functions for testing.
8-
var XorBytes = xorBytes
98
var NewCBCGenericEncrypter = newCBCGenericEncrypter
109
var NewCBCGenericDecrypter = newCBCGenericDecrypter

src/crypto/cipher/gcm.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -373,15 +373,15 @@ func (g *gcm) counterCrypt(out, in []byte, counter *[gcmBlockSize]byte) {
373373
g.cipher.Encrypt(mask[:], counter[:])
374374
gcmInc32(counter)
375375

376-
xorWords(out, in, mask[:])
376+
subtle.XORBytes(out, in, mask[:])
377377
out = out[gcmBlockSize:]
378378
in = in[gcmBlockSize:]
379379
}
380380

381381
if len(in) > 0 {
382382
g.cipher.Encrypt(mask[:], counter[:])
383383
gcmInc32(counter)
384-
xorBytes(out, in, mask[:])
384+
subtle.XORBytes(out, in, mask[:])
385385
}
386386
}
387387

@@ -423,5 +423,5 @@ func (g *gcm) auth(out, ciphertext, additionalData []byte, tagMask *[gcmTagSize]
423423
binary.BigEndian.PutUint64(out, y.low)
424424
binary.BigEndian.PutUint64(out[8:], y.high)
425425

426-
xorWords(out, out, tagMask[:])
426+
subtle.XORBytes(out, out, tagMask[:])
427427
}

src/crypto/cipher/ofb.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66

77
package cipher
88

9-
import "crypto/internal/alias"
9+
import (
10+
"crypto/internal/alias"
11+
"crypto/subtle"
12+
)
1013

1114
type ofb struct {
1215
b Block
@@ -66,7 +69,7 @@ func (x *ofb) XORKeyStream(dst, src []byte) {
6669
if x.outUsed >= len(x.out)-x.b.BlockSize() {
6770
x.refill()
6871
}
69-
n := xorBytes(dst, src, x.out[x.outUsed:])
72+
n := subtle.XORBytes(dst, src, x.out[x.outUsed:])
7073
dst = dst[n:]
7174
src = src[n:]
7275
x.outUsed += n

src/crypto/cipher/xor_amd64.go

-27
This file was deleted.

src/crypto/cipher/xor_arm64.go

-29
This file was deleted.

src/crypto/cipher/xor_generic.go

-91
This file was deleted.

src/crypto/cipher/xor_ppc64x.go

-29
This file was deleted.

src/crypto/cipher/xor_test.go

-75
This file was deleted.

0 commit comments

Comments
 (0)