// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:build !boringcrypto
+
package amd64_test
import (
if err != nil {
t.Fatalf("couldn't execute test: %s", err)
}
- if string(out) != "PASS\n" {
- t.Fatalf("test reported error: %s", string(out))
+ // Expect to see output of the form "PASS\n", unless the test binary
+ // was compiled for coverage (in which case there will be an extra line).
+ success := false
+ lines := strings.Split(string(out), "\n")
+ if len(lines) == 2 {
+ success = lines[0] == "PASS" && lines[1] == ""
+ } else if len(lines) == 3 {
+ success = lines[0] == "PASS" &&
+ strings.HasPrefix(lines[1], "coverage") && lines[2] == ""
+ }
+ if !success {
+ t.Fatalf("test reported error: %s lines=%+v", string(out), lines)
}
}
return typecheck.Expr(typecheck.NodAddr(n)).(*ir.AddrExpr)
}
- // ITabLsym returns the LSym representing the itab for concreate type typ
- // implementing interface iface.
+ // ITabLsym returns the LSym representing the itab for concrete type typ implementing
+ // interface iface. A dummy tab will be created in the unusual case where typ doesn't
+ // implement iface. Normally, this wouldn't happen, because the typechecker would
+ // have reported a compile-time error. This situation can only happen when the
+ // destination type of a type assert or a type in a type switch is parameterized, so
+ // it may sometimes, but not always, be a type that can't implement the specified
+ // interface.
func ITabLsym(typ, iface *types.Type) *obj.LSym {
s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString())
lsym := s.Linksym()
if !existed {
- writeITab(lsym, typ, iface)
+ writeITab(lsym, typ, iface, true)
}
return lsym
}
lsym := s.Linksym()
if !existed {
- writeITab(lsym, typ, iface)
+ writeITab(lsym, typ, iface, false)
}
n := ir.NewLinksymExpr(base.Pos, lsym, types.Types[types.TUINT8])
}
}
- // formalType replaces byte and rune aliases with real types.
+ // formalType replaces predeclared aliases with real types.
// They've been separate internally to make error messages
// better, but we have to merge them in the reflect tables.
func formalType(t *types.Type) *types.Type {
- if t == types.ByteType || t == types.RuneType {
+ switch t {
+ case types.AnyType, types.ByteType, types.RuneType:
return types.Types[t.Kind()]
}
return t
// for security, only the exported fields.
case types.TSTRUCT:
fields := t.Fields().Slice()
+
+ // omitFieldForAwfulBoringCryptoKludge reports whether
+ // the field t should be omitted from the reflect data.
+ // In the crypto/... packages we omit an unexported field
+ // named "boring", to keep from breaking client code that
+ // expects rsa.PublicKey etc to have only public fields.
+ // As the name suggests, this is an awful kludge, but it is
+ // limited to the dev.boringcrypto branch and avoids
+ // much more invasive effects elsewhere.
+ omitFieldForAwfulBoringCryptoKludge := func(t *types.Field) bool {
+ if t.Sym == nil || t.Sym.Name != "boring" || t.Sym.Pkg == nil {
+ return false
+ }
+ path := t.Sym.Pkg.Path
+ if t.Sym.Pkg == types.LocalPkg {
+ path = base.Ctxt.Pkgpath
+ }
+ return strings.HasPrefix(path, "crypto/")
+ }
+ newFields := fields[:0:0]
+ for _, t1 := range fields {
+ if !omitFieldForAwfulBoringCryptoKludge(t1) {
+ newFields = append(newFields, t1)
+ }
+ }
+ fields = newFields
+
for _, t1 := range fields {
writeType(t1.Type)
}
}
}
- // writeITab writes the itab for concrete type typ implementing
- // interface iface.
- func writeITab(lsym *obj.LSym, typ, iface *types.Type) {
+ // writeITab writes the itab for concrete type typ implementing interface iface. If
+ // allowNonImplement is true, allow the case where typ does not implement iface, and just
+ // create a dummy itab with zeroed-out method entries.
+ func writeITab(lsym *obj.LSym, typ, iface *types.Type, allowNonImplement bool) {
// TODO(mdempsky): Fix methodWrapper, geneq, and genhash (and maybe
// others) to stop clobbering these.
oldpos, oldfn := base.Pos, ir.CurFunc
break
}
}
- if sigs[0].Sym.Name == "==" {
- sigs = sigs[1:]
- if len(sigs) == 0 {
- break
- }
- }
}
- if len(sigs) != 0 {
+ completeItab := len(sigs) == 0
+ if !allowNonImplement && !completeItab {
base.Fatalf("incomplete itab")
}
o = objw.Uint32(lsym, o, types.TypeHash(typ)) // copy of type hash
o += 4 // skip unused field
for _, fn := range entries {
- o = objw.SymPtrWeak(lsym, o, fn, 0) // method pointer for each method
+ if !completeItab {
+ // If typ doesn't implement iface, make method entries be zero.
+ o = objw.Uintptr(lsym, o, 0)
+ } else {
+ o = objw.SymPtrWeak(lsym, o, fn, 0) // method pointer for each method
+ }
}
// Nothing writes static itabs, so they are read only.
objw.Global(lsym, int32(o), int16(obj.DUPOK|obj.RODATA))
}
writeType(types.NewPtr(types.Types[types.TSTRING]))
writeType(types.NewPtr(types.Types[types.TUNSAFEPTR]))
+ if base.Flag.G > 0 {
+ writeType(types.AnyType)
+ }
// emit type structs for error and func(error) string.
// The latter is the type of an auto-generated wrapper.
// Target method uses shaped names.
targs2 := make([]*types.Type, len(targs))
+ origRParams := deref(orig).OrigSym().Def.(*ir.Name).Type().RParams()
for i, t := range targs {
- targs2[i] = typecheck.Shapify(t, i)
+ targs2[i] = typecheck.Shapify(t, i, origRParams[i])
}
targs = targs2
sym := typecheck.MakeFuncInstSym(ir.MethodSym(methodrcvr, method.Sym), targs, false, true)
if sym.Def == nil {
- // Currently we make sure that we have all the instantiations
- // we need by generating them all in ../noder/stencil.go:instantiateMethods
- // TODO: maybe there's a better, more incremental way to generate
- // only the instantiations we need?
- base.Fatalf("instantiation %s not found", sym.Name)
+ // Currently we make sure that we have all the
+ // instantiations we need by generating them all in
+ // ../noder/stencil.go:instantiateMethods
+ // Extra instantiations because of an inlined function
+ // should have been exported, and so available via
+ // Resolve.
+ in := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
+ if in.Op() == ir.ONONAME {
+ base.Fatalf("instantiation %s not found", sym.Name)
+ }
+ sym = in.Sym()
}
target := ir.AsNode(sym.Def)
call = ir.NewCallExpr(base.Pos, ir.OCALL, target, args)
sym := typecheck.MakeDictSym(gf, targs, true)
// Dictionary should already have been generated by instantiateMethods().
+ // Extra dictionaries needed because of an inlined function should have been
+ // exported, and so available via Resolve.
if lsym := sym.Linksym(); len(lsym.P) == 0 {
- base.Fatalf("Dictionary should have already been generated: %s.%s", sym.Pkg.Path, sym.Name)
+ in := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
+ if in.Op() == ir.ONONAME {
+ base.Fatalf("Dictionary should have already been generated: %s.%s", sym.Pkg.Path, sym.Name)
+ }
+ sym = in.Sym()
}
// Make (or reuse) a node referencing the dictionary symbol.
}
gotool, err := testenv.GoTool()
if err != nil {
- fmt.Fprintln(os.Stderr, err)
+ fmt.Fprintln(os.Stderr, "locating go tool: ", err)
os.Exit(2)
}
tg.grepStdoutNot(`^testing \[sort.test\]$`, "unexpected test copy of testing")
tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing")
- tg.run("list", "-test", "cmd/dist", "cmd/doc")
- tg.grepStdout(`^cmd/dist$`, "missing cmd/dist")
+ tg.run("list", "-test", "cmd/buildid", "cmd/doc")
+ tg.grepStdout(`^cmd/buildid$`, "missing cmd/buildid")
tg.grepStdout(`^cmd/doc$`, "missing cmd/doc")
tg.grepStdout(`^cmd/doc\.test$`, "missing cmd/doc test")
- tg.grepStdoutNot(`^cmd/dist\.test$`, "unexpected cmd/dist test")
+ tg.grepStdoutNot(`^cmd/buildid\.test$`, "unexpected cmd/buildid test")
tg.grepStdoutNot(`^testing`, "unexpected testing")
tg.run("list", "-test", "runtime/cgo")
for buf.Len() < sys.ExecArgLengthLimit+1 {
buf.WriteString(testStr)
}
- tg.run("run", "-buildinfo=false", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go"))
+ tg.run("run", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go"))
if tg.stderr.String() != buf.String() {
t.Errorf("strings differ")
}
tg.grepStdout("p2: false", "p2 listed as BinaryOnly")
}
-// Issue 16050.
-func TestAlwaysLinkSysoFiles(t *testing.T) {
+// Issue 16050 and 21884.
+func TestLinkSysoFiles(t *testing.T) {
+ if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
+ t.Skip("not linux/amd64")
+ }
+
tg := testgo(t)
defer tg.cleanup()
tg.parallel()
tg.setenv("CGO_ENABLED", "0")
tg.run("list", "-f", "{{.SysoFiles}}", "syso")
tg.grepStdout("a.syso", "missing syso file with CGO_ENABLED=0")
+
+ tg.setenv("CGO_ENABLED", "1")
+ tg.run("list", "-msan", "-f", "{{.SysoFiles}}", "syso")
+ tg.grepStdoutNot("a.syso", "unexpected syso file with -msan")
}
// Issue 16120.
p.SwigFiles = pp.SwigFiles
p.SwigCXXFiles = pp.SwigCXXFiles
p.SysoFiles = pp.SysoFiles
+ if cfg.BuildMSan {
+ // There's no way for .syso files to be built both with and without
+ // support for memory sanitizer. Assume they are built without,
+ // and drop them.
+ p.SysoFiles = nil
+ }
p.CgoCFLAGS = pp.CgoCFLAGS
p.CgoCPPFLAGS = pp.CgoCPPFLAGS
p.CgoCXXFLAGS = pp.CgoCXXFLAGS
err error // created with fmt.Errorf
}
- func ImportErrorf(path, format string, args ...interface{}) ImportPathError {
+ func ImportErrorf(path, format string, args ...any) ImportPathError {
err := &importError{importPath: path, err: fmt.Errorf(format, args...)}
if errStr := err.Error(); !strings.Contains(errStr, path) {
panic(fmt.Sprintf("path %q not in error %q", path, errStr))
delete(packageCache, arg)
}
}
- resolvedImportCache.DeleteIf(func(key interface{}) bool {
+ resolvedImportCache.DeleteIf(func(key any) bool {
return shouldDelete[key.(importSpec).path]
})
- packageDataCache.DeleteIf(func(key interface{}) bool {
+ packageDataCache.DeleteIf(func(key any) bool {
return shouldDelete[key.(string)]
})
}
p := packageCache[arg]
if p != nil {
delete(packageCache, arg)
- resolvedImportCache.DeleteIf(func(key interface{}) bool {
+ resolvedImportCache.DeleteIf(func(key any) bool {
return key.(importSpec).path == p.ImportPath
})
packageDataCache.Delete(p.ImportPath)
parentIsStd: parentIsStd,
mode: mode,
}
- r := resolvedImportCache.Do(importKey, func() interface{} {
+ r := resolvedImportCache.Do(importKey, func() any {
var r resolvedImport
if build.IsLocalImport(path) {
r.dir = filepath.Join(parentDir, path)
// Load the package from its directory. If we already found the package's
// directory when resolving its import path, use that.
- data := packageDataCache.Do(r.path, func() interface{} {
+ data := packageDataCache.Do(r.path, func() any {
loaded = true
var data packageData
if r.dir != "" {
var isDirCache par.Cache
func isDir(path string) bool {
- return isDirCache.Do(path, func() interface{} {
+ return isDirCache.Do(path, func() any {
fi, err := fsys.Stat(path)
return err == nil && fi.IsDir()
}).(bool)
// goModPath returns the module path in the go.mod in dir, if any.
func goModPath(dir string) (path string) {
- return goModPathCache.Do(dir, func() interface{} {
+ return goModPathCache.Do(dir, func() any {
data, err := os.ReadFile(filepath.Join(dir, "go.mod"))
if err != nil {
return ""
for _, pattern = range patterns {
pid++
+ glob := pattern
+ all := strings.HasPrefix(pattern, "all:")
+ if all {
+ glob = pattern[len("all:"):]
+ }
// Check pattern is valid for //go:embed.
- if _, err := path.Match(pattern, ""); err != nil || !validEmbedPattern(pattern) {
+ if _, err := path.Match(glob, ""); err != nil || !validEmbedPattern(glob) {
return nil, nil, fmt.Errorf("invalid pattern syntax")
}
// Glob to find matches.
- match, err := fsys.Glob(pkgdir + string(filepath.Separator) + filepath.FromSlash(pattern))
+ match, err := fsys.Glob(pkgdir + string(filepath.Separator) + filepath.FromSlash(glob))
if err != nil {
return nil, nil, err
}
}
rel := filepath.ToSlash(path[len(pkgdir)+1:])
name := info.Name()
- if path != file && (isBadEmbedName(name) || name[0] == '.' || name[0] == '_') {
+ if path != file && (isBadEmbedName(name) || ((name[0] == '.' || name[0] == '_') && !all)) {
// Ignore bad names, assuming they won't go into modules.
// Also avoid hidden files that user may not know about.
// See golang.org/issue/42328.
}
}
+ // vcsStatusCache maps repository directories (string)
+ // to their VCS information (vcsStatusError).
+ var vcsStatusCache par.Cache
+
// setBuildInfo gathers build information, formats it as a string to be
// embedded in the binary, then sets p.Internal.BuildInfo to that string.
// setBuildInfo should only be called on a main package with no errors.
// executables always appear stale unless the user sets the same flags.
// Perhaps it's safe to omit those flags when GO_GCFLAGS and GO_LDFLAGS
// are not set?
- setPkgErrorf := func(format string, args ...interface{}) {
+ setPkgErrorf := func(format string, args ...any) {
if p.Error == nil {
p.Error = &PackageError{Err: fmt.Errorf(format, args...)}
}
Deps: deps,
}
appendSetting := func(key, value string) {
+ value = strings.ReplaceAll(value, "\n", " ") // make value safe
info.Settings = append(info.Settings, debug.BuildSetting{Key: key, Value: value})
}
// Add command-line flags relevant to the build.
// This is informational, not an exhaustive list.
- if cfg.BuildBuildinfo && !p.Standard {
- appendSetting("compiler", cfg.BuildContext.Compiler)
- if BuildAsmflags.present {
- appendSetting("asmflags", BuildAsmflags.String())
+ // Please keep the list sorted.
+ if !p.Standard {
+ if cfg.BuildASan {
+ appendSetting("-asan", "true")
}
- if BuildGcflags.present && cfg.BuildContext.Compiler == "gc" {
- appendSetting("gcflags", BuildGcflags.String())
+ if BuildAsmflags.present {
+ appendSetting("-asmflags", BuildAsmflags.String())
}
+ appendSetting("-compiler", cfg.BuildContext.Compiler)
if BuildGccgoflags.present && cfg.BuildContext.Compiler == "gccgo" {
- appendSetting("gccgoflags", BuildGccgoflags.String())
+ appendSetting("-gccgoflags", BuildGccgoflags.String())
+ }
+ if BuildGcflags.present && cfg.BuildContext.Compiler == "gc" {
+ appendSetting("-gcflags", BuildGcflags.String())
}
if BuildLdflags.present {
- appendSetting("ldflags", BuildLdflags.String())
+ appendSetting("-ldflags", BuildLdflags.String())
+ }
+ if cfg.BuildMSan {
+ appendSetting("-msan", "true")
}
- tags := append(cfg.BuildContext.BuildTags, cfg.BuildContext.ToolTags...)
- appendSetting("tags", strings.Join(tags, ","))
- appendSetting("CGO_ENABLED", strconv.FormatBool(cfg.BuildContext.CgoEnabled))
+ if cfg.BuildRace {
+ appendSetting("-race", "true")
+ }
+ if tags := cfg.BuildContext.BuildTags; len(tags) > 0 {
+ appendSetting("-tags", strings.Join(tags, ","))
+ }
+ cgo := "0"
if cfg.BuildContext.CgoEnabled {
- for _, name := range []string{"CGO_CPPFLAGS", "CGO_CFLAGS", "CGO_CXXFLAGS", "CGO_LDFLAGS"} {
+ cgo = "1"
+ }
+ appendSetting("CGO_ENABLED", cgo)
+ if cfg.BuildContext.CgoEnabled {
+ for _, name := range []string{"CGO_CFLAGS", "CGO_CPPFLAGS", "CGO_CXXFLAGS", "CGO_LDFLAGS"} {
appendSetting(name, cfg.Getenv(name))
}
}
+ appendSetting("GOARCH", cfg.BuildContext.GOARCH)
+ if cfg.GOEXPERIMENT != "" {
+ appendSetting("GOEXPERIMENT", cfg.GOEXPERIMENT)
+ }
+ appendSetting("GOOS", cfg.BuildContext.GOOS)
+ if key, val := cfg.GetArchEnv(); key != "" && val != "" {
+ appendSetting(key, val)
+ }
}
// Add VCS status if all conditions are true:
return
}
- st, err := vcsCmd.Status(vcsCmd, repoDir)
- if err != nil {
+ type vcsStatusError struct {
+ Status vcs.Status
+ Err error
+ }
+ cached := vcsStatusCache.Do(repoDir, func() any {
+ st, err := vcsCmd.Status(vcsCmd, repoDir)
+ return vcsStatusError{st, err}
+ }).(vcsStatusError)
+ if err := cached.Err; err != nil {
setVCSError(err)
return
}
+ st := cached.Status
+
+ appendSetting("vcs", vcsCmd.Cmd)
if st.Revision != "" {
- appendSetting(vcsCmd.Cmd+"revision", st.Revision)
+ appendSetting("vcs.revision", st.Revision)
}
if !st.CommitTime.IsZero() {
stamp := st.CommitTime.UTC().Format(time.RFC3339Nano)
- appendSetting(vcsCmd.Cmd+"committime", stamp)
+ appendSetting("vcs.time", stamp)
}
- appendSetting(vcsCmd.Cmd+"uncommitted", strconv.FormatBool(st.Uncommitted))
+ appendSetting("vcs.modified", strconv.FormatBool(st.Uncommitted))
}
text, err := info.MarshalText()
// These packages can use internal linking mode.
// Others trigger external mode.
var internalpkg = []string{
+ "crypto/internal/boring",
"crypto/x509",
"net",
"os/user",
*flagTmpdir = dir
ownTmpDir = true
AtExit(func() {
- ctxt.Out.Close()
os.RemoveAll(*flagTmpdir)
})
}
if ctxt.DynlinkingGo() && buildcfg.GOOS != "ios" {
// -flat_namespace is deprecated on iOS.
// It is useful for supporting plugins. We don't support plugins on iOS.
- argv = append(argv, "-Wl,-flat_namespace")
+ // -flat_namespace may cause the dynamic linker to hang at forkExec when
+ // resolving a lazy binding. See issue 38824.
+ // Force eager resolution to work around.
+ argv = append(argv, "-Wl,-flat_namespace", "-Wl,-bind_at_load")
}
if !combineDwarf {
argv = append(argv, "-Wl,-S") // suppress STAB (symbolic debugging) symbols
}
return strings.Trim(string(out), "\n")
}
- argv = append(argv, getPathFile("crtcxa.o"))
- argv = append(argv, getPathFile("crtdbase.o"))
+ // Since GCC version 11, the 64-bit version of GCC starting files
+ // are now suffixed by "_64". Even under "-maix64" multilib directory
+ // "crtcxa.o" is 32-bit.
+ crtcxa := getPathFile("crtcxa_64.o")
+ if !filepath.IsAbs(crtcxa) {
+ crtcxa = getPathFile("crtcxa.o")
+ }
+ crtdbase := getPathFile("crtdbase_64.o")
+ if !filepath.IsAbs(crtdbase) {
+ crtdbase = getPathFile("crtdbase.o")
+ }
+ argv = append(argv, crtcxa)
+ argv = append(argv, crtdbase)
}
if ctxt.linkShared {
// license that can be found in the LICENSE file.
// Package ecdsa implements the Elliptic Curve Digital Signature Algorithm, as
- // defined in FIPS 186-3.
+ // defined in FIPS 186-4 and SEC 1, Version 2.0.
//
- // This implementation derives the nonce from an AES-CTR CSPRNG keyed by:
- //
- // SHA2-512(priv.D || entropy || hash)[:32]
- //
- // The CSPRNG key is indifferentiable from a random oracle as shown in
- // [Coron], the AES-CTR stream is indifferentiable from a random oracle
- // under standard cryptographic assumptions (see [Larsson] for examples).
- //
- // References:
- // [Coron]
- // https://cs.nyu.edu/~dodis/ps/merkle.pdf
- // [Larsson]
- // https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf
+ // Signatures generated by this package are not deterministic, but entropy is
+ // mixed with the private key and the message, achieving the same level of
+ // security in case of randomness source failure.
package ecdsa
- // Further references:
- // [NSA]: Suite B implementer's guide to FIPS 186-3
- // https://apps.nsa.gov/iaarchive/library/ia-guidance/ia-solutions-for-classified/algorithm-guidance/suite-b-implementers-guide-to-fips-186-3-ecdsa.cfm
- // [SECG]: SECG, SEC1
- // http://www.secg.org/sec1-v2.pdf
+ // [FIPS 186-4] references ANSI X9.62-2005 for the bulk of the ECDSA algorithm.
+ // That standard is not freely available, which is a problem in an open source
+ // implementation, because not only the implementer, but also any maintainer,
+ // contributor, reviewer, auditor, and learner needs access to it. Instead, this
+ // package references and follows the equivalent [SEC 1, Version 2.0].
+ //
+ // [FIPS 186-4]: https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
+ // [SEC 1, Version 2.0]: https://www.secg.org/sec1-v2.pdf
import (
"crypto"
"golang.org/x/crypto/cryptobyte/asn1"
)
- // A invertible implements fast inverse mod Curve.Params().N
+import (
+ "crypto/internal/boring"
+ "unsafe"
+)
+
+ // A invertible implements fast inverse in GF(N).
type invertible interface {
- // Inverse returns the inverse of k in GF(P)
+ // Inverse returns the inverse of k mod Params().N.
Inverse(k *big.Int) *big.Int
}
- // combinedMult implements fast multiplication S1*g + S2*p (g - generator, p - arbitrary point)
+ // A combinedMult implements fast combined multiplication for verification.
type combinedMult interface {
- CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int)
+ // CombinedMult returns [s1]G + [s2]P where G is the generator.
+ CombinedMult(Px, Py *big.Int, s1, s2 []byte) (x, y *big.Int)
}
const (
type PublicKey struct {
elliptic.Curve
X, Y *big.Int
+
+ boring unsafe.Pointer
}
// Any methods implemented on PublicKey might need to also be implemented on
type PrivateKey struct {
PublicKey
D *big.Int
+
+ boring unsafe.Pointer
}
// Public returns the public key corresponding to priv.
//
// This method implements crypto.Signer, which is an interface to support keys
// where the private part is kept in, for example, a hardware module. Common
- // uses should use the Sign function in this package directly.
+ // uses can use the SignASN1 function in this package directly.
func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
+ if boring.Enabled && rand == boring.RandReader {
+ b, err := boringPrivateKey(priv)
+ if err != nil {
+ return nil, err
+ }
+ return boring.SignMarshalECDSA(b, digest)
+ }
+ boring.UnreachableExceptTests()
+
r, s, err := Sign(rand, priv, digest)
if err != nil {
return nil, err
var one = new(big.Int).SetInt64(1)
- // randFieldElement returns a random element of the field underlying the given
- // curve using the procedure given in [NSA] A.2.1.
+ // randFieldElement returns a random element of the order of the given
+ // curve using the procedure given in FIPS 186-4, Appendix B.5.1.
func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) {
params := c.Params()
- b := make([]byte, params.BitSize/8+8)
+ // Note that for P-521 this will actually be 63 bits more than the order, as
+ // division rounds down, but the extra bit is inconsequential.
+ b := make([]byte, params.BitSize/8+8) // TODO: use params.N.BitLen()
_, err = io.ReadFull(rand, b)
if err != nil {
return
// GenerateKey generates a public and private key pair.
func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) {
+ if boring.Enabled && rand == boring.RandReader {
+ x, y, d, err := boring.GenerateKeyECDSA(c.Params().Name)
+ if err != nil {
+ return nil, err
+ }
+ return &PrivateKey{PublicKey: PublicKey{Curve: c, X: x, Y: y}, D: d}, nil
+ }
+ boring.UnreachableExceptTests()
+
k, err := randFieldElement(c, rand)
if err != nil {
return nil, err
return priv, nil
}
- // hashToInt converts a hash value to an integer. There is some disagreement
- // about how this is done. [NSA] suggests that this is done in the obvious
- // manner, but [SECG] truncates the hash to the bit-length of the curve order
- // first. We follow [SECG] because that's what OpenSSL does. Additionally,
- // OpenSSL right shifts excess bits from the number if the hash is too large
- // and we mirror that too.
+ // hashToInt converts a hash value to an integer. Per FIPS 186-4, Section 6.4,
+ // we use the left-most bits of the hash to match the bit-length of the order of
+ // the curve. This also performs Step 5 of SEC 1, Version 2.0, Section 4.1.3.
func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
orderBits := c.Params().N.BitLen()
orderBytes := (orderBits + 7) / 8
return ret
}
- // fermatInverse calculates the inverse of k in GF(P) using Fermat's method.
- // This has better constant-time properties than Euclid's method (implemented
- // in math/big.Int.ModInverse) although math/big itself isn't strictly
- // constant-time so it's not perfect.
+ // fermatInverse calculates the inverse of k in GF(P) using Fermat's method
+ // (exponentiation modulo P - 2, per Euler's theorem). This has better
+ // constant-time properties than Euclid's method (implemented in
+ // math/big.Int.ModInverse and FIPS 186-4, Appendix C.1) although math/big
+ // itself isn't strictly constant-time so it's not perfect.
func fermatInverse(k, N *big.Int) *big.Int {
two := big.NewInt(2)
nMinus2 := new(big.Int).Sub(N, two)
// Sign signs a hash (which should be the result of hashing a larger message)
// using the private key, priv. If the hash is longer than the bit-length of the
// private key's curve order, the hash will be truncated to that length. It
- // returns the signature as a pair of integers. The security of the private key
- // depends on the entropy of rand.
+ // returns the signature as a pair of integers. Most applications should use
+ // SignASN1 instead of dealing directly with r, s.
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
randutil.MaybeReadByte(rand)
+ if boring.Enabled && rand == boring.RandReader {
+ b, err := boringPrivateKey(priv)
+ if err != nil {
+ return nil, nil, err
+ }
+ return boring.SignECDSA(b, hash)
+ }
+ boring.UnreachableExceptTests()
+
+ // This implementation derives the nonce from an AES-CTR CSPRNG keyed by:
+ //
+ // SHA2-512(priv.D || entropy || hash)[:32]
+ //
+ // The CSPRNG key is indifferentiable from a random oracle as shown in
+ // [Coron], the AES-CTR stream is indifferentiable from a random oracle
+ // under standard cryptographic assumptions (see [Larsson] for examples).
+ //
+ // [Coron]: https://cs.nyu.edu/~dodis/ps/merkle.pdf
+ // [Larsson]: https://web.archive.org/web/20040719170906/https://www.nada.kth.se/kurser/kth/2D1441/semteo03/lecturenotes/assump.pdf
+
// Get 256 bits of entropy from rand.
entropy := make([]byte, 32)
_, err = io.ReadFull(rand, entropy)
return
}
- // Initialize an SHA-512 hash context; digest ...
+ // Initialize an SHA-512 hash context; digest...
md := sha512.New()
md.Write(priv.D.Bytes()) // the private key,
md.Write(entropy) // the entropy,
S: cipher.NewCTR(block, []byte(aesIV)),
}
- // See [NSA] 3.4.1
c := priv.PublicKey.Curve
return sign(priv, &csprng, c, hash)
}
func signGeneric(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, hash []byte) (r, s *big.Int, err error) {
+ // SEC 1, Version 2.0, Section 4.1.3
N := c.Params().N
if N.Sign() == 0 {
return nil, nil, errZeroParam
// SignASN1 signs a hash (which should be the result of hashing a larger message)
// using the private key, priv. If the hash is longer than the bit-length of the
// private key's curve order, the hash will be truncated to that length. It
- // returns the ASN.1 encoded signature. The security of the private key
- // depends on the entropy of rand.
+ // returns the ASN.1 encoded signature.
func SignASN1(rand io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) {
return priv.Sign(rand, hash, nil)
}
// Verify verifies the signature in r, s of hash using the public key, pub. Its
- // return value records whether the signature is valid.
+ // return value records whether the signature is valid. Most applications should
+ // use VerifyASN1 instead of dealing directly with r, s.
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
- // See [NSA] 3.4.2
+ if boring.Enabled {
+ b, err := boringPublicKey(pub)
+ if err != nil {
+ return false
+ }
+ return boring.VerifyECDSA(b, hash, r, s)
+ }
+ boring.UnreachableExceptTests()
+
c := pub.Curve
N := c.Params().N
}
func verifyGeneric(pub *PublicKey, c elliptic.Curve, hash []byte, r, s *big.Int) bool {
+ // SEC 1, Version 2.0, Section 4.1.4
e := hashToInt(hash, c)
var w *big.Int
N := c.Params().N
package tls
+import "crypto/internal/boring"
+
import (
"crypto"
"crypto/aes"
ka func(version uint16) keyAgreement
// flags is a bitmask of the suite* values, above.
flags int
- cipher func(key, iv []byte, isRead bool) interface{}
+ cipher func(key, iv []byte, isRead bool) any
mac func(key []byte) hash.Hash
aead func(key, fixedNonce []byte) aead
}
return false
}
- func cipherRC4(key, iv []byte, isRead bool) interface{} {
+ func cipherRC4(key, iv []byte, isRead bool) any {
cipher, _ := rc4.NewCipher(key)
return cipher
}
- func cipher3DES(key, iv []byte, isRead bool) interface{} {
+ func cipher3DES(key, iv []byte, isRead bool) any {
block, _ := des.NewTripleDESCipher(key)
if isRead {
return cipher.NewCBCDecrypter(block, iv)
return cipher.NewCBCEncrypter(block, iv)
}
- func cipherAES(key, iv []byte, isRead bool) interface{} {
+ func cipherAES(key, iv []byte, isRead bool) any {
block, _ := aes.NewCipher(key)
if isRead {
return cipher.NewCBCDecrypter(block, iv)
// macSHA1 returns a SHA-1 based constant time MAC.
func macSHA1(key []byte) hash.Hash {
- return hmac.New(newConstantTimeHash(sha1.New), key)
+ h := sha1.New
+ // The BoringCrypto SHA1 does not have a constant-time
+ // checksum function, so don't try to use it.
+ if !boring.Enabled {
+ h = newConstantTimeHash(h)
+ }
+ return hmac.New(h, key)
}
// macSHA256 returns a SHA-256 based MAC. This is only supported in TLS 1.2 and
if err != nil {
panic(err)
}
- aead, err := cipher.NewGCM(aes)
+ type gcmtls interface {
+ NewGCMTLS() (cipher.AEAD, error)
+ }
+ var aead cipher.AEAD
+ if aesTLS, ok := aes.(gcmtls); ok {
+ aead, err = aesTLS.NewGCMTLS()
+ } else {
+ boring.Unreachable()
+ aead, err = cipher.NewGCM(aes)
+ }
if err != nil {
panic(err)
}
func (c *cthWrapper) Sum(b []byte) []byte { return c.h.ConstantTimeSum(b) }
func newConstantTimeHash(h func() hash.Hash) func() hash.Hash {
+ boring.Unreachable()
return func() hash.Hash {
return &cthWrapper{h().(constantTimeHash)}
}
// hash function associated with the Ed25519 signature scheme.
var directSigning crypto.Hash = 0
-// supportedSignatureAlgorithms contains the signature and hash algorithms that
+// defaultSupportedSignatureAlgorithms contains the signature and hash algorithms that
// the code advertises as supported in a TLS 1.2+ ClientHello and in a TLS 1.2+
// CertificateRequest. The two fields are merged to match with TLS 1.3.
// Note that in TLS 1.2, the ECDSA algorithms are not constrained to P-256, etc.
-var supportedSignatureAlgorithms = []SignatureScheme{
+var defaultSupportedSignatureAlgorithms = []SignatureScheme{
PSSWithSHA256,
ECDSAWithP256AndSHA256,
Ed25519,
}
func (c *Config) cipherSuites() []uint16 {
+ if needFIPS() {
+ return fipsCipherSuites(c)
+ }
if c.CipherSuites != nil {
return c.CipherSuites
}
func (c *Config) supportedVersions(isClient bool) []uint16 {
versions := make([]uint16, 0, len(supportedVersions))
for _, v := range supportedVersions {
+ if needFIPS() && (v < fipsMinVersion(c) || v > fipsMaxVersion(c)) {
+ continue
+ }
if (c == nil || c.MinVersion == 0) && !debugEnableTLS10 &&
isClient && v < VersionTLS12 {
continue
var defaultCurvePreferences = []CurveID{X25519, CurveP256, CurveP384, CurveP521}
func (c *Config) curvePreferences() []CurveID {
+ if needFIPS() {
+ return fipsCurvePreferences(c)
+ }
if c == nil || len(c.CurvePreferences) == 0 {
return defaultCurvePreferences
}
return &emptyConfig
}
- func unexpectedMessageError(wanted, got interface{}) error {
+ func unexpectedMessageError(wanted, got any) error {
return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted)
}
}
if hello.vers >= VersionTLS12 {
- hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms
+ hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
+ }
+ if testingOnlyForceClientHelloSignatureAlgorithms != nil {
+ hello.supportedSignatureAlgorithms = testingOnlyForceClientHelloSignatureAlgorithms
}
var params ecdheParameters
clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
- var clientCipher, serverCipher interface{}
+ var clientCipher, serverCipher any
var clientHash, serverHash hash.Hash
if hs.suite.cipher != nil {
clientCipher = hs.suite.cipher(clientKey, clientIV, false /* not for reading */)
if !c.config.InsecureSkipVerify {
opts := x509.VerifyOptions{
+ IsBoring: isBoringCertificate,
+
Roots: c.config.RootCAs,
CurrentTime: c.config.time(),
DNSName: c.config.ServerName,
"time"
)
- var tests = []interface{}{
+ var tests = []any{
&clientHelloMsg{},
&serverHelloMsg{},
&finishedMsg{},
}
}
if rand.Intn(10) > 5 {
- m.supportedSignatureAlgorithms = supportedSignatureAlgorithms
+ m.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
}
if rand.Intn(10) > 5 {
- m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms
+ m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms()
}
for i := 0; i < rand.Intn(5); i++ {
m.alpnProtocols = append(m.alpnProtocols, randomString(rand.Intn(20)+1, rand))
m.scts = true
}
if rand.Intn(10) > 5 {
- m.supportedSignatureAlgorithms = supportedSignatureAlgorithms
+ m.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
}
if rand.Intn(10) > 5 {
- m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms
+ m.supportedSignatureAlgorithmsCert = supportedSignatureAlgorithms()
}
if rand.Intn(10) > 5 {
m.certificateAuthorities = make([][]byte, 3)
}
if c.vers >= VersionTLS12 {
certReq.hasSignatureAlgorithm = true
- certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms
+ certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
}
// An empty list of certificateAuthorities signals to
clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
- var clientCipher, serverCipher interface{}
+ var clientCipher, serverCipher any
var clientHash, serverHash hash.Hash
if hs.suite.aead == nil {
if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
opts := x509.VerifyOptions{
+ IsBoring: isBoringCertificate,
+
Roots: c.config.ClientCAs,
CurrentTime: c.config.time(),
Intermediates: x509.NewCertPool(),
// VerifyOptions contains parameters for Certificate.Verify.
type VerifyOptions struct {
+ // IsBoring is a validity check for BoringCrypto.
+ // If not nil, it will be called to check whether a given certificate
+ // can be used for constructing verification chains.
+ IsBoring func(*Certificate) bool
+
// DNSName, if set, is checked against the leaf certificate with
// Certificate.VerifyHostname or the platform verifier.
DNSName string
maxConstraintComparisons int,
nameType string,
name string,
- parsedName interface{},
- match func(parsedName, constraint interface{}) (match bool, err error),
- permitted, excluded interface{}) error {
+ parsedName any,
+ match func(parsedName, constraint any) (match bool, err error),
+ permitted, excluded any) error {
excludedValue := reflect.ValueOf(excluded)
}
if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox,
- func(parsedName, constraint interface{}) (bool, error) {
+ func(parsedName, constraint any) (bool, error) {
return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string))
}, c.PermittedEmailAddresses, c.ExcludedEmailAddresses); err != nil {
return err
}
if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name,
- func(parsedName, constraint interface{}) (bool, error) {
+ func(parsedName, constraint any) (bool, error) {
return matchDomainConstraint(parsedName.(string), constraint.(string))
}, c.PermittedDNSDomains, c.ExcludedDNSDomains); err != nil {
return err
}
if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "URI", name, uri,
- func(parsedName, constraint interface{}) (bool, error) {
+ func(parsedName, constraint any) (bool, error) {
return matchURIConstraint(parsedName.(*url.URL), constraint.(string))
}, c.PermittedURIDomains, c.ExcludedURIDomains); err != nil {
return err
}
if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "IP address", ip.String(), ip,
- func(parsedName, constraint interface{}) (bool, error) {
+ func(parsedName, constraint any) (bool, error) {
return matchIPConstraint(parsedName.(net.IP), constraint.(*net.IPNet))
}, c.PermittedIPRanges, c.ExcludedIPRanges); err != nil {
return err
}
}
+ if opts.IsBoring != nil && !opts.IsBoring(c) {
+ // IncompatibleUsage is not quite right here,
+ // but it's also the "no chains found" error
+ // and is close enough.
+ return CertificateInvalidError{c, IncompatibleUsage, ""}
+ }
+
return nil
}
}
}
- // Use Windows's own verification and chain building.
- if opts.Roots == nil && runtime.GOOS == "windows" {
- return c.systemVerify(&opts)
+ // Use platform verifiers, where available, if Roots is from SystemCertPool.
+ if runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
+ if opts.Roots == nil {
+ return c.systemVerify(&opts)
+ }
+ if opts.Roots != nil && opts.Roots.systemPool {
+ platformChains, err := c.systemVerify(&opts)
+ // If the platform verifier succeeded, or there are no additional
+ // roots, return the platform verifier result. Otherwise, continue
+ // with the Go verifier.
+ if err == nil || opts.Roots.len() == 0 {
+ return platformChains, err
+ }
+ }
}
if opts.Roots == nil {
}
// package was not found
- return p, fmt.Errorf("cannot find package %q in:\n\t%s", path, p.Dir)
+ return p, fmt.Errorf("cannot find package %q in:\n\t%s", p.ImportPath, p.Dir)
}
if mode&FindOnly != 0 {
isTest := strings.HasSuffix(name, "_test.go")
isXTest := false
- if isTest && strings.HasSuffix(pkg, "_test") {
+ if isTest && strings.HasSuffix(pkg, "_test") && p.Name != pkg {
isXTest = true
pkg = pkg[:len(pkg)-len("_test")]
}
// cgo (if cgo is enabled)
// $GOOS
// $GOARCH
+// boringcrypto
// ctxt.Compiler
// linux (if GOOS = android)
// solaris (if GOOS = illumos)
if ctxt.GOOS == "ios" && name == "darwin" {
return true
}
+ // Let applications know that the Go+BoringCrypto toolchain is in use.
+ if name == "boringcrypto" {
+ return true
+ }
// other tags
for _, tag := range ctxt.BuildTags {
# Bulk of the standard library must not use cgo.
# The prohibition stops at net and os/user.
- C !< fmt, go/types, CRYPTO-MATH;
+ C !< fmt, go/types;
CGO, OS
< plugin;
NET, log
< net/mail;
- # CRYPTO is core crypto algorithms - no cgo, fmt, net.
- # Unfortunately, stuck with reflect via encoding/binary.
- encoding/binary, golang.org/x/sys/cpu, hash
+ NONE < crypto/internal/boring/sig;
+ sync/atomic < crypto/internal/boring/fipstls;
+
+ encoding/binary, golang.org/x/sys/cpu, hash,
+ FMT, math/big,
+ CGO, crypto/internal/boring/sig, crypto/internal/boring/fipstls
< crypto
< crypto/subtle
< crypto/internal/subtle
< crypto/ed25519/internal/edwards25519/field, golang.org/x/crypto/curve25519/internal/field
< crypto/ed25519/internal/edwards25519
< crypto/cipher
+ < encoding/asn1
+ < crypto/internal/boring
< crypto/aes, crypto/des, crypto/hmac, crypto/md5, crypto/rc4,
crypto/sha1, crypto/sha256, crypto/sha512
- < CRYPTO;
-
- CGO, fmt, net !< CRYPTO;
-
- # CRYPTO-MATH is core bignum-based crypto - no cgo, net; fmt now ok.
- CRYPTO, FMT, math/big
< crypto/rand
< crypto/internal/randutil
< crypto/ed25519
- < encoding/asn1
< golang.org/x/crypto/cryptobyte/asn1
< golang.org/x/crypto/cryptobyte
< golang.org/x/crypto/curve25519
< crypto/dsa, crypto/elliptic, crypto/rsa
< crypto/ecdsa
- < CRYPTO-MATH;
+ < CRYPTO-BORING;
- CGO, net !< CRYPTO-MATH;
+ net !< CRYPTO-BORING;
# TLS, Prince of Dependencies.
- CRYPTO-MATH, NET, container/list, encoding/hex, encoding/pem
+ CRYPTO-BORING, NET, container/list, encoding/hex, encoding/pem
< golang.org/x/crypto/internal/subtle
< golang.org/x/crypto/chacha20
- < golang.org/x/crypto/poly1305
+ < golang.org/x/crypto/internal/poly1305
< golang.org/x/crypto/chacha20poly1305
< golang.org/x/crypto/hkdf
< crypto/x509/internal/macos
< crypto/x509
< crypto/tls;
+ crypto/internal/boring/sig, crypto/internal/boring/fipstls
+ < crypto/tls/fipsonly;
+
+ crypto/internal/boring
+ < crypto/boring;
+
# crypto-aware packages
NET, crypto/rand, mime/quotedprintable
NET, testing, math/rand
< golang.org/x/net/nettest;
+ syscall
+ < os/exec/internal/fdtest;
+
FMT, container/heap, math/rand
< internal/trace;
`
import (
"bytes"
- "crypto/sha1"
"errors"
"fmt"
+ "hash/crc32"
"io"
"os"
"runtime"
func TestRaceCaseType(t *testing.T) {
var x, y int
- var i interface{} = x
+ var i any = x
c := make(chan int, 1)
go func() {
switch i.(type) {
func TestRaceCaseTypeBody(t *testing.T) {
var x, y int
- var i interface{} = &x
+ var i any = &x
c := make(chan int, 1)
go func() {
switch i := i.(type) {
// spurious extra instrumentation of the initial interface
// value.
var x, y int
- m := make(map[int]map[int]interface{})
- m[0] = make(map[int]interface{})
+ m := make(map[int]map[int]any)
+ m[0] = make(map[int]any)
c := make(chan int, 1)
go func() {
switch i := m[0][1].(type) {
}
func TestRaceEfaceWW(t *testing.T) {
- var a, b interface{}
+ var a, b any
ch := make(chan bool, 1)
go func() {
a = 1
c := make(chan bool)
v := 0
go func() {
- go func(x interface{}) {
+ go func(x any) {
}(v)
c <- true
}()
func TestRaceEmptyInterface1(t *testing.T) {
c := make(chan bool)
- var x interface{}
+ var x any
go func() {
x = nil
c <- true
func TestRaceEmptyInterface2(t *testing.T) {
c := make(chan bool)
- var x interface{}
+ var x any
go func() {
x = &Point{}
c <- true
func TestRaceTypeAssert(t *testing.T) {
c := make(chan bool, 1)
x := 0
- var i interface{} = x
+ var i any = x
go func() {
y := 0
i = y
err = nil
}
}()
- h := sha1.New()
+ h := crc32.New(crc32.MakeTable(0x12345678))
for b := range in {
h.Write(b)
}