%PDF- %PDF-
| Direktori : /data/old/usr/lib/golang/src/crypto/internal/boring/ |
| Current File : //data/old/usr/lib/golang/src/crypto/internal/boring/boring.go |
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build linux && !android && !cmd_go_bootstrap && !msan && !no_openssl && !static
// +build linux,!android,!cmd_go_bootstrap,!msan,!no_openssl,!static
package boring
/*
#cgo LDFLAGS: -ldl
#include "goboringcrypto.h"
*/
import "C"
import (
"crypto/internal/boring/fipstls"
"crypto/internal/boring/sig"
"errors"
"math/big"
"os"
"runtime"
"unsafe"
"fmt"
)
const (
fipsOn = C.int(1)
fipsOff = C.int(0)
)
const (
OPENSSL_VERSION_1_1_0 = uint64(C.ulong(0x10100000))
OPENSSL_VERSION_3_0_0 = uint64(C.ulong(0x30000000))
)
// Enabled controls whether FIPS crypto is enabled.
var enabled = false
// When this variable is true, the go crypto API will panic when a caller
// tries to use the API in a non-compliant manner. When this is false, the
// go crytpo API will allow existing go crypto APIs to be used even
// if they aren't FIPS compliant. However, all the unerlying crypto operations
// will still be done by OpenSSL.
var strictFIPS = false
func init() {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
// Check if we can `dlopen` OpenSSL
if C._goboringcrypto_DLOPEN_OPENSSL() == C.NULL {
return
}
// Initialize the OpenSSL library.
C._goboringcrypto_OPENSSL_setup()
// Check to see if the system is running in FIPS mode, if so
// enable "boring" mode to call into OpenSSL for FIPS compliance.
if fipsModeEnabled() {
enableBoringFIPSMode()
}
sig.BoringCrypto()
}
func openSSLVersion() uint64 {
return uint64(C._goboringcrypto_internal_OPENSSL_VERSION_NUMBER())
}
func enableBoringFIPSMode() {
enabled = true
if C._goboringcrypto_OPENSSL_thread_setup() != 1 {
panic("boringcrypto: OpenSSL thread setup failed")
}
fipstls.Force()
}
func fipsModeEnabled() bool {
// Due to the way providers work in openssl 3, the FIPS methods are not
// necessarily going to be available for us to load based on the GOLANG_FIPS
// environment variable alone. For now, we must rely on the config to tell
// us if the provider is configured and active.
fipsConfigured := C._goboringcrypto_FIPS_mode() == fipsOn
openSSLVersion := openSSLVersion()
if openSSLVersion >= OPENSSL_VERSION_3_0_0 {
if !fipsConfigured && os.Getenv("GOLANG_FIPS") == "1" {
panic("GOLANG_FIPS=1 specified but OpenSSL FIPS provider is not configured")
}
return fipsConfigured
} else {
return os.Getenv("GOLANG_FIPS") == "1" || fipsConfigured
}
}
var randstub bool
func RandStubbed() bool {
return randstub
}
func StubOpenSSLRand() {
if !randstub {
randstub = true
C._goboringcrypto_stub_openssl_rand()
}
}
func RestoreOpenSSLRand() {
if randstub {
randstub = false
C._goboringcrypto_restore_openssl_rand()
}
}
// Unreachable marks code that should be unreachable
// when BoringCrypto is in use. It panics only when
// the system is in FIPS mode.
func Unreachable() {
if Enabled() {
panic("boringcrypto: invalid code execution")
}
}
// provided by runtime to avoid os import
func runtime_arg0() string
func hasSuffix(s, t string) bool {
return len(s) > len(t) && s[len(s)-len(t):] == t
}
// UnreachableExceptTests marks code that should be unreachable
// when BoringCrypto is in use. It panics.
func UnreachableExceptTests() {
name := runtime_arg0()
// If BoringCrypto ran on Windows we'd need to allow _test.exe and .test.exe as well.
if Enabled() && !hasSuffix(name, "_test") && !hasSuffix(name, ".test") {
println("boringcrypto: unexpected code execution in", name)
panic("boringcrypto: invalid code execution")
}
}
func PanicIfStrictFIPS(msg string) {
if os.Getenv("GOLANG_STRICT_FIPS") == "1" || strictFIPS {
panic(msg)
}
}
func NewOpenSSLError(msg string) error {
var e C.ulong
message := fmt.Sprintf("\n%v\nopenssl error(s):", msg)
if openSSLVersion() >= OPENSSL_VERSION_3_0_0 {
for {
var buf [256]C.char
var file, fnc, data *C.char
var line, flags C.int
e = C._goboringcrypto_internal_ERR_get_error_all(&file, &line, &fnc, &data, &flags)
if e == 0 {
break
}
C._goboringcrypto_internal_ERR_error_string_n(e,(*C.uchar)(unsafe.Pointer (&buf[0])), 256)
message = fmt.Sprintf(
"%v\nfile: %v\nline: %v\nfunction: %v\nflags: %v\nerror string: %s\n",
message,C.GoString(file), line, C.GoString(fnc), flags, C.GoString(&(buf[0])))
}
} else {
for {
var buf [256]C.char
e = C._goboringcrypto_internal_ERR_get_error()
C._goboringcrypto_internal_ERR_error_string_n(e,(*C.uchar)(unsafe.Pointer (&buf[0])), 256)
if e == 0 {
break
}
message = fmt.Sprintf("%v: %v\n", message, buf)
}
}
return errors.New(message)
}
type fail string
func (e fail) Error() string { return "boringcrypto: " + string(e) + " failed" }
func bigToBN(x *big.Int) *C.GO_BIGNUM {
raw := x.Bytes()
return C._goboringcrypto_BN_bin2bn(base(raw), C.size_t(len(raw)), nil)
}
func bnToBig(bn *C.GO_BIGNUM) *big.Int {
raw := make([]byte, C._goboringcrypto_BN_num_bytes(bn))
n := C._goboringcrypto_BN_bn2bin(bn, base(raw))
return new(big.Int).SetBytes(raw[:n])
}
func bigToBn(bnp **C.GO_BIGNUM, b *big.Int) bool {
if *bnp != nil {
C._goboringcrypto_BN_free(*bnp)
*bnp = nil
}
if b == nil {
return true
}
raw := b.Bytes()
bn := C._goboringcrypto_BN_bin2bn(base(raw), C.size_t(len(raw)), nil)
if bn == nil {
return false
}
*bnp = bn
return true
}