]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.boringcrypto] crypto/internal/boring: avoid allocation in big.Int conversion
authorRuss Cox <rsc@golang.org>
Wed, 27 Apr 2022 13:02:53 +0000 (09:02 -0400)
committerRuss Cox <rsc@golang.org>
Fri, 29 Apr 2022 14:23:26 +0000 (14:23 +0000)
The conversion via byte slices is inefficient; we can convert via word slices
and avoid the copy entirely.

For #51940.

Change-Id: I06f747e0acffffae427d9706d43bdacf146c027d
Reviewed-on: https://go-review.googlesource.com/c/go/+/395875
Reviewed-by: Roland Shoemaker <roland@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/crypto/internal/boring/boring.go
src/crypto/internal/boring/goboringcrypto.h
src/crypto/internal/boring/syso/goboringcrypto_linux_amd64.syso

index 29e0baa1315e4b8c59c9f45ee4f68fa7ce134d60..7c6a730e0bf4cd3abeae9cc8ec3d163a9b1cd072 100644 (file)
@@ -18,6 +18,8 @@ import (
        "crypto/internal/boring/sig"
        _ "crypto/internal/boring/syso"
        "math/big"
+       "math/bits"
+       "unsafe"
 )
 
 const available = true
@@ -58,15 +60,26 @@ type fail string
 
 func (e fail) Error() string { return "boringcrypto: " + string(e) + " failed" }
 
+func wbase(b []big.Word) *C.uint8_t {
+       if len(b) == 0 {
+               return nil
+       }
+       return (*C.uint8_t)(unsafe.Pointer(&b[0]))
+}
+
+const wordBytes = bits.UintSize / 8
+
 func bigToBN(x *big.Int) *C.GO_BIGNUM {
-       raw := x.Bytes()
-       return C._goboringcrypto_BN_bin2bn(base(raw), C.size_t(len(raw)), nil)
+       raw := x.Bits()
+       return C._goboringcrypto_BN_le2bn(wbase(raw), C.size_t(len(raw)*wordBytes), nil)
 }
 
 func bnToBig(bn *C.GO_BIGNUM) *big.Int {
-       raw := make([]byte, C._goboringcrypto_BN_num_bytes(bn))
-       n := C._goboringcrypto_BN_bn2bin(bn, base(raw))
-       return new(big.Int).SetBytes(raw[:n])
+       raw := make([]big.Word, (C._goboringcrypto_BN_num_bytes(bn)+wordBytes-1)/wordBytes)
+       if C._goboringcrypto_BN_bn2le_padded(wbase(raw), C.size_t(len(raw)*wordBytes), bn) == 0 {
+               panic("boringcrypto: bignum conversion failed")
+       }
+       return new(big.Int).SetBits(raw)
 }
 
 func bigToBn(bnp **C.GO_BIGNUM, b *big.Int) bool {
@@ -77,8 +90,7 @@ func bigToBn(bnp **C.GO_BIGNUM, b *big.Int) bool {
        if b == nil {
                return true
        }
-       raw := b.Bytes()
-       bn := C._goboringcrypto_BN_bin2bn(base(raw), C.size_t(len(raw)), nil)
+       bn := bigToBN(b)
        if bn == nil {
                return false
        }
index 37b7917c048c710869976f37af94b0b95b65f2fe..d6d99b1dcde3dc3f4410d43e43ca0336ecc732e8 100644 (file)
@@ -141,7 +141,9 @@ unsigned _goboringcrypto_BN_num_bits(const GO_BIGNUM*);
 unsigned _goboringcrypto_BN_num_bytes(const GO_BIGNUM*);
 int _goboringcrypto_BN_is_negative(const GO_BIGNUM*);
 GO_BIGNUM* _goboringcrypto_BN_bin2bn(const uint8_t*, size_t, GO_BIGNUM*);
+GO_BIGNUM* _goboringcrypto_BN_le2bn(const uint8_t*, size_t, GO_BIGNUM*);
 size_t _goboringcrypto_BN_bn2bin(const GO_BIGNUM*, uint8_t*);
+int _goboringcrypto_BN_bn2le_padded(uint8_t*, size_t, const GO_BIGNUM*);
 
 // #include <openssl/ec.h>
 /*unchecked (opaque)*/ typedef struct GO_EC_GROUP { char data[1]; } GO_EC_GROUP;
index 2459dd780456b06ebb2c2e65db6eacdb622b7743..72e6c1783e16246439e1a18caa68bbedd3181e25 100644 (file)
Binary files a/src/crypto/internal/boring/syso/goboringcrypto_linux_amd64.syso and b/src/crypto/internal/boring/syso/goboringcrypto_linux_amd64.syso differ