1// Copyright 2017 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5//go:build boringcrypto && linux && (amd64 || arm64) && !android && !msan 6 7package boring 8 9/* 10// goboringcrypto_linux_amd64.syso references pthread functions. 11#cgo LDFLAGS: "-pthread" 12 13#include "goboringcrypto.h" 14*/ 15import "C" 16import ( 17 "crypto/internal/boring/sig" 18 _ "crypto/internal/boring/syso" 19 "internal/stringslite" 20 "math/bits" 21 "unsafe" 22) 23 24const available = true 25 26func init() { 27 C._goboringcrypto_BORINGSSL_bcm_power_on_self_test() 28 if C._goboringcrypto_FIPS_mode() != 1 { 29 panic("boringcrypto: not in FIPS mode") 30 } 31 sig.BoringCrypto() 32} 33 34// Unreachable marks code that should be unreachable 35// when BoringCrypto is in use. It panics. 36func Unreachable() { 37 panic("boringcrypto: invalid code execution") 38} 39 40// provided by runtime to avoid os import. 41func runtime_arg0() string 42 43// UnreachableExceptTests marks code that should be unreachable 44// when BoringCrypto is in use. It panics. 45func UnreachableExceptTests() { 46 name := runtime_arg0() 47 // If BoringCrypto ran on Windows we'd need to allow _test.exe and .test.exe as well. 48 if !stringslite.HasSuffix(name, "_test") && !stringslite.HasSuffix(name, ".test") { 49 println("boringcrypto: unexpected code execution in", name) 50 panic("boringcrypto: invalid code execution") 51 } 52} 53 54type fail string 55 56func (e fail) Error() string { return "boringcrypto: " + string(e) + " failed" } 57 58func wbase(b BigInt) *C.uint8_t { 59 if len(b) == 0 { 60 return nil 61 } 62 return (*C.uint8_t)(unsafe.Pointer(&b[0])) 63} 64 65const wordBytes = bits.UintSize / 8 66 67func bigToBN(x BigInt) *C.GO_BIGNUM { 68 return C._goboringcrypto_BN_le2bn(wbase(x), C.size_t(len(x)*wordBytes), nil) 69} 70 71func bytesToBN(x []byte) *C.GO_BIGNUM { 72 return C._goboringcrypto_BN_bin2bn((*C.uint8_t)(&x[0]), C.size_t(len(x)), nil) 73} 74 75func bnToBig(bn *C.GO_BIGNUM) BigInt { 76 x := make(BigInt, (C._goboringcrypto_BN_num_bytes(bn)+wordBytes-1)/wordBytes) 77 if C._goboringcrypto_BN_bn2le_padded(wbase(x), C.size_t(len(x)*wordBytes), bn) == 0 { 78 panic("boringcrypto: bignum conversion failed") 79 } 80 return x 81} 82 83func bigToBn(bnp **C.GO_BIGNUM, b BigInt) bool { 84 if *bnp != nil { 85 C._goboringcrypto_BN_free(*bnp) 86 *bnp = nil 87 } 88 if b == nil { 89 return true 90 } 91 bn := bigToBN(b) 92 if bn == nil { 93 return false 94 } 95 *bnp = bn 96 return true 97} 98 99// noescape hides a pointer from escape analysis. noescape is 100// the identity function but escape analysis doesn't think the 101// output depends on the input. noescape is inlined and currently 102// compiles down to zero instructions. 103// USE CAREFULLY! 104// 105//go:nosplit 106func noescape(p unsafe.Pointer) unsafe.Pointer { 107 x := uintptr(p) 108 return unsafe.Pointer(x ^ 0) 109} 110 111var zero byte 112 113// addr converts p to its base addr, including a noescape along the way. 114// If p is nil, addr returns a non-nil pointer, so that the result can always 115// be dereferenced. 116// 117//go:nosplit 118func addr(p []byte) *byte { 119 if len(p) == 0 { 120 return &zero 121 } 122 return (*byte)(noescape(unsafe.Pointer(&p[0]))) 123} 124