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