github.com/cloudflare/circl@v1.5.0/ecc/bls12381/ff/common.go (about) 1 // Package ff provides finite fields of characteristic P381. 2 package ff 3 4 import ( 5 "crypto/rand" 6 "crypto/subtle" 7 "errors" 8 "io" 9 "math/big" 10 11 "github.com/cloudflare/circl/internal/conv" 12 ) 13 14 var ( 15 errInputLength = errors.New("incorrect input length") 16 errInputRange = errors.New("value out of range [0,order)") 17 errInputString = errors.New("invalid string") 18 ) 19 20 func errFirst(e ...error) (err error) { 21 for i := 0; i < len(e); i++ { 22 if e[i] != nil { 23 return e[i] 24 } 25 } 26 return 27 } 28 29 func setString(in string, order []byte) ([]uint64, error) { 30 inBig, ok := new(big.Int).SetString(in, 0) 31 if !ok { 32 return nil, errInputString 33 } 34 if inBig.Sign() < 0 || inBig.Cmp(new(big.Int).SetBytes(order)) >= 0 { 35 return nil, errInputRange 36 } 37 inBytes := inBig.FillBytes(make([]byte, len(order))) 38 return setBytesBounded(inBytes, order) 39 } 40 41 func setBytesBounded(in []byte, order []byte) ([]uint64, error) { 42 if isLessThan(in, order) == 0 { 43 return nil, errInputRange 44 } 45 return conv.BytesBe2Uint64Le(in), nil 46 } 47 48 func setBytesUnbounded(in []byte, order []byte) []uint64 { 49 inBig := new(big.Int).SetBytes(in) 50 inBig.Mod(inBig, new(big.Int).SetBytes(order)) 51 inBytes := inBig.FillBytes(make([]byte, len(order))) 52 return conv.BytesBe2Uint64Le(inBytes) 53 } 54 55 // isLessThan returns 1 if 0 <= x < y, otherwise 0. Assumes that slices have the same length. 56 func isLessThan(x, y []byte) int { 57 i := 0 58 for i < len(x)-1 && x[i] == y[i] { 59 i++ 60 } 61 return 1 - subtle.ConstantTimeLessOrEq(int(y[i]), int(x[i])) 62 } 63 64 func randomInt(out []uint64, rnd io.Reader, order []byte) error { 65 r, err := rand.Int(rnd, new(big.Int).SetBytes(order)) 66 if err == nil { 67 conv.BigInt2Uint64Le(out, r) 68 } 69 return err 70 } 71 72 // ctUint64Eq returns 1 if the two slices have equal contents and 0 otherwise. 73 func ctUint64Eq(x, y []uint64) (b int) { 74 if len(x) == len(y) { 75 var v uint64 76 for i := 0; i < len(x); i++ { 77 v |= x[i] ^ y[i] 78 } 79 return subtle.ConstantTimeEq(int32(v>>32), 0) & subtle.ConstantTimeEq(int32(v), 0) 80 } 81 return 82 } 83 84 func cselectU64(z *uint64, b, x, y uint64) { *z = (x &^ (-b)) | (y & (-b)) }