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