| // Copyright 2017 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| //go:build boringcrypto && linux && (amd64 || arm64) && !android && !msan | |
| package boring | |
| /* | |
| // goboringcrypto_linux_amd64.syso references pthread functions. | |
| #cgo LDFLAGS: "-pthread" | |
| #include "goboringcrypto.h" | |
| */ | |
| import "C" | |
| import ( | |
| "crypto/internal/boring/sig" | |
| _ "crypto/internal/boring/syso" | |
| "crypto/internal/fips140" | |
| "internal/stringslite" | |
| "math/bits" | |
| "unsafe" | |
| ) | |
| const available = true | |
| func init() { | |
| C._goboringcrypto_BORINGSSL_bcm_power_on_self_test() | |
| if C._goboringcrypto_FIPS_mode() != 1 { | |
| panic("boringcrypto: not in FIPS mode") | |
| } | |
| sig.BoringCrypto() | |
| } | |
| func init() { | |
| if fips140.Enabled { | |
| panic("boringcrypto: cannot use GODEBUG=fips140 with GOEXPERIMENT=boringcrypto") | |
| } | |
| } | |
| // Unreachable marks code that should be unreachable | |
| // when BoringCrypto is in use. It panics. | |
| func Unreachable() { | |
| panic("boringcrypto: invalid code execution") | |
| } | |
| // provided by runtime to avoid os import. | |
| func runtime_arg0() string | |
| // UnreachableExceptTests marks code that should be unreachable | |
| // when BoringCrypto is in use. It panics. | |
| func UnreachableExceptTests() { | |
| name := runtime_arg0() | |
| // If BoringCrypto ran on Windows we'd need to allow _test.exe and .test.exe as well. | |
| if !stringslite.HasSuffix(name, "_test") && !stringslite.HasSuffix(name, ".test") { | |
| println("boringcrypto: unexpected code execution in", name) | |
| panic("boringcrypto: invalid code execution") | |
| } | |
| } | |
| type fail string | |
| func (e fail) Error() string { return "boringcrypto: " + string(e) + " failed" } | |
| func wbase(b BigInt) *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 BigInt) *C.GO_BIGNUM { | |
| return C._goboringcrypto_BN_le2bn(wbase(x), C.size_t(len(x)*wordBytes), nil) | |
| } | |
| func bytesToBN(x []byte) *C.GO_BIGNUM { | |
| return C._goboringcrypto_BN_bin2bn((*C.uint8_t)(&x[0]), C.size_t(len(x)), nil) | |
| } | |
| func bnToBig(bn *C.GO_BIGNUM) BigInt { | |
| x := make(BigInt, (C._goboringcrypto_BN_num_bytes(bn)+wordBytes-1)/wordBytes) | |
| if C._goboringcrypto_BN_bn2le_padded(wbase(x), C.size_t(len(x)*wordBytes), bn) == 0 { | |
| panic("boringcrypto: bignum conversion failed") | |
| } | |
| return x | |
| } | |
| func bigToBn(bnp **C.GO_BIGNUM, b BigInt) bool { | |
| if *bnp != nil { | |
| C._goboringcrypto_BN_free(*bnp) | |
| *bnp = nil | |
| } | |
| if b == nil { | |
| return true | |
| } | |
| bn := bigToBN(b) | |
| if bn == nil { | |
| return false | |
| } | |
| *bnp = bn | |
| return true | |
| } | |
| // noescape hides a pointer from escape analysis. noescape is | |
| // the identity function but escape analysis doesn't think the | |
| // output depends on the input. noescape is inlined and currently | |
| // compiles down to zero instructions. | |
| // USE CAREFULLY! | |
| // | |
| //go:nosplit | |
| func noescape(p unsafe.Pointer) unsafe.Pointer { | |
| x := uintptr(p) | |
| return unsafe.Pointer(x ^ 0) | |
| } | |
| var zero byte | |
| // addr converts p to its base addr, including a noescape along the way. | |
| // If p is nil, addr returns a non-nil pointer, so that the result can always | |
| // be dereferenced. | |
| // | |
| //go:nosplit | |
| func addr(p []byte) *byte { | |
| if len(p) == 0 { | |
| return &zero | |
| } | |
| return (*byte)(noescape(unsafe.Pointer(&p[0]))) | |
| } |