Skip to content

Commit

Permalink
[dev.boringcrypto] crypto/internal/boring: avoid allocation in big.In…
Browse files Browse the repository at this point in the history
…t conversion

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>
  • Loading branch information
rsc committed Apr 29, 2022
1 parent 509776b commit 3cb10d1
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 7 deletions.
26 changes: 19 additions & 7 deletions src/crypto/internal/boring/boring.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"crypto/internal/boring/sig"
_ "crypto/internal/boring/syso"
"math/big"
"math/bits"
"unsafe"
)

const available = true
Expand Down Expand Up @@ -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 {
Expand All @@ -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
}
Expand Down
2 changes: 2 additions & 0 deletions src/crypto/internal/boring/goboringcrypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Binary file modified src/crypto/internal/boring/syso/goboringcrypto_linux_amd64.syso
Binary file not shown.

0 comments on commit 3cb10d1

Please sign in to comment.