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