1
2
3
4
5
6
7 package subtle
8
9 import (
10 "runtime"
11 "unsafe"
12 )
13
14 const wordSize = unsafe.Sizeof(uintptr(0))
15
16 const supportsUnaligned = runtime.GOARCH == "386" ||
17 runtime.GOARCH == "amd64" ||
18 runtime.GOARCH == "ppc64" ||
19 runtime.GOARCH == "ppc64le" ||
20 runtime.GOARCH == "s390x"
21
22 func xorBytes(dstb, xb, yb *byte, n int) {
23
24 dst := unsafe.Slice(dstb, n)
25 x := unsafe.Slice(xb, n)
26 y := unsafe.Slice(yb, n)
27
28 if supportsUnaligned || aligned(dstb, xb, yb) {
29 xorLoop(words(dst), words(x), words(y))
30 if uintptr(n)%wordSize == 0 {
31 return
32 }
33 done := n &^ int(wordSize-1)
34 dst = dst[done:]
35 x = x[done:]
36 y = y[done:]
37 }
38 xorLoop(dst, x, y)
39 }
40
41
42 func aligned(dst, x, y *byte) bool {
43 return (uintptr(unsafe.Pointer(dst))|uintptr(unsafe.Pointer(x))|uintptr(unsafe.Pointer(y)))&(wordSize-1) == 0
44 }
45
46
47
48 func words(x []byte) []uintptr {
49 n := uintptr(len(x)) / wordSize
50 if n == 0 {
51
52
53 return nil
54 }
55 return unsafe.Slice((*uintptr)(unsafe.Pointer(&x[0])), n)
56 }
57
58 func xorLoop[T byte | uintptr](dst, x, y []T) {
59 x = x[:len(dst)]
60 y = y[:len(dst)]
61 for i := range dst {
62 dst[i] = x[i] ^ y[i]
63 }
64 }
65
View as plain text