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