github.com/mad-day/Yawning-crypto@v0.0.0-20190711051033-5a5f8cca32ec/bcns/subtle.go (about) 1 // 2 // 64 bit Subtle Comparisons 3 // 4 // To the extent possible under law, Yawning Angel waived all copyright 5 // and related or neighboring rights to bcns, using the Creative 6 // Commons "CC0" public domain dedication. See LICENSE or 7 // <http://creativecommons.org/publicdomain/zero/1.0/> for full details. 8 9 package bcns 10 11 // 12 // These routines provide constant-time comparisons and other subtle operations 13 // analagous to the `crypto/subtle` package over 64 bit integers. 14 // 15 16 // Returns 1 if x != 0 17 // Returns 0 if x == 0 18 // x and y are arbitrary unsigned 64-bit integers 19 func ctIsNonZeroU64(x uint64) uint64 { 20 return (x | -x) >> 63 21 } 22 23 // Returns 1 if x != y 24 // Returns 0 if x == y 25 // x and y are arbitrary unsigned 64-bit integers 26 func ctNeU64(x, y uint64) uint64 { 27 return ((x - y) | (y - x)) >> 63 28 } 29 30 // Returns 1 if x == y 31 // Returns 0 if x != y 32 // x and y are arbitrary unsigned 64-bit integers 33 func ctEqU64(x, y uint64) uint64 { 34 return 1 ^ ctNeU64(x, y) 35 } 36 37 // Returns 1 if x < y 38 // Returns 0 if x >= y 39 // x and y are arbitrary unsigned 64-bit integers 40 func ctLtU64(x, y uint64) uint64 { 41 return (x ^ ((x ^ y) | ((x - y) ^ y))) >> 63 42 } 43 44 // Returns 1 if x > y 45 // Returns 0 if x <= y 46 // x and y are arbitrary unsigned 64-bit integers 47 func ctGtU64(x, y uint64) uint64 { 48 return ctLtU64(y, x) 49 } 50 51 // Returns 1 if x <= y 52 // Returns 0 if x > y 53 // x and y are arbitrary unsigned 64-bit integers 54 func ctLeU64(x, y uint64) uint64 { 55 return 1 ^ ctGtU64(x, y) 56 } 57 58 // Returns 1 if x >= y 59 // Returns 0 if x < y 60 // x and y are arbitrary unsigned 64-bit integers 61 func ctGeU64(x, y uint64) uint64 { 62 return 1 ^ ctLtU64(x, y) 63 } 64 65 // Returns 0xFFFF..FFFF if bit != 0 66 // Returns 0 if bit == 0 67 func ctMaskU64(bit uint64) uint64 { 68 return 0 - uint64(ctIsNonZeroU64(bit)) 69 } 70 71 // Conditionally return x or y depending on whether bit is set 72 // Equivalent to: return bit ? x : y 73 // x and y are arbitrary 64-bit unsigned integers 74 // bit must be either 0 or 1. 75 func selectU64(x, y, bit uint64) uint64 { 76 m := ctMaskU64(bit) 77 return (x & m) | (y & (^m)) 78 } 79 80 // Returns 0 if a >= b 81 // Returns 1 if a < b 82 // Where a and b are both 3-limb 64-bit integers. 83 func lessThanU192(a, b *[3]uint64) uint64 { 84 var r, m uint64 85 for i := 0; i < 3; i++ { 86 r |= ctLtU64(a[i], b[i]) & (^m) 87 m |= ctMaskU64(ctNeU64(a[i], b[i])) /* stop when a[i] != b[i] */ 88 } 89 return r & 1 90 }