1
2
3
4
5 package subtle_test
6
7 import (
8 "bytes"
9 "crypto/rand"
10 . "crypto/subtle"
11 "fmt"
12 "testing"
13 )
14
15 func TestXORBytes(t *testing.T) {
16 for n := 1; n <= 1024; n++ {
17 if n > 16 && testing.Short() {
18 n += n >> 3
19 }
20 for alignP := 0; alignP < 8; alignP++ {
21 for alignQ := 0; alignQ < 8; alignQ++ {
22 for alignD := 0; alignD < 8; alignD++ {
23 p := make([]byte, alignP+n, alignP+n+100)[alignP:]
24 q := make([]byte, alignQ+n, alignQ+n+100)[alignQ:]
25 if n&1 != 0 {
26 p = p[:n]
27 } else {
28 q = q[:n]
29 }
30 rand.Read(p)
31 rand.Read(q)
32
33 d := make([]byte, alignD+n+100)
34 rand.Read(d)
35
36 want := bytes.Clone(d)
37 for i := range n {
38 want[alignD+i] = p[i] ^ q[i]
39 }
40
41 if nn := XORBytes(d[alignD:], p, q); !bytes.Equal(d, want) {
42 t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d:\n\tp = %x\n\tq = %x\n\td = %x\n\twant %x\n", n, alignP, alignQ, alignD, p, q, d, want)
43 } else if nn != n {
44 t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d: got %d, want %d", n, alignP, alignQ, alignD, nn, n)
45 }
46 p1 := bytes.Clone(p)
47 if nn := XORBytes(p, p, q); !bytes.Equal(p, want[alignD:alignD+n]) {
48 t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d:\n\tp = %x\n\tq = %x\n\td = %x\n\twant %x\n", n, alignP, alignQ, alignD, p, q, d, want)
49 } else if nn != n {
50 t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d: got %d, want %d", n, alignP, alignQ, alignD, nn, n)
51 }
52 if nn := XORBytes(q, p1, q); !bytes.Equal(q, want[alignD:alignD+n]) {
53 t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d:\n\tp = %x\n\tq = %x\n\td = %x\n\twant %x\n", n, alignP, alignQ, alignD, p, q, d, want)
54 } else if nn != n {
55 t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d: got %d, want %d", n, alignP, alignQ, alignD, nn, n)
56 }
57
58 if nn := XORBytes(p, p, p); !bytes.Equal(p, make([]byte, n)) {
59 t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d: got %x, want %x", n, alignP, alignQ, alignD, p, make([]byte, n))
60 } else if nn != n {
61 t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d: got %d, want %d", n, alignP, alignQ, alignD, nn, n)
62 }
63 if nn := XORBytes(p1, q, q); !bytes.Equal(p1, make([]byte, n)) {
64 t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d: got %x, want %x", n, alignP, alignQ, alignD, p1, make([]byte, n))
65 } else if nn != n {
66 t.Errorf("n=%d alignP=%d alignQ=%d alignD=%d: got %d, want %d", n, alignP, alignQ, alignD, nn, n)
67 }
68 }
69 }
70 }
71 }
72 }
73
74 func TestXorBytesPanic(t *testing.T) {
75 mustPanic(t, "subtle.XORBytes: dst too short", func() {
76 XORBytes(nil, make([]byte, 1), make([]byte, 1))
77 })
78 mustPanic(t, "subtle.XORBytes: dst too short", func() {
79 XORBytes(make([]byte, 1), make([]byte, 2), make([]byte, 3))
80 })
81 mustPanic(t, "subtle.XORBytes: invalid overlap", func() {
82 x := make([]byte, 3)
83 XORBytes(x, x[1:], make([]byte, 2))
84 })
85 mustPanic(t, "subtle.XORBytes: invalid overlap", func() {
86 x := make([]byte, 3)
87 XORBytes(x, make([]byte, 2), x[1:])
88 })
89 }
90
91 func BenchmarkXORBytes(b *testing.B) {
92 dst := make([]byte, 1<<15)
93 data0 := make([]byte, 1<<15)
94 data1 := make([]byte, 1<<15)
95 sizes := []int64{1 << 3, 1 << 7, 1 << 11, 1 << 15}
96 for _, size := range sizes {
97 b.Run(fmt.Sprintf("%dBytes", size), func(b *testing.B) {
98 s0 := data0[:size]
99 s1 := data1[:size]
100 b.SetBytes(int64(size))
101 for i := 0; i < b.N; i++ {
102 XORBytes(dst, s0, s1)
103 }
104 })
105 }
106 }
107
108 func mustPanic(t *testing.T, expected string, f func()) {
109 t.Helper()
110 defer func() {
111 t.Helper()
112 switch msg := recover().(type) {
113 case nil:
114 t.Errorf("expected panic(%q), but did not panic", expected)
115 case string:
116 if msg != expected {
117 t.Errorf("expected panic(%q), but got panic(%q)", expected, msg)
118 }
119 default:
120 t.Errorf("expected panic(%q), but got panic(%T%v)", expected, msg, msg)
121 }
122 }()
123 f()
124 }
125
View as plain text