Source file src/crypto/internal/boring/boring.go

     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  	"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 bytesToBN(x []byte) *C.GO_BIGNUM {
    75  	return C._goboringcrypto_BN_bin2bn((*C.uint8_t)(&x[0]), C.size_t(len(x)), nil)
    76  }
    77  
    78  func bnToBig(bn *C.GO_BIGNUM) BigInt {
    79  	x := make(BigInt, (C._goboringcrypto_BN_num_bytes(bn)+wordBytes-1)/wordBytes)
    80  	if C._goboringcrypto_BN_bn2le_padded(wbase(x), C.size_t(len(x)*wordBytes), bn) == 0 {
    81  		panic("boringcrypto: bignum conversion failed")
    82  	}
    83  	return x
    84  }
    85  
    86  func bigToBn(bnp **C.GO_BIGNUM, b BigInt) bool {
    87  	if *bnp != nil {
    88  		C._goboringcrypto_BN_free(*bnp)
    89  		*bnp = nil
    90  	}
    91  	if b == nil {
    92  		return true
    93  	}
    94  	bn := bigToBN(b)
    95  	if bn == nil {
    96  		return false
    97  	}
    98  	*bnp = bn
    99  	return true
   100  }
   101  
   102  // noescape hides a pointer from escape analysis.  noescape is
   103  // the identity function but escape analysis doesn't think the
   104  // output depends on the input.  noescape is inlined and currently
   105  // compiles down to zero instructions.
   106  // USE CAREFULLY!
   107  //
   108  //go:nosplit
   109  func noescape(p unsafe.Pointer) unsafe.Pointer {
   110  	x := uintptr(p)
   111  	return unsafe.Pointer(x ^ 0)
   112  }
   113  
   114  var zero byte
   115  
   116  // addr converts p to its base addr, including a noescape along the way.
   117  // If p is nil, addr returns a non-nil pointer, so that the result can always
   118  // be dereferenced.
   119  //
   120  //go:nosplit
   121  func addr(p []byte) *byte {
   122  	if len(p) == 0 {
   123  		return &zero
   124  	}
   125  	return (*byte)(noescape(unsafe.Pointer(&p[0])))
   126  }
   127  

View as plain text