• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2013 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
5package subtle_test
6
7import (
8	"bytes"
9	"crypto/rand"
10	. "crypto/subtle"
11	"fmt"
12	"io"
13	"testing"
14)
15
16func TestXORBytes(t *testing.T) {
17	for n := 1; n <= 1024; n++ {
18		if n > 16 && testing.Short() {
19			n += n >> 3
20		}
21		for alignP := 0; alignP < 8; alignP++ {
22			for alignQ := 0; alignQ < 8; alignQ++ {
23				for alignD := 0; alignD < 8; alignD++ {
24					p := make([]byte, alignP+n, alignP+n+10)[alignP:]
25					q := make([]byte, alignQ+n, alignQ+n+10)[alignQ:]
26					if n&1 != 0 {
27						p = p[:n]
28					} else {
29						q = q[:n]
30					}
31					if _, err := io.ReadFull(rand.Reader, p); err != nil {
32						t.Fatal(err)
33					}
34					if _, err := io.ReadFull(rand.Reader, q); err != nil {
35						t.Fatal(err)
36					}
37
38					d := make([]byte, alignD+n, alignD+n+10)
39					for i := range d {
40						d[i] = 0xdd
41					}
42					want := make([]byte, len(d), cap(d))
43					copy(want[:cap(want)], d[:cap(d)])
44					for i := 0; i < n; i++ {
45						want[alignD+i] = p[i] ^ q[i]
46					}
47
48					if XORBytes(d[alignD:], p, q); !bytes.Equal(d, want) {
49						t.Fatalf("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)
50					}
51				}
52			}
53		}
54	}
55}
56
57func TestXorBytesPanic(t *testing.T) {
58	mustPanic(t, "subtle.XORBytes: dst too short", func() {
59		XORBytes(nil, make([]byte, 1), make([]byte, 1))
60	})
61	mustPanic(t, "subtle.XORBytes: dst too short", func() {
62		XORBytes(make([]byte, 1), make([]byte, 2), make([]byte, 3))
63	})
64}
65
66func BenchmarkXORBytes(b *testing.B) {
67	dst := make([]byte, 1<<15)
68	data0 := make([]byte, 1<<15)
69	data1 := make([]byte, 1<<15)
70	sizes := []int64{1 << 3, 1 << 7, 1 << 11, 1 << 15}
71	for _, size := range sizes {
72		b.Run(fmt.Sprintf("%dBytes", size), func(b *testing.B) {
73			s0 := data0[:size]
74			s1 := data1[:size]
75			b.SetBytes(int64(size))
76			for i := 0; i < b.N; i++ {
77				XORBytes(dst, s0, s1)
78			}
79		})
80	}
81}
82
83func mustPanic(t *testing.T, expected string, f func()) {
84	t.Helper()
85	defer func() {
86		switch msg := recover().(type) {
87		case nil:
88			t.Errorf("expected panic(%q), but did not panic", expected)
89		case string:
90			if msg != expected {
91				t.Errorf("expected panic(%q), but got panic(%q)", expected, msg)
92			}
93		default:
94			t.Errorf("expected panic(%q), but got panic(%T%v)", expected, msg, msg)
95		}
96	}()
97	f()
98}
99