1
2
3
4
5 package subtle
6
7 import (
8 "crypto/internal/fips140deps/byteorder"
9 "math/bits"
10 )
11
12
13
14
15
16 func ConstantTimeCompare(x, y []byte) int {
17 if len(x) != len(y) {
18 return 0
19 }
20
21 var v byte
22
23 for i := 0; i < len(x); i++ {
24 v |= x[i] ^ y[i]
25 }
26
27 return ConstantTimeByteEq(v, 0)
28 }
29
30
31
32
33
34 func ConstantTimeLessOrEqBytes(x, y []byte) int {
35 if len(x) != len(y) {
36 return 0
37 }
38
39
40
41 var b uint64
42 for len(x) > 8 {
43 x0 := byteorder.BEUint64(x[len(x)-8:])
44 y0 := byteorder.BEUint64(y[len(y)-8:])
45 _, b = bits.Sub64(y0, x0, b)
46 x = x[:len(x)-8]
47 y = y[:len(y)-8]
48 }
49 if len(x) > 0 {
50 xb := make([]byte, 8)
51 yb := make([]byte, 8)
52 copy(xb[8-len(x):], x)
53 copy(yb[8-len(y):], y)
54 x0 := byteorder.BEUint64(xb)
55 y0 := byteorder.BEUint64(yb)
56 _, b = bits.Sub64(y0, x0, b)
57 }
58 return int(b ^ 1)
59 }
60
61
62
63 func ConstantTimeSelect(v, x, y int) int { return ^(v-1)&x | (v-1)&y }
64
65
66 func ConstantTimeByteEq(x, y uint8) int {
67 return int((uint32(x^y) - 1) >> 31)
68 }
69
70
71 func ConstantTimeEq(x, y int32) int {
72 return int((uint64(uint32(x^y)) - 1) >> 63)
73 }
74
75
76
77
78 func ConstantTimeCopy(v int, x, y []byte) {
79 if len(x) != len(y) {
80 panic("subtle: slices have different lengths")
81 }
82
83 xmask := byte(v - 1)
84 ymask := byte(^(v - 1))
85 for i := 0; i < len(x); i++ {
86 x[i] = x[i]&xmask | y[i]&ymask
87 }
88 }
89
90
91
92 func ConstantTimeLessOrEq(x, y int) int {
93 x32 := int32(x)
94 y32 := int32(y)
95 return int(((x32 - y32 - 1) >> 31) & 1)
96 }
97
View as plain text