Commit d58bf64d authored by Bryan A Ford's avatar Bryan A Ford Committed by Brad Fitzpatrick

crypto/subtle: simplify and speed up constant-time primitives

This changes improves the ConstantTimeByteEq and ConstantTimeEq
primitives to both simplify them and improve their performance.

Also, since there were no benchmarks for this package before,
this change adds benchmarks for ConstantTimeByteEq,
ConstantTimeEq, and ConstantTimeLessOrEq.

benchmarks on darwin/amd64, 10 runs on old vs new code:

name                    old time/op  new time/op  delta
ConstantTimeByteEq-4    2.28ns ±16%  1.53ns ± 2%  -33.09%  (p=0.000 n=10+9)
ConstantTimeEq-4        2.77ns ±10%  1.51ns ± 2%  -45.59%  (p=0.000 n=10+9)
ConstantTimeLessOrEq-4  1.52ns ± 8%  1.50ns ± 2%     ~     (p=0.866 n=9+9)

Change-Id: I29b8cbcf158e1f30411720db82d38b4ecd166b15
Reviewed-on: https://go-review.googlesource.com/45310Reviewed-by: 's avatarAdam Langley <agl@golang.org>
Reviewed-by: 's avatarBrad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent a1088483
......@@ -29,24 +29,12 @@ func ConstantTimeSelect(v, x, y int) int { return ^(v-1)&x | (v-1)&y }
// ConstantTimeByteEq returns 1 if x == y and 0 otherwise.
func ConstantTimeByteEq(x, y uint8) int {
z := ^(x ^ y)
z &= z >> 4
z &= z >> 2
z &= z >> 1
return int(z)
return int((uint32(x^y) - 1) >> 31)
}
// ConstantTimeEq returns 1 if x == y and 0 otherwise.
func ConstantTimeEq(x, y int32) int {
z := ^(x ^ y)
z &= z >> 16
z &= z >> 8
z &= z >> 4
z &= z >> 2
z &= z >> 1
return int(z & 1)
return int((uint64(uint32(x^y)) - 1) >> 63)
}
// ConstantTimeCopy copies the contents of y into x (a slice of equal length)
......
......@@ -125,3 +125,35 @@ func TestConstantTimeLessOrEq(t *testing.T) {
}
}
}
var benchmarkGlobal uint8
func BenchmarkConstantTimeByteEq(b *testing.B) {
var x, y uint8
for i := 0; i < b.N; i++ {
x, y = uint8(ConstantTimeByteEq(x, y)), x
}
benchmarkGlobal = x
}
func BenchmarkConstantTimeEq(b *testing.B) {
var x, y int
for i := 0; i < b.N; i++ {
x, y = ConstantTimeEq(int32(x), int32(y)), x
}
benchmarkGlobal = uint8(x)
}
func BenchmarkConstantTimeLessOrEq(b *testing.B) {
var x, y int
for i := 0; i < b.N; i++ {
x, y = ConstantTimeLessOrEq(x, y), x
}
benchmarkGlobal = uint8(x)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment