diff --git a/patches/001-initial-openssl-for-fips.patch b/patches/001-initial-openssl-for-fips.patch index cd12583930..ca4b1e7d5a 100644 --- a/patches/001-initial-openssl-for-fips.patch +++ b/patches/001-initial-openssl-for-fips.patch @@ -1,1573 +1,10 @@ -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD diff --git a/src/cmd/api/boring_test.go b/src/cmd/api/boring_test.go index f0e3575637..a4139169b8 100644 -======= -======= -diff --git a/src/cmd/api/api.go-e b/src/cmd/api/api.go-e -new file mode 100644 -index 0000000000..b07f5db9d4 ---- /dev/null -+++ b/src/cmd/api/api.go-e -@@ -0,0 +1,1229 @@ -+// Copyright 2011 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. -+ -+// Package api computes the exported API of a set of Go packages. -+// It is only a test, not a command, nor a usefully importable package. -+package api -+ -+import ( -+ "bufio" -+ "bytes" -+ "encoding/json" -+ "fmt" -+ "go/ast" -+ "go/build" -+ "go/parser" -+ "go/token" -+ "go/types" -+ "internal/testenv" -+ "io" -+ "log" -+ "os" -+ "os/exec" -+ "path/filepath" -+ "regexp" -+ "runtime" -+ "sort" -+ "strconv" -+ "strings" -+ "sync" -+ "testing" -+) -+ -+const verbose = false -+ -+func goCmd() string { -+ var exeSuffix string -+ if runtime.GOOS == "windows" { -+ exeSuffix = ".exe" -+ } -+ path := filepath.Join(testenv.GOROOT(nil), "bin", "go"+exeSuffix) -+ if _, err := os.Stat(path); err == nil { -+ return path -+ } -+ return "go" -+} -+ -+// contexts are the default contexts which are scanned. -+var contexts = []*build.Context{ -+ {GOOS: "linux", GOARCH: "386", CgoEnabled: true}, -+ {GOOS: "linux", GOARCH: "386"}, -+ {GOOS: "linux", GOARCH: "amd64", CgoEnabled: true}, -+ {GOOS: "linux", GOARCH: "amd64"}, -+ {GOOS: "linux", GOARCH: "arm", CgoEnabled: true}, -+ {GOOS: "linux", GOARCH: "arm"}, -+ {GOOS: "darwin", GOARCH: "amd64", CgoEnabled: true}, -+ {GOOS: "darwin", GOARCH: "amd64"}, -+ {GOOS: "darwin", GOARCH: "arm64", CgoEnabled: true}, -+ {GOOS: "darwin", GOARCH: "arm64"}, -+ {GOOS: "windows", GOARCH: "amd64"}, -+ {GOOS: "windows", GOARCH: "386"}, -+ {GOOS: "freebsd", GOARCH: "386", CgoEnabled: true}, -+ {GOOS: "freebsd", GOARCH: "386"}, -+ {GOOS: "freebsd", GOARCH: "amd64", CgoEnabled: true}, -+ {GOOS: "freebsd", GOARCH: "amd64"}, -+ {GOOS: "freebsd", GOARCH: "arm", CgoEnabled: true}, -+ {GOOS: "freebsd", GOARCH: "arm"}, -+ {GOOS: "freebsd", GOARCH: "arm64", CgoEnabled: true}, -+ {GOOS: "freebsd", GOARCH: "arm64"}, -+ {GOOS: "freebsd", GOARCH: "riscv64", CgoEnabled: true}, -+ {GOOS: "freebsd", GOARCH: "riscv64"}, -+ {GOOS: "netbsd", GOARCH: "386", CgoEnabled: true}, -+ {GOOS: "netbsd", GOARCH: "386"}, -+ {GOOS: "netbsd", GOARCH: "amd64", CgoEnabled: true}, -+ {GOOS: "netbsd", GOARCH: "amd64"}, -+ {GOOS: "netbsd", GOARCH: "arm", CgoEnabled: true}, -+ {GOOS: "netbsd", GOARCH: "arm"}, -+ {GOOS: "netbsd", GOARCH: "arm64", CgoEnabled: true}, -+ {GOOS: "netbsd", GOARCH: "arm64"}, -+ {GOOS: "openbsd", GOARCH: "386", CgoEnabled: true}, -+ {GOOS: "openbsd", GOARCH: "386"}, -+ {GOOS: "openbsd", GOARCH: "amd64", CgoEnabled: true}, -+ {GOOS: "openbsd", GOARCH: "amd64"}, -+} -+ -+func contextName(c *build.Context) string { -+ s := c.GOOS + "-" + c.GOARCH -+ if c.CgoEnabled { -+ s += "-cgo" -+ } -+ if c.Dir != "" { -+ s += fmt.Sprintf(" [%s]", c.Dir) -+ } -+ return s -+} -+ -+var internalPkg = regexp.MustCompile(`(^|/)internal($|/)`) -+ -+var exitCode = 0 -+ -+func Check(t *testing.T) { -+ checkFiles, err := filepath.Glob(filepath.Join(testenv.GOROOT(t), "api/go1*.txt")) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ var nextFiles []string -+ if strings.Contains(runtime.Version(), "devel") { -+ next, err := filepath.Glob(filepath.Join(testenv.GOROOT(t), "api/next/*.txt")) -+ if err != nil { -+ t.Fatal(err) -+ } -+ nextFiles = next -+ } -+ -+ for _, c := range contexts { -+ c.Compiler = build.Default.Compiler -+ } -+ -+ walkers := make([]*Walker, len(contexts)) -+ var wg sync.WaitGroup -+ for i, context := range contexts { -+ i, context := i, context -+ wg.Add(1) -+ go func() { -+ defer wg.Done() -+ walkers[i] = NewWalker(context, filepath.Join(testenv.GOROOT(t), "src")) -+ }() -+ } -+ wg.Wait() -+ -+ var featureCtx = make(map[string]map[string]bool) // feature -> context name -> true -+ for _, w := range walkers { -+ for _, name := range w.stdPackages { -+ pkg, err := w.import_(name) -+ if _, nogo := err.(*build.NoGoError); nogo { -+ continue -+ } -+ if err != nil { -+ log.Fatalf("Import(%q): %v", name, err) -+ } -+ w.export(pkg) -+ } -+ -+ ctxName := contextName(w.context) -+ for _, f := range w.Features() { -+ if featureCtx[f] == nil { -+ featureCtx[f] = make(map[string]bool) -+ } -+ featureCtx[f][ctxName] = true -+ } -+ } -+ -+ var features []string -+ for f, cmap := range featureCtx { -+ if len(cmap) == len(contexts) { -+ features = append(features, f) -+ continue -+ } -+ comma := strings.Index(f, ",") -+ for cname := range cmap { -+ f2 := fmt.Sprintf("%s (%s)%s", f[:comma], cname, f[comma:]) -+ features = append(features, f2) -+ } -+ } -+ -+ bw := bufio.NewWriter(os.Stdout) -+ defer bw.Flush() -+ -+ var required []string -+ for _, file := range checkFiles { -+ required = append(required, fileFeatures(file, needApproval(file))...) -+ } -+ for _, file := range nextFiles { -+ required = append(required, fileFeatures(file, true)...) -+ } -+ exception := fileFeatures(filepath.Join(testenv.GOROOT(t), "api/except.txt"), false) -+ -+ if exitCode == 1 { -+ t.Errorf("API database problems found") -+ } -+ if !compareAPI(bw, features, required, exception) { -+ t.Errorf("API differences found") -+ } -+} -+ -+// export emits the exported package features. -+func (w *Walker) export(pkg *apiPackage) { -+ if verbose { -+ log.Println(pkg) -+ } -+ pop := w.pushScope("pkg " + pkg.Path()) -+ w.current = pkg -+ w.collectDeprecated() -+ scope := pkg.Scope() -+ for _, name := range scope.Names() { -+ if token.IsExported(name) { -+ w.emitObj(scope.Lookup(name)) -+ } -+ } -+ pop() -+} -+ -+func set(items []string) map[string]bool { -+ s := make(map[string]bool) -+ for _, v := range items { -+ s[v] = true -+ } -+ return s -+} -+ -+var spaceParensRx = regexp.MustCompile(` \(\S+?\)`) -+ -+func featureWithoutContext(f string) string { -+ if !strings.Contains(f, "(") { -+ return f -+ } -+ return spaceParensRx.ReplaceAllString(f, "") -+} -+ -+// portRemoved reports whether the given port-specific API feature is -+// okay to no longer exist because its port was removed. -+func portRemoved(feature string) bool { -+ return strings.Contains(feature, "(darwin-386)") || -+ strings.Contains(feature, "(darwin-386-cgo)") -+} -+ -+func compareAPI(w io.Writer, features, required, exception []string) (ok bool) { -+ ok = true -+ -+ featureSet := set(features) -+ exceptionSet := set(exception) -+ -+ sort.Strings(features) -+ sort.Strings(required) -+ -+ take := func(sl *[]string) string { -+ s := (*sl)[0] -+ *sl = (*sl)[1:] -+ return s -+ } -+ -+ for len(features) > 0 || len(required) > 0 { -+ switch { -+ case len(features) == 0 || (len(required) > 0 && required[0] < features[0]): -+ feature := take(&required) -+ if exceptionSet[feature] { -+ // An "unfortunate" case: the feature was once -+ // included in the API (e.g. go1.txt), but was -+ // subsequently removed. These are already -+ // acknowledged by being in the file -+ // "api/except.txt". No need to print them out -+ // here. -+ } else if portRemoved(feature) { -+ // okay. -+ } else if featureSet[featureWithoutContext(feature)] { -+ // okay. -+ } else { -+ fmt.Fprintf(w, "-%s\n", feature) -+ ok = false // broke compatibility -+ } -+ case len(required) == 0 || (len(features) > 0 && required[0] > features[0]): -+ newFeature := take(&features) -+ fmt.Fprintf(w, "+%s\n", newFeature) -+ ok = false // feature not in api/next/* -+ default: -+ take(&required) -+ take(&features) -+ } -+ } -+ -+ return ok -+} -+ -+// aliasReplacer applies type aliases to earlier API files, -+// to avoid misleading negative results. -+// This makes all the references to os.FileInfo in go1.txt -+// be read as if they said fs.FileInfo, since os.FileInfo is now an alias. -+// If there are many of these, we could do a more general solution, -+// but for now the replacer is fine. -+var aliasReplacer = strings.NewReplacer( -+ "os.FileInfo", "fs.FileInfo", -+ "os.FileMode", "fs.FileMode", -+ "os.PathError", "fs.PathError", -+) -+ -+func fileFeatures(filename string, needApproval bool) []string { -+ bs, err := os.ReadFile(filename) -+ if err != nil { -+ log.Fatal(err) -+ } -+ s := string(bs) -+ -+ // Diagnose common mistakes people make, -+ // since there is no apifmt to format these files. -+ // The missing final newline is important for the -+ // final release step of cat next/*.txt >go1.X.txt. -+ // If the files don't end in full lines, the concatenation goes awry. -+ if strings.Contains(s, "\r") { -+ log.Printf("%s: contains CRLFs", filename) -+ exitCode = 1 -+ } -+ if filepath.Base(filename) == "go1.4.txt" { -+ // No use for blank lines in api files, except go1.4.txt -+ // used them in a reasonable way and we should let it be. -+ } else if strings.HasPrefix(s, "\n") || strings.Contains(s, "\n\n") { -+ log.Printf("%s: contains a blank line", filename) -+ exitCode = 1 -+ } -+ if s == "" { -+ log.Printf("%s: empty file", filename) -+ exitCode = 1 -+ } else if s[len(s)-1] != '\n' { -+ log.Printf("%s: missing final newline", filename) -+ exitCode = 1 -+ } -+ s = aliasReplacer.Replace(s) -+ lines := strings.Split(s, "\n") -+ var nonblank []string -+ for i, line := range lines { -+ line = strings.TrimSpace(line) -+ if line == "" || strings.HasPrefix(line, "#") { -+ continue -+ } -+ if needApproval { -+ feature, approval, ok := strings.Cut(line, "#") -+ if !ok { -+ log.Printf("%s:%d: missing proposal approval\n", filename, i+1) -+ exitCode = 1 -+ } else { -+ _, err := strconv.Atoi(approval) -+ if err != nil { -+ log.Printf("%s:%d: malformed proposal approval #%s\n", filename, i+1, approval) -+ exitCode = 1 -+ } -+ } -+ line = strings.TrimSpace(feature) -+ } else { -+ if strings.Contains(line, " #") { -+ log.Printf("%s:%d: unexpected approval\n", filename, i+1) -+ exitCode = 1 -+ } -+ } -+ nonblank = append(nonblank, line) -+ } -+ return nonblank -+} -+ -+var fset = token.NewFileSet() -+ -+type Walker struct { -+ context *build.Context -+ root string -+ scope []string -+ current *apiPackage -+ deprecated map[token.Pos]bool -+ features map[string]bool // set -+ imported map[string]*apiPackage // packages already imported -+ stdPackages []string // names, omitting "unsafe", internal, and vendored packages -+ importMap map[string]map[string]string // importer dir -> import path -> canonical path -+ importDir map[string]string // canonical import path -> dir -+ -+} -+ -+func NewWalker(context *build.Context, root string) *Walker { -+ w := &Walker{ -+ context: context, -+ root: root, -+ features: map[string]bool{}, -+ imported: map[string]*apiPackage{"unsafe": &apiPackage{Package: types.Unsafe}}, -+ } -+ w.loadImports() -+ return w -+} -+ -+func (w *Walker) Features() (fs []string) { -+ for f := range w.features { -+ fs = append(fs, f) -+ } -+ sort.Strings(fs) -+ return -+} -+ -+var parsedFileCache = make(map[string]*ast.File) -+ -+func (w *Walker) parseFile(dir, file string) (*ast.File, error) { -+ filename := filepath.Join(dir, file) -+ if f := parsedFileCache[filename]; f != nil { -+ return f, nil -+ } -+ -+ f, err := parser.ParseFile(fset, filename, nil, parser.ParseComments) -+ if err != nil { -+ return nil, err -+ } -+ parsedFileCache[filename] = f -+ -+ return f, nil -+} -+ -+// Disable before debugging non-obvious errors from the type-checker. -+const usePkgCache = true -+ -+var ( -+ pkgCache = map[string]*apiPackage{} // map tagKey to package -+ pkgTags = map[string][]string{} // map import dir to list of relevant tags -+) -+ -+// tagKey returns the tag-based key to use in the pkgCache. -+// It is a comma-separated string; the first part is dir, the rest tags. -+// The satisfied tags are derived from context but only those that -+// matter (the ones listed in the tags argument plus GOOS and GOARCH) are used. -+// The tags list, which came from go/build's Package.AllTags, -+// is known to be sorted. -+func tagKey(dir string, context *build.Context, tags []string) string { -+ ctags := map[string]bool{ -+ context.GOOS: true, -+ context.GOARCH: true, -+ } -+ if context.CgoEnabled { -+ ctags["cgo"] = true -+ } -+ for _, tag := range context.BuildTags { -+ ctags[tag] = true -+ } -+ // TODO: ReleaseTags (need to load default) -+ key := dir -+ -+ // explicit on GOOS and GOARCH as global cache will use "all" cached packages for -+ // an indirect imported package. See https://github.com/golang/go/issues/21181 -+ // for more detail. -+ tags = append(tags, context.GOOS, context.GOARCH) -+ sort.Strings(tags) -+ -+ for _, tag := range tags { -+ if ctags[tag] { -+ key += "," + tag -+ ctags[tag] = false -+ } -+ } -+ return key -+} -+ -+type listImports struct { -+ stdPackages []string // names, omitting "unsafe", internal, and vendored packages -+ importDir map[string]string // canonical import path → directory -+ importMap map[string]map[string]string // import path → canonical import path -+} -+ -+var listCache sync.Map // map[string]listImports, keyed by contextName -+ -+// listSem is a semaphore restricting concurrent invocations of 'go list'. 'go -+// list' has its own internal concurrency, so we use a hard-coded constant (to -+// allow the I/O-intensive phases of 'go list' to overlap) instead of scaling -+// all the way up to GOMAXPROCS. -+var listSem = make(chan semToken, 2) -+ -+type semToken struct{} -+ -+// loadImports populates w with information about the packages in the standard -+// library and the packages they themselves import in w's build context. -+// -+// The source import path and expanded import path are identical except for vendored packages. -+// For example, on return: -+// -+// w.importMap["math"] = "math" -+// w.importDir["math"] = "/src/math" -+// -+// w.importMap["golang.org/x/net/route"] = "vendor/golang.org/x/net/route" -+// w.importDir["vendor/golang.org/x/net/route"] = "/src/vendor/golang.org/x/net/route" -+// -+// Since the set of packages that exist depends on context, the result of -+// loadImports also depends on context. However, to improve test running time -+// the configuration for each environment is cached across runs. -+func (w *Walker) loadImports() { -+ if w.context == nil { -+ return // test-only Walker; does not use the import map -+ } -+ -+ name := contextName(w.context) -+ -+ imports, ok := listCache.Load(name) -+ if !ok { -+ listSem <- semToken{} -+ defer func() { <-listSem }() -+ -+ cmd := exec.Command(goCmd(), "list", "-e", "-deps", "-json", "std") -+ cmd.Env = listEnv(w.context) -+ if w.context.Dir != "" { -+ cmd.Dir = w.context.Dir -+ } -+ out, err := cmd.CombinedOutput() -+ if err != nil { -+ log.Fatalf("loading imports: %v\n%s", err, out) -+ } -+ -+ var stdPackages []string -+ importMap := make(map[string]map[string]string) -+ importDir := make(map[string]string) -+ dec := json.NewDecoder(bytes.NewReader(out)) -+ for { -+ var pkg struct { -+ ImportPath, Dir string -+ ImportMap map[string]string -+ Standard bool -+ } -+ err := dec.Decode(&pkg) -+ if err == io.EOF { -+ break -+ } -+ if err != nil { -+ log.Fatalf("go list: invalid output: %v", err) -+ } -+ -+ // - Package "unsafe" contains special signatures requiring -+ // extra care when printing them - ignore since it is not -+ // going to change w/o a language change. -+ // - Internal and vendored packages do not contribute to our -+ // API surface. (If we are running within the "std" module, -+ // vendored dependencies appear as themselves instead of -+ // their "vendor/" standard-library copies.) -+ // - 'go list std' does not include commands, which cannot be -+ // imported anyway. -+ if ip := pkg.ImportPath; pkg.Standard && ip != "unsafe" && !strings.HasPrefix(ip, "vendor/") && !internalPkg.MatchString(ip) { -+ stdPackages = append(stdPackages, ip) -+ } -+ importDir[pkg.ImportPath] = pkg.Dir -+ if len(pkg.ImportMap) > 0 { -+ importMap[pkg.Dir] = make(map[string]string, len(pkg.ImportMap)) -+ } -+ for k, v := range pkg.ImportMap { -+ importMap[pkg.Dir][k] = v -+ } -+ } -+ -+ sort.Strings(stdPackages) -+ imports = listImports{ -+ stdPackages: stdPackages, -+ importMap: importMap, -+ importDir: importDir, -+ } -+ imports, _ = listCache.LoadOrStore(name, imports) -+ } -+ -+ li := imports.(listImports) -+ w.stdPackages = li.stdPackages -+ w.importDir = li.importDir -+ w.importMap = li.importMap -+} -+ -+// listEnv returns the process environment to use when invoking 'go list' for -+// the given context. -+func listEnv(c *build.Context) []string { -+ if c == nil { -+ return os.Environ() -+ } -+ -+ environ := append(os.Environ(), -+ "GOOS="+c.GOOS, -+ "GOARCH="+c.GOARCH) -+ if c.CgoEnabled { -+ environ = append(environ, "CGO_ENABLED=1") -+ } else { -+ environ = append(environ, "CGO_ENABLED=0") -+ } -+ return environ -+} -+ -+type apiPackage struct { -+ *types.Package -+ Files []*ast.File -+} -+ -+// Importing is a sentinel taking the place in Walker.imported -+// for a package that is in the process of being imported. -+var importing apiPackage -+ -+// Import implements types.Importer. -+func (w *Walker) Import(name string) (*types.Package, error) { -+ return w.ImportFrom(name, "", 0) -+} -+ -+// ImportFrom implements types.ImporterFrom. -+func (w *Walker) ImportFrom(fromPath, fromDir string, mode types.ImportMode) (*types.Package, error) { -+ pkg, err := w.importFrom(fromPath, fromDir, mode) -+ if err != nil { -+ return nil, err -+ } -+ return pkg.Package, nil -+} -+ -+func (w *Walker) import_(name string) (*apiPackage, error) { -+ return w.importFrom(name, "", 0) -+} -+ -+func (w *Walker) importFrom(fromPath, fromDir string, mode types.ImportMode) (*apiPackage, error) { -+ name := fromPath -+ if canonical, ok := w.importMap[fromDir][fromPath]; ok { -+ name = canonical -+ } -+ -+ pkg := w.imported[name] -+ if pkg != nil { -+ if pkg == &importing { -+ log.Fatalf("cycle importing package %q", name) -+ } -+ return pkg, nil -+ } -+ w.imported[name] = &importing -+ -+ // Determine package files. -+ dir := w.importDir[name] -+ if dir == "" { -+ dir = filepath.Join(w.root, filepath.FromSlash(name)) -+ } -+ if fi, err := os.Stat(dir); err != nil || !fi.IsDir() { -+ log.Panicf("no source in tree for import %q (from import %s in %s): %v", name, fromPath, fromDir, err) -+ } -+ -+ context := w.context -+ if context == nil { -+ context = &build.Default -+ } -+ -+ // Look in cache. -+ // If we've already done an import with the same set -+ // of relevant tags, reuse the result. -+ var key string -+ if usePkgCache { -+ if tags, ok := pkgTags[dir]; ok { -+ key = tagKey(dir, context, tags) -+ if pkg := pkgCache[key]; pkg != nil { -+ w.imported[name] = pkg -+ return pkg, nil -+ } -+ } -+ } -+ -+ info, err := context.ImportDir(dir, 0) -+ if err != nil { -+ if _, nogo := err.(*build.NoGoError); nogo { -+ return nil, err -+ } -+ log.Fatalf("pkg %q, dir %q: ScanDir: %v", name, dir, err) -+ } -+ -+ // Save tags list first time we see a directory. -+ if usePkgCache { -+ if _, ok := pkgTags[dir]; !ok { -+ pkgTags[dir] = info.AllTags -+ key = tagKey(dir, context, info.AllTags) -+ } -+ } -+ -+ filenames := append(append([]string{}, info.GoFiles...), info.CgoFiles...) -+ -+ // Parse package files. -+ var files []*ast.File -+ for _, file := range filenames { -+ f, err := w.parseFile(dir, file) -+ if err != nil { -+ log.Fatalf("error parsing package %s: %s", name, err) -+ } -+ files = append(files, f) -+ } -+ -+ // Type-check package files. -+ var sizes types.Sizes -+ if w.context != nil { -+ sizes = types.SizesFor(w.context.Compiler, w.context.GOARCH) -+ } -+ conf := types.Config{ -+ IgnoreFuncBodies: true, -+ FakeImportC: true, -+ Importer: w, -+ Sizes: sizes, -+ } -+ tpkg, err := conf.Check(name, fset, files, nil) -+ if err != nil { -+ ctxt := "" -+ if w.context != nil { -+ ctxt = fmt.Sprintf("%s-%s", w.context.GOOS, w.context.GOARCH) -+ } -+ log.Fatalf("error typechecking package %s: %s (%s)", name, err, ctxt) -+ } -+ pkg = &apiPackage{tpkg, files} -+ -+ if usePkgCache { -+ pkgCache[key] = pkg -+ } -+ -+ w.imported[name] = pkg -+ return pkg, nil -+} -+ -+// pushScope enters a new scope (walking a package, type, node, etc) -+// and returns a function that will leave the scope (with sanity checking -+// for mismatched pushes & pops) -+func (w *Walker) pushScope(name string) (popFunc func()) { -+ w.scope = append(w.scope, name) -+ return func() { -+ if len(w.scope) == 0 { -+ log.Fatalf("attempt to leave scope %q with empty scope list", name) -+ } -+ if w.scope[len(w.scope)-1] != name { -+ log.Fatalf("attempt to leave scope %q, but scope is currently %#v", name, w.scope) -+ } -+ w.scope = w.scope[:len(w.scope)-1] -+ } -+} -+ -+func sortedMethodNames(typ *types.Interface) []string { -+ n := typ.NumMethods() -+ list := make([]string, n) -+ for i := range list { -+ list[i] = typ.Method(i).Name() -+ } -+ sort.Strings(list) -+ return list -+} -+ -+// sortedEmbeddeds returns constraint types embedded in an -+// interface. It does not include embedded interface types or methods. -+func (w *Walker) sortedEmbeddeds(typ *types.Interface) []string { -+ n := typ.NumEmbeddeds() -+ list := make([]string, 0, n) -+ for i := 0; i < n; i++ { -+ emb := typ.EmbeddedType(i) -+ switch emb := emb.(type) { -+ case *types.Interface: -+ list = append(list, w.sortedEmbeddeds(emb)...) -+ case *types.Union: -+ var buf bytes.Buffer -+ nu := emb.Len() -+ for i := 0; i < nu; i++ { -+ if i > 0 { -+ buf.WriteString(" | ") -+ } -+ term := emb.Term(i) -+ if term.Tilde() { -+ buf.WriteByte('~') -+ } -+ w.writeType(&buf, term.Type()) -+ } -+ list = append(list, buf.String()) -+ } -+ } -+ sort.Strings(list) -+ return list -+} -+ -+func (w *Walker) writeType(buf *bytes.Buffer, typ types.Type) { -+ switch typ := typ.(type) { -+ case *types.Basic: -+ s := typ.Name() -+ switch typ.Kind() { -+ case types.UnsafePointer: -+ s = "unsafe.Pointer" -+ case types.UntypedBool: -+ s = "ideal-bool" -+ case types.UntypedInt: -+ s = "ideal-int" -+ case types.UntypedRune: -+ // "ideal-char" for compatibility with old tool -+ // TODO(gri) change to "ideal-rune" -+ s = "ideal-char" -+ case types.UntypedFloat: -+ s = "ideal-float" -+ case types.UntypedComplex: -+ s = "ideal-complex" -+ case types.UntypedString: -+ s = "ideal-string" -+ case types.UntypedNil: -+ panic("should never see untyped nil type") -+ default: -+ switch s { -+ case "byte": -+ s = "uint8" -+ case "rune": -+ s = "int32" -+ } -+ } -+ buf.WriteString(s) -+ -+ case *types.Array: -+ fmt.Fprintf(buf, "[%d]", typ.Len()) -+ w.writeType(buf, typ.Elem()) -+ -+ case *types.Slice: -+ buf.WriteString("[]") -+ w.writeType(buf, typ.Elem()) -+ -+ case *types.Struct: -+ buf.WriteString("struct") -+ -+ case *types.Pointer: -+ buf.WriteByte('*') -+ w.writeType(buf, typ.Elem()) -+ -+ case *types.Tuple: -+ panic("should never see a tuple type") -+ -+ case *types.Signature: -+ buf.WriteString("func") -+ w.writeSignature(buf, typ) -+ -+ case *types.Interface: -+ buf.WriteString("interface{") -+ if typ.NumMethods() > 0 || typ.NumEmbeddeds() > 0 { -+ buf.WriteByte(' ') -+ } -+ if typ.NumMethods() > 0 { -+ buf.WriteString(strings.Join(sortedMethodNames(typ), ", ")) -+ } -+ if typ.NumEmbeddeds() > 0 { -+ buf.WriteString(strings.Join(w.sortedEmbeddeds(typ), ", ")) -+ } -+ if typ.NumMethods() > 0 || typ.NumEmbeddeds() > 0 { -+ buf.WriteByte(' ') -+ } -+ buf.WriteString("}") -+ -+ case *types.Map: -+ buf.WriteString("map[") -+ w.writeType(buf, typ.Key()) -+ buf.WriteByte(']') -+ w.writeType(buf, typ.Elem()) -+ -+ case *types.Chan: -+ var s string -+ switch typ.Dir() { -+ case types.SendOnly: -+ s = "chan<- " -+ case types.RecvOnly: -+ s = "<-chan " -+ case types.SendRecv: -+ s = "chan " -+ default: -+ panic("unreachable") -+ } -+ buf.WriteString(s) -+ w.writeType(buf, typ.Elem()) -+ -+ case *types.Named: -+ obj := typ.Obj() -+ pkg := obj.Pkg() -+ if pkg != nil && pkg != w.current.Package { -+ buf.WriteString(pkg.Name()) -+ buf.WriteByte('.') -+ } -+ buf.WriteString(typ.Obj().Name()) -+ -+ case *types.TypeParam: -+ // Type parameter names may change, so use a placeholder instead. -+ fmt.Fprintf(buf, "$%d", typ.Index()) -+ -+ default: -+ panic(fmt.Sprintf("unknown type %T", typ)) -+ } -+} -+ -+func (w *Walker) writeSignature(buf *bytes.Buffer, sig *types.Signature) { -+ if tparams := sig.TypeParams(); tparams != nil { -+ w.writeTypeParams(buf, tparams, true) -+ } -+ w.writeParams(buf, sig.Params(), sig.Variadic()) -+ switch res := sig.Results(); res.Len() { -+ case 0: -+ // nothing to do -+ case 1: -+ buf.WriteByte(' ') -+ w.writeType(buf, res.At(0).Type()) -+ default: -+ buf.WriteByte(' ') -+ w.writeParams(buf, res, false) -+ } -+} -+ -+func (w *Walker) writeTypeParams(buf *bytes.Buffer, tparams *types.TypeParamList, withConstraints bool) { -+ buf.WriteByte('[') -+ c := tparams.Len() -+ for i := 0; i < c; i++ { -+ if i > 0 { -+ buf.WriteString(", ") -+ } -+ tp := tparams.At(i) -+ w.writeType(buf, tp) -+ if withConstraints { -+ buf.WriteByte(' ') -+ w.writeType(buf, tp.Constraint()) -+ } -+ } -+ buf.WriteByte(']') -+} -+ -+func (w *Walker) writeParams(buf *bytes.Buffer, t *types.Tuple, variadic bool) { -+ buf.WriteByte('(') -+ for i, n := 0, t.Len(); i < n; i++ { -+ if i > 0 { -+ buf.WriteString(", ") -+ } -+ typ := t.At(i).Type() -+ if variadic && i+1 == n { -+ buf.WriteString("...") -+ typ = typ.(*types.Slice).Elem() -+ } -+ w.writeType(buf, typ) -+ } -+ buf.WriteByte(')') -+} -+ -+func (w *Walker) typeString(typ types.Type) string { -+ var buf bytes.Buffer -+ w.writeType(&buf, typ) -+ return buf.String() -+} -+ -+func (w *Walker) signatureString(sig *types.Signature) string { -+ var buf bytes.Buffer -+ w.writeSignature(&buf, sig) -+ return buf.String() -+} -+ -+func (w *Walker) emitObj(obj types.Object) { -+ switch obj := obj.(type) { -+ case *types.Const: -+ if w.isDeprecated(obj) { -+ w.emitf("const %s //deprecated", obj.Name()) -+ } -+ w.emitf("const %s %s", obj.Name(), w.typeString(obj.Type())) -+ x := obj.Val() -+ short := x.String() -+ exact := x.ExactString() -+ if short == exact { -+ w.emitf("const %s = %s", obj.Name(), short) -+ } else { -+ w.emitf("const %s = %s // %s", obj.Name(), short, exact) -+ } -+ case *types.Var: -+ if w.isDeprecated(obj) { -+ w.emitf("var %s //deprecated", obj.Name()) -+ } -+ w.emitf("var %s %s", obj.Name(), w.typeString(obj.Type())) -+ case *types.TypeName: -+ w.emitType(obj) -+ case *types.Func: -+ w.emitFunc(obj) -+ default: -+ panic("unknown object: " + obj.String()) -+ } -+} -+ -+func (w *Walker) emitType(obj *types.TypeName) { -+ name := obj.Name() -+ if w.isDeprecated(obj) { -+ w.emitf("type %s //deprecated", name) -+ } -+ if tparams := obj.Type().(*types.Named).TypeParams(); tparams != nil { -+ var buf bytes.Buffer -+ buf.WriteString(name) -+ w.writeTypeParams(&buf, tparams, true) -+ name = buf.String() -+ } -+ typ := obj.Type() -+ if obj.IsAlias() { -+ w.emitf("type %s = %s", name, w.typeString(typ)) -+ return -+ } -+ switch typ := typ.Underlying().(type) { -+ case *types.Struct: -+ w.emitStructType(name, typ) -+ case *types.Interface: -+ w.emitIfaceType(name, typ) -+ return // methods are handled by emitIfaceType -+ default: -+ w.emitf("type %s %s", name, w.typeString(typ.Underlying())) -+ } -+ -+ // emit methods with value receiver -+ var methodNames map[string]bool -+ vset := types.NewMethodSet(typ) -+ for i, n := 0, vset.Len(); i < n; i++ { -+ m := vset.At(i) -+ if m.Obj().Exported() { -+ w.emitMethod(m) -+ if methodNames == nil { -+ methodNames = make(map[string]bool) -+ } -+ methodNames[m.Obj().Name()] = true -+ } -+ } -+ -+ // emit methods with pointer receiver; exclude -+ // methods that we have emitted already -+ // (the method set of *T includes the methods of T) -+ pset := types.NewMethodSet(types.NewPointer(typ)) -+ for i, n := 0, pset.Len(); i < n; i++ { -+ m := pset.At(i) -+ if m.Obj().Exported() && !methodNames[m.Obj().Name()] { -+ w.emitMethod(m) -+ } -+ } -+} -+ -+func (w *Walker) emitStructType(name string, typ *types.Struct) { -+ typeStruct := fmt.Sprintf("type %s struct", name) -+ w.emitf(typeStruct) -+ defer w.pushScope(typeStruct)() -+ -+ for i := 0; i < typ.NumFields(); i++ { -+ f := typ.Field(i) -+ if !f.Exported() { -+ continue -+ } -+ typ := f.Type() -+ if f.Anonymous() { -+ if w.isDeprecated(f) { -+ w.emitf("embedded %s //deprecated", w.typeString(typ)) -+ } -+ w.emitf("embedded %s", w.typeString(typ)) -+ continue -+ } -+ if w.isDeprecated(f) { -+ w.emitf("%s //deprecated", f.Name()) -+ } -+ w.emitf("%s %s", f.Name(), w.typeString(typ)) -+ } -+} -+ -+func (w *Walker) emitIfaceType(name string, typ *types.Interface) { -+ pop := w.pushScope("type " + name + " interface") -+ -+ var methodNames []string -+ complete := true -+ mset := types.NewMethodSet(typ) -+ for i, n := 0, mset.Len(); i < n; i++ { -+ m := mset.At(i).Obj().(*types.Func) -+ if !m.Exported() { -+ complete = false -+ continue -+ } -+ methodNames = append(methodNames, m.Name()) -+ if w.isDeprecated(m) { -+ w.emitf("%s //deprecated", m.Name()) -+ } -+ w.emitf("%s%s", m.Name(), w.signatureString(m.Type().(*types.Signature))) -+ } -+ -+ if !complete { -+ // The method set has unexported methods, so all the -+ // implementations are provided by the same package, -+ // so the method set can be extended. Instead of recording -+ // the full set of names (below), record only that there were -+ // unexported methods. (If the interface shrinks, we will notice -+ // because a method signature emitted during the last loop -+ // will disappear.) -+ w.emitf("unexported methods") -+ } -+ -+ pop() -+ -+ if !complete { -+ return -+ } -+ -+ if len(methodNames) == 0 { -+ w.emitf("type %s interface {}", name) -+ return -+ } -+ -+ sort.Strings(methodNames) -+ w.emitf("type %s interface { %s }", name, strings.Join(methodNames, ", ")) -+} -+ -+func (w *Walker) emitFunc(f *types.Func) { -+ sig := f.Type().(*types.Signature) -+ if sig.Recv() != nil { -+ panic("method considered a regular function: " + f.String()) -+ } -+ if w.isDeprecated(f) { -+ w.emitf("func %s //deprecated", f.Name()) -+ } -+ w.emitf("func %s%s", f.Name(), w.signatureString(sig)) -+} -+ -+func (w *Walker) emitMethod(m *types.Selection) { -+ sig := m.Type().(*types.Signature) -+ recv := sig.Recv().Type() -+ // report exported methods with unexported receiver base type -+ if true { -+ base := recv -+ if p, _ := recv.(*types.Pointer); p != nil { -+ base = p.Elem() -+ } -+ if obj := base.(*types.Named).Obj(); !obj.Exported() { -+ log.Fatalf("exported method with unexported receiver base type: %s", m) -+ } -+ } -+ tps := "" -+ if rtp := sig.RecvTypeParams(); rtp != nil { -+ var buf bytes.Buffer -+ w.writeTypeParams(&buf, rtp, false) -+ tps = buf.String() -+ } -+ if w.isDeprecated(m.Obj()) { -+ w.emitf("method (%s%s) %s //deprecated", w.typeString(recv), tps, m.Obj().Name()) -+ } -+ w.emitf("method (%s%s) %s%s", w.typeString(recv), tps, m.Obj().Name(), w.signatureString(sig)) -+} -+ -+func (w *Walker) emitf(format string, args ...any) { -+ f := strings.Join(w.scope, ", ") + ", " + fmt.Sprintf(format, args...) -+ if strings.Contains(f, "\n") { -+ panic("feature contains newlines: " + f) -+ } -+ -+ if _, dup := w.features[f]; dup { -+ panic("duplicate feature inserted: " + f) -+ } -+ w.features[f] = true -+ -+ if verbose { -+ log.Printf("feature: %s", f) -+ } -+} -+ -+func needApproval(filename string) bool { -+ name := filepath.Base(filename) -+ if name == "go1.txt" { -+ return false -+ } -+ minor := strings.TrimSuffix(strings.TrimPrefix(name, "go1."), ".txt") -+ n, err := strconv.Atoi(minor) -+ if err != nil { -+ log.Fatalf("unexpected api file: %v", name) -+ } -+ return n >= 19 // started tracking approvals in Go 1.19 -+} -+ -+func (w *Walker) collectDeprecated() { -+ isDeprecated := func(doc *ast.CommentGroup) bool { -+ if doc != nil { -+ for _, c := range doc.List { -+ if strings.HasPrefix(c.Text, "// Deprecated:") { -+ return true -+ } -+ } -+ } -+ return false -+ } -+ -+ w.deprecated = make(map[token.Pos]bool) -+ mark := func(id *ast.Ident) { -+ if id != nil { -+ w.deprecated[id.Pos()] = true -+ } -+ } -+ for _, file := range w.current.Files { -+ ast.Inspect(file, func(n ast.Node) bool { -+ switch n := n.(type) { -+ case *ast.File: -+ if isDeprecated(n.Doc) { -+ mark(n.Name) -+ } -+ return true -+ case *ast.GenDecl: -+ if isDeprecated(n.Doc) { -+ for _, spec := range n.Specs { -+ switch spec := spec.(type) { -+ case *ast.ValueSpec: -+ for _, id := range spec.Names { -+ mark(id) -+ } -+ case *ast.TypeSpec: -+ mark(spec.Name) -+ } -+ } -+ } -+ return true // look at specs -+ case *ast.FuncDecl: -+ if isDeprecated(n.Doc) { -+ mark(n.Name) -+ } -+ return false -+ case *ast.TypeSpec: -+ if isDeprecated(n.Doc) { -+ mark(n.Name) -+ } -+ return true // recurse into struct or interface type -+ case *ast.StructType: -+ return true // recurse into fields -+ case *ast.InterfaceType: -+ return true // recurse into methods -+ case *ast.FieldList: -+ return true // recurse into fields -+ case *ast.ValueSpec: -+ if isDeprecated(n.Doc) { -+ for _, id := range n.Names { -+ mark(id) -+ } -+ } -+ return false -+ case *ast.Field: -+ if isDeprecated(n.Doc) { -+ for _, id := range n.Names { -+ mark(id) -+ } -+ if len(n.Names) == 0 { -+ // embedded field T or *T? -+ typ := n.Type -+ if ptr, ok := typ.(*ast.StarExpr); ok { -+ typ = ptr.X -+ } -+ if id, ok := typ.(*ast.Ident); ok { -+ mark(id) -+ } -+ } -+ } -+ return false -+ default: -+ return false -+ } -+ }) -+ } -+} -+ -+func (w *Walker) isDeprecated(obj types.Object) bool { -+ return w.deprecated[obj.Pos()] -+} -diff --git a/src/cmd/api/api_test.go-e b/src/cmd/api/api_test.go-e -new file mode 100644 -index 0000000000..a5ac49ce2d ---- /dev/null -+++ b/src/cmd/api/api_test.go-e -@@ -0,0 +1,294 @@ -+// Copyright 2011 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. -+ -+package api -+ -+import ( -+ "flag" -+ "fmt" -+ "go/build" -+ "internal/testenv" -+ "os" -+ "path/filepath" -+ "sort" -+ "strings" -+ "sync" -+ "testing" -+) -+ -+var flagCheck = flag.Bool("check", false, "run API checks") -+ -+func TestMain(m *testing.M) { -+ flag.Parse() -+ for _, c := range contexts { -+ c.Compiler = build.Default.Compiler -+ } -+ build.Default.GOROOT = testenv.GOROOT(nil) -+ -+ os.Exit(m.Run()) -+} -+ -+var ( -+ updateGolden = flag.Bool("updategolden", false, "update golden files") -+) -+ -+func TestGolden(t *testing.T) { -+ if *flagCheck { -+ // slow, not worth repeating in -check -+ t.Skip("skipping with -check set") -+ } -+ -+ testenv.MustHaveGoBuild(t) -+ -+ td, err := os.Open("testdata/src/pkg") -+ if err != nil { -+ t.Fatal(err) -+ } -+ fis, err := td.Readdir(0) -+ if err != nil { -+ t.Fatal(err) -+ } -+ for _, fi := range fis { -+ if !fi.IsDir() { -+ continue -+ } -+ -+ // TODO(gri) remove extra pkg directory eventually -+ goldenFile := filepath.Join("testdata", "src", "pkg", fi.Name(), "golden.txt") -+ w := NewWalker(nil, "testdata/src/pkg") -+ pkg, _ := w.import_(fi.Name()) -+ w.export(pkg) -+ -+ if *updateGolden { -+ os.Remove(goldenFile) -+ f, err := os.Create(goldenFile) -+ if err != nil { -+ t.Fatal(err) -+ } -+ for _, feat := range w.Features() { -+ fmt.Fprintf(f, "%s\n", feat) -+ } -+ f.Close() -+ } -+ -+ bs, err := os.ReadFile(goldenFile) -+ if err != nil { -+ t.Fatalf("opening golden.txt for package %q: %v", fi.Name(), err) -+ } -+ wanted := strings.Split(string(bs), "\n") -+ sort.Strings(wanted) -+ for _, feature := range wanted { -+ if feature == "" { -+ continue -+ } -+ _, ok := w.features[feature] -+ if !ok { -+ t.Errorf("package %s: missing feature %q", fi.Name(), feature) -+ } -+ delete(w.features, feature) -+ } -+ -+ for _, feature := range w.Features() { -+ t.Errorf("package %s: extra feature not in golden file: %q", fi.Name(), feature) -+ } -+ } -+} -+ -+func TestCompareAPI(t *testing.T) { -+ tests := []struct { -+ name string -+ features, required, exception []string -+ ok bool // want -+ out string // want -+ }{ -+ { -+ name: "equal", -+ features: []string{"A", "B", "C"}, -+ required: []string{"A", "B", "C"}, -+ ok: true, -+ out: "", -+ }, -+ { -+ name: "feature added", -+ features: []string{"A", "B", "C", "D", "E", "F"}, -+ required: []string{"B", "D"}, -+ ok: false, -+ out: "+A\n+C\n+E\n+F\n", -+ }, -+ { -+ name: "feature removed", -+ features: []string{"C", "A"}, -+ required: []string{"A", "B", "C"}, -+ ok: false, -+ out: "-B\n", -+ }, -+ { -+ name: "exception removal", -+ features: []string{"A", "C"}, -+ required: []string{"A", "B", "C"}, -+ exception: []string{"B"}, -+ ok: true, -+ out: "", -+ }, -+ -+ // Test that a feature required on a subset of ports is implicitly satisfied -+ // by the same feature being implemented on all ports. That is, it shouldn't -+ // say "pkg syscall (darwin-amd64), type RawSockaddrInet6 struct" is missing. -+ // See https://go.dev/issue/4303. -+ { -+ name: "contexts reconverging after api/next/* update", -+ features: []string{ -+ "A", -+ "pkg syscall, type RawSockaddrInet6 struct", -+ }, -+ required: []string{ -+ "A", -+ "pkg syscall (darwin-amd64), type RawSockaddrInet6 struct", // api/go1.n.txt -+ "pkg syscall, type RawSockaddrInet6 struct", // api/next/n.txt -+ }, -+ ok: true, -+ out: "", -+ }, -+ { -+ name: "contexts reconverging before api/next/* update", -+ features: []string{ -+ "A", -+ "pkg syscall, type RawSockaddrInet6 struct", -+ }, -+ required: []string{ -+ "A", -+ "pkg syscall (darwin-amd64), type RawSockaddrInet6 struct", -+ }, -+ ok: false, -+ out: "+pkg syscall, type RawSockaddrInet6 struct\n", -+ }, -+ } -+ for _, tt := range tests { -+ buf := new(strings.Builder) -+ gotOK := compareAPI(buf, tt.features, tt.required, tt.exception) -+ if gotOK != tt.ok { -+ t.Errorf("%s: ok = %v; want %v", tt.name, gotOK, tt.ok) -+ } -+ if got := buf.String(); got != tt.out { -+ t.Errorf("%s: output differs\nGOT:\n%s\nWANT:\n%s", tt.name, got, tt.out) -+ } -+ } -+} -+ -+func TestSkipInternal(t *testing.T) { -+ tests := []struct { -+ pkg string -+ want bool -+ }{ -+ {"net/http", true}, -+ {"net/http/internal-foo", true}, -+ {"net/http/internal", false}, -+ {"net/http/internal/bar", false}, -+ {"internal/foo", false}, -+ {"internal", false}, -+ } -+ for _, tt := range tests { -+ got := !internalPkg.MatchString(tt.pkg) -+ if got != tt.want { -+ t.Errorf("%s is internal = %v; want %v", tt.pkg, got, tt.want) -+ } -+ } -+} -+ -+func BenchmarkAll(b *testing.B) { -+ for i := 0; i < b.N; i++ { -+ for _, context := range contexts { -+ w := NewWalker(context, filepath.Join(testenv.GOROOT(b), "src")) -+ for _, name := range w.stdPackages { -+ pkg, _ := w.import_(name) -+ w.export(pkg) -+ } -+ w.Features() -+ } -+ } -+} -+ -+var warmupCache = sync.OnceFunc(func() { -+ // Warm up the import cache in parallel. -+ var wg sync.WaitGroup -+ for _, context := range contexts { -+ context := context -+ wg.Add(1) -+ go func() { -+ defer wg.Done() -+ _ = NewWalker(context, filepath.Join(testenv.GOROOT(nil), "src")) -+ }() -+ } -+ wg.Wait() -+}) -+ -+func TestIssue21181(t *testing.T) { -+ if testing.Short() { -+ t.Skip("skipping with -short") -+ } -+ if *flagCheck { -+ // slow, not worth repeating in -check -+ t.Skip("skipping with -check set") -+ } -+ testenv.MustHaveGoBuild(t) -+ -+ warmupCache() -+ -+ for _, context := range contexts { -+ w := NewWalker(context, "testdata/src/issue21181") -+ pkg, err := w.import_("p") -+ if err != nil { -+ t.Fatalf("%s: (%s-%s) %s %v", err, context.GOOS, context.GOARCH, -+ pkg.Name(), w.imported) -+ } -+ w.export(pkg) -+ } -+} -+ -+func TestIssue29837(t *testing.T) { -+ if testing.Short() { -+ t.Skip("skipping with -short") -+ } -+ if *flagCheck { -+ // slow, not worth repeating in -check -+ t.Skip("skipping with -check set") -+ } -+ testenv.MustHaveGoBuild(t) -+ -+ warmupCache() -+ -+ for _, context := range contexts { -+ w := NewWalker(context, "testdata/src/issue29837") -+ _, err := w.ImportFrom("p", "", 0) -+ if _, nogo := err.(*build.NoGoError); !nogo { -+ t.Errorf("expected *build.NoGoError, got %T", err) -+ } -+ } -+} -+ -+func TestIssue41358(t *testing.T) { -+ if *flagCheck { -+ // slow, not worth repeating in -check -+ t.Skip("skipping with -check set") -+ } -+ testenv.MustHaveGoBuild(t) -+ context := new(build.Context) -+ *context = build.Default -+ context.Dir = filepath.Join(testenv.GOROOT(t), "src") -+ -+ w := NewWalker(context, context.Dir) -+ for _, pkg := range w.stdPackages { -+ if strings.HasPrefix(pkg, "vendor/") || strings.HasPrefix(pkg, "golang.org/x/") { -+ t.Fatalf("stdPackages contains unexpected package %s", pkg) -+ } -+ } -+} -+ -+func TestCheck(t *testing.T) { -+ if !*flagCheck { -+ t.Skip("-check not specified") -+ } -+ testenv.MustHaveGoBuild(t) -+ Check(t) -+} ->>>>>>> 70a351c141 (wip) -======= ->>>>>>> 80d9391199 (wip) -diff --git a/src/cmd/api/boring_test.go b/src/cmd/api/boring_test.go -<<<<<<< HEAD -index a9ec6e6bfe..7111867b66 100644 ->>>>>>> 0023bf4c7a (rebase) -======= -index f0e3575637..a4139169b8 100644 ->>>>>>> 0b8240ca10 (support opensslv2, update strict fips checks) --- a/src/cmd/api/boring_test.go +++ b/src/cmd/api/boring_test.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -<<<<<<< HEAD - --//go:build boringcrypto -+//go:build !no_openssl - - package main - -@@ -12,6 +12,6 @@ import ( - ) - -======= -//go:build boringcrypto +//go:build !no_openssl @@ -1577,7 +14,6 @@ index f0e3575637..a4139169b8 100644 @@ -12,6 +12,6 @@ import ( ) ->>>>>>> 0023bf4c7a (rebase) func init() { - fmt.Printf("SKIP with boringcrypto enabled\n") + fmt.Printf("SKIP with !no_openssl enabled\n") @@ -1595,11 +31,7 @@ index 183c1697c8..abe85b5ad3 100644 + boring "crypto/internal/backend" "strconv" ) -<<<<<<< HEAD - -======= ->>>>>>> 0023bf4c7a (rebase) @@ -38,7 +38,7 @@ func NewCipher(key []byte) (cipher.Block, error) { case 16, 24, 32: break @@ -1629,17 +61,10 @@ index 097c37e343..47618fe3c6 100644 @@ -13,9 +13,9 @@ // is satisfied, so that applications can tag files that use this package. package boring -<<<<<<< HEAD - --import "crypto/internal/boring" -+import boring "crypto/internal/backend" - -======= -import "crypto/internal/boring" +import boring "crypto/internal/backend" ->>>>>>> 0023bf4c7a (rebase) // Enabled reports whether BoringCrypto handles supported crypto operations. func Enabled() bool { - return boring.Enabled @@ -1698,11 +123,7 @@ index b86f521787..5b48335c69 100644 --- a/src/crypto/ecdh/ecdh.go +++ b/src/crypto/ecdh/ecdh.go @@ -8,7 +8,7 @@ package ecdh -<<<<<<< HEAD - -======= ->>>>>>> 0023bf4c7a (rebase) import ( "crypto" - "crypto/internal/boring" @@ -1769,11 +190,7 @@ index 01354fa2cf..a7f1d9eced 100644 +++ b/src/crypto/ecdh/nist.go @@ -5,7 +5,7 @@ package ecdh -<<<<<<< HEAD - -======= ->>>>>>> 0023bf4c7a (rebase) import ( - "crypto/internal/boring" + boring "crypto/internal/backend" @@ -1782,11 +199,7 @@ index 01354fa2cf..a7f1d9eced 100644 "encoding/binary" @@ -36,7 +36,7 @@ func (c *nistCurve[Point]) String() string { var errInvalidPrivateKey = errors.New("crypto/ecdh: invalid private key") -<<<<<<< HEAD - -======= ->>>>>>> 0023bf4c7a (rebase) func (c *nistCurve[Point]) GenerateKey(rand io.Reader) (*PrivateKey, error) { - if boring.Enabled && rand == boring.RandReader { + if boring.Enabled() && rand == boring.RandReader { @@ -1814,449 +227,12 @@ index 01354fa2cf..a7f1d9eced 100644 @@ -196,7 +196,7 @@ func (c *nistCurve[Point]) ecdh(local *PrivateKey, remote *PublicKey) ([]byte, e // only be the result of a scalar multiplication if one of the inputs is the // zero scalar or the point at infinity. -<<<<<<< HEAD - -======= ->>>>>>> 0023bf4c7a (rebase) - if boring.Enabled { + if boring.Enabled() { return boring.ECDH(local.boring, remote.boring) } -<<<<<<< HEAD - -======= -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 0023bf4c7a (rebase) -======= -diff --git a/src/crypto/ecdh/nist.go-e b/src/crypto/ecdh/nist.go-e -new file mode 100644 -index 0000000000..a7f1d9eced ---- /dev/null -+++ b/src/crypto/ecdh/nist.go-e -@@ -0,0 +1,275 @@ -+// Copyright 2022 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. -+ -+package ecdh -+ -+import ( -+ boring "crypto/internal/backend" -+ "crypto/internal/nistec" -+ "crypto/internal/randutil" -+ "encoding/binary" -+ "errors" -+ "io" -+ "math/bits" -+) -+ -+type nistCurve[Point nistPoint[Point]] struct { -+ name string -+ newPoint func() Point -+ scalarOrder []byte -+} -+ -+// nistPoint is a generic constraint for the nistec Point types. -+type nistPoint[T any] interface { -+ Bytes() []byte -+ BytesX() ([]byte, error) -+ SetBytes([]byte) (T, error) -+ ScalarMult(T, []byte) (T, error) -+ ScalarBaseMult([]byte) (T, error) -+} -+ -+func (c *nistCurve[Point]) String() string { -+ return c.name -+} -+ -+var errInvalidPrivateKey = errors.New("crypto/ecdh: invalid private key") -+ -+func (c *nistCurve[Point]) GenerateKey(rand io.Reader) (*PrivateKey, error) { -+ if boring.Enabled() && rand == boring.RandReader { -+ key, bytes, err := boring.GenerateKeyECDH(c.name) -+ if err != nil { -+ return nil, err -+ } -+ return newBoringPrivateKey(c, key, bytes) -+ } -+ -+ key := make([]byte, len(c.scalarOrder)) -+ randutil.MaybeReadByte(rand) -+ for { -+ if _, err := io.ReadFull(rand, key); err != nil { -+ return nil, err -+ } -+ -+ // Mask off any excess bits if the size of the underlying field is not a -+ // whole number of bytes, which is only the case for P-521. We use a -+ // pointer to the scalarOrder field because comparing generic and -+ // instantiated types is not supported. -+ if &c.scalarOrder[0] == &p521Order[0] { -+ key[0] &= 0b0000_0001 -+ } -+ -+ // In tests, rand will return all zeros and NewPrivateKey will reject -+ // the zero key as it generates the identity as a public key. This also -+ // makes this function consistent with crypto/elliptic.GenerateKey. -+ key[1] ^= 0x42 -+ -+ k, err := c.NewPrivateKey(key) -+ if err == errInvalidPrivateKey { -+ continue -+ } -+ return k, err -+ } -+} -+ -+func (c *nistCurve[Point]) NewPrivateKey(key []byte) (*PrivateKey, error) { -+ if len(key) != len(c.scalarOrder) { -+ return nil, errors.New("crypto/ecdh: invalid private key size") -+ } -+ if isZero(key) || !isLess(key, c.scalarOrder) { -+ return nil, errInvalidPrivateKey -+ } -+ if boring.Enabled() { -+ bk, err := boring.NewPrivateKeyECDH(c.name, key) -+ if err != nil { -+ return nil, err -+ } -+ return newBoringPrivateKey(c, bk, key) -+ } -+ k := &PrivateKey{ -+ curve: c, -+ privateKey: append([]byte{}, key...), -+ } -+ return k, nil -+} -+ -+func newBoringPrivateKey(c Curve, bk *boring.PrivateKeyECDH, privateKey []byte) (*PrivateKey, error) { -+ k := &PrivateKey{ -+ curve: c, -+ boring: bk, -+ privateKey: append([]byte(nil), privateKey...), -+ } -+ return k, nil -+} -+ -+func (c *nistCurve[Point]) privateKeyToPublicKey(key *PrivateKey) *PublicKey { -+ boring.Unreachable() -+ if key.curve != c { -+ panic("crypto/ecdh: internal error: converting the wrong key type") -+ } -+ p, err := c.newPoint().ScalarBaseMult(key.privateKey) -+ if err != nil { -+ // This is unreachable because the only error condition of -+ // ScalarBaseMult is if the input is not the right size. -+ panic("crypto/ecdh: internal error: nistec ScalarBaseMult failed for a fixed-size input") -+ } -+ publicKey := p.Bytes() -+ if len(publicKey) == 1 { -+ // The encoding of the identity is a single 0x00 byte. This is -+ // unreachable because the only scalar that generates the identity is -+ // zero, which is rejected by NewPrivateKey. -+ panic("crypto/ecdh: internal error: nistec ScalarBaseMult returned the identity") -+ } -+ return &PublicKey{ -+ curve: key.curve, -+ publicKey: publicKey, -+ } -+} -+ -+// isZero returns whether a is all zeroes in constant time. -+func isZero(a []byte) bool { -+ var acc byte -+ for _, b := range a { -+ acc |= b -+ } -+ return acc == 0 -+} -+ -+// isLess returns whether a < b, where a and b are big-endian buffers of the -+// same length and shorter than 72 bytes. -+func isLess(a, b []byte) bool { -+ if len(a) != len(b) { -+ panic("crypto/ecdh: internal error: mismatched isLess inputs") -+ } -+ -+ // Copy the values into a fixed-size preallocated little-endian buffer. -+ // 72 bytes is enough for every scalar in this package, and having a fixed -+ // size lets us avoid heap allocations. -+ if len(a) > 72 { -+ panic("crypto/ecdh: internal error: isLess input too large") -+ } -+ bufA, bufB := make([]byte, 72), make([]byte, 72) -+ for i := range a { -+ bufA[i], bufB[i] = a[len(a)-i-1], b[len(b)-i-1] -+ } -+ -+ // Perform a subtraction with borrow. -+ var borrow uint64 -+ for i := 0; i < len(bufA); i += 8 { -+ limbA, limbB := binary.LittleEndian.Uint64(bufA[i:]), binary.LittleEndian.Uint64(bufB[i:]) -+ _, borrow = bits.Sub64(limbA, limbB, borrow) -+ } -+ -+ // If there is a borrow at the end of the operation, then a < b. -+ return borrow == 1 -+} -+ -+func (c *nistCurve[Point]) NewPublicKey(key []byte) (*PublicKey, error) { -+ // Reject the point at infinity and compressed encodings. -+ if len(key) == 0 || key[0] != 4 { -+ return nil, errors.New("crypto/ecdh: invalid public key") -+ } -+ k := &PublicKey{ -+ curve: c, -+ publicKey: append([]byte{}, key...), -+ } -+ if boring.Enabled() { -+ bk, err := boring.NewPublicKeyECDH(c.name, k.publicKey) -+ if err != nil { -+ return nil, err -+ } -+ k.boring = bk -+ } else { -+ // SetBytes also checks that the point is on the curve. -+ if _, err := c.newPoint().SetBytes(key); err != nil { -+ return nil, err -+ } -+ } -+ return k, nil -+} -+ -+func (c *nistCurve[Point]) ecdh(local *PrivateKey, remote *PublicKey) ([]byte, error) { -+ // Note that this function can't return an error, as NewPublicKey rejects -+ // invalid points and the point at infinity, and NewPrivateKey rejects -+ // invalid scalars and the zero value. BytesX returns an error for the point -+ // at infinity, but in a prime order group such as the NIST curves that can -+ // only be the result of a scalar multiplication if one of the inputs is the -+ // zero scalar or the point at infinity. -+ -+ if boring.Enabled() { -+ return boring.ECDH(local.boring, remote.boring) -+ } -+ -+ boring.Unreachable() -+ p, err := c.newPoint().SetBytes(remote.publicKey) -+ if err != nil { -+ return nil, err -+ } -+ if _, err := p.ScalarMult(p, local.privateKey); err != nil { -+ return nil, err -+ } -+ return p.BytesX() -+} -+ -+// P256 returns a Curve which implements NIST P-256 (FIPS 186-3, section D.2.3), -+// also known as secp256r1 or prime256v1. -+// -+// Multiple invocations of this function will return the same value, which can -+// be used for equality checks and switch statements. -+func P256() Curve { return p256 } -+ -+var p256 = &nistCurve[*nistec.P256Point]{ -+ name: "P-256", -+ newPoint: nistec.NewP256Point, -+ scalarOrder: p256Order, -+} -+ -+var p256Order = []byte{ -+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -+ 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, -+ 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51} -+ -+// P384 returns a Curve which implements NIST P-384 (FIPS 186-3, section D.2.4), -+// also known as secp384r1. -+// -+// Multiple invocations of this function will return the same value, which can -+// be used for equality checks and switch statements. -+func P384() Curve { return p384 } -+ -+var p384 = &nistCurve[*nistec.P384Point]{ -+ name: "P-384", -+ newPoint: nistec.NewP384Point, -+ scalarOrder: p384Order, -+} -+ -+var p384Order = []byte{ -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -+ 0xc7, 0x63, 0x4d, 0x81, 0xf4, 0x37, 0x2d, 0xdf, -+ 0x58, 0x1a, 0x0d, 0xb2, 0x48, 0xb0, 0xa7, 0x7a, -+ 0xec, 0xec, 0x19, 0x6a, 0xcc, 0xc5, 0x29, 0x73} -+ -+// P521 returns a Curve which implements NIST P-521 (FIPS 186-3, section D.2.5), -+// also known as secp521r1. -+// -+// Multiple invocations of this function will return the same value, which can -+// be used for equality checks and switch statements. -+func P521() Curve { return p521 } -+ -+var p521 = &nistCurve[*nistec.P521Point]{ -+ name: "P-521", -+ newPoint: nistec.NewP521Point, -+ scalarOrder: p521Order, -+} -+ -+var p521Order = []byte{0x01, 0xff, -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, -+ 0x51, 0x86, 0x87, 0x83, 0xbf, 0x2f, 0x96, 0x6b, -+ 0x7f, 0xcc, 0x01, 0x48, 0xf7, 0x09, 0xa5, 0xd0, -+ 0x3b, 0xb5, 0xc9, 0xb8, 0x89, 0x9c, 0x47, 0xae, -+ 0xbb, 0x6f, 0xb7, 0x1e, 0x91, 0x38, 0x64, 0x09} -diff --git a/src/crypto/ecdh/x25519.go-e b/src/crypto/ecdh/x25519.go-e -new file mode 100644 -index 0000000000..dbc3ea9dc8 ---- /dev/null -+++ b/src/crypto/ecdh/x25519.go-e -@@ -0,0 +1,136 @@ -+// Copyright 2022 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. -+ -+package ecdh -+ -+import ( -+ "crypto/internal/edwards25519/field" -+ "crypto/internal/randutil" -+ "errors" -+ "io" -+) -+ -+var ( -+ x25519PublicKeySize = 32 -+ x25519PrivateKeySize = 32 -+ x25519SharedSecretSize = 32 -+) -+ -+// X25519 returns a Curve which implements the X25519 function over Curve25519 -+// (RFC 7748, Section 5). -+// -+// Multiple invocations of this function will return the same value, so it can -+// be used for equality checks and switch statements. -+func X25519() Curve { return x25519 } -+ -+var x25519 = &x25519Curve{} -+ -+type x25519Curve struct{} -+ -+func (c *x25519Curve) String() string { -+ return "X25519" -+} -+ -+func (c *x25519Curve) GenerateKey(rand io.Reader) (*PrivateKey, error) { -+ key := make([]byte, x25519PrivateKeySize) -+ randutil.MaybeReadByte(rand) -+ if _, err := io.ReadFull(rand, key); err != nil { -+ return nil, err -+ } -+ return c.NewPrivateKey(key) -+} -+ -+func (c *x25519Curve) NewPrivateKey(key []byte) (*PrivateKey, error) { -+ if len(key) != x25519PrivateKeySize { -+ return nil, errors.New("crypto/ecdh: invalid private key size") -+ } -+ return &PrivateKey{ -+ curve: c, -+ privateKey: append([]byte{}, key...), -+ }, nil -+} -+ -+func (c *x25519Curve) privateKeyToPublicKey(key *PrivateKey) *PublicKey { -+ if key.curve != c { -+ panic("crypto/ecdh: internal error: converting the wrong key type") -+ } -+ k := &PublicKey{ -+ curve: key.curve, -+ publicKey: make([]byte, x25519PublicKeySize), -+ } -+ x25519Basepoint := [32]byte{9} -+ x25519ScalarMult(k.publicKey, key.privateKey, x25519Basepoint[:]) -+ return k -+} -+ -+func (c *x25519Curve) NewPublicKey(key []byte) (*PublicKey, error) { -+ if len(key) != x25519PublicKeySize { -+ return nil, errors.New("crypto/ecdh: invalid public key") -+ } -+ return &PublicKey{ -+ curve: c, -+ publicKey: append([]byte{}, key...), -+ }, nil -+} -+ -+func (c *x25519Curve) ecdh(local *PrivateKey, remote *PublicKey) ([]byte, error) { -+ out := make([]byte, x25519SharedSecretSize) -+ x25519ScalarMult(out, local.privateKey, remote.publicKey) -+ if isZero(out) { -+ return nil, errors.New("crypto/ecdh: bad X25519 remote ECDH input: low order point") -+ } -+ return out, nil -+} -+ -+func x25519ScalarMult(dst, scalar, point []byte) { -+ var e [32]byte -+ -+ copy(e[:], scalar[:]) -+ e[0] &= 248 -+ e[31] &= 127 -+ e[31] |= 64 -+ -+ var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element -+ x1.SetBytes(point[:]) -+ x2.One() -+ x3.Set(&x1) -+ z3.One() -+ -+ swap := 0 -+ for pos := 254; pos >= 0; pos-- { -+ b := e[pos/8] >> uint(pos&7) -+ b &= 1 -+ swap ^= int(b) -+ x2.Swap(&x3, swap) -+ z2.Swap(&z3, swap) -+ swap = int(b) -+ -+ tmp0.Subtract(&x3, &z3) -+ tmp1.Subtract(&x2, &z2) -+ x2.Add(&x2, &z2) -+ z2.Add(&x3, &z3) -+ z3.Multiply(&tmp0, &x2) -+ z2.Multiply(&z2, &tmp1) -+ tmp0.Square(&tmp1) -+ tmp1.Square(&x2) -+ x3.Add(&z3, &z2) -+ z2.Subtract(&z3, &z2) -+ x2.Multiply(&tmp1, &tmp0) -+ tmp1.Subtract(&tmp1, &tmp0) -+ z2.Square(&z2) -+ -+ z3.Mult32(&tmp1, 121666) -+ x3.Square(&x3) -+ tmp0.Add(&tmp0, &z3) -+ z3.Multiply(&x1, &z2) -+ z2.Multiply(&tmp1, &tmp0) -+ } -+ -+ x2.Swap(&x3, swap) -+ z2.Swap(&z3, swap) -+ -+ z2.Invert(&z2) -+ x2.Multiply(&x2, &z2) -+ copy(dst[:], x2.Bytes()) -+} ->>>>>>> 70a351c141 (wip) -======= ->>>>>>> 80d9391199 (wip) diff --git a/src/crypto/ecdsa/boring.go b/src/crypto/ecdsa/boring.go index 275c60b4de..58f0034b18 100644 --- a/src/crypto/ecdsa/boring.go @@ -2264,21 +240,12 @@ index 275c60b4de..58f0034b18 100644 @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -<<<<<<< HEAD - --//go:build boringcrypto -+//go:build !no_openssl - - package ecdsa - -======= -//go:build boringcrypto +//go:build !no_openssl package ecdsa ->>>>>>> 0023bf4c7a (rebase) import ( - "crypto/internal/boring" - "crypto/internal/boring/bbig" @@ -2305,11 +272,7 @@ index e1503779ae..00953a453a 100644 @@ -158,7 +158,7 @@ func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOp func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) { randutil.MaybeReadByte(rand) -<<<<<<< HEAD - -======= ->>>>>>> 0023bf4c7a (rebase) - if boring.Enabled && rand == boring.RandReader { + if boring.Enabled() && rand == boring.RandReader { x, y, d, err := boring.GenerateKeyECDSA(c.Params().Name) @@ -2318,11 +281,7 @@ index e1503779ae..00953a453a 100644 @@ -256,7 +256,7 @@ var errNoAsm = errors.New("no assembly implementation available") func SignASN1(rand io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) { randutil.MaybeReadByte(rand) -<<<<<<< HEAD - -======= ->>>>>>> 0023bf4c7a (rebase) - if boring.Enabled && rand == boring.RandReader { + if boring.Enabled() && rand == boring.RandReader { b, err := boringPrivateKey(priv) @@ -2337,1328 +296,126 @@ index e1503779ae..00953a453a 100644 key, err := boringPublicKey(pub) if err != nil { return false -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD -diff --git a/src/crypto/ecdsa/ecdsa_hashsignverify.go b/src/crypto/ecdsa/ecdsa_hashsignverify.go -index 37f3a18223..51e3b49cdc 100644 ---- a/src/crypto/ecdsa/ecdsa_hashsignverify.go -+++ b/src/crypto/ecdsa/ecdsa_hashsignverify.go -@@ -2,7 +2,7 @@ package ecdsa - - import ( - "crypto" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/randutil" - "math/big" - "io" -@@ -11,7 +11,7 @@ import ( - func HashSign(rand io.Reader, priv *PrivateKey, msg []byte, h crypto.Hash) (*big.Int, *big.Int, error) { - randutil.MaybeReadByte(rand) - -- if boring.Enabled { -+ if boring.Enabled() { - b, err := boringPrivateKey(priv) - if err != nil { - return nil, nil, err -@@ -28,7 +28,7 @@ func HashSign(rand io.Reader, priv *PrivateKey, msg []byte, h crypto.Hash) (*big - } - - func HashVerify(pub *PublicKey, msg []byte, r, s *big.Int, h crypto.Hash) bool { -- if boring.Enabled { -+ if boring.Enabled() { - bpk, err := boringPublicKey(pub) - if err != nil { - return false -diff --git a/src/crypto/ecdsa/ecdsa_hashsignverify_test.go b/src/crypto/ecdsa/ecdsa_hashsignverify_test.go -index d12ba2f441..6334a56496 100644 ---- a/src/crypto/ecdsa/ecdsa_hashsignverify_test.go -+++ b/src/crypto/ecdsa/ecdsa_hashsignverify_test.go -@@ -2,7 +2,7 @@ package ecdsa - - import ( - "crypto" +diff --git a/src/crypto/ecdsa/ecdsa_test.go b/src/crypto/ecdsa/ecdsa_test.go +index 61a4662036..80e484842b 100644 +--- a/src/crypto/ecdsa/ecdsa_test.go ++++ b/src/crypto/ecdsa/ecdsa_test.go +@@ -10,7 +10,7 @@ import ( + "compress/bzip2" + "crypto/elliptic" + "crypto/internal/backend/boringtest" - "crypto/internal/boring" + boring "crypto/internal/backend" + "crypto/internal/bigmod" + "crypto/rand" + "crypto/sha1" +@@ -38,7 +38,7 @@ func testAllCurves(t *testing.T, f func(*testing.T, elliptic.Curve)) { + } + if testing.Short() { + tests = tests[:1] +- } else if !boring.Enabled || boringtest.Supports(t, "CurveP224") { ++ } else if !boring.Enabled() || boringtest.Supports(t, "CurveP224") { + p224 := struct { + name string + curve elliptic.Curve +@@ -46,7 +46,7 @@ func testAllCurves(t *testing.T, f func(*testing.T, elliptic.Curve)) { + tests = append(tests, p224) + } + for _, test := range tests { +- if boring.Enabled && !boringtest.Supports(t, "Curve"+test.name) { ++ if boring.Enabled() && !boringtest.Supports(t, "Curve"+test.name) { + t.Skip("unsupported test in FIPS mode") + } + curve := test.curve +@@ -246,7 +246,7 @@ func TestVectors(t *testing.T) { + + switch curve { + case "P-224": +- if !boring.Enabled || boringtest.Supports(t, "CurveP224") { ++ if !boring.Enabled() || boringtest.Supports(t, "CurveP224") { + pub.Curve = elliptic.P224() + } else { + pub.Curve = nil +diff --git a/src/crypto/ecdsa/equal_test.go b/src/crypto/ecdsa/equal_test.go +index 4371e31b1a..5ef62abe37 100644 +--- a/src/crypto/ecdsa/equal_test.go ++++ b/src/crypto/ecdsa/equal_test.go +@@ -10,7 +10,7 @@ import ( "crypto/elliptic" "crypto/rand" + "crypto/x509" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/backend/boringtest" "testing" -@@ -34,7 +34,7 @@ func testHashSignAndHashVerify(t *testing.T, c elliptic.Curve, tag string) { - func TestHashSignAndHashVerify(t *testing.T) { - testHashSignAndHashVerify(t, elliptic.P256(), "p256") - -- if testing.Short() && !boring.Enabled { -+ if testing.Short() && !boring.Enabled() { + ) +@@ -71,7 +71,7 @@ func TestEqual(t *testing.T) { + if testing.Short() { return } - testHashSignAndHashVerify(t, elliptic.P384(), "p384") -======= ->>>>>>> 0023bf4c7a (rebase) -======= -diff --git a/src/crypto/ecdsa/ecdsa.go-e b/src/crypto/ecdsa/ecdsa.go-e -new file mode 100644 -index 0000000000..00953a453a ---- /dev/null -+++ b/src/crypto/ecdsa/ecdsa.go-e -@@ -0,0 +1,672 @@ -+// Copyright 2011 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. -+ -+// Package ecdsa implements the Elliptic Curve Digital Signature Algorithm, as -+// defined in FIPS 186-4 and SEC 1, Version 2.0. -+// -+// 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 -+ -+// [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 ( -+ "bytes" -+ "crypto" -+ "crypto/aes" -+ "crypto/cipher" -+ "crypto/ecdh" -+ "crypto/elliptic" -+ "crypto/internal/bigmod" -+ boring "crypto/internal/backend" -+ "crypto/internal/backend/bbig" -+ "crypto/internal/nistec" -+ "crypto/internal/randutil" -+ "crypto/sha512" -+ "crypto/subtle" -+ "errors" -+ "io" -+ "math/big" -+ "sync" -+ -+ "golang.org/x/crypto/cryptobyte" -+ "golang.org/x/crypto/cryptobyte/asn1" -+) -+ -+// PublicKey represents an ECDSA public key. -+type PublicKey struct { -+ elliptic.Curve -+ X, Y *big.Int -+} -+ -+// Any methods implemented on PublicKey might need to also be implemented on -+// PrivateKey, as the latter embeds the former and will expose its methods. -+ -+// ECDH returns k as a [ecdh.PublicKey]. It returns an error if the key is -+// invalid according to the definition of [ecdh.Curve.NewPublicKey], or if the -+// Curve is not supported by crypto/ecdh. -+func (k *PublicKey) ECDH() (*ecdh.PublicKey, error) { -+ c := curveToECDH(k.Curve) -+ if c == nil { -+ return nil, errors.New("ecdsa: unsupported curve by crypto/ecdh") -+ } -+ if !k.Curve.IsOnCurve(k.X, k.Y) { -+ return nil, errors.New("ecdsa: invalid public key") -+ } -+ return c.NewPublicKey(elliptic.Marshal(k.Curve, k.X, k.Y)) -+} -+ -+// Equal reports whether pub and x have the same value. -+// -+// Two keys are only considered to have the same value if they have the same Curve value. -+// Note that for example elliptic.P256() and elliptic.P256().Params() are different -+// values, as the latter is a generic not constant time implementation. -+func (pub *PublicKey) Equal(x crypto.PublicKey) bool { -+ xx, ok := x.(*PublicKey) -+ if !ok { -+ return false -+ } -+ return bigIntEqual(pub.X, xx.X) && bigIntEqual(pub.Y, xx.Y) && -+ // Standard library Curve implementations are singletons, so this check -+ // will work for those. Other Curves might be equivalent even if not -+ // singletons, but there is no definitive way to check for that, and -+ // better to err on the side of safety. -+ pub.Curve == xx.Curve -+} -+ -+// PrivateKey represents an ECDSA private key. -+type PrivateKey struct { -+ PublicKey -+ D *big.Int -+} -+ -+// ECDH returns k as a [ecdh.PrivateKey]. It returns an error if the key is -+// invalid according to the definition of [ecdh.Curve.NewPrivateKey], or if the -+// Curve is not supported by crypto/ecdh. -+func (k *PrivateKey) ECDH() (*ecdh.PrivateKey, error) { -+ c := curveToECDH(k.Curve) -+ if c == nil { -+ return nil, errors.New("ecdsa: unsupported curve by crypto/ecdh") -+ } -+ size := (k.Curve.Params().N.BitLen() + 7) / 8 -+ if k.D.BitLen() > size*8 { -+ return nil, errors.New("ecdsa: invalid private key") -+ } -+ return c.NewPrivateKey(k.D.FillBytes(make([]byte, size))) -+} -+ -+func curveToECDH(c elliptic.Curve) ecdh.Curve { -+ switch c { -+ case elliptic.P256(): -+ return ecdh.P256() -+ case elliptic.P384(): -+ return ecdh.P384() -+ case elliptic.P521(): -+ return ecdh.P521() -+ default: -+ return nil -+ } -+} -+ -+// Public returns the public key corresponding to priv. -+func (priv *PrivateKey) Public() crypto.PublicKey { -+ return &priv.PublicKey -+} -+ -+// Equal reports whether priv and x have the same value. -+// -+// See PublicKey.Equal for details on how Curve is compared. -+func (priv *PrivateKey) Equal(x crypto.PrivateKey) bool { -+ xx, ok := x.(*PrivateKey) -+ if !ok { -+ return false -+ } -+ return priv.PublicKey.Equal(&xx.PublicKey) && bigIntEqual(priv.D, xx.D) -+} -+ -+// bigIntEqual reports whether a and b are equal leaking only their bit length -+// through timing side-channels. -+func bigIntEqual(a, b *big.Int) bool { -+ return subtle.ConstantTimeCompare(a.Bytes(), b.Bytes()) == 1 -+} -+ -+// Sign signs digest with priv, reading randomness from rand. The opts argument -+// is not currently used but, in keeping with the crypto.Signer interface, -+// should be the hash function used to digest the message. -+// -+// 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 can use the SignASN1 function in this package directly. -+func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { -+ return SignASN1(rand, priv, digest) -+} -+ -+// GenerateKey generates a new ECDSA private key for the specified curve. -+// -+// Most applications should use [crypto/rand.Reader] as rand. Note that the -+// returned key does not depend deterministically on the bytes read from rand, -+// and may change between calls and/or between versions. -+func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) { -+ randutil.MaybeReadByte(rand) -+ -+ 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: bbig.Dec(x), Y: bbig.Dec(y)}, D: bbig.Dec(d)}, nil -+ } -+ boring.UnreachableExceptTests() -+ -+ switch c.Params() { -+ case elliptic.P224().Params(): -+ return generateNISTEC(p224(), rand) -+ case elliptic.P256().Params(): -+ return generateNISTEC(p256(), rand) -+ case elliptic.P384().Params(): -+ return generateNISTEC(p384(), rand) -+ case elliptic.P521().Params(): -+ return generateNISTEC(p521(), rand) -+ default: -+ return generateLegacy(c, rand) -+ } -+} -+ -+func generateNISTEC[Point nistPoint[Point]](c *nistCurve[Point], rand io.Reader) (*PrivateKey, error) { -+ k, Q, err := randomPoint(c, rand) -+ if err != nil { -+ return nil, err -+ } -+ -+ priv := new(PrivateKey) -+ priv.PublicKey.Curve = c.curve -+ priv.D = new(big.Int).SetBytes(k.Bytes(c.N)) -+ priv.PublicKey.X, priv.PublicKey.Y, err = c.pointToAffine(Q) -+ if err != nil { -+ return nil, err -+ } -+ return priv, nil -+} -+ -+// randomPoint returns a random scalar and the corresponding point using the -+// procedure given in FIPS 186-4, Appendix B.5.2 (rejection sampling). -+func randomPoint[Point nistPoint[Point]](c *nistCurve[Point], rand io.Reader) (k *bigmod.Nat, p Point, err error) { -+ k = bigmod.NewNat() -+ for { -+ b := make([]byte, c.N.Size()) -+ if _, err = io.ReadFull(rand, b); err != nil { -+ return -+ } -+ -+ // Mask off any excess bits to increase the chance of hitting a value in -+ // (0, N). These are the most dangerous lines in the package and maybe in -+ // the library: a single bit of bias in the selection of nonces would likely -+ // lead to key recovery, but no tests would fail. Look but DO NOT TOUCH. -+ if excess := len(b)*8 - c.N.BitLen(); excess > 0 { -+ // Just to be safe, assert that this only happens for the one curve that -+ // doesn't have a round number of bits. -+ if excess != 0 && c.curve.Params().Name != "P-521" { -+ panic("ecdsa: internal error: unexpectedly masking off bits") -+ } -+ b[0] >>= excess -+ } -+ -+ // FIPS 186-4 makes us check k <= N - 2 and then add one. -+ // Checking 0 < k <= N - 1 is strictly equivalent. -+ // None of this matters anyway because the chance of selecting -+ // zero is cryptographically negligible. -+ if _, err = k.SetBytes(b, c.N); err == nil && k.IsZero() == 0 { -+ break -+ } -+ -+ if testingOnlyRejectionSamplingLooped != nil { -+ testingOnlyRejectionSamplingLooped() -+ } -+ } -+ -+ p, err = c.newPoint().ScalarBaseMult(k.Bytes(c.N)) -+ return -+} -+ -+// testingOnlyRejectionSamplingLooped is called when rejection sampling in -+// randomPoint rejects a candidate for being higher than the modulus. -+var testingOnlyRejectionSamplingLooped func() -+ -+// errNoAsm is returned by signAsm and verifyAsm when the assembly -+// implementation is not available. -+var errNoAsm = errors.New("no assembly implementation available") -+ -+// 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 signature is randomized. Most applications should use [crypto/rand.Reader] -+// as rand. Note that the returned signature does not depend deterministically on -+// the bytes read from rand, and may change between calls and/or between versions. -+func SignASN1(rand io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) { -+ randutil.MaybeReadByte(rand) -+ -+ if boring.Enabled() && rand == boring.RandReader { -+ b, err := boringPrivateKey(priv) -+ if err != nil { -+ return nil, err -+ } -+ return boring.SignMarshalECDSA(b, hash) -+ } -+ boring.UnreachableExceptTests() -+ -+ csprng, err := mixedCSPRNG(rand, priv, hash) -+ if err != nil { -+ return nil, err -+ } -+ -+ if sig, err := signAsm(priv, csprng, hash); err != errNoAsm { -+ return sig, err -+ } -+ -+ switch priv.Curve.Params() { -+ case elliptic.P224().Params(): -+ return signNISTEC(p224(), priv, csprng, hash) -+ case elliptic.P256().Params(): -+ return signNISTEC(p256(), priv, csprng, hash) -+ case elliptic.P384().Params(): -+ return signNISTEC(p384(), priv, csprng, hash) -+ case elliptic.P521().Params(): -+ return signNISTEC(p521(), priv, csprng, hash) -+ default: -+ return signLegacy(priv, csprng, hash) -+ } -+} -+ -+func signNISTEC[Point nistPoint[Point]](c *nistCurve[Point], priv *PrivateKey, csprng io.Reader, hash []byte) (sig []byte, err error) { -+ // SEC 1, Version 2.0, Section 4.1.3 -+ -+ k, R, err := randomPoint(c, csprng) -+ if err != nil { -+ return nil, err -+ } -+ -+ // kInv = k⁻¹ -+ kInv := bigmod.NewNat() -+ inverse(c, kInv, k) -+ -+ Rx, err := R.BytesX() -+ if err != nil { -+ return nil, err -+ } -+ r, err := bigmod.NewNat().SetOverflowingBytes(Rx, c.N) -+ if err != nil { -+ return nil, err -+ } -+ -+ // The spec wants us to retry here, but the chance of hitting this condition -+ // on a large prime-order group like the NIST curves we support is -+ // cryptographically negligible. If we hit it, something is awfully wrong. -+ if r.IsZero() == 1 { -+ return nil, errors.New("ecdsa: internal error: r is zero") -+ } -+ -+ e := bigmod.NewNat() -+ hashToNat(c, e, hash) -+ -+ s, err := bigmod.NewNat().SetBytes(priv.D.Bytes(), c.N) -+ if err != nil { -+ return nil, err -+ } -+ s.Mul(r, c.N) -+ s.Add(e, c.N) -+ s.Mul(kInv, c.N) -+ -+ // Again, the chance of this happening is cryptographically negligible. -+ if s.IsZero() == 1 { -+ return nil, errors.New("ecdsa: internal error: s is zero") -+ } -+ -+ return encodeSignature(r.Bytes(c.N), s.Bytes(c.N)) -+} -+ -+func encodeSignature(r, s []byte) ([]byte, error) { -+ var b cryptobyte.Builder -+ b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) { -+ addASN1IntBytes(b, r) -+ addASN1IntBytes(b, s) -+ }) -+ return b.Bytes() -+} -+ -+// addASN1IntBytes encodes in ASN.1 a positive integer represented as -+// a big-endian byte slice with zero or more leading zeroes. -+func addASN1IntBytes(b *cryptobyte.Builder, bytes []byte) { -+ for len(bytes) > 0 && bytes[0] == 0 { -+ bytes = bytes[1:] -+ } -+ if len(bytes) == 0 { -+ b.SetError(errors.New("invalid integer")) -+ return -+ } -+ b.AddASN1(asn1.INTEGER, func(c *cryptobyte.Builder) { -+ if bytes[0]&0x80 != 0 { -+ c.AddUint8(0) -+ } -+ c.AddBytes(bytes) -+ }) -+} -+ -+// inverse sets kInv to the inverse of k modulo the order of the curve. -+func inverse[Point nistPoint[Point]](c *nistCurve[Point], kInv, k *bigmod.Nat) { -+ if c.curve.Params().Name == "P-256" { -+ kBytes, err := nistec.P256OrdInverse(k.Bytes(c.N)) -+ // Some platforms don't implement P256OrdInverse, and always return an error. -+ if err == nil { -+ _, err := kInv.SetBytes(kBytes, c.N) -+ if err != nil { -+ panic("ecdsa: internal error: P256OrdInverse produced an invalid value") -+ } -+ return -+ } -+ } -+ -+ // Calculate the inverse of s in GF(N) using Fermat's method -+ // (exponentiation modulo P - 2, per Euler's theorem) -+ kInv.Exp(k, c.nMinus2, c.N) -+} -+ -+// hashToNat sets e to the left-most bits of hash, according to -+// SEC 1, Section 4.1.3, point 5 and Section 4.1.4, point 3. -+func hashToNat[Point nistPoint[Point]](c *nistCurve[Point], e *bigmod.Nat, hash []byte) { -+ // ECDSA asks us to take the left-most log2(N) bits of hash, and use them as -+ // an integer modulo N. This is the absolute worst of all worlds: we still -+ // have to reduce, because the result might still overflow N, but to take -+ // the left-most bits for P-521 we have to do a right shift. -+ if size := c.N.Size(); len(hash) >= size { -+ hash = hash[:size] -+ if excess := len(hash)*8 - c.N.BitLen(); excess > 0 { -+ hash = bytes.Clone(hash) -+ for i := len(hash) - 1; i >= 0; i-- { -+ hash[i] >>= excess -+ if i > 0 { -+ hash[i] |= hash[i-1] << (8 - excess) -+ } -+ } -+ } -+ } -+ _, err := e.SetOverflowingBytes(hash, c.N) -+ if err != nil { -+ panic("ecdsa: internal error: truncated hash is too long") -+ } -+} -+ -+// mixedCSPRNG returns a CSPRNG that mixes entropy from rand with the message -+// and the private key, to protect the key in case rand fails. This is -+// equivalent in security to RFC 6979 deterministic nonce generation, but still -+// produces randomized signatures. -+func mixedCSPRNG(rand io.Reader, priv *PrivateKey, hash []byte) (io.Reader, error) { -+ // 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) -+ if _, err := io.ReadFull(rand, entropy); err != nil { -+ return nil, err -+ } -+ -+ // Initialize an SHA-512 hash context; digest... -+ md := sha512.New() -+ md.Write(priv.D.Bytes()) // the private key, -+ md.Write(entropy) // the entropy, -+ md.Write(hash) // and the input hash; -+ key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512), -+ // which is an indifferentiable MAC. -+ -+ // Create an AES-CTR instance to use as a CSPRNG. -+ block, err := aes.NewCipher(key) -+ if err != nil { -+ return nil, err -+ } -+ -+ // Create a CSPRNG that xors a stream of zeros with -+ // the output of the AES-CTR instance. -+ const aesIV = "IV for ECDSA CTR" -+ return &cipher.StreamReader{ -+ R: zeroReader, -+ S: cipher.NewCTR(block, []byte(aesIV)), -+ }, nil -+} -+ -+type zr struct{} -+ -+var zeroReader = zr{} -+ -+// Read replaces the contents of dst with zeros. It is safe for concurrent use. -+func (zr) Read(dst []byte) (n int, err error) { -+ for i := range dst { -+ dst[i] = 0 -+ } -+ return len(dst), nil -+} -+ -+// VerifyASN1 verifies the ASN.1 encoded signature, sig, of hash using the -+// public key, pub. Its return value records whether the signature is valid. -+func VerifyASN1(pub *PublicKey, hash, sig []byte) bool { +- if !boring.Enabled || boringtest.Supports(t, "CurveP224") { ++ if !boring.Enabled() || boringtest.Supports(t, "CurveP224") { + t.Run("P224", func(t *testing.T) { testEqual(t, elliptic.P224()) }) + } + t.Run("P384", func(t *testing.T) { testEqual(t, elliptic.P384()) }) +diff --git a/src/crypto/ecdsa/notboring.go b/src/crypto/ecdsa/notboring.go +index 039bd82ed2..21a35b760c 100644 +--- a/src/crypto/ecdsa/notboring.go ++++ b/src/crypto/ecdsa/notboring.go +@@ -2,15 +2,15 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build !boringcrypto ++//go:build no_openssl + + package ecdsa + +-import "crypto/internal/boring" ++import boring "crypto/internal/backend" + + func boringPublicKey(*PublicKey) (*boring.PublicKeyECDSA, error) { +- panic("boringcrypto: not available") ++ panic("!no_openssl: not available") + } + func boringPrivateKey(*PrivateKey) (*boring.PrivateKeyECDSA, error) { +- panic("boringcrypto: not available") ++ panic("!no_openssl: not available") + } +diff --git a/src/crypto/ed25519/ed25519_test.go b/src/crypto/ed25519/ed25519_test.go +index 8b5c2cc9af..ebbb1c0c07 100644 +--- a/src/crypto/ed25519/ed25519_test.go ++++ b/src/crypto/ed25519/ed25519_test.go +@@ -9,7 +9,7 @@ import ( + "bytes" + "compress/gzip" + "crypto" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/rand" + "crypto/sha512" + "encoding/hex" +@@ -322,7 +322,7 @@ func TestMalleability(t *testing.T) { + + func TestAllocations(t *testing.T) { + t.Skip("Allocations test broken with openssl linkage") +- if boring.Enabled { + if boring.Enabled() { -+ key, err := boringPublicKey(pub) -+ if err != nil { -+ return false -+ } -+ return boring.VerifyECDSA(key, hash, sig) -+ } -+ boring.UnreachableExceptTests() -+ -+ if err := verifyAsm(pub, hash, sig); err != errNoAsm { -+ return err == nil -+ } -+ -+ switch pub.Curve.Params() { -+ case elliptic.P224().Params(): -+ return verifyNISTEC(p224(), pub, hash, sig) -+ case elliptic.P256().Params(): -+ return verifyNISTEC(p256(), pub, hash, sig) -+ case elliptic.P384().Params(): -+ return verifyNISTEC(p384(), pub, hash, sig) -+ case elliptic.P521().Params(): -+ return verifyNISTEC(p521(), pub, hash, sig) -+ default: -+ return verifyLegacy(pub, hash, sig) -+ } -+} -+ -+func verifyNISTEC[Point nistPoint[Point]](c *nistCurve[Point], pub *PublicKey, hash, sig []byte) bool { -+ rBytes, sBytes, err := parseSignature(sig) -+ if err != nil { -+ return false -+ } -+ -+ Q, err := c.pointFromAffine(pub.X, pub.Y) -+ if err != nil { -+ return false -+ } -+ -+ // SEC 1, Version 2.0, Section 4.1.4 -+ -+ r, err := bigmod.NewNat().SetBytes(rBytes, c.N) -+ if err != nil || r.IsZero() == 1 { -+ return false -+ } -+ s, err := bigmod.NewNat().SetBytes(sBytes, c.N) -+ if err != nil || s.IsZero() == 1 { -+ return false -+ } -+ -+ e := bigmod.NewNat() -+ hashToNat(c, e, hash) -+ -+ // w = s⁻¹ -+ w := bigmod.NewNat() -+ inverse(c, w, s) -+ -+ // p₁ = [e * s⁻¹]G -+ p1, err := c.newPoint().ScalarBaseMult(e.Mul(w, c.N).Bytes(c.N)) -+ if err != nil { -+ return false -+ } -+ // p₂ = [r * s⁻¹]Q -+ p2, err := Q.ScalarMult(Q, w.Mul(r, c.N).Bytes(c.N)) -+ if err != nil { -+ return false -+ } -+ // BytesX returns an error for the point at infinity. -+ Rx, err := p1.Add(p1, p2).BytesX() -+ if err != nil { -+ return false -+ } -+ -+ v, err := bigmod.NewNat().SetOverflowingBytes(Rx, c.N) -+ if err != nil { -+ return false -+ } -+ -+ return v.Equal(r) == 1 -+} -+ -+func parseSignature(sig []byte) (r, s []byte, err error) { -+ var inner cryptobyte.String -+ input := cryptobyte.String(sig) -+ if !input.ReadASN1(&inner, asn1.SEQUENCE) || -+ !input.Empty() || -+ !inner.ReadASN1Integer(&r) || -+ !inner.ReadASN1Integer(&s) || -+ !inner.Empty() { -+ return nil, nil, errors.New("invalid ASN.1") -+ } -+ return r, s, nil -+} -+ -+type nistCurve[Point nistPoint[Point]] struct { -+ newPoint func() Point -+ curve elliptic.Curve -+ N *bigmod.Modulus -+ nMinus2 []byte -+} -+ -+// nistPoint is a generic constraint for the nistec Point types. -+type nistPoint[T any] interface { -+ Bytes() []byte -+ BytesX() ([]byte, error) -+ SetBytes([]byte) (T, error) -+ Add(T, T) T -+ ScalarMult(T, []byte) (T, error) -+ ScalarBaseMult([]byte) (T, error) -+} -+ -+// pointFromAffine is used to convert the PublicKey to a nistec Point. -+func (curve *nistCurve[Point]) pointFromAffine(x, y *big.Int) (p Point, err error) { -+ bitSize := curve.curve.Params().BitSize -+ // Reject values that would not get correctly encoded. -+ if x.Sign() < 0 || y.Sign() < 0 { -+ return p, errors.New("negative coordinate") -+ } -+ if x.BitLen() > bitSize || y.BitLen() > bitSize { -+ return p, errors.New("overflowing coordinate") -+ } -+ // Encode the coordinates and let SetBytes reject invalid points. -+ byteLen := (bitSize + 7) / 8 -+ buf := make([]byte, 1+2*byteLen) -+ buf[0] = 4 // uncompressed point -+ x.FillBytes(buf[1 : 1+byteLen]) -+ y.FillBytes(buf[1+byteLen : 1+2*byteLen]) -+ return curve.newPoint().SetBytes(buf) -+} -+ -+// pointToAffine is used to convert a nistec Point to a PublicKey. -+func (curve *nistCurve[Point]) pointToAffine(p Point) (x, y *big.Int, err error) { -+ out := p.Bytes() -+ if len(out) == 1 && out[0] == 0 { -+ // This is the encoding of the point at infinity. -+ return nil, nil, errors.New("ecdsa: public key point is the infinity") -+ } -+ byteLen := (curve.curve.Params().BitSize + 7) / 8 -+ x = new(big.Int).SetBytes(out[1 : 1+byteLen]) -+ y = new(big.Int).SetBytes(out[1+byteLen:]) -+ return x, y, nil -+} -+ -+var p224Once sync.Once -+var _p224 *nistCurve[*nistec.P224Point] -+ -+func p224() *nistCurve[*nistec.P224Point] { -+ p224Once.Do(func() { -+ _p224 = &nistCurve[*nistec.P224Point]{ -+ newPoint: func() *nistec.P224Point { return nistec.NewP224Point() }, -+ } -+ precomputeParams(_p224, elliptic.P224()) -+ }) -+ return _p224 -+} -+ -+var p256Once sync.Once -+var _p256 *nistCurve[*nistec.P256Point] -+ -+func p256() *nistCurve[*nistec.P256Point] { -+ p256Once.Do(func() { -+ _p256 = &nistCurve[*nistec.P256Point]{ -+ newPoint: func() *nistec.P256Point { return nistec.NewP256Point() }, -+ } -+ precomputeParams(_p256, elliptic.P256()) -+ }) -+ return _p256 -+} -+ -+var p384Once sync.Once -+var _p384 *nistCurve[*nistec.P384Point] -+ -+func p384() *nistCurve[*nistec.P384Point] { -+ p384Once.Do(func() { -+ _p384 = &nistCurve[*nistec.P384Point]{ -+ newPoint: func() *nistec.P384Point { return nistec.NewP384Point() }, -+ } -+ precomputeParams(_p384, elliptic.P384()) -+ }) -+ return _p384 -+} -+ -+var p521Once sync.Once -+var _p521 *nistCurve[*nistec.P521Point] -+ -+func p521() *nistCurve[*nistec.P521Point] { -+ p521Once.Do(func() { -+ _p521 = &nistCurve[*nistec.P521Point]{ -+ newPoint: func() *nistec.P521Point { return nistec.NewP521Point() }, -+ } -+ precomputeParams(_p521, elliptic.P521()) -+ }) -+ return _p521 -+} -+ -+func precomputeParams[Point nistPoint[Point]](c *nistCurve[Point], curve elliptic.Curve) { -+ params := curve.Params() -+ c.curve = curve -+ var err error -+ c.N, err = bigmod.NewModulusFromBig(params.N) -+ if err != nil { -+ panic(err) -+ } -+ c.nMinus2 = new(big.Int).Sub(params.N, big.NewInt(2)).Bytes() -+} -diff --git a/src/crypto/ecdsa/ecdsa_legacy.go-e b/src/crypto/ecdsa/ecdsa_legacy.go-e -new file mode 100644 -index 0000000000..12a40e4828 ---- /dev/null -+++ b/src/crypto/ecdsa/ecdsa_legacy.go-e -@@ -0,0 +1,188 @@ -+// Copyright 2022 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. -+ -+package ecdsa -+ -+import ( -+ "crypto/elliptic" -+ "errors" -+ "io" -+ "math/big" -+ -+ "golang.org/x/crypto/cryptobyte" -+ "golang.org/x/crypto/cryptobyte/asn1" -+) -+ -+// This file contains a math/big implementation of ECDSA that is only used for -+// deprecated custom curves. -+ -+func generateLegacy(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) { -+ k, err := randFieldElement(c, rand) -+ if err != nil { -+ return nil, err -+ } -+ -+ priv := new(PrivateKey) -+ priv.PublicKey.Curve = c -+ priv.D = k -+ priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes()) -+ return priv, nil -+} -+ -+// 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 -+ if len(hash) > orderBytes { -+ hash = hash[:orderBytes] -+ } -+ -+ ret := new(big.Int).SetBytes(hash) -+ excess := len(hash)*8 - orderBits -+ if excess > 0 { -+ ret.Rsh(ret, uint(excess)) -+ } -+ return ret -+} -+ -+var errZeroParam = errors.New("zero parameter") -+ -+// 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. 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) { -+ sig, err := SignASN1(rand, priv, hash) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ r, s = new(big.Int), new(big.Int) -+ var inner cryptobyte.String -+ input := cryptobyte.String(sig) -+ if !input.ReadASN1(&inner, asn1.SEQUENCE) || -+ !input.Empty() || -+ !inner.ReadASN1Integer(r) || -+ !inner.ReadASN1Integer(s) || -+ !inner.Empty() { -+ return nil, nil, errors.New("invalid ASN.1 from SignASN1") -+ } -+ return r, s, nil -+} -+ -+func signLegacy(priv *PrivateKey, csprng io.Reader, hash []byte) (sig []byte, err error) { -+ c := priv.Curve -+ -+ // SEC 1, Version 2.0, Section 4.1.3 -+ N := c.Params().N -+ if N.Sign() == 0 { -+ return nil, errZeroParam -+ } -+ var k, kInv, r, s *big.Int -+ for { -+ for { -+ k, err = randFieldElement(c, csprng) -+ if err != nil { -+ return nil, err -+ } -+ -+ kInv = new(big.Int).ModInverse(k, N) -+ -+ r, _ = c.ScalarBaseMult(k.Bytes()) -+ r.Mod(r, N) -+ if r.Sign() != 0 { -+ break -+ } -+ } -+ -+ e := hashToInt(hash, c) -+ s = new(big.Int).Mul(priv.D, r) -+ s.Add(s, e) -+ s.Mul(s, kInv) -+ s.Mod(s, N) // N != 0 -+ if s.Sign() != 0 { -+ break -+ } -+ } -+ -+ return encodeSignature(r.Bytes(), s.Bytes()) -+} -+ -+// Verify verifies the signature in r, s of hash using the public key, pub. Its -+// 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 { -+ if r.Sign() <= 0 || s.Sign() <= 0 { -+ return false -+ } -+ sig, err := encodeSignature(r.Bytes(), s.Bytes()) -+ if err != nil { -+ return false -+ } -+ return VerifyASN1(pub, hash, sig) -+} -+ -+func verifyLegacy(pub *PublicKey, hash []byte, sig []byte) bool { -+ rBytes, sBytes, err := parseSignature(sig) -+ if err != nil { -+ return false -+ } -+ r, s := new(big.Int).SetBytes(rBytes), new(big.Int).SetBytes(sBytes) -+ -+ c := pub.Curve -+ N := c.Params().N -+ -+ if r.Sign() <= 0 || s.Sign() <= 0 { -+ return false -+ } -+ if r.Cmp(N) >= 0 || s.Cmp(N) >= 0 { -+ return false -+ } -+ -+ // SEC 1, Version 2.0, Section 4.1.4 -+ e := hashToInt(hash, c) -+ w := new(big.Int).ModInverse(s, N) -+ -+ u1 := e.Mul(e, w) -+ u1.Mod(u1, N) -+ u2 := w.Mul(r, w) -+ u2.Mod(u2, N) -+ -+ x1, y1 := c.ScalarBaseMult(u1.Bytes()) -+ x2, y2 := c.ScalarMult(pub.X, pub.Y, u2.Bytes()) -+ x, y := c.Add(x1, y1, x2, y2) -+ -+ if x.Sign() == 0 && y.Sign() == 0 { -+ return false -+ } -+ x.Mod(x, N) -+ return x.Cmp(r) == 0 -+} -+ -+var one = new(big.Int).SetInt64(1) -+ -+// randFieldElement returns a random element of the order of the given -+// curve using the procedure given in FIPS 186-4, Appendix B.5.2. -+func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) { -+ // See randomPoint for notes on the algorithm. This has to match, or s390x -+ // signatures will come out different from other architectures, which will -+ // break TLS recorded tests. -+ for { -+ N := c.Params().N -+ b := make([]byte, (N.BitLen()+7)/8) -+ if _, err = io.ReadFull(rand, b); err != nil { -+ return -+ } -+ if excess := len(b)*8 - N.BitLen(); excess > 0 { -+ b[0] >>= excess -+ } -+ k = new(big.Int).SetBytes(b) -+ if k.Sign() != 0 && k.Cmp(N) < 0 { -+ return -+ } -+ } -+} -diff --git a/src/crypto/ecdsa/ecdsa_noasm.go-e b/src/crypto/ecdsa/ecdsa_noasm.go-e -new file mode 100644 -index 0000000000..a72aa4b04e ---- /dev/null -+++ b/src/crypto/ecdsa/ecdsa_noasm.go-e -@@ -0,0 +1,17 @@ -+// Copyright 2020 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 !s390x -+ -+package ecdsa -+ -+import "io" -+ -+func verifyAsm(pub *PublicKey, hash []byte, sig []byte) error { -+ return errNoAsm -+} -+ -+func signAsm(priv *PrivateKey, csprng io.Reader, hash []byte) (sig []byte, err error) { -+ return nil, errNoAsm -+} -diff --git a/src/crypto/ecdsa/ecdsa_s390x.go-e b/src/crypto/ecdsa/ecdsa_s390x.go-e -new file mode 100644 -index 0000000000..49f645a489 ---- /dev/null -+++ b/src/crypto/ecdsa/ecdsa_s390x.go-e -@@ -0,0 +1,177 @@ -+// Copyright 2020 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. -+ -+package ecdsa -+ -+import ( -+ "crypto/elliptic" -+ "errors" -+ "internal/cpu" -+ "io" -+ "math/big" -+) -+ -+// kdsa invokes the "compute digital signature authentication" -+// instruction with the given function code and 4096 byte -+// parameter block. -+// -+// The return value corresponds to the condition code set by the -+// instruction. Interrupted invocations are handled by the -+// function. -+// -+//go:noescape -+func kdsa(fc uint64, params *[4096]byte) (errn uint64) -+ -+// testingDisableKDSA forces the generic fallback path. It must only be set in tests. -+var testingDisableKDSA bool -+ -+// canUseKDSA checks if KDSA instruction is available, and if it is, it checks -+// the name of the curve to see if it matches the curves supported(P-256, P-384, P-521). -+// Then, based on the curve name, a function code and a block size will be assigned. -+// If KDSA instruction is not available or if the curve is not supported, canUseKDSA -+// will set ok to false. -+func canUseKDSA(c elliptic.Curve) (functionCode uint64, blockSize int, ok bool) { -+ if testingDisableKDSA { -+ return 0, 0, false -+ } -+ if !cpu.S390X.HasECDSA { -+ return 0, 0, false -+ } -+ switch c.Params().Name { -+ case "P-256": -+ return 1, 32, true -+ case "P-384": -+ return 2, 48, true -+ case "P-521": -+ return 3, 80, true -+ } -+ return 0, 0, false // A mismatch -+} -+ -+func hashToBytes(dst, hash []byte, c elliptic.Curve) { -+ l := len(dst) -+ if n := c.Params().N.BitLen(); n == l*8 { -+ // allocation free path for curves with a length that is a whole number of bytes -+ if len(hash) >= l { -+ // truncate hash -+ copy(dst, hash[:l]) -+ return -+ } -+ // pad hash with leading zeros -+ p := l - len(hash) -+ for i := 0; i < p; i++ { -+ dst[i] = 0 -+ } -+ copy(dst[p:], hash) -+ return -+ } -+ // TODO(mundaym): avoid hashToInt call here -+ hashToInt(hash, c).FillBytes(dst) -+} -+ -+func signAsm(priv *PrivateKey, csprng io.Reader, hash []byte) (sig []byte, err error) { -+ c := priv.Curve -+ functionCode, blockSize, ok := canUseKDSA(c) -+ if !ok { -+ return nil, errNoAsm -+ } -+ for { -+ var k *big.Int -+ k, err = randFieldElement(c, csprng) -+ if err != nil { -+ return nil, err -+ } -+ -+ // The parameter block looks like the following for sign. -+ // +---------------------+ -+ // | Signature(R) | -+ // +---------------------+ -+ // | Signature(S) | -+ // +---------------------+ -+ // | Hashed Message | -+ // +---------------------+ -+ // | Private Key | -+ // +---------------------+ -+ // | Random Number | -+ // +---------------------+ -+ // | | -+ // | ... | -+ // | | -+ // +---------------------+ -+ // The common components(signatureR, signatureS, hashedMessage, privateKey and -+ // random number) each takes block size of bytes. The block size is different for -+ // different curves and is set by canUseKDSA function. -+ var params [4096]byte -+ -+ // Copy content into the parameter block. In the sign case, -+ // we copy hashed message, private key and random number into -+ // the parameter block. -+ hashToBytes(params[2*blockSize:3*blockSize], hash, c) -+ priv.D.FillBytes(params[3*blockSize : 4*blockSize]) -+ k.FillBytes(params[4*blockSize : 5*blockSize]) -+ // Convert verify function code into a sign function code by adding 8. -+ // We also need to set the 'deterministic' bit in the function code, by -+ // adding 128, in order to stop the instruction using its own random number -+ // generator in addition to the random number we supply. -+ switch kdsa(functionCode+136, ¶ms) { -+ case 0: // success -+ return encodeSignature(params[:blockSize], params[blockSize:2*blockSize]) -+ case 1: // error -+ return nil, errZeroParam -+ case 2: // retry -+ continue -+ } -+ panic("unreachable") -+ } -+} -+ -+func verifyAsm(pub *PublicKey, hash []byte, sig []byte) error { -+ c := pub.Curve -+ functionCode, blockSize, ok := canUseKDSA(c) -+ if !ok { -+ return errNoAsm -+ } -+ -+ r, s, err := parseSignature(sig) -+ if err != nil { -+ return err -+ } -+ if len(r) > blockSize || len(s) > blockSize { -+ return errors.New("invalid signature") -+ } -+ -+ // The parameter block looks like the following for verify: -+ // +---------------------+ -+ // | Signature(R) | -+ // +---------------------+ -+ // | Signature(S) | -+ // +---------------------+ -+ // | Hashed Message | -+ // +---------------------+ -+ // | Public Key X | -+ // +---------------------+ -+ // | Public Key Y | -+ // +---------------------+ -+ // | | -+ // | ... | -+ // | | -+ // +---------------------+ -+ // The common components(signatureR, signatureS, hashed message, public key X, -+ // and public key Y) each takes block size of bytes. The block size is different for -+ // different curves and is set by canUseKDSA function. -+ var params [4096]byte -+ -+ // Copy content into the parameter block. In the verify case, -+ // we copy signature (r), signature(s), hashed message, public key x component, -+ // and public key y component into the parameter block. -+ copy(params[0*blockSize+blockSize-len(r):], r) -+ copy(params[1*blockSize+blockSize-len(s):], s) -+ hashToBytes(params[2*blockSize:3*blockSize], hash, c) -+ pub.X.FillBytes(params[3*blockSize : 4*blockSize]) -+ pub.Y.FillBytes(params[4*blockSize : 5*blockSize]) -+ if kdsa(functionCode, ¶ms) != 0 { -+ return errors.New("invalid signature") -+ } -+ return nil -+} -diff --git a/src/crypto/ecdsa/ecdsa_s390x_test.go-e b/src/crypto/ecdsa/ecdsa_s390x_test.go-e -new file mode 100644 -index 0000000000..fd1dc7c060 ---- /dev/null -+++ b/src/crypto/ecdsa/ecdsa_s390x_test.go-e -@@ -0,0 +1,32 @@ -+// Copyright 2020 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 s390x -+ -+package ecdsa -+ -+import ( -+ "crypto/elliptic" -+ "testing" -+) -+ -+func TestNoAsm(t *testing.T) { -+ testingDisableKDSA = true -+ defer func() { testingDisableKDSA = false }() -+ -+ curves := [...]elliptic.Curve{ -+ elliptic.P256(), -+ elliptic.P384(), -+ elliptic.P521(), -+ } -+ -+ for _, curve := range curves { -+ name := curve.Params().Name -+ t.Run(name, func(t *testing.T) { testKeyGeneration(t, curve) }) -+ t.Run(name, func(t *testing.T) { testSignAndVerify(t, curve) }) -+ t.Run(name, func(t *testing.T) { testNonceSafety(t, curve) }) -+ t.Run(name, func(t *testing.T) { testINDCCA(t, curve) }) -+ t.Run(name, func(t *testing.T) { testNegativeInputs(t, curve) }) -+ } -+} ->>>>>>> 70a351c141 (wip) -======= ->>>>>>> 80d9391199 (wip) -diff --git a/src/crypto/ecdsa/ecdsa_test.go b/src/crypto/ecdsa/ecdsa_test.go -index 61a4662036..80e484842b 100644 ---- a/src/crypto/ecdsa/ecdsa_test.go -+++ b/src/crypto/ecdsa/ecdsa_test.go -@@ -10,7 +10,7 @@ import ( - "compress/bzip2" - "crypto/elliptic" - "crypto/internal/backend/boringtest" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/bigmod" - "crypto/rand" - "crypto/sha1" -@@ -38,7 +38,7 @@ func testAllCurves(t *testing.T, f func(*testing.T, elliptic.Curve)) { - } - if testing.Short() { - tests = tests[:1] -- } else if !boring.Enabled || boringtest.Supports(t, "CurveP224") { -+ } else if !boring.Enabled() || boringtest.Supports(t, "CurveP224") { - p224 := struct { - name string - curve elliptic.Curve -@@ -46,7 +46,7 @@ func testAllCurves(t *testing.T, f func(*testing.T, elliptic.Curve)) { - tests = append(tests, p224) + t.Skip("skipping allocations test with BoringCrypto") } - for _, test := range tests { -- if boring.Enabled && !boringtest.Supports(t, "Curve"+test.name) { -+ if boring.Enabled() && !boringtest.Supports(t, "Curve"+test.name) { - t.Skip("unsupported test in FIPS mode") - } - curve := test.curve -@@ -246,7 +246,7 @@ func TestVectors(t *testing.T) { -<<<<<<< HEAD - -======= + testenv.SkipIfOptimizationOff(t) +diff --git a/src/crypto/hmac/hmac.go b/src/crypto/hmac/hmac.go +index 35b9d5a17a..5697756a27 100644 +--- a/src/crypto/hmac/hmac.go ++++ b/src/crypto/hmac/hmac.go +@@ -22,7 +22,7 @@ timing side-channels: + package hmac ->>>>>>> 0023bf4c7a (rebase) - switch curve { - case "P-224": -- if !boring.Enabled || boringtest.Supports(t, "CurveP224") { -+ if !boring.Enabled() || boringtest.Supports(t, "CurveP224") { - pub.Curve = elliptic.P224() - } else { - pub.Curve = nil -diff --git a/src/crypto/ecdsa/equal_test.go b/src/crypto/ecdsa/equal_test.go -index 4371e31b1a..5ef62abe37 100644 ---- a/src/crypto/ecdsa/equal_test.go -+++ b/src/crypto/ecdsa/equal_test.go -@@ -10,7 +10,7 @@ import ( - "crypto/elliptic" - "crypto/rand" - "crypto/x509" + import ( - "crypto/internal/boring" + boring "crypto/internal/backend" - "crypto/internal/backend/boringtest" - "testing" - ) -@@ -71,7 +71,7 @@ func TestEqual(t *testing.T) { - if testing.Short() { - return - } -- if !boring.Enabled || boringtest.Supports(t, "CurveP224") { -+ if !boring.Enabled() || boringtest.Supports(t, "CurveP224") { - t.Run("P224", func(t *testing.T) { testEqual(t, elliptic.P224()) }) - } - t.Run("P384", func(t *testing.T) { testEqual(t, elliptic.P384()) }) -diff --git a/src/crypto/ecdsa/notboring.go b/src/crypto/ecdsa/notboring.go -index 039bd82ed2..21a35b760c 100644 ---- a/src/crypto/ecdsa/notboring.go -+++ b/src/crypto/ecdsa/notboring.go -@@ -2,15 +2,15 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -<<<<<<< HEAD - --//go:build !boringcrypto -+//go:build no_openssl - - package ecdsa - --import "crypto/internal/boring" -+import boring "crypto/internal/backend" - -======= - --//go:build !boringcrypto -+//go:build no_openssl - - package ecdsa - --import "crypto/internal/boring" -+import boring "crypto/internal/backend" - ->>>>>>> 0023bf4c7a (rebase) - func boringPublicKey(*PublicKey) (*boring.PublicKeyECDSA, error) { -- panic("boringcrypto: not available") -+ panic("!no_openssl: not available") - } - func boringPrivateKey(*PrivateKey) (*boring.PrivateKeyECDSA, error) { -- panic("boringcrypto: not available") -+ panic("!no_openssl: not available") - } -diff --git a/src/crypto/ed25519/ed25519_test.go b/src/crypto/ed25519/ed25519_test.go -index 8b5c2cc9af..ebbb1c0c07 100644 ---- a/src/crypto/ed25519/ed25519_test.go -+++ b/src/crypto/ed25519/ed25519_test.go -@@ -9,7 +9,7 @@ import ( - "bytes" - "compress/gzip" - "crypto" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/rand" - "crypto/sha512" - "encoding/hex" -@@ -322,7 +322,7 @@ func TestMalleability(t *testing.T) { -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - func TestAllocations(t *testing.T) { - t.Skip("Allocations test broken with openssl linkage") -- if boring.Enabled { -+ if boring.Enabled() { - t.Skip("skipping allocations test with BoringCrypto") - } - testenv.SkipIfOptimizationOff(t) -diff --git a/src/crypto/hmac/hmac.go b/src/crypto/hmac/hmac.go -index 35b9d5a17a..5697756a27 100644 ---- a/src/crypto/hmac/hmac.go -+++ b/src/crypto/hmac/hmac.go -@@ -22,7 +22,7 @@ timing side-channels: - package hmac -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - import ( -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/subtle" - "hash" + "crypto/subtle" + "hash" ) @@ -127,7 +127,7 @@ func (h *hmac) Reset() { // the returned Hash does not implement encoding.BinaryMarshaler @@ -3674,11 +431,7 @@ index 55415abf02..0edd7a6003 100644 --- a/src/crypto/hmac/hmac_test.go +++ b/src/crypto/hmac/hmac_test.go @@ -6,7 +6,7 @@ package hmac -<<<<<<< HEAD - -======= ->>>>>>> 0023bf4c7a (rebase) import ( "bytes" - "crypto/internal/boring" @@ -3688,11 +441,7 @@ index 55415abf02..0edd7a6003 100644 "crypto/sha256" @@ -584,8 +584,8 @@ func TestHMAC(t *testing.T) { } -<<<<<<< HEAD - -======= ->>>>>>> 0023bf4c7a (rebase) func TestNonUniqueHash(t *testing.T) { - if boring.Enabled { - t.Skip("hash.Hash provided by boringcrypto are not comparable") @@ -4092,48 +841,6 @@ index 6fae1d54f8..0000000000 - } - return anyOverlap(x, y) -} -<<<<<<< HEAD -diff --git a/src/crypto/internal/boring/bbig/big.go b/src/crypto/internal/boring/bbig/big.go -deleted file mode 100644 -index 5ce46972b3..0000000000 ---- a/src/crypto/internal/boring/bbig/big.go -+++ /dev/null -@@ -1,33 +0,0 @@ --// Copyright 2022 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. -- --package bbig -- --import ( -- "crypto/internal/boring" -- "math/big" -- "unsafe" --) -- --func Enc(b *big.Int) boring.BigInt { -- if b == nil { -- return nil -- } -- x := b.Bits() -- if len(x) == 0 { -- return boring.BigInt{} -- } -- return unsafe.Slice((*uint)(&x[0]), len(x)) --} -- --func Dec(b boring.BigInt) *big.Int { -- if b == nil { -- return nil -- } -- if len(b) == 0 { -- return new(big.Int) -- } -- x := unsafe.Slice((*big.Word)(&b[0]), len(b)) -- return new(big.Int).SetBits(x) --} -======= ->>>>>>> 0023bf4c7a (rebase) diff --git a/src/crypto/internal/boring/boring.go b/src/crypto/internal/boring/boring.go deleted file mode 100644 index 102380a839..0000000000 @@ -4307,22 +1014,6 @@ index 83bbbd3404..0000000000 - UnreachableExceptTests() -} diff --git a/src/crypto/internal/boring/doc.go b/src/crypto/internal/boring/doc.go -<<<<<<< HEAD -deleted file mode 100644 -index 6060fe5951..0000000000 ---- a/src/crypto/internal/boring/doc.go -+++ /dev/null -@@ -1,19 +0,0 @@ --// 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. -- --// Package boring provides access to BoringCrypto implementation functions. --// Check the constant Enabled to find out whether BoringCrypto is available. --// If BoringCrypto is not available, the functions in this package all panic. --package boring -- -======= index 6060fe5951..ca24813149 100644 --- a/src/crypto/internal/boring/doc.go +++ b/src/crypto/internal/boring/doc.go @@ -4330,19 +1021,11 @@ index 6060fe5951..ca24813149 100644 // If BoringCrypto is not available, the functions in this package all panic. package boring ->>>>>>> 0023bf4c7a (rebase) -// Enabled reports whether BoringCrypto is available. -// When enabled is false, all functions in this package panic. -// -// BoringCrypto is only available on linux/amd64 systems. -const Enabled = available -<<<<<<< HEAD -- --// A BigInt is the raw words from a BigInt. --// This definition allows us to avoid importing math/big. --// Conversion between BigInt and *big.Int is in crypto/internal/boring/bbig. --type BigInt []uint -======= +import "github.com/golang-fips/openssl/v2" // A BigInt is the raw words from a BigInt. @@ -4351,7 +1034,6 @@ index 6060fe5951..ca24813149 100644 -type BigInt []uint +type BigInt = openssl.BigInt + ->>>>>>> 0023bf4c7a (rebase) diff --git a/src/crypto/internal/boring/ecdh.go b/src/crypto/internal/boring/ecdh.go deleted file mode 100644 index 8f46d8146f..0000000000 @@ -4582,8 +1264,6 @@ index 8f46d8146f..0000000000 - runtime.SetFinalizer(k, (*PrivateKeyECDH).finalize) - return k, bytes, nil -} -<<<<<<< HEAD -======= diff --git a/src/crypto/internal/boring/ecdsa.go b/src/crypto/internal/boring/ecdsa.go deleted file mode 100644 index e15f3682c7..0000000000 @@ -4762,7 +1442,6 @@ index e15f3682c7..0000000000 - } - return bnToBig(bx), bnToBig(by), bnToBig(bd), nil -} ->>>>>>> 0023bf4c7a (rebase) diff --git a/src/crypto/internal/boring/fipstls/stub.s b/src/crypto/internal/boring/fipstls/stub.s index f2e5a503ea..65918a480e 100644 --- a/src/crypto/internal/boring/fipstls/stub.s @@ -4770,17 +1449,10 @@ index f2e5a503ea..65918a480e 100644 @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -<<<<<<< HEAD - --//go:build boringcrypto -+//go:build !no_openssl - -======= -//go:build boringcrypto +//go:build !no_openssl ->>>>>>> 0023bf4c7a (rebase) // runtime_arg0 is declared in tls.go without a body. // It's provided by package runtime, diff --git a/src/crypto/internal/boring/fipstls/tls.go b/src/crypto/internal/boring/fipstls/tls.go @@ -4790,25 +1462,15 @@ index 3bf1471fb0..d6c5ca736d 100644 @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -<<<<<<< HEAD - --//go:build boringcrypto -+//go:build !no_openssl - -======= -//go:build boringcrypto +//go:build !no_openssl ->>>>>>> 0023bf4c7a (rebase) // Package fipstls allows control over whether crypto/tls requires FIPS-approved settings. -// This package only exists with GOEXPERIMENT=boringcrypto, but the effects are independent +// This package only exists with GOEXPERIMENT=!no_openssl, but the effects are independent // of the use of BoringCrypto. package fipstls -<<<<<<< HEAD - -======= diff --git a/src/crypto/internal/boring/hmac.go b/src/crypto/internal/boring/hmac.go deleted file mode 100644 @@ -6117,26298 +2779,2366 @@ index cf82f3f64f..0000000000 - x[2] = byte(s >> 8) - x[3] = byte(s) -} -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 0023bf4c7a (rebase) -======= -diff --git a/src/crypto/md5/example_test.go-e b/src/crypto/md5/example_test.go-e -new file mode 100644 -index 0000000000..af8c1bfd65 ---- /dev/null -+++ b/src/crypto/md5/example_test.go-e -@@ -0,0 +1,42 @@ -+// Copyright 2013 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. -+ -+package md5_test -+ -+import ( -+ "crypto/md5" -+ "fmt" -+ "io" -+ "log" -+ "os" -+) -+ -+func ExampleNew() { -+ h := md5.New() -+ io.WriteString(h, "The fog is getting thicker!") -+ io.WriteString(h, "And Leon's getting laaarger!") -+ fmt.Printf("%x", h.Sum(nil)) -+ // Output: e2c569be17396eca2a2e3c11578123ed -+} -+ -+func ExampleSum() { -+ data := []byte("These pretzels are making me thirsty.") -+ fmt.Printf("%x", md5.Sum(data)) -+ // Output: b0804ec967f48520697662a204f5fe72 -+} -+ -+func ExampleNew_file() { -+ f, err := os.Open("file.txt") -+ if err != nil { -+ log.Fatal(err) -+ } -+ defer f.Close() -+ -+ h := md5.New() -+ if _, err := io.Copy(h, f); err != nil { -+ log.Fatal(err) -+ } -+ -+ fmt.Printf("%x", h.Sum(nil)) -+} -diff --git a/src/crypto/md5/gen.go-e b/src/crypto/md5/gen.go-e -new file mode 100644 -index 0000000000..cd2700a5cf ---- /dev/null -+++ b/src/crypto/md5/gen.go-e -@@ -0,0 +1,259 @@ -+// Copyright 2012 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 ignore -+ -+// This program generates md5block.go -+// Invoke as -+// -+// go run gen.go -output md5block.go -+ -+package main -+ -+import ( -+ "bytes" -+ "flag" -+ "go/format" -+ "log" -+ "os" -+ "strings" -+ "text/template" -+) -+ -+var filename = flag.String("output", "md5block.go", "output file name") -+ -+func main() { -+ flag.Parse() -+ -+ var buf bytes.Buffer -+ -+ t := template.Must(template.New("main").Funcs(funcs).Parse(program)) -+ if err := t.Execute(&buf, data); err != nil { -+ log.Fatal(err) -+ } -+ -+ data, err := format.Source(buf.Bytes()) -+ if err != nil { -+ log.Fatal(err) -+ } -+ err = os.WriteFile(*filename, data, 0644) -+ if err != nil { -+ log.Fatal(err) -+ } -+} -+ -+type Data struct { -+ a, b, c, d string -+ Shift1 []int -+ Shift2 []int -+ Shift3 []int -+ Shift4 []int -+ Table1 []uint32 -+ Table2 []uint32 -+ Table3 []uint32 -+ Table4 []uint32 -+} -+ -+var funcs = template.FuncMap{ -+ "dup": dup, -+ "relabel": relabel, -+ "rotate": rotate, -+ "idx": idx, -+ "seq": seq, -+} -+ -+func dup(count int, x []int) []int { -+ var out []int -+ for i := 0; i < count; i++ { -+ out = append(out, x...) -+ } -+ return out -+} -+ -+func relabel(s string) string { -+ return strings.NewReplacer("arg0", data.a, "arg1", data.b, "arg2", data.c, "arg3", data.d).Replace(s) -+} -+ -+func rotate() string { -+ data.a, data.b, data.c, data.d = data.d, data.a, data.b, data.c -+ return "" // no output -+} -+ -+func idx(round, index int) int { -+ v := 0 -+ switch round { -+ case 1: -+ v = index -+ case 2: -+ v = (1 + 5*index) & 15 -+ case 3: -+ v = (5 + 3*index) & 15 -+ case 4: -+ v = (7 * index) & 15 -+ } -+ return v -+} -+ -+func seq(i int) []int { -+ s := make([]int, i) -+ for i := range s { -+ s[i] = i -+ } -+ return s -+} -+ -+var data = Data{ -+ a: "a", -+ b: "b", -+ c: "c", -+ d: "d", -+ Shift1: []int{7, 12, 17, 22}, -+ Shift2: []int{5, 9, 14, 20}, -+ Shift3: []int{4, 11, 16, 23}, -+ Shift4: []int{6, 10, 15, 21}, -+ -+ // table[i] = int((1<<32) * abs(sin(i+1 radians))). -+ Table1: []uint32{ -+ // round 1 -+ 0xd76aa478, -+ 0xe8c7b756, -+ 0x242070db, -+ 0xc1bdceee, -+ 0xf57c0faf, -+ 0x4787c62a, -+ 0xa8304613, -+ 0xfd469501, -+ 0x698098d8, -+ 0x8b44f7af, -+ 0xffff5bb1, -+ 0x895cd7be, -+ 0x6b901122, -+ 0xfd987193, -+ 0xa679438e, -+ 0x49b40821, -+ }, -+ Table2: []uint32{ -+ // round 2 -+ 0xf61e2562, -+ 0xc040b340, -+ 0x265e5a51, -+ 0xe9b6c7aa, -+ 0xd62f105d, -+ 0x2441453, -+ 0xd8a1e681, -+ 0xe7d3fbc8, -+ 0x21e1cde6, -+ 0xc33707d6, -+ 0xf4d50d87, -+ 0x455a14ed, -+ 0xa9e3e905, -+ 0xfcefa3f8, -+ 0x676f02d9, -+ 0x8d2a4c8a, -+ }, -+ Table3: []uint32{ -+ // round3 -+ 0xfffa3942, -+ 0x8771f681, -+ 0x6d9d6122, -+ 0xfde5380c, -+ 0xa4beea44, -+ 0x4bdecfa9, -+ 0xf6bb4b60, -+ 0xbebfbc70, -+ 0x289b7ec6, -+ 0xeaa127fa, -+ 0xd4ef3085, -+ 0x4881d05, -+ 0xd9d4d039, -+ 0xe6db99e5, -+ 0x1fa27cf8, -+ 0xc4ac5665, -+ }, -+ Table4: []uint32{ -+ // round 4 -+ 0xf4292244, -+ 0x432aff97, -+ 0xab9423a7, -+ 0xfc93a039, -+ 0x655b59c3, -+ 0x8f0ccc92, -+ 0xffeff47d, -+ 0x85845dd1, -+ 0x6fa87e4f, -+ 0xfe2ce6e0, -+ 0xa3014314, -+ 0x4e0811a1, -+ 0xf7537e82, -+ 0xbd3af235, -+ 0x2ad7d2bb, -+ 0xeb86d391, -+ }, -+} -+ -+var program = `// Copyright 2013 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. -+ -+// Code generated by go run gen.go -output md5block.go; DO NOT EDIT. -+ -+package md5 -+ -+import ( -+ "encoding/binary" -+ "math/bits" -+) -+ -+func blockGeneric(dig *digest, p []byte) { -+ // load state -+ a, b, c, d := dig.s[0], dig.s[1], dig.s[2], dig.s[3] -+ -+ for i := 0; i <= len(p)-BlockSize; i += BlockSize { -+ // eliminate bounds checks on p -+ q := p[i:] -+ q = q[:BlockSize:BlockSize] -+ -+ // save current state -+ aa, bb, cc, dd := a, b, c, d -+ -+ // load input block -+ {{range $i := seq 16 -}} -+ {{printf "x%x := binary.LittleEndian.Uint32(q[4*%#x:])" $i $i}} -+ {{end}} -+ -+ // round 1 -+ {{range $i, $s := dup 4 .Shift1 -}} -+ {{printf "arg0 = arg1 + bits.RotateLeft32((((arg2^arg3)&arg1)^arg3)+arg0+x%x+%#08x, %d)" (idx 1 $i) (index $.Table1 $i) $s | relabel}} -+ {{rotate -}} -+ {{end}} -+ -+ // round 2 -+ {{range $i, $s := dup 4 .Shift2 -}} -+ {{printf "arg0 = arg1 + bits.RotateLeft32((((arg1^arg2)&arg3)^arg2)+arg0+x%x+%#08x, %d)" (idx 2 $i) (index $.Table2 $i) $s | relabel}} -+ {{rotate -}} -+ {{end}} -+ -+ // round 3 -+ {{range $i, $s := dup 4 .Shift3 -}} -+ {{printf "arg0 = arg1 + bits.RotateLeft32((arg1^arg2^arg3)+arg0+x%x+%#08x, %d)" (idx 3 $i) (index $.Table3 $i) $s | relabel}} -+ {{rotate -}} -+ {{end}} -+ -+ // round 4 -+ {{range $i, $s := dup 4 .Shift4 -}} -+ {{printf "arg0 = arg1 + bits.RotateLeft32((arg2^(arg1|^arg3))+arg0+x%x+%#08x, %d)" (idx 4 $i) (index $.Table4 $i) $s | relabel}} -+ {{rotate -}} -+ {{end}} -+ -+ // add saved state -+ a += aa -+ b += bb -+ c += cc -+ d += dd -+ } -+ -+ // save state -+ dig.s[0], dig.s[1], dig.s[2], dig.s[3] = a, b, c, d -+} -+` -diff --git a/src/crypto/md5/md5.go-e b/src/crypto/md5/md5.go-e -new file mode 100644 -index 0000000000..ccee4ea3a9 ---- /dev/null -+++ b/src/crypto/md5/md5.go-e -@@ -0,0 +1,183 @@ -+// Copyright 2009 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:generate go run gen.go -output md5block.go -+ -+// Package md5 implements the MD5 hash algorithm as defined in RFC 1321. -+// -+// MD5 is cryptographically broken and should not be used for secure -+// applications. -+package md5 -+ -+import ( -+ "crypto" -+ "encoding/binary" -+ "errors" -+ "hash" -+) -+ -+func init() { -+ crypto.RegisterHash(crypto.MD5, New) -+} -+ -+// The size of an MD5 checksum in bytes. -+const Size = 16 -+ -+// The blocksize of MD5 in bytes. -+const BlockSize = 64 -+ -+const ( -+ init0 = 0x67452301 -+ init1 = 0xEFCDAB89 -+ init2 = 0x98BADCFE -+ init3 = 0x10325476 -+) -+ -+// digest represents the partial evaluation of a checksum. -+type digest struct { -+ s [4]uint32 -+ x [BlockSize]byte -+ nx int -+ len uint64 -+} -+ -+func (d *digest) Reset() { -+ d.s[0] = init0 -+ d.s[1] = init1 -+ d.s[2] = init2 -+ d.s[3] = init3 -+ d.nx = 0 -+ d.len = 0 -+} -+ -+const ( -+ magic = "md5\x01" -+ marshaledSize = len(magic) + 4*4 + BlockSize + 8 -+) -+ -+func (d *digest) MarshalBinary() ([]byte, error) { -+ b := make([]byte, 0, marshaledSize) -+ b = append(b, magic...) -+ b = binary.BigEndian.AppendUint32(b, d.s[0]) -+ b = binary.BigEndian.AppendUint32(b, d.s[1]) -+ b = binary.BigEndian.AppendUint32(b, d.s[2]) -+ b = binary.BigEndian.AppendUint32(b, d.s[3]) -+ b = append(b, d.x[:d.nx]...) -+ b = b[:len(b)+len(d.x)-d.nx] // already zero -+ b = binary.BigEndian.AppendUint64(b, d.len) -+ return b, nil -+} -+ -+func (d *digest) UnmarshalBinary(b []byte) error { -+ if len(b) < len(magic) || string(b[:len(magic)]) != magic { -+ return errors.New("crypto/md5: invalid hash state identifier") -+ } -+ if len(b) != marshaledSize { -+ return errors.New("crypto/md5: invalid hash state size") -+ } -+ b = b[len(magic):] -+ b, d.s[0] = consumeUint32(b) -+ b, d.s[1] = consumeUint32(b) -+ b, d.s[2] = consumeUint32(b) -+ b, d.s[3] = consumeUint32(b) -+ b = b[copy(d.x[:], b):] -+ b, d.len = consumeUint64(b) -+ d.nx = int(d.len % BlockSize) -+ return nil -+} -+ -+func consumeUint64(b []byte) ([]byte, uint64) { -+ return b[8:], binary.BigEndian.Uint64(b[0:8]) -+} -+ -+func consumeUint32(b []byte) ([]byte, uint32) { -+ return b[4:], binary.BigEndian.Uint32(b[0:4]) -+} -+ -+// New returns a new hash.Hash computing the MD5 checksum. The Hash also -+// implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to -+// marshal and unmarshal the internal state of the hash. -+func New() hash.Hash { -+ d := new(digest) -+ d.Reset() -+ return d -+} -+ -+func (d *digest) Size() int { return Size } -+ -+func (d *digest) BlockSize() int { return BlockSize } -+ -+func (d *digest) Write(p []byte) (nn int, err error) { -+ // Note that we currently call block or blockGeneric -+ // directly (guarded using haveAsm) because this allows -+ // escape analysis to see that p and d don't escape. -+ nn = len(p) -+ d.len += uint64(nn) -+ if d.nx > 0 { -+ n := copy(d.x[d.nx:], p) -+ d.nx += n -+ if d.nx == BlockSize { -+ if haveAsm { -+ block(d, d.x[:]) -+ } else { -+ blockGeneric(d, d.x[:]) -+ } -+ d.nx = 0 -+ } -+ p = p[n:] -+ } -+ if len(p) >= BlockSize { -+ n := len(p) &^ (BlockSize - 1) -+ if haveAsm { -+ block(d, p[:n]) -+ } else { -+ blockGeneric(d, p[:n]) -+ } -+ p = p[n:] -+ } -+ if len(p) > 0 { -+ d.nx = copy(d.x[:], p) -+ } -+ return -+} -+ -+func (d *digest) Sum(in []byte) []byte { -+ // Make a copy of d so that caller can keep writing and summing. -+ d0 := *d -+ hash := d0.checkSum() -+ return append(in, hash[:]...) -+} -+ -+func (d *digest) checkSum() [Size]byte { -+ // Append 0x80 to the end of the message and then append zeros -+ // until the length is a multiple of 56 bytes. Finally append -+ // 8 bytes representing the message length in bits. -+ // -+ // 1 byte end marker :: 0-63 padding bytes :: 8 byte length -+ tmp := [1 + 63 + 8]byte{0x80} -+ pad := (55 - d.len) % 64 // calculate number of padding bytes -+ binary.LittleEndian.PutUint64(tmp[1+pad:], d.len<<3) // append length in bits -+ d.Write(tmp[:1+pad+8]) -+ -+ // The previous write ensures that a whole number of -+ // blocks (i.e. a multiple of 64 bytes) have been hashed. -+ if d.nx != 0 { -+ panic("d.nx != 0") -+ } -+ -+ var digest [Size]byte -+ binary.LittleEndian.PutUint32(digest[0:], d.s[0]) -+ binary.LittleEndian.PutUint32(digest[4:], d.s[1]) -+ binary.LittleEndian.PutUint32(digest[8:], d.s[2]) -+ binary.LittleEndian.PutUint32(digest[12:], d.s[3]) -+ return digest -+} -+ -+// Sum returns the MD5 checksum of the data. -+func Sum(data []byte) [Size]byte { -+ var d digest -+ d.Reset() -+ d.Write(data) -+ return d.checkSum() -+} -diff --git a/src/crypto/md5/md5_test.go-e b/src/crypto/md5/md5_test.go-e -new file mode 100644 -index 0000000000..851e7fb10d ---- /dev/null -+++ b/src/crypto/md5/md5_test.go-e -@@ -0,0 +1,294 @@ -+// Copyright 2009 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. -+ -+package md5 -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "encoding" -+ "fmt" -+ "hash" -+ "io" -+ "testing" -+ "unsafe" -+) -+ -+type md5Test struct { -+ out string -+ in string -+ halfState string // marshaled hash state after first half of in written, used by TestGoldenMarshal -+} -+ -+var golden = []md5Test{ -+ {"d41d8cd98f00b204e9800998ecf8427e", "", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tv\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}, -+ {"0cc175b9c0f1b6a831c399e269772661", "a", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tv\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"}, -+ {"187ef4436122d1cc2f40dc2b92f0eba0", "ab", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tva\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"}, -+ {"900150983cd24fb0d6963f7d28e17f72", "abc", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tva\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"}, -+ {"e2fc714c4727ee9395f324cd2e7f331f", "abcd", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"}, -+ {"ab56b4d92b40713acc5af89985d4b786", "abcde", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvab\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"}, -+ {"e80b5017098950fc58aad83c8c14978e", "abcdef", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvabc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03"}, -+ {"7ac66c0f148de9519b8bd264312c4d64", "abcdefg", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvabc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03"}, -+ {"e8dc4081b13434b45189a720b77b6818", "abcdefgh", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvabcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04"}, -+ {"8aa99b1f439ff71293e95357bac6fd94", "abcdefghi", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvabcd\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04"}, -+ {"a925576942e94b2ef57a066101b48876", "abcdefghij", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvabcde\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05"}, -+ {"d747fc1719c7eacb84058196cfe56d57", "Discard medicine more than two years old.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvDiscard medicine mor\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14"}, -+ {"bff2dcb37ef3a44ba43ab144768ca837", "He who has a shady past knows that nice guys finish last.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvHe who has a shady past know\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"}, -+ {"0441015ecb54a7342d017ed1bcfdbea5", "I wouldn't marry him with a ten foot pole.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvI wouldn't marry him \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x15"}, -+ {"9e3cac8e9e9757a60c3ea391130d3689", "Free! Free!/A trip/to Mars/for 900/empty jars/Burma Shave", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvFree! Free!/A trip/to Mars/f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"}, -+ {"a0f04459b031f916a59a35cc482dc039", "The days of the digital watch are numbered. -Tom Stoppard", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvThe days of the digital watch\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1d"}, -+ {"e7a48e0fe884faf31475d2a04b1362cc", "Nepal premier won't resign.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvNepal premier\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\r"}, -+ {"637d2fe925c07c113800509964fb0e06", "For every action there is an equal and opposite government program.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvFor every action there is an equa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!"}, -+ {"834a8d18d5c6562119cf4c7f5086cb71", "His money is twice tainted: 'taint yours and 'taint mine.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvHis money is twice tainted: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"}, -+ {"de3a4d2fd6c73ec2db2abad23b444281", "There is no reason for any individual to have a computer in their home. -Ken Olsen, 1977", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvThere is no reason for any individual to hav\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,"}, -+ {"acf203f997e2cf74ea3aff86985aefaf", "It's a tiny change to the code and not completely disgusting. - Bob Manchek", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvIt's a tiny change to the code and no\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%"}, -+ {"e1c1384cb4d2221dfdd7c795a4222c9a", "size: a.out: bad magic", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102Tvsize: a.out\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\f"}, -+ {"c90f3ddecc54f34228c063d7525bf644", "The major problem is with sendmail. -Mark Horton", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvThe major problem is wit\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18"}, -+ {"cdf7ab6c1fd49bd9933c43f3ea5af185", "Give me a rock, paper and scissors and I will move the world. CCFestoon", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvGive me a rock, paper and scissors a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$"}, -+ {"83bc85234942fc883c063cbd7f0ad5d0", "If the enemy is within range, then so are you.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvIf the enemy is within \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17"}, -+ {"277cbe255686b48dd7e8f389394d9299", "It's well we cannot hear the screams/That we create in others' dreams.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvIt's well we cannot hear the scream\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00#"}, -+ {"fd3fb0a7ffb8af16603f3d3af98f8e1f", "You remind me of a TV show, but that's all right: I watch it anyway.", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvYou remind me of a TV show, but th\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\""}, -+ {"469b13a78ebf297ecda64d4723655154", "C is as portable as Stonehedge!!", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvC is as portable\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10"}, -+ {"63eb3a2f466410104731c4b037600110", "Even if I could be Shakespeare, I think I should still choose to be Faraday. - A. Huxley", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvEven if I could be Shakespeare, I think I sh\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,"}, -+ {"72c2ed7592debca1c90fc0100f931a2f", "The fugacity of a constituent in a mixture of gases at a given temperature is proportional to its mole fraction. Lewis-Randall Rule", "md5\x01\xa7\xc9\x18\x9b\xc3E\x18\xf2\x82\xfd\xf3$\x9d_\v\nem\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00B"}, -+ {"132f7619d33b523b1d9e5bd8e0928355", "How can you write a big system without C++? -Paul Glick", "md5\x01gE#\x01\xefͫ\x89\x98\xba\xdc\xfe\x102TvHow can you write a big syst\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c"}, -+} -+ -+func TestGolden(t *testing.T) { -+ for i := 0; i < len(golden); i++ { -+ g := golden[i] -+ s := fmt.Sprintf("%x", Sum([]byte(g.in))) -+ if s != g.out { -+ t.Fatalf("Sum function: md5(%s) = %s want %s", g.in, s, g.out) -+ } -+ c := New() -+ buf := make([]byte, len(g.in)+4) -+ for j := 0; j < 3+4; j++ { -+ if j < 2 { -+ io.WriteString(c, g.in) -+ } else if j == 2 { -+ io.WriteString(c, g.in[0:len(g.in)/2]) -+ c.Sum(nil) -+ io.WriteString(c, g.in[len(g.in)/2:]) -+ } else if j > 2 { -+ // test unaligned write -+ buf = buf[1:] -+ copy(buf, g.in) -+ c.Write(buf[:len(g.in)]) -+ } -+ s := fmt.Sprintf("%x", c.Sum(nil)) -+ if s != g.out { -+ t.Fatalf("md5[%d](%s) = %s want %s", j, g.in, s, g.out) -+ } -+ c.Reset() -+ } -+ } -+} -+ -+func TestGoldenMarshal(t *testing.T) { -+ for _, g := range golden { -+ h := New() -+ h2 := New() -+ -+ io.WriteString(h, g.in[:len(g.in)/2]) -+ -+ state, err := h.(encoding.BinaryMarshaler).MarshalBinary() -+ if err != nil { -+ t.Errorf("could not marshal: %v", err) -+ continue -+ } -+ -+ if string(state) != g.halfState { -+ t.Errorf("md5(%q) state = %q, want %q", g.in, state, g.halfState) -+ continue -+ } -+ -+ if err := h2.(encoding.BinaryUnmarshaler).UnmarshalBinary(state); err != nil { -+ t.Errorf("could not unmarshal: %v", err) -+ continue -+ } -+ -+ io.WriteString(h, g.in[len(g.in)/2:]) -+ io.WriteString(h2, g.in[len(g.in)/2:]) -+ -+ if actual, actual2 := h.Sum(nil), h2.Sum(nil); !bytes.Equal(actual, actual2) { -+ t.Errorf("md5(%q) = 0x%x != marshaled 0x%x", g.in, actual, actual2) -+ } -+ } -+} -+ -+func TestLarge(t *testing.T) { -+ const N = 10000 -+ ok := "2bb571599a4180e1d542f76904adc3df" // md5sum of "0123456789" * 1000 -+ block := make([]byte, 10004) -+ c := New() -+ for offset := 0; offset < 4; offset++ { -+ for i := 0; i < N; i++ { -+ block[offset+i] = '0' + byte(i%10) -+ } -+ for blockSize := 10; blockSize <= N; blockSize *= 10 { -+ blocks := N / blockSize -+ b := block[offset : offset+blockSize] -+ c.Reset() -+ for i := 0; i < blocks; i++ { -+ c.Write(b) -+ } -+ s := fmt.Sprintf("%x", c.Sum(nil)) -+ if s != ok { -+ t.Fatalf("md5 TestLarge offset=%d, blockSize=%d = %s want %s", offset, blockSize, s, ok) -+ } -+ } -+ } -+} -+ -+// Tests that blockGeneric (pure Go) and block (in assembly for amd64, 386, arm) match. -+func TestBlockGeneric(t *testing.T) { -+ gen, asm := New().(*digest), New().(*digest) -+ buf := make([]byte, BlockSize*20) // arbitrary factor -+ rand.Read(buf) -+ blockGeneric(gen, buf) -+ block(asm, buf) -+ if *gen != *asm { -+ t.Error("block and blockGeneric resulted in different states") -+ } -+} -+ -+// Tests for unmarshaling hashes that have hashed a large amount of data -+// The initial hash generation is omitted from the test, because it takes a long time. -+// The test contains some already-generated states, and their expected sums -+// Tests a problem that is outlined in GitHub issue #29541 -+// The problem is triggered when an amount of data has been hashed for which -+// the data length has a 1 in the 32nd bit. When casted to int, this changes -+// the sign of the value, and causes the modulus operation to return a -+// different result. -+type unmarshalTest struct { -+ state string -+ sum string -+} -+ -+var largeUnmarshalTests = []unmarshalTest{ -+ // Data length: 7_102_415_735 -+ { -+ state: "md5\x01\xa5\xf7\xf0=\xd6S\x85\xd9M\n}\xc3\u0601\x89\xe7@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuv\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xa7VCw", -+ sum: "cddefcf74ffec709a0b45a6a987564d5", -+ }, -+ // Data length: 6_565_544_823 -+ { -+ state: "md5\x01{\xda\x1a\xc7\xc9'?\x83EX\xe0\x88q\xfeG\x18@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuv\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x87VCw", -+ sum: "fd9f41874ab240698e7bc9c3ae70c8e4", -+ }, -+} -+ -+func safeSum(h hash.Hash) (sum []byte, err error) { -+ defer func() { -+ if r := recover(); r != nil { -+ err = fmt.Errorf("sum panic: %v", r) -+ } -+ }() -+ -+ return h.Sum(nil), nil -+} -+ -+func TestLargeHashes(t *testing.T) { -+ for i, test := range largeUnmarshalTests { -+ -+ h := New() -+ if err := h.(encoding.BinaryUnmarshaler).UnmarshalBinary([]byte(test.state)); err != nil { -+ t.Errorf("test %d could not unmarshal: %v", i, err) -+ continue -+ } -+ -+ sum, err := safeSum(h) -+ if err != nil { -+ t.Errorf("test %d could not sum: %v", i, err) -+ continue -+ } -+ -+ if fmt.Sprintf("%x", sum) != test.sum { -+ t.Errorf("test %d sum mismatch: expect %s got %x", i, test.sum, sum) -+ } -+ } -+} -+ -+func TestAllocations(t *testing.T) { -+ in := []byte("hello, world!") -+ out := make([]byte, 0, Size) -+ h := New() -+ n := int(testing.AllocsPerRun(10, func() { -+ h.Reset() -+ h.Write(in) -+ out = h.Sum(out[:0]) -+ })) -+ if n > 0 { -+ t.Errorf("allocs = %d, want 0", n) -+ } -+} -+ -+var bench = New() -+var buf = make([]byte, 1024*1024*8+1) -+var sum = make([]byte, bench.Size()) -+ -+func benchmarkSize(b *testing.B, size int, unaligned bool) { -+ b.SetBytes(int64(size)) -+ buf := buf -+ if unaligned { -+ if uintptr(unsafe.Pointer(&buf[0]))&(unsafe.Alignof(uint32(0))-1) == 0 { -+ buf = buf[1:] -+ } -+ } -+ b.ResetTimer() -+ for i := 0; i < b.N; i++ { -+ bench.Reset() -+ bench.Write(buf[:size]) -+ bench.Sum(sum[:0]) -+ } -+} -+ -+func BenchmarkHash8Bytes(b *testing.B) { -+ benchmarkSize(b, 8, false) -+} -+ -+func BenchmarkHash64(b *testing.B) { -+ benchmarkSize(b, 64, false) -+} -+ -+func BenchmarkHash128(b *testing.B) { -+ benchmarkSize(b, 128, false) -+} -+ -+func BenchmarkHash256(b *testing.B) { -+ benchmarkSize(b, 256, false) -+} -+ -+func BenchmarkHash512(b *testing.B) { -+ benchmarkSize(b, 512, false) -+} -+ -+func BenchmarkHash1K(b *testing.B) { -+ benchmarkSize(b, 1024, false) -+} -+ -+func BenchmarkHash8K(b *testing.B) { -+ benchmarkSize(b, 8192, false) -+} -+ -+func BenchmarkHash1M(b *testing.B) { -+ benchmarkSize(b, 1024*1024, false) -+} -+ -+func BenchmarkHash8M(b *testing.B) { -+ benchmarkSize(b, 8*1024*1024, false) -+} -+ -+func BenchmarkHash8BytesUnaligned(b *testing.B) { -+ benchmarkSize(b, 8, true) -+} -+ -+func BenchmarkHash1KUnaligned(b *testing.B) { -+ benchmarkSize(b, 1024, true) -+} -+ -+func BenchmarkHash8KUnaligned(b *testing.B) { -+ benchmarkSize(b, 8192, true) -+} -diff --git a/src/crypto/md5/md5block.go-e b/src/crypto/md5/md5block.go-e -new file mode 100644 -index 0000000000..4ff289e860 ---- /dev/null -+++ b/src/crypto/md5/md5block.go-e -@@ -0,0 +1,125 @@ -+// Copyright 2013 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. -+ -+// Code generated by go run gen.go -output md5block.go; DO NOT EDIT. -+ -+package md5 -+ -+import ( -+ "encoding/binary" -+ "math/bits" -+) -+ -+func blockGeneric(dig *digest, p []byte) { -+ // load state -+ a, b, c, d := dig.s[0], dig.s[1], dig.s[2], dig.s[3] -+ -+ for i := 0; i <= len(p)-BlockSize; i += BlockSize { -+ // eliminate bounds checks on p -+ q := p[i:] -+ q = q[:BlockSize:BlockSize] -+ -+ // save current state -+ aa, bb, cc, dd := a, b, c, d -+ -+ // load input block -+ x0 := binary.LittleEndian.Uint32(q[4*0x0:]) -+ x1 := binary.LittleEndian.Uint32(q[4*0x1:]) -+ x2 := binary.LittleEndian.Uint32(q[4*0x2:]) -+ x3 := binary.LittleEndian.Uint32(q[4*0x3:]) -+ x4 := binary.LittleEndian.Uint32(q[4*0x4:]) -+ x5 := binary.LittleEndian.Uint32(q[4*0x5:]) -+ x6 := binary.LittleEndian.Uint32(q[4*0x6:]) -+ x7 := binary.LittleEndian.Uint32(q[4*0x7:]) -+ x8 := binary.LittleEndian.Uint32(q[4*0x8:]) -+ x9 := binary.LittleEndian.Uint32(q[4*0x9:]) -+ xa := binary.LittleEndian.Uint32(q[4*0xa:]) -+ xb := binary.LittleEndian.Uint32(q[4*0xb:]) -+ xc := binary.LittleEndian.Uint32(q[4*0xc:]) -+ xd := binary.LittleEndian.Uint32(q[4*0xd:]) -+ xe := binary.LittleEndian.Uint32(q[4*0xe:]) -+ xf := binary.LittleEndian.Uint32(q[4*0xf:]) -+ -+ // round 1 -+ a = b + bits.RotateLeft32((((c^d)&b)^d)+a+x0+0xd76aa478, 7) -+ d = a + bits.RotateLeft32((((b^c)&a)^c)+d+x1+0xe8c7b756, 12) -+ c = d + bits.RotateLeft32((((a^b)&d)^b)+c+x2+0x242070db, 17) -+ b = c + bits.RotateLeft32((((d^a)&c)^a)+b+x3+0xc1bdceee, 22) -+ a = b + bits.RotateLeft32((((c^d)&b)^d)+a+x4+0xf57c0faf, 7) -+ d = a + bits.RotateLeft32((((b^c)&a)^c)+d+x5+0x4787c62a, 12) -+ c = d + bits.RotateLeft32((((a^b)&d)^b)+c+x6+0xa8304613, 17) -+ b = c + bits.RotateLeft32((((d^a)&c)^a)+b+x7+0xfd469501, 22) -+ a = b + bits.RotateLeft32((((c^d)&b)^d)+a+x8+0x698098d8, 7) -+ d = a + bits.RotateLeft32((((b^c)&a)^c)+d+x9+0x8b44f7af, 12) -+ c = d + bits.RotateLeft32((((a^b)&d)^b)+c+xa+0xffff5bb1, 17) -+ b = c + bits.RotateLeft32((((d^a)&c)^a)+b+xb+0x895cd7be, 22) -+ a = b + bits.RotateLeft32((((c^d)&b)^d)+a+xc+0x6b901122, 7) -+ d = a + bits.RotateLeft32((((b^c)&a)^c)+d+xd+0xfd987193, 12) -+ c = d + bits.RotateLeft32((((a^b)&d)^b)+c+xe+0xa679438e, 17) -+ b = c + bits.RotateLeft32((((d^a)&c)^a)+b+xf+0x49b40821, 22) -+ -+ // round 2 -+ a = b + bits.RotateLeft32((((b^c)&d)^c)+a+x1+0xf61e2562, 5) -+ d = a + bits.RotateLeft32((((a^b)&c)^b)+d+x6+0xc040b340, 9) -+ c = d + bits.RotateLeft32((((d^a)&b)^a)+c+xb+0x265e5a51, 14) -+ b = c + bits.RotateLeft32((((c^d)&a)^d)+b+x0+0xe9b6c7aa, 20) -+ a = b + bits.RotateLeft32((((b^c)&d)^c)+a+x5+0xd62f105d, 5) -+ d = a + bits.RotateLeft32((((a^b)&c)^b)+d+xa+0x02441453, 9) -+ c = d + bits.RotateLeft32((((d^a)&b)^a)+c+xf+0xd8a1e681, 14) -+ b = c + bits.RotateLeft32((((c^d)&a)^d)+b+x4+0xe7d3fbc8, 20) -+ a = b + bits.RotateLeft32((((b^c)&d)^c)+a+x9+0x21e1cde6, 5) -+ d = a + bits.RotateLeft32((((a^b)&c)^b)+d+xe+0xc33707d6, 9) -+ c = d + bits.RotateLeft32((((d^a)&b)^a)+c+x3+0xf4d50d87, 14) -+ b = c + bits.RotateLeft32((((c^d)&a)^d)+b+x8+0x455a14ed, 20) -+ a = b + bits.RotateLeft32((((b^c)&d)^c)+a+xd+0xa9e3e905, 5) -+ d = a + bits.RotateLeft32((((a^b)&c)^b)+d+x2+0xfcefa3f8, 9) -+ c = d + bits.RotateLeft32((((d^a)&b)^a)+c+x7+0x676f02d9, 14) -+ b = c + bits.RotateLeft32((((c^d)&a)^d)+b+xc+0x8d2a4c8a, 20) -+ -+ // round 3 -+ a = b + bits.RotateLeft32((b^c^d)+a+x5+0xfffa3942, 4) -+ d = a + bits.RotateLeft32((a^b^c)+d+x8+0x8771f681, 11) -+ c = d + bits.RotateLeft32((d^a^b)+c+xb+0x6d9d6122, 16) -+ b = c + bits.RotateLeft32((c^d^a)+b+xe+0xfde5380c, 23) -+ a = b + bits.RotateLeft32((b^c^d)+a+x1+0xa4beea44, 4) -+ d = a + bits.RotateLeft32((a^b^c)+d+x4+0x4bdecfa9, 11) -+ c = d + bits.RotateLeft32((d^a^b)+c+x7+0xf6bb4b60, 16) -+ b = c + bits.RotateLeft32((c^d^a)+b+xa+0xbebfbc70, 23) -+ a = b + bits.RotateLeft32((b^c^d)+a+xd+0x289b7ec6, 4) -+ d = a + bits.RotateLeft32((a^b^c)+d+x0+0xeaa127fa, 11) -+ c = d + bits.RotateLeft32((d^a^b)+c+x3+0xd4ef3085, 16) -+ b = c + bits.RotateLeft32((c^d^a)+b+x6+0x04881d05, 23) -+ a = b + bits.RotateLeft32((b^c^d)+a+x9+0xd9d4d039, 4) -+ d = a + bits.RotateLeft32((a^b^c)+d+xc+0xe6db99e5, 11) -+ c = d + bits.RotateLeft32((d^a^b)+c+xf+0x1fa27cf8, 16) -+ b = c + bits.RotateLeft32((c^d^a)+b+x2+0xc4ac5665, 23) -+ -+ // round 4 -+ a = b + bits.RotateLeft32((c^(b|^d))+a+x0+0xf4292244, 6) -+ d = a + bits.RotateLeft32((b^(a|^c))+d+x7+0x432aff97, 10) -+ c = d + bits.RotateLeft32((a^(d|^b))+c+xe+0xab9423a7, 15) -+ b = c + bits.RotateLeft32((d^(c|^a))+b+x5+0xfc93a039, 21) -+ a = b + bits.RotateLeft32((c^(b|^d))+a+xc+0x655b59c3, 6) -+ d = a + bits.RotateLeft32((b^(a|^c))+d+x3+0x8f0ccc92, 10) -+ c = d + bits.RotateLeft32((a^(d|^b))+c+xa+0xffeff47d, 15) -+ b = c + bits.RotateLeft32((d^(c|^a))+b+x1+0x85845dd1, 21) -+ a = b + bits.RotateLeft32((c^(b|^d))+a+x8+0x6fa87e4f, 6) -+ d = a + bits.RotateLeft32((b^(a|^c))+d+xf+0xfe2ce6e0, 10) -+ c = d + bits.RotateLeft32((a^(d|^b))+c+x6+0xa3014314, 15) -+ b = c + bits.RotateLeft32((d^(c|^a))+b+xd+0x4e0811a1, 21) -+ a = b + bits.RotateLeft32((c^(b|^d))+a+x4+0xf7537e82, 6) -+ d = a + bits.RotateLeft32((b^(a|^c))+d+xb+0xbd3af235, 10) -+ c = d + bits.RotateLeft32((a^(d|^b))+c+x2+0x2ad7d2bb, 15) -+ b = c + bits.RotateLeft32((d^(c|^a))+b+x9+0xeb86d391, 21) -+ -+ // add saved state -+ a += aa -+ b += bb -+ c += cc -+ d += dd -+ } -+ -+ // save state -+ dig.s[0], dig.s[1], dig.s[2], dig.s[3] = a, b, c, d -+} -diff --git a/src/crypto/md5/md5block_decl.go-e b/src/crypto/md5/md5block_decl.go-e -new file mode 100644 -index 0000000000..f1fb34c3d7 ---- /dev/null -+++ b/src/crypto/md5/md5block_decl.go-e -@@ -0,0 +1,12 @@ -+// Copyright 2013 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 amd64 || 386 || arm || ppc64le || ppc64 || s390x || arm64 -+ -+package md5 -+ -+const haveAsm = true -+ -+//go:noescape -+func block(dig *digest, p []byte) -diff --git a/src/crypto/md5/md5block_generic.go-e b/src/crypto/md5/md5block_generic.go-e -new file mode 100644 -index 0000000000..c929c2b84a ---- /dev/null -+++ b/src/crypto/md5/md5block_generic.go-e -@@ -0,0 +1,13 @@ -+// Copyright 2014 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 !amd64 && !386 && !arm && !ppc64le && !ppc64 && !s390x && !arm64 -+ -+package md5 -+ -+const haveAsm = false -+ -+func block(dig *digest, p []byte) { -+ blockGeneric(dig, p) -+} -diff --git a/src/crypto/rand/example_test.go-e b/src/crypto/rand/example_test.go-e -new file mode 100644 -index 0000000000..ed1864761a ---- /dev/null -+++ b/src/crypto/rand/example_test.go-e -@@ -0,0 +1,28 @@ -+// Copyright 2011 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. -+ -+package rand_test -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "fmt" -+) -+ -+// This example reads 10 cryptographically secure pseudorandom numbers from -+// rand.Reader and writes them to a byte slice. -+func ExampleRead() { -+ c := 10 -+ b := make([]byte, c) -+ _, err := rand.Read(b) -+ if err != nil { -+ fmt.Println("error:", err) -+ return -+ } -+ // The slice should now contain random bytes instead of only zeroes. -+ fmt.Println(bytes.Equal(b, make([]byte, c))) -+ -+ // Output: -+ // false -+} -diff --git a/src/crypto/rand/rand.go-e b/src/crypto/rand/rand.go-e -new file mode 100644 -index 0000000000..62738e2cb1 ---- /dev/null -+++ b/src/crypto/rand/rand.go-e -@@ -0,0 +1,45 @@ -+// Copyright 2010 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. -+ -+// Package rand implements a cryptographically secure -+// random number generator. -+package rand -+ -+import "io" -+ -+// Reader is a global, shared instance of a cryptographically -+// secure random number generator. -+// -+// On Linux, FreeBSD, Dragonfly, NetBSD and Solaris, Reader uses getrandom(2) if -+// available, /dev/urandom otherwise. -+// On OpenBSD and macOS, Reader uses getentropy(2). -+// On other Unix-like systems, Reader reads from /dev/urandom. -+// On Windows systems, Reader uses the RtlGenRandom API. -+// On JS/Wasm, Reader uses the Web Crypto API. -+// On WASIP1/Wasm, Reader uses random_get from wasi_snapshot_preview1. -+var Reader io.Reader -+ -+// Read is a helper function that calls Reader.Read using io.ReadFull. -+// On return, n == len(b) if and only if err == nil. -+func Read(b []byte) (n int, err error) { -+ return io.ReadFull(Reader, b) -+} -+ -+// batched returns a function that calls f to populate a []byte by chunking it -+// into subslices of, at most, readMax bytes. -+func batched(f func([]byte) error, readMax int) func([]byte) error { -+ return func(out []byte) error { -+ for len(out) > 0 { -+ read := len(out) -+ if read > readMax { -+ read = readMax -+ } -+ if err := f(out[:read]); err != nil { -+ return err -+ } -+ out = out[read:] -+ } -+ return nil -+ } -+} -diff --git a/src/crypto/rand/rand_batched_test.go-e b/src/crypto/rand/rand_batched_test.go-e -new file mode 100644 -index 0000000000..02f48931e3 ---- /dev/null -+++ b/src/crypto/rand/rand_batched_test.go-e -@@ -0,0 +1,75 @@ -+// Copyright 2014 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 unix -+ -+package rand -+ -+import ( -+ "bytes" -+ "errors" -+ prand "math/rand" -+ "testing" -+) -+ -+func TestBatched(t *testing.T) { -+ fillBatched := batched(func(p []byte) error { -+ for i := range p { -+ p[i] = byte(i) -+ } -+ return nil -+ }, 5) -+ -+ p := make([]byte, 13) -+ if err := fillBatched(p); err != nil { -+ t.Fatalf("batched function returned error: %s", err) -+ } -+ expected := []byte{0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2} -+ if !bytes.Equal(expected, p) { -+ t.Errorf("incorrect batch result: got %x, want %x", p, expected) -+ } -+} -+ -+func TestBatchedBuffering(t *testing.T) { -+ backingStore := make([]byte, 1<<23) -+ prand.Read(backingStore) -+ backingMarker := backingStore[:] -+ output := make([]byte, len(backingStore)) -+ outputMarker := output[:] -+ -+ fillBatched := batched(func(p []byte) error { -+ n := copy(p, backingMarker) -+ backingMarker = backingMarker[n:] -+ return nil -+ }, 731) -+ -+ for len(outputMarker) > 0 { -+ max := 9200 -+ if max > len(outputMarker) { -+ max = len(outputMarker) -+ } -+ howMuch := prand.Intn(max + 1) -+ if err := fillBatched(outputMarker[:howMuch]); err != nil { -+ t.Fatalf("batched function returned error: %s", err) -+ } -+ outputMarker = outputMarker[howMuch:] -+ } -+ if !bytes.Equal(backingStore, output) { -+ t.Error("incorrect batch result") -+ } -+} -+ -+func TestBatchedError(t *testing.T) { -+ b := batched(func(p []byte) error { return errors.New("failure") }, 5) -+ if b(make([]byte, 13)) == nil { -+ t.Fatal("batched function should have returned an error") -+ } -+} -+ -+func TestBatchedEmpty(t *testing.T) { -+ b := batched(func(p []byte) error { return errors.New("failure") }, 5) -+ if b(make([]byte, 0)) != nil { -+ t.Fatal("empty slice should always return successful") -+ } -+} -diff --git a/src/crypto/rand/rand_getentropy.go-e b/src/crypto/rand/rand_getentropy.go-e -new file mode 100644 -index 0000000000..68f921b0fc ---- /dev/null -+++ b/src/crypto/rand/rand_getentropy.go-e -@@ -0,0 +1,14 @@ -+// Copyright 2016 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 (darwin && !ios) || openbsd -+ -+package rand -+ -+import "internal/syscall/unix" -+ -+func init() { -+ // getentropy(2) returns a maximum of 256 bytes per call -+ altGetRandom = batched(unix.GetEntropy, 256) -+} -diff --git a/src/crypto/rand/rand_getrandom.go-e b/src/crypto/rand/rand_getrandom.go-e -new file mode 100644 -index 0000000000..46c4133a73 ---- /dev/null -+++ b/src/crypto/rand/rand_getrandom.go-e -@@ -0,0 +1,48 @@ -+// Copyright 2014 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 dragonfly || freebsd || linux || netbsd || solaris -+ -+package rand -+ -+import ( -+ "internal/syscall/unix" -+ "runtime" -+ "syscall" -+) -+ -+func init() { -+ var maxGetRandomRead int -+ switch runtime.GOOS { -+ case "linux", "android": -+ // Per the manpage: -+ // When reading from the urandom source, a maximum of 33554431 bytes -+ // is returned by a single call to getrandom() on systems where int -+ // has a size of 32 bits. -+ maxGetRandomRead = (1 << 25) - 1 -+ case "dragonfly", "freebsd", "illumos", "netbsd", "solaris": -+ maxGetRandomRead = 1 << 8 -+ default: -+ panic("no maximum specified for GetRandom") -+ } -+ altGetRandom = batched(getRandom, maxGetRandomRead) -+} -+ -+// If the kernel is too old to support the getrandom syscall(), -+// unix.GetRandom will immediately return ENOSYS and we will then fall back to -+// reading from /dev/urandom in rand_unix.go. unix.GetRandom caches the ENOSYS -+// result so we only suffer the syscall overhead once in this case. -+// If the kernel supports the getrandom() syscall, unix.GetRandom will block -+// until the kernel has sufficient randomness (as we don't use GRND_NONBLOCK). -+// In this case, unix.GetRandom will not return an error. -+func getRandom(p []byte) error { -+ n, err := unix.GetRandom(p, 0) -+ if err != nil { -+ return err -+ } -+ if n != len(p) { -+ return syscall.EIO -+ } -+ return nil -+} -diff --git a/src/crypto/rand/rand_js.go-e b/src/crypto/rand/rand_js.go-e -new file mode 100644 -index 0000000000..d8fe81580b ---- /dev/null -+++ b/src/crypto/rand/rand_js.go-e -@@ -0,0 +1,42 @@ -+// Copyright 2018 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 js && wasm -+ -+package rand -+ -+import "syscall/js" -+ -+// The maximum buffer size for crypto.getRandomValues is 65536 bytes. -+// https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues#exceptions -+const maxGetRandomRead = 64 << 10 -+ -+var batchedGetRandom func([]byte) error -+ -+func init() { -+ Reader = &reader{} -+ batchedGetRandom = batched(getRandom, maxGetRandomRead) -+} -+ -+var jsCrypto = js.Global().Get("crypto") -+var uint8Array = js.Global().Get("Uint8Array") -+ -+// reader implements a pseudorandom generator -+// using JavaScript crypto.getRandomValues method. -+// See https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues. -+type reader struct{} -+ -+func (r *reader) Read(b []byte) (int, error) { -+ if err := batchedGetRandom(b); err != nil { -+ return 0, err -+ } -+ return len(b), nil -+} -+ -+func getRandom(b []byte) error { -+ a := uint8Array.New(len(b)) -+ jsCrypto.Call("getRandomValues", a) -+ js.CopyBytesToGo(b, a) -+ return nil -+} -diff --git a/src/crypto/rand/rand_plan9.go-e b/src/crypto/rand/rand_plan9.go-e -new file mode 100644 -index 0000000000..5d0af0959e ---- /dev/null -+++ b/src/crypto/rand/rand_plan9.go-e -@@ -0,0 +1,87 @@ -+// Copyright 2010 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. -+ -+// Plan9 cryptographically secure pseudorandom number -+// generator. -+ -+package rand -+ -+import ( -+ "crypto/aes" -+ "encoding/binary" -+ "io" -+ "os" -+ "sync" -+ "time" -+) -+ -+const randomDevice = "/dev/random" -+ -+func init() { -+ Reader = &reader{} -+} -+ -+// reader is a new pseudorandom generator that seeds itself by -+// reading from /dev/random. The Read method on the returned -+// reader always returns the full amount asked for, or else it -+// returns an error. The generator is a fast key erasure RNG. -+type reader struct { -+ mu sync.Mutex -+ seeded sync.Once -+ seedErr error -+ key [32]byte -+} -+ -+func (r *reader) Read(b []byte) (n int, err error) { -+ r.seeded.Do(func() { -+ t := time.AfterFunc(time.Minute, func() { -+ println("crypto/rand: blocked for 60 seconds waiting to read random data from the kernel") -+ }) -+ defer t.Stop() -+ entropy, err := os.Open(randomDevice) -+ if err != nil { -+ r.seedErr = err -+ return -+ } -+ _, r.seedErr = io.ReadFull(entropy, r.key[:]) -+ }) -+ if r.seedErr != nil { -+ return 0, r.seedErr -+ } -+ -+ r.mu.Lock() -+ blockCipher, err := aes.NewCipher(r.key[:]) -+ if err != nil { -+ r.mu.Unlock() -+ return 0, err -+ } -+ var ( -+ counter uint64 -+ block [aes.BlockSize]byte -+ ) -+ inc := func() { -+ counter++ -+ if counter == 0 { -+ panic("crypto/rand counter wrapped") -+ } -+ binary.LittleEndian.PutUint64(block[:], counter) -+ } -+ blockCipher.Encrypt(r.key[:aes.BlockSize], block[:]) -+ inc() -+ blockCipher.Encrypt(r.key[aes.BlockSize:], block[:]) -+ inc() -+ r.mu.Unlock() -+ -+ n = len(b) -+ for len(b) >= aes.BlockSize { -+ blockCipher.Encrypt(b[:aes.BlockSize], block[:]) -+ inc() -+ b = b[aes.BlockSize:] -+ } -+ if len(b) > 0 { -+ blockCipher.Encrypt(block[:], block[:]) -+ copy(b, block[:]) -+ } -+ return n, nil -+} -diff --git a/src/crypto/rand/rand_test.go-e b/src/crypto/rand/rand_test.go-e -new file mode 100644 -index 0000000000..e45f58e4e7 ---- /dev/null -+++ b/src/crypto/rand/rand_test.go-e -@@ -0,0 +1,43 @@ -+// Copyright 2010 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. -+ -+package rand -+ -+import ( -+ "bytes" -+ "compress/flate" -+ "io" -+ "testing" -+) -+ -+func TestRead(t *testing.T) { -+ var n int = 4e6 -+ if testing.Short() { -+ n = 1e5 -+ } -+ b := make([]byte, n) -+ n, err := io.ReadFull(Reader, b) -+ if n != len(b) || err != nil { -+ t.Fatalf("ReadFull(buf) = %d, %s", n, err) -+ } -+ -+ var z bytes.Buffer -+ f, _ := flate.NewWriter(&z, 5) -+ f.Write(b) -+ f.Close() -+ if z.Len() < len(b)*99/100 { -+ t.Fatalf("Compressed %d -> %d", len(b), z.Len()) -+ } -+} -+ -+func TestReadEmpty(t *testing.T) { -+ n, err := Reader.Read(make([]byte, 0)) -+ if n != 0 || err != nil { -+ t.Fatalf("Read(make([]byte, 0)) = %d, %v", n, err) -+ } -+ n, err = Reader.Read(nil) -+ if n != 0 || err != nil { -+ t.Fatalf("Read(nil) = %d, %v", n, err) -+ } -+} ->>>>>>> 70a351c141 (wip) -======= ->>>>>>> 80d9391199 (wip) -diff --git a/src/crypto/rand/rand_unix.go b/src/crypto/rand/rand_unix.go -index 40fce36314..c30be35635 100644 ---- a/src/crypto/rand/rand_unix.go -+++ b/src/crypto/rand/rand_unix.go -@@ -10,7 +10,7 @@ - package rand -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - import ( -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "errors" - "io" - "os" -@@ -23,7 +23,7 @@ import ( - const urandomDevice = "/dev/urandom" -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - func init() { -- if boring.Enabled { -+ if boring.Enabled() { - Reader = boring.RandReader - return - } -diff --git a/src/crypto/rsa/boring.go b/src/crypto/rsa/boring.go -index b9f9d3154f..85c2a45848 100644 ---- a/src/crypto/rsa/boring.go -+++ b/src/crypto/rsa/boring.go -@@ -2,13 +2,13 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -<<<<<<< HEAD - --//go:build boringcrypto -+//go:build !no_openssl - - package rsa - -======= - --//go:build boringcrypto -+//go:build !no_openssl - - package rsa - ->>>>>>> 0023bf4c7a (rebase) - import ( -- "crypto/internal/boring" -- "crypto/internal/boring/bbig" -+ boring "crypto/internal/backend" -+ "crypto/internal/backend/bbig" - "crypto/internal/boring/bcache" - "math/big" - ) -diff --git a/src/crypto/rsa/boring_test.go b/src/crypto/rsa/boring_test.go -index 2234d079f0..4e7fd9de4a 100644 ---- a/src/crypto/rsa/boring_test.go -+++ b/src/crypto/rsa/boring_test.go -@@ -2,7 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -<<<<<<< HEAD - --//go:build boringcrypto -+//go:build !no_openssl - -======= - --//go:build boringcrypto -+//go:build !no_openssl - ->>>>>>> 0023bf4c7a (rebase) - // Note: Can run these tests against the non-BoringCrypto - // version of the code by using "CGO_ENABLED=0 go test". -diff --git a/src/crypto/rsa/notboring.go b/src/crypto/rsa/notboring.go -index 2abc043640..a83be6dfdb 100644 ---- a/src/crypto/rsa/notboring.go -+++ b/src/crypto/rsa/notboring.go -@@ -2,15 +2,15 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -<<<<<<< HEAD - --//go:build !boringcrypto -+//go:build no_openssl - - package rsa - --import "crypto/internal/boring" -+import boring "crypto/internal/backend" - -======= - --//go:build !boringcrypto -+//go:build no_openssl - - package rsa - --import "crypto/internal/boring" -+import boring "crypto/internal/backend" - ->>>>>>> 0023bf4c7a (rebase) - func boringPublicKey(*PublicKey) (*boring.PublicKeyRSA, error) { -- panic("boringcrypto: not available") -+ panic("!no_openssl: not available") - } - func boringPrivateKey(*PrivateKey) (*boring.PrivateKeyRSA, error) { -- panic("boringcrypto: not available") -+ panic("!no_openssl: not available") - } -diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go -<<<<<<< HEAD -index 55fea1ab93..d6eaf7cea8 100644 ---- a/src/crypto/rsa/pkcs1v15.go -+++ b/src/crypto/rsa/pkcs1v15.go -@@ -6,7 +6,7 @@ package rsa - -======= -index 55fea1ab93..8524c02547 100644 ---- a/src/crypto/rsa/pkcs1v15.go -+++ b/src/crypto/rsa/pkcs1v15.go -@@ -6,7 +6,7 @@ package rsa - ->>>>>>> 0023bf4c7a (rebase) - import ( - "crypto" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/randutil" - "crypto/subtle" - "errors" -@@ -49,7 +49,7 @@ func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, erro - return nil, ErrMessageTooLong - } -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled && random == boring.RandReader { -+ if boring.Enabled() && random == boring.RandReader { - bkey, err := boringPublicKey(pub) - if err != nil { - return nil, err -@@ -69,7 +69,7 @@ func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, erro - em[len(em)-len(msg)-1] = 0 - copy(mm, msg) -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled { -+ if boring.Enabled() { - var bkey *boring.PublicKeyRSA - bkey, err = boringPublicKey(pub) - if err != nil { -@@ -94,7 +94,7 @@ func DecryptPKCS1v15(random io.Reader, priv *PrivateKey, ciphertext []byte) ([]b - return nil, err - } -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled { -+ if boring.Enabled() { - bkey, err := boringPrivateKey(priv) - if err != nil { - return nil, err -@@ -188,7 +188,7 @@ func decryptPKCS1v15(priv *PrivateKey, ciphertext []byte) (valid int, em []byte, - return - } -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled { -+ if boring.Enabled() { - var bkey *boring.PrivateKeyRSA - bkey, err = boringPrivateKey(priv) - if err != nil { -<<<<<<< HEAD -@@ -296,12 +296,12 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [ - return nil, ErrMessageTooLong - } - -======= -@@ -296,7 +296,7 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [ - return nil, ErrMessageTooLong - } - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled { -+ if boring.Enabled() { - bkey, err := boringPrivateKey(priv) - if err != nil { - return nil, err -<<<<<<< HEAD - } -- return boring.SignRSAPKCS1v15(bkey, hash, hashed) -+ return boring.SignRSAPKCS1v15(bkey, hash, hashed, true) - } - - // EM = 0x00 || 0x01 || PS || 0x00 || T -@@ -322,12 +322,12 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [ -======= -@@ -322,7 +322,7 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [ ->>>>>>> 0023bf4c7a (rebase) - // returning a nil error. If hash is zero then hashed is used directly. This - // isn't advisable except for interoperability. - func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error { -- if boring.Enabled { -+ if boring.Enabled() { - bkey, err := boringPublicKey(pub) - if err != nil { - return err -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - } -- if err := boring.VerifyRSAPKCS1v15(bkey, hash, hashed, sig); err != nil { -+ if err := boring.VerifyRSAPKCS1v15(bkey, hash, hashed, sig, hash != crypto.Hash(0)); err != nil { - return ErrVerification - } - return nil -======= ->>>>>>> 0023bf4c7a (rebase) -======= -diff --git a/src/crypto/rsa/pkcs1v15.go-e b/src/crypto/rsa/pkcs1v15.go-e -new file mode 100644 -index 0000000000..8524c02547 ---- /dev/null -+++ b/src/crypto/rsa/pkcs1v15.go-e -@@ -0,0 +1,393 @@ -+// Copyright 2009 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. -+ -+package rsa -+ -+import ( -+ "crypto" -+ boring "crypto/internal/backend" -+ "crypto/internal/randutil" -+ "crypto/subtle" -+ "errors" -+ "io" -+) -+ -+// This file implements encryption and decryption using PKCS #1 v1.5 padding. -+ -+// PKCS1v15DecryptOptions is for passing options to PKCS #1 v1.5 decryption using -+// the crypto.Decrypter interface. -+type PKCS1v15DecryptOptions struct { -+ // SessionKeyLen is the length of the session key that is being -+ // decrypted. If not zero, then a padding error during decryption will -+ // cause a random plaintext of this length to be returned rather than -+ // an error. These alternatives happen in constant time. -+ SessionKeyLen int -+} -+ -+// EncryptPKCS1v15 encrypts the given message with RSA and the padding -+// scheme from PKCS #1 v1.5. The message must be no longer than the -+// length of the public modulus minus 11 bytes. -+// -+// The random parameter is used as a source of entropy to ensure that -+// encrypting the same message twice doesn't result in the same -+// ciphertext. Most applications should use [crypto/rand.Reader] -+// as random. Note that the returned ciphertext does not depend -+// deterministically on the bytes read from random, and may change -+// between calls and/or between versions. -+// -+// WARNING: use of this function to encrypt plaintexts other than -+// session keys is dangerous. Use RSA OAEP in new protocols. -+func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, error) { -+ randutil.MaybeReadByte(random) -+ -+ if err := checkPub(pub); err != nil { -+ return nil, err -+ } -+ k := pub.Size() -+ if len(msg) > k-11 { -+ return nil, ErrMessageTooLong -+ } -+ -+ if boring.Enabled() && random == boring.RandReader { -+ bkey, err := boringPublicKey(pub) -+ if err != nil { -+ return nil, err -+ } -+ return boring.EncryptRSAPKCS1(bkey, msg) -+ } -+ boring.UnreachableExceptTests() -+ -+ // EM = 0x00 || 0x02 || PS || 0x00 || M -+ em := make([]byte, k) -+ em[1] = 2 -+ ps, mm := em[2:len(em)-len(msg)-1], em[len(em)-len(msg):] -+ err := nonZeroRandomBytes(ps, random) -+ if err != nil { -+ return nil, err -+ } -+ em[len(em)-len(msg)-1] = 0 -+ copy(mm, msg) -+ -+ if boring.Enabled() { -+ var bkey *boring.PublicKeyRSA -+ bkey, err = boringPublicKey(pub) -+ if err != nil { -+ return nil, err -+ } -+ return boring.EncryptRSANoPadding(bkey, em) -+ } -+ -+ return encrypt(pub, em) -+} -+ -+// DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS #1 v1.5. -+// The random parameter is legacy and ignored, and it can be nil. -+// -+// Note that whether this function returns an error or not discloses secret -+// information. If an attacker can cause this function to run repeatedly and -+// learn whether each instance returned an error then they can decrypt and -+// forge signatures as if they had the private key. See -+// DecryptPKCS1v15SessionKey for a way of solving this problem. -+func DecryptPKCS1v15(random io.Reader, priv *PrivateKey, ciphertext []byte) ([]byte, error) { -+ if err := checkPub(&priv.PublicKey); err != nil { -+ return nil, err -+ } -+ -+ if boring.Enabled() { -+ bkey, err := boringPrivateKey(priv) -+ if err != nil { -+ return nil, err -+ } -+ out, err := boring.DecryptRSAPKCS1(bkey, ciphertext) -+ if err != nil { -+ return nil, ErrDecryption -+ } -+ return out, nil -+ } -+ -+ valid, out, index, err := decryptPKCS1v15(priv, ciphertext) -+ if err != nil { -+ return nil, err -+ } -+ if valid == 0 { -+ return nil, ErrDecryption -+ } -+ return out[index:], nil -+} -+ -+// DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding -+// scheme from PKCS #1 v1.5. The random parameter is legacy and ignored, and it -+// can be nil. -+// -+// DecryptPKCS1v15SessionKey returns an error if the ciphertext is the wrong -+// length or if the ciphertext is greater than the public modulus. Otherwise, no -+// error is returned. If the padding is valid, the resulting plaintext message -+// is copied into key. Otherwise, key is unchanged. These alternatives occur in -+// constant time. It is intended that the user of this function generate a -+// random session key beforehand and continue the protocol with the resulting -+// value. -+// -+// Note that if the session key is too small then it may be possible for an -+// attacker to brute-force it. If they can do that then they can learn whether a -+// random value was used (because it'll be different for the same ciphertext) -+// and thus whether the padding was correct. This also defeats the point of this -+// function. Using at least a 16-byte key will protect against this attack. -+// -+// This method implements protections against Bleichenbacher chosen ciphertext -+// attacks [0] described in RFC 3218 Section 2.3.2 [1]. While these protections -+// make a Bleichenbacher attack significantly more difficult, the protections -+// are only effective if the rest of the protocol which uses -+// DecryptPKCS1v15SessionKey is designed with these considerations in mind. In -+// particular, if any subsequent operations which use the decrypted session key -+// leak any information about the key (e.g. whether it is a static or random -+// key) then the mitigations are defeated. This method must be used extremely -+// carefully, and typically should only be used when absolutely necessary for -+// compatibility with an existing protocol (such as TLS) that is designed with -+// these properties in mind. -+// -+// - [0] “Chosen Ciphertext Attacks Against Protocols Based on the RSA Encryption -+// Standard PKCS #1”, Daniel Bleichenbacher, Advances in Cryptology (Crypto '98) -+// - [1] RFC 3218, Preventing the Million Message Attack on CMS, -+// https://www.rfc-editor.org/rfc/rfc3218.html -+func DecryptPKCS1v15SessionKey(random io.Reader, priv *PrivateKey, ciphertext []byte, key []byte) error { -+ if err := checkPub(&priv.PublicKey); err != nil { -+ return err -+ } -+ k := priv.Size() -+ if k-(len(key)+3+8) < 0 { -+ return ErrDecryption -+ } -+ -+ valid, em, index, err := decryptPKCS1v15(priv, ciphertext) -+ if err != nil { -+ return err -+ } -+ -+ if len(em) != k { -+ // This should be impossible because decryptPKCS1v15 always -+ // returns the full slice. -+ return ErrDecryption -+ } -+ -+ valid &= subtle.ConstantTimeEq(int32(len(em)-index), int32(len(key))) -+ subtle.ConstantTimeCopy(valid, key, em[len(em)-len(key):]) -+ return nil -+} -+ -+// decryptPKCS1v15 decrypts ciphertext using priv. It returns one or zero in -+// valid that indicates whether the plaintext was correctly structured. -+// In either case, the plaintext is returned in em so that it may be read -+// independently of whether it was valid in order to maintain constant memory -+// access patterns. If the plaintext was valid then index contains the index of -+// the original message in em, to allow constant time padding removal. -+func decryptPKCS1v15(priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) { -+ k := priv.Size() -+ if k < 11 { -+ err = ErrDecryption -+ return -+ } -+ -+ if boring.Enabled() { -+ var bkey *boring.PrivateKeyRSA -+ bkey, err = boringPrivateKey(priv) -+ if err != nil { -+ return -+ } -+ em, err = boring.DecryptRSANoPadding(bkey, ciphertext) -+ if err != nil { -+ return -+ } -+ } else { -+ em, err = decrypt(priv, ciphertext, noCheck) -+ if err != nil { -+ return -+ } -+ } -+ -+ firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0) -+ secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2) -+ -+ // The remainder of the plaintext must be a string of non-zero random -+ // octets, followed by a 0, followed by the message. -+ // lookingForIndex: 1 iff we are still looking for the zero. -+ // index: the offset of the first zero byte. -+ lookingForIndex := 1 -+ -+ for i := 2; i < len(em); i++ { -+ equals0 := subtle.ConstantTimeByteEq(em[i], 0) -+ index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index) -+ lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex) -+ } -+ -+ // The PS padding must be at least 8 bytes long, and it starts two -+ // bytes into em. -+ validPS := subtle.ConstantTimeLessOrEq(2+8, index) -+ -+ valid = firstByteIsZero & secondByteIsTwo & (^lookingForIndex & 1) & validPS -+ index = subtle.ConstantTimeSelect(valid, index+1, 0) -+ return valid, em, index, nil -+} -+ -+// nonZeroRandomBytes fills the given slice with non-zero random octets. -+func nonZeroRandomBytes(s []byte, random io.Reader) (err error) { -+ _, err = io.ReadFull(random, s) -+ if err != nil { -+ return -+ } -+ -+ for i := 0; i < len(s); i++ { -+ for s[i] == 0 { -+ _, err = io.ReadFull(random, s[i:i+1]) -+ if err != nil { -+ return -+ } -+ // In tests, the PRNG may return all zeros so we do -+ // this to break the loop. -+ s[i] ^= 0x42 -+ } -+ } -+ -+ return -+} -+ -+// These are ASN1 DER structures: -+// -+// DigestInfo ::= SEQUENCE { -+// digestAlgorithm AlgorithmIdentifier, -+// digest OCTET STRING -+// } -+// -+// For performance, we don't use the generic ASN1 encoder. Rather, we -+// precompute a prefix of the digest value that makes a valid ASN1 DER string -+// with the correct contents. -+var hashPrefixes = map[crypto.Hash][]byte{ -+ crypto.MD5: {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10}, -+ crypto.SHA1: {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14}, -+ crypto.SHA224: {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c}, -+ crypto.SHA256: {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}, -+ crypto.SHA384: {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}, -+ crypto.SHA512: {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}, -+ crypto.MD5SHA1: {}, // A special TLS case which doesn't use an ASN1 prefix. -+ crypto.RIPEMD160: {0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14}, -+} -+ -+// SignPKCS1v15 calculates the signature of hashed using -+// RSASSA-PKCS1-V1_5-SIGN from RSA PKCS #1 v1.5. Note that hashed must -+// be the result of hashing the input message using the given hash -+// function. If hash is zero, hashed is signed directly. This isn't -+// advisable except for interoperability. -+// -+// The random parameter is legacy and ignored, and it can be nil. -+// -+// This function is deterministic. Thus, if the set of possible -+// messages is small, an attacker may be able to build a map from -+// messages to signatures and identify the signed messages. As ever, -+// signatures provide authenticity, not confidentiality. -+func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte) ([]byte, error) { -+ hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed)) -+ if err != nil { -+ return nil, err -+ } -+ -+ tLen := len(prefix) + hashLen -+ k := priv.Size() -+ if k < tLen+11 { -+ return nil, ErrMessageTooLong -+ } -+ -+ if boring.Enabled() { -+ bkey, err := boringPrivateKey(priv) -+ if err != nil { -+ return nil, err -+ } -+ return boring.SignRSAPKCS1v15(bkey, hash, hashed) -+ } -+ -+ // EM = 0x00 || 0x01 || PS || 0x00 || T -+ em := make([]byte, k) -+ em[1] = 1 -+ for i := 2; i < k-tLen-1; i++ { -+ em[i] = 0xff -+ } -+ copy(em[k-tLen:k-hashLen], prefix) -+ copy(em[k-hashLen:k], hashed) -+ -+ return decrypt(priv, em, withCheck) -+} -+ -+// VerifyPKCS1v15 verifies an RSA PKCS #1 v1.5 signature. -+// hashed is the result of hashing the input message using the given hash -+// function and sig is the signature. A valid signature is indicated by -+// returning a nil error. If hash is zero then hashed is used directly. This -+// isn't advisable except for interoperability. -+func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error { -+ if boring.Enabled() { -+ bkey, err := boringPublicKey(pub) -+ if err != nil { -+ return err -+ } -+ if err := boring.VerifyRSAPKCS1v15(bkey, hash, hashed, sig); err != nil { -+ return ErrVerification -+ } -+ return nil -+ } -+ -+ hashLen, prefix, err := pkcs1v15HashInfo(hash, len(hashed)) -+ if err != nil { -+ return err -+ } -+ -+ tLen := len(prefix) + hashLen -+ k := pub.Size() -+ if k < tLen+11 { -+ return ErrVerification -+ } -+ -+ // RFC 8017 Section 8.2.2: If the length of the signature S is not k -+ // octets (where k is the length in octets of the RSA modulus n), output -+ // "invalid signature" and stop. -+ if k != len(sig) { -+ return ErrVerification -+ } -+ -+ em, err := encrypt(pub, sig) -+ if err != nil { -+ return ErrVerification -+ } -+ // EM = 0x00 || 0x01 || PS || 0x00 || T -+ -+ ok := subtle.ConstantTimeByteEq(em[0], 0) -+ ok &= subtle.ConstantTimeByteEq(em[1], 1) -+ ok &= subtle.ConstantTimeCompare(em[k-hashLen:k], hashed) -+ ok &= subtle.ConstantTimeCompare(em[k-tLen:k-hashLen], prefix) -+ ok &= subtle.ConstantTimeByteEq(em[k-tLen-1], 0) -+ -+ for i := 2; i < k-tLen-1; i++ { -+ ok &= subtle.ConstantTimeByteEq(em[i], 0xff) -+ } -+ -+ if ok != 1 { -+ return ErrVerification -+ } -+ -+ return nil -+} -+ -+func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, err error) { -+ // Special case: crypto.Hash(0) is used to indicate that the data is -+ // signed directly. -+ if hash == 0 { -+ return inLen, nil, nil -+ } -+ -+ hashLen = hash.Size() -+ if inLen != hashLen { -+ return 0, nil, errors.New("crypto/rsa: input must be hashed message") -+ } -+ prefix, ok := hashPrefixes[hash] -+ if !ok { -+ return 0, nil, errors.New("crypto/rsa: unsupported hash function") -+ } -+ return -+} ->>>>>>> 70a351c141 (wip) -======= ->>>>>>> 80d9391199 (wip) -diff --git a/src/crypto/rsa/pkcs1v15_test.go b/src/crypto/rsa/pkcs1v15_test.go -index 39a4fc184a..0853178e3a 100644 ---- a/src/crypto/rsa/pkcs1v15_test.go -+++ b/src/crypto/rsa/pkcs1v15_test.go -@@ -7,7 +7,7 @@ package rsa_test - import ( - "bytes" - "crypto" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/backend/boringtest" - "crypto/rand" - . "crypto/rsa" -@@ -56,7 +56,7 @@ var decryptPKCS1v15Tests = []DecryptPKCS1v15Test{ - } -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - func TestDecryptPKCS1v15(t *testing.T) { -- if boring.Enabled && !boringtest.Supports(t, "PKCSv1.5") { -+ if boring.Enabled() && !boringtest.Supports(t, "PKCSv1.5") { - t.Skip("skipping PKCS#1 v1.5 encryption test with BoringCrypto") - } -<<<<<<< HEAD - -@@ -84,7 +84,7 @@ func TestDecryptPKCS1v15(t *testing.T) { - } - -======= - -@@ -84,7 +84,7 @@ func TestDecryptPKCS1v15(t *testing.T) { - } - ->>>>>>> 0023bf4c7a (rebase) - func TestEncryptPKCS1v15(t *testing.T) { -- if boring.Enabled && !boringtest.Supports(t, "PKCSv1.5") { -+ if boring.Enabled() && !boringtest.Supports(t, "PKCSv1.5") { - t.Skip("skipping PKCS#1 v1.5 encryption test with BoringCrypto") - } -<<<<<<< HEAD - -@@ -149,7 +149,7 @@ var decryptPKCS1v15SessionKeyTests = []DecryptPKCS1v15Test{ - } - -======= - -@@ -149,7 +149,7 @@ var decryptPKCS1v15SessionKeyTests = []DecryptPKCS1v15Test{ - } - ->>>>>>> 0023bf4c7a (rebase) - func TestEncryptPKCS1v15SessionKey(t *testing.T) { -- if boring.Enabled && !boringtest.Supports(t, "PKCSv1.5") { -+ if boring.Enabled() && !boringtest.Supports(t, "PKCSv1.5") { - t.Skip("skipping PKCS#1 v1.5 encryption test with BoringCrypto") - } -<<<<<<< HEAD - -@@ -167,7 +167,7 @@ func TestEncryptPKCS1v15SessionKey(t *testing.T) { - } - -======= - -@@ -167,7 +167,7 @@ func TestEncryptPKCS1v15SessionKey(t *testing.T) { - } - ->>>>>>> 0023bf4c7a (rebase) - func TestEncryptPKCS1v15DecrypterSessionKey(t *testing.T) { -- if boring.Enabled && !boringtest.Supports(t, "PKCSv1.5") { -+ if boring.Enabled() && !boringtest.Supports(t, "PKCSv1.5") { - t.Skip("skipping PKCS#1 v1.5 encryption test with BoringCrypto") - } -<<<<<<< HEAD - -@@ -277,7 +277,7 @@ func TestUnpaddedSignature(t *testing.T) { - } - -======= - -@@ -277,7 +277,7 @@ func TestUnpaddedSignature(t *testing.T) { - } - ->>>>>>> 0023bf4c7a (rebase) - func TestShortSessionKey(t *testing.T) { -- if boring.Enabled && !boringtest.Supports(t, "PKCSv1.5") { -+ if boring.Enabled() && !boringtest.Supports(t, "PKCSv1.5") { - t.Skip("skipping PKCS#1 v1.5 encryption test with BoringCrypto") - } -<<<<<<< HEAD - -======= - -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 0023bf4c7a (rebase) -======= -diff --git a/src/crypto/rsa/pkcs1v15_test.go-e b/src/crypto/rsa/pkcs1v15_test.go-e -new file mode 100644 -index 0000000000..0853178e3a ---- /dev/null -+++ b/src/crypto/rsa/pkcs1v15_test.go-e -@@ -0,0 +1,366 @@ -+// Copyright 2009 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. -+ -+package rsa_test -+ -+import ( -+ "bytes" -+ "crypto" -+ boring "crypto/internal/backend" -+ "crypto/internal/backend/boringtest" -+ "crypto/rand" -+ . "crypto/rsa" -+ "crypto/sha1" -+ "crypto/sha256" -+ "crypto/x509" -+ "encoding/base64" -+ "encoding/hex" -+ "encoding/pem" -+ "io" -+ "testing" -+ "testing/quick" -+) -+ -+func decodeBase64(in string) []byte { -+ out := make([]byte, base64.StdEncoding.DecodedLen(len(in))) -+ n, err := base64.StdEncoding.Decode(out, []byte(in)) -+ if err != nil { -+ return nil -+ } -+ return out[0:n] -+} -+ -+type DecryptPKCS1v15Test struct { -+ in, out string -+} -+ -+// These test vectors were generated with `openssl rsautl -pkcs -encrypt` -+var decryptPKCS1v15Tests = []DecryptPKCS1v15Test{ -+ { -+ "gIcUIoVkD6ATMBk/u/nlCZCCWRKdkfjCgFdo35VpRXLduiKXhNz1XupLLzTXAybEq15juc+EgY5o0DHv/nt3yg==", -+ "x", -+ }, -+ { -+ "Y7TOCSqofGhkRb+jaVRLzK8xw2cSo1IVES19utzv6hwvx+M8kFsoWQm5DzBeJCZTCVDPkTpavUuEbgp8hnUGDw==", -+ "testing.", -+ }, -+ { -+ "arReP9DJtEVyV2Dg3dDp4c/PSk1O6lxkoJ8HcFupoRorBZG+7+1fDAwT1olNddFnQMjmkb8vxwmNMoTAT/BFjQ==", -+ "testing.\n", -+ }, -+ { -+ "WtaBXIoGC54+vH0NH0CHHE+dRDOsMc/6BrfFu2lEqcKL9+uDuWaf+Xj9mrbQCjjZcpQuX733zyok/jsnqe/Ftw==", -+ "01234567890123456789012345678901234567890123456789012", -+ }, -+} -+ -+func TestDecryptPKCS1v15(t *testing.T) { -+ if boring.Enabled() && !boringtest.Supports(t, "PKCSv1.5") { -+ t.Skip("skipping PKCS#1 v1.5 encryption test with BoringCrypto") -+ } -+ -+ decryptionFuncs := []func([]byte) ([]byte, error){ -+ func(ciphertext []byte) (plaintext []byte, err error) { -+ return DecryptPKCS1v15(nil, rsaPrivateKey, ciphertext) -+ }, -+ func(ciphertext []byte) (plaintext []byte, err error) { -+ return rsaPrivateKey.Decrypt(nil, ciphertext, nil) -+ }, -+ } -+ -+ for _, decryptFunc := range decryptionFuncs { -+ for i, test := range decryptPKCS1v15Tests { -+ out, err := decryptFunc(decodeBase64(test.in)) -+ if err != nil { -+ t.Errorf("#%d error decrypting: %v", i, err) -+ } -+ want := []byte(test.out) -+ if !bytes.Equal(out, want) { -+ t.Errorf("#%d got:%#v want:%#v", i, out, want) -+ } -+ } -+ } -+} -+ -+func TestEncryptPKCS1v15(t *testing.T) { -+ if boring.Enabled() && !boringtest.Supports(t, "PKCSv1.5") { -+ t.Skip("skipping PKCS#1 v1.5 encryption test with BoringCrypto") -+ } -+ -+ random := rand.Reader -+ k := (rsaPrivateKey.N.BitLen() + 7) / 8 -+ -+ tryEncryptDecrypt := func(in []byte, blind bool) bool { -+ if len(in) > k-11 { -+ in = in[0 : k-11] -+ } -+ -+ ciphertext, err := EncryptPKCS1v15(random, &rsaPrivateKey.PublicKey, in) -+ if err != nil { -+ t.Errorf("error encrypting: %s", err) -+ return false -+ } -+ -+ var rand io.Reader -+ if !blind { -+ rand = nil -+ } else { -+ rand = random -+ } -+ plaintext, err := DecryptPKCS1v15(rand, rsaPrivateKey, ciphertext) -+ if err != nil { -+ t.Errorf("error decrypting: %s", err) -+ return false -+ } -+ -+ if !bytes.Equal(plaintext, in) { -+ t.Errorf("output mismatch: %#v %#v", plaintext, in) -+ return false -+ } -+ return true -+ } -+ -+ config := new(quick.Config) -+ if testing.Short() { -+ config.MaxCount = 10 -+ } -+ quick.Check(tryEncryptDecrypt, config) -+} -+ -+// These test vectors were generated with `openssl rsautl -pkcs -encrypt` -+var decryptPKCS1v15SessionKeyTests = []DecryptPKCS1v15Test{ -+ { -+ "e6ukkae6Gykq0fKzYwULpZehX+UPXYzMoB5mHQUDEiclRbOTqas4Y0E6nwns1BBpdvEJcilhl5zsox/6DtGsYg==", -+ "1234", -+ }, -+ { -+ "Dtis4uk/q/LQGGqGk97P59K03hkCIVFMEFZRgVWOAAhxgYpCRG0MX2adptt92l67IqMki6iVQyyt0TtX3IdtEw==", -+ "FAIL", -+ }, -+ { -+ "LIyFyCYCptPxrvTxpol8F3M7ZivlMsf53zs0vHRAv+rDIh2YsHS69ePMoPMe3TkOMZ3NupiL3takPxIs1sK+dw==", -+ "abcd", -+ }, -+ { -+ "bafnobel46bKy76JzqU/RIVOH0uAYvzUtauKmIidKgM0sMlvobYVAVQPeUQ/oTGjbIZ1v/6Gyi5AO4DtHruGdw==", -+ "FAIL", -+ }, -+} -+ -+func TestEncryptPKCS1v15SessionKey(t *testing.T) { -+ if boring.Enabled() && !boringtest.Supports(t, "PKCSv1.5") { -+ t.Skip("skipping PKCS#1 v1.5 encryption test with BoringCrypto") -+ } -+ -+ for i, test := range decryptPKCS1v15SessionKeyTests { -+ key := []byte("FAIL") -+ err := DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, decodeBase64(test.in), key) -+ if err != nil { -+ t.Errorf("#%d error decrypting", i) -+ } -+ want := []byte(test.out) -+ if !bytes.Equal(key, want) { -+ t.Errorf("#%d got:%#v want:%#v", i, key, want) -+ } -+ } -+} -+ -+func TestEncryptPKCS1v15DecrypterSessionKey(t *testing.T) { -+ if boring.Enabled() && !boringtest.Supports(t, "PKCSv1.5") { -+ t.Skip("skipping PKCS#1 v1.5 encryption test with BoringCrypto") -+ } -+ -+ for i, test := range decryptPKCS1v15SessionKeyTests { -+ plaintext, err := rsaPrivateKey.Decrypt(rand.Reader, decodeBase64(test.in), &PKCS1v15DecryptOptions{SessionKeyLen: 4}) -+ if err != nil { -+ t.Fatalf("#%d: error decrypting: %s", i, err) -+ } -+ if len(plaintext) != 4 { -+ t.Fatalf("#%d: incorrect length plaintext: got %d, want 4", i, len(plaintext)) -+ } -+ -+ if test.out != "FAIL" && !bytes.Equal(plaintext, []byte(test.out)) { -+ t.Errorf("#%d: incorrect plaintext: got %x, want %x", i, plaintext, test.out) -+ } -+ } -+} -+ -+func TestNonZeroRandomBytes(t *testing.T) { -+ random := rand.Reader -+ -+ b := make([]byte, 512) -+ err := NonZeroRandomBytes(b, random) -+ if err != nil { -+ t.Errorf("returned error: %s", err) -+ } -+ for _, b := range b { -+ if b == 0 { -+ t.Errorf("Zero octet found") -+ return -+ } -+ } -+} -+ -+type signPKCS1v15Test struct { -+ in, out string -+} -+ -+// These vectors have been tested with -+// -+// `openssl rsautl -verify -inkey pk -in signature | hexdump -C` -+var signPKCS1v15Tests = []signPKCS1v15Test{ -+ {"Test.\n", "0c7c85d938862248846cba06b06ac9bfe752aafed3092c224f257855006aa35b43d101e6c8e59cbc4c20b07c81552963f189dea700e042d4b70c236a031a29a9273cc138e69dc1a5834491de4822d8cb6acf218789d2586cb0f3892236b0948ffaf8691f6fa04597caa45068f9be39b8ea8b5336a8c94e2696f872120778abcfea711e5fbf75f835f0f5204ccdd020013c2ceae25e9d1378a1d10cf86ca269eef48fee8ebb5e8dfb08f0c48d22d1a7162e080ec1f6e48541288aaaa1f2370f0688cf1786a32abed41df1d3b96b665794bf7a772743fc8b62d73901cea4569494c794a01ccc7dda0d42199f5b58739c0c0e280774b56ccf51993f5ea3d4954319"}, -+} -+ -+func TestSignPKCS1v15(t *testing.T) { -+ for i, test := range signPKCS1v15Tests { -+ h := sha1.New() -+ h.Write([]byte(test.in)) -+ digest := h.Sum(nil) -+ -+ s, err := SignPKCS1v15(nil, boringRsaPrivateKey, crypto.SHA1, digest) -+ if err != nil { -+ t.Errorf("#%d %s", i, err) -+ } -+ -+ expected, _ := hex.DecodeString(test.out) -+ if !bytes.Equal(s, expected) { -+ t.Errorf("#%d got: %x want: %x", i, s, expected) -+ } -+ } -+} -+ -+func TestVerifyPKCS1v15(t *testing.T) { -+ for i, test := range signPKCS1v15Tests { -+ h := sha1.New() -+ h.Write([]byte(test.in)) -+ digest := h.Sum(nil) -+ -+ sig, _ := hex.DecodeString(test.out) -+ -+ err := VerifyPKCS1v15(&boringRsaPrivateKey.PublicKey, crypto.SHA1, digest, sig) -+ if err != nil { -+ t.Errorf("#%d %s", i, err) -+ } -+ } -+} -+ -+func TestOverlongMessagePKCS1v15(t *testing.T) { -+ ciphertext := decodeBase64("fjOVdirUzFoLlukv80dBllMLjXythIf22feqPrNo0YoIjzyzyoMFiLjAc/Y4krkeZ11XFThIrEvw\nkRiZcCq5ng==") -+ _, err := DecryptPKCS1v15(nil, rsaPrivateKey, ciphertext) -+ if err == nil { -+ t.Error("RSA decrypted a message that was too long.") -+ } -+} -+ -+func TestUnpaddedSignature(t *testing.T) { -+ msg := []byte("Thu Dec 19 18:06:16 EST 2013\n") -+ // This base64 value was generated with: -+ // % echo Thu Dec 19 18:06:16 EST 2013 > /tmp/msg -+ // % openssl rsautl -sign -inkey key -out /tmp/sig -in /tmp/msg -+ // -+ // Where "key" contains the RSA private key given at the bottom of this -+ // file. -+ expectedSig := decodeBase64("XgDn6nJdfL/gY3eq15l9Va41/nNkDrkTlxOZYHYeFaMOW+Z4BHTCZ1LhqNBXOBK9XEyHho6okpY4rqE1zTIVX/kCGJ+jS6VRgUsHcTcpvKBYZCW84yrjE360gkntzkGxUF9FaiOGzmJKwBm1UvFgFIaYlvF+PdU0H1trBvm/RYRU42xOQRY1U+MSXgruFfINE20vPTlAG22uJ2CELrZUDykQGnrDFsEP0UqyyyiqGqxHt8E7iNYC6+xhPPC/ato9Bev08nu/U/EGH2imifSoNz/IN6h3fQClHwk1a74bPrcRsmUAAHOX2X1VKxK7IruinU8iOyoG6oFuvT+QlMnWAw==") -+ -+ sig, err := SignPKCS1v15(nil, boringRsaPrivateKey, crypto.Hash(0), msg) -+ if err != nil { -+ t.Fatalf("SignPKCS1v15 failed: %s", err) -+ } -+ if !bytes.Equal(sig, expectedSig) { -+ t.Fatalf("signature is not expected value: got %x, want %x", sig, expectedSig) -+ } -+ if err := VerifyPKCS1v15(&boringRsaPrivateKey.PublicKey, crypto.Hash(0), msg, sig); err != nil { -+ t.Fatalf("signature failed to verify: %s", err) -+ } -+} -+ -+func TestShortSessionKey(t *testing.T) { -+ if boring.Enabled() && !boringtest.Supports(t, "PKCSv1.5") { -+ t.Skip("skipping PKCS#1 v1.5 encryption test with BoringCrypto") -+ } -+ -+ // This tests that attempting to decrypt a session key where the -+ // ciphertext is too small doesn't run outside the array bounds. -+ ciphertext, err := EncryptPKCS1v15(rand.Reader, &rsaPrivateKey.PublicKey, []byte{1}) -+ if err != nil { -+ t.Fatalf("Failed to encrypt short message: %s", err) -+ } -+ -+ var key [32]byte -+ if err := DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, ciphertext, key[:]); err != nil { -+ t.Fatalf("Failed to decrypt short message: %s", err) -+ } -+ -+ for _, v := range key { -+ if v != 0 { -+ t.Fatal("key was modified when ciphertext was invalid") -+ } -+ } -+} -+ -+var rsaPrivateKey = parseKey(testingKey(`-----BEGIN RSA TESTING KEY----- -+MIIBOgIBAAJBALKZD0nEffqM1ACuak0bijtqE2QrI/KLADv7l3kK3ppMyCuLKoF0 -+fd7Ai2KW5ToIwzFofvJcS/STa6HA5gQenRUCAwEAAQJBAIq9amn00aS0h/CrjXqu -+/ThglAXJmZhOMPVn4eiu7/ROixi9sex436MaVeMqSNf7Ex9a8fRNfWss7Sqd9eWu -+RTUCIQDasvGASLqmjeffBNLTXV2A5g4t+kLVCpsEIZAycV5GswIhANEPLmax0ME/ -+EO+ZJ79TJKN5yiGBRsv5yvx5UiHxajEXAiAhAol5N4EUyq6I9w1rYdhPMGpLfk7A -+IU2snfRJ6Nq2CQIgFrPsWRCkV+gOYcajD17rEqmuLrdIRexpg8N1DOSXoJ8CIGlS -+tAboUGBxTDq3ZroNism3DaMIbKPyYrAqhKov1h5V -+-----END RSA TESTING KEY-----`)) -+ -+func parsePublicKey(s string) *PublicKey { -+ p, _ := pem.Decode([]byte(s)) -+ k, err := x509.ParsePKCS1PublicKey(p.Bytes) -+ if err != nil { -+ panic(err) -+ } -+ return k -+} -+ -+ -+var boringRsaPrivateKey = parseKey(testingKey(`-----BEGIN RSA TESTING KEY----- -+MIIEogIBAAKCAQEAp5qgUIj096pw8U+AjcJucLWenR3oe+tEthXiAuqcYgslW5UU -+lMim34U/h7NbLvbG2KJ2chUsmLtuCFaoIe/YKW5DKm3SPytK/KCBsVa+MQ7zuF/1 -+ks5p7yBqFBl6QTekMzwskt/zyDIG9f3A+38akruHNBvUgYqwbWPx4ycclQ52GSev -+/Cfx0I68TGT5SwN/eCJ/ghq3iGAf0mX1bkVaW1seKbL49aAA94KnDCRdl813+S2R -+EPDf2tZwlT0JpZm5QtAqthonZjkjHocZNxhkKF3XWUntE/+l6R4A+CWZlC2vmUc1 -+hJTEraksy2JUIjxAaq//FnDpIEVG/N2ofmNpaQIDAQABAoIBAAYH7h9fwkLcNvqz -+8+oF9k/ndSjtr9UvstYDhRG6S/zKLmK0g1xUOQ7/fjj9lvkiZ6bZd74krWlkizHR -+HnU0KnjZLyEKeR+NSQI8q1YMi0T8JwB6MX3CIDU62x5UiV3p6OZwEqGJXf4U8MOu -+ySAzo2rmxRd2reeobC9Pgp98I47oeqaSRwFVZRPfKk5RvfI7KRmL58BAB0XS56PA -+PJ+3l0fB/oIV11iaBEKildxLDtrvlepQ2KPNf7Dpk0/CPRtS/jxyxIyML8tjR3F0 -+KuHplsRjTANyzW/aHddO1fnfnXsVo+0PzSPTHCbxKSu5XmChqsKoB1jM+/tJci4y -+ST5hUXUCgYEAzfA5XEMkR/NNJMfR+FBbdfpQ1b0wqH3qtWZx/tBjKC2Y0XnDQ8ZR -+SEWONLVZMRtTlJaHIPZ9i6anQRR5harrff0OpsKiJUGDout8ehE6eiN8ABWGNlCI -+AiLCerVJZMDcSuDU7xsdHVIdSxYh88Z9g54vUQ4214BG/G0Qm1emV3UCgYEA0FjP -+wq5cEGt9xDCg+oXk0bLm4Wn4FkabJH7M+oCosHHY9W1vgvv50bpNoAbaB5r1mlan -+T6gEtkQPB2juMTnuIwRL+kvOmSKqZGlAsyrq8smTuBUv7brbybkYN3Rg51KV6u1J -+vCdGpMYWHUNRkkQ88cr6iFPodYU+CzRR4ABif6UCgYBc0jDYb/7TW0tjD5mJJZcD -+xw5WOE7NMuvuVT1+T6jRvDOL/yjOzH1oaMle4npQEvQKHgrMBa2ymyv5vmPDprU7 -+9Sp8aW+yASR281MIpelIkePbGdiDdKrI46fqrPlmqzLfoRT4rKzjwVYouNIW0VlT -+UKIdE54OZegY8IOysL/t3QKBgDZnSnECiIW9G80UCaUBO3vKZGFuA1sFutMvzSSI -+XgQc5lNH7TtdwqESLdzgjSQ5QXK4t92j+P8DDI2Zx8DQ6K76G0DTdLImDCpGFZ/z -+UABvxIPn/GjuRyAIlhs852Tf+seqiHt6Igc6tmGTx4QTD3rvzrW0e1ncnhPc6Jg+ -+YXoFAoGARD9OPrd4J2N+nkSWif9VOuPHvOXEczwBDJbsAGrOW1kTbDStF0OIVOt0 -+Ukj+mnnL8ZNyVLgTrZDRfXvlA94EbPK5/rMAYwjMlXHP8R22ts3eDMNUdw0/Zl1g -+QOhL8wXZcdwHKsONy55kZHo8pmneqi9EnqqLGguLwx5WIMzWvZ8= -+-----END RSA TESTING KEY-----`)) -+ -+func TestShortPKCS1v15Signature(t *testing.T) { -+ pub := parsePublicKey(`-----BEGIN RSA PUBLIC KEY----- -+MEgCQQCd9BVzo775lkohasxjnefF1nCMcNoibqIWEVDe/K7M2GSoO4zlSQB+gkix -+O3AnTcdHB51iaZpWfxPSnew8yfulAgMBAAE= -+-----END RSA PUBLIC KEY-----`) -+ sig, err := hex.DecodeString("193a310d0dcf64094c6e3a00c8219b80ded70535473acff72c08e1222974bb24a93a535b1dc4c59fc0e65775df7ba2007dd20e9193f4c4025a18a7070aee93") -+ if err != nil { -+ t.Fatalf("failed to decode signature: %s", err) -+ } -+ -+ h := sha256.Sum256([]byte("hello")) -+ err = VerifyPKCS1v15(pub, crypto.SHA256, h[:], sig) -+ if err == nil { -+ t.Fatal("VerifyPKCS1v15 accepted a truncated signature") -+ } -+} ->>>>>>> 70a351c141 (wip) -======= ->>>>>>> 80d9391199 (wip) -diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go -index 3a377cc9db..ce78a13d6f 100644 ---- a/src/crypto/rsa/pss.go -+++ b/src/crypto/rsa/pss.go -@@ -9,7 +9,7 @@ package rsa - import ( - "bytes" - "crypto" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "errors" - "hash" - "io" -@@ -214,7 +214,7 @@ func signPSSWithSalt(priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) ([ - return nil, err - } -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled { -+ if boring.Enabled() { - bkey, err := boringPrivateKey(priv) - if err != nil { - return nil, err -@@ -296,7 +296,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, - // well-specified number of random bytes is included in the signature, in a - // well-specified way. -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled && rand == boring.RandReader { -+ if boring.Enabled() && rand == boring.RandReader { - bkey, err := boringPrivateKey(priv) - if err != nil { - return nil, err -@@ -339,7 +339,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, - // argument may be nil, in which case sensible defaults are used. opts.Hash is - // ignored. - func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error { -- if boring.Enabled { -+ if boring.Enabled() { - bkey, err := boringPublicKey(pub) - if err != nil { - return err -diff --git a/src/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go -index 1226149321..befd1612b5 100644 ---- a/src/crypto/rsa/pss_test.go -+++ b/src/crypto/rsa/pss_test.go -@@ -79,7 +79,7 @@ func TestEMSAPSS(t *testing.T) { - // TestPSSGolden tests all the test vectors in pss-vect.txt from - // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip - func TestPSSGolden(t *testing.T) { -- if boring.Enabled && !boringtest.Supports(t, "SHA1") { -+ if boring.Enabled() && !boringtest.Supports(t, "SHA1") { - t.Skip("skipping PSS test with BoringCrypto: SHA-1 not allowed") - } - inFile, err := os.Open("testdata/pss-vect.txt.bz2") -@@ -173,7 +173,7 @@ func TestPSSGolden(t *testing.T) { - // TestPSSOpenSSL ensures that we can verify a PSS signature from OpenSSL with - // the default options. OpenSSL sets the salt length to be maximal. - func TestPSSOpenSSL(t *testing.T) { -- if boring.Enabled { -+ if boring.Enabled() { - t.Skip("skipping PSS test with BoringCrypto: too short key") - } -<<<<<<< HEAD - -@@ -209,7 +209,7 @@ func TestPSSNilOpts(t *testing.T) { - } - -======= - -@@ -209,7 +209,7 @@ func TestPSSNilOpts(t *testing.T) { - } - ->>>>>>> 0023bf4c7a (rebase) - func TestPSSSigning(t *testing.T) { -- if boring.Enabled && !boringtest.Supports(t, "SHA1") { -+ if boring.Enabled() && !boringtest.Supports(t, "SHA1") { - t.Skip("skipping PSS test with BoringCrypto: too short key") - } -<<<<<<< HEAD - -diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go -index ad860d7f0c..86f700bee2 100644 -======= - -diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go -index f0aef1f542..e6bf6a5e88 100644 ->>>>>>> 0023bf4c7a (rebase) ---- a/src/crypto/rsa/rsa.go -+++ b/src/crypto/rsa/rsa.go -@@ -28,8 +28,8 @@ package rsa - import ( - "crypto" - "crypto/internal/bigmod" -- "crypto/internal/boring" -- "crypto/internal/boring/bbig" -+ boring "crypto/internal/backend" -+ "crypto/internal/backend/bbig" - "crypto/internal/randutil" - "crypto/rand" - "crypto/subtle" -@@ -294,7 +294,7 @@ func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) { - func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error) { - randutil.MaybeReadByte(random) -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled && random == boring.RandReader && nprimes == 2 && -+ if boring.Enabled() && random == boring.RandReader && nprimes == 2 && - (bits == 2048 || bits == 3072 || bits == 4096) { - bN, bE, bD, bP, bQ, bDp, bDq, bQinv, err := boring.GenerateKeyRSA(bits) - if err != nil { -@@ -529,7 +529,7 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l - return nil, ErrMessageTooLong - } -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled && random == boring.RandReader { -+ if boring.Enabled() && random == boring.RandReader { - bkey, err := boringPublicKey(pub) - if err != nil { - return nil, err -@@ -558,7 +558,7 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l - mgf1XOR(db, hash, seed) - mgf1XOR(seed, hash, db) -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled { -+ if boring.Enabled() { - var bkey *boring.PublicKeyRSA - bkey, err = boringPublicKey(pub) - if err != nil { -@@ -719,7 +719,7 @@ func decryptOAEP(hash, mgfHash hash.Hash, random io.Reader, priv *PrivateKey, ci - return nil, ErrDecryption - } -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled { -+ if boring.Enabled() { - bkey, err := boringPrivateKey(priv) - if err != nil { - return nil, err -diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go -index b994daec19..4b7427e1ae 100644 ---- a/src/crypto/rsa/rsa_test.go -+++ b/src/crypto/rsa/rsa_test.go -@@ -8,7 +8,7 @@ import ( - "bufio" - "bytes" - "crypto" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/rand" - . "crypto/rsa" - "crypto/sha1" -@@ -34,7 +34,7 @@ func TestKeyGeneration(t *testing.T) { - if bits := priv.N.BitLen(); bits != size { - t.Errorf("key too short (%d vs %d)", bits, size) - } -- if boring.Enabled && size < 1024 { -+ if boring.Enabled() && size < 1024 { - t.Logf("skipping short key with BoringCrypto: %d", size) - continue - } -@@ -120,12 +120,12 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) { - t.Errorf("private exponent too large") - } -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled { -+ if boring.Enabled() { - // Cannot call encrypt/decrypt with raw RSA. PKCSv1.5 - // not supported in some configurations. Test with - // OAEP if possible (i.e., key size is equal to or - // longer than 2048 bits). -- if bits := priv.N.BitLen(); boring.Enabled && bits < 2048 { -+ if bits := priv.N.BitLen(); boring.Enabled() && bits < 2048 { - t.Logf("skipping short key with BoringCrypto: %d", bits) - return - } -@@ -167,7 +167,7 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) { - } -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - func TestAllocations(t *testing.T) { -- if boring.Enabled { -+ if boring.Enabled() { - t.Skip("skipping allocations test with BoringCrypto") - } - testenv.SkipIfOptimizationOff(t) -@@ -213,7 +213,7 @@ func TestEverything(t *testing.T) { - if bits := priv.N.BitLen(); bits != size { - t.Errorf("key too short (%d vs %d)", bits, size) - } -- if boring.Enabled && size < 2048 { -+ if boring.Enabled() && size < 2048 { - t.Skip("skipping short key with BoringCrypto") - } - testEverything(t, priv) -@@ -667,7 +667,7 @@ func TestEncryptOAEP(t *testing.T) { - n := new(big.Int) - for i, test := range testEncryptOAEPData { - n.SetString(test.modulus, 16) -- if boring.Enabled { -+ if boring.Enabled() { - t.Log("skipping test in FIPS mode due to short keys and unpadded RSA operations not allowed with FIPS") - continue - } -@@ -694,7 +694,7 @@ func TestDecryptOAEP(t *testing.T) { - d := new(big.Int) - for i, test := range testEncryptOAEPData { - n.SetString(test.modulus, 16) -- if boring.Enabled && !boringtest.Supports(t, "RSA1024") && n.BitLen() < 2048 { -+ if boring.Enabled() && !boringtest.Supports(t, "RSA1024") && n.BitLen() < 2048 { - t.Logf("skipping encryption tests with BoringCrypto: too short key: %d", n.BitLen()) - continue - } -@@ -741,7 +741,7 @@ func Test2DecryptOAEP(t *testing.T) { - sha1 := crypto.SHA1 - sha256 := crypto.SHA256 -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled && n.BitLen() < 2048 { -+ if boring.Enabled() && n.BitLen() < 2048 { - t.Skipf("skipping encryption tests with BoringCrypto: too short key: %d", n.BitLen()) - } -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) -@@ -760,7 +760,7 @@ func TestEncryptDecryptOAEP(t *testing.T) { - d := new(big.Int) - for i, test := range testEncryptOAEPData { - n.SetString(test.modulus, 16) -- if boring.Enabled && !boringtest.Supports(t, "RSA1024") && n.BitLen() < 2048 { -+ if boring.Enabled() && !boringtest.Supports(t, "RSA1024") && n.BitLen() < 2048 { - t.Logf("skipping encryption tests with BoringCrypto: too short key: %d", n.BitLen()) - continue - } -diff --git a/src/crypto/sha1/boring.go b/src/crypto/sha1/boring.go -index b5786d1bf4..9bd03f3940 100644 ---- a/src/crypto/sha1/boring.go -+++ b/src/crypto/sha1/boring.go -@@ -12,11 +12,11 @@ - package sha1 -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - import ( -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "hash" - ) -<<<<<<< HEAD - --const boringEnabled = boring.Enabled -+var boringEnabled = boring.Enabled() - - func boringNewSHA1() hash.Hash { return boring.NewSHA1() } - -======= - --const boringEnabled = boring.Enabled -+var boringEnabled = boring.Enabled() - - func boringNewSHA1() hash.Hash { return boring.NewSHA1() } - -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 0023bf4c7a (rebase) -======= -diff --git a/src/crypto/sha1/boring.go-e b/src/crypto/sha1/boring.go-e -new file mode 100644 -index 0000000000..9bd03f3940 ---- /dev/null -+++ b/src/crypto/sha1/boring.go-e -@@ -0,0 +1,25 @@ -+// Copyright 2009 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. -+ -+// Extra indirection here so that when building go_bootstrap -+// cmd/internal/boring is not even imported, so that we don't -+// have to maintain changes to cmd/dist's deps graph. -+ -+//go:build !cmd_go_bootstrap && cgo -+// +build !cmd_go_bootstrap,cgo -+ -+package sha1 -+ -+import ( -+ boring "crypto/internal/backend" -+ "hash" -+) -+ -+var boringEnabled = boring.Enabled() -+ -+func boringNewSHA1() hash.Hash { return boring.NewSHA1() } -+ -+func boringUnreachable() { boring.Unreachable() } -+ -+func boringSHA1(p []byte) [20]byte { return boring.SHA1(p) } -diff --git a/src/crypto/sha1/example_test.go-e b/src/crypto/sha1/example_test.go-e -new file mode 100644 -index 0000000000..499055cc96 ---- /dev/null -+++ b/src/crypto/sha1/example_test.go-e -@@ -0,0 +1,42 @@ -+// Copyright 2009 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. -+ -+package sha1_test -+ -+import ( -+ "crypto/sha1" -+ "fmt" -+ "io" -+ "log" -+ "os" -+) -+ -+func ExampleNew() { -+ h := sha1.New() -+ io.WriteString(h, "His money is twice tainted:") -+ io.WriteString(h, " 'taint yours and 'taint mine.") -+ fmt.Printf("% x", h.Sum(nil)) -+ // Output: 59 7f 6a 54 00 10 f9 4c 15 d7 18 06 a9 9a 2c 87 10 e7 47 bd -+} -+ -+func ExampleSum() { -+ data := []byte("This page intentionally left blank.") -+ fmt.Printf("% x", sha1.Sum(data)) -+ // Output: af 06 49 23 bb f2 30 15 96 aa c4 c2 73 ba 32 17 8e bc 4a 96 -+} -+ -+func ExampleNew_file() { -+ f, err := os.Open("file.txt") -+ if err != nil { -+ log.Fatal(err) -+ } -+ defer f.Close() -+ -+ h := sha1.New() -+ if _, err := io.Copy(h, f); err != nil { -+ log.Fatal(err) -+ } -+ -+ fmt.Printf("% x", h.Sum(nil)) -+} -diff --git a/src/crypto/sha1/fallback_test.go-e b/src/crypto/sha1/fallback_test.go-e -new file mode 100644 -index 0000000000..45d1f57d39 ---- /dev/null -+++ b/src/crypto/sha1/fallback_test.go-e -@@ -0,0 +1,34 @@ -+// Copyright 2016 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 s390x -+ -+package sha1 -+ -+import ( -+ "fmt" -+ "io" -+ "testing" -+) -+ -+// Tests the fallback code path in case the optimized asm -+// implementation cannot be used. -+// See also TestBlockGeneric. -+func TestGenericPath(t *testing.T) { -+ if useAsm == false { -+ t.Skipf("assembly implementation unavailable") -+ } -+ useAsm = false -+ defer func() { useAsm = true }() -+ c := New() -+ in := "ΑΒΓΔΕϜΖΗΘΙΚΛΜΝΞΟΠϺϘΡΣΤΥΦΧΨΩ" -+ gold := "0f58c2bb130f8182375f325c18342215255387e5" -+ if _, err := io.WriteString(c, in); err != nil { -+ t.Fatalf("could not write to c: %v", err) -+ } -+ out := fmt.Sprintf("%x", c.Sum(nil)) -+ if out != gold { -+ t.Fatalf("mismatch: got %s, wanted %s", out, gold) -+ } -+} -diff --git a/src/crypto/sha1/issue15617_test.go-e b/src/crypto/sha1/issue15617_test.go-e -new file mode 100644 -index 0000000000..116c78ff74 ---- /dev/null -+++ b/src/crypto/sha1/issue15617_test.go-e -@@ -0,0 +1,27 @@ -+// Copyright 2016 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 amd64 && (linux || darwin) -+ -+package sha1_test -+ -+import ( -+ "crypto/sha1" -+ "syscall" -+ "testing" -+) -+ -+func TestOutOfBoundsRead(t *testing.T) { -+ const pageSize = 4 << 10 -+ data, err := syscall.Mmap(0, 0, 2*pageSize, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE) -+ if err != nil { -+ panic(err) -+ } -+ if err := syscall.Mprotect(data[pageSize:], syscall.PROT_NONE); err != nil { -+ panic(err) -+ } -+ for i := 0; i < pageSize; i++ { -+ sha1.Sum(data[pageSize-i : pageSize]) -+ } -+} ->>>>>>> 70a351c141 (wip) -======= ->>>>>>> 80d9391199 (wip) -diff --git a/src/crypto/sha1/notboring.go b/src/crypto/sha1/notboring.go -index 42ef87937f..c1a3205539 100644 ---- a/src/crypto/sha1/notboring.go -+++ b/src/crypto/sha1/notboring.go -@@ -11,10 +11,10 @@ import ( - "hash" - ) -<<<<<<< HEAD - --const boringEnabled = false -+var boringEnabled = false - --func boringNewSHA1() hash.Hash { panic("boringcrypto: not available") } -+func boringNewSHA1() hash.Hash { panic("!no_openssl: not available") } - - func boringUnreachable() {} - -======= - --const boringEnabled = false -+var boringEnabled = false - --func boringNewSHA1() hash.Hash { panic("boringcrypto: not available") } -+func boringNewSHA1() hash.Hash { panic("!no_openssl: not available") } - - func boringUnreachable() {} - ->>>>>>> 0023bf4c7a (rebase) --func boringSHA1([]byte) [20]byte { panic("boringcrypto: not available") } -+func boringSHA1([]byte) [20]byte { panic("!no_openssl: not available") } -diff --git a/src/crypto/sha1/sha1_test.go b/src/crypto/sha1/sha1_test.go -index 85ed126091..71f4b46663 100644 ---- a/src/crypto/sha1/sha1_test.go -+++ b/src/crypto/sha1/sha1_test.go -@@ -8,7 +8,7 @@ package sha1 -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - import ( - "bytes" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/rand" - "encoding" - "fmt" -@@ -78,7 +78,7 @@ func TestGolden(t *testing.T) { - io.WriteString(c, g.in[len(g.in)/2:]) - sum = c.Sum(nil) - case 3: -- if boring.Enabled { -+ if boring.Enabled() { - continue - } - io.WriteString(c, g.in[0:len(g.in)/2]) -@@ -145,7 +145,7 @@ func TestBlockSize(t *testing.T) { -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - // Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match. - func TestBlockGeneric(t *testing.T) { -- if boring.Enabled { -+ if boring.Enabled() { - t.Skip("BoringCrypto doesn't expose digest") - } - for i := 1; i < 30; i++ { // arbitrary factor -@@ -218,7 +218,7 @@ func TestLargeHashes(t *testing.T) { - } -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - func TestAllocations(t *testing.T) { -- if boring.Enabled { -+ if boring.Enabled() { - t.Skip("BoringCrypto doesn't allocate the same way as stdlib") - } - in := []byte("hello, world!") -diff --git a/src/crypto/sha256/sha256.go b/src/crypto/sha256/sha256.go -index 2deafbc9fc..282c326b32 100644 ---- a/src/crypto/sha256/sha256.go -+++ b/src/crypto/sha256/sha256.go -@@ -8,7 +8,7 @@ package sha256 -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - import ( - "crypto" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "encoding/binary" - "errors" - "hash" -@@ -148,7 +148,7 @@ func (d *digest) Reset() { - // encoding.BinaryUnmarshaler to marshal and unmarshal the internal - // state of the hash. - func New() hash.Hash { -- if boring.Enabled { -+ if boring.Enabled() { - return boring.NewSHA256() - } - d := new(digest) -@@ -158,7 +158,7 @@ func New() hash.Hash { -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - // New224 returns a new hash.Hash computing the SHA224 checksum. - func New224() hash.Hash { -- if boring.Enabled { -+ if boring.Enabled() { - return boring.NewSHA224() - } - d := new(digest) -@@ -251,7 +251,7 @@ func (d *digest) checkSum() [Size]byte { -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - // Sum256 returns the SHA256 checksum of the data. - func Sum256(data []byte) [Size]byte { -- if boring.Enabled { -+ if boring.Enabled() { - return boring.SHA256(data) - } - var d digest -@@ -262,7 +262,7 @@ func Sum256(data []byte) [Size]byte { -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - // Sum224 returns the SHA224 checksum of the data. - func Sum224(data []byte) [Size224]byte { -- if boring.Enabled { -+ if boring.Enabled() { - return boring.SHA224(data) - } - var d digest -diff --git a/src/crypto/sha256/sha256_test.go b/src/crypto/sha256/sha256_test.go -index 7304678346..a073d31119 100644 ---- a/src/crypto/sha256/sha256_test.go -+++ b/src/crypto/sha256/sha256_test.go -@@ -8,7 +8,7 @@ package sha256 -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - import ( - "bytes" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/rand" - "encoding" - "fmt" -@@ -217,7 +217,7 @@ func TestBlockSize(t *testing.T) { -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - // Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match. - func TestBlockGeneric(t *testing.T) { -- if boring.Enabled { -+ if boring.Enabled() { - t.Skip("BoringCrypto doesn't expose digest") - } - gen, asm := New().(*digest), New().(*digest) -@@ -294,7 +294,7 @@ func TestLargeHashes(t *testing.T) { - } -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - func TestAllocations(t *testing.T) { -- if boring.Enabled { -+ if boring.Enabled() { - t.Skip("BoringCrypto doesn't allocate the same way as stdlib") - } - in := []byte("hello, world!") -diff --git a/src/crypto/sha512/sha512.go b/src/crypto/sha512/sha512.go -index 9ae1b3aae2..e56eedb201 100644 ---- a/src/crypto/sha512/sha512.go -+++ b/src/crypto/sha512/sha512.go -@@ -12,7 +12,7 @@ package sha512 -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - import ( - "crypto" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "encoding/binary" - "errors" - "hash" -@@ -206,7 +206,7 @@ func consumeUint64(b []byte) ([]byte, uint64) { -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - // New returns a new hash.Hash computing the SHA-512 checksum. - func New() hash.Hash { -- if boring.Enabled { -+ if boring.Enabled() { - return boring.NewSHA512() - } - d := &digest{function: crypto.SHA512} -@@ -230,7 +230,7 @@ func New512_256() hash.Hash { -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - // New384 returns a new hash.Hash computing the SHA-384 checksum. - func New384() hash.Hash { -- if boring.Enabled { -+ if boring.Enabled() { - return boring.NewSHA384() - } - d := &digest{function: crypto.SHA384} -@@ -341,7 +341,7 @@ func (d *digest) checkSum() [Size]byte { -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - // Sum512 returns the SHA512 checksum of the data. - func Sum512(data []byte) [Size]byte { -- if boring.Enabled { -+ if boring.Enabled() { - return boring.SHA512(data) - } - d := digest{function: crypto.SHA512} -@@ -352,7 +352,7 @@ func Sum512(data []byte) [Size]byte { -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - // Sum384 returns the SHA384 checksum of the data. - func Sum384(data []byte) [Size384]byte { -- if boring.Enabled { -+ if boring.Enabled() { - return boring.SHA384(data) - } - d := digest{function: crypto.SHA384} -diff --git a/src/crypto/sha512/sha512_test.go b/src/crypto/sha512/sha512_test.go -index 921cdbb7bb..a35165bcbf 100644 ---- a/src/crypto/sha512/sha512_test.go -+++ b/src/crypto/sha512/sha512_test.go -@@ -8,7 +8,7 @@ package sha512 -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - import ( - "bytes" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/rand" - "encoding" - "encoding/hex" -@@ -823,7 +823,7 @@ func TestBlockSize(t *testing.T) { -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - // Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match. - func TestBlockGeneric(t *testing.T) { -- if boring.Enabled { -+ if boring.Enabled() { - t.Skip("BoringCrypto doesn't expose digest") - } - gen, asm := New().(*digest), New().(*digest) -@@ -893,7 +893,7 @@ func TestLargeHashes(t *testing.T) { - } -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - func TestAllocations(t *testing.T) { -- if boring.Enabled { -+ if boring.Enabled() { - t.Skip("BoringCrypto doesn't allocate the same way as stdlib") - } - in := []byte("hello, world!") -diff --git a/src/crypto/tls/boring.go b/src/crypto/tls/boring.go -index 140b1a3dd8..fe6fa96d28 100644 ---- a/src/crypto/tls/boring.go -+++ b/src/crypto/tls/boring.go -@@ -2,7 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -<<<<<<< HEAD - --//go:build boringcrypto -+//go:build !no_openssl - - package tls - -@@ -12,7 +12,7 @@ import ( - ) - -======= - --//go:build boringcrypto -+//go:build !no_openssl - - package tls - -@@ -12,7 +12,7 @@ import ( - ) - ->>>>>>> 0023bf4c7a (rebase) - func init() { -- if boring.Enabled && !boring.ExecutingTest() { -+ if boring.Enabled() && !boring.ExecutingTest() { - fipstls.Force() - } - } -diff --git a/src/crypto/tls/boring_test.go b/src/crypto/tls/boring_test.go -index 7bfe3f9417..49702f59ba 100644 ---- a/src/crypto/tls/boring_test.go -+++ b/src/crypto/tls/boring_test.go -@@ -2,14 +2,14 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -<<<<<<< HEAD - --//go:build boringcrypto -+//go:build !no_openssl - - package tls - -======= - --//go:build boringcrypto -+//go:build !no_openssl - - package tls - ->>>>>>> 0023bf4c7a (rebase) - import ( - "crypto/ecdsa" - "crypto/elliptic" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/backend/boringtest" - "crypto/internal/boring/fipstls" - "crypto/rand" -@@ -46,7 +46,7 @@ func TestBoringServerProtocolVersion(t *testing.T) { - test("VersionTLS10", VersionTLS10, "") - test("VersionTLS11", VersionTLS11, "") - test("VersionTLS12", VersionTLS12, "") -- if boring.Enabled && !boring.SupportsHKDF() { -+ if boring.Enabled() && !boring.SupportsHKDF() { - test("VersionTLS13", VersionTLS13, "client offered only unsupported versions") - } else { - test("VersionTLS13", VersionTLS13, "") -@@ -238,7 +238,7 @@ func TestBoringServerSignatureAndHash(t *testing.T) { -<<<<<<< HEAD - - clientConfig := testConfig.Clone() - -======= - - clientConfig := testConfig.Clone() - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled { -+ if boring.Enabled() { - serverConfig.Rand = boring.RandReader - clientConfig.Rand = boring.RandReader - } -@@ -369,7 +369,7 @@ func TestBoringCertAlgs(t *testing.T) { - serverConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}} - serverConfig.BuildNameToCertificate() -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled { -+ if boring.Enabled() { - serverConfig.Rand = boring.RandReader - clientConfig.Rand = boring.RandReader - } -@@ -400,13 +400,13 @@ func TestBoringCertAlgs(t *testing.T) { - serverConfig := testConfig.Clone() - serverConfig.ClientCAs = pool - serverConfig.ClientAuth = RequireAndVerifyClientCert -- if boring.Enabled { -+ if boring.Enabled() { - serverConfig.Certificates[0].Certificate = [][]byte{testRSA2048Certificate} - serverConfig.Certificates[0].PrivateKey = testRSA2048PrivateKey - serverConfig.BuildNameToCertificate() - } -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) -- if boring.Enabled { -+ if boring.Enabled() { - serverConfig.Rand = boring.RandReader - clientConfig.Rand = boring.RandReader - } -@@ -432,8 +432,8 @@ func TestBoringCertAlgs(t *testing.T) { - // exhaustive test with computed answers. - r1pool := x509.NewCertPool() - r1pool.AddCert(R1.cert) -- testServerCert(t, "basic", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, !(L2_I.notBoring && boring.Enabled)) -- testClientCert(t, "basic (client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, !(L2_I.notBoring && boring.Enabled)) -+ testServerCert(t, "basic", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, !(L2_I.notBoring && boring.Enabled())) -+ testClientCert(t, "basic (client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, !(L2_I.notBoring && boring.Enabled())) - fipstls.Force() - testServerCert(t, "basic (fips)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false) - testClientCert(t, "basic (fips, client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false) -@@ -454,7 +454,7 @@ func TestBoringCertAlgs(t *testing.T) { - leaf = L2_I - } - for i := 0; i < 64; i++ { -- reachable := map[string]bool{leaf.parentOrg: !(leaf.notBoring && boring.Enabled)} -+ reachable := map[string]bool{leaf.parentOrg: !(leaf.notBoring && boring.Enabled())} - reachableFIPS := map[string]bool{leaf.parentOrg: leaf.fipsOK} - list := [][]byte{leaf.der} - listName := leaf.name -@@ -462,7 +462,7 @@ func TestBoringCertAlgs(t *testing.T) { - if cond != 0 { - list = append(list, c.der) - listName += "," + c.name -- if reachable[c.org] && !(c.notBoring && boring.Enabled) { -+ if reachable[c.org] && !(c.notBoring && boring.Enabled()) { - reachable[c.parentOrg] = true - } - if reachableFIPS[c.org] && c.fipsOK { -@@ -486,7 +486,7 @@ func TestBoringCertAlgs(t *testing.T) { - if cond != 0 { - rootName += "," + c.name - pool.AddCert(c.cert) -- if reachable[c.org] && !(c.notBoring && boring.Enabled) { -+ if reachable[c.org] && !(c.notBoring && boring.Enabled()) { - shouldVerify = true - } - if reachableFIPS[c.org] && c.fipsOK { -diff --git a/src/crypto/tls/cipher_suites.go b/src/crypto/tls/cipher_suites.go -index 669208bb86..15a44e8cf6 100644 ---- a/src/crypto/tls/cipher_suites.go -+++ b/src/crypto/tls/cipher_suites.go -@@ -10,7 +10,7 @@ import ( - "crypto/cipher" - "crypto/des" - "crypto/hmac" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/rc4" - "crypto/sha1" - "crypto/sha256" -@@ -422,7 +422,7 @@ func macSHA1(key []byte) hash.Hash { - h := sha1.New - // The BoringCrypto SHA1 does not have a constant-time - // checksum function, so don't try to use it. -- if !boring.Enabled { -+ if !boring.Enabled() { - h = newConstantTimeHash(h) - } - return hmac.New(h, key) -@@ -514,7 +514,7 @@ func aeadAESGCM(key, noncePrefix []byte) aead { - panic(err) - } - var aead cipher.AEAD -- if boring.Enabled { -+ if boring.Enabled() { - aead, err = boring.NewGCMTLS(aes) - } else { - boring.Unreachable() -diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go -index 5edbd19995..a72d4855c1 100644 ---- a/src/crypto/tls/common.go -+++ b/src/crypto/tls/common.go -@@ -12,7 +12,7 @@ import ( - "crypto/ecdsa" - "crypto/ed25519" - "crypto/elliptic" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/rand" - "crypto/rsa" - "crypto/sha512" -@@ -1032,7 +1032,7 @@ const roleServer = false - func (c *Config) supportedVersions(isClient bool) []uint16 { - versions := make([]uint16, 0, len(supportedVersions)) - for _, v := range supportedVersions { -- if boring.Enabled && !boring.SupportsHKDF() && v > VersionTLS12 { -+ if boring.Enabled() && !boring.SupportsHKDF() && v > VersionTLS12 { - continue - } - if needFIPS() && (v < fipsMinVersion(c) || v > fipsMaxVersion(c)) { -diff --git a/src/crypto/tls/key_schedule.go b/src/crypto/tls/key_schedule.go -index e7a360fdd4..9ea9eed2fb 100644 ---- a/src/crypto/tls/key_schedule.go -+++ b/src/crypto/tls/key_schedule.go -@@ -7,7 +7,7 @@ package tls - import ( - "crypto/ecdh" - "crypto/hmac" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "errors" - "fmt" - "hash" -@@ -60,7 +60,7 @@ func (c *cipherSuiteTLS13) expandLabel(secret []byte, label string, context []by - panic(fmt.Errorf("failed to construct HKDF label: %s", err)) - } - out := make([]byte, length) -- if boring.Enabled { -+ if boring.Enabled() { - reader, err := boring.ExpandHKDF(c.hash.New, secret, hkdfLabelBytes) - if err != nil { - panic("tls: HKDF-Expand-Label invocation failed unexpectedly") -@@ -91,7 +91,7 @@ func (c *cipherSuiteTLS13) extract(newSecret, currentSecret []byte) []byte { - if newSecret == nil { - newSecret = make([]byte, c.hash.Size()) - } -- if boring.Enabled { -+ if boring.Enabled() { - ikm, err := boring.ExtractHKDF(c.hash.New, newSecret, currentSecret) - if err != nil { - panic("tls: HKDF-Extract invocation failed unexpectedly") -diff --git a/src/crypto/tls/notboring.go b/src/crypto/tls/notboring.go -index 7d85b39c59..fe2719485b 100644 ---- a/src/crypto/tls/notboring.go -+++ b/src/crypto/tls/notboring.go -@@ -2,7 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -<<<<<<< HEAD - --//go:build !boringcrypto -+//go:build no_openssl - - package tls - -======= - --//go:build !boringcrypto -+//go:build no_openssl - - package tls - -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 0023bf4c7a (rebase) -======= -diff --git a/src/crypto/tls/notboring.go-e b/src/crypto/tls/notboring.go-e -new file mode 100644 -index 0000000000..fe2719485b ---- /dev/null -+++ b/src/crypto/tls/notboring.go-e -@@ -0,0 +1,20 @@ -+// Copyright 2022 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 no_openssl -+ -+package tls -+ -+func needFIPS() bool { return false } -+ -+func supportedSignatureAlgorithms() []SignatureScheme { -+ return defaultSupportedSignatureAlgorithms -+} -+ -+func fipsMinVersion(c *Config) uint16 { panic("fipsMinVersion") } -+func fipsMaxVersion(c *Config) uint16 { panic("fipsMaxVersion") } -+func fipsCurvePreferences(c *Config) []CurveID { panic("fipsCurvePreferences") } -+func fipsCipherSuites(c *Config) []uint16 { panic("fipsCipherSuites") } -+ -+var fipsSupportedSignatureAlgorithms []SignatureScheme -diff --git a/src/crypto/tls/prf.go-e b/src/crypto/tls/prf.go-e -new file mode 100644 -index 0000000000..20bac96e86 ---- /dev/null -+++ b/src/crypto/tls/prf.go-e -@@ -0,0 +1,292 @@ -+// Copyright 2009 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. -+ -+package tls -+ -+import ( -+ "crypto" -+ "crypto/hmac" -+ "crypto/md5" -+ "crypto/sha1" -+ "crypto/sha256" -+ "crypto/sha512" -+ "errors" -+ "fmt" -+ "hash" -+) -+ -+// Split a premaster secret in two as specified in RFC 4346, Section 5. -+func splitPreMasterSecret(secret []byte) (s1, s2 []byte) { -+ s1 = secret[0 : (len(secret)+1)/2] -+ s2 = secret[len(secret)/2:] -+ return -+} -+ -+// pHash implements the P_hash function, as defined in RFC 4346, Section 5. -+func pHash(result, secret, seed []byte, hash func() hash.Hash) { -+ h := hmac.New(hash, secret) -+ h.Write(seed) -+ a := h.Sum(nil) -+ -+ j := 0 -+ for j < len(result) { -+ h.Reset() -+ h.Write(a) -+ h.Write(seed) -+ b := h.Sum(nil) -+ copy(result[j:], b) -+ j += len(b) -+ -+ h.Reset() -+ h.Write(a) -+ a = h.Sum(nil) -+ } -+} -+ -+// prf10 implements the TLS 1.0 pseudo-random function, as defined in RFC 2246, Section 5. -+func prf10(result, secret, label, seed []byte) { -+ hashSHA1 := sha1.New -+ hashMD5 := md5.New -+ -+ labelAndSeed := make([]byte, len(label)+len(seed)) -+ copy(labelAndSeed, label) -+ copy(labelAndSeed[len(label):], seed) -+ -+ s1, s2 := splitPreMasterSecret(secret) -+ pHash(result, s1, labelAndSeed, hashMD5) -+ result2 := make([]byte, len(result)) -+ pHash(result2, s2, labelAndSeed, hashSHA1) -+ -+ for i, b := range result2 { -+ result[i] ^= b -+ } -+} -+ -+// prf12 implements the TLS 1.2 pseudo-random function, as defined in RFC 5246, Section 5. -+func prf12(hashFunc func() hash.Hash) func(result, secret, label, seed []byte) { -+ return func(result, secret, label, seed []byte) { -+ labelAndSeed := make([]byte, len(label)+len(seed)) -+ copy(labelAndSeed, label) -+ copy(labelAndSeed[len(label):], seed) -+ -+ pHash(result, secret, labelAndSeed, hashFunc) -+ } -+} -+ -+const ( -+ masterSecretLength = 48 // Length of a master secret in TLS 1.1. -+ finishedVerifyLength = 12 // Length of verify_data in a Finished message. -+) -+ -+var masterSecretLabel = []byte("master secret") -+var extendedMasterSecretLabel = []byte("extended master secret") -+var keyExpansionLabel = []byte("key expansion") -+var clientFinishedLabel = []byte("client finished") -+var serverFinishedLabel = []byte("server finished") -+ -+func prfAndHashForVersion(version uint16, suite *cipherSuite) (func(result, secret, label, seed []byte), crypto.Hash) { -+ switch version { -+ case VersionTLS10, VersionTLS11: -+ return prf10, crypto.Hash(0) -+ case VersionTLS12: -+ if suite.flags&suiteSHA384 != 0 { -+ return prf12(sha512.New384), crypto.SHA384 -+ } -+ return prf12(sha256.New), crypto.SHA256 -+ default: -+ panic("unknown version") -+ } -+} -+ -+func prfForVersion(version uint16, suite *cipherSuite) func(result, secret, label, seed []byte) { -+ prf, _ := prfAndHashForVersion(version, suite) -+ return prf -+} -+ -+// masterFromPreMasterSecret generates the master secret from the pre-master -+// secret. See RFC 5246, Section 8.1. -+func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte { -+ seed := make([]byte, 0, len(clientRandom)+len(serverRandom)) -+ seed = append(seed, clientRandom...) -+ seed = append(seed, serverRandom...) -+ -+ masterSecret := make([]byte, masterSecretLength) -+ prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed) -+ return masterSecret -+} -+ -+// extMasterFromPreMasterSecret generates the extended master secret from the -+// pre-master secret. See RFC 7627. -+func extMasterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, transcript []byte) []byte { -+ masterSecret := make([]byte, masterSecretLength) -+ prfForVersion(version, suite)(masterSecret, preMasterSecret, extendedMasterSecretLabel, transcript) -+ return masterSecret -+} -+ -+// keysFromMasterSecret generates the connection keys from the master -+// secret, given the lengths of the MAC key, cipher key and IV, as defined in -+// RFC 2246, Section 6.3. -+func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) { -+ seed := make([]byte, 0, len(serverRandom)+len(clientRandom)) -+ seed = append(seed, serverRandom...) -+ seed = append(seed, clientRandom...) -+ -+ n := 2*macLen + 2*keyLen + 2*ivLen -+ keyMaterial := make([]byte, n) -+ prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed) -+ clientMAC = keyMaterial[:macLen] -+ keyMaterial = keyMaterial[macLen:] -+ serverMAC = keyMaterial[:macLen] -+ keyMaterial = keyMaterial[macLen:] -+ clientKey = keyMaterial[:keyLen] -+ keyMaterial = keyMaterial[keyLen:] -+ serverKey = keyMaterial[:keyLen] -+ keyMaterial = keyMaterial[keyLen:] -+ clientIV = keyMaterial[:ivLen] -+ keyMaterial = keyMaterial[ivLen:] -+ serverIV = keyMaterial[:ivLen] -+ return -+} -+ -+func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash { -+ var buffer []byte -+ if version >= VersionTLS12 { -+ buffer = []byte{} -+ } -+ -+ prf, hash := prfAndHashForVersion(version, cipherSuite) -+ if hash != 0 { -+ return finishedHash{hash.New(), hash.New(), nil, nil, buffer, version, prf} -+ } -+ -+ return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), buffer, version, prf} -+} -+ -+// A finishedHash calculates the hash of a set of handshake messages suitable -+// for including in a Finished message. -+type finishedHash struct { -+ client hash.Hash -+ server hash.Hash -+ -+ // Prior to TLS 1.2, an additional MD5 hash is required. -+ clientMD5 hash.Hash -+ serverMD5 hash.Hash -+ -+ // In TLS 1.2, a full buffer is sadly required. -+ buffer []byte -+ -+ version uint16 -+ prf func(result, secret, label, seed []byte) -+} -+ -+func (h *finishedHash) Write(msg []byte) (n int, err error) { -+ h.client.Write(msg) -+ h.server.Write(msg) -+ -+ if h.version < VersionTLS12 { -+ h.clientMD5.Write(msg) -+ h.serverMD5.Write(msg) -+ } -+ -+ if h.buffer != nil { -+ h.buffer = append(h.buffer, msg...) -+ } -+ -+ return len(msg), nil -+} -+ -+func (h finishedHash) Sum() []byte { -+ if h.version >= VersionTLS12 { -+ return h.client.Sum(nil) -+ } -+ -+ out := make([]byte, 0, md5.Size+sha1.Size) -+ out = h.clientMD5.Sum(out) -+ return h.client.Sum(out) -+} -+ -+// clientSum returns the contents of the verify_data member of a client's -+// Finished message. -+func (h finishedHash) clientSum(masterSecret []byte) []byte { -+ out := make([]byte, finishedVerifyLength) -+ h.prf(out, masterSecret, clientFinishedLabel, h.Sum()) -+ return out -+} -+ -+// serverSum returns the contents of the verify_data member of a server's -+// Finished message. -+func (h finishedHash) serverSum(masterSecret []byte) []byte { -+ out := make([]byte, finishedVerifyLength) -+ h.prf(out, masterSecret, serverFinishedLabel, h.Sum()) -+ return out -+} -+ -+// hashForClientCertificate returns the handshake messages so far, pre-hashed if -+// necessary, suitable for signing by a TLS client certificate. -+func (h finishedHash) hashForClientCertificate(sigType uint8, hashAlg crypto.Hash) []byte { -+ if (h.version >= VersionTLS12 || sigType == signatureEd25519) && h.buffer == nil { -+ panic("tls: handshake hash for a client certificate requested after discarding the handshake buffer") -+ } -+ -+ if sigType == signatureEd25519 { -+ return h.buffer -+ } -+ -+ if h.version >= VersionTLS12 { -+ hash := hashAlg.New() -+ hash.Write(h.buffer) -+ return hash.Sum(nil) -+ } -+ -+ if sigType == signatureECDSA { -+ return h.server.Sum(nil) -+ } -+ -+ return h.Sum() -+} -+ -+// discardHandshakeBuffer is called when there is no more need to -+// buffer the entirety of the handshake messages. -+func (h *finishedHash) discardHandshakeBuffer() { -+ h.buffer = nil -+} -+ -+// noExportedKeyingMaterial is used as a value of -+// ConnectionState.ekm when renegotiation is enabled and thus -+// we wish to fail all key-material export requests. -+func noExportedKeyingMaterial(label string, context []byte, length int) ([]byte, error) { -+ return nil, errors.New("crypto/tls: ExportKeyingMaterial is unavailable when renegotiation is enabled") -+} -+ -+// ekmFromMasterSecret generates exported keying material as defined in RFC 5705. -+func ekmFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte) func(string, []byte, int) ([]byte, error) { -+ return func(label string, context []byte, length int) ([]byte, error) { -+ switch label { -+ case "client finished", "server finished", "master secret", "key expansion": -+ // These values are reserved and may not be used. -+ return nil, fmt.Errorf("crypto/tls: reserved ExportKeyingMaterial label: %s", label) -+ } -+ -+ seedLen := len(serverRandom) + len(clientRandom) -+ if context != nil { -+ seedLen += 2 + len(context) -+ } -+ seed := make([]byte, 0, seedLen) -+ -+ seed = append(seed, clientRandom...) -+ seed = append(seed, serverRandom...) -+ -+ if context != nil { -+ if len(context) >= 1<<16 { -+ return nil, fmt.Errorf("crypto/tls: ExportKeyingMaterial context too long") -+ } -+ seed = append(seed, byte(len(context)>>8), byte(len(context))) -+ seed = append(seed, context...) -+ } -+ -+ keyMaterial := make([]byte, length) -+ prfForVersion(version, suite)(keyMaterial, masterSecret, []byte(label), seed) -+ return keyMaterial, nil -+ } -+} -diff --git a/src/crypto/tls/prf_test.go-e b/src/crypto/tls/prf_test.go-e -new file mode 100644 -index 0000000000..8233985a62 ---- /dev/null -+++ b/src/crypto/tls/prf_test.go-e -@@ -0,0 +1,140 @@ -+// Copyright 2009 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. -+ -+package tls -+ -+import ( -+ "encoding/hex" -+ "testing" -+) -+ -+type testSplitPreMasterSecretTest struct { -+ in, out1, out2 string -+} -+ -+var testSplitPreMasterSecretTests = []testSplitPreMasterSecretTest{ -+ {"", "", ""}, -+ {"00", "00", "00"}, -+ {"0011", "00", "11"}, -+ {"001122", "0011", "1122"}, -+ {"00112233", "0011", "2233"}, -+} -+ -+func TestSplitPreMasterSecret(t *testing.T) { -+ for i, test := range testSplitPreMasterSecretTests { -+ in, _ := hex.DecodeString(test.in) -+ out1, out2 := splitPreMasterSecret(in) -+ s1 := hex.EncodeToString(out1) -+ s2 := hex.EncodeToString(out2) -+ if s1 != test.out1 || s2 != test.out2 { -+ t.Errorf("#%d: got: (%s, %s) want: (%s, %s)", i, s1, s2, test.out1, test.out2) -+ } -+ } -+} -+ -+type testKeysFromTest struct { -+ version uint16 -+ suite *cipherSuite -+ preMasterSecret string -+ clientRandom, serverRandom string -+ masterSecret string -+ clientMAC, serverMAC string -+ clientKey, serverKey string -+ macLen, keyLen int -+ contextKeyingMaterial, noContextKeyingMaterial string -+} -+ -+func TestKeysFromPreMasterSecret(t *testing.T) { -+ for i, test := range testKeysFromTests { -+ in, _ := hex.DecodeString(test.preMasterSecret) -+ clientRandom, _ := hex.DecodeString(test.clientRandom) -+ serverRandom, _ := hex.DecodeString(test.serverRandom) -+ -+ masterSecret := masterFromPreMasterSecret(test.version, test.suite, in, clientRandom, serverRandom) -+ if s := hex.EncodeToString(masterSecret); s != test.masterSecret { -+ t.Errorf("#%d: bad master secret %s, want %s", i, s, test.masterSecret) -+ continue -+ } -+ -+ clientMAC, serverMAC, clientKey, serverKey, _, _ := keysFromMasterSecret(test.version, test.suite, masterSecret, clientRandom, serverRandom, test.macLen, test.keyLen, 0) -+ clientMACString := hex.EncodeToString(clientMAC) -+ serverMACString := hex.EncodeToString(serverMAC) -+ clientKeyString := hex.EncodeToString(clientKey) -+ serverKeyString := hex.EncodeToString(serverKey) -+ if clientMACString != test.clientMAC || -+ serverMACString != test.serverMAC || -+ clientKeyString != test.clientKey || -+ serverKeyString != test.serverKey { -+ t.Errorf("#%d: got: (%s, %s, %s, %s) want: (%s, %s, %s, %s)", i, clientMACString, serverMACString, clientKeyString, serverKeyString, test.clientMAC, test.serverMAC, test.clientKey, test.serverKey) -+ } -+ -+ ekm := ekmFromMasterSecret(test.version, test.suite, masterSecret, clientRandom, serverRandom) -+ contextKeyingMaterial, err := ekm("label", []byte("context"), 32) -+ if err != nil { -+ t.Fatalf("ekmFromMasterSecret failed: %v", err) -+ } -+ -+ noContextKeyingMaterial, err := ekm("label", nil, 32) -+ if err != nil { -+ t.Fatalf("ekmFromMasterSecret failed: %v", err) -+ } -+ -+ if hex.EncodeToString(contextKeyingMaterial) != test.contextKeyingMaterial || -+ hex.EncodeToString(noContextKeyingMaterial) != test.noContextKeyingMaterial { -+ t.Errorf("#%d: got keying material: (%s, %s) want: (%s, %s)", i, contextKeyingMaterial, noContextKeyingMaterial, test.contextKeyingMaterial, test.noContextKeyingMaterial) -+ } -+ } -+} -+ -+// These test vectors were generated from GnuTLS using `gnutls-cli --insecure -d 9 ` -+var testKeysFromTests = []testKeysFromTest{ -+ { -+ VersionTLS10, -+ cipherSuiteByID(TLS_RSA_WITH_RC4_128_SHA), -+ "0302cac83ad4b1db3b9ab49ad05957de2a504a634a386fc600889321e1a971f57479466830ac3e6f468e87f5385fa0c5", -+ "4ae66303755184a3917fcb44880605fcc53baa01912b22ed94473fc69cebd558", -+ "4ae663020ec16e6bb5130be918cfcafd4d765979a3136a5d50c593446e4e44db", -+ "3d851bab6e5556e959a16bc36d66cfae32f672bfa9ecdef6096cbb1b23472df1da63dbbd9827606413221d149ed08ceb", -+ "805aaa19b3d2c0a0759a4b6c9959890e08480119", -+ "2d22f9fe519c075c16448305ceee209fc24ad109", -+ "d50b5771244f850cd8117a9ccafe2cf1", -+ "e076e33206b30507a85c32855acd0919", -+ 20, -+ 16, -+ "4d1bb6fc278c37d27aa6e2a13c2e079095d143272c2aa939da33d88c1c0cec22", -+ "93fba89599b6321ae538e27c6548ceb8b46821864318f5190d64a375e5d69d41", -+ }, -+ { -+ VersionTLS10, -+ cipherSuiteByID(TLS_RSA_WITH_RC4_128_SHA), -+ "03023f7527316bc12cbcd69e4b9e8275d62c028f27e65c745cfcddc7ce01bd3570a111378b63848127f1c36e5f9e4890", -+ "4ae66364b5ea56b20ce4e25555aed2d7e67f42788dd03f3fee4adae0459ab106", -+ "4ae66363ab815cbf6a248b87d6b556184e945e9b97fbdf247858b0bdafacfa1c", -+ "7d64be7c80c59b740200b4b9c26d0baaa1c5ae56705acbcf2307fe62beb4728c19392c83f20483801cce022c77645460", -+ "97742ed60a0554ca13f04f97ee193177b971e3b0", -+ "37068751700400e03a8477a5c7eec0813ab9e0dc", -+ "207cddbc600d2a200abac6502053ee5c", -+ "df3f94f6e1eacc753b815fe16055cd43", -+ 20, -+ 16, -+ "2c9f8961a72b97cbe76553b5f954caf8294fc6360ef995ac1256fe9516d0ce7f", -+ "274f19c10291d188857ad8878e2119f5aa437d4da556601cf1337aff23154016", -+ }, -+ { -+ VersionTLS10, -+ cipherSuiteByID(TLS_RSA_WITH_RC4_128_SHA), -+ "832d515f1d61eebb2be56ba0ef79879efb9b527504abb386fb4310ed5d0e3b1f220d3bb6b455033a2773e6d8bdf951d278a187482b400d45deb88a5d5a6bb7d6a7a1decc04eb9ef0642876cd4a82d374d3b6ff35f0351dc5d411104de431375355addc39bfb1f6329fb163b0bc298d658338930d07d313cd980a7e3d9196cac1", -+ "4ae663b2ee389c0de147c509d8f18f5052afc4aaf9699efe8cb05ece883d3a5e", -+ "4ae664d503fd4cff50cfc1fb8fc606580f87b0fcdac9554ba0e01d785bdf278e", -+ "1aff2e7a2c4279d0126f57a65a77a8d9d0087cf2733366699bec27eb53d5740705a8574bb1acc2abbe90e44f0dd28d6c", -+ "3c7647c93c1379a31a609542aa44e7f117a70085", -+ "0d73102994be74a575a3ead8532590ca32a526d4", -+ "ac7581b0b6c10d85bbd905ffbf36c65e", -+ "ff07edde49682b45466bd2e39464b306", -+ 20, -+ 16, -+ "678b0d43f607de35241dc7e9d1a7388a52c35033a1a0336d4d740060a6638fe2", -+ "f3b4ac743f015ef21d79978297a53da3e579ee047133f38c234d829c0f907dab", -+ }, -+} -diff --git a/src/crypto/tls/quic.go-e b/src/crypto/tls/quic.go-e -new file mode 100644 -index 0000000000..286302f0ec ---- /dev/null -+++ b/src/crypto/tls/quic.go-e -@@ -0,0 +1,415 @@ -+// Copyright 2023 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. -+ -+package tls -+ -+import ( -+ "context" -+ "errors" -+ "fmt" -+) -+ -+// QUICEncryptionLevel represents a QUIC encryption level used to transmit -+// handshake messages. -+type QUICEncryptionLevel int -+ -+const ( -+ QUICEncryptionLevelInitial = QUICEncryptionLevel(iota) -+ QUICEncryptionLevelEarly -+ QUICEncryptionLevelHandshake -+ QUICEncryptionLevelApplication -+) -+ -+func (l QUICEncryptionLevel) String() string { -+ switch l { -+ case QUICEncryptionLevelInitial: -+ return "Initial" -+ case QUICEncryptionLevelEarly: -+ return "Early" -+ case QUICEncryptionLevelHandshake: -+ return "Handshake" -+ case QUICEncryptionLevelApplication: -+ return "Application" -+ default: -+ return fmt.Sprintf("QUICEncryptionLevel(%v)", int(l)) -+ } -+} -+ -+// A QUICConn represents a connection which uses a QUIC implementation as the underlying -+// transport as described in RFC 9001. -+// -+// Methods of QUICConn are not safe for concurrent use. -+type QUICConn struct { -+ conn *Conn -+ -+ sessionTicketSent bool -+} -+ -+// A QUICConfig configures a QUICConn. -+type QUICConfig struct { -+ TLSConfig *Config -+} -+ -+// A QUICEventKind is a type of operation on a QUIC connection. -+type QUICEventKind int -+ -+const ( -+ // QUICNoEvent indicates that there are no events available. -+ QUICNoEvent QUICEventKind = iota -+ -+ // QUICSetReadSecret and QUICSetWriteSecret provide the read and write -+ // secrets for a given encryption level. -+ // QUICEvent.Level, QUICEvent.Data, and QUICEvent.Suite are set. -+ // -+ // Secrets for the Initial encryption level are derived from the initial -+ // destination connection ID, and are not provided by the QUICConn. -+ QUICSetReadSecret -+ QUICSetWriteSecret -+ -+ // QUICWriteData provides data to send to the peer in CRYPTO frames. -+ // QUICEvent.Data is set. -+ QUICWriteData -+ -+ // QUICTransportParameters provides the peer's QUIC transport parameters. -+ // QUICEvent.Data is set. -+ QUICTransportParameters -+ -+ // QUICTransportParametersRequired indicates that the caller must provide -+ // QUIC transport parameters to send to the peer. The caller should set -+ // the transport parameters with QUICConn.SetTransportParameters and call -+ // QUICConn.NextEvent again. -+ // -+ // If transport parameters are set before calling QUICConn.Start, the -+ // connection will never generate a QUICTransportParametersRequired event. -+ QUICTransportParametersRequired -+ -+ // QUICRejectedEarlyData indicates that the server rejected 0-RTT data even -+ // if we offered it. It's returned before QUICEncryptionLevelApplication -+ // keys are returned. -+ QUICRejectedEarlyData -+ -+ // QUICHandshakeDone indicates that the TLS handshake has completed. -+ QUICHandshakeDone -+) -+ -+// A QUICEvent is an event occurring on a QUIC connection. -+// -+// The type of event is specified by the Kind field. -+// The contents of the other fields are kind-specific. -+type QUICEvent struct { -+ Kind QUICEventKind -+ -+ // Set for QUICSetReadSecret, QUICSetWriteSecret, and QUICWriteData. -+ Level QUICEncryptionLevel -+ -+ // Set for QUICTransportParameters, QUICSetReadSecret, QUICSetWriteSecret, and QUICWriteData. -+ // The contents are owned by crypto/tls, and are valid until the next NextEvent call. -+ Data []byte -+ -+ // Set for QUICSetReadSecret and QUICSetWriteSecret. -+ Suite uint16 -+} -+ -+type quicState struct { -+ events []QUICEvent -+ nextEvent int -+ -+ // eventArr is a statically allocated event array, large enough to handle -+ // the usual maximum number of events resulting from a single call: transport -+ // parameters, Initial data, Early read secret, Handshake write and read -+ // secrets, Handshake data, Application write secret, Application data. -+ eventArr [8]QUICEvent -+ -+ started bool -+ signalc chan struct{} // handshake data is available to be read -+ blockedc chan struct{} // handshake is waiting for data, closed when done -+ cancelc <-chan struct{} // handshake has been canceled -+ cancel context.CancelFunc -+ -+ // readbuf is shared between HandleData and the handshake goroutine. -+ // HandshakeCryptoData passes ownership to the handshake goroutine by -+ // reading from signalc, and reclaims ownership by reading from blockedc. -+ readbuf []byte -+ -+ transportParams []byte // to send to the peer -+} -+ -+// QUICClient returns a new TLS client side connection using QUICTransport as the -+// underlying transport. The config cannot be nil. -+// -+// The config's MinVersion must be at least TLS 1.3. -+func QUICClient(config *QUICConfig) *QUICConn { -+ return newQUICConn(Client(nil, config.TLSConfig)) -+} -+ -+// QUICServer returns a new TLS server side connection using QUICTransport as the -+// underlying transport. The config cannot be nil. -+// -+// The config's MinVersion must be at least TLS 1.3. -+func QUICServer(config *QUICConfig) *QUICConn { -+ return newQUICConn(Server(nil, config.TLSConfig)) -+} -+ -+func newQUICConn(conn *Conn) *QUICConn { -+ conn.quic = &quicState{ -+ signalc: make(chan struct{}), -+ blockedc: make(chan struct{}), -+ } -+ conn.quic.events = conn.quic.eventArr[:0] -+ return &QUICConn{ -+ conn: conn, -+ } -+} -+ -+// Start starts the client or server handshake protocol. -+// It may produce connection events, which may be read with NextEvent. -+// -+// Start must be called at most once. -+func (q *QUICConn) Start(ctx context.Context) error { -+ if q.conn.quic.started { -+ return quicError(errors.New("tls: Start called more than once")) -+ } -+ q.conn.quic.started = true -+ if q.conn.config.MinVersion < VersionTLS13 { -+ return quicError(errors.New("tls: Config MinVersion must be at least TLS 1.13")) -+ } -+ go q.conn.HandshakeContext(ctx) -+ if _, ok := <-q.conn.quic.blockedc; !ok { -+ return q.conn.handshakeErr -+ } -+ return nil -+} -+ -+// NextEvent returns the next event occurring on the connection. -+// It returns an event with a Kind of QUICNoEvent when no events are available. -+func (q *QUICConn) NextEvent() QUICEvent { -+ qs := q.conn.quic -+ if last := qs.nextEvent - 1; last >= 0 && len(qs.events[last].Data) > 0 { -+ // Write over some of the previous event's data, -+ // to catch callers erroniously retaining it. -+ qs.events[last].Data[0] = 0 -+ } -+ if qs.nextEvent >= len(qs.events) { -+ qs.events = qs.events[:0] -+ qs.nextEvent = 0 -+ return QUICEvent{Kind: QUICNoEvent} -+ } -+ e := qs.events[qs.nextEvent] -+ qs.events[qs.nextEvent] = QUICEvent{} // zero out references to data -+ qs.nextEvent++ -+ return e -+} -+ -+// Close closes the connection and stops any in-progress handshake. -+func (q *QUICConn) Close() error { -+ if q.conn.quic.cancel == nil { -+ return nil // never started -+ } -+ q.conn.quic.cancel() -+ for range q.conn.quic.blockedc { -+ // Wait for the handshake goroutine to return. -+ } -+ return q.conn.handshakeErr -+} -+ -+// HandleData handles handshake bytes received from the peer. -+// It may produce connection events, which may be read with NextEvent. -+func (q *QUICConn) HandleData(level QUICEncryptionLevel, data []byte) error { -+ c := q.conn -+ if c.in.level != level { -+ return quicError(c.in.setErrorLocked(errors.New("tls: handshake data received at wrong level"))) -+ } -+ c.quic.readbuf = data -+ <-c.quic.signalc -+ _, ok := <-c.quic.blockedc -+ if ok { -+ // The handshake goroutine is waiting for more data. -+ return nil -+ } -+ // The handshake goroutine has exited. -+ c.hand.Write(c.quic.readbuf) -+ c.quic.readbuf = nil -+ for q.conn.hand.Len() >= 4 && q.conn.handshakeErr == nil { -+ b := q.conn.hand.Bytes() -+ n := int(b[1])<<16 | int(b[2])<<8 | int(b[3]) -+ if 4+n < len(b) { -+ return nil -+ } -+ if err := q.conn.handlePostHandshakeMessage(); err != nil { -+ return quicError(err) -+ } -+ } -+ if q.conn.handshakeErr != nil { -+ return quicError(q.conn.handshakeErr) -+ } -+ return nil -+} -+ -+type QUICSessionTicketOptions struct { -+ // EarlyData specifies whether the ticket may be used for 0-RTT. -+ EarlyData bool -+} -+ -+// SendSessionTicket sends a session ticket to the client. -+// It produces connection events, which may be read with NextEvent. -+// Currently, it can only be called once. -+func (q *QUICConn) SendSessionTicket(opts QUICSessionTicketOptions) error { -+ c := q.conn -+ if !c.isHandshakeComplete.Load() { -+ return quicError(errors.New("tls: SendSessionTicket called before handshake completed")) -+ } -+ if c.isClient { -+ return quicError(errors.New("tls: SendSessionTicket called on the client")) -+ } -+ if q.sessionTicketSent { -+ return quicError(errors.New("tls: SendSessionTicket called multiple times")) -+ } -+ q.sessionTicketSent = true -+ return quicError(c.sendSessionTicket(opts.EarlyData)) -+} -+ -+// ConnectionState returns basic TLS details about the connection. -+func (q *QUICConn) ConnectionState() ConnectionState { -+ return q.conn.ConnectionState() -+} -+ -+// SetTransportParameters sets the transport parameters to send to the peer. -+// -+// Server connections may delay setting the transport parameters until after -+// receiving the client's transport parameters. See QUICTransportParametersRequired. -+func (q *QUICConn) SetTransportParameters(params []byte) { -+ if params == nil { -+ params = []byte{} -+ } -+ q.conn.quic.transportParams = params -+ if q.conn.quic.started { -+ <-q.conn.quic.signalc -+ <-q.conn.quic.blockedc -+ } -+} -+ -+// quicError ensures err is an AlertError. -+// If err is not already, quicError wraps it with alertInternalError. -+func quicError(err error) error { -+ if err == nil { -+ return nil -+ } -+ var ae AlertError -+ if errors.As(err, &ae) { -+ return err -+ } -+ var a alert -+ if !errors.As(err, &a) { -+ a = alertInternalError -+ } -+ // Return an error wrapping the original error and an AlertError. -+ // Truncate the text of the alert to 0 characters. -+ return fmt.Errorf("%w%.0w", err, AlertError(a)) -+} -+ -+func (c *Conn) quicReadHandshakeBytes(n int) error { -+ for c.hand.Len() < n { -+ if err := c.quicWaitForSignal(); err != nil { -+ return err -+ } -+ } -+ return nil -+} -+ -+func (c *Conn) quicSetReadSecret(level QUICEncryptionLevel, suite uint16, secret []byte) { -+ c.quic.events = append(c.quic.events, QUICEvent{ -+ Kind: QUICSetReadSecret, -+ Level: level, -+ Suite: suite, -+ Data: secret, -+ }) -+} -+ -+func (c *Conn) quicSetWriteSecret(level QUICEncryptionLevel, suite uint16, secret []byte) { -+ c.quic.events = append(c.quic.events, QUICEvent{ -+ Kind: QUICSetWriteSecret, -+ Level: level, -+ Suite: suite, -+ Data: secret, -+ }) -+} -+ -+func (c *Conn) quicWriteCryptoData(level QUICEncryptionLevel, data []byte) { -+ var last *QUICEvent -+ if len(c.quic.events) > 0 { -+ last = &c.quic.events[len(c.quic.events)-1] -+ } -+ if last == nil || last.Kind != QUICWriteData || last.Level != level { -+ c.quic.events = append(c.quic.events, QUICEvent{ -+ Kind: QUICWriteData, -+ Level: level, -+ }) -+ last = &c.quic.events[len(c.quic.events)-1] -+ } -+ last.Data = append(last.Data, data...) -+} -+ -+func (c *Conn) quicSetTransportParameters(params []byte) { -+ c.quic.events = append(c.quic.events, QUICEvent{ -+ Kind: QUICTransportParameters, -+ Data: params, -+ }) -+} -+ -+func (c *Conn) quicGetTransportParameters() ([]byte, error) { -+ if c.quic.transportParams == nil { -+ c.quic.events = append(c.quic.events, QUICEvent{ -+ Kind: QUICTransportParametersRequired, -+ }) -+ } -+ for c.quic.transportParams == nil { -+ if err := c.quicWaitForSignal(); err != nil { -+ return nil, err -+ } -+ } -+ return c.quic.transportParams, nil -+} -+ -+func (c *Conn) quicHandshakeComplete() { -+ c.quic.events = append(c.quic.events, QUICEvent{ -+ Kind: QUICHandshakeDone, -+ }) -+} -+ -+func (c *Conn) quicRejectedEarlyData() { -+ c.quic.events = append(c.quic.events, QUICEvent{ -+ Kind: QUICRejectedEarlyData, -+ }) -+} -+ -+// quicWaitForSignal notifies the QUICConn that handshake progress is blocked, -+// and waits for a signal that the handshake should proceed. -+// -+// The handshake may become blocked waiting for handshake bytes -+// or for the user to provide transport parameters. -+func (c *Conn) quicWaitForSignal() error { -+ // Drop the handshake mutex while blocked to allow the user -+ // to call ConnectionState before the handshake completes. -+ c.handshakeMutex.Unlock() -+ defer c.handshakeMutex.Lock() -+ // Send on blockedc to notify the QUICConn that the handshake is blocked. -+ // Exported methods of QUICConn wait for the handshake to become blocked -+ // before returning to the user. -+ select { -+ case c.quic.blockedc <- struct{}{}: -+ case <-c.quic.cancelc: -+ return c.sendAlertLocked(alertCloseNotify) -+ } -+ // The QUICConn reads from signalc to notify us that the handshake may -+ // be able to proceed. (The QUICConn reads, because we close signalc to -+ // indicate that the handshake has completed.) -+ select { -+ case c.quic.signalc <- struct{}{}: -+ c.hand.Write(c.quic.readbuf) -+ c.quic.readbuf = nil -+ case <-c.quic.cancelc: -+ return c.sendAlertLocked(alertCloseNotify) -+ } -+ return nil -+} -diff --git a/src/crypto/tls/quic_test.go-e b/src/crypto/tls/quic_test.go-e -new file mode 100644 -index 0000000000..9a29fa56b8 ---- /dev/null -+++ b/src/crypto/tls/quic_test.go-e -@@ -0,0 +1,437 @@ -+// Copyright 2023 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. -+ -+package tls -+ -+import ( -+ "context" -+ "errors" -+ "reflect" -+ "testing" -+) -+ -+type testQUICConn struct { -+ t *testing.T -+ conn *QUICConn -+ readSecret map[QUICEncryptionLevel]suiteSecret -+ writeSecret map[QUICEncryptionLevel]suiteSecret -+ gotParams []byte -+ complete bool -+} -+ -+func newTestQUICClient(t *testing.T, config *Config) *testQUICConn { -+ q := &testQUICConn{t: t} -+ q.conn = QUICClient(&QUICConfig{ -+ TLSConfig: config, -+ }) -+ t.Cleanup(func() { -+ q.conn.Close() -+ }) -+ return q -+} -+ -+func newTestQUICServer(t *testing.T, config *Config) *testQUICConn { -+ q := &testQUICConn{t: t} -+ q.conn = QUICServer(&QUICConfig{ -+ TLSConfig: config, -+ }) -+ t.Cleanup(func() { -+ q.conn.Close() -+ }) -+ return q -+} -+ -+type suiteSecret struct { -+ suite uint16 -+ secret []byte -+} -+ -+func (q *testQUICConn) setReadSecret(level QUICEncryptionLevel, suite uint16, secret []byte) { -+ if _, ok := q.writeSecret[level]; !ok { -+ q.t.Errorf("SetReadSecret for level %v called before SetWriteSecret", level) -+ } -+ if level == QUICEncryptionLevelApplication && !q.complete { -+ q.t.Errorf("SetReadSecret for level %v called before HandshakeComplete", level) -+ } -+ if _, ok := q.readSecret[level]; ok { -+ q.t.Errorf("SetReadSecret for level %v called twice", level) -+ } -+ if q.readSecret == nil { -+ q.readSecret = map[QUICEncryptionLevel]suiteSecret{} -+ } -+ switch level { -+ case QUICEncryptionLevelHandshake, QUICEncryptionLevelApplication: -+ q.readSecret[level] = suiteSecret{suite, secret} -+ default: -+ q.t.Errorf("SetReadSecret for unexpected level %v", level) -+ } -+} -+ -+func (q *testQUICConn) setWriteSecret(level QUICEncryptionLevel, suite uint16, secret []byte) { -+ if _, ok := q.writeSecret[level]; ok { -+ q.t.Errorf("SetWriteSecret for level %v called twice", level) -+ } -+ if q.writeSecret == nil { -+ q.writeSecret = map[QUICEncryptionLevel]suiteSecret{} -+ } -+ switch level { -+ case QUICEncryptionLevelHandshake, QUICEncryptionLevelApplication: -+ q.writeSecret[level] = suiteSecret{suite, secret} -+ default: -+ q.t.Errorf("SetWriteSecret for unexpected level %v", level) -+ } -+} -+ -+var errTransportParametersRequired = errors.New("transport parameters required") -+ -+func runTestQUICConnection(ctx context.Context, cli, srv *testQUICConn, onHandleCryptoData func()) error { -+ a, b := cli, srv -+ for _, c := range []*testQUICConn{a, b} { -+ if !c.conn.conn.quic.started { -+ if err := c.conn.Start(ctx); err != nil { -+ return err -+ } -+ } -+ } -+ idleCount := 0 -+ for { -+ e := a.conn.NextEvent() -+ switch e.Kind { -+ case QUICNoEvent: -+ idleCount++ -+ if idleCount == 2 { -+ if !a.complete || !b.complete { -+ return errors.New("handshake incomplete") -+ } -+ return nil -+ } -+ a, b = b, a -+ case QUICSetReadSecret: -+ a.setReadSecret(e.Level, e.Suite, e.Data) -+ case QUICSetWriteSecret: -+ a.setWriteSecret(e.Level, e.Suite, e.Data) -+ case QUICWriteData: -+ if err := b.conn.HandleData(e.Level, e.Data); err != nil { -+ return err -+ } -+ case QUICTransportParameters: -+ a.gotParams = e.Data -+ if a.gotParams == nil { -+ a.gotParams = []byte{} -+ } -+ case QUICTransportParametersRequired: -+ return errTransportParametersRequired -+ case QUICHandshakeDone: -+ a.complete = true -+ if a == srv { -+ opts := QUICSessionTicketOptions{} -+ if err := srv.conn.SendSessionTicket(opts); err != nil { -+ return err -+ } -+ } -+ } -+ if e.Kind != QUICNoEvent { -+ idleCount = 0 -+ } -+ } -+} -+ -+func TestQUICConnection(t *testing.T) { -+ config := testConfig.Clone() -+ config.MinVersion = VersionTLS13 -+ -+ cli := newTestQUICClient(t, config) -+ cli.conn.SetTransportParameters(nil) -+ -+ srv := newTestQUICServer(t, config) -+ srv.conn.SetTransportParameters(nil) -+ -+ if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil { -+ t.Fatalf("error during connection handshake: %v", err) -+ } -+ -+ if _, ok := cli.readSecret[QUICEncryptionLevelHandshake]; !ok { -+ t.Errorf("client has no Handshake secret") -+ } -+ if _, ok := cli.readSecret[QUICEncryptionLevelApplication]; !ok { -+ t.Errorf("client has no Application secret") -+ } -+ if _, ok := srv.readSecret[QUICEncryptionLevelHandshake]; !ok { -+ t.Errorf("server has no Handshake secret") -+ } -+ if _, ok := srv.readSecret[QUICEncryptionLevelApplication]; !ok { -+ t.Errorf("server has no Application secret") -+ } -+ for _, level := range []QUICEncryptionLevel{QUICEncryptionLevelHandshake, QUICEncryptionLevelApplication} { -+ if _, ok := cli.readSecret[level]; !ok { -+ t.Errorf("client has no %v read secret", level) -+ } -+ if _, ok := srv.readSecret[level]; !ok { -+ t.Errorf("server has no %v read secret", level) -+ } -+ if !reflect.DeepEqual(cli.readSecret[level], srv.writeSecret[level]) { -+ t.Errorf("client read secret does not match server write secret for level %v", level) -+ } -+ if !reflect.DeepEqual(cli.writeSecret[level], srv.readSecret[level]) { -+ t.Errorf("client write secret does not match server read secret for level %v", level) -+ } -+ } -+} -+ -+func TestQUICSessionResumption(t *testing.T) { -+ clientConfig := testConfig.Clone() -+ clientConfig.MinVersion = VersionTLS13 -+ clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) -+ clientConfig.ServerName = "example.go.dev" -+ -+ serverConfig := testConfig.Clone() -+ serverConfig.MinVersion = VersionTLS13 -+ -+ cli := newTestQUICClient(t, clientConfig) -+ cli.conn.SetTransportParameters(nil) -+ srv := newTestQUICServer(t, serverConfig) -+ srv.conn.SetTransportParameters(nil) -+ if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil { -+ t.Fatalf("error during first connection handshake: %v", err) -+ } -+ if cli.conn.ConnectionState().DidResume { -+ t.Errorf("first connection unexpectedly used session resumption") -+ } -+ -+ cli2 := newTestQUICClient(t, clientConfig) -+ cli2.conn.SetTransportParameters(nil) -+ srv2 := newTestQUICServer(t, serverConfig) -+ srv2.conn.SetTransportParameters(nil) -+ if err := runTestQUICConnection(context.Background(), cli2, srv2, nil); err != nil { -+ t.Fatalf("error during second connection handshake: %v", err) -+ } -+ if !cli2.conn.ConnectionState().DidResume { -+ t.Errorf("second connection did not use session resumption") -+ } -+} -+ -+func TestQUICPostHandshakeClientAuthentication(t *testing.T) { -+ // RFC 9001, Section 4.4. -+ config := testConfig.Clone() -+ config.MinVersion = VersionTLS13 -+ cli := newTestQUICClient(t, config) -+ cli.conn.SetTransportParameters(nil) -+ srv := newTestQUICServer(t, config) -+ srv.conn.SetTransportParameters(nil) -+ if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil { -+ t.Fatalf("error during connection handshake: %v", err) -+ } -+ -+ certReq := new(certificateRequestMsgTLS13) -+ certReq.ocspStapling = true -+ certReq.scts = true -+ certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms() -+ certReqBytes, err := certReq.marshal() -+ if err != nil { -+ t.Fatal(err) -+ } -+ if err := cli.conn.HandleData(QUICEncryptionLevelApplication, append([]byte{ -+ byte(typeCertificateRequest), -+ byte(0), byte(0), byte(len(certReqBytes)), -+ }, certReqBytes...)); err == nil { -+ t.Fatalf("post-handshake authentication request: got no error, want one") -+ } -+} -+ -+func TestQUICPostHandshakeKeyUpdate(t *testing.T) { -+ // RFC 9001, Section 6. -+ config := testConfig.Clone() -+ config.MinVersion = VersionTLS13 -+ cli := newTestQUICClient(t, config) -+ cli.conn.SetTransportParameters(nil) -+ srv := newTestQUICServer(t, config) -+ srv.conn.SetTransportParameters(nil) -+ if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil { -+ t.Fatalf("error during connection handshake: %v", err) -+ } -+ -+ keyUpdate := new(keyUpdateMsg) -+ keyUpdateBytes, err := keyUpdate.marshal() -+ if err != nil { -+ t.Fatal(err) -+ } -+ if err := cli.conn.HandleData(QUICEncryptionLevelApplication, append([]byte{ -+ byte(typeKeyUpdate), -+ byte(0), byte(0), byte(len(keyUpdateBytes)), -+ }, keyUpdateBytes...)); !errors.Is(err, alertUnexpectedMessage) { -+ t.Fatalf("key update request: got error %v, want alertUnexpectedMessage", err) -+ } -+} -+ -+func TestQUICHandshakeError(t *testing.T) { -+ clientConfig := testConfig.Clone() -+ clientConfig.MinVersion = VersionTLS13 -+ clientConfig.InsecureSkipVerify = false -+ clientConfig.ServerName = "name" -+ -+ serverConfig := testConfig.Clone() -+ serverConfig.MinVersion = VersionTLS13 -+ -+ cli := newTestQUICClient(t, clientConfig) -+ cli.conn.SetTransportParameters(nil) -+ srv := newTestQUICServer(t, serverConfig) -+ srv.conn.SetTransportParameters(nil) -+ err := runTestQUICConnection(context.Background(), cli, srv, nil) -+ if !errors.Is(err, AlertError(alertBadCertificate)) { -+ t.Errorf("connection handshake terminated with error %q, want alertBadCertificate", err) -+ } -+ var e *CertificateVerificationError -+ if !errors.As(err, &e) { -+ t.Errorf("connection handshake terminated with error %q, want CertificateVerificationError", err) -+ } -+} -+ -+// Test that QUICConn.ConnectionState can be used during the handshake, -+// and that it reports the application protocol as soon as it has been -+// negotiated. -+func TestQUICConnectionState(t *testing.T) { -+ config := testConfig.Clone() -+ config.MinVersion = VersionTLS13 -+ config.NextProtos = []string{"h3"} -+ cli := newTestQUICClient(t, config) -+ cli.conn.SetTransportParameters(nil) -+ srv := newTestQUICServer(t, config) -+ srv.conn.SetTransportParameters(nil) -+ onHandleCryptoData := func() { -+ cliCS := cli.conn.ConnectionState() -+ cliWantALPN := "" -+ if _, ok := cli.readSecret[QUICEncryptionLevelApplication]; ok { -+ cliWantALPN = "h3" -+ } -+ if want, got := cliCS.NegotiatedProtocol, cliWantALPN; want != got { -+ t.Errorf("cli.ConnectionState().NegotiatedProtocol = %q, want %q", want, got) -+ } -+ -+ srvCS := srv.conn.ConnectionState() -+ srvWantALPN := "" -+ if _, ok := srv.readSecret[QUICEncryptionLevelHandshake]; ok { -+ srvWantALPN = "h3" -+ } -+ if want, got := srvCS.NegotiatedProtocol, srvWantALPN; want != got { -+ t.Errorf("srv.ConnectionState().NegotiatedProtocol = %q, want %q", want, got) -+ } -+ } -+ if err := runTestQUICConnection(context.Background(), cli, srv, onHandleCryptoData); err != nil { -+ t.Fatalf("error during connection handshake: %v", err) -+ } -+} -+ -+func TestQUICStartContextPropagation(t *testing.T) { -+ const key = "key" -+ const value = "value" -+ ctx := context.WithValue(context.Background(), key, value) -+ config := testConfig.Clone() -+ config.MinVersion = VersionTLS13 -+ calls := 0 -+ config.GetConfigForClient = func(info *ClientHelloInfo) (*Config, error) { -+ calls++ -+ got, _ := info.Context().Value(key).(string) -+ if got != value { -+ t.Errorf("GetConfigForClient context key %q has value %q, want %q", key, got, value) -+ } -+ return nil, nil -+ } -+ cli := newTestQUICClient(t, config) -+ cli.conn.SetTransportParameters(nil) -+ srv := newTestQUICServer(t, config) -+ srv.conn.SetTransportParameters(nil) -+ if err := runTestQUICConnection(ctx, cli, srv, nil); err != nil { -+ t.Fatalf("error during connection handshake: %v", err) -+ } -+ if calls != 1 { -+ t.Errorf("GetConfigForClient called %v times, want 1", calls) -+ } -+} -+ -+func TestQUICDelayedTransportParameters(t *testing.T) { -+ clientConfig := testConfig.Clone() -+ clientConfig.MinVersion = VersionTLS13 -+ clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) -+ clientConfig.ServerName = "example.go.dev" -+ -+ serverConfig := testConfig.Clone() -+ serverConfig.MinVersion = VersionTLS13 -+ -+ cliParams := "client params" -+ srvParams := "server params" -+ -+ cli := newTestQUICClient(t, clientConfig) -+ srv := newTestQUICServer(t, serverConfig) -+ if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != errTransportParametersRequired { -+ t.Fatalf("handshake with no client parameters: %v; want errTransportParametersRequired", err) -+ } -+ cli.conn.SetTransportParameters([]byte(cliParams)) -+ if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != errTransportParametersRequired { -+ t.Fatalf("handshake with no server parameters: %v; want errTransportParametersRequired", err) -+ } -+ srv.conn.SetTransportParameters([]byte(srvParams)) -+ if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil { -+ t.Fatalf("error during connection handshake: %v", err) -+ } -+ -+ if got, want := string(cli.gotParams), srvParams; got != want { -+ t.Errorf("client got transport params: %q, want %q", got, want) -+ } -+ if got, want := string(srv.gotParams), cliParams; got != want { -+ t.Errorf("server got transport params: %q, want %q", got, want) -+ } -+} -+ -+func TestQUICEmptyTransportParameters(t *testing.T) { -+ config := testConfig.Clone() -+ config.MinVersion = VersionTLS13 -+ -+ cli := newTestQUICClient(t, config) -+ cli.conn.SetTransportParameters(nil) -+ srv := newTestQUICServer(t, config) -+ srv.conn.SetTransportParameters(nil) -+ if err := runTestQUICConnection(context.Background(), cli, srv, nil); err != nil { -+ t.Fatalf("error during connection handshake: %v", err) -+ } -+ -+ if cli.gotParams == nil { -+ t.Errorf("client did not get transport params") -+ } -+ if srv.gotParams == nil { -+ t.Errorf("server did not get transport params") -+ } -+ if len(cli.gotParams) != 0 { -+ t.Errorf("client got transport params: %v, want empty", cli.gotParams) -+ } -+ if len(srv.gotParams) != 0 { -+ t.Errorf("server got transport params: %v, want empty", srv.gotParams) -+ } -+} -+ -+func TestQUICCanceledWaitingForData(t *testing.T) { -+ config := testConfig.Clone() -+ config.MinVersion = VersionTLS13 -+ cli := newTestQUICClient(t, config) -+ cli.conn.SetTransportParameters(nil) -+ cli.conn.Start(context.Background()) -+ for cli.conn.NextEvent().Kind != QUICNoEvent { -+ } -+ err := cli.conn.Close() -+ if !errors.Is(err, alertCloseNotify) { -+ t.Errorf("conn.Close() = %v, want alertCloseNotify", err) -+ } -+} -+ -+func TestQUICCanceledWaitingForTransportParams(t *testing.T) { -+ config := testConfig.Clone() -+ config.MinVersion = VersionTLS13 -+ cli := newTestQUICClient(t, config) -+ cli.conn.Start(context.Background()) -+ for cli.conn.NextEvent().Kind != QUICTransportParametersRequired { -+ } -+ err := cli.conn.Close() -+ if !errors.Is(err, alertCloseNotify) { -+ t.Errorf("conn.Close() = %v, want alertCloseNotify", err) -+ } -+} -diff --git a/src/crypto/tls/ticket.go-e b/src/crypto/tls/ticket.go-e -new file mode 100644 -index 0000000000..b43101ff66 ---- /dev/null -+++ b/src/crypto/tls/ticket.go-e -@@ -0,0 +1,421 @@ -+// Copyright 2012 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. -+ -+package tls -+ -+import ( -+ "crypto/aes" -+ "crypto/cipher" -+ "crypto/hmac" -+ "crypto/sha256" -+ "crypto/subtle" -+ "crypto/x509" -+ "errors" -+ "io" -+ -+ "golang.org/x/crypto/cryptobyte" -+) -+ -+// A SessionState is a resumable session. -+type SessionState struct { -+ // Encoded as a SessionState (in the language of RFC 8446, Section 3). -+ // -+ // enum { server(1), client(2) } SessionStateType; -+ // -+ // opaque Certificate<1..2^24-1>; -+ // -+ // Certificate CertificateChain<0..2^24-1>; -+ // -+ // opaque Extra<0..2^24-1>; -+ // -+ // struct { -+ // uint16 version; -+ // SessionStateType type; -+ // uint16 cipher_suite; -+ // uint64 created_at; -+ // opaque secret<1..2^8-1>; -+ // Extra extra<0..2^24-1>; -+ // uint8 ext_master_secret = { 0, 1 }; -+ // uint8 early_data = { 0, 1 }; -+ // CertificateEntry certificate_list<0..2^24-1>; -+ // CertificateChain verified_chains<0..2^24-1>; /* excluding leaf */ -+ // select (SessionState.early_data) { -+ // case 0: Empty; -+ // case 1: opaque alpn<1..2^8-1>; -+ // }; -+ // select (SessionState.type) { -+ // case server: Empty; -+ // case client: struct { -+ // select (SessionState.version) { -+ // case VersionTLS10..VersionTLS12: Empty; -+ // case VersionTLS13: struct { -+ // uint64 use_by; -+ // uint32 age_add; -+ // }; -+ // }; -+ // }; -+ // }; -+ // } SessionState; -+ // -+ -+ // Extra is ignored by crypto/tls, but is encoded by [SessionState.Bytes] -+ // and parsed by [ParseSessionState]. -+ // -+ // This allows [Config.UnwrapSession]/[Config.WrapSession] and -+ // [ClientSessionCache] implementations to store and retrieve additional -+ // data alongside this session. -+ // -+ // To allow different layers in a protocol stack to share this field, -+ // applications must only append to it, not replace it, and must use entries -+ // that can be recognized even if out of order (for example, by starting -+ // with a id and version prefix). -+ Extra [][]byte -+ -+ // EarlyData indicates whether the ticket can be used for 0-RTT in a QUIC -+ // connection. The application may set this to false if it is true to -+ // decline to offer 0-RTT even if supported. -+ EarlyData bool -+ -+ version uint16 -+ isClient bool -+ cipherSuite uint16 -+ // createdAt is the generation time of the secret on the sever (which for -+ // TLS 1.0–1.2 might be earlier than the current session) and the time at -+ // which the ticket was received on the client. -+ createdAt uint64 // seconds since UNIX epoch -+ secret []byte // master secret for TLS 1.2, or the PSK for TLS 1.3 -+ extMasterSecret bool -+ peerCertificates []*x509.Certificate -+ activeCertHandles []*activeCert -+ ocspResponse []byte -+ scts [][]byte -+ verifiedChains [][]*x509.Certificate -+ alpnProtocol string // only set if EarlyData is true -+ -+ // Client-side TLS 1.3-only fields. -+ useBy uint64 // seconds since UNIX epoch -+ ageAdd uint32 -+} -+ -+// Bytes encodes the session, including any private fields, so that it can be -+// parsed by [ParseSessionState]. The encoding contains secret values critical -+// to the security of future and possibly past sessions. -+// -+// The specific encoding should be considered opaque and may change incompatibly -+// between Go versions. -+func (s *SessionState) Bytes() ([]byte, error) { -+ var b cryptobyte.Builder -+ b.AddUint16(s.version) -+ if s.isClient { -+ b.AddUint8(2) // client -+ } else { -+ b.AddUint8(1) // server -+ } -+ b.AddUint16(s.cipherSuite) -+ addUint64(&b, s.createdAt) -+ b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { -+ b.AddBytes(s.secret) -+ }) -+ b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { -+ for _, extra := range s.Extra { -+ b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { -+ b.AddBytes(extra) -+ }) -+ } -+ }) -+ if s.extMasterSecret { -+ b.AddUint8(1) -+ } else { -+ b.AddUint8(0) -+ } -+ if s.EarlyData { -+ b.AddUint8(1) -+ } else { -+ b.AddUint8(0) -+ } -+ marshalCertificate(&b, Certificate{ -+ Certificate: certificatesToBytesSlice(s.peerCertificates), -+ OCSPStaple: s.ocspResponse, -+ SignedCertificateTimestamps: s.scts, -+ }) -+ b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { -+ for _, chain := range s.verifiedChains { -+ b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { -+ // We elide the first certificate because it's always the leaf. -+ if len(chain) == 0 { -+ b.SetError(errors.New("tls: internal error: empty verified chain")) -+ return -+ } -+ for _, cert := range chain[1:] { -+ b.AddUint24LengthPrefixed(func(b *cryptobyte.Builder) { -+ b.AddBytes(cert.Raw) -+ }) -+ } -+ }) -+ } -+ }) -+ if s.EarlyData { -+ b.AddUint8LengthPrefixed(func(b *cryptobyte.Builder) { -+ b.AddBytes([]byte(s.alpnProtocol)) -+ }) -+ } -+ if s.isClient { -+ if s.version >= VersionTLS13 { -+ addUint64(&b, s.useBy) -+ b.AddUint32(s.ageAdd) -+ } -+ } -+ return b.Bytes() -+} -+ -+func certificatesToBytesSlice(certs []*x509.Certificate) [][]byte { -+ s := make([][]byte, 0, len(certs)) -+ for _, c := range certs { -+ s = append(s, c.Raw) -+ } -+ return s -+} -+ -+// ParseSessionState parses a [SessionState] encoded by [SessionState.Bytes]. -+func ParseSessionState(data []byte) (*SessionState, error) { -+ ss := &SessionState{} -+ s := cryptobyte.String(data) -+ var typ, extMasterSecret, earlyData uint8 -+ var cert Certificate -+ var extra cryptobyte.String -+ if !s.ReadUint16(&ss.version) || -+ !s.ReadUint8(&typ) || -+ (typ != 1 && typ != 2) || -+ !s.ReadUint16(&ss.cipherSuite) || -+ !readUint64(&s, &ss.createdAt) || -+ !readUint8LengthPrefixed(&s, &ss.secret) || -+ !s.ReadUint24LengthPrefixed(&extra) || -+ !s.ReadUint8(&extMasterSecret) || -+ !s.ReadUint8(&earlyData) || -+ len(ss.secret) == 0 || -+ !unmarshalCertificate(&s, &cert) { -+ return nil, errors.New("tls: invalid session encoding") -+ } -+ for !extra.Empty() { -+ var e []byte -+ if !readUint24LengthPrefixed(&extra, &e) { -+ return nil, errors.New("tls: invalid session encoding") -+ } -+ ss.Extra = append(ss.Extra, e) -+ } -+ switch extMasterSecret { -+ case 0: -+ ss.extMasterSecret = false -+ case 1: -+ ss.extMasterSecret = true -+ default: -+ return nil, errors.New("tls: invalid session encoding") -+ } -+ switch earlyData { -+ case 0: -+ ss.EarlyData = false -+ case 1: -+ ss.EarlyData = true -+ default: -+ return nil, errors.New("tls: invalid session encoding") -+ } -+ for _, cert := range cert.Certificate { -+ c, err := globalCertCache.newCert(cert) -+ if err != nil { -+ return nil, err -+ } -+ ss.activeCertHandles = append(ss.activeCertHandles, c) -+ ss.peerCertificates = append(ss.peerCertificates, c.cert) -+ } -+ ss.ocspResponse = cert.OCSPStaple -+ ss.scts = cert.SignedCertificateTimestamps -+ var chainList cryptobyte.String -+ if !s.ReadUint24LengthPrefixed(&chainList) { -+ return nil, errors.New("tls: invalid session encoding") -+ } -+ for !chainList.Empty() { -+ var certList cryptobyte.String -+ if !chainList.ReadUint24LengthPrefixed(&certList) { -+ return nil, errors.New("tls: invalid session encoding") -+ } -+ var chain []*x509.Certificate -+ if len(ss.peerCertificates) == 0 { -+ return nil, errors.New("tls: invalid session encoding") -+ } -+ chain = append(chain, ss.peerCertificates[0]) -+ for !certList.Empty() { -+ var cert []byte -+ if !readUint24LengthPrefixed(&certList, &cert) { -+ return nil, errors.New("tls: invalid session encoding") -+ } -+ c, err := globalCertCache.newCert(cert) -+ if err != nil { -+ return nil, err -+ } -+ ss.activeCertHandles = append(ss.activeCertHandles, c) -+ chain = append(chain, c.cert) -+ } -+ ss.verifiedChains = append(ss.verifiedChains, chain) -+ } -+ if ss.EarlyData { -+ var alpn []byte -+ if !readUint8LengthPrefixed(&s, &alpn) { -+ return nil, errors.New("tls: invalid session encoding") -+ } -+ ss.alpnProtocol = string(alpn) -+ } -+ if isClient := typ == 2; !isClient { -+ if !s.Empty() { -+ return nil, errors.New("tls: invalid session encoding") -+ } -+ return ss, nil -+ } -+ ss.isClient = true -+ if len(ss.peerCertificates) == 0 { -+ return nil, errors.New("tls: no server certificates in client session") -+ } -+ if ss.version < VersionTLS13 { -+ if !s.Empty() { -+ return nil, errors.New("tls: invalid session encoding") -+ } -+ return ss, nil -+ } -+ if !s.ReadUint64(&ss.useBy) || !s.ReadUint32(&ss.ageAdd) || !s.Empty() { -+ return nil, errors.New("tls: invalid session encoding") -+ } -+ return ss, nil -+} -+ -+// sessionState returns a partially filled-out [SessionState] with information -+// from the current connection. -+func (c *Conn) sessionState() (*SessionState, error) { -+ return &SessionState{ -+ version: c.vers, -+ cipherSuite: c.cipherSuite, -+ createdAt: uint64(c.config.time().Unix()), -+ alpnProtocol: c.clientProtocol, -+ peerCertificates: c.peerCertificates, -+ activeCertHandles: c.activeCertHandles, -+ ocspResponse: c.ocspResponse, -+ scts: c.scts, -+ isClient: c.isClient, -+ extMasterSecret: c.extMasterSecret, -+ verifiedChains: c.verifiedChains, -+ }, nil -+} -+ -+// EncryptTicket encrypts a ticket with the Config's configured (or default) -+// session ticket keys. It can be used as a [Config.WrapSession] implementation. -+func (c *Config) EncryptTicket(cs ConnectionState, ss *SessionState) ([]byte, error) { -+ ticketKeys := c.ticketKeys(nil) -+ stateBytes, err := ss.Bytes() -+ if err != nil { -+ return nil, err -+ } -+ return c.encryptTicket(stateBytes, ticketKeys) -+} -+ -+func (c *Config) encryptTicket(state []byte, ticketKeys []ticketKey) ([]byte, error) { -+ if len(ticketKeys) == 0 { -+ return nil, errors.New("tls: internal error: session ticket keys unavailable") -+ } -+ -+ encrypted := make([]byte, aes.BlockSize+len(state)+sha256.Size) -+ iv := encrypted[:aes.BlockSize] -+ ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size] -+ authenticated := encrypted[:len(encrypted)-sha256.Size] -+ macBytes := encrypted[len(encrypted)-sha256.Size:] -+ -+ if _, err := io.ReadFull(c.rand(), iv); err != nil { -+ return nil, err -+ } -+ key := ticketKeys[0] -+ block, err := aes.NewCipher(key.aesKey[:]) -+ if err != nil { -+ return nil, errors.New("tls: failed to create cipher while encrypting ticket: " + err.Error()) -+ } -+ cipher.NewCTR(block, iv).XORKeyStream(ciphertext, state) -+ -+ mac := hmac.New(sha256.New, key.hmacKey[:]) -+ mac.Write(authenticated) -+ mac.Sum(macBytes[:0]) -+ -+ return encrypted, nil -+} -+ -+// DecryptTicket decrypts a ticket encrypted by [Config.EncryptTicket]. It can -+// be used as a [Config.UnwrapSession] implementation. -+// -+// If the ticket can't be decrypted or parsed, DecryptTicket returns (nil, nil). -+func (c *Config) DecryptTicket(identity []byte, cs ConnectionState) (*SessionState, error) { -+ ticketKeys := c.ticketKeys(nil) -+ stateBytes := c.decryptTicket(identity, ticketKeys) -+ if stateBytes == nil { -+ return nil, nil -+ } -+ s, err := ParseSessionState(stateBytes) -+ if err != nil { -+ return nil, nil // drop unparsable tickets on the floor -+ } -+ return s, nil -+} -+ -+func (c *Config) decryptTicket(encrypted []byte, ticketKeys []ticketKey) []byte { -+ if len(encrypted) < aes.BlockSize+sha256.Size { -+ return nil -+ } -+ -+ iv := encrypted[:aes.BlockSize] -+ ciphertext := encrypted[aes.BlockSize : len(encrypted)-sha256.Size] -+ authenticated := encrypted[:len(encrypted)-sha256.Size] -+ macBytes := encrypted[len(encrypted)-sha256.Size:] -+ -+ for _, key := range ticketKeys { -+ mac := hmac.New(sha256.New, key.hmacKey[:]) -+ mac.Write(authenticated) -+ expected := mac.Sum(nil) -+ -+ if subtle.ConstantTimeCompare(macBytes, expected) != 1 { -+ continue -+ } -+ -+ block, err := aes.NewCipher(key.aesKey[:]) -+ if err != nil { -+ return nil -+ } -+ plaintext := make([]byte, len(ciphertext)) -+ cipher.NewCTR(block, iv).XORKeyStream(plaintext, ciphertext) -+ -+ return plaintext -+ } -+ -+ return nil -+} -+ -+// ClientSessionState contains the state needed by a client to -+// resume a previous TLS session. -+type ClientSessionState struct { -+ ticket []byte -+ session *SessionState -+} -+ -+// ResumptionState returns the session ticket sent by the server (also known as -+// the session's identity) and the state necessary to resume this session. -+// -+// It can be called by [ClientSessionCache.Put] to serialize (with -+// [SessionState.Bytes]) and store the session. -+func (cs *ClientSessionState) ResumptionState() (ticket []byte, state *SessionState, err error) { -+ return cs.ticket, cs.session, nil -+} -+ -+// NewResumptionState returns a state value that can be returned by -+// [ClientSessionCache.Get] to resume a previous session. -+// -+// state needs to be returned by [ParseSessionState], and the ticket and session -+// state must have been returned by [ClientSessionState.ResumptionState]. -+func NewResumptionState(ticket []byte, state *SessionState) (*ClientSessionState, error) { -+ return &ClientSessionState{ -+ ticket: ticket, session: state, -+ }, nil -+} -diff --git a/src/crypto/tls/ticket_test.go-e b/src/crypto/tls/ticket_test.go-e -new file mode 100644 -index 0000000000..f925451cef ---- /dev/null -+++ b/src/crypto/tls/ticket_test.go-e -@@ -0,0 +1,8 @@ -+// Copyright 2023 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. -+ -+package tls -+ -+var _ = &Config{WrapSession: (&Config{}).EncryptTicket} -+var _ = &Config{UnwrapSession: (&Config{}).DecryptTicket} -diff --git a/src/crypto/tls/tls.go-e b/src/crypto/tls/tls.go-e -new file mode 100644 -index 0000000000..b529c70523 ---- /dev/null -+++ b/src/crypto/tls/tls.go-e -@@ -0,0 +1,356 @@ -+// Copyright 2009 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. -+ -+// Package tls partially implements TLS 1.2, as specified in RFC 5246, -+// and TLS 1.3, as specified in RFC 8446. -+package tls -+ -+// BUG(agl): The crypto/tls package only implements some countermeasures -+// against Lucky13 attacks on CBC-mode encryption, and only on SHA1 -+// variants. See http://www.isg.rhul.ac.uk/tls/TLStiming.pdf and -+// https://www.imperialviolet.org/2013/02/04/luckythirteen.html. -+ -+import ( -+ "bytes" -+ "context" -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/ed25519" -+ "crypto/rsa" -+ "crypto/x509" -+ "encoding/pem" -+ "errors" -+ "fmt" -+ "net" -+ "os" -+ "strings" -+) -+ -+// Server returns a new TLS server side connection -+// using conn as the underlying transport. -+// The configuration config must be non-nil and must include -+// at least one certificate or else set GetCertificate. -+func Server(conn net.Conn, config *Config) *Conn { -+ c := &Conn{ -+ conn: conn, -+ config: config, -+ } -+ c.handshakeFn = c.serverHandshake -+ return c -+} -+ -+// Client returns a new TLS client side connection -+// using conn as the underlying transport. -+// The config cannot be nil: users must set either ServerName or -+// InsecureSkipVerify in the config. -+func Client(conn net.Conn, config *Config) *Conn { -+ c := &Conn{ -+ conn: conn, -+ config: config, -+ isClient: true, -+ } -+ c.handshakeFn = c.clientHandshake -+ return c -+} -+ -+// A listener implements a network listener (net.Listener) for TLS connections. -+type listener struct { -+ net.Listener -+ config *Config -+} -+ -+// Accept waits for and returns the next incoming TLS connection. -+// The returned connection is of type *Conn. -+func (l *listener) Accept() (net.Conn, error) { -+ c, err := l.Listener.Accept() -+ if err != nil { -+ return nil, err -+ } -+ return Server(c, l.config), nil -+} -+ -+// NewListener creates a Listener which accepts connections from an inner -+// Listener and wraps each connection with Server. -+// The configuration config must be non-nil and must include -+// at least one certificate or else set GetCertificate. -+func NewListener(inner net.Listener, config *Config) net.Listener { -+ l := new(listener) -+ l.Listener = inner -+ l.config = config -+ return l -+} -+ -+// Listen creates a TLS listener accepting connections on the -+// given network address using net.Listen. -+// The configuration config must be non-nil and must include -+// at least one certificate or else set GetCertificate. -+func Listen(network, laddr string, config *Config) (net.Listener, error) { -+ if config == nil || len(config.Certificates) == 0 && -+ config.GetCertificate == nil && config.GetConfigForClient == nil { -+ return nil, errors.New("tls: neither Certificates, GetCertificate, nor GetConfigForClient set in Config") -+ } -+ l, err := net.Listen(network, laddr) -+ if err != nil { -+ return nil, err -+ } -+ return NewListener(l, config), nil -+} -+ -+type timeoutError struct{} -+ -+func (timeoutError) Error() string { return "tls: DialWithDialer timed out" } -+func (timeoutError) Timeout() bool { return true } -+func (timeoutError) Temporary() bool { return true } -+ -+// DialWithDialer connects to the given network address using dialer.Dial and -+// then initiates a TLS handshake, returning the resulting TLS connection. Any -+// timeout or deadline given in the dialer apply to connection and TLS -+// handshake as a whole. -+// -+// DialWithDialer interprets a nil configuration as equivalent to the zero -+// configuration; see the documentation of Config for the defaults. -+// -+// DialWithDialer uses context.Background internally; to specify the context, -+// use Dialer.DialContext with NetDialer set to the desired dialer. -+func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { -+ return dial(context.Background(), dialer, network, addr, config) -+} -+ -+func dial(ctx context.Context, netDialer *net.Dialer, network, addr string, config *Config) (*Conn, error) { -+ if netDialer.Timeout != 0 { -+ var cancel context.CancelFunc -+ ctx, cancel = context.WithTimeout(ctx, netDialer.Timeout) -+ defer cancel() -+ } -+ -+ if !netDialer.Deadline.IsZero() { -+ var cancel context.CancelFunc -+ ctx, cancel = context.WithDeadline(ctx, netDialer.Deadline) -+ defer cancel() -+ } -+ -+ rawConn, err := netDialer.DialContext(ctx, network, addr) -+ if err != nil { -+ return nil, err -+ } -+ -+ colonPos := strings.LastIndex(addr, ":") -+ if colonPos == -1 { -+ colonPos = len(addr) -+ } -+ hostname := addr[:colonPos] -+ -+ if config == nil { -+ config = defaultConfig() -+ } -+ // If no ServerName is set, infer the ServerName -+ // from the hostname we're connecting to. -+ if config.ServerName == "" { -+ // Make a copy to avoid polluting argument or default. -+ c := config.Clone() -+ c.ServerName = hostname -+ config = c -+ } -+ -+ conn := Client(rawConn, config) -+ if err := conn.HandshakeContext(ctx); err != nil { -+ rawConn.Close() -+ return nil, err -+ } -+ return conn, nil -+} -+ -+// Dial connects to the given network address using net.Dial -+// and then initiates a TLS handshake, returning the resulting -+// TLS connection. -+// Dial interprets a nil configuration as equivalent to -+// the zero configuration; see the documentation of Config -+// for the defaults. -+func Dial(network, addr string, config *Config) (*Conn, error) { -+ return DialWithDialer(new(net.Dialer), network, addr, config) -+} -+ -+// Dialer dials TLS connections given a configuration and a Dialer for the -+// underlying connection. -+type Dialer struct { -+ // NetDialer is the optional dialer to use for the TLS connections' -+ // underlying TCP connections. -+ // A nil NetDialer is equivalent to the net.Dialer zero value. -+ NetDialer *net.Dialer -+ -+ // Config is the TLS configuration to use for new connections. -+ // A nil configuration is equivalent to the zero -+ // configuration; see the documentation of Config for the -+ // defaults. -+ Config *Config -+} -+ -+// Dial connects to the given network address and initiates a TLS -+// handshake, returning the resulting TLS connection. -+// -+// The returned Conn, if any, will always be of type *Conn. -+// -+// Dial uses context.Background internally; to specify the context, -+// use DialContext. -+func (d *Dialer) Dial(network, addr string) (net.Conn, error) { -+ return d.DialContext(context.Background(), network, addr) -+} -+ -+func (d *Dialer) netDialer() *net.Dialer { -+ if d.NetDialer != nil { -+ return d.NetDialer -+ } -+ return new(net.Dialer) -+} -+ -+// DialContext connects to the given network address and initiates a TLS -+// handshake, returning the resulting TLS connection. -+// -+// The provided Context must be non-nil. If the context expires before -+// the connection is complete, an error is returned. Once successfully -+// connected, any expiration of the context will not affect the -+// connection. -+// -+// The returned Conn, if any, will always be of type *Conn. -+func (d *Dialer) DialContext(ctx context.Context, network, addr string) (net.Conn, error) { -+ c, err := dial(ctx, d.netDialer(), network, addr, d.Config) -+ if err != nil { -+ // Don't return c (a typed nil) in an interface. -+ return nil, err -+ } -+ return c, nil -+} -+ -+// LoadX509KeyPair reads and parses a public/private key pair from a pair -+// of files. The files must contain PEM encoded data. The certificate file -+// may contain intermediate certificates following the leaf certificate to -+// form a certificate chain. On successful return, Certificate.Leaf will -+// be nil because the parsed form of the certificate is not retained. -+func LoadX509KeyPair(certFile, keyFile string) (Certificate, error) { -+ certPEMBlock, err := os.ReadFile(certFile) -+ if err != nil { -+ return Certificate{}, err -+ } -+ keyPEMBlock, err := os.ReadFile(keyFile) -+ if err != nil { -+ return Certificate{}, err -+ } -+ return X509KeyPair(certPEMBlock, keyPEMBlock) -+} -+ -+// X509KeyPair parses a public/private key pair from a pair of -+// PEM encoded data. On successful return, Certificate.Leaf will be nil because -+// the parsed form of the certificate is not retained. -+func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) { -+ fail := func(err error) (Certificate, error) { return Certificate{}, err } -+ -+ var cert Certificate -+ var skippedBlockTypes []string -+ for { -+ var certDERBlock *pem.Block -+ certDERBlock, certPEMBlock = pem.Decode(certPEMBlock) -+ if certDERBlock == nil { -+ break -+ } -+ if certDERBlock.Type == "CERTIFICATE" { -+ cert.Certificate = append(cert.Certificate, certDERBlock.Bytes) -+ } else { -+ skippedBlockTypes = append(skippedBlockTypes, certDERBlock.Type) -+ } -+ } -+ -+ if len(cert.Certificate) == 0 { -+ if len(skippedBlockTypes) == 0 { -+ return fail(errors.New("tls: failed to find any PEM data in certificate input")) -+ } -+ if len(skippedBlockTypes) == 1 && strings.HasSuffix(skippedBlockTypes[0], "PRIVATE KEY") { -+ return fail(errors.New("tls: failed to find certificate PEM data in certificate input, but did find a private key; PEM inputs may have been switched")) -+ } -+ return fail(fmt.Errorf("tls: failed to find \"CERTIFICATE\" PEM block in certificate input after skipping PEM blocks of the following types: %v", skippedBlockTypes)) -+ } -+ -+ skippedBlockTypes = skippedBlockTypes[:0] -+ var keyDERBlock *pem.Block -+ for { -+ keyDERBlock, keyPEMBlock = pem.Decode(keyPEMBlock) -+ if keyDERBlock == nil { -+ if len(skippedBlockTypes) == 0 { -+ return fail(errors.New("tls: failed to find any PEM data in key input")) -+ } -+ if len(skippedBlockTypes) == 1 && skippedBlockTypes[0] == "CERTIFICATE" { -+ return fail(errors.New("tls: found a certificate rather than a key in the PEM for the private key")) -+ } -+ return fail(fmt.Errorf("tls: failed to find PEM block with type ending in \"PRIVATE KEY\" in key input after skipping PEM blocks of the following types: %v", skippedBlockTypes)) -+ } -+ if keyDERBlock.Type == "PRIVATE KEY" || strings.HasSuffix(keyDERBlock.Type, " PRIVATE KEY") { -+ break -+ } -+ skippedBlockTypes = append(skippedBlockTypes, keyDERBlock.Type) -+ } -+ -+ // We don't need to parse the public key for TLS, but we so do anyway -+ // to check that it looks sane and matches the private key. -+ x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) -+ if err != nil { -+ return fail(err) -+ } -+ -+ cert.PrivateKey, err = parsePrivateKey(keyDERBlock.Bytes) -+ if err != nil { -+ return fail(err) -+ } -+ -+ switch pub := x509Cert.PublicKey.(type) { -+ case *rsa.PublicKey: -+ priv, ok := cert.PrivateKey.(*rsa.PrivateKey) -+ if !ok { -+ return fail(errors.New("tls: private key type does not match public key type")) -+ } -+ if pub.N.Cmp(priv.N) != 0 { -+ return fail(errors.New("tls: private key does not match public key")) -+ } -+ case *ecdsa.PublicKey: -+ priv, ok := cert.PrivateKey.(*ecdsa.PrivateKey) -+ if !ok { -+ return fail(errors.New("tls: private key type does not match public key type")) -+ } -+ if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 { -+ return fail(errors.New("tls: private key does not match public key")) -+ } -+ case ed25519.PublicKey: -+ priv, ok := cert.PrivateKey.(ed25519.PrivateKey) -+ if !ok { -+ return fail(errors.New("tls: private key type does not match public key type")) -+ } -+ if !bytes.Equal(priv.Public().(ed25519.PublicKey), pub) { -+ return fail(errors.New("tls: private key does not match public key")) -+ } -+ default: -+ return fail(errors.New("tls: unknown public key algorithm")) -+ } -+ -+ return cert, nil -+} -+ -+// Attempt to parse the given private key DER block. OpenSSL 0.9.8 generates -+// PKCS #1 private keys by default, while OpenSSL 1.0.0 generates PKCS #8 keys. -+// OpenSSL ecparam generates SEC1 EC private keys for ECDSA. We try all three. -+func parsePrivateKey(der []byte) (crypto.PrivateKey, error) { -+ if key, err := x509.ParsePKCS1PrivateKey(der); err == nil { -+ return key, nil -+ } -+ if key, err := x509.ParsePKCS8PrivateKey(der); err == nil { -+ switch key := key.(type) { -+ case *rsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey: -+ return key, nil -+ default: -+ return nil, errors.New("tls: found unknown private key type in PKCS#8 wrapping") -+ } -+ } -+ if key, err := x509.ParseECPrivateKey(der); err == nil { -+ return key, nil -+ } -+ -+ return nil, errors.New("tls: failed to parse private key") -+} -diff --git a/src/crypto/tls/tls_test.go-e b/src/crypto/tls/tls_test.go-e -new file mode 100644 -index 0000000000..c3f16c704a ---- /dev/null -+++ b/src/crypto/tls/tls_test.go-e -@@ -0,0 +1,1804 @@ -+// Copyright 2012 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. -+ -+package tls -+ -+import ( -+ "bytes" -+ "context" -+ "crypto" -+ "crypto/x509" -+ "encoding/json" -+ "errors" -+ "fmt" -+ "internal/testenv" -+ "io" -+ "math" -+ "net" -+ "os" -+ "reflect" -+ "sort" -+ "strings" -+ "testing" -+ "time" -+) -+ -+var rsaCertPEM = `-----BEGIN CERTIFICATE----- -+MIIB0zCCAX2gAwIBAgIJAI/M7BYjwB+uMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV -+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX -+aWRnaXRzIFB0eSBMdGQwHhcNMTIwOTEyMjE1MjAyWhcNMTUwOTEyMjE1MjAyWjBF -+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 -+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANLJ -+hPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wok/4xIA+ui35/MmNa -+rtNuC+BdZ1tMuVCPFZcCAwEAAaNQME4wHQYDVR0OBBYEFJvKs8RfJaXTH08W+SGv -+zQyKn0H8MB8GA1UdIwQYMBaAFJvKs8RfJaXTH08W+SGvzQyKn0H8MAwGA1UdEwQF -+MAMBAf8wDQYJKoZIhvcNAQEFBQADQQBJlffJHybjDGxRMqaRmDhX0+6v02TUKZsW -+r5QuVbpQhH6u+0UgcW0jp9QwpxoPTLTWGXEWBBBurxFwiCBhkQ+V -+-----END CERTIFICATE----- -+` -+ -+var rsaKeyPEM = testingKey(`-----BEGIN RSA TESTING KEY----- -+MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo -+k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G -+6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N -+MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW -+SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T -+xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi -+D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g== -+-----END RSA TESTING KEY----- -+`) -+ -+// keyPEM is the same as rsaKeyPEM, but declares itself as just -+// "PRIVATE KEY", not "RSA PRIVATE KEY". https://golang.org/issue/4477 -+var keyPEM = testingKey(`-----BEGIN TESTING KEY----- -+MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo -+k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G -+6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N -+MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW -+SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T -+xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi -+D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g== -+-----END TESTING KEY----- -+`) -+ -+var ecdsaCertPEM = `-----BEGIN CERTIFICATE----- -+MIIB/jCCAWICCQDscdUxw16XFDAJBgcqhkjOPQQBMEUxCzAJBgNVBAYTAkFVMRMw -+EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0 -+eSBMdGQwHhcNMTIxMTE0MTI0MDQ4WhcNMTUxMTE0MTI0MDQ4WjBFMQswCQYDVQQG -+EwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lk -+Z2l0cyBQdHkgTHRkMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBY9+my9OoeSUR -+lDQdV/x8LsOuLilthhiS1Tz4aGDHIPwC1mlvnf7fg5lecYpMCrLLhauAc1UJXcgl -+01xoLuzgtAEAgv2P/jgytzRSpUYvgLBt1UA0leLYBy6mQQbrNEuqT3INapKIcUv8 -+XxYP0xMEUksLPq6Ca+CRSqTtrd/23uTnapkwCQYHKoZIzj0EAQOBigAwgYYCQXJo -+A7Sl2nLVf+4Iu/tAX/IF4MavARKC4PPHK3zfuGfPR3oCCcsAoz3kAzOeijvd0iXb -+H5jBImIxPL4WxQNiBTexAkF8D1EtpYuWdlVQ80/h/f4pBcGiXPqX5h2PQSQY7hP1 -++jwM1FGS4fREIOvlBYr/SzzQRtwrvrzGYxDEDbsC0ZGRnA== -+-----END CERTIFICATE----- -+` -+ -+var ecdsaKeyPEM = testingKey(`-----BEGIN EC PARAMETERS----- -+BgUrgQQAIw== -+-----END EC PARAMETERS----- -+-----BEGIN EC TESTING KEY----- -+MIHcAgEBBEIBrsoKp0oqcv6/JovJJDoDVSGWdirrkgCWxrprGlzB9o0X8fV675X0 -+NwuBenXFfeZvVcwluO7/Q9wkYoPd/t3jGImgBwYFK4EEACOhgYkDgYYABAFj36bL -+06h5JRGUNB1X/Hwuw64uKW2GGJLVPPhoYMcg/ALWaW+d/t+DmV5xikwKssuFq4Bz -+VQldyCXTXGgu7OC0AQCC/Y/+ODK3NFKlRi+AsG3VQDSV4tgHLqZBBus0S6pPcg1q -+kohxS/xfFg/TEwRSSws+roJr4JFKpO2t3/be5OdqmQ== -+-----END EC TESTING KEY----- -+`) -+ -+var keyPairTests = []struct { -+ algo string -+ cert string -+ key string -+}{ -+ {"ECDSA", ecdsaCertPEM, ecdsaKeyPEM}, -+ {"RSA", rsaCertPEM, rsaKeyPEM}, -+ {"RSA-untyped", rsaCertPEM, keyPEM}, // golang.org/issue/4477 -+} -+ -+func TestX509KeyPair(t *testing.T) { -+ t.Parallel() -+ var pem []byte -+ for _, test := range keyPairTests { -+ pem = []byte(test.cert + test.key) -+ if _, err := X509KeyPair(pem, pem); err != nil { -+ t.Errorf("Failed to load %s cert followed by %s key: %s", test.algo, test.algo, err) -+ } -+ pem = []byte(test.key + test.cert) -+ if _, err := X509KeyPair(pem, pem); err != nil { -+ t.Errorf("Failed to load %s key followed by %s cert: %s", test.algo, test.algo, err) -+ } -+ } -+} -+ -+func TestX509KeyPairErrors(t *testing.T) { -+ _, err := X509KeyPair([]byte(rsaKeyPEM), []byte(rsaCertPEM)) -+ if err == nil { -+ t.Fatalf("X509KeyPair didn't return an error when arguments were switched") -+ } -+ if subStr := "been switched"; !strings.Contains(err.Error(), subStr) { -+ t.Fatalf("Expected %q in the error when switching arguments to X509KeyPair, but the error was %q", subStr, err) -+ } -+ -+ _, err = X509KeyPair([]byte(rsaCertPEM), []byte(rsaCertPEM)) -+ if err == nil { -+ t.Fatalf("X509KeyPair didn't return an error when both arguments were certificates") -+ } -+ if subStr := "certificate"; !strings.Contains(err.Error(), subStr) { -+ t.Fatalf("Expected %q in the error when both arguments to X509KeyPair were certificates, but the error was %q", subStr, err) -+ } -+ -+ const nonsensePEM = ` -+-----BEGIN NONSENSE----- -+Zm9vZm9vZm9v -+-----END NONSENSE----- -+` -+ -+ _, err = X509KeyPair([]byte(nonsensePEM), []byte(nonsensePEM)) -+ if err == nil { -+ t.Fatalf("X509KeyPair didn't return an error when both arguments were nonsense") -+ } -+ if subStr := "NONSENSE"; !strings.Contains(err.Error(), subStr) { -+ t.Fatalf("Expected %q in the error when both arguments to X509KeyPair were nonsense, but the error was %q", subStr, err) -+ } -+} -+ -+func TestX509MixedKeyPair(t *testing.T) { -+ if _, err := X509KeyPair([]byte(rsaCertPEM), []byte(ecdsaKeyPEM)); err == nil { -+ t.Error("Load of RSA certificate succeeded with ECDSA private key") -+ } -+ if _, err := X509KeyPair([]byte(ecdsaCertPEM), []byte(rsaKeyPEM)); err == nil { -+ t.Error("Load of ECDSA certificate succeeded with RSA private key") -+ } -+} -+ -+func newLocalListener(t testing.TB) net.Listener { -+ ln, err := net.Listen("tcp", "127.0.0.1:0") -+ if err != nil { -+ ln, err = net.Listen("tcp6", "[::1]:0") -+ } -+ if err != nil { -+ t.Fatal(err) -+ } -+ return ln -+} -+ -+func TestDialTimeout(t *testing.T) { -+ if testing.Short() { -+ t.Skip("skipping in short mode") -+ } -+ -+ timeout := 100 * time.Microsecond -+ for !t.Failed() { -+ acceptc := make(chan net.Conn) -+ listener := newLocalListener(t) -+ go func() { -+ for { -+ conn, err := listener.Accept() -+ if err != nil { -+ close(acceptc) -+ return -+ } -+ acceptc <- conn -+ } -+ }() -+ -+ addr := listener.Addr().String() -+ dialer := &net.Dialer{ -+ Timeout: timeout, -+ } -+ if conn, err := DialWithDialer(dialer, "tcp", addr, nil); err == nil { -+ conn.Close() -+ t.Errorf("DialWithTimeout unexpectedly completed successfully") -+ } else if !isTimeoutError(err) { -+ t.Errorf("resulting error not a timeout: %v\nType %T: %#v", err, err, err) -+ } -+ -+ listener.Close() -+ -+ // We're looking for a timeout during the handshake, so check that the -+ // Listener actually accepted the connection to initiate it. (If the server -+ // takes too long to accept the connection, we might cancel before the -+ // underlying net.Conn is ever dialed — without ever attempting a -+ // handshake.) -+ lconn, ok := <-acceptc -+ if ok { -+ // The Listener accepted a connection, so assume that it was from our -+ // Dial: we triggered the timeout at the point where we wanted it! -+ t.Logf("Listener accepted a connection from %s", lconn.RemoteAddr()) -+ lconn.Close() -+ } -+ // Close any spurious extra connecitions from the listener. (This is -+ // possible if there are, for example, stray Dial calls from other tests.) -+ for extraConn := range acceptc { -+ t.Logf("spurious extra connection from %s", extraConn.RemoteAddr()) -+ extraConn.Close() -+ } -+ if ok { -+ break -+ } -+ -+ t.Logf("with timeout %v, DialWithDialer returned before listener accepted any connections; retrying", timeout) -+ timeout *= 2 -+ } -+} -+ -+func TestDeadlineOnWrite(t *testing.T) { -+ if testing.Short() { -+ t.Skip("skipping in short mode") -+ } -+ -+ ln := newLocalListener(t) -+ defer ln.Close() -+ -+ srvCh := make(chan *Conn, 1) -+ -+ go func() { -+ sconn, err := ln.Accept() -+ if err != nil { -+ srvCh <- nil -+ return -+ } -+ srv := Server(sconn, testConfig.Clone()) -+ if err := srv.Handshake(); err != nil { -+ srvCh <- nil -+ return -+ } -+ srvCh <- srv -+ }() -+ -+ clientConfig := testConfig.Clone() -+ clientConfig.MaxVersion = VersionTLS12 -+ conn, err := Dial("tcp", ln.Addr().String(), clientConfig) -+ if err != nil { -+ t.Fatal(err) -+ } -+ defer conn.Close() -+ -+ srv := <-srvCh -+ if srv == nil { -+ t.Error(err) -+ } -+ -+ // Make sure the client/server is setup correctly and is able to do a typical Write/Read -+ buf := make([]byte, 6) -+ if _, err := srv.Write([]byte("foobar")); err != nil { -+ t.Errorf("Write err: %v", err) -+ } -+ if n, err := conn.Read(buf); n != 6 || err != nil || string(buf) != "foobar" { -+ t.Errorf("Read = %d, %v, data %q; want 6, nil, foobar", n, err, buf) -+ } -+ -+ // Set a deadline which should cause Write to timeout -+ if err = srv.SetDeadline(time.Now()); err != nil { -+ t.Fatalf("SetDeadline(time.Now()) err: %v", err) -+ } -+ if _, err = srv.Write([]byte("should fail")); err == nil { -+ t.Fatal("Write should have timed out") -+ } -+ -+ // Clear deadline and make sure it still times out -+ if err = srv.SetDeadline(time.Time{}); err != nil { -+ t.Fatalf("SetDeadline(time.Time{}) err: %v", err) -+ } -+ if _, err = srv.Write([]byte("This connection is permanently broken")); err == nil { -+ t.Fatal("Write which previously failed should still time out") -+ } -+ -+ // Verify the error -+ if ne := err.(net.Error); ne.Temporary() != false { -+ t.Error("Write timed out but incorrectly classified the error as Temporary") -+ } -+ if !isTimeoutError(err) { -+ t.Error("Write timed out but did not classify the error as a Timeout") -+ } -+} -+ -+type readerFunc func([]byte) (int, error) -+ -+func (f readerFunc) Read(b []byte) (int, error) { return f(b) } -+ -+// TestDialer tests that tls.Dialer.DialContext can abort in the middle of a handshake. -+// (The other cases are all handled by the existing dial tests in this package, which -+// all also flow through the same code shared code paths) -+func TestDialer(t *testing.T) { -+ ln := newLocalListener(t) -+ defer ln.Close() -+ -+ unblockServer := make(chan struct{}) // close-only -+ defer close(unblockServer) -+ go func() { -+ conn, err := ln.Accept() -+ if err != nil { -+ return -+ } -+ defer conn.Close() -+ <-unblockServer -+ }() -+ -+ ctx, cancel := context.WithCancel(context.Background()) -+ d := Dialer{Config: &Config{ -+ Rand: readerFunc(func(b []byte) (n int, err error) { -+ // By the time crypto/tls wants randomness, that means it has a TCP -+ // connection, so we're past the Dialer's dial and now blocked -+ // in a handshake. Cancel our context and see if we get unstuck. -+ // (Our TCP listener above never reads or writes, so the Handshake -+ // would otherwise be stuck forever) -+ cancel() -+ return len(b), nil -+ }), -+ ServerName: "foo", -+ }} -+ _, err := d.DialContext(ctx, "tcp", ln.Addr().String()) -+ if err != context.Canceled { -+ t.Errorf("err = %v; want context.Canceled", err) -+ } -+} -+ -+func isTimeoutError(err error) bool { -+ if ne, ok := err.(net.Error); ok { -+ return ne.Timeout() -+ } -+ return false -+} -+ -+// tests that Conn.Read returns (non-zero, io.EOF) instead of -+// (non-zero, nil) when a Close (alertCloseNotify) is sitting right -+// behind the application data in the buffer. -+func TestConnReadNonzeroAndEOF(t *testing.T) { -+ // This test is racy: it assumes that after a write to a -+ // localhost TCP connection, the peer TCP connection can -+ // immediately read it. Because it's racy, we skip this test -+ // in short mode, and then retry it several times with an -+ // increasing sleep in between our final write (via srv.Close -+ // below) and the following read. -+ if testing.Short() { -+ t.Skip("skipping in short mode") -+ } -+ var err error -+ for delay := time.Millisecond; delay <= 64*time.Millisecond; delay *= 2 { -+ if err = testConnReadNonzeroAndEOF(t, delay); err == nil { -+ return -+ } -+ } -+ t.Error(err) -+} -+ -+func testConnReadNonzeroAndEOF(t *testing.T, delay time.Duration) error { -+ ln := newLocalListener(t) -+ defer ln.Close() -+ -+ srvCh := make(chan *Conn, 1) -+ var serr error -+ go func() { -+ sconn, err := ln.Accept() -+ if err != nil { -+ serr = err -+ srvCh <- nil -+ return -+ } -+ serverConfig := testConfig.Clone() -+ srv := Server(sconn, serverConfig) -+ if err := srv.Handshake(); err != nil { -+ serr = fmt.Errorf("handshake: %v", err) -+ srvCh <- nil -+ return -+ } -+ srvCh <- srv -+ }() -+ -+ clientConfig := testConfig.Clone() -+ // In TLS 1.3, alerts are encrypted and disguised as application data, so -+ // the opportunistic peek won't work. -+ clientConfig.MaxVersion = VersionTLS12 -+ conn, err := Dial("tcp", ln.Addr().String(), clientConfig) -+ if err != nil { -+ t.Fatal(err) -+ } -+ defer conn.Close() -+ -+ srv := <-srvCh -+ if srv == nil { -+ return serr -+ } -+ -+ buf := make([]byte, 6) -+ -+ srv.Write([]byte("foobar")) -+ n, err := conn.Read(buf) -+ if n != 6 || err != nil || string(buf) != "foobar" { -+ return fmt.Errorf("Read = %d, %v, data %q; want 6, nil, foobar", n, err, buf) -+ } -+ -+ srv.Write([]byte("abcdef")) -+ srv.Close() -+ time.Sleep(delay) -+ n, err = conn.Read(buf) -+ if n != 6 || string(buf) != "abcdef" { -+ return fmt.Errorf("Read = %d, buf= %q; want 6, abcdef", n, buf) -+ } -+ if err != io.EOF { -+ return fmt.Errorf("Second Read error = %v; want io.EOF", err) -+ } -+ return nil -+} -+ -+func TestTLSUniqueMatches(t *testing.T) { -+ ln := newLocalListener(t) -+ defer ln.Close() -+ -+ serverTLSUniques := make(chan []byte) -+ parentDone := make(chan struct{}) -+ childDone := make(chan struct{}) -+ defer close(parentDone) -+ go func() { -+ defer close(childDone) -+ for i := 0; i < 2; i++ { -+ sconn, err := ln.Accept() -+ if err != nil { -+ t.Error(err) -+ return -+ } -+ serverConfig := testConfig.Clone() -+ serverConfig.MaxVersion = VersionTLS12 // TLSUnique is not defined in TLS 1.3 -+ srv := Server(sconn, serverConfig) -+ if err := srv.Handshake(); err != nil { -+ t.Error(err) -+ return -+ } -+ select { -+ case <-parentDone: -+ return -+ case serverTLSUniques <- srv.ConnectionState().TLSUnique: -+ } -+ } -+ }() -+ -+ clientConfig := testConfig.Clone() -+ clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) -+ conn, err := Dial("tcp", ln.Addr().String(), clientConfig) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ var serverTLSUniquesValue []byte -+ select { -+ case <-childDone: -+ return -+ case serverTLSUniquesValue = <-serverTLSUniques: -+ } -+ -+ if !bytes.Equal(conn.ConnectionState().TLSUnique, serverTLSUniquesValue) { -+ t.Error("client and server channel bindings differ") -+ } -+ if serverTLSUniquesValue == nil || bytes.Equal(serverTLSUniquesValue, make([]byte, 12)) { -+ t.Error("tls-unique is empty or zero") -+ } -+ conn.Close() -+ -+ conn, err = Dial("tcp", ln.Addr().String(), clientConfig) -+ if err != nil { -+ t.Fatal(err) -+ } -+ defer conn.Close() -+ if !conn.ConnectionState().DidResume { -+ t.Error("second session did not use resumption") -+ } -+ -+ select { -+ case <-childDone: -+ return -+ case serverTLSUniquesValue = <-serverTLSUniques: -+ } -+ -+ if !bytes.Equal(conn.ConnectionState().TLSUnique, serverTLSUniquesValue) { -+ t.Error("client and server channel bindings differ when session resumption is used") -+ } -+ if serverTLSUniquesValue == nil || bytes.Equal(serverTLSUniquesValue, make([]byte, 12)) { -+ t.Error("resumption tls-unique is empty or zero") -+ } -+} -+ -+func TestVerifyHostname(t *testing.T) { -+ testenv.MustHaveExternalNetwork(t) -+ -+ c, err := Dial("tcp", "www.google.com:https", nil) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if err := c.VerifyHostname("www.google.com"); err != nil { -+ t.Fatalf("verify www.google.com: %v", err) -+ } -+ if err := c.VerifyHostname("www.yahoo.com"); err == nil { -+ t.Fatalf("verify www.yahoo.com succeeded") -+ } -+ -+ c, err = Dial("tcp", "www.google.com:https", &Config{InsecureSkipVerify: true}) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if err := c.VerifyHostname("www.google.com"); err == nil { -+ t.Fatalf("verify www.google.com succeeded with InsecureSkipVerify=true") -+ } -+} -+ -+func TestConnCloseBreakingWrite(t *testing.T) { -+ ln := newLocalListener(t) -+ defer ln.Close() -+ -+ srvCh := make(chan *Conn, 1) -+ var serr error -+ var sconn net.Conn -+ go func() { -+ var err error -+ sconn, err = ln.Accept() -+ if err != nil { -+ serr = err -+ srvCh <- nil -+ return -+ } -+ serverConfig := testConfig.Clone() -+ srv := Server(sconn, serverConfig) -+ if err := srv.Handshake(); err != nil { -+ serr = fmt.Errorf("handshake: %v", err) -+ srvCh <- nil -+ return -+ } -+ srvCh <- srv -+ }() -+ -+ cconn, err := net.Dial("tcp", ln.Addr().String()) -+ if err != nil { -+ t.Fatal(err) -+ } -+ defer cconn.Close() -+ -+ conn := &changeImplConn{ -+ Conn: cconn, -+ } -+ -+ clientConfig := testConfig.Clone() -+ tconn := Client(conn, clientConfig) -+ if err := tconn.Handshake(); err != nil { -+ t.Fatal(err) -+ } -+ -+ srv := <-srvCh -+ if srv == nil { -+ t.Fatal(serr) -+ } -+ defer sconn.Close() -+ -+ connClosed := make(chan struct{}) -+ conn.closeFunc = func() error { -+ close(connClosed) -+ return nil -+ } -+ -+ inWrite := make(chan bool, 1) -+ var errConnClosed = errors.New("conn closed for test") -+ conn.writeFunc = func(p []byte) (n int, err error) { -+ inWrite <- true -+ <-connClosed -+ return 0, errConnClosed -+ } -+ -+ closeReturned := make(chan bool, 1) -+ go func() { -+ <-inWrite -+ tconn.Close() // test that this doesn't block forever. -+ closeReturned <- true -+ }() -+ -+ _, err = tconn.Write([]byte("foo")) -+ if err != errConnClosed { -+ t.Errorf("Write error = %v; want errConnClosed", err) -+ } -+ -+ <-closeReturned -+ if err := tconn.Close(); err != net.ErrClosed { -+ t.Errorf("Close error = %v; want net.ErrClosed", err) -+ } -+} -+ -+func TestConnCloseWrite(t *testing.T) { -+ ln := newLocalListener(t) -+ defer ln.Close() -+ -+ clientDoneChan := make(chan struct{}) -+ -+ serverCloseWrite := func() error { -+ sconn, err := ln.Accept() -+ if err != nil { -+ return fmt.Errorf("accept: %v", err) -+ } -+ defer sconn.Close() -+ -+ serverConfig := testConfig.Clone() -+ srv := Server(sconn, serverConfig) -+ if err := srv.Handshake(); err != nil { -+ return fmt.Errorf("handshake: %v", err) -+ } -+ defer srv.Close() -+ -+ data, err := io.ReadAll(srv) -+ if err != nil { -+ return err -+ } -+ if len(data) > 0 { -+ return fmt.Errorf("Read data = %q; want nothing", data) -+ } -+ -+ if err := srv.CloseWrite(); err != nil { -+ return fmt.Errorf("server CloseWrite: %v", err) -+ } -+ -+ // Wait for clientCloseWrite to finish, so we know we -+ // tested the CloseWrite before we defer the -+ // sconn.Close above, which would also cause the -+ // client to unblock like CloseWrite. -+ <-clientDoneChan -+ return nil -+ } -+ -+ clientCloseWrite := func() error { -+ defer close(clientDoneChan) -+ -+ clientConfig := testConfig.Clone() -+ conn, err := Dial("tcp", ln.Addr().String(), clientConfig) -+ if err != nil { -+ return err -+ } -+ if err := conn.Handshake(); err != nil { -+ return err -+ } -+ defer conn.Close() -+ -+ if err := conn.CloseWrite(); err != nil { -+ return fmt.Errorf("client CloseWrite: %v", err) -+ } -+ -+ if _, err := conn.Write([]byte{0}); err != errShutdown { -+ return fmt.Errorf("CloseWrite error = %v; want errShutdown", err) -+ } -+ -+ data, err := io.ReadAll(conn) -+ if err != nil { -+ return err -+ } -+ if len(data) > 0 { -+ return fmt.Errorf("Read data = %q; want nothing", data) -+ } -+ return nil -+ } -+ -+ errChan := make(chan error, 2) -+ -+ go func() { errChan <- serverCloseWrite() }() -+ go func() { errChan <- clientCloseWrite() }() -+ -+ for i := 0; i < 2; i++ { -+ select { -+ case err := <-errChan: -+ if err != nil { -+ t.Fatal(err) -+ } -+ case <-time.After(10 * time.Second): -+ t.Fatal("deadlock") -+ } -+ } -+ -+ // Also test CloseWrite being called before the handshake is -+ // finished: -+ { -+ ln2 := newLocalListener(t) -+ defer ln2.Close() -+ -+ netConn, err := net.Dial("tcp", ln2.Addr().String()) -+ if err != nil { -+ t.Fatal(err) -+ } -+ defer netConn.Close() -+ conn := Client(netConn, testConfig.Clone()) -+ -+ if err := conn.CloseWrite(); err != errEarlyCloseWrite { -+ t.Errorf("CloseWrite error = %v; want errEarlyCloseWrite", err) -+ } -+ } -+} -+ -+func TestWarningAlertFlood(t *testing.T) { -+ ln := newLocalListener(t) -+ defer ln.Close() -+ -+ server := func() error { -+ sconn, err := ln.Accept() -+ if err != nil { -+ return fmt.Errorf("accept: %v", err) -+ } -+ defer sconn.Close() -+ -+ serverConfig := testConfig.Clone() -+ srv := Server(sconn, serverConfig) -+ if err := srv.Handshake(); err != nil { -+ return fmt.Errorf("handshake: %v", err) -+ } -+ defer srv.Close() -+ -+ _, err = io.ReadAll(srv) -+ if err == nil { -+ return errors.New("unexpected lack of error from server") -+ } -+ const expected = "too many ignored" -+ if str := err.Error(); !strings.Contains(str, expected) { -+ return fmt.Errorf("expected error containing %q, but saw: %s", expected, str) -+ } -+ -+ return nil -+ } -+ -+ errChan := make(chan error, 1) -+ go func() { errChan <- server() }() -+ -+ clientConfig := testConfig.Clone() -+ clientConfig.MaxVersion = VersionTLS12 // there are no warning alerts in TLS 1.3 -+ conn, err := Dial("tcp", ln.Addr().String(), clientConfig) -+ if err != nil { -+ t.Fatal(err) -+ } -+ defer conn.Close() -+ if err := conn.Handshake(); err != nil { -+ t.Fatal(err) -+ } -+ -+ for i := 0; i < maxUselessRecords+1; i++ { -+ conn.sendAlert(alertNoRenegotiation) -+ } -+ -+ if err := <-errChan; err != nil { -+ t.Fatal(err) -+ } -+} -+ -+func TestCloneFuncFields(t *testing.T) { -+ const expectedCount = 8 -+ called := 0 -+ -+ c1 := Config{ -+ Time: func() time.Time { -+ called |= 1 << 0 -+ return time.Time{} -+ }, -+ GetCertificate: func(*ClientHelloInfo) (*Certificate, error) { -+ called |= 1 << 1 -+ return nil, nil -+ }, -+ GetClientCertificate: func(*CertificateRequestInfo) (*Certificate, error) { -+ called |= 1 << 2 -+ return nil, nil -+ }, -+ GetConfigForClient: func(*ClientHelloInfo) (*Config, error) { -+ called |= 1 << 3 -+ return nil, nil -+ }, -+ VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { -+ called |= 1 << 4 -+ return nil -+ }, -+ VerifyConnection: func(ConnectionState) error { -+ called |= 1 << 5 -+ return nil -+ }, -+ UnwrapSession: func(identity []byte, cs ConnectionState) (*SessionState, error) { -+ called |= 1 << 6 -+ return nil, nil -+ }, -+ WrapSession: func(cs ConnectionState, ss *SessionState) ([]byte, error) { -+ called |= 1 << 7 -+ return nil, nil -+ }, -+ } -+ -+ c2 := c1.Clone() -+ -+ c2.Time() -+ c2.GetCertificate(nil) -+ c2.GetClientCertificate(nil) -+ c2.GetConfigForClient(nil) -+ c2.VerifyPeerCertificate(nil, nil) -+ c2.VerifyConnection(ConnectionState{}) -+ c2.UnwrapSession(nil, ConnectionState{}) -+ c2.WrapSession(ConnectionState{}, nil) -+ -+ if called != (1< len(p) { -+ allowed = len(p) -+ } -+ if wrote < allowed { -+ n, err := c.Conn.Write(p[wrote:allowed]) -+ wrote += n -+ if err != nil { -+ return wrote, err -+ } -+ } -+ } -+ return len(p), nil -+} -+ -+func latency(b *testing.B, version uint16, bps int, dynamicRecordSizingDisabled bool) { -+ ln := newLocalListener(b) -+ defer ln.Close() -+ -+ N := b.N -+ -+ go func() { -+ for i := 0; i < N; i++ { -+ sconn, err := ln.Accept() -+ if err != nil { -+ // panic rather than synchronize to avoid benchmark overhead -+ // (cannot call b.Fatal in goroutine) -+ panic(fmt.Errorf("accept: %v", err)) -+ } -+ serverConfig := testConfig.Clone() -+ serverConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled -+ srv := Server(&slowConn{sconn, bps}, serverConfig) -+ if err := srv.Handshake(); err != nil { -+ panic(fmt.Errorf("handshake: %v", err)) -+ } -+ io.Copy(srv, srv) -+ } -+ }() -+ -+ clientConfig := testConfig.Clone() -+ clientConfig.DynamicRecordSizingDisabled = dynamicRecordSizingDisabled -+ clientConfig.MaxVersion = version -+ -+ buf := make([]byte, 16384) -+ peek := make([]byte, 1) -+ -+ for i := 0; i < N; i++ { -+ conn, err := Dial("tcp", ln.Addr().String(), clientConfig) -+ if err != nil { -+ b.Fatal(err) -+ } -+ // make sure we're connected and previous connection has stopped -+ if _, err := conn.Write(buf[:1]); err != nil { -+ b.Fatal(err) -+ } -+ if _, err := io.ReadFull(conn, peek); err != nil { -+ b.Fatal(err) -+ } -+ if _, err := conn.Write(buf); err != nil { -+ b.Fatal(err) -+ } -+ if _, err = io.ReadFull(conn, peek); err != nil { -+ b.Fatal(err) -+ } -+ conn.Close() -+ } -+} -+ -+func BenchmarkLatency(b *testing.B) { -+ for _, mode := range []string{"Max", "Dynamic"} { -+ for _, kbps := range []int{200, 500, 1000, 2000, 5000} { -+ name := fmt.Sprintf("%sPacket/%dkbps", mode, kbps) -+ b.Run(name, func(b *testing.B) { -+ b.Run("TLSv12", func(b *testing.B) { -+ latency(b, VersionTLS12, kbps*1000, mode == "Max") -+ }) -+ b.Run("TLSv13", func(b *testing.B) { -+ latency(b, VersionTLS13, kbps*1000, mode == "Max") -+ }) -+ }) -+ } -+ } -+} -+ -+func TestConnectionStateMarshal(t *testing.T) { -+ cs := &ConnectionState{} -+ _, err := json.Marshal(cs) -+ if err != nil { -+ t.Errorf("json.Marshal failed on ConnectionState: %v", err) -+ } -+} -+ -+func TestConnectionState(t *testing.T) { -+ issuer, err := x509.ParseCertificate(testRSACertificateIssuer) -+ if err != nil { -+ panic(err) -+ } -+ rootCAs := x509.NewCertPool() -+ rootCAs.AddCert(issuer) -+ -+ now := func() time.Time { return time.Unix(1476984729, 0) } -+ -+ const alpnProtocol = "golang" -+ const serverName = "example.golang" -+ var scts = [][]byte{[]byte("dummy sct 1"), []byte("dummy sct 2")} -+ var ocsp = []byte("dummy ocsp") -+ -+ for _, v := range []uint16{VersionTLS12, VersionTLS13} { -+ var name string -+ switch v { -+ case VersionTLS12: -+ name = "TLSv12" -+ case VersionTLS13: -+ name = "TLSv13" -+ } -+ t.Run(name, func(t *testing.T) { -+ config := &Config{ -+ Time: now, -+ Rand: zeroSource{}, -+ Certificates: make([]Certificate, 1), -+ MaxVersion: v, -+ RootCAs: rootCAs, -+ ClientCAs: rootCAs, -+ ClientAuth: RequireAndVerifyClientCert, -+ NextProtos: []string{alpnProtocol}, -+ ServerName: serverName, -+ } -+ config.Certificates[0].Certificate = [][]byte{testRSACertificate} -+ config.Certificates[0].PrivateKey = testRSAPrivateKey -+ config.Certificates[0].SignedCertificateTimestamps = scts -+ config.Certificates[0].OCSPStaple = ocsp -+ -+ ss, cs, err := testHandshake(t, config, config) -+ if err != nil { -+ t.Fatalf("Handshake failed: %v", err) -+ } -+ -+ if ss.Version != v || cs.Version != v { -+ t.Errorf("Got versions %x (server) and %x (client), expected %x", ss.Version, cs.Version, v) -+ } -+ -+ if !ss.HandshakeComplete || !cs.HandshakeComplete { -+ t.Errorf("Got HandshakeComplete %v (server) and %v (client), expected true", ss.HandshakeComplete, cs.HandshakeComplete) -+ } -+ -+ if ss.DidResume || cs.DidResume { -+ t.Errorf("Got DidResume %v (server) and %v (client), expected false", ss.DidResume, cs.DidResume) -+ } -+ -+ if ss.CipherSuite == 0 || cs.CipherSuite == 0 { -+ t.Errorf("Got invalid cipher suite: %v (server) and %v (client)", ss.CipherSuite, cs.CipherSuite) -+ } -+ -+ if ss.NegotiatedProtocol != alpnProtocol || cs.NegotiatedProtocol != alpnProtocol { -+ t.Errorf("Got negotiated protocol %q (server) and %q (client), expected %q", ss.NegotiatedProtocol, cs.NegotiatedProtocol, alpnProtocol) -+ } -+ -+ if !cs.NegotiatedProtocolIsMutual { -+ t.Errorf("Got false NegotiatedProtocolIsMutual on the client side") -+ } -+ // NegotiatedProtocolIsMutual on the server side is unspecified. -+ -+ if ss.ServerName != serverName { -+ t.Errorf("Got server name %q, expected %q", ss.ServerName, serverName) -+ } -+ if cs.ServerName != serverName { -+ t.Errorf("Got server name on client connection %q, expected %q", cs.ServerName, serverName) -+ } -+ -+ if len(ss.PeerCertificates) != 1 || len(cs.PeerCertificates) != 1 { -+ t.Errorf("Got %d (server) and %d (client) peer certificates, expected %d", len(ss.PeerCertificates), len(cs.PeerCertificates), 1) -+ } -+ -+ if len(ss.VerifiedChains) != 1 || len(cs.VerifiedChains) != 1 { -+ t.Errorf("Got %d (server) and %d (client) verified chains, expected %d", len(ss.VerifiedChains), len(cs.VerifiedChains), 1) -+ } else if len(ss.VerifiedChains[0]) != 2 || len(cs.VerifiedChains[0]) != 2 { -+ t.Errorf("Got %d (server) and %d (client) long verified chain, expected %d", len(ss.VerifiedChains[0]), len(cs.VerifiedChains[0]), 2) -+ } -+ -+ if len(cs.SignedCertificateTimestamps) != 2 { -+ t.Errorf("Got %d SCTs, expected %d", len(cs.SignedCertificateTimestamps), 2) -+ } -+ if !bytes.Equal(cs.OCSPResponse, ocsp) { -+ t.Errorf("Got OCSPs %x, expected %x", cs.OCSPResponse, ocsp) -+ } -+ // Only TLS 1.3 supports OCSP and SCTs on client certs. -+ if v == VersionTLS13 { -+ if len(ss.SignedCertificateTimestamps) != 2 { -+ t.Errorf("Got %d client SCTs, expected %d", len(ss.SignedCertificateTimestamps), 2) -+ } -+ if !bytes.Equal(ss.OCSPResponse, ocsp) { -+ t.Errorf("Got client OCSPs %x, expected %x", ss.OCSPResponse, ocsp) -+ } -+ } -+ -+ if v == VersionTLS13 { -+ if ss.TLSUnique != nil || cs.TLSUnique != nil { -+ t.Errorf("Got TLSUnique %x (server) and %x (client), expected nil in TLS 1.3", ss.TLSUnique, cs.TLSUnique) -+ } -+ } else { -+ if ss.TLSUnique == nil || cs.TLSUnique == nil { -+ t.Errorf("Got TLSUnique %x (server) and %x (client), expected non-nil", ss.TLSUnique, cs.TLSUnique) -+ } -+ } -+ }) -+ } -+} -+ -+// Issue 28744: Ensure that we don't modify memory -+// that Config doesn't own such as Certificates. -+func TestBuildNameToCertificate_doesntModifyCertificates(t *testing.T) { -+ c0 := Certificate{ -+ Certificate: [][]byte{testRSACertificate}, -+ PrivateKey: testRSAPrivateKey, -+ } -+ c1 := Certificate{ -+ Certificate: [][]byte{testSNICertificate}, -+ PrivateKey: testRSAPrivateKey, -+ } -+ config := testConfig.Clone() -+ config.Certificates = []Certificate{c0, c1} -+ -+ config.BuildNameToCertificate() -+ got := config.Certificates -+ want := []Certificate{c0, c1} -+ if !reflect.DeepEqual(got, want) { -+ t.Fatalf("Certificates were mutated by BuildNameToCertificate\nGot: %#v\nWant: %#v\n", got, want) -+ } -+} -+ -+func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } -+ -+func TestClientHelloInfo_SupportsCertificate(t *testing.T) { -+ rsaCert := &Certificate{ -+ Certificate: [][]byte{testRSACertificate}, -+ PrivateKey: testRSAPrivateKey, -+ } -+ pkcs1Cert := &Certificate{ -+ Certificate: [][]byte{testRSACertificate}, -+ PrivateKey: testRSAPrivateKey, -+ SupportedSignatureAlgorithms: []SignatureScheme{PKCS1WithSHA1, PKCS1WithSHA256}, -+ } -+ ecdsaCert := &Certificate{ -+ // ECDSA P-256 certificate -+ Certificate: [][]byte{testP256Certificate}, -+ PrivateKey: testP256PrivateKey, -+ } -+ ed25519Cert := &Certificate{ -+ Certificate: [][]byte{testEd25519Certificate}, -+ PrivateKey: testEd25519PrivateKey, -+ } -+ -+ tests := []struct { -+ c *Certificate -+ chi *ClientHelloInfo -+ wantErr string -+ }{ -+ {rsaCert, &ClientHelloInfo{ -+ ServerName: "example.golang", -+ SignatureSchemes: []SignatureScheme{PSSWithSHA256}, -+ SupportedVersions: []uint16{VersionTLS13}, -+ }, ""}, -+ {ecdsaCert, &ClientHelloInfo{ -+ SignatureSchemes: []SignatureScheme{PSSWithSHA256, ECDSAWithP256AndSHA256}, -+ SupportedVersions: []uint16{VersionTLS13, VersionTLS12}, -+ }, ""}, -+ {rsaCert, &ClientHelloInfo{ -+ ServerName: "example.com", -+ SignatureSchemes: []SignatureScheme{PSSWithSHA256}, -+ SupportedVersions: []uint16{VersionTLS13}, -+ }, "not valid for requested server name"}, -+ {ecdsaCert, &ClientHelloInfo{ -+ SignatureSchemes: []SignatureScheme{ECDSAWithP384AndSHA384}, -+ SupportedVersions: []uint16{VersionTLS13}, -+ }, "signature algorithms"}, -+ {pkcs1Cert, &ClientHelloInfo{ -+ SignatureSchemes: []SignatureScheme{PSSWithSHA256, ECDSAWithP256AndSHA256}, -+ SupportedVersions: []uint16{VersionTLS13}, -+ }, "signature algorithms"}, -+ -+ {rsaCert, &ClientHelloInfo{ -+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, -+ SignatureSchemes: []SignatureScheme{PKCS1WithSHA1}, -+ SupportedVersions: []uint16{VersionTLS13, VersionTLS12}, -+ }, "signature algorithms"}, -+ {rsaCert, &ClientHelloInfo{ -+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, -+ SignatureSchemes: []SignatureScheme{PKCS1WithSHA1}, -+ SupportedVersions: []uint16{VersionTLS13, VersionTLS12}, -+ config: &Config{ -+ MaxVersion: VersionTLS12, -+ }, -+ }, ""}, // Check that mutual version selection works. -+ -+ {ecdsaCert, &ClientHelloInfo{ -+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, -+ SupportedCurves: []CurveID{CurveP256}, -+ SupportedPoints: []uint8{pointFormatUncompressed}, -+ SignatureSchemes: []SignatureScheme{ECDSAWithP256AndSHA256}, -+ SupportedVersions: []uint16{VersionTLS12}, -+ }, ""}, -+ {ecdsaCert, &ClientHelloInfo{ -+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, -+ SupportedCurves: []CurveID{CurveP256}, -+ SupportedPoints: []uint8{pointFormatUncompressed}, -+ SignatureSchemes: []SignatureScheme{ECDSAWithP384AndSHA384}, -+ SupportedVersions: []uint16{VersionTLS12}, -+ }, ""}, // TLS 1.2 does not restrict curves based on the SignatureScheme. -+ {ecdsaCert, &ClientHelloInfo{ -+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, -+ SupportedCurves: []CurveID{CurveP256}, -+ SupportedPoints: []uint8{pointFormatUncompressed}, -+ SignatureSchemes: nil, -+ SupportedVersions: []uint16{VersionTLS12}, -+ }, ""}, // TLS 1.2 comes with default signature schemes. -+ {ecdsaCert, &ClientHelloInfo{ -+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, -+ SupportedCurves: []CurveID{CurveP256}, -+ SupportedPoints: []uint8{pointFormatUncompressed}, -+ SignatureSchemes: []SignatureScheme{ECDSAWithP256AndSHA256}, -+ SupportedVersions: []uint16{VersionTLS12}, -+ }, "cipher suite"}, -+ {ecdsaCert, &ClientHelloInfo{ -+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, -+ SupportedCurves: []CurveID{CurveP256}, -+ SupportedPoints: []uint8{pointFormatUncompressed}, -+ SignatureSchemes: []SignatureScheme{ECDSAWithP256AndSHA256}, -+ SupportedVersions: []uint16{VersionTLS12}, -+ config: &Config{ -+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, -+ }, -+ }, "cipher suite"}, -+ {ecdsaCert, &ClientHelloInfo{ -+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, -+ SupportedCurves: []CurveID{CurveP384}, -+ SupportedPoints: []uint8{pointFormatUncompressed}, -+ SignatureSchemes: []SignatureScheme{ECDSAWithP256AndSHA256}, -+ SupportedVersions: []uint16{VersionTLS12}, -+ }, "certificate curve"}, -+ {ecdsaCert, &ClientHelloInfo{ -+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, -+ SupportedCurves: []CurveID{CurveP256}, -+ SupportedPoints: []uint8{1}, -+ SignatureSchemes: []SignatureScheme{ECDSAWithP256AndSHA256}, -+ SupportedVersions: []uint16{VersionTLS12}, -+ }, "doesn't support ECDHE"}, -+ {ecdsaCert, &ClientHelloInfo{ -+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, -+ SupportedCurves: []CurveID{CurveP256}, -+ SupportedPoints: []uint8{pointFormatUncompressed}, -+ SignatureSchemes: []SignatureScheme{PSSWithSHA256}, -+ SupportedVersions: []uint16{VersionTLS12}, -+ }, "signature algorithms"}, -+ -+ {ed25519Cert, &ClientHelloInfo{ -+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, -+ SupportedCurves: []CurveID{CurveP256}, // only relevant for ECDHE support -+ SupportedPoints: []uint8{pointFormatUncompressed}, -+ SignatureSchemes: []SignatureScheme{Ed25519}, -+ SupportedVersions: []uint16{VersionTLS12}, -+ }, ""}, -+ {ed25519Cert, &ClientHelloInfo{ -+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, -+ SupportedCurves: []CurveID{CurveP256}, // only relevant for ECDHE support -+ SupportedPoints: []uint8{pointFormatUncompressed}, -+ SignatureSchemes: []SignatureScheme{Ed25519}, -+ SupportedVersions: []uint16{VersionTLS10}, -+ }, "doesn't support Ed25519"}, -+ {ed25519Cert, &ClientHelloInfo{ -+ CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, -+ SupportedCurves: []CurveID{}, -+ SupportedPoints: []uint8{pointFormatUncompressed}, -+ SignatureSchemes: []SignatureScheme{Ed25519}, -+ SupportedVersions: []uint16{VersionTLS12}, -+ }, "doesn't support ECDHE"}, -+ -+ {rsaCert, &ClientHelloInfo{ -+ CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, -+ SupportedCurves: []CurveID{CurveP256}, // only relevant for ECDHE support -+ SupportedPoints: []uint8{pointFormatUncompressed}, -+ SupportedVersions: []uint16{VersionTLS10}, -+ }, ""}, -+ {rsaCert, &ClientHelloInfo{ -+ CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, -+ SupportedVersions: []uint16{VersionTLS12}, -+ }, ""}, // static RSA fallback -+ } -+ for i, tt := range tests { -+ err := tt.chi.SupportsCertificate(tt.c) -+ switch { -+ case tt.wantErr == "" && err != nil: -+ t.Errorf("%d: unexpected error: %v", i, err) -+ case tt.wantErr != "" && err == nil: -+ t.Errorf("%d: unexpected success", i) -+ case tt.wantErr != "" && !strings.Contains(err.Error(), tt.wantErr): -+ t.Errorf("%d: got error %q, expected %q", i, err, tt.wantErr) -+ } -+ } -+} -+ -+func TestCipherSuites(t *testing.T) { -+ var lastID uint16 -+ for _, c := range CipherSuites() { -+ if lastID > c.ID { -+ t.Errorf("CipherSuites are not ordered by ID: got %#04x after %#04x", c.ID, lastID) -+ } else { -+ lastID = c.ID -+ } -+ -+ if c.Insecure { -+ t.Errorf("%#04x: Insecure CipherSuite returned by CipherSuites()", c.ID) -+ } -+ } -+ lastID = 0 -+ for _, c := range InsecureCipherSuites() { -+ if lastID > c.ID { -+ t.Errorf("InsecureCipherSuites are not ordered by ID: got %#04x after %#04x", c.ID, lastID) -+ } else { -+ lastID = c.ID -+ } -+ -+ if !c.Insecure { -+ t.Errorf("%#04x: not Insecure CipherSuite returned by InsecureCipherSuites()", c.ID) -+ } -+ } -+ -+ CipherSuiteByID := func(id uint16) *CipherSuite { -+ for _, c := range CipherSuites() { -+ if c.ID == id { -+ return c -+ } -+ } -+ for _, c := range InsecureCipherSuites() { -+ if c.ID == id { -+ return c -+ } -+ } -+ return nil -+ } -+ -+ for _, c := range cipherSuites { -+ cc := CipherSuiteByID(c.id) -+ if cc == nil { -+ t.Errorf("%#04x: no CipherSuite entry", c.id) -+ continue -+ } -+ -+ if tls12Only := c.flags&suiteTLS12 != 0; tls12Only && len(cc.SupportedVersions) != 1 { -+ t.Errorf("%#04x: suite is TLS 1.2 only, but SupportedVersions is %v", c.id, cc.SupportedVersions) -+ } else if !tls12Only && len(cc.SupportedVersions) != 3 { -+ t.Errorf("%#04x: suite TLS 1.0-1.2, but SupportedVersions is %v", c.id, cc.SupportedVersions) -+ } -+ -+ if got := CipherSuiteName(c.id); got != cc.Name { -+ t.Errorf("%#04x: unexpected CipherSuiteName: got %q, expected %q", c.id, got, cc.Name) -+ } -+ } -+ for _, c := range cipherSuitesTLS13 { -+ cc := CipherSuiteByID(c.id) -+ if cc == nil { -+ t.Errorf("%#04x: no CipherSuite entry", c.id) -+ continue -+ } -+ -+ if cc.Insecure { -+ t.Errorf("%#04x: Insecure %v, expected false", c.id, cc.Insecure) -+ } -+ if len(cc.SupportedVersions) != 1 || cc.SupportedVersions[0] != VersionTLS13 { -+ t.Errorf("%#04x: suite is TLS 1.3 only, but SupportedVersions is %v", c.id, cc.SupportedVersions) -+ } -+ -+ if got := CipherSuiteName(c.id); got != cc.Name { -+ t.Errorf("%#04x: unexpected CipherSuiteName: got %q, expected %q", c.id, got, cc.Name) -+ } -+ } -+ -+ if got := CipherSuiteName(0xabc); got != "0x0ABC" { -+ t.Errorf("unexpected fallback CipherSuiteName: got %q, expected 0x0ABC", got) -+ } -+ -+ if len(cipherSuitesPreferenceOrder) != len(cipherSuites) { -+ t.Errorf("cipherSuitesPreferenceOrder is not the same size as cipherSuites") -+ } -+ if len(cipherSuitesPreferenceOrderNoAES) != len(cipherSuitesPreferenceOrder) { -+ t.Errorf("cipherSuitesPreferenceOrderNoAES is not the same size as cipherSuitesPreferenceOrder") -+ } -+ -+ // Check that disabled suites are at the end of the preference lists, and -+ // that they are marked insecure. -+ for i, id := range disabledCipherSuites { -+ offset := len(cipherSuitesPreferenceOrder) - len(disabledCipherSuites) -+ if cipherSuitesPreferenceOrder[offset+i] != id { -+ t.Errorf("disabledCipherSuites[%d]: not at the end of cipherSuitesPreferenceOrder", i) -+ } -+ if cipherSuitesPreferenceOrderNoAES[offset+i] != id { -+ t.Errorf("disabledCipherSuites[%d]: not at the end of cipherSuitesPreferenceOrderNoAES", i) -+ } -+ c := CipherSuiteByID(id) -+ if c == nil { -+ t.Errorf("%#04x: no CipherSuite entry", id) -+ continue -+ } -+ if !c.Insecure { -+ t.Errorf("%#04x: disabled by default but not marked insecure", id) -+ } -+ } -+ -+ for i, prefOrder := range [][]uint16{cipherSuitesPreferenceOrder, cipherSuitesPreferenceOrderNoAES} { -+ // Check that insecure and HTTP/2 bad cipher suites are at the end of -+ // the preference lists. -+ var sawInsecure, sawBad bool -+ for _, id := range prefOrder { -+ c := CipherSuiteByID(id) -+ if c == nil { -+ t.Errorf("%#04x: no CipherSuite entry", id) -+ continue -+ } -+ -+ if c.Insecure { -+ sawInsecure = true -+ } else if sawInsecure { -+ t.Errorf("%#04x: secure suite after insecure one(s)", id) -+ } -+ -+ if http2isBadCipher(id) { -+ sawBad = true -+ } else if sawBad { -+ t.Errorf("%#04x: non-bad suite after bad HTTP/2 one(s)", id) -+ } -+ } -+ -+ // Check that the list is sorted according to the documented criteria. -+ isBetter := func(a, b int) bool { -+ aSuite, bSuite := cipherSuiteByID(prefOrder[a]), cipherSuiteByID(prefOrder[b]) -+ aName, bName := CipherSuiteName(prefOrder[a]), CipherSuiteName(prefOrder[b]) -+ // * < RC4 -+ if !strings.Contains(aName, "RC4") && strings.Contains(bName, "RC4") { -+ return true -+ } else if strings.Contains(aName, "RC4") && !strings.Contains(bName, "RC4") { -+ return false -+ } -+ // * < CBC_SHA256 -+ if !strings.Contains(aName, "CBC_SHA256") && strings.Contains(bName, "CBC_SHA256") { -+ return true -+ } else if strings.Contains(aName, "CBC_SHA256") && !strings.Contains(bName, "CBC_SHA256") { -+ return false -+ } -+ // * < 3DES -+ if !strings.Contains(aName, "3DES") && strings.Contains(bName, "3DES") { -+ return true -+ } else if strings.Contains(aName, "3DES") && !strings.Contains(bName, "3DES") { -+ return false -+ } -+ // ECDHE < * -+ if aSuite.flags&suiteECDHE != 0 && bSuite.flags&suiteECDHE == 0 { -+ return true -+ } else if aSuite.flags&suiteECDHE == 0 && bSuite.flags&suiteECDHE != 0 { -+ return false -+ } -+ // AEAD < CBC -+ if aSuite.aead != nil && bSuite.aead == nil { -+ return true -+ } else if aSuite.aead == nil && bSuite.aead != nil { -+ return false -+ } -+ // AES < ChaCha20 -+ if strings.Contains(aName, "AES") && strings.Contains(bName, "CHACHA20") { -+ return i == 0 // true for cipherSuitesPreferenceOrder -+ } else if strings.Contains(aName, "CHACHA20") && strings.Contains(bName, "AES") { -+ return i != 0 // true for cipherSuitesPreferenceOrderNoAES -+ } -+ // AES-128 < AES-256 -+ if strings.Contains(aName, "AES_128") && strings.Contains(bName, "AES_256") { -+ return true -+ } else if strings.Contains(aName, "AES_256") && strings.Contains(bName, "AES_128") { -+ return false -+ } -+ // ECDSA < RSA -+ if aSuite.flags&suiteECSign != 0 && bSuite.flags&suiteECSign == 0 { -+ return true -+ } else if aSuite.flags&suiteECSign == 0 && bSuite.flags&suiteECSign != 0 { -+ return false -+ } -+ t.Fatalf("two ciphersuites are equal by all criteria: %v and %v", aName, bName) -+ panic("unreachable") -+ } -+ if !sort.SliceIsSorted(prefOrder, isBetter) { -+ t.Error("preference order is not sorted according to the rules") -+ } -+ } -+} -+ -+func TestVersionName(t *testing.T) { -+ if got, exp := VersionName(VersionTLS13), "TLS 1.3"; got != exp { -+ t.Errorf("unexpected VersionName: got %q, expected %q", got, exp) -+ } -+ if got, exp := VersionName(0x12a), "0x012A"; got != exp { -+ t.Errorf("unexpected fallback VersionName: got %q, expected %q", got, exp) -+ } -+} -+ -+// http2isBadCipher is copied from net/http. -+// TODO: if it ends up exposed somewhere, use that instead. -+func http2isBadCipher(cipher uint16) bool { -+ switch cipher { -+ case TLS_RSA_WITH_RC4_128_SHA, -+ TLS_RSA_WITH_3DES_EDE_CBC_SHA, -+ TLS_RSA_WITH_AES_128_CBC_SHA, -+ TLS_RSA_WITH_AES_256_CBC_SHA, -+ TLS_RSA_WITH_AES_128_CBC_SHA256, -+ TLS_RSA_WITH_AES_128_GCM_SHA256, -+ TLS_RSA_WITH_AES_256_GCM_SHA384, -+ TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, -+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, -+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, -+ TLS_ECDHE_RSA_WITH_RC4_128_SHA, -+ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, -+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, -+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, -+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, -+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: -+ return true -+ default: -+ return false -+ } -+} -+ -+type brokenSigner struct{ crypto.Signer } -+ -+func (s brokenSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) { -+ // Replace opts with opts.HashFunc(), so rsa.PSSOptions are discarded. -+ return s.Signer.Sign(rand, digest, opts.HashFunc()) -+} -+ -+// TestPKCS1OnlyCert uses a client certificate with a broken crypto.Signer that -+// always makes PKCS #1 v1.5 signatures, so can't be used with RSA-PSS. -+func TestPKCS1OnlyCert(t *testing.T) { -+ clientConfig := testConfig.Clone() -+ clientConfig.Certificates = []Certificate{{ -+ Certificate: [][]byte{testRSACertificate}, -+ PrivateKey: brokenSigner{testRSAPrivateKey}, -+ }} -+ serverConfig := testConfig.Clone() -+ serverConfig.MaxVersion = VersionTLS12 // TLS 1.3 doesn't support PKCS #1 v1.5 -+ serverConfig.ClientAuth = RequireAnyClientCert -+ -+ // If RSA-PSS is selected, the handshake should fail. -+ if _, _, err := testHandshake(t, clientConfig, serverConfig); err == nil { -+ t.Fatal("expected broken certificate to cause connection to fail") -+ } -+ -+ clientConfig.Certificates[0].SupportedSignatureAlgorithms = -+ []SignatureScheme{PKCS1WithSHA1, PKCS1WithSHA256} -+ -+ // But if the certificate restricts supported algorithms, RSA-PSS should not -+ // be selected, and the handshake should succeed. -+ if _, _, err := testHandshake(t, clientConfig, serverConfig); err != nil { -+ t.Error(err) -+ } -+} -+ -+func TestVerifyCertificates(t *testing.T) { -+ // See https://go.dev/issue/31641. -+ t.Run("TLSv12", func(t *testing.T) { testVerifyCertificates(t, VersionTLS12) }) -+ t.Run("TLSv13", func(t *testing.T) { testVerifyCertificates(t, VersionTLS13) }) -+} -+ -+func testVerifyCertificates(t *testing.T, version uint16) { -+ tests := []struct { -+ name string -+ -+ InsecureSkipVerify bool -+ ClientAuth ClientAuthType -+ ClientCertificates bool -+ }{ -+ { -+ name: "defaults", -+ }, -+ { -+ name: "InsecureSkipVerify", -+ InsecureSkipVerify: true, -+ }, -+ { -+ name: "RequestClientCert with no certs", -+ ClientAuth: RequestClientCert, -+ }, -+ { -+ name: "RequestClientCert with certs", -+ ClientAuth: RequestClientCert, -+ ClientCertificates: true, -+ }, -+ { -+ name: "RequireAnyClientCert", -+ ClientAuth: RequireAnyClientCert, -+ ClientCertificates: true, -+ }, -+ { -+ name: "VerifyClientCertIfGiven with no certs", -+ ClientAuth: VerifyClientCertIfGiven, -+ }, -+ { -+ name: "VerifyClientCertIfGiven with certs", -+ ClientAuth: VerifyClientCertIfGiven, -+ ClientCertificates: true, -+ }, -+ { -+ name: "RequireAndVerifyClientCert", -+ ClientAuth: RequireAndVerifyClientCert, -+ ClientCertificates: true, -+ }, -+ } -+ -+ issuer, err := x509.ParseCertificate(testRSACertificateIssuer) -+ if err != nil { -+ t.Fatal(err) -+ } -+ rootCAs := x509.NewCertPool() -+ rootCAs.AddCert(issuer) -+ -+ for _, test := range tests { -+ test := test -+ t.Run(test.name, func(t *testing.T) { -+ t.Parallel() -+ -+ var serverVerifyConnection, clientVerifyConnection bool -+ var serverVerifyPeerCertificates, clientVerifyPeerCertificates bool -+ -+ clientConfig := testConfig.Clone() -+ clientConfig.Time = func() time.Time { return time.Unix(1476984729, 0) } -+ clientConfig.MaxVersion = version -+ clientConfig.MinVersion = version -+ clientConfig.RootCAs = rootCAs -+ clientConfig.ServerName = "example.golang" -+ clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) -+ serverConfig := clientConfig.Clone() -+ serverConfig.ClientCAs = rootCAs -+ -+ clientConfig.VerifyConnection = func(cs ConnectionState) error { -+ clientVerifyConnection = true -+ return nil -+ } -+ clientConfig.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { -+ clientVerifyPeerCertificates = true -+ return nil -+ } -+ serverConfig.VerifyConnection = func(cs ConnectionState) error { -+ serverVerifyConnection = true -+ return nil -+ } -+ serverConfig.VerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { -+ serverVerifyPeerCertificates = true -+ return nil -+ } -+ -+ clientConfig.InsecureSkipVerify = test.InsecureSkipVerify -+ serverConfig.ClientAuth = test.ClientAuth -+ if !test.ClientCertificates { -+ clientConfig.Certificates = nil -+ } -+ -+ if _, _, err := testHandshake(t, clientConfig, serverConfig); err != nil { -+ t.Fatal(err) -+ } -+ -+ want := serverConfig.ClientAuth != NoClientCert -+ if serverVerifyPeerCertificates != want { -+ t.Errorf("VerifyPeerCertificates on the server: got %v, want %v", -+ serverVerifyPeerCertificates, want) -+ } -+ if !clientVerifyPeerCertificates { -+ t.Errorf("VerifyPeerCertificates not called on the client") -+ } -+ if !serverVerifyConnection { -+ t.Error("VerifyConnection did not get called on the server") -+ } -+ if !clientVerifyConnection { -+ t.Error("VerifyConnection did not get called on the client") -+ } -+ -+ serverVerifyPeerCertificates, clientVerifyPeerCertificates = false, false -+ serverVerifyConnection, clientVerifyConnection = false, false -+ cs, _, err := testHandshake(t, clientConfig, serverConfig) -+ if err != nil { -+ t.Fatal(err) -+ } -+ if !cs.DidResume { -+ t.Error("expected resumption") -+ } -+ -+ if serverVerifyPeerCertificates { -+ t.Error("VerifyPeerCertificates got called on the server on resumption") -+ } -+ if clientVerifyPeerCertificates { -+ t.Error("VerifyPeerCertificates got called on the client on resumption") -+ } -+ if !serverVerifyConnection { -+ t.Error("VerifyConnection did not get called on the server on resumption") -+ } -+ if !clientVerifyConnection { -+ t.Error("VerifyConnection did not get called on the client on resumption") -+ } -+ }) -+ } -+} ->>>>>>> 70a351c141 (wip) -======= ->>>>>>> 80d9391199 (wip) -diff --git a/src/crypto/x509/boring.go b/src/crypto/x509/boring.go -index 095b58c315..ac06591ea8 100644 ---- a/src/crypto/x509/boring.go -+++ b/src/crypto/x509/boring.go -@@ -2,7 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -<<<<<<< HEAD - --//go:build boringcrypto -+//go:build !no_openssl - - package x509 - -======= - --//go:build boringcrypto -+//go:build !no_openssl - - package x509 - -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 0023bf4c7a (rebase) -======= -diff --git a/src/crypto/x509/boring.go-e b/src/crypto/x509/boring.go-e -new file mode 100644 -index 0000000000..095b58c315 ---- /dev/null -+++ b/src/crypto/x509/boring.go-e -@@ -0,0 +1,39 @@ -+// Copyright 2022 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 boringcrypto -+ -+package x509 -+ -+import ( -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/internal/boring/fipstls" -+ "crypto/rsa" -+) -+ -+// boringAllowCert reports whether c is allowed to be used -+// in a certificate chain by the current fipstls enforcement setting. -+// It is called for each leaf, intermediate, and root certificate. -+func boringAllowCert(c *Certificate) bool { -+ if !fipstls.Required() { -+ return true -+ } -+ -+ // The key must be RSA 2048, RSA 3072, RSA 4096, -+ // or ECDSA P-256, P-384, P-521. -+ switch k := c.PublicKey.(type) { -+ default: -+ return false -+ case *rsa.PublicKey: -+ if size := k.N.BitLen(); size != 2048 && size != 3072 && size != 4096 { -+ return false -+ } -+ case *ecdsa.PublicKey: -+ if k.Curve != elliptic.P256() && k.Curve != elliptic.P384() && k.Curve != elliptic.P521() { -+ return false -+ } -+ } -+ return true -+} ->>>>>>> 70a351c141 (wip) -======= ->>>>>>> 80d9391199 (wip) -diff --git a/src/crypto/x509/boring_test.go b/src/crypto/x509/boring_test.go -index 102acda578..07b3c7095e 100644 ---- a/src/crypto/x509/boring_test.go -+++ b/src/crypto/x509/boring_test.go -@@ -2,7 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -<<<<<<< HEAD - --//go:build boringcrypto -+//go:build !no_openssl - - package x509 - -======= - --//go:build boringcrypto -+//go:build !no_openssl - - package x509 - -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 0023bf4c7a (rebase) -======= -diff --git a/src/crypto/x509/boring_test.go-e b/src/crypto/x509/boring_test.go-e -new file mode 100644 -index 0000000000..102acda578 ---- /dev/null -+++ b/src/crypto/x509/boring_test.go-e -@@ -0,0 +1,151 @@ -+// Copyright 2022 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 boringcrypto -+ -+package x509 -+ -+import ( -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/internal/boring/fipstls" -+ "crypto/internal/backend/boringtest" -+ "crypto/rand" -+ "crypto/rsa" -+ "crypto/x509/pkix" -+ "fmt" -+ "math/big" -+ "strings" -+ "testing" -+ "time" -+) -+ -+const ( -+ boringCertCA = iota -+ boringCertLeaf -+ boringCertFIPSOK = 0x80 -+) -+ -+func boringRSAKey(t *testing.T, size int) *rsa.PrivateKey { -+ k, err := rsa.GenerateKey(rand.Reader, size) -+ if err != nil { -+ t.Fatal(err) -+ } -+ return k -+} -+ -+func boringECDSAKey(t *testing.T, curve elliptic.Curve) *ecdsa.PrivateKey { -+ k, err := ecdsa.GenerateKey(curve, rand.Reader) -+ if err != nil { -+ t.Fatal(err) -+ } -+ return k -+} -+ -+type boringCertificate struct { -+ name string -+ org string -+ parentOrg string -+ der []byte -+ cert *Certificate -+ key interface{} -+ fipsOK bool -+} -+ -+func TestBoringAllowCert(t *testing.T) { -+ R1 := testBoringCert(t, "R1", boringRSAKey(t, 2048), nil, boringCertCA|boringCertFIPSOK) -+ R2 := testBoringCert(t, "R2", boringRSAKey(t, 512), nil, boringCertCA) -+ R3 := testBoringCert(t, "R3", boringRSAKey(t, 4096), nil, boringCertCA|boringCertFIPSOK) -+ -+ M1_R1 := testBoringCert(t, "M1_R1", boringECDSAKey(t, elliptic.P256()), R1, boringCertCA|boringCertFIPSOK) -+ -+ var M2_R1 *boringCertificate -+ // If OpenSSL supports P224, use the default upstream behavior, -+ // otherwise test with P384 -+ if boringtest.Supports(t, "CurveP224") { -+ M2_R1 = testBoringCert(t, "M2_R1", boringECDSAKey(t, elliptic.P224()), R1, boringCertCA) -+ } else { -+ M2_R1 = testBoringCert(t, "M2_R1", boringECDSAKey(t, elliptic.P384()), R1, boringCertCA|boringCertFIPSOK) -+ } -+ -+ I_R1 := testBoringCert(t, "I_R1", boringRSAKey(t, 3072), R1, boringCertCA|boringCertFIPSOK) -+ testBoringCert(t, "I_R2", I_R1.key, R2, boringCertCA|boringCertFIPSOK) -+ testBoringCert(t, "I_M1", I_R1.key, M1_R1, boringCertCA|boringCertFIPSOK) -+ testBoringCert(t, "I_M2", I_R1.key, M2_R1, boringCertCA|boringCertFIPSOK) -+ -+ I_R3 := testBoringCert(t, "I_R3", boringRSAKey(t, 3072), R3, boringCertCA|boringCertFIPSOK) -+ testBoringCert(t, "I_R3", I_R3.key, R3, boringCertCA|boringCertFIPSOK) -+ -+ testBoringCert(t, "L1_I", boringECDSAKey(t, elliptic.P384()), I_R1, boringCertLeaf|boringCertFIPSOK) -+ testBoringCert(t, "L2_I", boringRSAKey(t, 1024), I_R1, boringCertLeaf) -+} -+ -+func testBoringCert(t *testing.T, name string, key interface{}, parent *boringCertificate, mode int) *boringCertificate { -+ org := name -+ parentOrg := "" -+ if i := strings.Index(org, "_"); i >= 0 { -+ org = org[:i] -+ parentOrg = name[i+1:] -+ } -+ tmpl := &Certificate{ -+ SerialNumber: big.NewInt(1), -+ Subject: pkix.Name{ -+ Organization: []string{org}, -+ }, -+ NotBefore: time.Unix(0, 0), -+ NotAfter: time.Unix(0, 0), -+ -+ KeyUsage: KeyUsageKeyEncipherment | KeyUsageDigitalSignature, -+ ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}, -+ BasicConstraintsValid: true, -+ } -+ if mode&^boringCertFIPSOK == boringCertLeaf { -+ tmpl.DNSNames = []string{"example.com"} -+ } else { -+ tmpl.IsCA = true -+ tmpl.KeyUsage |= KeyUsageCertSign -+ } -+ -+ var pcert *Certificate -+ var pkey interface{} -+ if parent != nil { -+ pcert = parent.cert -+ pkey = parent.key -+ } else { -+ pcert = tmpl -+ pkey = key -+ } -+ -+ var pub interface{} -+ var desc string -+ switch k := key.(type) { -+ case *rsa.PrivateKey: -+ pub = &k.PublicKey -+ desc = fmt.Sprintf("RSA-%d", k.N.BitLen()) -+ case *ecdsa.PrivateKey: -+ pub = &k.PublicKey -+ desc = "ECDSA-" + k.Curve.Params().Name -+ default: -+ t.Fatalf("invalid key %T", key) -+ } -+ -+ der, err := CreateCertificate(rand.Reader, tmpl, pcert, pub, pkey) -+ if err != nil { -+ t.Fatal(err) -+ } -+ cert, err := ParseCertificate(der) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ // Tell isBoringCertificate to enforce FIPS restrictions for this check. -+ fipstls.Force() -+ defer fipstls.Abandon() -+ -+ fipsOK := mode&boringCertFIPSOK != 0 -+ if boringAllowCert(cert) != fipsOK { -+ t.Errorf("boringAllowCert(cert with %s key) = %v, want %v", desc, !fipsOK, fipsOK) -+ } -+ return &boringCertificate{name, org, parentOrg, der, cert, key, fipsOK} -+} -diff --git a/src/crypto/x509/cert_pool.go-e b/src/crypto/x509/cert_pool.go-e -new file mode 100644 -index 0000000000..e9b2c122b9 ---- /dev/null -+++ b/src/crypto/x509/cert_pool.go-e -@@ -0,0 +1,268 @@ -+// Copyright 2011 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. -+ -+package x509 -+ -+import ( -+ "bytes" -+ "crypto/sha256" -+ "encoding/pem" -+ "sync" -+) -+ -+type sum224 [sha256.Size224]byte -+ -+// CertPool is a set of certificates. -+type CertPool struct { -+ byName map[string][]int // cert.RawSubject => index into lazyCerts -+ -+ // lazyCerts contains funcs that return a certificate, -+ // lazily parsing/decompressing it as needed. -+ lazyCerts []lazyCert -+ -+ // haveSum maps from sum224(cert.Raw) to true. It's used only -+ // for AddCert duplicate detection, to avoid CertPool.contains -+ // calls in the AddCert path (because the contains method can -+ // call getCert and otherwise negate savings from lazy getCert -+ // funcs). -+ haveSum map[sum224]bool -+ -+ // systemPool indicates whether this is a special pool derived from the -+ // system roots. If it includes additional roots, it requires doing two -+ // verifications, one using the roots provided by the caller, and one using -+ // the system platform verifier. -+ systemPool bool -+} -+ -+// lazyCert is minimal metadata about a Cert and a func to retrieve it -+// in its normal expanded *Certificate form. -+type lazyCert struct { -+ // rawSubject is the Certificate.RawSubject value. -+ // It's the same as the CertPool.byName key, but in []byte -+ // form to make CertPool.Subjects (as used by crypto/tls) do -+ // fewer allocations. -+ rawSubject []byte -+ -+ // getCert returns the certificate. -+ // -+ // It is not meant to do network operations or anything else -+ // where a failure is likely; the func is meant to lazily -+ // parse/decompress data that is already known to be good. The -+ // error in the signature primarily is meant for use in the -+ // case where a cert file existed on local disk when the program -+ // started up is deleted later before it's read. -+ getCert func() (*Certificate, error) -+} -+ -+// NewCertPool returns a new, empty CertPool. -+func NewCertPool() *CertPool { -+ return &CertPool{ -+ byName: make(map[string][]int), -+ haveSum: make(map[sum224]bool), -+ } -+} -+ -+// len returns the number of certs in the set. -+// A nil set is a valid empty set. -+func (s *CertPool) len() int { -+ if s == nil { -+ return 0 -+ } -+ return len(s.lazyCerts) -+} -+ -+// cert returns cert index n in s. -+func (s *CertPool) cert(n int) (*Certificate, error) { -+ return s.lazyCerts[n].getCert() -+} -+ -+// Clone returns a copy of s. -+func (s *CertPool) Clone() *CertPool { -+ p := &CertPool{ -+ byName: make(map[string][]int, len(s.byName)), -+ lazyCerts: make([]lazyCert, len(s.lazyCerts)), -+ haveSum: make(map[sum224]bool, len(s.haveSum)), -+ systemPool: s.systemPool, -+ } -+ for k, v := range s.byName { -+ indexes := make([]int, len(v)) -+ copy(indexes, v) -+ p.byName[k] = indexes -+ } -+ for k := range s.haveSum { -+ p.haveSum[k] = true -+ } -+ copy(p.lazyCerts, s.lazyCerts) -+ return p -+} -+ -+// SystemCertPool returns a copy of the system cert pool. -+// -+// On Unix systems other than macOS the environment variables SSL_CERT_FILE and -+// SSL_CERT_DIR can be used to override the system default locations for the SSL -+// certificate file and SSL certificate files directory, respectively. The -+// latter can be a colon-separated list. -+// -+// Any mutations to the returned pool are not written to disk and do not affect -+// any other pool returned by SystemCertPool. -+// -+// New changes in the system cert pool might not be reflected in subsequent calls. -+func SystemCertPool() (*CertPool, error) { -+ if sysRoots := systemRootsPool(); sysRoots != nil { -+ return sysRoots.Clone(), nil -+ } -+ -+ return loadSystemRoots() -+} -+ -+// findPotentialParents returns the indexes of certificates in s which might -+// have signed cert. -+func (s *CertPool) findPotentialParents(cert *Certificate) []*Certificate { -+ if s == nil { -+ return nil -+ } -+ -+ // consider all candidates where cert.Issuer matches cert.Subject. -+ // when picking possible candidates the list is built in the order -+ // of match plausibility as to save cycles in buildChains: -+ // AKID and SKID match -+ // AKID present, SKID missing / AKID missing, SKID present -+ // AKID and SKID don't match -+ var matchingKeyID, oneKeyID, mismatchKeyID []*Certificate -+ for _, c := range s.byName[string(cert.RawIssuer)] { -+ candidate, err := s.cert(c) -+ if err != nil { -+ continue -+ } -+ kidMatch := bytes.Equal(candidate.SubjectKeyId, cert.AuthorityKeyId) -+ switch { -+ case kidMatch: -+ matchingKeyID = append(matchingKeyID, candidate) -+ case (len(candidate.SubjectKeyId) == 0 && len(cert.AuthorityKeyId) > 0) || -+ (len(candidate.SubjectKeyId) > 0 && len(cert.AuthorityKeyId) == 0): -+ oneKeyID = append(oneKeyID, candidate) -+ default: -+ mismatchKeyID = append(mismatchKeyID, candidate) -+ } -+ } -+ -+ found := len(matchingKeyID) + len(oneKeyID) + len(mismatchKeyID) -+ if found == 0 { -+ return nil -+ } -+ candidates := make([]*Certificate, 0, found) -+ candidates = append(candidates, matchingKeyID...) -+ candidates = append(candidates, oneKeyID...) -+ candidates = append(candidates, mismatchKeyID...) -+ return candidates -+} -+ -+func (s *CertPool) contains(cert *Certificate) bool { -+ if s == nil { -+ return false -+ } -+ return s.haveSum[sha256.Sum224(cert.Raw)] -+} -+ -+// AddCert adds a certificate to a pool. -+func (s *CertPool) AddCert(cert *Certificate) { -+ if cert == nil { -+ panic("adding nil Certificate to CertPool") -+ } -+ s.addCertFunc(sha256.Sum224(cert.Raw), string(cert.RawSubject), func() (*Certificate, error) { -+ return cert, nil -+ }) -+} -+ -+// addCertFunc adds metadata about a certificate to a pool, along with -+// a func to fetch that certificate later when needed. -+// -+// The rawSubject is Certificate.RawSubject and must be non-empty. -+// The getCert func may be called 0 or more times. -+func (s *CertPool) addCertFunc(rawSum224 sum224, rawSubject string, getCert func() (*Certificate, error)) { -+ if getCert == nil { -+ panic("getCert can't be nil") -+ } -+ -+ // Check that the certificate isn't being added twice. -+ if s.haveSum[rawSum224] { -+ return -+ } -+ -+ s.haveSum[rawSum224] = true -+ s.lazyCerts = append(s.lazyCerts, lazyCert{ -+ rawSubject: []byte(rawSubject), -+ getCert: getCert, -+ }) -+ s.byName[rawSubject] = append(s.byName[rawSubject], len(s.lazyCerts)-1) -+} -+ -+// AppendCertsFromPEM attempts to parse a series of PEM encoded certificates. -+// It appends any certificates found to s and reports whether any certificates -+// were successfully parsed. -+// -+// On many Linux systems, /etc/ssl/cert.pem will contain the system wide set -+// of root CAs in a format suitable for this function. -+func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) { -+ for len(pemCerts) > 0 { -+ var block *pem.Block -+ block, pemCerts = pem.Decode(pemCerts) -+ if block == nil { -+ break -+ } -+ if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { -+ continue -+ } -+ -+ certBytes := block.Bytes -+ cert, err := ParseCertificate(certBytes) -+ if err != nil { -+ continue -+ } -+ var lazyCert struct { -+ sync.Once -+ v *Certificate -+ } -+ s.addCertFunc(sha256.Sum224(cert.Raw), string(cert.RawSubject), func() (*Certificate, error) { -+ lazyCert.Do(func() { -+ // This can't fail, as the same bytes already parsed above. -+ lazyCert.v, _ = ParseCertificate(certBytes) -+ certBytes = nil -+ }) -+ return lazyCert.v, nil -+ }) -+ ok = true -+ } -+ -+ return ok -+} -+ -+// Subjects returns a list of the DER-encoded subjects of -+// all of the certificates in the pool. -+// -+// Deprecated: if s was returned by SystemCertPool, Subjects -+// will not include the system roots. -+func (s *CertPool) Subjects() [][]byte { -+ res := make([][]byte, s.len()) -+ for i, lc := range s.lazyCerts { -+ res[i] = lc.rawSubject -+ } -+ return res -+} -+ -+// Equal reports whether s and other are equal. -+func (s *CertPool) Equal(other *CertPool) bool { -+ if s == nil || other == nil { -+ return s == other -+ } -+ if s.systemPool != other.systemPool || len(s.haveSum) != len(other.haveSum) { -+ return false -+ } -+ for h := range s.haveSum { -+ if !other.haveSum[h] { -+ return false -+ } -+ } -+ return true -+} -diff --git a/src/crypto/x509/cert_pool_test.go-e b/src/crypto/x509/cert_pool_test.go-e -new file mode 100644 -index 0000000000..a12beda83d ---- /dev/null -+++ b/src/crypto/x509/cert_pool_test.go-e -@@ -0,0 +1,108 @@ -+// Copyright 2022 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. -+ -+package x509 -+ -+import "testing" -+ -+func TestCertPoolEqual(t *testing.T) { -+ tc := &Certificate{Raw: []byte{1, 2, 3}, RawSubject: []byte{2}} -+ otherTC := &Certificate{Raw: []byte{9, 8, 7}, RawSubject: []byte{8}} -+ -+ emptyPool := NewCertPool() -+ nonSystemPopulated := NewCertPool() -+ nonSystemPopulated.AddCert(tc) -+ nonSystemPopulatedAlt := NewCertPool() -+ nonSystemPopulatedAlt.AddCert(otherTC) -+ emptySystem, err := SystemCertPool() -+ if err != nil { -+ t.Fatal(err) -+ } -+ populatedSystem, err := SystemCertPool() -+ if err != nil { -+ t.Fatal(err) -+ } -+ populatedSystem.AddCert(tc) -+ populatedSystemAlt, err := SystemCertPool() -+ if err != nil { -+ t.Fatal(err) -+ } -+ populatedSystemAlt.AddCert(otherTC) -+ tests := []struct { -+ name string -+ a *CertPool -+ b *CertPool -+ equal bool -+ }{ -+ { -+ name: "two empty pools", -+ a: emptyPool, -+ b: emptyPool, -+ equal: true, -+ }, -+ { -+ name: "one empty pool, one populated pool", -+ a: emptyPool, -+ b: nonSystemPopulated, -+ equal: false, -+ }, -+ { -+ name: "two populated pools", -+ a: nonSystemPopulated, -+ b: nonSystemPopulated, -+ equal: true, -+ }, -+ { -+ name: "two populated pools, different content", -+ a: nonSystemPopulated, -+ b: nonSystemPopulatedAlt, -+ equal: false, -+ }, -+ { -+ name: "two empty system pools", -+ a: emptySystem, -+ b: emptySystem, -+ equal: true, -+ }, -+ { -+ name: "one empty system pool, one populated system pool", -+ a: emptySystem, -+ b: populatedSystem, -+ equal: false, -+ }, -+ { -+ name: "two populated system pools", -+ a: populatedSystem, -+ b: populatedSystem, -+ equal: true, -+ }, -+ { -+ name: "two populated pools, different content", -+ a: populatedSystem, -+ b: populatedSystemAlt, -+ equal: false, -+ }, -+ { -+ name: "two nil pools", -+ a: nil, -+ b: nil, -+ equal: true, -+ }, -+ { -+ name: "one nil pool, one empty pool", -+ a: nil, -+ b: emptyPool, -+ equal: false, -+ }, -+ } -+ -+ for _, tc := range tests { -+ t.Run(tc.name, func(t *testing.T) { -+ equal := tc.a.Equal(tc.b) -+ if equal != tc.equal { -+ t.Errorf("Unexpected Equal result: got %t, want %t", equal, tc.equal) -+ } -+ }) -+ } -+} -diff --git a/src/crypto/x509/example_test.go-e b/src/crypto/x509/example_test.go-e -new file mode 100644 -index 0000000000..19d249af7a ---- /dev/null -+++ b/src/crypto/x509/example_test.go-e -@@ -0,0 +1,137 @@ -+// Copyright 2014 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. -+ -+package x509_test -+ -+import ( -+ "crypto/dsa" -+ "crypto/ecdsa" -+ "crypto/ed25519" -+ "crypto/rsa" -+ "crypto/x509" -+ "encoding/pem" -+ "fmt" -+) -+ -+func ExampleCertificate_Verify() { -+ // Verifying with a custom list of root certificates. -+ -+ const rootPEM = ` -+-----BEGIN CERTIFICATE----- -+MIIEBDCCAuygAwIBAgIDAjppMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT -+MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i -+YWwgQ0EwHhcNMTMwNDA1MTUxNTU1WhcNMTUwNDA0MTUxNTU1WjBJMQswCQYDVQQG -+EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy -+bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -+AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP -+VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv -+h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE -+ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ -+EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC -+DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB+zCB+DAfBgNVHSMEGDAWgBTAephojYn7 -+qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wEgYD -+VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMwMTAvoC2g -+K4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9ndGdsb2JhbC5jcmwwPQYI -+KwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwOi8vZ3RnbG9iYWwtb2NzcC5n -+ZW90cnVzdC5jb20wFwYDVR0gBBAwDjAMBgorBgEEAdZ5AgUBMA0GCSqGSIb3DQEB -+BQUAA4IBAQA21waAESetKhSbOHezI6B1WLuxfoNCunLaHtiONgaX4PCVOzf9G0JY -+/iLIa704XtE7JW4S615ndkZAkNoUyHgN7ZVm2o6Gb4ChulYylYbc3GrKBIxbf/a/ -+zG+FA1jDaFETzf3I93k9mTXwVqO94FntT0QJo544evZG0R0SnU++0ED8Vf4GXjza -+HFa9llF7b1cq26KqltyMdMKVvvBulRP/F/A8rLIQjcxz++iPAsbw+zOzlTvjwsto -+WHPbqCRiOwY1nQ2pM714A5AuTHhdUDqB1O6gyHA43LL5Z/qHQF1hwFGPa4NrzQU6 -+yuGnBXj8ytqU0CwIPX4WecigUCAkVDNx -+-----END CERTIFICATE-----` -+ -+ const certPEM = ` -+-----BEGIN CERTIFICATE----- -+MIIDujCCAqKgAwIBAgIIE31FZVaPXTUwDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE -+BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl -+cm5ldCBBdXRob3JpdHkgRzIwHhcNMTQwMTI5MTMyNzQzWhcNMTQwNTI5MDAwMDAw -+WjBpMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN -+TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEYMBYGA1UEAwwPbWFp -+bC5nb29nbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEfRrObuSW5T7q -+5CnSEqefEmtH4CCv6+5EckuriNr1CjfVvqzwfAhopXkLrq45EQm8vkmf7W96XJhC -+7ZM0dYi1/qOCAU8wggFLMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAa -+BgNVHREEEzARgg9tYWlsLmdvb2dsZS5jb20wCwYDVR0PBAQDAgeAMGgGCCsGAQUF -+BwEBBFwwWjArBggrBgEFBQcwAoYfaHR0cDovL3BraS5nb29nbGUuY29tL0dJQUcy -+LmNydDArBggrBgEFBQcwAYYfaHR0cDovL2NsaWVudHMxLmdvb2dsZS5jb20vb2Nz -+cDAdBgNVHQ4EFgQUiJxtimAuTfwb+aUtBn5UYKreKvMwDAYDVR0TAQH/BAIwADAf -+BgNVHSMEGDAWgBRK3QYWG7z2aLV29YG2u2IaulqBLzAXBgNVHSAEEDAOMAwGCisG -+AQQB1nkCBQEwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL3BraS5nb29nbGUuY29t -+L0dJQUcyLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAH6RYHxHdcGpMpFE3oxDoFnP+ -+gtuBCHan2yE2GRbJ2Cw8Lw0MmuKqHlf9RSeYfd3BXeKkj1qO6TVKwCh+0HdZk283 -+TZZyzmEOyclm3UGFYe82P/iDFt+CeQ3NpmBg+GoaVCuWAARJN/KfglbLyyYygcQq -+0SgeDh8dRKUiaW3HQSoYvTvdTuqzwK4CXsr3b5/dAOY8uMuG/IAR3FgwTbZ1dtoW -+RvOTa8hYiU6A475WuZKyEHcwnGYe57u2I2KbMgcKjPniocj4QzgYsVAVKW3IwaOh -+yE+vPxsiUkvQHdO2fojCkY8jg70jxM+gu59tPDNbw3Uh/2Ij310FgTHsnGQMyA== -+-----END CERTIFICATE-----` -+ -+ // First, create the set of root certificates. For this example we only -+ // have one. It's also possible to omit this in order to use the -+ // default root set of the current operating system. -+ roots := x509.NewCertPool() -+ ok := roots.AppendCertsFromPEM([]byte(rootPEM)) -+ if !ok { -+ panic("failed to parse root certificate") -+ } -+ -+ block, _ := pem.Decode([]byte(certPEM)) -+ if block == nil { -+ panic("failed to parse certificate PEM") -+ } -+ cert, err := x509.ParseCertificate(block.Bytes) -+ if err != nil { -+ panic("failed to parse certificate: " + err.Error()) -+ } -+ -+ opts := x509.VerifyOptions{ -+ DNSName: "mail.google.com", -+ Roots: roots, -+ } -+ -+ if _, err := cert.Verify(opts); err != nil { -+ panic("failed to verify certificate: " + err.Error()) -+ } -+} -+ -+func ExampleParsePKIXPublicKey() { -+ const pubPEM = ` -+-----BEGIN PUBLIC KEY----- -+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlRuRnThUjU8/prwYxbty -+WPT9pURI3lbsKMiB6Fn/VHOKE13p4D8xgOCADpdRagdT6n4etr9atzDKUSvpMtR3 -+CP5noNc97WiNCggBjVWhs7szEe8ugyqF23XwpHQ6uV1LKH50m92MbOWfCtjU9p/x -+qhNpQQ1AZhqNy5Gevap5k8XzRmjSldNAFZMY7Yv3Gi+nyCwGwpVtBUwhuLzgNFK/ -+yDtw2WcWmUU7NuC8Q6MWvPebxVtCfVp/iQU6q60yyt6aGOBkhAX0LpKAEhKidixY -+nP9PNVBvxgu3XZ4P36gZV6+ummKdBVnc3NqwBLu5+CcdRdusmHPHd5pHf4/38Z3/ -+6qU2a/fPvWzceVTEgZ47QjFMTCTmCwNt29cvi7zZeQzjtwQgn4ipN9NibRH/Ax/q -+TbIzHfrJ1xa2RteWSdFjwtxi9C20HUkjXSeI4YlzQMH0fPX6KCE7aVePTOnB69I/ -+a9/q96DiXZajwlpq3wFctrs1oXqBp5DVrCIj8hU2wNgB7LtQ1mCtsYz//heai0K9 -+PhE4X6hiE0YmeAZjR0uHl8M/5aW9xCoJ72+12kKpWAa0SFRWLy6FejNYCYpkupVJ -+yecLk/4L1W0l6jQQZnWErXZYe0PNFcmwGXy1Rep83kfBRNKRy5tvocalLlwXLdUk -+AIU+2GKjyT3iMuzZxxFxPFMCAwEAAQ== -+-----END PUBLIC KEY-----` -+ -+ block, _ := pem.Decode([]byte(pubPEM)) -+ if block == nil { -+ panic("failed to parse PEM block containing the public key") -+ } -+ -+ pub, err := x509.ParsePKIXPublicKey(block.Bytes) -+ if err != nil { -+ panic("failed to parse DER encoded public key: " + err.Error()) -+ } -+ -+ switch pub := pub.(type) { -+ case *rsa.PublicKey: -+ fmt.Println("pub is of type RSA:", pub) -+ case *dsa.PublicKey: -+ fmt.Println("pub is of type DSA:", pub) -+ case *ecdsa.PublicKey: -+ fmt.Println("pub is of type ECDSA:", pub) -+ case ed25519.PublicKey: -+ fmt.Println("pub is of type Ed25519:", pub) -+ default: -+ panic("unknown type of public key") -+ } -+} -diff --git a/src/crypto/x509/hybrid_pool_test.go-e b/src/crypto/x509/hybrid_pool_test.go-e -new file mode 100644 -index 0000000000..2b8eb62dd0 ---- /dev/null -+++ b/src/crypto/x509/hybrid_pool_test.go-e -@@ -0,0 +1,123 @@ -+// Copyright 2011 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. -+ -+package x509_test -+ -+import ( -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/tls" -+ "crypto/x509" -+ "crypto/x509/pkix" -+ "internal/testenv" -+ "math/big" -+ "runtime" -+ "testing" -+ "time" -+) -+ -+func TestHybridPool(t *testing.T) { -+ t.Parallel() -+ if !(runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios") { -+ t.Skipf("platform verifier not available on %s", runtime.GOOS) -+ } -+ if !testenv.HasExternalNetwork() { -+ t.Skip() -+ } -+ if runtime.GOOS == "windows" { -+ // NOTE(#51599): on the Windows builders we sometimes see that the state -+ // of the root pool is not fully initialized, causing an expected -+ // platform verification to fail. In part this is because Windows -+ // dynamically populates roots into its local trust store at time of -+ // use. We can attempt to prime the pool by attempting TLS connections -+ // to google.com until it works, suggesting the pool has been properly -+ // updated. If after we hit the dealine, the pool has _still_ not been -+ // populated with the expected root, it's unlikely we are ever going to -+ // get into a good state, and so we just fail the test. #52108 suggests -+ // a better possible long term solution. -+ -+ deadline := time.Now().Add(time.Second * 10) -+ nextSleep := 10 * time.Millisecond -+ for i := 0; ; i++ { -+ c, err := tls.Dial("tcp", "google.com:443", nil) -+ if err == nil { -+ c.Close() -+ break -+ } -+ nextSleep = nextSleep * time.Duration(i) -+ if time.Until(deadline) < nextSleep { -+ t.Fatal("windows root pool appears to be in an uninitialized state (missing root that chains to google.com)") -+ } -+ time.Sleep(nextSleep) -+ } -+ } -+ -+ // Get the google.com chain, which should be valid on all platforms we -+ // are testing -+ c, err := tls.Dial("tcp", "google.com:443", &tls.Config{InsecureSkipVerify: true}) -+ if err != nil { -+ t.Fatalf("tls connection failed: %s", err) -+ } -+ googChain := c.ConnectionState().PeerCertificates -+ -+ rootTmpl := &x509.Certificate{ -+ SerialNumber: big.NewInt(1), -+ Subject: pkix.Name{CommonName: "Go test root"}, -+ IsCA: true, -+ BasicConstraintsValid: true, -+ NotBefore: time.Now().Add(-time.Hour), -+ NotAfter: time.Now().Add(time.Hour * 10), -+ } -+ k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ t.Fatalf("failed to generate test key: %s", err) -+ } -+ rootDER, err := x509.CreateCertificate(rand.Reader, rootTmpl, rootTmpl, k.Public(), k) -+ if err != nil { -+ t.Fatalf("failed to create test cert: %s", err) -+ } -+ root, err := x509.ParseCertificate(rootDER) -+ if err != nil { -+ t.Fatalf("failed to parse test cert: %s", err) -+ } -+ -+ pool, err := x509.SystemCertPool() -+ if err != nil { -+ t.Fatalf("SystemCertPool failed: %s", err) -+ } -+ opts := x509.VerifyOptions{Roots: pool} -+ -+ _, err = googChain[0].Verify(opts) -+ if err != nil { -+ t.Fatalf("verification failed for google.com chain (system only pool): %s", err) -+ } -+ -+ pool.AddCert(root) -+ -+ _, err = googChain[0].Verify(opts) -+ if err != nil { -+ t.Fatalf("verification failed for google.com chain (hybrid pool): %s", err) -+ } -+ -+ certTmpl := &x509.Certificate{ -+ SerialNumber: big.NewInt(1), -+ NotBefore: time.Now().Add(-time.Hour), -+ NotAfter: time.Now().Add(time.Hour * 10), -+ DNSNames: []string{"example.com"}, -+ } -+ certDER, err := x509.CreateCertificate(rand.Reader, certTmpl, rootTmpl, k.Public(), k) -+ if err != nil { -+ t.Fatalf("failed to create test cert: %s", err) -+ } -+ cert, err := x509.ParseCertificate(certDER) -+ if err != nil { -+ t.Fatalf("failed to parse test cert: %s", err) -+ } -+ -+ _, err = cert.Verify(opts) -+ if err != nil { -+ t.Fatalf("verification failed for custom chain (hybrid pool): %s", err) -+ } -+} -diff --git a/src/crypto/x509/name_constraints_test.go-e b/src/crypto/x509/name_constraints_test.go-e -new file mode 100644 -index 0000000000..4c22c4cd8e ---- /dev/null -+++ b/src/crypto/x509/name_constraints_test.go-e -@@ -0,0 +1,2171 @@ -+// 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. -+ -+package x509 -+ -+import ( -+ "bytes" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+ "encoding/hex" -+ "encoding/pem" -+ "fmt" -+ "math/big" -+ "net" -+ "net/url" -+ "os" -+ "os/exec" -+ "strconv" -+ "strings" -+ "sync" -+ "testing" -+ "time" -+) -+ -+const ( -+ // testNameConstraintsAgainstOpenSSL can be set to true to run tests -+ // against the system OpenSSL. This is disabled by default because Go -+ // cannot depend on having OpenSSL installed at testing time. -+ testNameConstraintsAgainstOpenSSL = false -+ -+ // debugOpenSSLFailure can be set to true, when -+ // testNameConstraintsAgainstOpenSSL is also true, to cause -+ // intermediate files to be preserved for debugging. -+ debugOpenSSLFailure = false -+) -+ -+type nameConstraintsTest struct { -+ roots []constraintsSpec -+ intermediates [][]constraintsSpec -+ leaf leafSpec -+ requestedEKUs []ExtKeyUsage -+ expectedError string -+ noOpenSSL bool -+ ignoreCN bool -+} -+ -+type constraintsSpec struct { -+ ok []string -+ bad []string -+ ekus []string -+} -+ -+type leafSpec struct { -+ sans []string -+ ekus []string -+ cn string -+} -+ -+var nameConstraintsTests = []nameConstraintsTest{ -+ // #0: dummy test for the certificate generation process itself. -+ { -+ roots: make([]constraintsSpec, 1), -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ }, -+ }, -+ -+ // #1: dummy test for the certificate generation process itself: single -+ // level of intermediate. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ }, -+ }, -+ -+ // #2: dummy test for the certificate generation process itself: two -+ // levels of intermediates. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ }, -+ }, -+ -+ // #3: matching DNS constraint in root -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ }, -+ }, -+ -+ // #4: matching DNS constraint in intermediate. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ok: []string{"dns:example.com"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ }, -+ }, -+ -+ // #5: .example.com only matches subdomains. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:.example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ }, -+ expectedError: "\"example.com\" is not permitted", -+ }, -+ -+ // #6: .example.com matches subdomains. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ok: []string{"dns:.example.com"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:foo.example.com"}, -+ }, -+ }, -+ -+ // #7: .example.com matches multiple levels of subdomains -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:.example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:foo.bar.example.com"}, -+ }, -+ }, -+ -+ // #8: specifying a permitted list of names does not exclude other name -+ // types -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:.example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"ip:10.1.1.1"}, -+ }, -+ }, -+ -+ // #9: specifying a permitted list of names does not exclude other name -+ // types -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"ip:10.0.0.0/8"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ }, -+ }, -+ -+ // #10: intermediates can try to permit other names, which isn't -+ // forbidden if the leaf doesn't mention them. I.e. name constraints -+ // apply to names, not constraints themselves. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ok: []string{"dns:example.com", "dns:foo.com"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ }, -+ }, -+ -+ // #11: intermediates cannot add permitted names that the root doesn't -+ // grant them. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ok: []string{"dns:example.com", "dns:foo.com"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:foo.com"}, -+ }, -+ expectedError: "\"foo.com\" is not permitted", -+ }, -+ -+ // #12: intermediates can further limit their scope if they wish. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:.example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ok: []string{"dns:.bar.example.com"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:foo.bar.example.com"}, -+ }, -+ }, -+ -+ // #13: intermediates can further limit their scope and that limitation -+ // is effective -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:.example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ok: []string{"dns:.bar.example.com"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:foo.notbar.example.com"}, -+ }, -+ expectedError: "\"foo.notbar.example.com\" is not permitted", -+ }, -+ -+ // #14: roots can exclude subtrees and that doesn't affect other names. -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"dns:.example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:foo.com"}, -+ }, -+ }, -+ -+ // #15: roots exclusions are effective. -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"dns:.example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:foo.example.com"}, -+ }, -+ expectedError: "\"foo.example.com\" is excluded", -+ }, -+ -+ // #16: intermediates can also exclude names and that doesn't affect -+ // other names. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ bad: []string{"dns:.example.com"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:foo.com"}, -+ }, -+ }, -+ -+ // #17: intermediate exclusions are effective. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ bad: []string{"dns:.example.com"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:foo.example.com"}, -+ }, -+ expectedError: "\"foo.example.com\" is excluded", -+ }, -+ -+ // #18: having an exclusion doesn't prohibit other types of names. -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"dns:.example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:foo.com", "ip:10.1.1.1"}, -+ }, -+ }, -+ -+ // #19: IP-based exclusions are permitted and don't affect unrelated IP -+ // addresses. -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"ip:10.0.0.0/8"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"ip:192.168.1.1"}, -+ }, -+ }, -+ -+ // #20: IP-based exclusions are effective -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"ip:10.0.0.0/8"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"ip:10.0.0.1"}, -+ }, -+ expectedError: "\"10.0.0.1\" is excluded", -+ }, -+ -+ // #21: intermediates can further constrain IP ranges. -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"ip:0.0.0.0/1"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ bad: []string{"ip:11.0.0.0/8"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"ip:11.0.0.1"}, -+ }, -+ expectedError: "\"11.0.0.1\" is excluded", -+ }, -+ -+ // #22: when multiple intermediates are present, chain building can -+ // avoid intermediates with incompatible constraints. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ok: []string{"dns:.foo.com"}, -+ }, -+ { -+ ok: []string{"dns:.example.com"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:foo.example.com"}, -+ }, -+ noOpenSSL: true, // OpenSSL's chain building is not informed by constraints. -+ }, -+ -+ // #23: (same as the previous test, but in the other order in ensure -+ // that we don't pass it by luck.) -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ok: []string{"dns:.example.com"}, -+ }, -+ { -+ ok: []string{"dns:.foo.com"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:foo.example.com"}, -+ }, -+ noOpenSSL: true, // OpenSSL's chain building is not informed by constraints. -+ }, -+ -+ // #24: when multiple roots are valid, chain building can avoid roots -+ // with incompatible constraints. -+ { -+ roots: []constraintsSpec{ -+ {}, -+ { -+ ok: []string{"dns:foo.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ }, -+ noOpenSSL: true, // OpenSSL's chain building is not informed by constraints. -+ }, -+ -+ // #25: (same as the previous test, but in the other order in ensure -+ // that we don't pass it by luck.) -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:foo.com"}, -+ }, -+ {}, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ }, -+ noOpenSSL: true, // OpenSSL's chain building is not informed by constraints. -+ }, -+ -+ // #26: chain building can find a valid path even with multiple levels -+ // of alternative intermediates and alternative roots. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:foo.com"}, -+ }, -+ { -+ ok: []string{"dns:example.com"}, -+ }, -+ {}, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ { -+ ok: []string{"dns:foo.com"}, -+ }, -+ }, -+ { -+ {}, -+ { -+ ok: []string{"dns:foo.com"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:bar.com"}, -+ }, -+ noOpenSSL: true, // OpenSSL's chain building is not informed by constraints. -+ }, -+ -+ // #27: chain building doesn't get stuck when there is no valid path. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:foo.com"}, -+ }, -+ { -+ ok: []string{"dns:example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ { -+ ok: []string{"dns:foo.com"}, -+ }, -+ }, -+ { -+ { -+ ok: []string{"dns:bar.com"}, -+ }, -+ { -+ ok: []string{"dns:foo.com"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:bar.com"}, -+ }, -+ expectedError: "\"bar.com\" is not permitted", -+ }, -+ -+ // #28: unknown name types don't cause a problem without constraints. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"unknown:"}, -+ }, -+ }, -+ -+ // #29: unknown name types are allowed even in constrained chains. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:foo.com", "dns:.foo.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"unknown:"}, -+ }, -+ }, -+ -+ // #30: without SANs, a certificate with a CN is still accepted in a -+ // constrained chain, since we ignore the CN in VerifyHostname. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:foo.com", "dns:.foo.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{}, -+ cn: "foo.com", -+ }, -+ }, -+ -+ // #31: IPv6 addresses work in constraints: roots can permit them as -+ // expected. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"ip:2000:abcd::/32"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"ip:2000:abcd:1234::"}, -+ }, -+ }, -+ -+ // #32: IPv6 addresses work in constraints: root restrictions are -+ // effective. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"ip:2000:abcd::/32"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"ip:2000:1234:abcd::"}, -+ }, -+ expectedError: "\"2000:1234:abcd::\" is not permitted", -+ }, -+ -+ // #33: An IPv6 permitted subtree doesn't affect DNS names. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"ip:2000:abcd::/32"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"ip:2000:abcd::", "dns:foo.com"}, -+ }, -+ }, -+ -+ // #34: IPv6 exclusions don't affect unrelated addresses. -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"ip:2000:abcd::/32"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"ip:2000:1234::"}, -+ }, -+ }, -+ -+ // #35: IPv6 exclusions are effective. -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"ip:2000:abcd::/32"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"ip:2000:abcd::"}, -+ }, -+ expectedError: "\"2000:abcd::\" is excluded", -+ }, -+ -+ // #36: IPv6 constraints do not permit IPv4 addresses. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"ip:2000:abcd::/32"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"ip:10.0.0.1"}, -+ }, -+ expectedError: "\"10.0.0.1\" is not permitted", -+ }, -+ -+ // #37: IPv4 constraints do not permit IPv6 addresses. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"ip:10.0.0.0/8"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"ip:2000:abcd::"}, -+ }, -+ expectedError: "\"2000:abcd::\" is not permitted", -+ }, -+ -+ // #38: an exclusion of an unknown type doesn't affect other names. -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"unknown:"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ }, -+ }, -+ -+ // #39: a permitted subtree of an unknown type doesn't affect other -+ // name types. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"unknown:"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ }, -+ }, -+ -+ // #40: exact email constraints work -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"email:foo@example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"email:foo@example.com"}, -+ }, -+ }, -+ -+ // #41: exact email constraints are effective -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"email:foo@example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"email:bar@example.com"}, -+ }, -+ expectedError: "\"bar@example.com\" is not permitted", -+ }, -+ -+ // #42: email canonicalisation works. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"email:foo@example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"email:\"\\f\\o\\o\"@example.com"}, -+ }, -+ noOpenSSL: true, // OpenSSL doesn't canonicalise email addresses before matching -+ }, -+ -+ // #43: limiting email addresses to a host works. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"email:example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"email:foo@example.com"}, -+ }, -+ }, -+ -+ // #44: a leading dot matches hosts one level deep -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"email:.example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"email:foo@sub.example.com"}, -+ }, -+ }, -+ -+ // #45: a leading dot does not match the host itself -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"email:.example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"email:foo@example.com"}, -+ }, -+ expectedError: "\"foo@example.com\" is not permitted", -+ }, -+ -+ // #46: a leading dot also matches two (or more) levels deep. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"email:.example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"email:foo@sub.sub.example.com"}, -+ }, -+ }, -+ -+ // #47: the local part of an email is case-sensitive -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"email:foo@example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"email:Foo@example.com"}, -+ }, -+ expectedError: "\"Foo@example.com\" is not permitted", -+ }, -+ -+ // #48: the domain part of an email is not case-sensitive -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"email:foo@EXAMPLE.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"email:foo@example.com"}, -+ }, -+ }, -+ -+ // #49: the domain part of a DNS constraint is also not case-sensitive. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:EXAMPLE.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ }, -+ }, -+ -+ // #50: URI constraints only cover the host part of the URI -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"uri:example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{ -+ "uri:http://example.com/bar", -+ "uri:http://example.com:8080/", -+ "uri:https://example.com/wibble#bar", -+ }, -+ }, -+ }, -+ -+ // #51: URIs with IPs are rejected -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"uri:example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"uri:http://1.2.3.4/"}, -+ }, -+ expectedError: "URI with IP", -+ }, -+ -+ // #52: URIs with IPs and ports are rejected -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"uri:example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"uri:http://1.2.3.4:43/"}, -+ }, -+ expectedError: "URI with IP", -+ }, -+ -+ // #53: URIs with IPv6 addresses are also rejected -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"uri:example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"uri:http://[2006:abcd::1]/"}, -+ }, -+ expectedError: "URI with IP", -+ }, -+ -+ // #54: URIs with IPv6 addresses with ports are also rejected -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"uri:example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"uri:http://[2006:abcd::1]:16/"}, -+ }, -+ expectedError: "URI with IP", -+ }, -+ -+ // #55: URI constraints are effective -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"uri:example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"uri:http://bar.com/"}, -+ }, -+ expectedError: "\"http://bar.com/\" is not permitted", -+ }, -+ -+ // #56: URI constraints are effective -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"uri:foo.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"uri:http://foo.com/"}, -+ }, -+ expectedError: "\"http://foo.com/\" is excluded", -+ }, -+ -+ // #57: URI constraints can allow subdomains -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"uri:.foo.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"uri:http://www.foo.com/"}, -+ }, -+ }, -+ -+ // #58: excluding an IPv4-mapped-IPv6 address doesn't affect the IPv4 -+ // version of that address. -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"ip:::ffff:1.2.3.4/128"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"ip:1.2.3.4"}, -+ }, -+ }, -+ -+ // #59: a URI constraint isn't matched by a URN. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"uri:example.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"uri:urn:example"}, -+ }, -+ expectedError: "URI with empty host", -+ }, -+ -+ // #60: excluding all IPv6 addresses doesn't exclude all IPv4 addresses -+ // too, even though IPv4 is mapped into the IPv6 range. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"ip:1.2.3.0/24"}, -+ bad: []string{"ip:::0/0"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"ip:1.2.3.4"}, -+ }, -+ }, -+ -+ // #61: omitting extended key usage in a CA certificate implies that -+ // any usage is ok. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ ekus: []string{"serverAuth", "other"}, -+ }, -+ }, -+ -+ // #62: The “any” EKU also means that any usage is ok. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ekus: []string{"any"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ ekus: []string{"serverAuth", "other"}, -+ }, -+ }, -+ -+ // #63: An intermediate with enumerated EKUs causes a failure if we -+ // test for an EKU not in that set. (ServerAuth is required by -+ // default.) -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ekus: []string{"email"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ ekus: []string{"serverAuth"}, -+ }, -+ expectedError: "incompatible key usage", -+ }, -+ -+ // #64: an unknown EKU in the leaf doesn't break anything, even if it's not -+ // correctly nested. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ekus: []string{"email"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ ekus: []string{"other"}, -+ }, -+ requestedEKUs: []ExtKeyUsage{ExtKeyUsageAny}, -+ }, -+ -+ // #65: trying to add extra permitted key usages in an intermediate -+ // (after a limitation in the root) is acceptable so long as the leaf -+ // certificate doesn't use them. -+ { -+ roots: []constraintsSpec{ -+ { -+ ekus: []string{"serverAuth"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ekus: []string{"serverAuth", "email"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ ekus: []string{"serverAuth"}, -+ }, -+ }, -+ -+ // #66: EKUs in roots are not ignored. -+ { -+ roots: []constraintsSpec{ -+ { -+ ekus: []string{"email"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ekus: []string{"serverAuth"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ ekus: []string{"serverAuth"}, -+ }, -+ expectedError: "incompatible key usage", -+ }, -+ -+ // #67: SGC key usages used to permit serverAuth and clientAuth, -+ // but don't anymore. -+ { -+ roots: []constraintsSpec{ -+ {}, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ekus: []string{"netscapeSGC"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ ekus: []string{"serverAuth", "clientAuth"}, -+ }, -+ expectedError: "incompatible key usage", -+ }, -+ -+ // #68: SGC key usages used to permit serverAuth and clientAuth, -+ // but don't anymore. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ekus: []string{"msSGC"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ ekus: []string{"serverAuth", "clientAuth"}, -+ }, -+ expectedError: "incompatible key usage", -+ }, -+ -+ // #69: an empty DNS constraint should allow anything. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ }, -+ }, -+ -+ // #70: an empty DNS constraint should also reject everything. -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"dns:"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ }, -+ expectedError: "\"example.com\" is excluded", -+ }, -+ -+ // #71: an empty email constraint should allow anything -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"email:"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"email:foo@example.com"}, -+ }, -+ }, -+ -+ // #72: an empty email constraint should also reject everything. -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"email:"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"email:foo@example.com"}, -+ }, -+ expectedError: "\"foo@example.com\" is excluded", -+ }, -+ -+ // #73: an empty URI constraint should allow anything -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"uri:"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"uri:https://example.com/test"}, -+ }, -+ }, -+ -+ // #74: an empty URI constraint should also reject everything. -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"uri:"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"uri:https://example.com/test"}, -+ }, -+ expectedError: "\"https://example.com/test\" is excluded", -+ }, -+ -+ // #75: serverAuth in a leaf shouldn't permit clientAuth when requested in -+ // VerifyOptions. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ ekus: []string{"serverAuth"}, -+ }, -+ requestedEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth}, -+ expectedError: "incompatible key usage", -+ }, -+ -+ // #76: MSSGC in a leaf used to match a request for serverAuth, but doesn't -+ // anymore. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ ekus: []string{"msSGC"}, -+ }, -+ requestedEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ expectedError: "incompatible key usage", -+ }, -+ -+ // An invalid DNS SAN should be detected only at validation time so -+ // that we can process CA certificates in the wild that have invalid SANs. -+ // See https://github.com/golang/go/issues/23995 -+ -+ // #77: an invalid DNS or mail SAN will not be detected if name constraint -+ // checking is not triggered. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:this is invalid", "email:this @ is invalid"}, -+ }, -+ }, -+ -+ // #78: an invalid DNS SAN will be detected if any name constraint checking -+ // is triggered. -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"uri:"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:this is invalid"}, -+ }, -+ expectedError: "cannot parse dnsName", -+ }, -+ -+ // #79: an invalid email SAN will be detected if any name constraint -+ // checking is triggered. -+ { -+ roots: []constraintsSpec{ -+ { -+ bad: []string{"uri:"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"email:this @ is invalid"}, -+ }, -+ expectedError: "cannot parse rfc822Name", -+ }, -+ -+ // #80: if several EKUs are requested, satisfying any of them is sufficient. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ ekus: []string{"email"}, -+ }, -+ requestedEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageEmailProtection}, -+ }, -+ -+ // #81: EKUs that are not asserted in VerifyOpts are not required to be -+ // nested. -+ { -+ roots: make([]constraintsSpec, 1), -+ intermediates: [][]constraintsSpec{ -+ { -+ { -+ ekus: []string{"serverAuth"}, -+ }, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:example.com"}, -+ // There's no email EKU in the intermediate. This would be rejected if -+ // full nesting was required. -+ ekus: []string{"email", "serverAuth"}, -+ }, -+ }, -+ -+ // #82: a certificate without SANs and CN is accepted in a constrained chain. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:foo.com", "dns:.foo.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{}, -+ }, -+ }, -+ -+ // #83: a certificate without SANs and with a CN that does not parse as a -+ // hostname is accepted in a constrained chain. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:foo.com", "dns:.foo.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{}, -+ cn: "foo,bar", -+ }, -+ }, -+ -+ // #84: a certificate with SANs and CN is accepted in a constrained chain. -+ { -+ roots: []constraintsSpec{ -+ { -+ ok: []string{"dns:foo.com", "dns:.foo.com"}, -+ }, -+ }, -+ intermediates: [][]constraintsSpec{ -+ { -+ {}, -+ }, -+ }, -+ leaf: leafSpec{ -+ sans: []string{"dns:foo.com"}, -+ cn: "foo.bar", -+ }, -+ }, -+} -+ -+func makeConstraintsCACert(constraints constraintsSpec, name string, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) { -+ var serialBytes [16]byte -+ rand.Read(serialBytes[:]) -+ -+ template := &Certificate{ -+ SerialNumber: new(big.Int).SetBytes(serialBytes[:]), -+ Subject: pkix.Name{ -+ CommonName: name, -+ }, -+ NotBefore: time.Unix(1000, 0), -+ NotAfter: time.Unix(2000, 0), -+ KeyUsage: KeyUsageCertSign, -+ BasicConstraintsValid: true, -+ IsCA: true, -+ } -+ -+ if err := addConstraintsToTemplate(constraints, template); err != nil { -+ return nil, err -+ } -+ -+ if parent == nil { -+ parent = template -+ } -+ derBytes, err := CreateCertificate(rand.Reader, template, parent, &key.PublicKey, parentKey) -+ if err != nil { -+ return nil, err -+ } -+ -+ caCert, err := ParseCertificate(derBytes) -+ if err != nil { -+ return nil, err -+ } -+ -+ return caCert, nil -+} -+ -+func makeConstraintsLeafCert(leaf leafSpec, key *ecdsa.PrivateKey, parent *Certificate, parentKey *ecdsa.PrivateKey) (*Certificate, error) { -+ var serialBytes [16]byte -+ rand.Read(serialBytes[:]) -+ -+ template := &Certificate{ -+ SerialNumber: new(big.Int).SetBytes(serialBytes[:]), -+ Subject: pkix.Name{ -+ OrganizationalUnit: []string{"Leaf"}, -+ CommonName: leaf.cn, -+ }, -+ NotBefore: time.Unix(1000, 0), -+ NotAfter: time.Unix(2000, 0), -+ KeyUsage: KeyUsageDigitalSignature, -+ BasicConstraintsValid: true, -+ IsCA: false, -+ } -+ -+ for _, name := range leaf.sans { -+ switch { -+ case strings.HasPrefix(name, "dns:"): -+ template.DNSNames = append(template.DNSNames, name[4:]) -+ -+ case strings.HasPrefix(name, "ip:"): -+ ip := net.ParseIP(name[3:]) -+ if ip == nil { -+ return nil, fmt.Errorf("cannot parse IP %q", name[3:]) -+ } -+ template.IPAddresses = append(template.IPAddresses, ip) -+ -+ case strings.HasPrefix(name, "invalidip:"): -+ ipBytes, err := hex.DecodeString(name[10:]) -+ if err != nil { -+ return nil, fmt.Errorf("cannot parse invalid IP: %s", err) -+ } -+ template.IPAddresses = append(template.IPAddresses, net.IP(ipBytes)) -+ -+ case strings.HasPrefix(name, "email:"): -+ template.EmailAddresses = append(template.EmailAddresses, name[6:]) -+ -+ case strings.HasPrefix(name, "uri:"): -+ uri, err := url.Parse(name[4:]) -+ if err != nil { -+ return nil, fmt.Errorf("cannot parse URI %q: %s", name[4:], err) -+ } -+ template.URIs = append(template.URIs, uri) -+ -+ case strings.HasPrefix(name, "unknown:"): -+ // This is a special case for testing unknown -+ // name types. A custom SAN extension is -+ // injected into the certificate. -+ if len(leaf.sans) != 1 { -+ panic("when using unknown name types, it must be the sole name") -+ } -+ -+ template.ExtraExtensions = append(template.ExtraExtensions, pkix.Extension{ -+ Id: []int{2, 5, 29, 17}, -+ Value: []byte{ -+ 0x30, // SEQUENCE -+ 3, // three bytes -+ 9, // undefined GeneralName type 9 -+ 1, -+ 1, -+ }, -+ }) -+ -+ default: -+ return nil, fmt.Errorf("unknown name type %q", name) -+ } -+ } -+ -+ var err error -+ if template.ExtKeyUsage, template.UnknownExtKeyUsage, err = parseEKUs(leaf.ekus); err != nil { -+ return nil, err -+ } -+ -+ if parent == nil { -+ parent = template -+ } -+ -+ derBytes, err := CreateCertificate(rand.Reader, template, parent, &key.PublicKey, parentKey) -+ if err != nil { -+ return nil, err -+ } -+ -+ return ParseCertificate(derBytes) -+} -+ -+func customConstraintsExtension(typeNum int, constraint []byte, isExcluded bool) pkix.Extension { -+ appendConstraint := func(contents []byte, tag uint8) []byte { -+ contents = append(contents, tag|32 /* constructed */ |0x80 /* context-specific */) -+ contents = append(contents, byte(4+len(constraint)) /* length */) -+ contents = append(contents, 0x30 /* SEQUENCE */) -+ contents = append(contents, byte(2+len(constraint)) /* length */) -+ contents = append(contents, byte(typeNum) /* GeneralName type */) -+ contents = append(contents, byte(len(constraint))) -+ return append(contents, constraint...) -+ } -+ -+ var contents []byte -+ if !isExcluded { -+ contents = appendConstraint(contents, 0 /* tag 0 for permitted */) -+ } else { -+ contents = appendConstraint(contents, 1 /* tag 1 for excluded */) -+ } -+ -+ var value []byte -+ value = append(value, 0x30 /* SEQUENCE */) -+ value = append(value, byte(len(contents))) -+ value = append(value, contents...) -+ -+ return pkix.Extension{ -+ Id: []int{2, 5, 29, 30}, -+ Value: value, -+ } -+} -+ -+func addConstraintsToTemplate(constraints constraintsSpec, template *Certificate) error { -+ parse := func(constraints []string) (dnsNames []string, ips []*net.IPNet, emailAddrs []string, uriDomains []string, err error) { -+ for _, constraint := range constraints { -+ switch { -+ case strings.HasPrefix(constraint, "dns:"): -+ dnsNames = append(dnsNames, constraint[4:]) -+ -+ case strings.HasPrefix(constraint, "ip:"): -+ _, ipNet, err := net.ParseCIDR(constraint[3:]) -+ if err != nil { -+ return nil, nil, nil, nil, err -+ } -+ ips = append(ips, ipNet) -+ -+ case strings.HasPrefix(constraint, "email:"): -+ emailAddrs = append(emailAddrs, constraint[6:]) -+ -+ case strings.HasPrefix(constraint, "uri:"): -+ uriDomains = append(uriDomains, constraint[4:]) -+ -+ default: -+ return nil, nil, nil, nil, fmt.Errorf("unknown constraint %q", constraint) -+ } -+ } -+ -+ return dnsNames, ips, emailAddrs, uriDomains, err -+ } -+ -+ handleSpecialConstraint := func(constraint string, isExcluded bool) bool { -+ switch { -+ case constraint == "unknown:": -+ template.ExtraExtensions = append(template.ExtraExtensions, customConstraintsExtension(9 /* undefined GeneralName type */, []byte{1}, isExcluded)) -+ -+ default: -+ return false -+ } -+ -+ return true -+ } -+ -+ if len(constraints.ok) == 1 && len(constraints.bad) == 0 { -+ if handleSpecialConstraint(constraints.ok[0], false) { -+ return nil -+ } -+ } -+ -+ if len(constraints.bad) == 1 && len(constraints.ok) == 0 { -+ if handleSpecialConstraint(constraints.bad[0], true) { -+ return nil -+ } -+ } -+ -+ var err error -+ template.PermittedDNSDomains, template.PermittedIPRanges, template.PermittedEmailAddresses, template.PermittedURIDomains, err = parse(constraints.ok) -+ if err != nil { -+ return err -+ } -+ -+ template.ExcludedDNSDomains, template.ExcludedIPRanges, template.ExcludedEmailAddresses, template.ExcludedURIDomains, err = parse(constraints.bad) -+ if err != nil { -+ return err -+ } -+ -+ if template.ExtKeyUsage, template.UnknownExtKeyUsage, err = parseEKUs(constraints.ekus); err != nil { -+ return err -+ } -+ -+ return nil -+} -+ -+func parseEKUs(ekuStrs []string) (ekus []ExtKeyUsage, unknowns []asn1.ObjectIdentifier, err error) { -+ for _, s := range ekuStrs { -+ switch s { -+ case "serverAuth": -+ ekus = append(ekus, ExtKeyUsageServerAuth) -+ case "clientAuth": -+ ekus = append(ekus, ExtKeyUsageClientAuth) -+ case "email": -+ ekus = append(ekus, ExtKeyUsageEmailProtection) -+ case "netscapeSGC": -+ ekus = append(ekus, ExtKeyUsageNetscapeServerGatedCrypto) -+ case "msSGC": -+ ekus = append(ekus, ExtKeyUsageMicrosoftServerGatedCrypto) -+ case "any": -+ ekus = append(ekus, ExtKeyUsageAny) -+ case "other": -+ unknowns = append(unknowns, asn1.ObjectIdentifier{2, 4, 1, 2, 3}) -+ default: -+ return nil, nil, fmt.Errorf("unknown EKU %q", s) -+ } -+ } -+ -+ return -+} -+ -+func TestConstraintCases(t *testing.T) { -+ privateKeys := sync.Pool{ -+ New: func() any { -+ priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ panic(err) -+ } -+ return priv -+ }, -+ } -+ -+ for i, test := range nameConstraintsTests { -+ t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) { -+ rootPool := NewCertPool() -+ rootKey := privateKeys.Get().(*ecdsa.PrivateKey) -+ rootName := "Root " + strconv.Itoa(i) -+ -+ // keys keeps track of all the private keys used in a given -+ // test and puts them back in the privateKeys pool at the end. -+ keys := []*ecdsa.PrivateKey{rootKey} -+ -+ // At each level (root, intermediate(s), leaf), parent points to -+ // an example parent certificate and parentKey the key for the -+ // parent level. Since all certificates at a given level have -+ // the same name and public key, any parent certificate is -+ // sufficient to get the correct issuer name and authority -+ // key ID. -+ var parent *Certificate -+ parentKey := rootKey -+ -+ for _, root := range test.roots { -+ rootCert, err := makeConstraintsCACert(root, rootName, rootKey, nil, rootKey) -+ if err != nil { -+ t.Fatalf("failed to create root: %s", err) -+ } -+ -+ parent = rootCert -+ rootPool.AddCert(rootCert) -+ } -+ -+ intermediatePool := NewCertPool() -+ -+ for level, intermediates := range test.intermediates { -+ levelKey := privateKeys.Get().(*ecdsa.PrivateKey) -+ keys = append(keys, levelKey) -+ levelName := "Intermediate level " + strconv.Itoa(level) -+ var last *Certificate -+ -+ for _, intermediate := range intermediates { -+ caCert, err := makeConstraintsCACert(intermediate, levelName, levelKey, parent, parentKey) -+ if err != nil { -+ t.Fatalf("failed to create %q: %s", levelName, err) -+ } -+ -+ last = caCert -+ intermediatePool.AddCert(caCert) -+ } -+ -+ parent = last -+ parentKey = levelKey -+ } -+ -+ leafKey := privateKeys.Get().(*ecdsa.PrivateKey) -+ keys = append(keys, leafKey) -+ -+ leafCert, err := makeConstraintsLeafCert(test.leaf, leafKey, parent, parentKey) -+ if err != nil { -+ t.Fatalf("cannot create leaf: %s", err) -+ } -+ -+ // Skip tests with CommonName set because OpenSSL will try to match it -+ // against name constraints, while we ignore it when it's not hostname-looking. -+ if !test.noOpenSSL && testNameConstraintsAgainstOpenSSL && test.leaf.cn == "" { -+ output, err := testChainAgainstOpenSSL(t, leafCert, intermediatePool, rootPool) -+ if err == nil && len(test.expectedError) > 0 { -+ t.Error("unexpectedly succeeded against OpenSSL") -+ if debugOpenSSLFailure { -+ return -+ } -+ } -+ -+ if err != nil { -+ if _, ok := err.(*exec.ExitError); !ok { -+ t.Errorf("OpenSSL failed to run: %s", err) -+ } else if len(test.expectedError) == 0 { -+ t.Errorf("OpenSSL unexpectedly failed: %v", output) -+ if debugOpenSSLFailure { -+ return -+ } -+ } -+ } -+ } -+ -+ verifyOpts := VerifyOptions{ -+ Roots: rootPool, -+ Intermediates: intermediatePool, -+ CurrentTime: time.Unix(1500, 0), -+ KeyUsages: test.requestedEKUs, -+ } -+ _, err = leafCert.Verify(verifyOpts) -+ -+ logInfo := true -+ if len(test.expectedError) == 0 { -+ if err != nil { -+ t.Errorf("unexpected failure: %s", err) -+ } else { -+ logInfo = false -+ } -+ } else { -+ if err == nil { -+ t.Error("unexpected success") -+ } else if !strings.Contains(err.Error(), test.expectedError) { -+ t.Errorf("expected error containing %q, but got: %s", test.expectedError, err) -+ } else { -+ logInfo = false -+ } -+ } -+ -+ if logInfo { -+ certAsPEM := func(cert *Certificate) string { -+ var buf bytes.Buffer -+ pem.Encode(&buf, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}) -+ return buf.String() -+ } -+ t.Errorf("root:\n%s", certAsPEM(rootPool.mustCert(t, 0))) -+ if intermediates := allCerts(t, intermediatePool); len(intermediates) > 0 { -+ for ii, intermediate := range intermediates { -+ t.Errorf("intermediate %d:\n%s", ii, certAsPEM(intermediate)) -+ } -+ } -+ t.Errorf("leaf:\n%s", certAsPEM(leafCert)) -+ } -+ -+ for _, key := range keys { -+ privateKeys.Put(key) -+ } -+ }) -+ } -+} -+ -+func writePEMsToTempFile(certs []*Certificate) *os.File { -+ file, err := os.CreateTemp("", "name_constraints_test") -+ if err != nil { -+ panic("cannot create tempfile") -+ } -+ -+ pemBlock := &pem.Block{Type: "CERTIFICATE"} -+ for _, cert := range certs { -+ pemBlock.Bytes = cert.Raw -+ pem.Encode(file, pemBlock) -+ } -+ -+ return file -+} -+ -+func testChainAgainstOpenSSL(t *testing.T, leaf *Certificate, intermediates, roots *CertPool) (string, error) { -+ args := []string{"verify", "-no_check_time"} -+ -+ rootsFile := writePEMsToTempFile(allCerts(t, roots)) -+ if debugOpenSSLFailure { -+ println("roots file:", rootsFile.Name()) -+ } else { -+ defer os.Remove(rootsFile.Name()) -+ } -+ args = append(args, "-CAfile", rootsFile.Name()) -+ -+ if intermediates.len() > 0 { -+ intermediatesFile := writePEMsToTempFile(allCerts(t, intermediates)) -+ if debugOpenSSLFailure { -+ println("intermediates file:", intermediatesFile.Name()) -+ } else { -+ defer os.Remove(intermediatesFile.Name()) -+ } -+ args = append(args, "-untrusted", intermediatesFile.Name()) -+ } -+ -+ leafFile := writePEMsToTempFile([]*Certificate{leaf}) -+ if debugOpenSSLFailure { -+ println("leaf file:", leafFile.Name()) -+ } else { -+ defer os.Remove(leafFile.Name()) -+ } -+ args = append(args, leafFile.Name()) -+ -+ var output bytes.Buffer -+ cmd := exec.Command("openssl", args...) -+ cmd.Stdout = &output -+ cmd.Stderr = &output -+ -+ err := cmd.Run() -+ return output.String(), err -+} -+ -+var rfc2821Tests = []struct { -+ in string -+ localPart, domain string -+}{ -+ {"foo@example.com", "foo", "example.com"}, -+ {"@example.com", "", ""}, -+ {"\"@example.com", "", ""}, -+ {"\"\"@example.com", "", "example.com"}, -+ {"\"a\"@example.com", "a", "example.com"}, -+ {"\"\\a\"@example.com", "a", "example.com"}, -+ {"a\"@example.com", "", ""}, -+ {"foo..bar@example.com", "", ""}, -+ {".foo.bar@example.com", "", ""}, -+ {"foo.bar.@example.com", "", ""}, -+ {"|{}?'@example.com", "|{}?'", "example.com"}, -+ -+ // Examples from RFC 3696 -+ {"Abc\\@def@example.com", "Abc@def", "example.com"}, -+ {"Fred\\ Bloggs@example.com", "Fred Bloggs", "example.com"}, -+ {"Joe.\\\\Blow@example.com", "Joe.\\Blow", "example.com"}, -+ {"\"Abc@def\"@example.com", "Abc@def", "example.com"}, -+ {"\"Fred Bloggs\"@example.com", "Fred Bloggs", "example.com"}, -+ {"customer/department=shipping@example.com", "customer/department=shipping", "example.com"}, -+ {"$A12345@example.com", "$A12345", "example.com"}, -+ {"!def!xyz%abc@example.com", "!def!xyz%abc", "example.com"}, -+ {"_somename@example.com", "_somename", "example.com"}, -+} -+ -+func TestRFC2821Parsing(t *testing.T) { -+ for i, test := range rfc2821Tests { -+ mailbox, ok := parseRFC2821Mailbox(test.in) -+ expectedFailure := len(test.localPart) == 0 && len(test.domain) == 0 -+ -+ if ok && expectedFailure { -+ t.Errorf("#%d: %q unexpectedly parsed as (%q, %q)", i, test.in, mailbox.local, mailbox.domain) -+ continue -+ } -+ -+ if !ok && !expectedFailure { -+ t.Errorf("#%d: unexpected failure for %q", i, test.in) -+ continue -+ } -+ -+ if !ok { -+ continue -+ } -+ -+ if mailbox.local != test.localPart || mailbox.domain != test.domain { -+ t.Errorf("#%d: %q parsed as (%q, %q), but wanted (%q, %q)", i, test.in, mailbox.local, mailbox.domain, test.localPart, test.domain) -+ } -+ } -+} -+ -+func TestBadNamesInConstraints(t *testing.T) { -+ constraintParseError := func(err error) bool { -+ str := err.Error() -+ return strings.Contains(str, "failed to parse ") && strings.Contains(str, "constraint") -+ } -+ -+ encodingError := func(err error) bool { -+ return strings.Contains(err.Error(), "cannot be encoded as an IA5String") -+ } -+ -+ // Bad names in constraints should not parse. -+ badNames := []struct { -+ name string -+ matcher func(error) bool -+ }{ -+ {"dns:foo.com.", constraintParseError}, -+ {"email:abc@foo.com.", constraintParseError}, -+ {"email:foo.com.", constraintParseError}, -+ {"uri:example.com.", constraintParseError}, -+ {"uri:1.2.3.4", constraintParseError}, -+ {"uri:ffff::1", constraintParseError}, -+ {"dns:not–hyphen.com", encodingError}, -+ {"email:foo@not–hyphen.com", encodingError}, -+ {"uri:not–hyphen.com", encodingError}, -+ } -+ -+ priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ panic(err) -+ } -+ -+ for _, test := range badNames { -+ _, err := makeConstraintsCACert(constraintsSpec{ -+ ok: []string{test.name}, -+ }, "TestAbsoluteNamesInConstraints", priv, nil, priv) -+ -+ if err == nil { -+ t.Errorf("bad name %q unexpectedly accepted in name constraint", test.name) -+ continue -+ } else { -+ if !test.matcher(err) { -+ t.Errorf("bad name %q triggered unrecognised error: %s", test.name, err) -+ } -+ } -+ } -+} -+ -+func TestBadNamesInSANs(t *testing.T) { -+ // Bad names in URI and IP SANs should not parse. Bad DNS and email SANs -+ // will parse and are tested in name constraint tests at the top of this -+ // file. -+ badNames := []string{ -+ "uri:https://example.com./dsf", -+ "invalidip:0102", -+ "invalidip:0102030405", -+ } -+ -+ priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ panic(err) -+ } -+ -+ for _, badName := range badNames { -+ _, err := makeConstraintsLeafCert(leafSpec{sans: []string{badName}}, priv, nil, priv) -+ -+ if err == nil { -+ t.Errorf("bad name %q unexpectedly accepted in SAN", badName) -+ continue -+ } -+ -+ if str := err.Error(); !strings.Contains(str, "cannot parse ") { -+ t.Errorf("bad name %q triggered unrecognised error: %s", badName, str) -+ } -+ } -+} ->>>>>>> 70a351c141 (wip) -======= ->>>>>>> 80d9391199 (wip) -diff --git a/src/crypto/x509/notboring.go b/src/crypto/x509/notboring.go -index c83a7272c9..0c7dea2f1f 100644 ---- a/src/crypto/x509/notboring.go -+++ b/src/crypto/x509/notboring.go -@@ -2,7 +2,7 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. -<<<<<<< HEAD - --//go:build !boringcrypto -+//go:build no_openssl - - package x509 - -======= - --//go:build !boringcrypto -+//go:build no_openssl - - package x509 - -<<<<<<< HEAD -<<<<<<< HEAD ->>>>>>> 0023bf4c7a (rebase) -======= -diff --git a/src/crypto/x509/notboring.go-e b/src/crypto/x509/notboring.go-e -new file mode 100644 -index 0000000000..0c7dea2f1f ---- /dev/null -+++ b/src/crypto/x509/notboring.go-e -@@ -0,0 +1,9 @@ -+// Copyright 2022 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 no_openssl -+ -+package x509 -+ -+func boringAllowCert(c *Certificate) bool { return true } -diff --git a/src/crypto/x509/parser.go-e b/src/crypto/x509/parser.go-e -new file mode 100644 -index 0000000000..6695212a0b ---- /dev/null -+++ b/src/crypto/x509/parser.go-e -@@ -0,0 +1,1193 @@ -+// Copyright 2021 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. -+ -+package x509 -+ -+import ( -+ "bytes" -+ "crypto/dsa" -+ "crypto/ecdh" -+ "crypto/ecdsa" -+ "crypto/ed25519" -+ "crypto/elliptic" -+ "crypto/rsa" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+ "errors" -+ "fmt" -+ "math/big" -+ "net" -+ "net/url" -+ "strconv" -+ "strings" -+ "time" -+ "unicode/utf16" -+ "unicode/utf8" -+ -+ "golang.org/x/crypto/cryptobyte" -+ cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" -+) -+ -+// isPrintable reports whether the given b is in the ASN.1 PrintableString set. -+// This is a simplified version of encoding/asn1.isPrintable. -+func isPrintable(b byte) bool { -+ return 'a' <= b && b <= 'z' || -+ 'A' <= b && b <= 'Z' || -+ '0' <= b && b <= '9' || -+ '\'' <= b && b <= ')' || -+ '+' <= b && b <= '/' || -+ b == ' ' || -+ b == ':' || -+ b == '=' || -+ b == '?' || -+ // This is technically not allowed in a PrintableString. -+ // However, x509 certificates with wildcard strings don't -+ // always use the correct string type so we permit it. -+ b == '*' || -+ // This is not technically allowed either. However, not -+ // only is it relatively common, but there are also a -+ // handful of CA certificates that contain it. At least -+ // one of which will not expire until 2027. -+ b == '&' -+} -+ -+// parseASN1String parses the ASN.1 string types T61String, PrintableString, -+// UTF8String, BMPString, IA5String, and NumericString. This is mostly copied -+// from the respective encoding/asn1.parse... methods, rather than just -+// increasing the API surface of that package. -+func parseASN1String(tag cryptobyte_asn1.Tag, value []byte) (string, error) { -+ switch tag { -+ case cryptobyte_asn1.T61String: -+ return string(value), nil -+ case cryptobyte_asn1.PrintableString: -+ for _, b := range value { -+ if !isPrintable(b) { -+ return "", errors.New("invalid PrintableString") -+ } -+ } -+ return string(value), nil -+ case cryptobyte_asn1.UTF8String: -+ if !utf8.Valid(value) { -+ return "", errors.New("invalid UTF-8 string") -+ } -+ return string(value), nil -+ case cryptobyte_asn1.Tag(asn1.TagBMPString): -+ if len(value)%2 != 0 { -+ return "", errors.New("invalid BMPString") -+ } -+ -+ // Strip terminator if present. -+ if l := len(value); l >= 2 && value[l-1] == 0 && value[l-2] == 0 { -+ value = value[:l-2] -+ } -+ -+ s := make([]uint16, 0, len(value)/2) -+ for len(value) > 0 { -+ s = append(s, uint16(value[0])<<8+uint16(value[1])) -+ value = value[2:] -+ } -+ -+ return string(utf16.Decode(s)), nil -+ case cryptobyte_asn1.IA5String: -+ s := string(value) -+ if isIA5String(s) != nil { -+ return "", errors.New("invalid IA5String") -+ } -+ return s, nil -+ case cryptobyte_asn1.Tag(asn1.TagNumericString): -+ for _, b := range value { -+ if !('0' <= b && b <= '9' || b == ' ') { -+ return "", errors.New("invalid NumericString") -+ } -+ } -+ return string(value), nil -+ } -+ return "", fmt.Errorf("unsupported string type: %v", tag) -+} -+ -+// parseName parses a DER encoded Name as defined in RFC 5280. We may -+// want to export this function in the future for use in crypto/tls. -+func parseName(raw cryptobyte.String) (*pkix.RDNSequence, error) { -+ if !raw.ReadASN1(&raw, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: invalid RDNSequence") -+ } -+ -+ var rdnSeq pkix.RDNSequence -+ for !raw.Empty() { -+ var rdnSet pkix.RelativeDistinguishedNameSET -+ var set cryptobyte.String -+ if !raw.ReadASN1(&set, cryptobyte_asn1.SET) { -+ return nil, errors.New("x509: invalid RDNSequence") -+ } -+ for !set.Empty() { -+ var atav cryptobyte.String -+ if !set.ReadASN1(&atav, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: invalid RDNSequence: invalid attribute") -+ } -+ var attr pkix.AttributeTypeAndValue -+ if !atav.ReadASN1ObjectIdentifier(&attr.Type) { -+ return nil, errors.New("x509: invalid RDNSequence: invalid attribute type") -+ } -+ var rawValue cryptobyte.String -+ var valueTag cryptobyte_asn1.Tag -+ if !atav.ReadAnyASN1(&rawValue, &valueTag) { -+ return nil, errors.New("x509: invalid RDNSequence: invalid attribute value") -+ } -+ var err error -+ attr.Value, err = parseASN1String(valueTag, rawValue) -+ if err != nil { -+ return nil, fmt.Errorf("x509: invalid RDNSequence: invalid attribute value: %s", err) -+ } -+ rdnSet = append(rdnSet, attr) -+ } -+ -+ rdnSeq = append(rdnSeq, rdnSet) -+ } -+ -+ return &rdnSeq, nil -+} -+ -+func parseAI(der cryptobyte.String) (pkix.AlgorithmIdentifier, error) { -+ ai := pkix.AlgorithmIdentifier{} -+ if !der.ReadASN1ObjectIdentifier(&ai.Algorithm) { -+ return ai, errors.New("x509: malformed OID") -+ } -+ if der.Empty() { -+ return ai, nil -+ } -+ var params cryptobyte.String -+ var tag cryptobyte_asn1.Tag -+ if !der.ReadAnyASN1Element(¶ms, &tag) { -+ return ai, errors.New("x509: malformed parameters") -+ } -+ ai.Parameters.Tag = int(tag) -+ ai.Parameters.FullBytes = params -+ return ai, nil -+} -+ -+func parseTime(der *cryptobyte.String) (time.Time, error) { -+ var t time.Time -+ switch { -+ case der.PeekASN1Tag(cryptobyte_asn1.UTCTime): -+ if !der.ReadASN1UTCTime(&t) { -+ return t, errors.New("x509: malformed UTCTime") -+ } -+ case der.PeekASN1Tag(cryptobyte_asn1.GeneralizedTime): -+ if !der.ReadASN1GeneralizedTime(&t) { -+ return t, errors.New("x509: malformed GeneralizedTime") -+ } -+ default: -+ return t, errors.New("x509: unsupported time format") -+ } -+ return t, nil -+} -+ -+func parseValidity(der cryptobyte.String) (time.Time, time.Time, error) { -+ notBefore, err := parseTime(&der) -+ if err != nil { -+ return time.Time{}, time.Time{}, err -+ } -+ notAfter, err := parseTime(&der) -+ if err != nil { -+ return time.Time{}, time.Time{}, err -+ } -+ -+ return notBefore, notAfter, nil -+} -+ -+func parseExtension(der cryptobyte.String) (pkix.Extension, error) { -+ var ext pkix.Extension -+ if !der.ReadASN1ObjectIdentifier(&ext.Id) { -+ return ext, errors.New("x509: malformed extension OID field") -+ } -+ if der.PeekASN1Tag(cryptobyte_asn1.BOOLEAN) { -+ if !der.ReadASN1Boolean(&ext.Critical) { -+ return ext, errors.New("x509: malformed extension critical field") -+ } -+ } -+ var val cryptobyte.String -+ if !der.ReadASN1(&val, cryptobyte_asn1.OCTET_STRING) { -+ return ext, errors.New("x509: malformed extension value field") -+ } -+ ext.Value = val -+ return ext, nil -+} -+ -+func parsePublicKey(keyData *publicKeyInfo) (any, error) { -+ oid := keyData.Algorithm.Algorithm -+ params := keyData.Algorithm.Parameters -+ der := cryptobyte.String(keyData.PublicKey.RightAlign()) -+ switch { -+ case oid.Equal(oidPublicKeyRSA): -+ // RSA public keys must have a NULL in the parameters. -+ // See RFC 3279, Section 2.3.1. -+ if !bytes.Equal(params.FullBytes, asn1.NullBytes) { -+ return nil, errors.New("x509: RSA key missing NULL parameters") -+ } -+ -+ p := &pkcs1PublicKey{N: new(big.Int)} -+ if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: invalid RSA public key") -+ } -+ if !der.ReadASN1Integer(p.N) { -+ return nil, errors.New("x509: invalid RSA modulus") -+ } -+ if !der.ReadASN1Integer(&p.E) { -+ return nil, errors.New("x509: invalid RSA public exponent") -+ } -+ -+ if p.N.Sign() <= 0 { -+ return nil, errors.New("x509: RSA modulus is not a positive number") -+ } -+ if p.E <= 0 { -+ return nil, errors.New("x509: RSA public exponent is not a positive number") -+ } -+ -+ pub := &rsa.PublicKey{ -+ E: p.E, -+ N: p.N, -+ } -+ return pub, nil -+ case oid.Equal(oidPublicKeyECDSA): -+ paramsDer := cryptobyte.String(params.FullBytes) -+ namedCurveOID := new(asn1.ObjectIdentifier) -+ if !paramsDer.ReadASN1ObjectIdentifier(namedCurveOID) { -+ return nil, errors.New("x509: invalid ECDSA parameters") -+ } -+ namedCurve := namedCurveFromOID(*namedCurveOID) -+ if namedCurve == nil { -+ return nil, errors.New("x509: unsupported elliptic curve") -+ } -+ x, y := elliptic.Unmarshal(namedCurve, der) -+ if x == nil { -+ return nil, errors.New("x509: failed to unmarshal elliptic curve point") -+ } -+ pub := &ecdsa.PublicKey{ -+ Curve: namedCurve, -+ X: x, -+ Y: y, -+ } -+ return pub, nil -+ case oid.Equal(oidPublicKeyEd25519): -+ // RFC 8410, Section 3 -+ // > For all of the OIDs, the parameters MUST be absent. -+ if len(params.FullBytes) != 0 { -+ return nil, errors.New("x509: Ed25519 key encoded with illegal parameters") -+ } -+ if len(der) != ed25519.PublicKeySize { -+ return nil, errors.New("x509: wrong Ed25519 public key size") -+ } -+ return ed25519.PublicKey(der), nil -+ case oid.Equal(oidPublicKeyX25519): -+ // RFC 8410, Section 3 -+ // > For all of the OIDs, the parameters MUST be absent. -+ if len(params.FullBytes) != 0 { -+ return nil, errors.New("x509: X25519 key encoded with illegal parameters") -+ } -+ return ecdh.X25519().NewPublicKey(der) -+ case oid.Equal(oidPublicKeyDSA): -+ y := new(big.Int) -+ if !der.ReadASN1Integer(y) { -+ return nil, errors.New("x509: invalid DSA public key") -+ } -+ pub := &dsa.PublicKey{ -+ Y: y, -+ Parameters: dsa.Parameters{ -+ P: new(big.Int), -+ Q: new(big.Int), -+ G: new(big.Int), -+ }, -+ } -+ paramsDer := cryptobyte.String(params.FullBytes) -+ if !paramsDer.ReadASN1(¶msDer, cryptobyte_asn1.SEQUENCE) || -+ !paramsDer.ReadASN1Integer(pub.Parameters.P) || -+ !paramsDer.ReadASN1Integer(pub.Parameters.Q) || -+ !paramsDer.ReadASN1Integer(pub.Parameters.G) { -+ return nil, errors.New("x509: invalid DSA parameters") -+ } -+ if pub.Y.Sign() <= 0 || pub.Parameters.P.Sign() <= 0 || -+ pub.Parameters.Q.Sign() <= 0 || pub.Parameters.G.Sign() <= 0 { -+ return nil, errors.New("x509: zero or negative DSA parameter") -+ } -+ return pub, nil -+ default: -+ return nil, errors.New("x509: unknown public key algorithm") -+ } -+} -+ -+func parseKeyUsageExtension(der cryptobyte.String) (KeyUsage, error) { -+ var usageBits asn1.BitString -+ if !der.ReadASN1BitString(&usageBits) { -+ return 0, errors.New("x509: invalid key usage") -+ } -+ -+ var usage int -+ for i := 0; i < 9; i++ { -+ if usageBits.At(i) != 0 { -+ usage |= 1 << uint(i) -+ } -+ } -+ return KeyUsage(usage), nil -+} -+ -+func parseBasicConstraintsExtension(der cryptobyte.String) (bool, int, error) { -+ var isCA bool -+ if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { -+ return false, 0, errors.New("x509: invalid basic constraints") -+ } -+ if der.PeekASN1Tag(cryptobyte_asn1.BOOLEAN) { -+ if !der.ReadASN1Boolean(&isCA) { -+ return false, 0, errors.New("x509: invalid basic constraints") -+ } -+ } -+ maxPathLen := -1 -+ if der.PeekASN1Tag(cryptobyte_asn1.INTEGER) { -+ if !der.ReadASN1Integer(&maxPathLen) { -+ return false, 0, errors.New("x509: invalid basic constraints") -+ } -+ } -+ -+ // TODO: map out.MaxPathLen to 0 if it has the -1 default value? (Issue 19285) -+ return isCA, maxPathLen, nil -+} -+ -+func forEachSAN(der cryptobyte.String, callback func(tag int, data []byte) error) error { -+ if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { -+ return errors.New("x509: invalid subject alternative names") -+ } -+ for !der.Empty() { -+ var san cryptobyte.String -+ var tag cryptobyte_asn1.Tag -+ if !der.ReadAnyASN1(&san, &tag) { -+ return errors.New("x509: invalid subject alternative name") -+ } -+ if err := callback(int(tag^0x80), san); err != nil { -+ return err -+ } -+ } -+ -+ return nil -+} -+ -+func parseSANExtension(der cryptobyte.String) (dnsNames, emailAddresses []string, ipAddresses []net.IP, uris []*url.URL, err error) { -+ err = forEachSAN(der, func(tag int, data []byte) error { -+ switch tag { -+ case nameTypeEmail: -+ email := string(data) -+ if err := isIA5String(email); err != nil { -+ return errors.New("x509: SAN rfc822Name is malformed") -+ } -+ emailAddresses = append(emailAddresses, email) -+ case nameTypeDNS: -+ name := string(data) -+ if err := isIA5String(name); err != nil { -+ return errors.New("x509: SAN dNSName is malformed") -+ } -+ dnsNames = append(dnsNames, string(name)) -+ case nameTypeURI: -+ uriStr := string(data) -+ if err := isIA5String(uriStr); err != nil { -+ return errors.New("x509: SAN uniformResourceIdentifier is malformed") -+ } -+ uri, err := url.Parse(uriStr) -+ if err != nil { -+ return fmt.Errorf("x509: cannot parse URI %q: %s", uriStr, err) -+ } -+ if len(uri.Host) > 0 { -+ if _, ok := domainToReverseLabels(uri.Host); !ok { -+ return fmt.Errorf("x509: cannot parse URI %q: invalid domain", uriStr) -+ } -+ } -+ uris = append(uris, uri) -+ case nameTypeIP: -+ switch len(data) { -+ case net.IPv4len, net.IPv6len: -+ ipAddresses = append(ipAddresses, data) -+ default: -+ return errors.New("x509: cannot parse IP address of length " + strconv.Itoa(len(data))) -+ } -+ } -+ -+ return nil -+ }) -+ -+ return -+} -+ -+func parseExtKeyUsageExtension(der cryptobyte.String) ([]ExtKeyUsage, []asn1.ObjectIdentifier, error) { -+ var extKeyUsages []ExtKeyUsage -+ var unknownUsages []asn1.ObjectIdentifier -+ if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { -+ return nil, nil, errors.New("x509: invalid extended key usages") -+ } -+ for !der.Empty() { -+ var eku asn1.ObjectIdentifier -+ if !der.ReadASN1ObjectIdentifier(&eku) { -+ return nil, nil, errors.New("x509: invalid extended key usages") -+ } -+ if extKeyUsage, ok := extKeyUsageFromOID(eku); ok { -+ extKeyUsages = append(extKeyUsages, extKeyUsage) -+ } else { -+ unknownUsages = append(unknownUsages, eku) -+ } -+ } -+ return extKeyUsages, unknownUsages, nil -+} -+ -+func parseCertificatePoliciesExtension(der cryptobyte.String) ([]asn1.ObjectIdentifier, error) { -+ var oids []asn1.ObjectIdentifier -+ if !der.ReadASN1(&der, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: invalid certificate policies") -+ } -+ for !der.Empty() { -+ var cp cryptobyte.String -+ if !der.ReadASN1(&cp, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: invalid certificate policies") -+ } -+ var oid asn1.ObjectIdentifier -+ if !cp.ReadASN1ObjectIdentifier(&oid) { -+ return nil, errors.New("x509: invalid certificate policies") -+ } -+ oids = append(oids, oid) -+ } -+ -+ return oids, nil -+} -+ -+// isValidIPMask reports whether mask consists of zero or more 1 bits, followed by zero bits. -+func isValidIPMask(mask []byte) bool { -+ seenZero := false -+ -+ for _, b := range mask { -+ if seenZero { -+ if b != 0 { -+ return false -+ } -+ -+ continue -+ } -+ -+ switch b { -+ case 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe: -+ seenZero = true -+ case 0xff: -+ default: -+ return false -+ } -+ } -+ -+ return true -+} -+ -+func parseNameConstraintsExtension(out *Certificate, e pkix.Extension) (unhandled bool, err error) { -+ // RFC 5280, 4.2.1.10 -+ -+ // NameConstraints ::= SEQUENCE { -+ // permittedSubtrees [0] GeneralSubtrees OPTIONAL, -+ // excludedSubtrees [1] GeneralSubtrees OPTIONAL } -+ // -+ // GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree -+ // -+ // GeneralSubtree ::= SEQUENCE { -+ // base GeneralName, -+ // minimum [0] BaseDistance DEFAULT 0, -+ // maximum [1] BaseDistance OPTIONAL } -+ // -+ // BaseDistance ::= INTEGER (0..MAX) -+ -+ outer := cryptobyte.String(e.Value) -+ var toplevel, permitted, excluded cryptobyte.String -+ var havePermitted, haveExcluded bool -+ if !outer.ReadASN1(&toplevel, cryptobyte_asn1.SEQUENCE) || -+ !outer.Empty() || -+ !toplevel.ReadOptionalASN1(&permitted, &havePermitted, cryptobyte_asn1.Tag(0).ContextSpecific().Constructed()) || -+ !toplevel.ReadOptionalASN1(&excluded, &haveExcluded, cryptobyte_asn1.Tag(1).ContextSpecific().Constructed()) || -+ !toplevel.Empty() { -+ return false, errors.New("x509: invalid NameConstraints extension") -+ } -+ -+ if !havePermitted && !haveExcluded || len(permitted) == 0 && len(excluded) == 0 { -+ // From RFC 5280, Section 4.2.1.10: -+ // “either the permittedSubtrees field -+ // or the excludedSubtrees MUST be -+ // present” -+ return false, errors.New("x509: empty name constraints extension") -+ } -+ -+ getValues := func(subtrees cryptobyte.String) (dnsNames []string, ips []*net.IPNet, emails, uriDomains []string, err error) { -+ for !subtrees.Empty() { -+ var seq, value cryptobyte.String -+ var tag cryptobyte_asn1.Tag -+ if !subtrees.ReadASN1(&seq, cryptobyte_asn1.SEQUENCE) || -+ !seq.ReadAnyASN1(&value, &tag) { -+ return nil, nil, nil, nil, fmt.Errorf("x509: invalid NameConstraints extension") -+ } -+ -+ var ( -+ dnsTag = cryptobyte_asn1.Tag(2).ContextSpecific() -+ emailTag = cryptobyte_asn1.Tag(1).ContextSpecific() -+ ipTag = cryptobyte_asn1.Tag(7).ContextSpecific() -+ uriTag = cryptobyte_asn1.Tag(6).ContextSpecific() -+ ) -+ -+ switch tag { -+ case dnsTag: -+ domain := string(value) -+ if err := isIA5String(domain); err != nil { -+ return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error()) -+ } -+ -+ trimmedDomain := domain -+ if len(trimmedDomain) > 0 && trimmedDomain[0] == '.' { -+ // constraints can have a leading -+ // period to exclude the domain -+ // itself, but that's not valid in a -+ // normal domain name. -+ trimmedDomain = trimmedDomain[1:] -+ } -+ if _, ok := domainToReverseLabels(trimmedDomain); !ok { -+ return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse dnsName constraint %q", domain) -+ } -+ dnsNames = append(dnsNames, domain) -+ -+ case ipTag: -+ l := len(value) -+ var ip, mask []byte -+ -+ switch l { -+ case 8: -+ ip = value[:4] -+ mask = value[4:] -+ -+ case 32: -+ ip = value[:16] -+ mask = value[16:] -+ -+ default: -+ return nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained value of length %d", l) -+ } -+ -+ if !isValidIPMask(mask) { -+ return nil, nil, nil, nil, fmt.Errorf("x509: IP constraint contained invalid mask %x", mask) -+ } -+ -+ ips = append(ips, &net.IPNet{IP: net.IP(ip), Mask: net.IPMask(mask)}) -+ -+ case emailTag: -+ constraint := string(value) -+ if err := isIA5String(constraint); err != nil { -+ return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error()) -+ } -+ -+ // If the constraint contains an @ then -+ // it specifies an exact mailbox name. -+ if strings.Contains(constraint, "@") { -+ if _, ok := parseRFC2821Mailbox(constraint); !ok { -+ return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint) -+ } -+ } else { -+ // Otherwise it's a domain name. -+ domain := constraint -+ if len(domain) > 0 && domain[0] == '.' { -+ domain = domain[1:] -+ } -+ if _, ok := domainToReverseLabels(domain); !ok { -+ return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse rfc822Name constraint %q", constraint) -+ } -+ } -+ emails = append(emails, constraint) -+ -+ case uriTag: -+ domain := string(value) -+ if err := isIA5String(domain); err != nil { -+ return nil, nil, nil, nil, errors.New("x509: invalid constraint value: " + err.Error()) -+ } -+ -+ if net.ParseIP(domain) != nil { -+ return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q: cannot be IP address", domain) -+ } -+ -+ trimmedDomain := domain -+ if len(trimmedDomain) > 0 && trimmedDomain[0] == '.' { -+ // constraints can have a leading -+ // period to exclude the domain itself, -+ // but that's not valid in a normal -+ // domain name. -+ trimmedDomain = trimmedDomain[1:] -+ } -+ if _, ok := domainToReverseLabels(trimmedDomain); !ok { -+ return nil, nil, nil, nil, fmt.Errorf("x509: failed to parse URI constraint %q", domain) -+ } -+ uriDomains = append(uriDomains, domain) -+ -+ default: -+ unhandled = true -+ } -+ } -+ -+ return dnsNames, ips, emails, uriDomains, nil -+ } -+ -+ if out.PermittedDNSDomains, out.PermittedIPRanges, out.PermittedEmailAddresses, out.PermittedURIDomains, err = getValues(permitted); err != nil { -+ return false, err -+ } -+ if out.ExcludedDNSDomains, out.ExcludedIPRanges, out.ExcludedEmailAddresses, out.ExcludedURIDomains, err = getValues(excluded); err != nil { -+ return false, err -+ } -+ out.PermittedDNSDomainsCritical = e.Critical -+ -+ return unhandled, nil -+} -+ -+func processExtensions(out *Certificate) error { -+ var err error -+ for _, e := range out.Extensions { -+ unhandled := false -+ -+ if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 { -+ switch e.Id[3] { -+ case 15: -+ out.KeyUsage, err = parseKeyUsageExtension(e.Value) -+ if err != nil { -+ return err -+ } -+ case 19: -+ out.IsCA, out.MaxPathLen, err = parseBasicConstraintsExtension(e.Value) -+ if err != nil { -+ return err -+ } -+ out.BasicConstraintsValid = true -+ out.MaxPathLenZero = out.MaxPathLen == 0 -+ case 17: -+ out.DNSNames, out.EmailAddresses, out.IPAddresses, out.URIs, err = parseSANExtension(e.Value) -+ if err != nil { -+ return err -+ } -+ -+ if len(out.DNSNames) == 0 && len(out.EmailAddresses) == 0 && len(out.IPAddresses) == 0 && len(out.URIs) == 0 { -+ // If we didn't parse anything then we do the critical check, below. -+ unhandled = true -+ } -+ -+ case 30: -+ unhandled, err = parseNameConstraintsExtension(out, e) -+ if err != nil { -+ return err -+ } -+ -+ case 31: -+ // RFC 5280, 4.2.1.13 -+ -+ // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint -+ // -+ // DistributionPoint ::= SEQUENCE { -+ // distributionPoint [0] DistributionPointName OPTIONAL, -+ // reasons [1] ReasonFlags OPTIONAL, -+ // cRLIssuer [2] GeneralNames OPTIONAL } -+ // -+ // DistributionPointName ::= CHOICE { -+ // fullName [0] GeneralNames, -+ // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } -+ val := cryptobyte.String(e.Value) -+ if !val.ReadASN1(&val, cryptobyte_asn1.SEQUENCE) { -+ return errors.New("x509: invalid CRL distribution points") -+ } -+ for !val.Empty() { -+ var dpDER cryptobyte.String -+ if !val.ReadASN1(&dpDER, cryptobyte_asn1.SEQUENCE) { -+ return errors.New("x509: invalid CRL distribution point") -+ } -+ var dpNameDER cryptobyte.String -+ var dpNamePresent bool -+ if !dpDER.ReadOptionalASN1(&dpNameDER, &dpNamePresent, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) { -+ return errors.New("x509: invalid CRL distribution point") -+ } -+ if !dpNamePresent { -+ continue -+ } -+ if !dpNameDER.ReadASN1(&dpNameDER, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) { -+ return errors.New("x509: invalid CRL distribution point") -+ } -+ for !dpNameDER.Empty() { -+ if !dpNameDER.PeekASN1Tag(cryptobyte_asn1.Tag(6).ContextSpecific()) { -+ break -+ } -+ var uri cryptobyte.String -+ if !dpNameDER.ReadASN1(&uri, cryptobyte_asn1.Tag(6).ContextSpecific()) { -+ return errors.New("x509: invalid CRL distribution point") -+ } -+ out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(uri)) -+ } -+ } -+ -+ case 35: -+ // RFC 5280, 4.2.1.1 -+ val := cryptobyte.String(e.Value) -+ var akid cryptobyte.String -+ if !val.ReadASN1(&akid, cryptobyte_asn1.SEQUENCE) { -+ return errors.New("x509: invalid authority key identifier") -+ } -+ if akid.PeekASN1Tag(cryptobyte_asn1.Tag(0).ContextSpecific()) { -+ if !akid.ReadASN1(&akid, cryptobyte_asn1.Tag(0).ContextSpecific()) { -+ return errors.New("x509: invalid authority key identifier") -+ } -+ out.AuthorityKeyId = akid -+ } -+ case 37: -+ out.ExtKeyUsage, out.UnknownExtKeyUsage, err = parseExtKeyUsageExtension(e.Value) -+ if err != nil { -+ return err -+ } -+ case 14: -+ // RFC 5280, 4.2.1.2 -+ val := cryptobyte.String(e.Value) -+ var skid cryptobyte.String -+ if !val.ReadASN1(&skid, cryptobyte_asn1.OCTET_STRING) { -+ return errors.New("x509: invalid subject key identifier") -+ } -+ out.SubjectKeyId = skid -+ case 32: -+ out.PolicyIdentifiers, err = parseCertificatePoliciesExtension(e.Value) -+ if err != nil { -+ return err -+ } -+ default: -+ // Unknown extensions are recorded if critical. -+ unhandled = true -+ } -+ } else if e.Id.Equal(oidExtensionAuthorityInfoAccess) { -+ // RFC 5280 4.2.2.1: Authority Information Access -+ val := cryptobyte.String(e.Value) -+ if !val.ReadASN1(&val, cryptobyte_asn1.SEQUENCE) { -+ return errors.New("x509: invalid authority info access") -+ } -+ for !val.Empty() { -+ var aiaDER cryptobyte.String -+ if !val.ReadASN1(&aiaDER, cryptobyte_asn1.SEQUENCE) { -+ return errors.New("x509: invalid authority info access") -+ } -+ var method asn1.ObjectIdentifier -+ if !aiaDER.ReadASN1ObjectIdentifier(&method) { -+ return errors.New("x509: invalid authority info access") -+ } -+ if !aiaDER.PeekASN1Tag(cryptobyte_asn1.Tag(6).ContextSpecific()) { -+ continue -+ } -+ if !aiaDER.ReadASN1(&aiaDER, cryptobyte_asn1.Tag(6).ContextSpecific()) { -+ return errors.New("x509: invalid authority info access") -+ } -+ switch { -+ case method.Equal(oidAuthorityInfoAccessOcsp): -+ out.OCSPServer = append(out.OCSPServer, string(aiaDER)) -+ case method.Equal(oidAuthorityInfoAccessIssuers): -+ out.IssuingCertificateURL = append(out.IssuingCertificateURL, string(aiaDER)) -+ } -+ } -+ } else { -+ // Unknown extensions are recorded if critical. -+ unhandled = true -+ } -+ -+ if e.Critical && unhandled { -+ out.UnhandledCriticalExtensions = append(out.UnhandledCriticalExtensions, e.Id) -+ } -+ } -+ -+ return nil -+} -+ -+func parseCertificate(der []byte) (*Certificate, error) { -+ cert := &Certificate{} -+ -+ input := cryptobyte.String(der) -+ // we read the SEQUENCE including length and tag bytes so that -+ // we can populate Certificate.Raw, before unwrapping the -+ // SEQUENCE so it can be operated on -+ if !input.ReadASN1Element(&input, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed certificate") -+ } -+ cert.Raw = input -+ if !input.ReadASN1(&input, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed certificate") -+ } -+ -+ var tbs cryptobyte.String -+ // do the same trick again as above to extract the raw -+ // bytes for Certificate.RawTBSCertificate -+ if !input.ReadASN1Element(&tbs, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed tbs certificate") -+ } -+ cert.RawTBSCertificate = tbs -+ if !tbs.ReadASN1(&tbs, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed tbs certificate") -+ } -+ -+ if !tbs.ReadOptionalASN1Integer(&cert.Version, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific(), 0) { -+ return nil, errors.New("x509: malformed version") -+ } -+ if cert.Version < 0 { -+ return nil, errors.New("x509: malformed version") -+ } -+ // for backwards compat reasons Version is one-indexed, -+ // rather than zero-indexed as defined in 5280 -+ cert.Version++ -+ if cert.Version > 3 { -+ return nil, errors.New("x509: invalid version") -+ } -+ -+ serial := new(big.Int) -+ if !tbs.ReadASN1Integer(serial) { -+ return nil, errors.New("x509: malformed serial number") -+ } -+ // we ignore the presence of negative serial numbers because -+ // of their prevalence, despite them being invalid -+ // TODO(rolandshoemaker): revisit this decision, there are currently -+ // only 10 trusted certificates with negative serial numbers -+ // according to censys.io. -+ cert.SerialNumber = serial -+ -+ var sigAISeq cryptobyte.String -+ if !tbs.ReadASN1(&sigAISeq, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed signature algorithm identifier") -+ } -+ // Before parsing the inner algorithm identifier, extract -+ // the outer algorithm identifier and make sure that they -+ // match. -+ var outerSigAISeq cryptobyte.String -+ if !input.ReadASN1(&outerSigAISeq, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed algorithm identifier") -+ } -+ if !bytes.Equal(outerSigAISeq, sigAISeq) { -+ return nil, errors.New("x509: inner and outer signature algorithm identifiers don't match") -+ } -+ sigAI, err := parseAI(sigAISeq) -+ if err != nil { -+ return nil, err -+ } -+ cert.SignatureAlgorithm = getSignatureAlgorithmFromAI(sigAI) -+ -+ var issuerSeq cryptobyte.String -+ if !tbs.ReadASN1Element(&issuerSeq, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed issuer") -+ } -+ cert.RawIssuer = issuerSeq -+ issuerRDNs, err := parseName(issuerSeq) -+ if err != nil { -+ return nil, err -+ } -+ cert.Issuer.FillFromRDNSequence(issuerRDNs) -+ -+ var validity cryptobyte.String -+ if !tbs.ReadASN1(&validity, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed validity") -+ } -+ cert.NotBefore, cert.NotAfter, err = parseValidity(validity) -+ if err != nil { -+ return nil, err -+ } -+ -+ var subjectSeq cryptobyte.String -+ if !tbs.ReadASN1Element(&subjectSeq, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed issuer") -+ } -+ cert.RawSubject = subjectSeq -+ subjectRDNs, err := parseName(subjectSeq) -+ if err != nil { -+ return nil, err -+ } -+ cert.Subject.FillFromRDNSequence(subjectRDNs) -+ -+ var spki cryptobyte.String -+ if !tbs.ReadASN1Element(&spki, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed spki") -+ } -+ cert.RawSubjectPublicKeyInfo = spki -+ if !spki.ReadASN1(&spki, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed spki") -+ } -+ var pkAISeq cryptobyte.String -+ if !spki.ReadASN1(&pkAISeq, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed public key algorithm identifier") -+ } -+ pkAI, err := parseAI(pkAISeq) -+ if err != nil { -+ return nil, err -+ } -+ cert.PublicKeyAlgorithm = getPublicKeyAlgorithmFromOID(pkAI.Algorithm) -+ var spk asn1.BitString -+ if !spki.ReadASN1BitString(&spk) { -+ return nil, errors.New("x509: malformed subjectPublicKey") -+ } -+ if cert.PublicKeyAlgorithm != UnknownPublicKeyAlgorithm { -+ cert.PublicKey, err = parsePublicKey(&publicKeyInfo{ -+ Algorithm: pkAI, -+ PublicKey: spk, -+ }) -+ if err != nil { -+ return nil, err -+ } -+ } -+ -+ if cert.Version > 1 { -+ if !tbs.SkipOptionalASN1(cryptobyte_asn1.Tag(1).ContextSpecific()) { -+ return nil, errors.New("x509: malformed issuerUniqueID") -+ } -+ if !tbs.SkipOptionalASN1(cryptobyte_asn1.Tag(2).ContextSpecific()) { -+ return nil, errors.New("x509: malformed subjectUniqueID") -+ } -+ if cert.Version == 3 { -+ var extensions cryptobyte.String -+ var present bool -+ if !tbs.ReadOptionalASN1(&extensions, &present, cryptobyte_asn1.Tag(3).Constructed().ContextSpecific()) { -+ return nil, errors.New("x509: malformed extensions") -+ } -+ if present { -+ seenExts := make(map[string]bool) -+ if !extensions.ReadASN1(&extensions, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed extensions") -+ } -+ for !extensions.Empty() { -+ var extension cryptobyte.String -+ if !extensions.ReadASN1(&extension, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed extension") -+ } -+ ext, err := parseExtension(extension) -+ if err != nil { -+ return nil, err -+ } -+ oidStr := ext.Id.String() -+ if seenExts[oidStr] { -+ return nil, errors.New("x509: certificate contains duplicate extensions") -+ } -+ seenExts[oidStr] = true -+ cert.Extensions = append(cert.Extensions, ext) -+ } -+ err = processExtensions(cert) -+ if err != nil { -+ return nil, err -+ } -+ } -+ } -+ } -+ -+ var signature asn1.BitString -+ if !input.ReadASN1BitString(&signature) { -+ return nil, errors.New("x509: malformed signature") -+ } -+ cert.Signature = signature.RightAlign() -+ -+ return cert, nil -+} -+ -+// ParseCertificate parses a single certificate from the given ASN.1 DER data. -+func ParseCertificate(der []byte) (*Certificate, error) { -+ cert, err := parseCertificate(der) -+ if err != nil { -+ return nil, err -+ } -+ if len(der) != len(cert.Raw) { -+ return nil, errors.New("x509: trailing data") -+ } -+ return cert, err -+} -+ -+// ParseCertificates parses one or more certificates from the given ASN.1 DER -+// data. The certificates must be concatenated with no intermediate padding. -+func ParseCertificates(der []byte) ([]*Certificate, error) { -+ var certs []*Certificate -+ for len(der) > 0 { -+ cert, err := parseCertificate(der) -+ if err != nil { -+ return nil, err -+ } -+ certs = append(certs, cert) -+ der = der[len(cert.Raw):] -+ } -+ return certs, nil -+} -+ -+// The X.509 standards confusingly 1-indexed the version names, but 0-indexed -+// the actual encoded version, so the version for X.509v2 is 1. -+const x509v2Version = 1 -+ -+// ParseRevocationList parses a X509 v2 Certificate Revocation List from the given -+// ASN.1 DER data. -+func ParseRevocationList(der []byte) (*RevocationList, error) { -+ rl := &RevocationList{} -+ -+ input := cryptobyte.String(der) -+ // we read the SEQUENCE including length and tag bytes so that -+ // we can populate RevocationList.Raw, before unwrapping the -+ // SEQUENCE so it can be operated on -+ if !input.ReadASN1Element(&input, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed crl") -+ } -+ rl.Raw = input -+ if !input.ReadASN1(&input, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed crl") -+ } -+ -+ var tbs cryptobyte.String -+ // do the same trick again as above to extract the raw -+ // bytes for Certificate.RawTBSCertificate -+ if !input.ReadASN1Element(&tbs, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed tbs crl") -+ } -+ rl.RawTBSRevocationList = tbs -+ if !tbs.ReadASN1(&tbs, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed tbs crl") -+ } -+ -+ var version int -+ if !tbs.PeekASN1Tag(cryptobyte_asn1.INTEGER) { -+ return nil, errors.New("x509: unsupported crl version") -+ } -+ if !tbs.ReadASN1Integer(&version) { -+ return nil, errors.New("x509: malformed crl") -+ } -+ if version != x509v2Version { -+ return nil, fmt.Errorf("x509: unsupported crl version: %d", version) -+ } -+ -+ var sigAISeq cryptobyte.String -+ if !tbs.ReadASN1(&sigAISeq, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed signature algorithm identifier") -+ } -+ // Before parsing the inner algorithm identifier, extract -+ // the outer algorithm identifier and make sure that they -+ // match. -+ var outerSigAISeq cryptobyte.String -+ if !input.ReadASN1(&outerSigAISeq, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed algorithm identifier") -+ } -+ if !bytes.Equal(outerSigAISeq, sigAISeq) { -+ return nil, errors.New("x509: inner and outer signature algorithm identifiers don't match") -+ } -+ sigAI, err := parseAI(sigAISeq) -+ if err != nil { -+ return nil, err -+ } -+ rl.SignatureAlgorithm = getSignatureAlgorithmFromAI(sigAI) -+ -+ var signature asn1.BitString -+ if !input.ReadASN1BitString(&signature) { -+ return nil, errors.New("x509: malformed signature") -+ } -+ rl.Signature = signature.RightAlign() -+ -+ var issuerSeq cryptobyte.String -+ if !tbs.ReadASN1Element(&issuerSeq, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed issuer") -+ } -+ rl.RawIssuer = issuerSeq -+ issuerRDNs, err := parseName(issuerSeq) -+ if err != nil { -+ return nil, err -+ } -+ rl.Issuer.FillFromRDNSequence(issuerRDNs) -+ -+ rl.ThisUpdate, err = parseTime(&tbs) -+ if err != nil { -+ return nil, err -+ } -+ if tbs.PeekASN1Tag(cryptobyte_asn1.GeneralizedTime) || tbs.PeekASN1Tag(cryptobyte_asn1.UTCTime) { -+ rl.NextUpdate, err = parseTime(&tbs) -+ if err != nil { -+ return nil, err -+ } -+ } -+ -+ if tbs.PeekASN1Tag(cryptobyte_asn1.SEQUENCE) { -+ var revokedSeq cryptobyte.String -+ if !tbs.ReadASN1(&revokedSeq, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed crl") -+ } -+ for !revokedSeq.Empty() { -+ rce := RevocationListEntry{} -+ -+ var certSeq cryptobyte.String -+ if !revokedSeq.ReadASN1Element(&certSeq, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed crl") -+ } -+ rce.Raw = certSeq -+ if !certSeq.ReadASN1(&certSeq, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed crl") -+ } -+ -+ rce.SerialNumber = new(big.Int) -+ if !certSeq.ReadASN1Integer(rce.SerialNumber) { -+ return nil, errors.New("x509: malformed serial number") -+ } -+ rce.RevocationTime, err = parseTime(&certSeq) -+ if err != nil { -+ return nil, err -+ } -+ var extensions cryptobyte.String -+ var present bool -+ if !certSeq.ReadOptionalASN1(&extensions, &present, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed extensions") -+ } -+ if present { -+ for !extensions.Empty() { -+ var extension cryptobyte.String -+ if !extensions.ReadASN1(&extension, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed extension") -+ } -+ ext, err := parseExtension(extension) -+ if err != nil { -+ return nil, err -+ } -+ if ext.Id.Equal(oidExtensionReasonCode) { -+ val := cryptobyte.String(ext.Value) -+ if !val.ReadASN1Enum(&rce.ReasonCode) { -+ return nil, fmt.Errorf("x509: malformed reasonCode extension") -+ } -+ } -+ rce.Extensions = append(rce.Extensions, ext) -+ } -+ } -+ -+ rl.RevokedCertificateEntries = append(rl.RevokedCertificateEntries, rce) -+ rcDeprecated := pkix.RevokedCertificate{ -+ SerialNumber: rce.SerialNumber, -+ RevocationTime: rce.RevocationTime, -+ Extensions: rce.Extensions, -+ } -+ rl.RevokedCertificates = append(rl.RevokedCertificates, rcDeprecated) -+ } -+ } -+ -+ var extensions cryptobyte.String -+ var present bool -+ if !tbs.ReadOptionalASN1(&extensions, &present, cryptobyte_asn1.Tag(0).Constructed().ContextSpecific()) { -+ return nil, errors.New("x509: malformed extensions") -+ } -+ if present { -+ if !extensions.ReadASN1(&extensions, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed extensions") -+ } -+ for !extensions.Empty() { -+ var extension cryptobyte.String -+ if !extensions.ReadASN1(&extension, cryptobyte_asn1.SEQUENCE) { -+ return nil, errors.New("x509: malformed extension") -+ } -+ ext, err := parseExtension(extension) -+ if err != nil { -+ return nil, err -+ } -+ if ext.Id.Equal(oidExtensionAuthorityKeyId) { -+ rl.AuthorityKeyId = ext.Value -+ } else if ext.Id.Equal(oidExtensionCRLNumber) { -+ value := cryptobyte.String(ext.Value) -+ rl.Number = new(big.Int) -+ if !value.ReadASN1Integer(rl.Number) { -+ return nil, errors.New("x509: malformed crl number") -+ } -+ } -+ rl.Extensions = append(rl.Extensions, ext) -+ } -+ } -+ -+ return rl, nil -+} -diff --git a/src/crypto/x509/parser_test.go-e b/src/crypto/x509/parser_test.go-e -new file mode 100644 -index 0000000000..b31f9cdb24 ---- /dev/null -+++ b/src/crypto/x509/parser_test.go-e -@@ -0,0 +1,103 @@ -+// Copyright 2021 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. -+ -+package x509 -+ -+import ( -+ "encoding/asn1" -+ "testing" -+ -+ cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" -+) -+ -+func TestParseASN1String(t *testing.T) { -+ tests := []struct { -+ name string -+ tag cryptobyte_asn1.Tag -+ value []byte -+ expected string -+ expectedErr string -+ }{ -+ { -+ name: "T61String", -+ tag: cryptobyte_asn1.T61String, -+ value: []byte{80, 81, 82}, -+ expected: string("PQR"), -+ }, -+ { -+ name: "PrintableString", -+ tag: cryptobyte_asn1.PrintableString, -+ value: []byte{80, 81, 82}, -+ expected: string("PQR"), -+ }, -+ { -+ name: "PrintableString (invalid)", -+ tag: cryptobyte_asn1.PrintableString, -+ value: []byte{1, 2, 3}, -+ expectedErr: "invalid PrintableString", -+ }, -+ { -+ name: "UTF8String", -+ tag: cryptobyte_asn1.UTF8String, -+ value: []byte{80, 81, 82}, -+ expected: string("PQR"), -+ }, -+ { -+ name: "UTF8String (invalid)", -+ tag: cryptobyte_asn1.UTF8String, -+ value: []byte{255}, -+ expectedErr: "invalid UTF-8 string", -+ }, -+ { -+ name: "BMPString", -+ tag: cryptobyte_asn1.Tag(asn1.TagBMPString), -+ value: []byte{80, 81}, -+ expected: string("偑"), -+ }, -+ { -+ name: "BMPString (invalid length)", -+ tag: cryptobyte_asn1.Tag(asn1.TagBMPString), -+ value: []byte{255}, -+ expectedErr: "invalid BMPString", -+ }, -+ { -+ name: "IA5String", -+ tag: cryptobyte_asn1.IA5String, -+ value: []byte{80, 81}, -+ expected: string("PQ"), -+ }, -+ { -+ name: "IA5String (invalid)", -+ tag: cryptobyte_asn1.IA5String, -+ value: []byte{255}, -+ expectedErr: "invalid IA5String", -+ }, -+ { -+ name: "NumericString", -+ tag: cryptobyte_asn1.Tag(asn1.TagNumericString), -+ value: []byte{49, 50}, -+ expected: string("12"), -+ }, -+ { -+ name: "NumericString (invalid)", -+ tag: cryptobyte_asn1.Tag(asn1.TagNumericString), -+ value: []byte{80}, -+ expectedErr: "invalid NumericString", -+ }, -+ } -+ -+ for _, tc := range tests { -+ t.Run(tc.name, func(t *testing.T) { -+ out, err := parseASN1String(tc.tag, tc.value) -+ if err != nil && err.Error() != tc.expectedErr { -+ t.Fatalf("parseASN1String returned unexpected error: got %q, want %q", err, tc.expectedErr) -+ } else if err == nil && tc.expectedErr != "" { -+ t.Fatalf("parseASN1String didn't fail, expected: %s", tc.expectedErr) -+ } -+ if out != tc.expected { -+ t.Fatalf("parseASN1String returned unexpected value: got %q, want %q", out, tc.expected) -+ } -+ }) -+ } -+} -diff --git a/src/crypto/x509/pem_decrypt.go-e b/src/crypto/x509/pem_decrypt.go-e -new file mode 100644 -index 0000000000..682923ac53 ---- /dev/null -+++ b/src/crypto/x509/pem_decrypt.go-e -@@ -0,0 +1,252 @@ -+// Copyright 2012 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. -+ -+package x509 -+ -+// RFC 1423 describes the encryption of PEM blocks. The algorithm used to -+// generate a key from the password was derived by looking at the OpenSSL -+// implementation. -+ -+import ( -+ "crypto/aes" -+ "crypto/cipher" -+ "crypto/des" -+ "crypto/md5" -+ "encoding/hex" -+ "encoding/pem" -+ "errors" -+ "io" -+ "strings" -+) -+ -+type PEMCipher int -+ -+// Possible values for the EncryptPEMBlock encryption algorithm. -+const ( -+ _ PEMCipher = iota -+ PEMCipherDES -+ PEMCipher3DES -+ PEMCipherAES128 -+ PEMCipherAES192 -+ PEMCipherAES256 -+) -+ -+// rfc1423Algo holds a method for enciphering a PEM block. -+type rfc1423Algo struct { -+ cipher PEMCipher -+ name string -+ cipherFunc func(key []byte) (cipher.Block, error) -+ keySize int -+ blockSize int -+} -+ -+// rfc1423Algos holds a slice of the possible ways to encrypt a PEM -+// block. The ivSize numbers were taken from the OpenSSL source. -+var rfc1423Algos = []rfc1423Algo{{ -+ cipher: PEMCipherDES, -+ name: "DES-CBC", -+ cipherFunc: des.NewCipher, -+ keySize: 8, -+ blockSize: des.BlockSize, -+}, { -+ cipher: PEMCipher3DES, -+ name: "DES-EDE3-CBC", -+ cipherFunc: des.NewTripleDESCipher, -+ keySize: 24, -+ blockSize: des.BlockSize, -+}, { -+ cipher: PEMCipherAES128, -+ name: "AES-128-CBC", -+ cipherFunc: aes.NewCipher, -+ keySize: 16, -+ blockSize: aes.BlockSize, -+}, { -+ cipher: PEMCipherAES192, -+ name: "AES-192-CBC", -+ cipherFunc: aes.NewCipher, -+ keySize: 24, -+ blockSize: aes.BlockSize, -+}, { -+ cipher: PEMCipherAES256, -+ name: "AES-256-CBC", -+ cipherFunc: aes.NewCipher, -+ keySize: 32, -+ blockSize: aes.BlockSize, -+}, -+} -+ -+// deriveKey uses a key derivation function to stretch the password into a key -+// with the number of bits our cipher requires. This algorithm was derived from -+// the OpenSSL source. -+func (c rfc1423Algo) deriveKey(password, salt []byte) []byte { -+ hash := md5.New() -+ out := make([]byte, c.keySize) -+ var digest []byte -+ -+ for i := 0; i < len(out); i += len(digest) { -+ hash.Reset() -+ hash.Write(digest) -+ hash.Write(password) -+ hash.Write(salt) -+ digest = hash.Sum(digest[:0]) -+ copy(out[i:], digest) -+ } -+ return out -+} -+ -+// IsEncryptedPEMBlock returns whether the PEM block is password encrypted -+// according to RFC 1423. -+// -+// Deprecated: Legacy PEM encryption as specified in RFC 1423 is insecure by -+// design. Since it does not authenticate the ciphertext, it is vulnerable to -+// padding oracle attacks that can let an attacker recover the plaintext. -+func IsEncryptedPEMBlock(b *pem.Block) bool { -+ _, ok := b.Headers["DEK-Info"] -+ return ok -+} -+ -+// IncorrectPasswordError is returned when an incorrect password is detected. -+var IncorrectPasswordError = errors.New("x509: decryption password incorrect") -+ -+// DecryptPEMBlock takes a PEM block encrypted according to RFC 1423 and the -+// password used to encrypt it and returns a slice of decrypted DER encoded -+// bytes. It inspects the DEK-Info header to determine the algorithm used for -+// decryption. If no DEK-Info header is present, an error is returned. If an -+// incorrect password is detected an IncorrectPasswordError is returned. Because -+// of deficiencies in the format, it's not always possible to detect an -+// incorrect password. In these cases no error will be returned but the -+// decrypted DER bytes will be random noise. -+// -+// Deprecated: Legacy PEM encryption as specified in RFC 1423 is insecure by -+// design. Since it does not authenticate the ciphertext, it is vulnerable to -+// padding oracle attacks that can let an attacker recover the plaintext. -+func DecryptPEMBlock(b *pem.Block, password []byte) ([]byte, error) { -+ dek, ok := b.Headers["DEK-Info"] -+ if !ok { -+ return nil, errors.New("x509: no DEK-Info header in block") -+ } -+ -+ mode, hexIV, ok := strings.Cut(dek, ",") -+ if !ok { -+ return nil, errors.New("x509: malformed DEK-Info header") -+ } -+ -+ ciph := cipherByName(mode) -+ if ciph == nil { -+ return nil, errors.New("x509: unknown encryption mode") -+ } -+ iv, err := hex.DecodeString(hexIV) -+ if err != nil { -+ return nil, err -+ } -+ if len(iv) != ciph.blockSize { -+ return nil, errors.New("x509: incorrect IV size") -+ } -+ -+ // Based on the OpenSSL implementation. The salt is the first 8 bytes -+ // of the initialization vector. -+ key := ciph.deriveKey(password, iv[:8]) -+ block, err := ciph.cipherFunc(key) -+ if err != nil { -+ return nil, err -+ } -+ -+ if len(b.Bytes)%block.BlockSize() != 0 { -+ return nil, errors.New("x509: encrypted PEM data is not a multiple of the block size") -+ } -+ -+ data := make([]byte, len(b.Bytes)) -+ dec := cipher.NewCBCDecrypter(block, iv) -+ dec.CryptBlocks(data, b.Bytes) -+ -+ // Blocks are padded using a scheme where the last n bytes of padding are all -+ // equal to n. It can pad from 1 to blocksize bytes inclusive. See RFC 1423. -+ // For example: -+ // [x y z 2 2] -+ // [x y 7 7 7 7 7 7 7] -+ // If we detect a bad padding, we assume it is an invalid password. -+ dlen := len(data) -+ if dlen == 0 || dlen%ciph.blockSize != 0 { -+ return nil, errors.New("x509: invalid padding") -+ } -+ last := int(data[dlen-1]) -+ if dlen < last { -+ return nil, IncorrectPasswordError -+ } -+ if last == 0 || last > ciph.blockSize { -+ return nil, IncorrectPasswordError -+ } -+ for _, val := range data[dlen-last:] { -+ if int(val) != last { -+ return nil, IncorrectPasswordError -+ } -+ } -+ return data[:dlen-last], nil -+} -+ -+// EncryptPEMBlock returns a PEM block of the specified type holding the -+// given DER encoded data encrypted with the specified algorithm and -+// password according to RFC 1423. -+// -+// Deprecated: Legacy PEM encryption as specified in RFC 1423 is insecure by -+// design. Since it does not authenticate the ciphertext, it is vulnerable to -+// padding oracle attacks that can let an attacker recover the plaintext. -+func EncryptPEMBlock(rand io.Reader, blockType string, data, password []byte, alg PEMCipher) (*pem.Block, error) { -+ ciph := cipherByKey(alg) -+ if ciph == nil { -+ return nil, errors.New("x509: unknown encryption mode") -+ } -+ iv := make([]byte, ciph.blockSize) -+ if _, err := io.ReadFull(rand, iv); err != nil { -+ return nil, errors.New("x509: cannot generate IV: " + err.Error()) -+ } -+ // The salt is the first 8 bytes of the initialization vector, -+ // matching the key derivation in DecryptPEMBlock. -+ key := ciph.deriveKey(password, iv[:8]) -+ block, err := ciph.cipherFunc(key) -+ if err != nil { -+ return nil, err -+ } -+ enc := cipher.NewCBCEncrypter(block, iv) -+ pad := ciph.blockSize - len(data)%ciph.blockSize -+ encrypted := make([]byte, len(data), len(data)+pad) -+ // We could save this copy by encrypting all the whole blocks in -+ // the data separately, but it doesn't seem worth the additional -+ // code. -+ copy(encrypted, data) -+ // See RFC 1423, Section 1.1. -+ for i := 0; i < pad; i++ { -+ encrypted = append(encrypted, byte(pad)) -+ } -+ enc.CryptBlocks(encrypted, encrypted) -+ -+ return &pem.Block{ -+ Type: blockType, -+ Headers: map[string]string{ -+ "Proc-Type": "4,ENCRYPTED", -+ "DEK-Info": ciph.name + "," + hex.EncodeToString(iv), -+ }, -+ Bytes: encrypted, -+ }, nil -+} -+ -+func cipherByName(name string) *rfc1423Algo { -+ for i := range rfc1423Algos { -+ alg := &rfc1423Algos[i] -+ if alg.name == name { -+ return alg -+ } -+ } -+ return nil -+} -+ -+func cipherByKey(key PEMCipher) *rfc1423Algo { -+ for i := range rfc1423Algos { -+ alg := &rfc1423Algos[i] -+ if alg.cipher == key { -+ return alg -+ } -+ } -+ return nil -+} -diff --git a/src/crypto/x509/pem_decrypt_test.go-e b/src/crypto/x509/pem_decrypt_test.go-e -new file mode 100644 -index 0000000000..dacef8b861 ---- /dev/null -+++ b/src/crypto/x509/pem_decrypt_test.go-e -@@ -0,0 +1,249 @@ -+// Copyright 2012 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. -+ -+package x509 -+ -+import ( -+ "bytes" -+ "crypto/rand" -+ "encoding/base64" -+ "encoding/pem" -+ "strings" -+ "testing" -+) -+ -+func TestDecrypt(t *testing.T) { -+ for i, data := range testData { -+ t.Logf("test %v. %v", i, data.kind) -+ block, rest := pem.Decode(data.pemData) -+ if len(rest) > 0 { -+ t.Error("extra data") -+ } -+ der, err := DecryptPEMBlock(block, data.password) -+ if err != nil { -+ t.Error("decrypt failed: ", err) -+ continue -+ } -+ if _, err := ParsePKCS1PrivateKey(der); err != nil { -+ t.Error("invalid private key: ", err) -+ } -+ plainDER, err := base64.StdEncoding.DecodeString(data.plainDER) -+ if err != nil { -+ t.Fatal("cannot decode test DER data: ", err) -+ } -+ if !bytes.Equal(der, plainDER) { -+ t.Error("data mismatch") -+ } -+ } -+} -+ -+func TestEncrypt(t *testing.T) { -+ for i, data := range testData { -+ t.Logf("test %v. %v", i, data.kind) -+ plainDER, err := base64.StdEncoding.DecodeString(data.plainDER) -+ if err != nil { -+ t.Fatal("cannot decode test DER data: ", err) -+ } -+ password := []byte("kremvax1") -+ block, err := EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", plainDER, password, data.kind) -+ if err != nil { -+ t.Error("encrypt: ", err) -+ continue -+ } -+ if !IsEncryptedPEMBlock(block) { -+ t.Error("PEM block does not appear to be encrypted") -+ } -+ if block.Type != "RSA PRIVATE KEY" { -+ t.Errorf("unexpected block type; got %q want %q", block.Type, "RSA PRIVATE KEY") -+ } -+ if block.Headers["Proc-Type"] != "4,ENCRYPTED" { -+ t.Errorf("block does not have correct Proc-Type header") -+ } -+ der, err := DecryptPEMBlock(block, password) -+ if err != nil { -+ t.Error("decrypt: ", err) -+ continue -+ } -+ if !bytes.Equal(der, plainDER) { -+ t.Errorf("data mismatch") -+ } -+ } -+} -+ -+var testData = []struct { -+ kind PEMCipher -+ password []byte -+ pemData []byte -+ plainDER string -+}{ -+ { -+ kind: PEMCipherDES, -+ password: []byte("asdf"), -+ pemData: []byte(testingKey(` -+-----BEGIN RSA TESTING KEY----- -+Proc-Type: 4,ENCRYPTED -+DEK-Info: DES-CBC,34F09A4FC8DE22B5 -+ -+WXxy8kbZdiZvANtKvhmPBLV7eVFj2A5z6oAxvI9KGyhG0ZK0skfnt00C24vfU7m5 -+ICXeoqP67lzJ18xCzQfHjDaBNs53DSDT+Iz4e8QUep1xQ30+8QKX2NA2coee3nwc -+6oM1cuvhNUDemBH2i3dKgMVkfaga0zQiiOq6HJyGSncCMSruQ7F9iWEfRbFcxFCx -+qtHb1kirfGKEtgWTF+ynyco6+2gMXNu70L7nJcnxnV/RLFkHt7AUU1yrclxz7eZz -+XOH9VfTjb52q/I8Suozq9coVQwg4tXfIoYUdT//O+mB7zJb9HI9Ps77b9TxDE6Gm -+4C9brwZ3zg2vqXcwwV6QRZMtyll9rOpxkbw6NPlpfBqkc3xS51bbxivbO/Nve4KD -+r12ymjFNF4stXCfJnNqKoZ50BHmEEUDu5Wb0fpVn82XrGw7CYc4iug== -+-----END RSA TESTING KEY-----`)), -+ plainDER: ` -+MIIBPAIBAAJBAPASZe+tCPU6p80AjHhDkVsLYa51D35e/YGa8QcZyooeZM8EHozo -+KD0fNiKI+53bHdy07N+81VQ8/ejPcRoXPlsCAwEAAQJBAMTxIuSq27VpR+zZ7WJf -+c6fvv1OBvpMZ0/d1pxL/KnOAgq2rD5hDtk9b0LGhTPgQAmrrMTKuSeGoIuYE+gKQ -+QvkCIQD+GC1m+/do+QRurr0uo46Kx1LzLeSCrjBk34wiOp2+dwIhAPHfTLRXS2fv -+7rljm0bYa4+eDZpz+E8RcXEgzhhvcQQ9AiAI5eHZJGOyml3MXnQjiPi55WcDOw0w -+glcRgT6QCEtz2wIhANSyqaFtosIkHKqrDUGfz/bb5tqMYTAnBruVPaf/WEOBAiEA -+9xORWeRG1tRpso4+dYy4KdDkuLPIO01KY6neYGm3BCM=`, -+ }, -+ { -+ kind: PEMCipher3DES, -+ password: []byte("asdf"), -+ pemData: []byte(testingKey(` -+-----BEGIN RSA TESTING KEY----- -+Proc-Type: 4,ENCRYPTED -+DEK-Info: DES-EDE3-CBC,C1F4A6A03682C2C7 -+ -+0JqVdBEH6iqM7drTkj+e2W/bE3LqakaiWhb9WUVonFkhyu8ca/QzebY3b5gCvAZQ -+YwBvDcT/GHospKqPx+cxDHJNsUASDZws6bz8ZXWJGwZGExKzr0+Qx5fgXn44Ms3x -+8g1ENFuTXtxo+KoNK0zuAMAqp66Llcds3Fjl4XR18QaD0CrVNAfOdgATWZm5GJxk -+Fgx5f84nT+/ovvreG+xeOzWgvtKo0UUZVrhGOgfKLpa57adumcJ6SkUuBtEFpZFB -+ldw5w7WC7d13x2LsRkwo8ZrDKgIV+Y9GNvhuCCkTzNP0V3gNeJpd201HZHR+9n3w -+3z0VjR/MGqsfcy1ziEWMNOO53At3zlG6zP05aHMnMcZoVXadEK6L1gz++inSSDCq -+gI0UJP4e3JVB7AkgYymYAwiYALAkoEIuanxoc50njJk= -+-----END RSA TESTING KEY-----`)), -+ plainDER: ` -+MIIBOwIBAAJBANOCXKdoNS/iP/MAbl9cf1/SF3P+Ns7ZeNL27CfmDh0O6Zduaax5 -+NBiumd2PmjkaCu7lQ5JOibHfWn+xJsc3kw0CAwEAAQJANX/W8d1Q/sCqzkuAn4xl -+B5a7qfJWaLHndu1QRLNTRJPn0Ee7OKJ4H0QKOhQM6vpjRrz+P2u9thn6wUxoPsef -+QQIhAP/jCkfejFcy4v15beqKzwz08/tslVjF+Yq41eJGejmxAiEA05pMoqfkyjcx -+fyvGhpoOyoCp71vSGUfR2I9CR65oKh0CIC1Msjs66LlfJtQctRq6bCEtFCxEcsP+ -+eEjYo/Sk6WphAiEAxpgWPMJeU/shFT28gS+tmhjPZLpEoT1qkVlC14u0b3ECIQDX -+tZZZxCtPAm7shftEib0VU77Lk8MsXJcx2C4voRsjEw==`, -+ }, -+ { -+ kind: PEMCipherAES128, -+ password: []byte("asdf"), -+ pemData: []byte(testingKey(` -+-----BEGIN RSA TESTING KEY----- -+Proc-Type: 4,ENCRYPTED -+DEK-Info: AES-128-CBC,D4492E793FC835CC038A728ED174F78A -+ -+EyfQSzXSjv6BaNH+NHdXRlkHdimpF9izWlugVJAPApgXrq5YldPe2aGIOFXyJ+QE -+ZIG20DYqaPzJRjTEbPNZ6Es0S2JJ5yCpKxwJuDkgJZKtF39Q2i36JeGbSZQIuWJE -+GZbBpf1jDH/pr0iGonuAdl2PCCZUiy+8eLsD2tyviHUkFLOB+ykYoJ5t8ngZ/B6D -+33U43LLb7+9zD4y3Q9OVHqBFGyHcxCY9+9Qh4ZnFp7DTf6RY5TNEvE3s4g6aDpBs -+3NbvRVvYTgs8K9EPk4K+5R+P2kD8J8KvEIGxVa1vz8QoCJ/jr7Ka2rvNgPCex5/E -+080LzLHPCrXKdlr/f50yhNWq08ZxMWQFkui+FDHPDUaEELKAXV8/5PDxw80Rtybo -+AVYoCVIbZXZCuCO81op8UcOgEpTtyU5Lgh3Mw5scQL0= -+-----END RSA TESTING KEY-----`)), -+ plainDER: ` -+MIIBOgIBAAJBAMBlj5FxYtqbcy8wY89d/S7n0+r5MzD9F63BA/Lpl78vQKtdJ5dT -+cDGh/rBt1ufRrNp0WihcmZi7Mpl/3jHjiWECAwEAAQJABNOHYnKhtDIqFYj1OAJ3 -+k3GlU0OlERmIOoeY/cL2V4lgwllPBEs7r134AY4wMmZSBUj8UR/O4SNO668ElKPE -+cQIhAOuqY7/115x5KCdGDMWi+jNaMxIvI4ETGwV40ykGzqlzAiEA0P9oEC3m9tHB -+kbpjSTxaNkrXxDgdEOZz8X0uOUUwHNsCIAwzcSCiGLyYJTULUmP1ESERfW1mlV78 -+XzzESaJpIM/zAiBQkSTcl9VhcJreQqvjn5BnPZLP4ZHS4gPwJAGdsj5J4QIhAOVR -+B3WlRNTXR2WsJ5JdByezg9xzdXzULqmga0OE339a`, -+ }, -+ { -+ kind: PEMCipherAES192, -+ password: []byte("asdf"), -+ pemData: []byte(testingKey(` -+-----BEGIN RSA TESTING KEY----- -+Proc-Type: 4,ENCRYPTED -+DEK-Info: AES-192-CBC,E2C9FB02BCA23ADE1829F8D8BC5F5369 -+ -+cqVslvHqDDM6qwU6YjezCRifXmKsrgEev7ng6Qs7UmDJOpHDgJQZI9fwMFUhIyn5 -+FbCu1SHkLMW52Ld3CuEqMnzWMlhPrW8tFvUOrMWPYSisv7nNq88HobZEJcUNL2MM -+Y15XmHW6IJwPqhKyLHpWXyOCVEh4ODND2nV15PCoi18oTa475baxSk7+1qH7GuIs -+Rb7tshNTMqHbCpyo9Rn3UxeFIf9efdl8YLiMoIqc7J8E5e9VlbeQSdLMQOgDAQJG -+ReUtTw8exmKsY4gsSjhkg5uiw7/ZB1Ihto0qnfQJgjGc680qGkT1d6JfvOfeYAk6 -+xn5RqS/h8rYAYm64KnepfC9vIujo4NqpaREDmaLdX5MJPQ+SlytITQvgUsUq3q/t -+Ss85xjQEZH3hzwjQqdJvmA4hYP6SUjxYpBM+02xZ1Xw= -+-----END RSA TESTING KEY-----`)), -+ plainDER: ` -+MIIBOwIBAAJBAMGcRrZiNNmtF20zyS6MQ7pdGx17aFDl+lTl+qnLuJRUCMUG05xs -+OmxmL/O1Qlf+bnqR8Bgg65SfKg21SYuLhiMCAwEAAQJBAL94uuHyO4wux2VC+qpj -+IzPykjdU7XRcDHbbvksf4xokSeUFjjD3PB0Qa83M94y89ZfdILIqS9x5EgSB4/lX -+qNkCIQD6cCIqLfzq/lYbZbQgAAjpBXeQVYsbvVtJrPrXJAlVVQIhAMXpDKMeFPMn -+J0g2rbx1gngx0qOa5r5iMU5w/noN4W2XAiBjf+WzCG5yFvazD+dOx3TC0A8+4x3P -+uZ3pWbaXf5PNuQIgAcdXarvhelH2w2piY1g3BPeFqhzBSCK/yLGxR82KIh8CIQDD -++qGKsd09NhQ/G27y/DARzOYtml1NvdmCQAgsDIIOLA==`, -+ }, -+ { -+ kind: PEMCipherAES256, -+ password: []byte("asdf"), -+ pemData: []byte(testingKey(` -+-----BEGIN RSA TESTING KEY----- -+Proc-Type: 4,ENCRYPTED -+DEK-Info: AES-256-CBC,8E7ED5CD731902CE938957A886A5FFBD -+ -+4Mxr+KIzRVwoOP0wwq6caSkvW0iS+GE2h2Ov/u+n9ZTMwL83PRnmjfjzBgfRZLVf -+JFPXxUK26kMNpIdssNnqGOds+DhB+oSrsNKoxgxSl5OBoYv9eJTVYm7qOyAFIsjr -+DRKAcjYCmzfesr7PVTowwy0RtHmYwyXMGDlAzzZrEvaiySFFmMyKKvtoavwaFoc7 -+Pz3RZScwIuubzTGJ1x8EzdffYOsdCa9Mtgpp3L136+23dOd6L/qK2EG2fzrJSHs/ -+2XugkleBFSMKzEp9mxXKRfa++uidQvMZTFLDK9w5YjrRvMBo/l2BoZIsq0jAIE1N -+sv5Z/KwlX+3MDEpPQpUwGPlGGdLnjI3UZ+cjgqBcoMiNc6HfgbBgYJSU6aDSHuCk -+clCwByxWkBNgJ2GrkwNrF26v+bGJJJNR4SKouY1jQf0= -+-----END RSA TESTING KEY-----`)), -+ plainDER: ` -+MIIBOgIBAAJBAKy3GFkstoCHIEeUU/qO8207m8WSrjksR+p9B4tf1w5k+2O1V/GY -+AQ5WFCApItcOkQe/I0yZZJk/PmCqMzSxrc8CAwEAAQJAOCAz0F7AW9oNelVQSP8F -+Sfzx7O1yom+qWyAQQJF/gFR11gpf9xpVnnyu1WxIRnDUh1LZwUsjwlDYb7MB74id -+oQIhANPcOiLwOPT4sIUpRM5HG6BF1BI7L77VpyGVk8xNP7X/AiEA0LMHZtk4I+lJ -+nClgYp4Yh2JZ1Znbu7IoQMCEJCjwKDECIGd8Dzm5tViTkUW6Hs3Tlf73nNs65duF -+aRnSglss8I3pAiEAonEnKruawgD8RavDFR+fUgmQiPz4FnGGeVgfwpGG1JECIBYq -+PXHYtPqxQIbD2pScR5qum7iGUh11lEUPkmt+2uqS`, -+ }, -+ { -+ // generated with: -+ // openssl genrsa -aes128 -passout pass:asdf -out server.orig.key 128 -+ kind: PEMCipherAES128, -+ password: []byte("asdf"), -+ pemData: []byte(testingKey(` -+-----BEGIN RSA TESTING KEY----- -+Proc-Type: 4,ENCRYPTED -+DEK-Info: AES-128-CBC,74611ABC2571AF11B1BF9B69E62C89E7 -+ -+6ei/MlytjE0FFgZOGQ+jrwomKfpl8kdefeE0NSt/DMRrw8OacHAzBNi3pPEa0eX3 -+eND9l7C9meCirWovjj9QWVHrXyugFuDIqgdhQ8iHTgCfF3lrmcttVrbIfMDw+smD -+hTP8O1mS/MHl92NE0nhv0w== -+-----END RSA TESTING KEY-----`)), -+ plainDER: ` -+MGMCAQACEQC6ssxmYuauuHGOCDAI54RdAgMBAAECEQCWIn6Yv2O+kBcDF7STctKB -+AgkA8SEfu/2i3g0CCQDGNlXbBHX7kQIIK3Ww5o0cYbECCQDCimPb0dYGsQIIeQ7A -+jryIst8=`, -+ }, -+} -+ -+var incompleteBlockPEM = testingKey(` -+-----BEGIN RSA TESTING KEY----- -+Proc-Type: 4,ENCRYPTED -+DEK-Info: AES-128-CBC,74611ABC2571AF11B1BF9B69E62C89E7 -+ -+6L8yXK2MTQUWBk4ZD6OvCiYp+mXyR1594TQ1K38MxGvDw5pwcDME2Lek8RrR5fd40P2XsL2Z4KKt -+ai+OP1BZUetfK6AW4MiqB2FDyIdOAJ8XeWuZy21Wtsh8wPD6yYOFM/w7WZL8weX3Y0TSeG/T -+-----END RSA TESTING KEY-----`) -+ -+func TestIncompleteBlock(t *testing.T) { -+ // incompleteBlockPEM contains ciphertext that is not a multiple of the -+ // block size. This previously panicked. See #11215. -+ block, _ := pem.Decode([]byte(incompleteBlockPEM)) -+ _, err := DecryptPEMBlock(block, []byte("foo")) -+ if err == nil { -+ t.Fatal("Bad PEM data decrypted successfully") -+ } -+ const expectedSubstr = "block size" -+ if e := err.Error(); !strings.Contains(e, expectedSubstr) { -+ t.Fatalf("Expected error containing %q but got: %q", expectedSubstr, e) -+ } -+} -+ -+func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") } -diff --git a/src/crypto/x509/pkcs1.go-e b/src/crypto/x509/pkcs1.go-e -new file mode 100644 -index 0000000000..f9d384018a ---- /dev/null -+++ b/src/crypto/x509/pkcs1.go-e -@@ -0,0 +1,173 @@ -+// Copyright 2011 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. -+ -+package x509 -+ -+import ( -+ "crypto/rsa" -+ "encoding/asn1" -+ "errors" -+ "math/big" -+) -+ -+// pkcs1PrivateKey is a structure which mirrors the PKCS #1 ASN.1 for an RSA private key. -+type pkcs1PrivateKey struct { -+ Version int -+ N *big.Int -+ E int -+ D *big.Int -+ P *big.Int -+ Q *big.Int -+ // We ignore these values, if present, because rsa will calculate them. -+ Dp *big.Int `asn1:"optional"` -+ Dq *big.Int `asn1:"optional"` -+ Qinv *big.Int `asn1:"optional"` -+ -+ AdditionalPrimes []pkcs1AdditionalRSAPrime `asn1:"optional,omitempty"` -+} -+ -+type pkcs1AdditionalRSAPrime struct { -+ Prime *big.Int -+ -+ // We ignore these values because rsa will calculate them. -+ Exp *big.Int -+ Coeff *big.Int -+} -+ -+// pkcs1PublicKey reflects the ASN.1 structure of a PKCS #1 public key. -+type pkcs1PublicKey struct { -+ N *big.Int -+ E int -+} -+ -+// ParsePKCS1PrivateKey parses an RSA private key in PKCS #1, ASN.1 DER form. -+// -+// This kind of key is commonly encoded in PEM blocks of type "RSA PRIVATE KEY". -+func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) { -+ var priv pkcs1PrivateKey -+ rest, err := asn1.Unmarshal(der, &priv) -+ if len(rest) > 0 { -+ return nil, asn1.SyntaxError{Msg: "trailing data"} -+ } -+ if err != nil { -+ if _, err := asn1.Unmarshal(der, &ecPrivateKey{}); err == nil { -+ return nil, errors.New("x509: failed to parse private key (use ParseECPrivateKey instead for this key format)") -+ } -+ if _, err := asn1.Unmarshal(der, &pkcs8{}); err == nil { -+ return nil, errors.New("x509: failed to parse private key (use ParsePKCS8PrivateKey instead for this key format)") -+ } -+ return nil, err -+ } -+ -+ if priv.Version > 1 { -+ return nil, errors.New("x509: unsupported private key version") -+ } -+ -+ if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 { -+ return nil, errors.New("x509: private key contains zero or negative value") -+ } -+ -+ key := new(rsa.PrivateKey) -+ key.PublicKey = rsa.PublicKey{ -+ E: priv.E, -+ N: priv.N, -+ } -+ -+ key.D = priv.D -+ key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes)) -+ key.Primes[0] = priv.P -+ key.Primes[1] = priv.Q -+ for i, a := range priv.AdditionalPrimes { -+ if a.Prime.Sign() <= 0 { -+ return nil, errors.New("x509: private key contains zero or negative prime") -+ } -+ key.Primes[i+2] = a.Prime -+ // We ignore the other two values because rsa will calculate -+ // them as needed. -+ } -+ -+ err = key.Validate() -+ if err != nil { -+ return nil, err -+ } -+ key.Precompute() -+ -+ return key, nil -+} -+ -+// MarshalPKCS1PrivateKey converts an RSA private key to PKCS #1, ASN.1 DER form. -+// -+// This kind of key is commonly encoded in PEM blocks of type "RSA PRIVATE KEY". -+// For a more flexible key format which is not RSA specific, use -+// MarshalPKCS8PrivateKey. -+func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte { -+ key.Precompute() -+ -+ version := 0 -+ if len(key.Primes) > 2 { -+ version = 1 -+ } -+ -+ priv := pkcs1PrivateKey{ -+ Version: version, -+ N: key.N, -+ E: key.PublicKey.E, -+ D: key.D, -+ P: key.Primes[0], -+ Q: key.Primes[1], -+ Dp: key.Precomputed.Dp, -+ Dq: key.Precomputed.Dq, -+ Qinv: key.Precomputed.Qinv, -+ } -+ -+ priv.AdditionalPrimes = make([]pkcs1AdditionalRSAPrime, len(key.Precomputed.CRTValues)) -+ for i, values := range key.Precomputed.CRTValues { -+ priv.AdditionalPrimes[i].Prime = key.Primes[2+i] -+ priv.AdditionalPrimes[i].Exp = values.Exp -+ priv.AdditionalPrimes[i].Coeff = values.Coeff -+ } -+ -+ b, _ := asn1.Marshal(priv) -+ return b -+} -+ -+// ParsePKCS1PublicKey parses an RSA public key in PKCS #1, ASN.1 DER form. -+// -+// This kind of key is commonly encoded in PEM blocks of type "RSA PUBLIC KEY". -+func ParsePKCS1PublicKey(der []byte) (*rsa.PublicKey, error) { -+ var pub pkcs1PublicKey -+ rest, err := asn1.Unmarshal(der, &pub) -+ if err != nil { -+ if _, err := asn1.Unmarshal(der, &publicKeyInfo{}); err == nil { -+ return nil, errors.New("x509: failed to parse public key (use ParsePKIXPublicKey instead for this key format)") -+ } -+ return nil, err -+ } -+ if len(rest) > 0 { -+ return nil, asn1.SyntaxError{Msg: "trailing data"} -+ } -+ -+ if pub.N.Sign() <= 0 || pub.E <= 0 { -+ return nil, errors.New("x509: public key contains zero or negative value") -+ } -+ if pub.E > 1<<31-1 { -+ return nil, errors.New("x509: public key contains large public exponent") -+ } -+ -+ return &rsa.PublicKey{ -+ E: pub.E, -+ N: pub.N, -+ }, nil -+} -+ -+// MarshalPKCS1PublicKey converts an RSA public key to PKCS #1, ASN.1 DER form. -+// -+// This kind of key is commonly encoded in PEM blocks of type "RSA PUBLIC KEY". -+func MarshalPKCS1PublicKey(key *rsa.PublicKey) []byte { -+ derBytes, _ := asn1.Marshal(pkcs1PublicKey{ -+ N: key.N, -+ E: key.E, -+ }) -+ return derBytes -+} -diff --git a/src/crypto/x509/pkcs8.go-e b/src/crypto/x509/pkcs8.go-e -new file mode 100644 -index 0000000000..74b2f99708 ---- /dev/null -+++ b/src/crypto/x509/pkcs8.go-e -@@ -0,0 +1,175 @@ -+// Copyright 2011 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. -+ -+package x509 -+ -+import ( -+ "crypto/ecdh" -+ "crypto/ecdsa" -+ "crypto/ed25519" -+ "crypto/rsa" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+ "errors" -+ "fmt" -+) -+ -+// pkcs8 reflects an ASN.1, PKCS #8 PrivateKey. See -+// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-8/pkcs-8v1_2.asn -+// and RFC 5208. -+type pkcs8 struct { -+ Version int -+ Algo pkix.AlgorithmIdentifier -+ PrivateKey []byte -+ // optional attributes omitted. -+} -+ -+// ParsePKCS8PrivateKey parses an unencrypted private key in PKCS #8, ASN.1 DER form. -+// -+// It returns a *rsa.PrivateKey, an *ecdsa.PrivateKey, an ed25519.PrivateKey (not -+// a pointer), or an *ecdh.PrivateKey (for X25519). More types might be supported -+// in the future. -+// -+// This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY". -+func ParsePKCS8PrivateKey(der []byte) (key any, err error) { -+ var privKey pkcs8 -+ if _, err := asn1.Unmarshal(der, &privKey); err != nil { -+ if _, err := asn1.Unmarshal(der, &ecPrivateKey{}); err == nil { -+ return nil, errors.New("x509: failed to parse private key (use ParseECPrivateKey instead for this key format)") -+ } -+ if _, err := asn1.Unmarshal(der, &pkcs1PrivateKey{}); err == nil { -+ return nil, errors.New("x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)") -+ } -+ return nil, err -+ } -+ switch { -+ case privKey.Algo.Algorithm.Equal(oidPublicKeyRSA): -+ key, err = ParsePKCS1PrivateKey(privKey.PrivateKey) -+ if err != nil { -+ return nil, errors.New("x509: failed to parse RSA private key embedded in PKCS#8: " + err.Error()) -+ } -+ return key, nil -+ -+ case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA): -+ bytes := privKey.Algo.Parameters.FullBytes -+ namedCurveOID := new(asn1.ObjectIdentifier) -+ if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil { -+ namedCurveOID = nil -+ } -+ key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey) -+ if err != nil { -+ return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error()) -+ } -+ return key, nil -+ -+ case privKey.Algo.Algorithm.Equal(oidPublicKeyEd25519): -+ if l := len(privKey.Algo.Parameters.FullBytes); l != 0 { -+ return nil, errors.New("x509: invalid Ed25519 private key parameters") -+ } -+ var curvePrivateKey []byte -+ if _, err := asn1.Unmarshal(privKey.PrivateKey, &curvePrivateKey); err != nil { -+ return nil, fmt.Errorf("x509: invalid Ed25519 private key: %v", err) -+ } -+ if l := len(curvePrivateKey); l != ed25519.SeedSize { -+ return nil, fmt.Errorf("x509: invalid Ed25519 private key length: %d", l) -+ } -+ return ed25519.NewKeyFromSeed(curvePrivateKey), nil -+ -+ case privKey.Algo.Algorithm.Equal(oidPublicKeyX25519): -+ if l := len(privKey.Algo.Parameters.FullBytes); l != 0 { -+ return nil, errors.New("x509: invalid X25519 private key parameters") -+ } -+ var curvePrivateKey []byte -+ if _, err := asn1.Unmarshal(privKey.PrivateKey, &curvePrivateKey); err != nil { -+ return nil, fmt.Errorf("x509: invalid X25519 private key: %v", err) -+ } -+ return ecdh.X25519().NewPrivateKey(curvePrivateKey) -+ -+ default: -+ return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm) -+ } -+} -+ -+// MarshalPKCS8PrivateKey converts a private key to PKCS #8, ASN.1 DER form. -+// -+// The following key types are currently supported: *rsa.PrivateKey, -+// *ecdsa.PrivateKey, ed25519.PrivateKey (not a pointer), and *ecdh.PrivateKey. -+// Unsupported key types result in an error. -+// -+// This kind of key is commonly encoded in PEM blocks of type "PRIVATE KEY". -+func MarshalPKCS8PrivateKey(key any) ([]byte, error) { -+ var privKey pkcs8 -+ -+ switch k := key.(type) { -+ case *rsa.PrivateKey: -+ privKey.Algo = pkix.AlgorithmIdentifier{ -+ Algorithm: oidPublicKeyRSA, -+ Parameters: asn1.NullRawValue, -+ } -+ privKey.PrivateKey = MarshalPKCS1PrivateKey(k) -+ -+ case *ecdsa.PrivateKey: -+ oid, ok := oidFromNamedCurve(k.Curve) -+ if !ok { -+ return nil, errors.New("x509: unknown curve while marshaling to PKCS#8") -+ } -+ oidBytes, err := asn1.Marshal(oid) -+ if err != nil { -+ return nil, errors.New("x509: failed to marshal curve OID: " + err.Error()) -+ } -+ privKey.Algo = pkix.AlgorithmIdentifier{ -+ Algorithm: oidPublicKeyECDSA, -+ Parameters: asn1.RawValue{ -+ FullBytes: oidBytes, -+ }, -+ } -+ if privKey.PrivateKey, err = marshalECPrivateKeyWithOID(k, nil); err != nil { -+ return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error()) -+ } -+ -+ case ed25519.PrivateKey: -+ privKey.Algo = pkix.AlgorithmIdentifier{ -+ Algorithm: oidPublicKeyEd25519, -+ } -+ curvePrivateKey, err := asn1.Marshal(k.Seed()) -+ if err != nil { -+ return nil, fmt.Errorf("x509: failed to marshal private key: %v", err) -+ } -+ privKey.PrivateKey = curvePrivateKey -+ -+ case *ecdh.PrivateKey: -+ if k.Curve() == ecdh.X25519() { -+ privKey.Algo = pkix.AlgorithmIdentifier{ -+ Algorithm: oidPublicKeyX25519, -+ } -+ var err error -+ if privKey.PrivateKey, err = asn1.Marshal(k.Bytes()); err != nil { -+ return nil, fmt.Errorf("x509: failed to marshal private key: %v", err) -+ } -+ } else { -+ oid, ok := oidFromECDHCurve(k.Curve()) -+ if !ok { -+ return nil, errors.New("x509: unknown curve while marshaling to PKCS#8") -+ } -+ oidBytes, err := asn1.Marshal(oid) -+ if err != nil { -+ return nil, errors.New("x509: failed to marshal curve OID: " + err.Error()) -+ } -+ privKey.Algo = pkix.AlgorithmIdentifier{ -+ Algorithm: oidPublicKeyECDSA, -+ Parameters: asn1.RawValue{ -+ FullBytes: oidBytes, -+ }, -+ } -+ if privKey.PrivateKey, err = marshalECDHPrivateKey(k); err != nil { -+ return nil, errors.New("x509: failed to marshal EC private key while building PKCS#8: " + err.Error()) -+ } -+ } -+ -+ default: -+ return nil, fmt.Errorf("x509: unknown key type while marshaling PKCS#8: %T", key) -+ } -+ -+ return asn1.Marshal(privKey) -+} -diff --git a/src/crypto/x509/pkcs8_test.go-e b/src/crypto/x509/pkcs8_test.go-e -new file mode 100644 -index 0000000000..d0328800bc ---- /dev/null -+++ b/src/crypto/x509/pkcs8_test.go-e -@@ -0,0 +1,175 @@ -+// Copyright 2011 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. -+ -+package x509 -+ -+import ( -+ "bytes" -+ "crypto/ecdh" -+ "crypto/ecdsa" -+ "crypto/ed25519" -+ "crypto/elliptic" -+ "crypto/rsa" -+ "encoding/hex" -+ "reflect" -+ "strings" -+ "testing" -+) -+ -+// Generated using: -+// -+// openssl genrsa 1024 | openssl pkcs8 -topk8 -nocrypt -+var pkcs8RSAPrivateKeyHex = `30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100cfb1b5bf9685ffa97b4f99df4ff122b70e59ac9b992f3bc2b3dde17d53c1a34928719b02e8fd17839499bfbd515bd6ef99c7a1c47a239718fe36bfd824c0d96060084b5f67f0273443007a24dfaf5634f7772c9346e10eb294c2306671a5a5e719ae24b4de467291bc571014b0e02dec04534d66a9bb171d644b66b091780e8d020301000102818100b595778383c4afdbab95d2bfed12b3f93bb0a73a7ad952f44d7185fd9ec6c34de8f03a48770f2009c8580bcd275e9632714e9a5e3f32f29dc55474b2329ff0ebc08b3ffcb35bc96e6516b483df80a4a59cceb71918cbabf91564e64a39d7e35dce21cb3031824fdbc845dba6458852ec16af5dddf51a8397a8797ae0337b1439024100ea0eb1b914158c70db39031dd8904d6f18f408c85fbbc592d7d20dee7986969efbda081fdf8bc40e1b1336d6b638110c836bfdc3f314560d2e49cd4fbde1e20b024100e32a4e793b574c9c4a94c8803db5152141e72d03de64e54ef2c8ed104988ca780cd11397bc359630d01b97ebd87067c5451ba777cf045ca23f5912f1031308c702406dfcdbbd5a57c9f85abc4edf9e9e29153507b07ce0a7ef6f52e60dcfebe1b8341babd8b789a837485da6c8d55b29bbb142ace3c24a1f5b54b454d01b51e2ad03024100bd6a2b60dee01e1b3bfcef6a2f09ed027c273cdbbaf6ba55a80f6dcc64e4509ee560f84b4f3e076bd03b11e42fe71a3fdd2dffe7e0902c8584f8cad877cdc945024100aa512fa4ada69881f1d8bb8ad6614f192b83200aef5edf4811313d5ef30a86cbd0a90f7b025c71ea06ec6b34db6306c86b1040670fd8654ad7291d066d06d031` -+ -+// Generated using: -+// -+// openssl ecparam -genkey -name secp224r1 | openssl pkcs8 -topk8 -nocrypt -+var pkcs8P224PrivateKeyHex = `3078020100301006072a8648ce3d020106052b810400210461305f020101041cca3d72b3e88fed2684576dad9b80a9180363a5424986900e3abcab3fa13c033a0004f8f2a6372872a4e61263ed893afb919576a4cacfecd6c081a2cbc76873cf4ba8530703c6042b3a00e2205087e87d2435d2e339e25702fae1` -+ -+// Generated using: -+// -+// openssl ecparam -genkey -name secp256r1 | openssl pkcs8 -topk8 -nocrypt -+var pkcs8P256PrivateKeyHex = `308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b0201010420dad6b2f49ca774c36d8ae9517e935226f667c929498f0343d2424d0b9b591b43a14403420004b9c9b90095476afe7b860d8bd43568cab7bcb2eed7b8bf2fa0ce1762dd20b04193f859d2d782b1e4cbfd48492f1f533113a6804903f292258513837f07fda735` -+ -+// Generated using: -+// -+// openssl ecparam -genkey -name secp384r1 | openssl pkcs8 -topk8 -nocrypt -+var pkcs8P384PrivateKeyHex = `3081b6020100301006072a8648ce3d020106052b8104002204819e30819b02010104309bf832f6aaaeacb78ce47ffb15e6fd0fd48683ae79df6eca39bfb8e33829ac94aa29d08911568684c2264a08a4ceb679a164036200049070ad4ed993c7770d700e9f6dc2baa83f63dd165b5507f98e8ff29b5d2e78ccbe05c8ddc955dbf0f7497e8222cfa49314fe4e269459f8e880147f70d785e530f2939e4bf9f838325bb1a80ad4cf59272ae0e5efe9a9dc33d874492596304bd3` -+ -+// Generated using: -+// -+// openssl ecparam -genkey -name secp521r1 | openssl pkcs8 -topk8 -nocrypt -+// -+// Note that OpenSSL will truncate the private key if it can (i.e. it emits it -+// like an integer, even though it's an OCTET STRING field). Thus if you -+// regenerate this you may, randomly, find that it's a byte shorter than -+// expected and the Go test will fail to recreate it exactly. -+var pkcs8P521PrivateKeyHex = `3081ee020100301006072a8648ce3d020106052b810400230481d63081d3020101044200cfe0b87113a205cf291bb9a8cd1a74ac6c7b2ebb8199aaa9a5010d8b8012276fa3c22ac913369fa61beec2a3b8b4516bc049bde4fb3b745ac11b56ab23ac52e361a1818903818600040138f75acdd03fbafa4f047a8e4b272ba9d555c667962b76f6f232911a5786a0964e5edea6bd21a6f8725720958de049c6e3e6661c1c91b227cebee916c0319ed6ca003db0a3206d372229baf9dd25d868bf81140a518114803ce40c1855074d68c4e9dab9e65efba7064c703b400f1767f217dac82715ac1f6d88c74baf47a7971de4ea` -+ -+// From RFC 8410, Section 7. -+var pkcs8Ed25519PrivateKeyHex = `302e020100300506032b657004220420d4ee72dbf913584ad5b6d8f1f769f8ad3afe7c28cbf1d4fbe097a88f44755842` -+ -+// Generated using: -+// -+// openssl genpkey -algorithm x25519 -+var pkcs8X25519PrivateKeyHex = `302e020100300506032b656e0422042068ff93a73c5adefd6d498b24e588fd4daa10924d992afed01b43ca5725025a6b` -+ -+func TestPKCS8(t *testing.T) { -+ tests := []struct { -+ name string -+ keyHex string -+ keyType reflect.Type -+ curve elliptic.Curve -+ }{ -+ { -+ name: "RSA private key", -+ keyHex: pkcs8RSAPrivateKeyHex, -+ keyType: reflect.TypeOf(&rsa.PrivateKey{}), -+ }, -+ { -+ name: "P-224 private key", -+ keyHex: pkcs8P224PrivateKeyHex, -+ keyType: reflect.TypeOf(&ecdsa.PrivateKey{}), -+ curve: elliptic.P224(), -+ }, -+ { -+ name: "P-256 private key", -+ keyHex: pkcs8P256PrivateKeyHex, -+ keyType: reflect.TypeOf(&ecdsa.PrivateKey{}), -+ curve: elliptic.P256(), -+ }, -+ { -+ name: "P-384 private key", -+ keyHex: pkcs8P384PrivateKeyHex, -+ keyType: reflect.TypeOf(&ecdsa.PrivateKey{}), -+ curve: elliptic.P384(), -+ }, -+ { -+ name: "P-521 private key", -+ keyHex: pkcs8P521PrivateKeyHex, -+ keyType: reflect.TypeOf(&ecdsa.PrivateKey{}), -+ curve: elliptic.P521(), -+ }, -+ { -+ name: "Ed25519 private key", -+ keyHex: pkcs8Ed25519PrivateKeyHex, -+ keyType: reflect.TypeOf(ed25519.PrivateKey{}), -+ }, -+ { -+ name: "X25519 private key", -+ keyHex: pkcs8X25519PrivateKeyHex, -+ keyType: reflect.TypeOf(&ecdh.PrivateKey{}), -+ }, -+ } -+ -+ for _, test := range tests { -+ derBytes, err := hex.DecodeString(test.keyHex) -+ if err != nil { -+ t.Errorf("%s: failed to decode hex: %s", test.name, err) -+ continue -+ } -+ privKey, err := ParsePKCS8PrivateKey(derBytes) -+ if err != nil { -+ t.Errorf("%s: failed to decode PKCS#8: %s", test.name, err) -+ continue -+ } -+ if reflect.TypeOf(privKey) != test.keyType { -+ t.Errorf("%s: decoded PKCS#8 returned unexpected key type: %T", test.name, privKey) -+ continue -+ } -+ if ecKey, isEC := privKey.(*ecdsa.PrivateKey); isEC && ecKey.Curve != test.curve { -+ t.Errorf("%s: decoded PKCS#8 returned unexpected curve %#v", test.name, ecKey.Curve) -+ continue -+ } -+ reserialised, err := MarshalPKCS8PrivateKey(privKey) -+ if err != nil { -+ t.Errorf("%s: failed to marshal into PKCS#8: %s", test.name, err) -+ continue -+ } -+ if !bytes.Equal(derBytes, reserialised) { -+ t.Errorf("%s: marshaled PKCS#8 didn't match original: got %x, want %x", test.name, reserialised, derBytes) -+ continue -+ } -+ -+ if ecKey, isEC := privKey.(*ecdsa.PrivateKey); isEC { -+ ecdhKey, err := ecKey.ECDH() -+ if err != nil { -+ if ecKey.Curve != elliptic.P224() { -+ t.Errorf("%s: failed to convert to ecdh: %s", test.name, err) -+ } -+ continue -+ } -+ reserialised, err := MarshalPKCS8PrivateKey(ecdhKey) -+ if err != nil { -+ t.Errorf("%s: failed to marshal into PKCS#8: %s", test.name, err) -+ continue -+ } -+ if !bytes.Equal(derBytes, reserialised) { -+ t.Errorf("%s: marshaled PKCS#8 didn't match original: got %x, want %x", test.name, reserialised, derBytes) -+ continue -+ } -+ } -+ } -+} -+ -+const hexPKCS8TestPKCS1Key = "3082025c02010002818100b1a1e0945b9289c4d3f1329f8a982c4a2dcd59bfd372fb8085a9c517554607ebd2f7990eef216ac9f4605f71a03b04f42a5255b158cf8e0844191f5119348baa44c35056e20609bcf9510f30ead4b481c81d7865fb27b8e0090e112b717f3ee08cdfc4012da1f1f7cf2a1bc34c73a54a12b06372d09714742dd7895eadde4aa5020301000102818062b7fa1db93e993e40237de4d89b7591cc1ea1d04fed4904c643f17ae4334557b4295270d0491c161cb02a9af557978b32b20b59c267a721c4e6c956c2d147046e9ae5f2da36db0106d70021fa9343455f8f973a4b355a26fd19e6b39dee0405ea2b32deddf0f4817759ef705d02b34faab9ca93c6766e9f722290f119f34449024100d9c29a4a013a90e35fd1be14a3f747c589fac613a695282d61812a711906b8a0876c6181f0333ca1066596f57bff47e7cfcabf19c0fc69d9cd76df743038b3cb024100d0d3546fecf879b5551f2bd2c05e6385f2718a08a6face3d2aecc9d7e03645a480a46c81662c12ad6bd6901e3bd4f38029462de7290859567cdf371c79088d4f024100c254150657e460ea58573fcf01a82a4791e3d6223135c8bdfed69afe84fbe7857274f8eb5165180507455f9b4105c6b08b51fe8a481bb986a202245576b713530240045700003b7a867d0041df9547ae2e7f50248febd21c9040b12dae9c2feab0d3d4609668b208e4727a3541557f84d372ac68eaf74ce1018a4c9a0ef92682c8fd02405769731480bb3a4570abf422527c5f34bf732fa6c1e08cc322753c511ce055fac20fc770025663ad3165324314df907f1f1942f0448a7e9cdbf87ecd98b92156" -+const hexPKCS8TestECKey = "3081a40201010430bdb9839c08ee793d1157886a7a758a3c8b2a17a4df48f17ace57c72c56b4723cf21dcda21d4e1ad57ff034f19fcfd98ea00706052b81040022a16403620004feea808b5ee2429cfcce13c32160e1c960990bd050bb0fdf7222f3decd0a55008e32a6aa3c9062051c4cba92a7a3b178b24567412d43cdd2f882fa5addddd726fe3e208d2c26d733a773a597abb749714df7256ead5105fa6e7b3650de236b50" -+ -+var pkcs8MismatchKeyTests = []struct { -+ hexKey string -+ errorContains string -+}{ -+ {hexKey: hexPKCS8TestECKey, errorContains: "use ParseECPrivateKey instead"}, -+ {hexKey: hexPKCS8TestPKCS1Key, errorContains: "use ParsePKCS1PrivateKey instead"}, -+} -+ -+func TestPKCS8MismatchKeyFormat(t *testing.T) { -+ for i, test := range pkcs8MismatchKeyTests { -+ derBytes, _ := hex.DecodeString(test.hexKey) -+ _, err := ParsePKCS8PrivateKey(derBytes) -+ if !strings.Contains(err.Error(), test.errorContains) { -+ t.Errorf("#%d: expected error containing %q, got %s", i, test.errorContains, err) -+ } -+ } -+} -diff --git a/src/crypto/x509/platform_test.go-e b/src/crypto/x509/platform_test.go-e -new file mode 100644 -index 0000000000..c35f0b448e ---- /dev/null -+++ b/src/crypto/x509/platform_test.go-e -@@ -0,0 +1,251 @@ -+// Copyright 2023 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. -+ -+package x509 -+ -+//go:generate go run gen_testing_root.go -+ -+import ( -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "encoding/pem" -+ "math/big" -+ "os" -+ "runtime" -+ "strings" -+ "testing" -+ "time" -+) -+ -+// In order to run this test suite locally, you need to insert the test root, at -+// the path below, into your trust store. This root is constrained such that it -+// should not be dangerous to local developers to trust, but care should be -+// taken when inserting it into the trust store not to give it increased -+// permissions. -+// -+// On macOS the certificate can be further constrained to only be valid for -+// 'SSL' in the certificate properties pane of the 'Keychain Access' program. -+// -+// On Windows the certificate can also be constrained to only server -+// authentication in the properties pane of the certificate in the -+// "Certificates" snap-in of mmc.exe. -+ -+const ( -+ rootCertPath = "platform_root_cert.pem" -+ rootKeyPath = "platform_root_key.pem" -+) -+ -+func TestPlatformVerifier(t *testing.T) { -+ if runtime.GOOS != "windows" && runtime.GOOS != "darwin" { -+ t.Skip("only tested on windows and darwin") -+ } -+ -+ der, err := os.ReadFile(rootCertPath) -+ if err != nil { -+ t.Fatalf("failed to read test root: %s", err) -+ } -+ b, _ := pem.Decode(der) -+ testRoot, err := ParseCertificate(b.Bytes) -+ if err != nil { -+ t.Fatalf("failed to parse test root: %s", err) -+ } -+ -+ der, err = os.ReadFile(rootKeyPath) -+ if err != nil { -+ t.Fatalf("failed to read test key: %s", err) -+ } -+ b, _ = pem.Decode(der) -+ testRootKey, err := ParseECPrivateKey(b.Bytes) -+ if err != nil { -+ t.Fatalf("failed to parse test key: %s", err) -+ } -+ -+ if _, err := testRoot.Verify(VerifyOptions{}); err != nil { -+ t.Skipf("test root is not in trust store, skipping (err: %q)", err) -+ } -+ -+ now := time.Now() -+ -+ tests := []struct { -+ name string -+ cert *Certificate -+ selfSigned bool -+ dnsName string -+ time time.Time -+ eku []ExtKeyUsage -+ -+ expectedErr string -+ windowsErr string -+ macosErr string -+ }{ -+ { -+ name: "valid", -+ cert: &Certificate{ -+ SerialNumber: big.NewInt(1), -+ DNSNames: []string{"valid.testing.golang.invalid"}, -+ NotBefore: now.Add(-time.Hour), -+ NotAfter: now.Add(time.Hour), -+ ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ }, -+ }, -+ { -+ name: "valid (with name)", -+ cert: &Certificate{ -+ SerialNumber: big.NewInt(1), -+ DNSNames: []string{"valid.testing.golang.invalid"}, -+ NotBefore: now.Add(-time.Hour), -+ NotAfter: now.Add(time.Hour), -+ ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ }, -+ dnsName: "valid.testing.golang.invalid", -+ }, -+ { -+ name: "valid (with time)", -+ cert: &Certificate{ -+ SerialNumber: big.NewInt(1), -+ DNSNames: []string{"valid.testing.golang.invalid"}, -+ NotBefore: now.Add(-time.Hour), -+ NotAfter: now.Add(time.Hour), -+ ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ }, -+ time: now.Add(time.Minute * 30), -+ }, -+ { -+ name: "valid (with eku)", -+ cert: &Certificate{ -+ SerialNumber: big.NewInt(1), -+ DNSNames: []string{"valid.testing.golang.invalid"}, -+ NotBefore: now.Add(-time.Hour), -+ NotAfter: now.Add(time.Hour), -+ ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ }, -+ eku: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ }, -+ { -+ name: "wrong name", -+ cert: &Certificate{ -+ SerialNumber: big.NewInt(1), -+ DNSNames: []string{"valid.testing.golang.invalid"}, -+ NotBefore: now.Add(-time.Hour), -+ NotAfter: now.Add(time.Hour), -+ ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ }, -+ dnsName: "invalid.testing.golang.invalid", -+ expectedErr: "x509: certificate is valid for valid.testing.golang.invalid, not invalid.testing.golang.invalid", -+ }, -+ { -+ name: "expired (future)", -+ cert: &Certificate{ -+ SerialNumber: big.NewInt(1), -+ DNSNames: []string{"valid.testing.golang.invalid"}, -+ NotBefore: now.Add(-time.Hour), -+ NotAfter: now.Add(time.Hour), -+ ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ }, -+ time: now.Add(time.Hour * 2), -+ expectedErr: "x509: certificate has expired or is not yet valid", -+ }, -+ { -+ name: "expired (past)", -+ cert: &Certificate{ -+ SerialNumber: big.NewInt(1), -+ DNSNames: []string{"valid.testing.golang.invalid"}, -+ NotBefore: now.Add(-time.Hour), -+ NotAfter: now.Add(time.Hour), -+ ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ }, -+ time: now.Add(time.Hour * 2), -+ expectedErr: "x509: certificate has expired or is not yet valid", -+ }, -+ { -+ name: "self-signed", -+ cert: &Certificate{ -+ SerialNumber: big.NewInt(1), -+ DNSNames: []string{"valid.testing.golang.invalid"}, -+ NotBefore: now.Add(-time.Hour), -+ NotAfter: now.Add(time.Hour), -+ ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ }, -+ selfSigned: true, -+ macosErr: "x509: “valid.testing.golang.invalid” certificate is not trusted", -+ windowsErr: "x509: certificate signed by unknown authority", -+ }, -+ { -+ name: "non-specified KU", -+ cert: &Certificate{ -+ SerialNumber: big.NewInt(1), -+ DNSNames: []string{"valid.testing.golang.invalid"}, -+ NotBefore: now.Add(-time.Hour), -+ NotAfter: now.Add(time.Hour), -+ ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ }, -+ eku: []ExtKeyUsage{ExtKeyUsageEmailProtection}, -+ expectedErr: "x509: certificate specifies an incompatible key usage", -+ }, -+ { -+ name: "non-nested KU", -+ cert: &Certificate{ -+ SerialNumber: big.NewInt(1), -+ DNSNames: []string{"valid.testing.golang.invalid"}, -+ NotBefore: now.Add(-time.Hour), -+ NotAfter: now.Add(time.Hour), -+ ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageEmailProtection}, -+ }, -+ macosErr: "x509: “valid.testing.golang.invalid” certificate is not permitted for this usage", -+ windowsErr: "x509: certificate specifies an incompatible key usage", -+ }, -+ } -+ -+ leafKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ t.Fatalf("ecdsa.GenerateKey failed: %s", err) -+ } -+ -+ for _, tc := range tests { -+ tc := tc -+ t.Run(tc.name, func(t *testing.T) { -+ t.Parallel() -+ parent := testRoot -+ if tc.selfSigned { -+ parent = tc.cert -+ } -+ certDER, err := CreateCertificate(rand.Reader, tc.cert, parent, leafKey.Public(), testRootKey) -+ if err != nil { -+ t.Fatalf("CreateCertificate failed: %s", err) -+ } -+ cert, err := ParseCertificate(certDER) -+ if err != nil { -+ t.Fatalf("ParseCertificate failed: %s", err) -+ } -+ -+ var opts VerifyOptions -+ if tc.dnsName != "" { -+ opts.DNSName = tc.dnsName -+ } -+ if !tc.time.IsZero() { -+ opts.CurrentTime = tc.time -+ } -+ if len(tc.eku) > 0 { -+ opts.KeyUsages = tc.eku -+ } -+ -+ expectedErr := tc.expectedErr -+ if runtime.GOOS == "darwin" && tc.macosErr != "" { -+ expectedErr = tc.macosErr -+ } else if runtime.GOOS == "windows" && tc.windowsErr != "" { -+ expectedErr = tc.windowsErr -+ } -+ -+ _, err = cert.Verify(opts) -+ if err != nil && expectedErr == "" { -+ t.Errorf("unexpected verification error: %s", err) -+ } else if err != nil && !strings.HasPrefix(err.Error(), expectedErr) { -+ t.Errorf("unexpected verification error: got %q, want %q", err.Error(), expectedErr) -+ } else if err == nil && expectedErr != "" { -+ t.Errorf("unexpected verification success: want %q", expectedErr) -+ } -+ }) -+ } -+} -diff --git a/src/crypto/x509/root.go-e b/src/crypto/x509/root.go-e -new file mode 100644 -index 0000000000..b454af2c4c ---- /dev/null -+++ b/src/crypto/x509/root.go-e -@@ -0,0 +1,75 @@ -+// Copyright 2012 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. -+ -+package x509 -+ -+import ( -+ "internal/godebug" -+ "sync" -+) -+ -+var ( -+ once sync.Once -+ systemRootsMu sync.RWMutex -+ systemRoots *CertPool -+ systemRootsErr error -+ fallbacksSet bool -+) -+ -+func systemRootsPool() *CertPool { -+ once.Do(initSystemRoots) -+ systemRootsMu.RLock() -+ defer systemRootsMu.RUnlock() -+ return systemRoots -+} -+ -+func initSystemRoots() { -+ systemRootsMu.Lock() -+ defer systemRootsMu.Unlock() -+ systemRoots, systemRootsErr = loadSystemRoots() -+ if systemRootsErr != nil { -+ systemRoots = nil -+ } -+} -+ -+var x509usefallbackroots = godebug.New("x509usefallbackroots") -+ -+// SetFallbackRoots sets the roots to use during certificate verification, if no -+// custom roots are specified and a platform verifier or a system certificate -+// pool is not available (for instance in a container which does not have a root -+// certificate bundle). SetFallbackRoots will panic if roots is nil. -+// -+// SetFallbackRoots may only be called once, if called multiple times it will -+// panic. -+// -+// The fallback behavior can be forced on all platforms, even when there is a -+// system certificate pool, by setting GODEBUG=x509usefallbackroots=1 (note that -+// on Windows and macOS this will disable usage of the platform verification -+// APIs and cause the pure Go verifier to be used). Setting -+// x509usefallbackroots=1 without calling SetFallbackRoots has no effect. -+func SetFallbackRoots(roots *CertPool) { -+ if roots == nil { -+ panic("roots must be non-nil") -+ } -+ -+ // trigger initSystemRoots if it hasn't already been called before we -+ // take the lock -+ _ = systemRootsPool() -+ -+ systemRootsMu.Lock() -+ defer systemRootsMu.Unlock() -+ -+ if fallbacksSet { -+ panic("SetFallbackRoots has already been called") -+ } -+ fallbacksSet = true -+ -+ if systemRoots != nil && (systemRoots.len() > 0 || systemRoots.systemPool) { -+ if x509usefallbackroots.Value() != "1" { -+ return -+ } -+ x509usefallbackroots.IncNonDefault() -+ } -+ systemRoots, systemRootsErr = roots, nil -+} -diff --git a/src/crypto/x509/root_aix.go-e b/src/crypto/x509/root_aix.go-e -new file mode 100644 -index 0000000000..99b7463a2a ---- /dev/null -+++ b/src/crypto/x509/root_aix.go-e -@@ -0,0 +1,15 @@ -+// Copyright 2018 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. -+ -+package x509 -+ -+// Possible certificate files; stop after finding one. -+var certFiles = []string{ -+ "/var/ssl/certs/ca-bundle.crt", -+} -+ -+// Possible directories with certificate files; all will be read. -+var certDirectories = []string{ -+ "/var/ssl/certs", -+} -diff --git a/src/crypto/x509/root_bsd.go-e b/src/crypto/x509/root_bsd.go-e -new file mode 100644 -index 0000000000..a76aef8659 ---- /dev/null -+++ b/src/crypto/x509/root_bsd.go-e -@@ -0,0 +1,22 @@ -+// Copyright 2015 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 dragonfly || freebsd || netbsd || openbsd -+ -+package x509 -+ -+// Possible certificate files; stop after finding one. -+var certFiles = []string{ -+ "/usr/local/etc/ssl/cert.pem", // FreeBSD -+ "/etc/ssl/cert.pem", // OpenBSD -+ "/usr/local/share/certs/ca-root-nss.crt", // DragonFly -+ "/etc/openssl/certs/ca-certificates.crt", // NetBSD -+} -+ -+// Possible directories with certificate files; all will be read. -+var certDirectories = []string{ -+ "/etc/ssl/certs", // FreeBSD 12.2+ -+ "/usr/local/share/certs", // FreeBSD -+ "/etc/openssl/certs", // NetBSD -+} -diff --git a/src/crypto/x509/root_darwin.go-e b/src/crypto/x509/root_darwin.go-e -new file mode 100644 -index 0000000000..469e907a8e ---- /dev/null -+++ b/src/crypto/x509/root_darwin.go-e -@@ -0,0 +1,130 @@ -+// Copyright 2020 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. -+ -+package x509 -+ -+import ( -+ macOS "crypto/x509/internal/macos" -+ "errors" -+ "fmt" -+) -+ -+func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { -+ certs := macOS.CFArrayCreateMutable() -+ defer macOS.ReleaseCFArray(certs) -+ leaf, err := macOS.SecCertificateCreateWithData(c.Raw) -+ if err != nil { -+ return nil, errors.New("invalid leaf certificate") -+ } -+ macOS.CFArrayAppendValue(certs, leaf) -+ if opts.Intermediates != nil { -+ for _, lc := range opts.Intermediates.lazyCerts { -+ c, err := lc.getCert() -+ if err != nil { -+ return nil, err -+ } -+ sc, err := macOS.SecCertificateCreateWithData(c.Raw) -+ if err != nil { -+ return nil, err -+ } -+ macOS.CFArrayAppendValue(certs, sc) -+ } -+ } -+ -+ policies := macOS.CFArrayCreateMutable() -+ defer macOS.ReleaseCFArray(policies) -+ sslPolicy, err := macOS.SecPolicyCreateSSL(opts.DNSName) -+ if err != nil { -+ return nil, err -+ } -+ macOS.CFArrayAppendValue(policies, sslPolicy) -+ -+ trustObj, err := macOS.SecTrustCreateWithCertificates(certs, policies) -+ if err != nil { -+ return nil, err -+ } -+ defer macOS.CFRelease(trustObj) -+ -+ if !opts.CurrentTime.IsZero() { -+ dateRef := macOS.TimeToCFDateRef(opts.CurrentTime) -+ defer macOS.CFRelease(dateRef) -+ if err := macOS.SecTrustSetVerifyDate(trustObj, dateRef); err != nil { -+ return nil, err -+ } -+ } -+ -+ // TODO(roland): we may want to allow passing in SCTs via VerifyOptions and -+ // set them via SecTrustSetSignedCertificateTimestamps, since Apple will -+ // always enforce its SCT requirements, and there are still _some_ people -+ // using TLS or OCSP for that. -+ -+ if ret, err := macOS.SecTrustEvaluateWithError(trustObj); err != nil { -+ switch ret { -+ case macOS.ErrSecCertificateExpired: -+ return nil, CertificateInvalidError{c, Expired, err.Error()} -+ case macOS.ErrSecHostNameMismatch: -+ return nil, HostnameError{c, opts.DNSName} -+ case macOS.ErrSecNotTrusted: -+ return nil, UnknownAuthorityError{Cert: c} -+ default: -+ return nil, fmt.Errorf("x509: %s", err) -+ } -+ } -+ -+ chain := [][]*Certificate{{}} -+ numCerts := macOS.SecTrustGetCertificateCount(trustObj) -+ for i := 0; i < numCerts; i++ { -+ certRef, err := macOS.SecTrustGetCertificateAtIndex(trustObj, i) -+ if err != nil { -+ return nil, err -+ } -+ cert, err := exportCertificate(certRef) -+ if err != nil { -+ return nil, err -+ } -+ chain[0] = append(chain[0], cert) -+ } -+ if len(chain[0]) == 0 { -+ // This should _never_ happen, but to be safe -+ return nil, errors.New("x509: macOS certificate verification internal error") -+ } -+ -+ if opts.DNSName != "" { -+ // If we have a DNS name, apply our own name verification -+ if err := chain[0][0].VerifyHostname(opts.DNSName); err != nil { -+ return nil, err -+ } -+ } -+ -+ keyUsages := opts.KeyUsages -+ if len(keyUsages) == 0 { -+ keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth} -+ } -+ -+ // If any key usage is acceptable then we're done. -+ for _, usage := range keyUsages { -+ if usage == ExtKeyUsageAny { -+ return chain, nil -+ } -+ } -+ -+ if !checkChainForKeyUsage(chain[0], keyUsages) { -+ return nil, CertificateInvalidError{c, IncompatibleUsage, ""} -+ } -+ -+ return chain, nil -+} -+ -+// exportCertificate returns a *Certificate for a SecCertificateRef. -+func exportCertificate(cert macOS.CFRef) (*Certificate, error) { -+ data, err := macOS.SecCertificateCopyData(cert) -+ if err != nil { -+ return nil, err -+ } -+ return ParseCertificate(data) -+} -+ -+func loadSystemRoots() (*CertPool, error) { -+ return &CertPool{systemPool: true}, nil -+} -diff --git a/src/crypto/x509/root_darwin_test.go-e b/src/crypto/x509/root_darwin_test.go-e -new file mode 100644 -index 0000000000..e6b52e9f91 ---- /dev/null -+++ b/src/crypto/x509/root_darwin_test.go-e -@@ -0,0 +1,131 @@ -+// Copyright 2013 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. -+ -+package x509_test -+ -+import ( -+ "crypto/tls" -+ "crypto/x509" -+ "internal/testenv" -+ "testing" -+ "time" -+) -+ -+func TestPlatformVerifierLegacy(t *testing.T) { -+ // TODO(#52108): This can be removed once the synthetic test root is deployed on -+ // builders. -+ if !testenv.HasExternalNetwork() { -+ t.Skip() -+ } -+ -+ getChain := func(host string) []*x509.Certificate { -+ t.Helper() -+ c, err := tls.Dial("tcp", host+":443", &tls.Config{InsecureSkipVerify: true}) -+ if err != nil { -+ t.Fatalf("tls connection failed: %s", err) -+ } -+ return c.ConnectionState().PeerCertificates -+ } -+ -+ tests := []struct { -+ name string -+ host string -+ verifyName string -+ verifyTime time.Time -+ verifyEKU []x509.ExtKeyUsage -+ expectedErr string -+ skip string -+ }{ -+ { -+ // whatever google.com serves should, hopefully, be trusted -+ name: "valid chain", -+ host: "google.com", -+ }, -+ { -+ name: "expired leaf", -+ host: "expired.badssl.com", -+ expectedErr: "x509: certificate has expired or is not yet valid: “*.badssl.com” certificate is expired", -+ }, -+ { -+ name: "wrong host for leaf", -+ host: "wrong.host.badssl.com", -+ verifyName: "wrong.host.badssl.com", -+ expectedErr: "x509: certificate is valid for *.badssl.com, badssl.com, not wrong.host.badssl.com", -+ }, -+ { -+ name: "self-signed leaf", -+ host: "self-signed.badssl.com", -+ expectedErr: "x509: certificate signed by unknown authority", -+ }, -+ { -+ name: "untrusted root", -+ host: "untrusted-root.badssl.com", -+ expectedErr: "x509: certificate signed by unknown authority", -+ }, -+ { -+ name: "revoked leaf", -+ host: "revoked.badssl.com", -+ expectedErr: "x509: “revoked.badssl.com” certificate is revoked", -+ skip: "skipping; broken on recent versions of macOS. See issue 57428.", -+ }, -+ { -+ name: "leaf missing SCTs", -+ host: "no-sct.badssl.com", -+ expectedErr: "x509: “no-sct.badssl.com” certificate is not standards compliant", -+ skip: "skipping; broken on recent versions of macOS. See issue 57428.", -+ }, -+ { -+ name: "expired leaf (custom time)", -+ host: "google.com", -+ verifyTime: time.Time{}.Add(time.Hour), -+ expectedErr: "x509: certificate has expired or is not yet valid: “*.google.com” certificate is expired", -+ }, -+ { -+ name: "valid chain (custom time)", -+ host: "google.com", -+ verifyTime: time.Now(), -+ }, -+ { -+ name: "leaf doesn't have acceptable ExtKeyUsage", -+ host: "google.com", -+ expectedErr: "x509: certificate specifies an incompatible key usage", -+ verifyEKU: []x509.ExtKeyUsage{x509.ExtKeyUsageEmailProtection}, -+ }, -+ } -+ -+ for _, tc := range tests { -+ t.Run(tc.name, func(t *testing.T) { -+ if tc.skip != "" { -+ t.Skip(tc.skip) -+ } -+ -+ chain := getChain(tc.host) -+ var opts x509.VerifyOptions -+ if len(chain) > 1 { -+ opts.Intermediates = x509.NewCertPool() -+ for _, c := range chain[1:] { -+ opts.Intermediates.AddCert(c) -+ } -+ } -+ if tc.verifyName != "" { -+ opts.DNSName = tc.verifyName -+ } -+ if !tc.verifyTime.IsZero() { -+ opts.CurrentTime = tc.verifyTime -+ } -+ if len(tc.verifyEKU) > 0 { -+ opts.KeyUsages = tc.verifyEKU -+ } -+ -+ _, err := chain[0].Verify(opts) -+ if err != nil && tc.expectedErr == "" { -+ t.Errorf("unexpected verification error: %s", err) -+ } else if err != nil && err.Error() != tc.expectedErr { -+ t.Errorf("unexpected verification error: got %q, want %q", err.Error(), tc.expectedErr) -+ } else if err == nil && tc.expectedErr != "" { -+ t.Errorf("unexpected verification success: want %q", tc.expectedErr) -+ } -+ }) -+ } -+} -diff --git a/src/crypto/x509/root_linux.go-e b/src/crypto/x509/root_linux.go-e -new file mode 100644 -index 0000000000..e32989b999 ---- /dev/null -+++ b/src/crypto/x509/root_linux.go-e -@@ -0,0 +1,22 @@ -+// Copyright 2015 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. -+ -+package x509 -+ -+// Possible certificate files; stop after finding one. -+var certFiles = []string{ -+ "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. -+ "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6 -+ "/etc/ssl/ca-bundle.pem", // OpenSUSE -+ "/etc/pki/tls/cacert.pem", // OpenELEC -+ "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7 -+ "/etc/ssl/cert.pem", // Alpine Linux -+} -+ -+// Possible directories with certificate files; all will be read. -+var certDirectories = []string{ -+ "/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139 -+ "/etc/pki/tls/certs", // Fedora/RHEL -+ "/system/etc/security/cacerts", // Android -+} -diff --git a/src/crypto/x509/root_plan9.go-e b/src/crypto/x509/root_plan9.go-e -new file mode 100644 -index 0000000000..3bd06fe50d ---- /dev/null -+++ b/src/crypto/x509/root_plan9.go-e -@@ -0,0 +1,39 @@ -+// Copyright 2012 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 plan9 -+ -+package x509 -+ -+import ( -+ "os" -+) -+ -+// Possible certificate files; stop after finding one. -+var certFiles = []string{ -+ "/sys/lib/tls/ca.pem", -+} -+ -+func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { -+ return nil, nil -+} -+ -+func loadSystemRoots() (*CertPool, error) { -+ roots := NewCertPool() -+ var bestErr error -+ for _, file := range certFiles { -+ data, err := os.ReadFile(file) -+ if err == nil { -+ roots.AppendCertsFromPEM(data) -+ return roots, nil -+ } -+ if bestErr == nil || (os.IsNotExist(bestErr) && !os.IsNotExist(err)) { -+ bestErr = err -+ } -+ } -+ if bestErr == nil { -+ return roots, nil -+ } -+ return nil, bestErr -+} -diff --git a/src/crypto/x509/root_solaris.go-e b/src/crypto/x509/root_solaris.go-e -new file mode 100644 -index 0000000000..617f26961f ---- /dev/null -+++ b/src/crypto/x509/root_solaris.go-e -@@ -0,0 +1,17 @@ -+// Copyright 2015 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. -+ -+package x509 -+ -+// Possible certificate files; stop after finding one. -+var certFiles = []string{ -+ "/etc/certs/ca-certificates.crt", // Solaris 11.2+ -+ "/etc/ssl/certs/ca-certificates.crt", // Joyent SmartOS -+ "/etc/ssl/cacert.pem", // OmniOS -+} -+ -+// Possible directories with certificate files; all will be read. -+var certDirectories = []string{ -+ "/etc/certs/CA", -+} -diff --git a/src/crypto/x509/root_test.go-e b/src/crypto/x509/root_test.go-e -new file mode 100644 -index 0000000000..94ee6a632d ---- /dev/null -+++ b/src/crypto/x509/root_test.go-e -@@ -0,0 +1,108 @@ -+// Copyright 2022 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. -+ -+package x509 -+ -+import ( -+ "testing" -+) -+ -+func TestFallbackPanic(t *testing.T) { -+ defer func() { -+ if recover() == nil { -+ t.Fatal("Multiple calls to SetFallbackRoots should panic") -+ } -+ }() -+ SetFallbackRoots(nil) -+ SetFallbackRoots(nil) -+} -+ -+func TestFallback(t *testing.T) { -+ // call systemRootsPool so that the sync.Once is triggered, and we can -+ // manipulate systemRoots without worrying about our working being overwritten -+ systemRootsPool() -+ if systemRoots != nil { -+ originalSystemRoots := *systemRoots -+ defer func() { systemRoots = &originalSystemRoots }() -+ } -+ -+ tests := []struct { -+ name string -+ systemRoots *CertPool -+ systemPool bool -+ poolContent []*Certificate -+ forceFallback bool -+ returnsFallback bool -+ }{ -+ { -+ name: "nil systemRoots", -+ returnsFallback: true, -+ }, -+ { -+ name: "empty systemRoots", -+ systemRoots: NewCertPool(), -+ returnsFallback: true, -+ }, -+ { -+ name: "empty systemRoots system pool", -+ systemRoots: NewCertPool(), -+ systemPool: true, -+ }, -+ { -+ name: "filled systemRoots system pool", -+ systemRoots: NewCertPool(), -+ poolContent: []*Certificate{{}}, -+ systemPool: true, -+ }, -+ { -+ name: "filled systemRoots", -+ systemRoots: NewCertPool(), -+ poolContent: []*Certificate{{}}, -+ }, -+ { -+ name: "filled systemRoots, force fallback", -+ systemRoots: NewCertPool(), -+ poolContent: []*Certificate{{}}, -+ forceFallback: true, -+ returnsFallback: true, -+ }, -+ { -+ name: "filled systemRoot system pool, force fallback", -+ systemRoots: NewCertPool(), -+ poolContent: []*Certificate{{}}, -+ systemPool: true, -+ forceFallback: true, -+ returnsFallback: true, -+ }, -+ } -+ -+ for _, tc := range tests { -+ t.Run(tc.name, func(t *testing.T) { -+ fallbacksSet = false -+ systemRoots = tc.systemRoots -+ if systemRoots != nil { -+ systemRoots.systemPool = tc.systemPool -+ } -+ for _, c := range tc.poolContent { -+ systemRoots.AddCert(c) -+ } -+ if tc.forceFallback { -+ t.Setenv("GODEBUG", "x509usefallbackroots=1") -+ } else { -+ t.Setenv("GODEBUG", "x509usefallbackroots=0") -+ } -+ -+ fallbackPool := NewCertPool() -+ SetFallbackRoots(fallbackPool) -+ -+ systemPoolIsFallback := systemRoots == fallbackPool -+ -+ if tc.returnsFallback && !systemPoolIsFallback { -+ t.Error("systemRoots was not set to fallback pool") -+ } else if !tc.returnsFallback && systemPoolIsFallback { -+ t.Error("systemRoots was set to fallback pool when it shouldn't have been") -+ } -+ }) -+ } -+} -diff --git a/src/crypto/x509/root_unix.go-e b/src/crypto/x509/root_unix.go-e -new file mode 100644 -index 0000000000..c513b20169 ---- /dev/null -+++ b/src/crypto/x509/root_unix.go-e -@@ -0,0 +1,108 @@ -+// Copyright 2011 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 aix || dragonfly || freebsd || (js && wasm) || linux || netbsd || openbsd || solaris || wasip1 -+ -+package x509 -+ -+import ( -+ "io/fs" -+ "os" -+ "path/filepath" -+ "strings" -+) -+ -+const ( -+ // certFileEnv is the environment variable which identifies where to locate -+ // the SSL certificate file. If set this overrides the system default. -+ certFileEnv = "SSL_CERT_FILE" -+ -+ // certDirEnv is the environment variable which identifies which directory -+ // to check for SSL certificate files. If set this overrides the system default. -+ // It is a colon separated list of directories. -+ // See https://www.openssl.org/docs/man1.0.2/man1/c_rehash.html. -+ certDirEnv = "SSL_CERT_DIR" -+) -+ -+func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { -+ return nil, nil -+} -+ -+func loadSystemRoots() (*CertPool, error) { -+ roots := NewCertPool() -+ -+ files := certFiles -+ if f := os.Getenv(certFileEnv); f != "" { -+ files = []string{f} -+ } -+ -+ var firstErr error -+ for _, file := range files { -+ data, err := os.ReadFile(file) -+ if err == nil { -+ roots.AppendCertsFromPEM(data) -+ break -+ } -+ if firstErr == nil && !os.IsNotExist(err) { -+ firstErr = err -+ } -+ } -+ -+ dirs := certDirectories -+ if d := os.Getenv(certDirEnv); d != "" { -+ // OpenSSL and BoringSSL both use ":" as the SSL_CERT_DIR separator. -+ // See: -+ // * https://golang.org/issue/35325 -+ // * https://www.openssl.org/docs/man1.0.2/man1/c_rehash.html -+ dirs = strings.Split(d, ":") -+ } -+ -+ for _, directory := range dirs { -+ fis, err := readUniqueDirectoryEntries(directory) -+ if err != nil { -+ if firstErr == nil && !os.IsNotExist(err) { -+ firstErr = err -+ } -+ continue -+ } -+ for _, fi := range fis { -+ data, err := os.ReadFile(directory + "/" + fi.Name()) -+ if err == nil { -+ roots.AppendCertsFromPEM(data) -+ } -+ } -+ } -+ -+ if roots.len() > 0 || firstErr == nil { -+ return roots, nil -+ } -+ -+ return nil, firstErr -+} -+ -+// readUniqueDirectoryEntries is like os.ReadDir but omits -+// symlinks that point within the directory. -+func readUniqueDirectoryEntries(dir string) ([]fs.DirEntry, error) { -+ files, err := os.ReadDir(dir) -+ if err != nil { -+ return nil, err -+ } -+ uniq := files[:0] -+ for _, f := range files { -+ if !isSameDirSymlink(f, dir) { -+ uniq = append(uniq, f) -+ } -+ } -+ return uniq, nil -+} -+ -+// isSameDirSymlink reports whether fi in dir is a symlink with a -+// target not containing a slash. -+func isSameDirSymlink(f fs.DirEntry, dir string) bool { -+ if f.Type()&fs.ModeSymlink == 0 { -+ return false -+ } -+ target, err := os.Readlink(filepath.Join(dir, f.Name())) -+ return err == nil && !strings.Contains(target, "/") -+} -diff --git a/src/crypto/x509/root_unix_test.go-e b/src/crypto/x509/root_unix_test.go-e -new file mode 100644 -index 0000000000..d5215b9ff2 ---- /dev/null -+++ b/src/crypto/x509/root_unix_test.go-e -@@ -0,0 +1,228 @@ -+// 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 dragonfly || freebsd || linux || netbsd || openbsd || solaris -+ -+package x509 -+ -+import ( -+ "bytes" -+ "fmt" -+ "os" -+ "path/filepath" -+ "reflect" -+ "strings" -+ "testing" -+) -+ -+const ( -+ testDir = "testdata" -+ testDirCN = "test-dir" -+ testFile = "test-file.crt" -+ testFileCN = "test-file" -+ testMissing = "missing" -+) -+ -+func TestEnvVars(t *testing.T) { -+ testCases := []struct { -+ name string -+ fileEnv string -+ dirEnv string -+ files []string -+ dirs []string -+ cns []string -+ }{ -+ { -+ // Environment variables override the default locations preventing fall through. -+ name: "override-defaults", -+ fileEnv: testMissing, -+ dirEnv: testMissing, -+ files: []string{testFile}, -+ dirs: []string{testDir}, -+ cns: nil, -+ }, -+ { -+ // File environment overrides default file locations. -+ name: "file", -+ fileEnv: testFile, -+ dirEnv: "", -+ files: nil, -+ dirs: nil, -+ cns: []string{testFileCN}, -+ }, -+ { -+ // Directory environment overrides default directory locations. -+ name: "dir", -+ fileEnv: "", -+ dirEnv: testDir, -+ files: nil, -+ dirs: nil, -+ cns: []string{testDirCN}, -+ }, -+ { -+ // File & directory environment overrides both default locations. -+ name: "file+dir", -+ fileEnv: testFile, -+ dirEnv: testDir, -+ files: nil, -+ dirs: nil, -+ cns: []string{testFileCN, testDirCN}, -+ }, -+ { -+ // Environment variable empty / unset uses default locations. -+ name: "empty-fall-through", -+ fileEnv: "", -+ dirEnv: "", -+ files: []string{testFile}, -+ dirs: []string{testDir}, -+ cns: []string{testFileCN, testDirCN}, -+ }, -+ } -+ -+ // Save old settings so we can restore before the test ends. -+ origCertFiles, origCertDirectories := certFiles, certDirectories -+ origFile, origDir := os.Getenv(certFileEnv), os.Getenv(certDirEnv) -+ defer func() { -+ certFiles = origCertFiles -+ certDirectories = origCertDirectories -+ os.Setenv(certFileEnv, origFile) -+ os.Setenv(certDirEnv, origDir) -+ }() -+ -+ for _, tc := range testCases { -+ t.Run(tc.name, func(t *testing.T) { -+ if err := os.Setenv(certFileEnv, tc.fileEnv); err != nil { -+ t.Fatalf("setenv %q failed: %v", certFileEnv, err) -+ } -+ if err := os.Setenv(certDirEnv, tc.dirEnv); err != nil { -+ t.Fatalf("setenv %q failed: %v", certDirEnv, err) -+ } -+ -+ certFiles, certDirectories = tc.files, tc.dirs -+ -+ r, err := loadSystemRoots() -+ if err != nil { -+ t.Fatal("unexpected failure:", err) -+ } -+ -+ if r == nil { -+ t.Fatal("nil roots") -+ } -+ -+ // Verify that the returned certs match, otherwise report where the mismatch is. -+ for i, cn := range tc.cns { -+ if i >= r.len() { -+ t.Errorf("missing cert %v @ %v", cn, i) -+ } else if r.mustCert(t, i).Subject.CommonName != cn { -+ fmt.Printf("%#v\n", r.mustCert(t, 0).Subject) -+ t.Errorf("unexpected cert common name %q, want %q", r.mustCert(t, i).Subject.CommonName, cn) -+ } -+ } -+ if r.len() > len(tc.cns) { -+ t.Errorf("got %v certs, which is more than %v wanted", r.len(), len(tc.cns)) -+ } -+ }) -+ } -+} -+ -+// Ensure that "SSL_CERT_DIR" when used as the environment -+// variable delimited by colons, allows loadSystemRoots to -+// load all the roots from the respective directories. -+// See https://golang.org/issue/35325. -+func TestLoadSystemCertsLoadColonSeparatedDirs(t *testing.T) { -+ origFile, origDir := os.Getenv(certFileEnv), os.Getenv(certDirEnv) -+ origCertFiles := certFiles[:] -+ -+ // To prevent any other certs from being loaded in -+ // through "SSL_CERT_FILE" or from known "certFiles", -+ // clear them all, and they'll be reverting on defer. -+ certFiles = certFiles[:0] -+ os.Setenv(certFileEnv, "") -+ -+ defer func() { -+ certFiles = origCertFiles[:] -+ os.Setenv(certDirEnv, origDir) -+ os.Setenv(certFileEnv, origFile) -+ }() -+ -+ tmpDir := t.TempDir() -+ -+ rootPEMs := []string{ -+ gtsRoot, -+ googleLeaf, -+ startComRoot, -+ } -+ -+ var certDirs []string -+ for i, certPEM := range rootPEMs { -+ certDir := filepath.Join(tmpDir, fmt.Sprintf("cert-%d", i)) -+ if err := os.MkdirAll(certDir, 0755); err != nil { -+ t.Fatalf("Failed to create certificate dir: %v", err) -+ } -+ certOutFile := filepath.Join(certDir, "cert.crt") -+ if err := os.WriteFile(certOutFile, []byte(certPEM), 0655); err != nil { -+ t.Fatalf("Failed to write certificate to file: %v", err) -+ } -+ certDirs = append(certDirs, certDir) -+ } -+ -+ // Sanity check: the number of certDirs should be equal to the number of roots. -+ if g, w := len(certDirs), len(rootPEMs); g != w { -+ t.Fatalf("Failed sanity check: len(certsDir)=%d is not equal to len(rootsPEMS)=%d", g, w) -+ } -+ -+ // Now finally concatenate them with a colon. -+ colonConcatCertDirs := strings.Join(certDirs, ":") -+ os.Setenv(certDirEnv, colonConcatCertDirs) -+ gotPool, err := loadSystemRoots() -+ if err != nil { -+ t.Fatalf("Failed to load system roots: %v", err) -+ } -+ subjects := gotPool.Subjects() -+ // We expect exactly len(rootPEMs) subjects back. -+ if g, w := len(subjects), len(rootPEMs); g != w { -+ t.Fatalf("Invalid number of subjects: got %d want %d", g, w) -+ } -+ -+ wantPool := NewCertPool() -+ for _, certPEM := range rootPEMs { -+ wantPool.AppendCertsFromPEM([]byte(certPEM)) -+ } -+ strCertPool := func(p *CertPool) string { -+ return string(bytes.Join(p.Subjects(), []byte("\n"))) -+ } -+ -+ if !certPoolEqual(gotPool, wantPool) { -+ g, w := strCertPool(gotPool), strCertPool(wantPool) -+ t.Fatalf("Mismatched certPools\nGot:\n%s\n\nWant:\n%s", g, w) -+ } -+} -+ -+func TestReadUniqueDirectoryEntries(t *testing.T) { -+ tmp := t.TempDir() -+ temp := func(base string) string { return filepath.Join(tmp, base) } -+ if f, err := os.Create(temp("file")); err != nil { -+ t.Fatal(err) -+ } else { -+ f.Close() -+ } -+ if err := os.Symlink("target-in", temp("link-in")); err != nil { -+ t.Fatal(err) -+ } -+ if err := os.Symlink("../target-out", temp("link-out")); err != nil { -+ t.Fatal(err) -+ } -+ got, err := readUniqueDirectoryEntries(tmp) -+ if err != nil { -+ t.Fatal(err) -+ } -+ gotNames := []string{} -+ for _, fi := range got { -+ gotNames = append(gotNames, fi.Name()) -+ } -+ wantNames := []string{"file", "link-out"} -+ if !reflect.DeepEqual(gotNames, wantNames) { -+ t.Errorf("got %q; want %q", gotNames, wantNames) -+ } -+} -diff --git a/src/crypto/x509/root_wasm.go-e b/src/crypto/x509/root_wasm.go-e -new file mode 100644 -index 0000000000..275c9213d9 ---- /dev/null -+++ b/src/crypto/x509/root_wasm.go-e -@@ -0,0 +1,13 @@ -+// Copyright 2018 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 wasm -+ -+package x509 -+ -+// Possible certificate files; stop after finding one. -+var certFiles = []string{} -+ -+// Possible directories with certificate files; all will be read. -+var certDirectories = []string{} -diff --git a/src/crypto/x509/root_windows.go-e b/src/crypto/x509/root_windows.go-e -new file mode 100644 -index 0000000000..11a4257b01 ---- /dev/null -+++ b/src/crypto/x509/root_windows.go-e -@@ -0,0 +1,277 @@ -+// Copyright 2012 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. -+ -+package x509 -+ -+import ( -+ "bytes" -+ "errors" -+ "strings" -+ "syscall" -+ "unsafe" -+) -+ -+func loadSystemRoots() (*CertPool, error) { -+ return &CertPool{systemPool: true}, nil -+} -+ -+// Creates a new *syscall.CertContext representing the leaf certificate in an in-memory -+// certificate store containing itself and all of the intermediate certificates specified -+// in the opts.Intermediates CertPool. -+// -+// A pointer to the in-memory store is available in the returned CertContext's Store field. -+// The store is automatically freed when the CertContext is freed using -+// syscall.CertFreeCertificateContext. -+func createStoreContext(leaf *Certificate, opts *VerifyOptions) (*syscall.CertContext, error) { -+ var storeCtx *syscall.CertContext -+ -+ leafCtx, err := syscall.CertCreateCertificateContext(syscall.X509_ASN_ENCODING|syscall.PKCS_7_ASN_ENCODING, &leaf.Raw[0], uint32(len(leaf.Raw))) -+ if err != nil { -+ return nil, err -+ } -+ defer syscall.CertFreeCertificateContext(leafCtx) -+ -+ handle, err := syscall.CertOpenStore(syscall.CERT_STORE_PROV_MEMORY, 0, 0, syscall.CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, 0) -+ if err != nil { -+ return nil, err -+ } -+ defer syscall.CertCloseStore(handle, 0) -+ -+ err = syscall.CertAddCertificateContextToStore(handle, leafCtx, syscall.CERT_STORE_ADD_ALWAYS, &storeCtx) -+ if err != nil { -+ return nil, err -+ } -+ -+ if opts.Intermediates != nil { -+ for i := 0; i < opts.Intermediates.len(); i++ { -+ intermediate, err := opts.Intermediates.cert(i) -+ if err != nil { -+ return nil, err -+ } -+ ctx, err := syscall.CertCreateCertificateContext(syscall.X509_ASN_ENCODING|syscall.PKCS_7_ASN_ENCODING, &intermediate.Raw[0], uint32(len(intermediate.Raw))) -+ if err != nil { -+ return nil, err -+ } -+ -+ err = syscall.CertAddCertificateContextToStore(handle, ctx, syscall.CERT_STORE_ADD_ALWAYS, nil) -+ syscall.CertFreeCertificateContext(ctx) -+ if err != nil { -+ return nil, err -+ } -+ } -+ } -+ -+ return storeCtx, nil -+} -+ -+// extractSimpleChain extracts the final certificate chain from a CertSimpleChain. -+func extractSimpleChain(simpleChain **syscall.CertSimpleChain, count int) (chain []*Certificate, err error) { -+ if simpleChain == nil || count == 0 { -+ return nil, errors.New("x509: invalid simple chain") -+ } -+ -+ simpleChains := unsafe.Slice(simpleChain, count) -+ lastChain := simpleChains[count-1] -+ elements := unsafe.Slice(lastChain.Elements, lastChain.NumElements) -+ for i := 0; i < int(lastChain.NumElements); i++ { -+ // Copy the buf, since ParseCertificate does not create its own copy. -+ cert := elements[i].CertContext -+ encodedCert := unsafe.Slice(cert.EncodedCert, cert.Length) -+ buf := bytes.Clone(encodedCert) -+ parsedCert, err := ParseCertificate(buf) -+ if err != nil { -+ return nil, err -+ } -+ chain = append(chain, parsedCert) -+ } -+ -+ return chain, nil -+} -+ -+// checkChainTrustStatus checks the trust status of the certificate chain, translating -+// any errors it finds into Go errors in the process. -+func checkChainTrustStatus(c *Certificate, chainCtx *syscall.CertChainContext) error { -+ if chainCtx.TrustStatus.ErrorStatus != syscall.CERT_TRUST_NO_ERROR { -+ status := chainCtx.TrustStatus.ErrorStatus -+ switch status { -+ case syscall.CERT_TRUST_IS_NOT_TIME_VALID: -+ return CertificateInvalidError{c, Expired, ""} -+ case syscall.CERT_TRUST_IS_NOT_VALID_FOR_USAGE: -+ return CertificateInvalidError{c, IncompatibleUsage, ""} -+ // TODO(filippo): surface more error statuses. -+ default: -+ return UnknownAuthorityError{c, nil, nil} -+ } -+ } -+ return nil -+} -+ -+// checkChainSSLServerPolicy checks that the certificate chain in chainCtx is valid for -+// use as a certificate chain for a SSL/TLS server. -+func checkChainSSLServerPolicy(c *Certificate, chainCtx *syscall.CertChainContext, opts *VerifyOptions) error { -+ servernamep, err := syscall.UTF16PtrFromString(strings.TrimSuffix(opts.DNSName, ".")) -+ if err != nil { -+ return err -+ } -+ sslPara := &syscall.SSLExtraCertChainPolicyPara{ -+ AuthType: syscall.AUTHTYPE_SERVER, -+ ServerName: servernamep, -+ } -+ sslPara.Size = uint32(unsafe.Sizeof(*sslPara)) -+ -+ para := &syscall.CertChainPolicyPara{ -+ ExtraPolicyPara: (syscall.Pointer)(unsafe.Pointer(sslPara)), -+ } -+ para.Size = uint32(unsafe.Sizeof(*para)) -+ -+ status := syscall.CertChainPolicyStatus{} -+ err = syscall.CertVerifyCertificateChainPolicy(syscall.CERT_CHAIN_POLICY_SSL, chainCtx, para, &status) -+ if err != nil { -+ return err -+ } -+ -+ // TODO(mkrautz): use the lChainIndex and lElementIndex fields -+ // of the CertChainPolicyStatus to provide proper context, instead -+ // using c. -+ if status.Error != 0 { -+ switch status.Error { -+ case syscall.CERT_E_EXPIRED: -+ return CertificateInvalidError{c, Expired, ""} -+ case syscall.CERT_E_CN_NO_MATCH: -+ return HostnameError{c, opts.DNSName} -+ case syscall.CERT_E_UNTRUSTEDROOT: -+ return UnknownAuthorityError{c, nil, nil} -+ default: -+ return UnknownAuthorityError{c, nil, nil} -+ } -+ } -+ -+ return nil -+} -+ -+// windowsExtKeyUsageOIDs are the C NUL-terminated string representations of the -+// OIDs for use with the Windows API. -+var windowsExtKeyUsageOIDs = make(map[ExtKeyUsage][]byte, len(extKeyUsageOIDs)) -+ -+func init() { -+ for _, eku := range extKeyUsageOIDs { -+ windowsExtKeyUsageOIDs[eku.extKeyUsage] = []byte(eku.oid.String() + "\x00") -+ } -+} -+ -+func verifyChain(c *Certificate, chainCtx *syscall.CertChainContext, opts *VerifyOptions) (chain []*Certificate, err error) { -+ err = checkChainTrustStatus(c, chainCtx) -+ if err != nil { -+ return nil, err -+ } -+ -+ if opts != nil && len(opts.DNSName) > 0 { -+ err = checkChainSSLServerPolicy(c, chainCtx, opts) -+ if err != nil { -+ return nil, err -+ } -+ } -+ -+ chain, err = extractSimpleChain(chainCtx.Chains, int(chainCtx.ChainCount)) -+ if err != nil { -+ return nil, err -+ } -+ if len(chain) == 0 { -+ return nil, errors.New("x509: internal error: system verifier returned an empty chain") -+ } -+ -+ // Mitigate CVE-2020-0601, where the Windows system verifier might be -+ // tricked into using custom curve parameters for a trusted root, by -+ // double-checking all ECDSA signatures. If the system was tricked into -+ // using spoofed parameters, the signature will be invalid for the correct -+ // ones we parsed. (We don't support custom curves ourselves.) -+ for i, parent := range chain[1:] { -+ if parent.PublicKeyAlgorithm != ECDSA { -+ continue -+ } -+ if err := parent.CheckSignature(chain[i].SignatureAlgorithm, -+ chain[i].RawTBSCertificate, chain[i].Signature); err != nil { -+ return nil, err -+ } -+ } -+ return chain, nil -+} -+ -+// systemVerify is like Verify, except that it uses CryptoAPI calls -+// to build certificate chains and verify them. -+func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) { -+ storeCtx, err := createStoreContext(c, opts) -+ if err != nil { -+ return nil, err -+ } -+ defer syscall.CertFreeCertificateContext(storeCtx) -+ -+ para := new(syscall.CertChainPara) -+ para.Size = uint32(unsafe.Sizeof(*para)) -+ -+ keyUsages := opts.KeyUsages -+ if len(keyUsages) == 0 { -+ keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth} -+ } -+ oids := make([]*byte, 0, len(keyUsages)) -+ for _, eku := range keyUsages { -+ if eku == ExtKeyUsageAny { -+ oids = nil -+ break -+ } -+ if oid, ok := windowsExtKeyUsageOIDs[eku]; ok { -+ oids = append(oids, &oid[0]) -+ } -+ } -+ if oids != nil { -+ para.RequestedUsage.Type = syscall.USAGE_MATCH_TYPE_OR -+ para.RequestedUsage.Usage.Length = uint32(len(oids)) -+ para.RequestedUsage.Usage.UsageIdentifiers = &oids[0] -+ } else { -+ para.RequestedUsage.Type = syscall.USAGE_MATCH_TYPE_AND -+ para.RequestedUsage.Usage.Length = 0 -+ para.RequestedUsage.Usage.UsageIdentifiers = nil -+ } -+ -+ var verifyTime *syscall.Filetime -+ if opts != nil && !opts.CurrentTime.IsZero() { -+ ft := syscall.NsecToFiletime(opts.CurrentTime.UnixNano()) -+ verifyTime = &ft -+ } -+ -+ // The default is to return only the highest quality chain, -+ // setting this flag will add additional lower quality contexts. -+ // These are returned in the LowerQualityChains field. -+ const CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS = 0x00000080 -+ -+ // CertGetCertificateChain will traverse Windows's root stores in an attempt to build a verified certificate chain -+ var topCtx *syscall.CertChainContext -+ err = syscall.CertGetCertificateChain(syscall.Handle(0), storeCtx, verifyTime, storeCtx.Store, para, CERT_CHAIN_RETURN_LOWER_QUALITY_CONTEXTS, 0, &topCtx) -+ if err != nil { -+ return nil, err -+ } -+ defer syscall.CertFreeCertificateChain(topCtx) -+ -+ chain, topErr := verifyChain(c, topCtx, opts) -+ if topErr == nil { -+ chains = append(chains, chain) -+ } -+ -+ if lqCtxCount := topCtx.LowerQualityChainCount; lqCtxCount > 0 { -+ lqCtxs := unsafe.Slice(topCtx.LowerQualityChains, lqCtxCount) -+ for _, ctx := range lqCtxs { -+ chain, err := verifyChain(c, ctx, opts) -+ if err == nil { -+ chains = append(chains, chain) -+ } -+ } -+ } -+ -+ if len(chains) == 0 { -+ // Return the error from the highest quality context. -+ return nil, topErr -+ } -+ -+ return chains, nil -+} -diff --git a/src/crypto/x509/root_windows_test.go-e b/src/crypto/x509/root_windows_test.go-e -new file mode 100644 -index 0000000000..1372c043b2 ---- /dev/null -+++ b/src/crypto/x509/root_windows_test.go-e -@@ -0,0 +1,127 @@ -+// Copyright 2021 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. -+ -+package x509_test -+ -+import ( -+ "crypto/tls" -+ "crypto/x509" -+ "errors" -+ "internal/testenv" -+ "net" -+ "strings" -+ "syscall" -+ "testing" -+ "time" -+) -+ -+func TestPlatformVerifierLegacy(t *testing.T) { -+ // TODO(#52108): This can be removed once the synthetic test root is deployed on -+ // builders. -+ if !testenv.HasExternalNetwork() { -+ t.Skip() -+ } -+ -+ getChain := func(t *testing.T, host string) []*x509.Certificate { -+ t.Helper() -+ c, err := tls.Dial("tcp", host+":443", &tls.Config{InsecureSkipVerify: true}) -+ if err != nil { -+ // From https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2, -+ // matching the error string observed in https://go.dev/issue/52094. -+ const WSATRY_AGAIN syscall.Errno = 11002 -+ var errDNS *net.DNSError -+ if strings.HasSuffix(host, ".badssl.com") && errors.As(err, &errDNS) && strings.HasSuffix(errDNS.Err, WSATRY_AGAIN.Error()) { -+ t.Log(err) -+ testenv.SkipFlaky(t, 52094) -+ } -+ -+ t.Fatalf("tls connection failed: %s", err) -+ } -+ return c.ConnectionState().PeerCertificates -+ } -+ -+ tests := []struct { -+ name string -+ host string -+ verifyName string -+ verifyTime time.Time -+ expectedErr string -+ }{ -+ { -+ // whatever google.com serves should, hopefully, be trusted -+ name: "valid chain", -+ host: "google.com", -+ }, -+ { -+ name: "valid chain (dns check)", -+ host: "google.com", -+ verifyName: "google.com", -+ }, -+ { -+ name: "valid chain (fqdn dns check)", -+ host: "google.com.", -+ verifyName: "google.com.", -+ }, -+ { -+ name: "expired leaf", -+ host: "expired.badssl.com", -+ expectedErr: "x509: certificate has expired or is not yet valid: ", -+ }, -+ { -+ name: "wrong host for leaf", -+ host: "wrong.host.badssl.com", -+ verifyName: "wrong.host.badssl.com", -+ expectedErr: "x509: certificate is valid for *.badssl.com, badssl.com, not wrong.host.badssl.com", -+ }, -+ { -+ name: "self-signed leaf", -+ host: "self-signed.badssl.com", -+ expectedErr: "x509: certificate signed by unknown authority", -+ }, -+ { -+ name: "untrusted root", -+ host: "untrusted-root.badssl.com", -+ expectedErr: "x509: certificate signed by unknown authority", -+ }, -+ { -+ name: "expired leaf (custom time)", -+ host: "google.com", -+ verifyTime: time.Time{}.Add(time.Hour), -+ expectedErr: "x509: certificate has expired or is not yet valid: ", -+ }, -+ { -+ name: "valid chain (custom time)", -+ host: "google.com", -+ verifyTime: time.Now(), -+ }, -+ } -+ -+ for _, tc := range tests { -+ t.Run(tc.name, func(t *testing.T) { -+ chain := getChain(t, tc.host) -+ var opts x509.VerifyOptions -+ if len(chain) > 1 { -+ opts.Intermediates = x509.NewCertPool() -+ for _, c := range chain[1:] { -+ opts.Intermediates.AddCert(c) -+ } -+ } -+ if tc.verifyName != "" { -+ opts.DNSName = tc.verifyName -+ } -+ if !tc.verifyTime.IsZero() { -+ opts.CurrentTime = tc.verifyTime -+ } -+ -+ _, err := chain[0].Verify(opts) -+ if err != nil && tc.expectedErr == "" { -+ t.Errorf("unexpected verification error: %s", err) -+ } else if err != nil && err.Error() != tc.expectedErr { -+ t.Errorf("unexpected verification error: got %q, want %q", err.Error(), tc.expectedErr) -+ } else if err == nil && tc.expectedErr != "" { -+ t.Errorf("unexpected verification success: want %q", tc.expectedErr) -+ } -+ }) -+ } -+} -diff --git a/src/crypto/x509/sec1.go-e b/src/crypto/x509/sec1.go-e -new file mode 100644 -index 0000000000..6bfba0d93f ---- /dev/null -+++ b/src/crypto/x509/sec1.go-e -@@ -0,0 +1,136 @@ -+// Copyright 2012 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. -+ -+package x509 -+ -+import ( -+ "crypto/ecdh" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "encoding/asn1" -+ "errors" -+ "fmt" -+ "math/big" -+) -+ -+const ecPrivKeyVersion = 1 -+ -+// ecPrivateKey reflects an ASN.1 Elliptic Curve Private Key Structure. -+// References: -+// -+// RFC 5915 -+// SEC1 - http://www.secg.org/sec1-v2.pdf -+// -+// Per RFC 5915 the NamedCurveOID is marked as ASN.1 OPTIONAL, however in -+// most cases it is not. -+type ecPrivateKey struct { -+ Version int -+ PrivateKey []byte -+ NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"` -+ PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"` -+} -+ -+// ParseECPrivateKey parses an EC private key in SEC 1, ASN.1 DER form. -+// -+// This kind of key is commonly encoded in PEM blocks of type "EC PRIVATE KEY". -+func ParseECPrivateKey(der []byte) (*ecdsa.PrivateKey, error) { -+ return parseECPrivateKey(nil, der) -+} -+ -+// MarshalECPrivateKey converts an EC private key to SEC 1, ASN.1 DER form. -+// -+// This kind of key is commonly encoded in PEM blocks of type "EC PRIVATE KEY". -+// For a more flexible key format which is not EC specific, use -+// MarshalPKCS8PrivateKey. -+func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) { -+ oid, ok := oidFromNamedCurve(key.Curve) -+ if !ok { -+ return nil, errors.New("x509: unknown elliptic curve") -+ } -+ -+ return marshalECPrivateKeyWithOID(key, oid) -+} -+ -+// marshalECPrivateKeyWithOID marshals an EC private key into ASN.1, DER format and -+// sets the curve ID to the given OID, or omits it if OID is nil. -+func marshalECPrivateKeyWithOID(key *ecdsa.PrivateKey, oid asn1.ObjectIdentifier) ([]byte, error) { -+ if !key.Curve.IsOnCurve(key.X, key.Y) { -+ return nil, errors.New("invalid elliptic key public key") -+ } -+ privateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8) -+ return asn1.Marshal(ecPrivateKey{ -+ Version: 1, -+ PrivateKey: key.D.FillBytes(privateKey), -+ NamedCurveOID: oid, -+ PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}, -+ }) -+} -+ -+// marshalECDHPrivateKey marshals an EC private key into ASN.1, DER format -+// suitable for NIST curves. -+func marshalECDHPrivateKey(key *ecdh.PrivateKey) ([]byte, error) { -+ return asn1.Marshal(ecPrivateKey{ -+ Version: 1, -+ PrivateKey: key.Bytes(), -+ PublicKey: asn1.BitString{Bytes: key.PublicKey().Bytes()}, -+ }) -+} -+ -+// parseECPrivateKey parses an ASN.1 Elliptic Curve Private Key Structure. -+// The OID for the named curve may be provided from another source (such as -+// the PKCS8 container) - if it is provided then use this instead of the OID -+// that may exist in the EC private key structure. -+func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) { -+ var privKey ecPrivateKey -+ if _, err := asn1.Unmarshal(der, &privKey); err != nil { -+ if _, err := asn1.Unmarshal(der, &pkcs8{}); err == nil { -+ return nil, errors.New("x509: failed to parse private key (use ParsePKCS8PrivateKey instead for this key format)") -+ } -+ if _, err := asn1.Unmarshal(der, &pkcs1PrivateKey{}); err == nil { -+ return nil, errors.New("x509: failed to parse private key (use ParsePKCS1PrivateKey instead for this key format)") -+ } -+ return nil, errors.New("x509: failed to parse EC private key: " + err.Error()) -+ } -+ if privKey.Version != ecPrivKeyVersion { -+ return nil, fmt.Errorf("x509: unknown EC private key version %d", privKey.Version) -+ } -+ -+ var curve elliptic.Curve -+ if namedCurveOID != nil { -+ curve = namedCurveFromOID(*namedCurveOID) -+ } else { -+ curve = namedCurveFromOID(privKey.NamedCurveOID) -+ } -+ if curve == nil { -+ return nil, errors.New("x509: unknown elliptic curve") -+ } -+ -+ k := new(big.Int).SetBytes(privKey.PrivateKey) -+ curveOrder := curve.Params().N -+ if k.Cmp(curveOrder) >= 0 { -+ return nil, errors.New("x509: invalid elliptic curve private key value") -+ } -+ priv := new(ecdsa.PrivateKey) -+ priv.Curve = curve -+ priv.D = k -+ -+ privateKey := make([]byte, (curveOrder.BitLen()+7)/8) -+ -+ // Some private keys have leading zero padding. This is invalid -+ // according to [SEC1], but this code will ignore it. -+ for len(privKey.PrivateKey) > len(privateKey) { -+ if privKey.PrivateKey[0] != 0 { -+ return nil, errors.New("x509: invalid private key length") -+ } -+ privKey.PrivateKey = privKey.PrivateKey[1:] -+ } -+ -+ // Some private keys remove all leading zeros, this is also invalid -+ // according to [SEC1] but since OpenSSL used to do this, we ignore -+ // this too. -+ copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey) -+ priv.X, priv.Y = curve.ScalarBaseMult(privateKey) -+ -+ return priv, nil -+} -diff --git a/src/crypto/x509/sec1_test.go-e b/src/crypto/x509/sec1_test.go-e -new file mode 100644 -index 0000000000..9ac251896b ---- /dev/null -+++ b/src/crypto/x509/sec1_test.go-e -@@ -0,0 +1,66 @@ -+// Copyright 2012 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. -+ -+package x509 -+ -+import ( -+ "bytes" -+ "encoding/hex" -+ "strings" -+ "testing" -+) -+ -+var ecKeyTests = []struct { -+ derHex string -+ shouldReserialize bool -+}{ -+ // Generated using: -+ // openssl ecparam -genkey -name secp384r1 -outform PEM -+ {"3081a40201010430bdb9839c08ee793d1157886a7a758a3c8b2a17a4df48f17ace57c72c56b4723cf21dcda21d4e1ad57ff034f19fcfd98ea00706052b81040022a16403620004feea808b5ee2429cfcce13c32160e1c960990bd050bb0fdf7222f3decd0a55008e32a6aa3c9062051c4cba92a7a3b178b24567412d43cdd2f882fa5addddd726fe3e208d2c26d733a773a597abb749714df7256ead5105fa6e7b3650de236b50", true}, -+ // This key was generated by GnuTLS and has illegal zero-padding of the -+ // private key. See https://golang.org/issues/13699. -+ {"3078020101042100f9f43a04b9bdc3ab01f53be6df80e7a7bc3eaf7b87fc24e630a4a0aa97633645a00a06082a8648ce3d030107a1440342000441a51bc318461b4c39a45048a16d4fc2a935b1ea7fe86e8c1fa219d6f2438f7c7fd62957d3442efb94b6a23eb0ea66dda663dc42f379cda6630b21b7888a5d3d", false}, -+ // This was generated using an old version of OpenSSL and is missing a -+ // leading zero byte in the private key that should be present. -+ {"3081db0201010441607b4f985774ac21e633999794542e09312073480baa69550914d6d43d8414441e61b36650567901da714f94dffb3ce0e2575c31928a0997d51df5c440e983ca17a00706052b81040023a181890381860004001661557afedd7ac8d6b70e038e576558c626eb62edda36d29c3a1310277c11f67a8c6f949e5430a37dcfb95d902c1b5b5379c389873b9dd17be3bdb088a4774a7401072f830fb9a08d93bfa50a03dd3292ea07928724ddb915d831917a338f6b0aecfbc3cf5352c4a1295d356890c41c34116d29eeb93779aab9d9d78e2613437740f6", false}, -+} -+ -+func TestParseECPrivateKey(t *testing.T) { -+ for i, test := range ecKeyTests { -+ derBytes, _ := hex.DecodeString(test.derHex) -+ key, err := ParseECPrivateKey(derBytes) -+ if err != nil { -+ t.Fatalf("#%d: failed to decode EC private key: %s", i, err) -+ } -+ serialized, err := MarshalECPrivateKey(key) -+ if err != nil { -+ t.Fatalf("#%d: failed to encode EC private key: %s", i, err) -+ } -+ matches := bytes.Equal(serialized, derBytes) -+ if matches != test.shouldReserialize { -+ t.Fatalf("#%d: when serializing key: matches=%t, should match=%t: original %x, reserialized %x", i, matches, test.shouldReserialize, serialized, derBytes) -+ } -+ } -+} -+ -+const hexECTestPKCS1Key = "3082025c02010002818100b1a1e0945b9289c4d3f1329f8a982c4a2dcd59bfd372fb8085a9c517554607ebd2f7990eef216ac9f4605f71a03b04f42a5255b158cf8e0844191f5119348baa44c35056e20609bcf9510f30ead4b481c81d7865fb27b8e0090e112b717f3ee08cdfc4012da1f1f7cf2a1bc34c73a54a12b06372d09714742dd7895eadde4aa5020301000102818062b7fa1db93e993e40237de4d89b7591cc1ea1d04fed4904c643f17ae4334557b4295270d0491c161cb02a9af557978b32b20b59c267a721c4e6c956c2d147046e9ae5f2da36db0106d70021fa9343455f8f973a4b355a26fd19e6b39dee0405ea2b32deddf0f4817759ef705d02b34faab9ca93c6766e9f722290f119f34449024100d9c29a4a013a90e35fd1be14a3f747c589fac613a695282d61812a711906b8a0876c6181f0333ca1066596f57bff47e7cfcabf19c0fc69d9cd76df743038b3cb024100d0d3546fecf879b5551f2bd2c05e6385f2718a08a6face3d2aecc9d7e03645a480a46c81662c12ad6bd6901e3bd4f38029462de7290859567cdf371c79088d4f024100c254150657e460ea58573fcf01a82a4791e3d6223135c8bdfed69afe84fbe7857274f8eb5165180507455f9b4105c6b08b51fe8a481bb986a202245576b713530240045700003b7a867d0041df9547ae2e7f50248febd21c9040b12dae9c2feab0d3d4609668b208e4727a3541557f84d372ac68eaf74ce1018a4c9a0ef92682c8fd02405769731480bb3a4570abf422527c5f34bf732fa6c1e08cc322753c511ce055fac20fc770025663ad3165324314df907f1f1942f0448a7e9cdbf87ecd98b92156" -+const hexECTestPKCS8Key = "30820278020100300d06092a864886f70d0101010500048202623082025e02010002818100cfb1b5bf9685ffa97b4f99df4ff122b70e59ac9b992f3bc2b3dde17d53c1a34928719b02e8fd17839499bfbd515bd6ef99c7a1c47a239718fe36bfd824c0d96060084b5f67f0273443007a24dfaf5634f7772c9346e10eb294c2306671a5a5e719ae24b4de467291bc571014b0e02dec04534d66a9bb171d644b66b091780e8d020301000102818100b595778383c4afdbab95d2bfed12b3f93bb0a73a7ad952f44d7185fd9ec6c34de8f03a48770f2009c8580bcd275e9632714e9a5e3f32f29dc55474b2329ff0ebc08b3ffcb35bc96e6516b483df80a4a59cceb71918cbabf91564e64a39d7e35dce21cb3031824fdbc845dba6458852ec16af5dddf51a8397a8797ae0337b1439024100ea0eb1b914158c70db39031dd8904d6f18f408c85fbbc592d7d20dee7986969efbda081fdf8bc40e1b1336d6b638110c836bfdc3f314560d2e49cd4fbde1e20b024100e32a4e793b574c9c4a94c8803db5152141e72d03de64e54ef2c8ed104988ca780cd11397bc359630d01b97ebd87067c5451ba777cf045ca23f5912f1031308c702406dfcdbbd5a57c9f85abc4edf9e9e29153507b07ce0a7ef6f52e60dcfebe1b8341babd8b789a837485da6c8d55b29bbb142ace3c24a1f5b54b454d01b51e2ad03024100bd6a2b60dee01e1b3bfcef6a2f09ed027c273cdbbaf6ba55a80f6dcc64e4509ee560f84b4f3e076bd03b11e42fe71a3fdd2dffe7e0902c8584f8cad877cdc945024100aa512fa4ada69881f1d8bb8ad6614f192b83200aef5edf4811313d5ef30a86cbd0a90f7b025c71ea06ec6b34db6306c86b1040670fd8654ad7291d066d06d031" -+ -+var ecMismatchKeyTests = []struct { -+ hexKey string -+ errorContains string -+}{ -+ {hexKey: hexECTestPKCS8Key, errorContains: "use ParsePKCS8PrivateKey instead"}, -+ {hexKey: hexECTestPKCS1Key, errorContains: "use ParsePKCS1PrivateKey instead"}, -+} -+ -+func TestECMismatchKeyFormat(t *testing.T) { -+ for i, test := range ecMismatchKeyTests { -+ derBytes, _ := hex.DecodeString(test.hexKey) -+ _, err := ParseECPrivateKey(derBytes) -+ if !strings.Contains(err.Error(), test.errorContains) { -+ t.Errorf("#%d: expected error containing %q, got %s", i, test.errorContains, err) -+ } -+ } -+} -diff --git a/src/crypto/x509/verify.go-e b/src/crypto/x509/verify.go-e -new file mode 100644 -index 0000000000..345d434453 ---- /dev/null -+++ b/src/crypto/x509/verify.go-e -@@ -0,0 +1,1176 @@ -+// Copyright 2011 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. -+ -+package x509 -+ -+import ( -+ "bytes" -+ "crypto" -+ "crypto/x509/pkix" -+ "errors" -+ "fmt" -+ "net" -+ "net/url" -+ "reflect" -+ "runtime" -+ "strings" -+ "time" -+ "unicode/utf8" -+) -+ -+type InvalidReason int -+ -+const ( -+ // NotAuthorizedToSign results when a certificate is signed by another -+ // which isn't marked as a CA certificate. -+ NotAuthorizedToSign InvalidReason = iota -+ // Expired results when a certificate has expired, based on the time -+ // given in the VerifyOptions. -+ Expired -+ // CANotAuthorizedForThisName results when an intermediate or root -+ // certificate has a name constraint which doesn't permit a DNS or -+ // other name (including IP address) in the leaf certificate. -+ CANotAuthorizedForThisName -+ // TooManyIntermediates results when a path length constraint is -+ // violated. -+ TooManyIntermediates -+ // IncompatibleUsage results when the certificate's key usage indicates -+ // that it may only be used for a different purpose. -+ IncompatibleUsage -+ // NameMismatch results when the subject name of a parent certificate -+ // does not match the issuer name in the child. -+ NameMismatch -+ // NameConstraintsWithoutSANs is a legacy error and is no longer returned. -+ NameConstraintsWithoutSANs -+ // UnconstrainedName results when a CA certificate contains permitted -+ // name constraints, but leaf certificate contains a name of an -+ // unsupported or unconstrained type. -+ UnconstrainedName -+ // TooManyConstraints results when the number of comparison operations -+ // needed to check a certificate exceeds the limit set by -+ // VerifyOptions.MaxConstraintComparisions. This limit exists to -+ // prevent pathological certificates can consuming excessive amounts of -+ // CPU time to verify. -+ TooManyConstraints -+ // CANotAuthorizedForExtKeyUsage results when an intermediate or root -+ // certificate does not permit a requested extended key usage. -+ CANotAuthorizedForExtKeyUsage -+) -+ -+// CertificateInvalidError results when an odd error occurs. Users of this -+// library probably want to handle all these errors uniformly. -+type CertificateInvalidError struct { -+ Cert *Certificate -+ Reason InvalidReason -+ Detail string -+} -+ -+func (e CertificateInvalidError) Error() string { -+ switch e.Reason { -+ case NotAuthorizedToSign: -+ return "x509: certificate is not authorized to sign other certificates" -+ case Expired: -+ return "x509: certificate has expired or is not yet valid: " + e.Detail -+ case CANotAuthorizedForThisName: -+ return "x509: a root or intermediate certificate is not authorized to sign for this name: " + e.Detail -+ case CANotAuthorizedForExtKeyUsage: -+ return "x509: a root or intermediate certificate is not authorized for an extended key usage: " + e.Detail -+ case TooManyIntermediates: -+ return "x509: too many intermediates for path length constraint" -+ case IncompatibleUsage: -+ return "x509: certificate specifies an incompatible key usage" -+ case NameMismatch: -+ return "x509: issuer name does not match subject from issuing certificate" -+ case NameConstraintsWithoutSANs: -+ return "x509: issuer has name constraints but leaf doesn't have a SAN extension" -+ case UnconstrainedName: -+ return "x509: issuer has name constraints but leaf contains unknown or unconstrained name: " + e.Detail -+ } -+ return "x509: unknown error" -+} -+ -+// HostnameError results when the set of authorized names doesn't match the -+// requested name. -+type HostnameError struct { -+ Certificate *Certificate -+ Host string -+} -+ -+func (h HostnameError) Error() string { -+ c := h.Certificate -+ -+ if !c.hasSANExtension() && matchHostnames(c.Subject.CommonName, h.Host) { -+ return "x509: certificate relies on legacy Common Name field, use SANs instead" -+ } -+ -+ var valid string -+ if ip := net.ParseIP(h.Host); ip != nil { -+ // Trying to validate an IP -+ if len(c.IPAddresses) == 0 { -+ return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs" -+ } -+ for _, san := range c.IPAddresses { -+ if len(valid) > 0 { -+ valid += ", " -+ } -+ valid += san.String() -+ } -+ } else { -+ valid = strings.Join(c.DNSNames, ", ") -+ } -+ -+ if len(valid) == 0 { -+ return "x509: certificate is not valid for any names, but wanted to match " + h.Host -+ } -+ return "x509: certificate is valid for " + valid + ", not " + h.Host -+} -+ -+// UnknownAuthorityError results when the certificate issuer is unknown -+type UnknownAuthorityError struct { -+ Cert *Certificate -+ // hintErr contains an error that may be helpful in determining why an -+ // authority wasn't found. -+ hintErr error -+ // hintCert contains a possible authority certificate that was rejected -+ // because of the error in hintErr. -+ hintCert *Certificate -+} -+ -+func (e UnknownAuthorityError) Error() string { -+ s := "x509: certificate signed by unknown authority" -+ if e.hintErr != nil { -+ certName := e.hintCert.Subject.CommonName -+ if len(certName) == 0 { -+ if len(e.hintCert.Subject.Organization) > 0 { -+ certName = e.hintCert.Subject.Organization[0] -+ } else { -+ certName = "serial:" + e.hintCert.SerialNumber.String() -+ } -+ } -+ s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName) -+ } -+ return s -+} -+ -+// SystemRootsError results when we fail to load the system root certificates. -+type SystemRootsError struct { -+ Err error -+} -+ -+func (se SystemRootsError) Error() string { -+ msg := "x509: failed to load system roots and no roots provided" -+ if se.Err != nil { -+ return msg + "; " + se.Err.Error() -+ } -+ return msg -+} -+ -+func (se SystemRootsError) Unwrap() error { return se.Err } -+ -+// errNotParsed is returned when a certificate without ASN.1 contents is -+// verified. Platform-specific verification needs the ASN.1 contents. -+var errNotParsed = errors.New("x509: missing ASN.1 contents; use ParseCertificate") -+ -+// VerifyOptions contains parameters for Certificate.Verify. -+type VerifyOptions struct { -+ // DNSName, if set, is checked against the leaf certificate with -+ // Certificate.VerifyHostname or the platform verifier. -+ DNSName string -+ -+ // Intermediates is an optional pool of certificates that are not trust -+ // anchors, but can be used to form a chain from the leaf certificate to a -+ // root certificate. -+ Intermediates *CertPool -+ // Roots is the set of trusted root certificates the leaf certificate needs -+ // to chain up to. If nil, the system roots or the platform verifier are used. -+ Roots *CertPool -+ -+ // CurrentTime is used to check the validity of all certificates in the -+ // chain. If zero, the current time is used. -+ CurrentTime time.Time -+ -+ // KeyUsages specifies which Extended Key Usage values are acceptable. A -+ // chain is accepted if it allows any of the listed values. An empty list -+ // means ExtKeyUsageServerAuth. To accept any key usage, include ExtKeyUsageAny. -+ KeyUsages []ExtKeyUsage -+ -+ // MaxConstraintComparisions is the maximum number of comparisons to -+ // perform when checking a given certificate's name constraints. If -+ // zero, a sensible default is used. This limit prevents pathological -+ // certificates from consuming excessive amounts of CPU time when -+ // validating. It does not apply to the platform verifier. -+ MaxConstraintComparisions int -+} -+ -+const ( -+ leafCertificate = iota -+ intermediateCertificate -+ rootCertificate -+) -+ -+// rfc2821Mailbox represents a “mailbox” (which is an email address to most -+// people) by breaking it into the “local” (i.e. before the '@') and “domain” -+// parts. -+type rfc2821Mailbox struct { -+ local, domain string -+} -+ -+// parseRFC2821Mailbox parses an email address into local and domain parts, -+// based on the ABNF for a “Mailbox” from RFC 2821. According to RFC 5280, -+// Section 4.2.1.6 that's correct for an rfc822Name from a certificate: “The -+// format of an rfc822Name is a "Mailbox" as defined in RFC 2821, Section 4.1.2”. -+func parseRFC2821Mailbox(in string) (mailbox rfc2821Mailbox, ok bool) { -+ if len(in) == 0 { -+ return mailbox, false -+ } -+ -+ localPartBytes := make([]byte, 0, len(in)/2) -+ -+ if in[0] == '"' { -+ // Quoted-string = DQUOTE *qcontent DQUOTE -+ // non-whitespace-control = %d1-8 / %d11 / %d12 / %d14-31 / %d127 -+ // qcontent = qtext / quoted-pair -+ // qtext = non-whitespace-control / -+ // %d33 / %d35-91 / %d93-126 -+ // quoted-pair = ("\" text) / obs-qp -+ // text = %d1-9 / %d11 / %d12 / %d14-127 / obs-text -+ // -+ // (Names beginning with “obs-” are the obsolete syntax from RFC 2822, -+ // Section 4. Since it has been 16 years, we no longer accept that.) -+ in = in[1:] -+ QuotedString: -+ for { -+ if len(in) == 0 { -+ return mailbox, false -+ } -+ c := in[0] -+ in = in[1:] -+ -+ switch { -+ case c == '"': -+ break QuotedString -+ -+ case c == '\\': -+ // quoted-pair -+ if len(in) == 0 { -+ return mailbox, false -+ } -+ if in[0] == 11 || -+ in[0] == 12 || -+ (1 <= in[0] && in[0] <= 9) || -+ (14 <= in[0] && in[0] <= 127) { -+ localPartBytes = append(localPartBytes, in[0]) -+ in = in[1:] -+ } else { -+ return mailbox, false -+ } -+ -+ case c == 11 || -+ c == 12 || -+ // Space (char 32) is not allowed based on the -+ // BNF, but RFC 3696 gives an example that -+ // assumes that it is. Several “verified” -+ // errata continue to argue about this point. -+ // We choose to accept it. -+ c == 32 || -+ c == 33 || -+ c == 127 || -+ (1 <= c && c <= 8) || -+ (14 <= c && c <= 31) || -+ (35 <= c && c <= 91) || -+ (93 <= c && c <= 126): -+ // qtext -+ localPartBytes = append(localPartBytes, c) -+ -+ default: -+ return mailbox, false -+ } -+ } -+ } else { -+ // Atom ("." Atom)* -+ NextChar: -+ for len(in) > 0 { -+ // atext from RFC 2822, Section 3.2.4 -+ c := in[0] -+ -+ switch { -+ case c == '\\': -+ // Examples given in RFC 3696 suggest that -+ // escaped characters can appear outside of a -+ // quoted string. Several “verified” errata -+ // continue to argue the point. We choose to -+ // accept it. -+ in = in[1:] -+ if len(in) == 0 { -+ return mailbox, false -+ } -+ fallthrough -+ -+ case ('0' <= c && c <= '9') || -+ ('a' <= c && c <= 'z') || -+ ('A' <= c && c <= 'Z') || -+ c == '!' || c == '#' || c == '$' || c == '%' || -+ c == '&' || c == '\'' || c == '*' || c == '+' || -+ c == '-' || c == '/' || c == '=' || c == '?' || -+ c == '^' || c == '_' || c == '`' || c == '{' || -+ c == '|' || c == '}' || c == '~' || c == '.': -+ localPartBytes = append(localPartBytes, in[0]) -+ in = in[1:] -+ -+ default: -+ break NextChar -+ } -+ } -+ -+ if len(localPartBytes) == 0 { -+ return mailbox, false -+ } -+ -+ // From RFC 3696, Section 3: -+ // “period (".") may also appear, but may not be used to start -+ // or end the local part, nor may two or more consecutive -+ // periods appear.” -+ twoDots := []byte{'.', '.'} -+ if localPartBytes[0] == '.' || -+ localPartBytes[len(localPartBytes)-1] == '.' || -+ bytes.Contains(localPartBytes, twoDots) { -+ return mailbox, false -+ } -+ } -+ -+ if len(in) == 0 || in[0] != '@' { -+ return mailbox, false -+ } -+ in = in[1:] -+ -+ // The RFC species a format for domains, but that's known to be -+ // violated in practice so we accept that anything after an '@' is the -+ // domain part. -+ if _, ok := domainToReverseLabels(in); !ok { -+ return mailbox, false -+ } -+ -+ mailbox.local = string(localPartBytes) -+ mailbox.domain = in -+ return mailbox, true -+} -+ -+// domainToReverseLabels converts a textual domain name like foo.example.com to -+// the list of labels in reverse order, e.g. ["com", "example", "foo"]. -+func domainToReverseLabels(domain string) (reverseLabels []string, ok bool) { -+ for len(domain) > 0 { -+ if i := strings.LastIndexByte(domain, '.'); i == -1 { -+ reverseLabels = append(reverseLabels, domain) -+ domain = "" -+ } else { -+ reverseLabels = append(reverseLabels, domain[i+1:]) -+ domain = domain[:i] -+ } -+ } -+ -+ if len(reverseLabels) > 0 && len(reverseLabels[0]) == 0 { -+ // An empty label at the end indicates an absolute value. -+ return nil, false -+ } -+ -+ for _, label := range reverseLabels { -+ if len(label) == 0 { -+ // Empty labels are otherwise invalid. -+ return nil, false -+ } -+ -+ for _, c := range label { -+ if c < 33 || c > 126 { -+ // Invalid character. -+ return nil, false -+ } -+ } -+ } -+ -+ return reverseLabels, true -+} -+ -+func matchEmailConstraint(mailbox rfc2821Mailbox, constraint string) (bool, error) { -+ // If the constraint contains an @, then it specifies an exact mailbox -+ // name. -+ if strings.Contains(constraint, "@") { -+ constraintMailbox, ok := parseRFC2821Mailbox(constraint) -+ if !ok { -+ return false, fmt.Errorf("x509: internal error: cannot parse constraint %q", constraint) -+ } -+ return mailbox.local == constraintMailbox.local && strings.EqualFold(mailbox.domain, constraintMailbox.domain), nil -+ } -+ -+ // Otherwise the constraint is like a DNS constraint of the domain part -+ // of the mailbox. -+ return matchDomainConstraint(mailbox.domain, constraint) -+} -+ -+func matchURIConstraint(uri *url.URL, constraint string) (bool, error) { -+ // From RFC 5280, Section 4.2.1.10: -+ // “a uniformResourceIdentifier that does not include an authority -+ // component with a host name specified as a fully qualified domain -+ // name (e.g., if the URI either does not include an authority -+ // component or includes an authority component in which the host name -+ // is specified as an IP address), then the application MUST reject the -+ // certificate.” -+ -+ host := uri.Host -+ if len(host) == 0 { -+ return false, fmt.Errorf("URI with empty host (%q) cannot be matched against constraints", uri.String()) -+ } -+ -+ if strings.Contains(host, ":") && !strings.HasSuffix(host, "]") { -+ var err error -+ host, _, err = net.SplitHostPort(uri.Host) -+ if err != nil { -+ return false, err -+ } -+ } -+ -+ if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") || -+ net.ParseIP(host) != nil { -+ return false, fmt.Errorf("URI with IP (%q) cannot be matched against constraints", uri.String()) -+ } -+ -+ return matchDomainConstraint(host, constraint) -+} -+ -+func matchIPConstraint(ip net.IP, constraint *net.IPNet) (bool, error) { -+ if len(ip) != len(constraint.IP) { -+ return false, nil -+ } -+ -+ for i := range ip { -+ if mask := constraint.Mask[i]; ip[i]&mask != constraint.IP[i]&mask { -+ return false, nil -+ } -+ } -+ -+ return true, nil -+} -+ -+func matchDomainConstraint(domain, constraint string) (bool, error) { -+ // The meaning of zero length constraints is not specified, but this -+ // code follows NSS and accepts them as matching everything. -+ if len(constraint) == 0 { -+ return true, nil -+ } -+ -+ domainLabels, ok := domainToReverseLabels(domain) -+ if !ok { -+ return false, fmt.Errorf("x509: internal error: cannot parse domain %q", domain) -+ } -+ -+ // RFC 5280 says that a leading period in a domain name means that at -+ // least one label must be prepended, but only for URI and email -+ // constraints, not DNS constraints. The code also supports that -+ // behaviour for DNS constraints. -+ -+ mustHaveSubdomains := false -+ if constraint[0] == '.' { -+ mustHaveSubdomains = true -+ constraint = constraint[1:] -+ } -+ -+ constraintLabels, ok := domainToReverseLabels(constraint) -+ if !ok { -+ return false, fmt.Errorf("x509: internal error: cannot parse domain %q", constraint) -+ } -+ -+ if len(domainLabels) < len(constraintLabels) || -+ (mustHaveSubdomains && len(domainLabels) == len(constraintLabels)) { -+ return false, nil -+ } -+ -+ for i, constraintLabel := range constraintLabels { -+ if !strings.EqualFold(constraintLabel, domainLabels[i]) { -+ return false, nil -+ } -+ } -+ -+ return true, nil -+} -+ -+// checkNameConstraints checks that c permits a child certificate to claim the -+// given name, of type nameType. The argument parsedName contains the parsed -+// form of name, suitable for passing to the match function. The total number -+// of comparisons is tracked in the given count and should not exceed the given -+// limit. -+func (c *Certificate) checkNameConstraints(count *int, -+ maxConstraintComparisons int, -+ nameType string, -+ name string, -+ parsedName any, -+ match func(parsedName, constraint any) (match bool, err error), -+ permitted, excluded any) error { -+ -+ excludedValue := reflect.ValueOf(excluded) -+ -+ *count += excludedValue.Len() -+ if *count > maxConstraintComparisons { -+ return CertificateInvalidError{c, TooManyConstraints, ""} -+ } -+ -+ for i := 0; i < excludedValue.Len(); i++ { -+ constraint := excludedValue.Index(i).Interface() -+ match, err := match(parsedName, constraint) -+ if err != nil { -+ return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()} -+ } -+ -+ if match { -+ return CertificateInvalidError{c, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is excluded by constraint %q", nameType, name, constraint)} -+ } -+ } -+ -+ permittedValue := reflect.ValueOf(permitted) -+ -+ *count += permittedValue.Len() -+ if *count > maxConstraintComparisons { -+ return CertificateInvalidError{c, TooManyConstraints, ""} -+ } -+ -+ ok := true -+ for i := 0; i < permittedValue.Len(); i++ { -+ constraint := permittedValue.Index(i).Interface() -+ -+ var err error -+ if ok, err = match(parsedName, constraint); err != nil { -+ return CertificateInvalidError{c, CANotAuthorizedForThisName, err.Error()} -+ } -+ -+ if ok { -+ break -+ } -+ } -+ -+ if !ok { -+ return CertificateInvalidError{c, CANotAuthorizedForThisName, fmt.Sprintf("%s %q is not permitted by any constraint", nameType, name)} -+ } -+ -+ return nil -+} -+ -+// isValid performs validity checks on c given that it is a candidate to append -+// to the chain in currentChain. -+func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error { -+ if len(c.UnhandledCriticalExtensions) > 0 { -+ return UnhandledCriticalExtension{} -+ } -+ -+ if len(currentChain) > 0 { -+ child := currentChain[len(currentChain)-1] -+ if !bytes.Equal(child.RawIssuer, c.RawSubject) { -+ return CertificateInvalidError{c, NameMismatch, ""} -+ } -+ } -+ -+ now := opts.CurrentTime -+ if now.IsZero() { -+ now = time.Now() -+ } -+ if now.Before(c.NotBefore) { -+ return CertificateInvalidError{ -+ Cert: c, -+ Reason: Expired, -+ Detail: fmt.Sprintf("current time %s is before %s", now.Format(time.RFC3339), c.NotBefore.Format(time.RFC3339)), -+ } -+ } else if now.After(c.NotAfter) { -+ return CertificateInvalidError{ -+ Cert: c, -+ Reason: Expired, -+ Detail: fmt.Sprintf("current time %s is after %s", now.Format(time.RFC3339), c.NotAfter.Format(time.RFC3339)), -+ } -+ } -+ -+ maxConstraintComparisons := opts.MaxConstraintComparisions -+ if maxConstraintComparisons == 0 { -+ maxConstraintComparisons = 250000 -+ } -+ comparisonCount := 0 -+ -+ if certType == intermediateCertificate || certType == rootCertificate { -+ if len(currentChain) == 0 { -+ return errors.New("x509: internal error: empty chain when appending CA cert") -+ } -+ } -+ -+ if (certType == intermediateCertificate || certType == rootCertificate) && -+ c.hasNameConstraints() { -+ toCheck := []*Certificate{} -+ for _, c := range currentChain { -+ if c.hasSANExtension() { -+ toCheck = append(toCheck, c) -+ } -+ } -+ for _, sanCert := range toCheck { -+ err := forEachSAN(sanCert.getSANExtension(), func(tag int, data []byte) error { -+ switch tag { -+ case nameTypeEmail: -+ name := string(data) -+ mailbox, ok := parseRFC2821Mailbox(name) -+ if !ok { -+ return fmt.Errorf("x509: cannot parse rfc822Name %q", mailbox) -+ } -+ -+ if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "email address", name, mailbox, -+ func(parsedName, constraint any) (bool, error) { -+ return matchEmailConstraint(parsedName.(rfc2821Mailbox), constraint.(string)) -+ }, c.PermittedEmailAddresses, c.ExcludedEmailAddresses); err != nil { -+ return err -+ } -+ -+ case nameTypeDNS: -+ name := string(data) -+ if _, ok := domainToReverseLabels(name); !ok { -+ return fmt.Errorf("x509: cannot parse dnsName %q", name) -+ } -+ -+ if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "DNS name", name, name, -+ func(parsedName, constraint any) (bool, error) { -+ return matchDomainConstraint(parsedName.(string), constraint.(string)) -+ }, c.PermittedDNSDomains, c.ExcludedDNSDomains); err != nil { -+ return err -+ } -+ -+ case nameTypeURI: -+ name := string(data) -+ uri, err := url.Parse(name) -+ if err != nil { -+ return fmt.Errorf("x509: internal error: URI SAN %q failed to parse", name) -+ } -+ -+ if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "URI", name, uri, -+ func(parsedName, constraint any) (bool, error) { -+ return matchURIConstraint(parsedName.(*url.URL), constraint.(string)) -+ }, c.PermittedURIDomains, c.ExcludedURIDomains); err != nil { -+ return err -+ } -+ -+ case nameTypeIP: -+ ip := net.IP(data) -+ if l := len(ip); l != net.IPv4len && l != net.IPv6len { -+ return fmt.Errorf("x509: internal error: IP SAN %x failed to parse", data) -+ } -+ -+ if err := c.checkNameConstraints(&comparisonCount, maxConstraintComparisons, "IP address", ip.String(), ip, -+ func(parsedName, constraint any) (bool, error) { -+ return matchIPConstraint(parsedName.(net.IP), constraint.(*net.IPNet)) -+ }, c.PermittedIPRanges, c.ExcludedIPRanges); err != nil { -+ return err -+ } -+ -+ default: -+ // Unknown SAN types are ignored. -+ } -+ -+ return nil -+ }) -+ -+ if err != nil { -+ return err -+ } -+ } -+ } -+ -+ // KeyUsage status flags are ignored. From Engineering Security, Peter -+ // Gutmann: A European government CA marked its signing certificates as -+ // being valid for encryption only, but no-one noticed. Another -+ // European CA marked its signature keys as not being valid for -+ // signatures. A different CA marked its own trusted root certificate -+ // as being invalid for certificate signing. Another national CA -+ // distributed a certificate to be used to encrypt data for the -+ // country’s tax authority that was marked as only being usable for -+ // digital signatures but not for encryption. Yet another CA reversed -+ // the order of the bit flags in the keyUsage due to confusion over -+ // encoding endianness, essentially setting a random keyUsage in -+ // certificates that it issued. Another CA created a self-invalidating -+ // certificate by adding a certificate policy statement stipulating -+ // that the certificate had to be used strictly as specified in the -+ // keyUsage, and a keyUsage containing a flag indicating that the RSA -+ // encryption key could only be used for Diffie-Hellman key agreement. -+ -+ if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) { -+ return CertificateInvalidError{c, NotAuthorizedToSign, ""} -+ } -+ -+ if c.BasicConstraintsValid && c.MaxPathLen >= 0 { -+ numIntermediates := len(currentChain) - 1 -+ if numIntermediates > c.MaxPathLen { -+ return CertificateInvalidError{c, TooManyIntermediates, ""} -+ } -+ } -+ -+ if !boringAllowCert(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 -+} -+ -+// Verify attempts to verify c by building one or more chains from c to a -+// certificate in opts.Roots, using certificates in opts.Intermediates if -+// needed. If successful, it returns one or more chains where the first -+// element of the chain is c and the last element is from opts.Roots. -+// -+// If opts.Roots is nil, the platform verifier might be used, and -+// verification details might differ from what is described below. If system -+// roots are unavailable the returned error will be of type SystemRootsError. -+// -+// Name constraints in the intermediates will be applied to all names claimed -+// in the chain, not just opts.DNSName. Thus it is invalid for a leaf to claim -+// example.com if an intermediate doesn't permit it, even if example.com is not -+// the name being validated. Note that DirectoryName constraints are not -+// supported. -+// -+// Name constraint validation follows the rules from RFC 5280, with the -+// addition that DNS name constraints may use the leading period format -+// defined for emails and URIs. When a constraint has a leading period -+// it indicates that at least one additional label must be prepended to -+// the constrained name to be considered valid. -+// -+// Extended Key Usage values are enforced nested down a chain, so an intermediate -+// or root that enumerates EKUs prevents a leaf from asserting an EKU not in that -+// list. (While this is not specified, it is common practice in order to limit -+// the types of certificates a CA can issue.) -+// -+// Certificates that use SHA1WithRSA and ECDSAWithSHA1 signatures are not supported, -+// and will not be used to build chains. -+// -+// Certificates other than c in the returned chains should not be modified. -+// -+// WARNING: this function doesn't do any revocation checking. -+func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) { -+ // Platform-specific verification needs the ASN.1 contents so -+ // this makes the behavior consistent across platforms. -+ if len(c.Raw) == 0 { -+ return nil, errNotParsed -+ } -+ for i := 0; i < opts.Intermediates.len(); i++ { -+ c, err := opts.Intermediates.cert(i) -+ if err != nil { -+ return nil, fmt.Errorf("crypto/x509: error fetching intermediate: %w", err) -+ } -+ if len(c.Raw) == 0 { -+ return nil, errNotParsed -+ } -+ } -+ -+ // Use platform verifiers, where available, if Roots is from SystemCertPool. -+ if runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios" { -+ // Don't use the system verifier if the system pool was replaced with a non-system pool, -+ // i.e. if SetFallbackRoots was called with x509usefallbackroots=1. -+ systemPool := systemRootsPool() -+ if opts.Roots == nil && (systemPool == nil || systemPool.systemPool) { -+ 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 { -+ opts.Roots = systemRootsPool() -+ if opts.Roots == nil { -+ return nil, SystemRootsError{systemRootsErr} -+ } -+ } -+ -+ err = c.isValid(leafCertificate, nil, &opts) -+ if err != nil { -+ return -+ } -+ -+ if len(opts.DNSName) > 0 { -+ err = c.VerifyHostname(opts.DNSName) -+ if err != nil { -+ return -+ } -+ } -+ -+ var candidateChains [][]*Certificate -+ if opts.Roots.contains(c) { -+ candidateChains = [][]*Certificate{{c}} -+ } else { -+ candidateChains, err = c.buildChains([]*Certificate{c}, nil, &opts) -+ if err != nil { -+ return nil, err -+ } -+ } -+ -+ if len(opts.KeyUsages) == 0 { -+ opts.KeyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth} -+ } -+ -+ for _, eku := range opts.KeyUsages { -+ if eku == ExtKeyUsageAny { -+ // If any key usage is acceptable, no need to check the chain for -+ // key usages. -+ return candidateChains, nil -+ } -+ } -+ -+ chains = make([][]*Certificate, 0, len(candidateChains)) -+ for _, candidate := range candidateChains { -+ if checkChainForKeyUsage(candidate, opts.KeyUsages) { -+ chains = append(chains, candidate) -+ } -+ } -+ -+ if len(chains) == 0 { -+ return nil, CertificateInvalidError{c, IncompatibleUsage, ""} -+ } -+ -+ return chains, nil -+} -+ -+func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate { -+ n := make([]*Certificate, len(chain)+1) -+ copy(n, chain) -+ n[len(chain)] = cert -+ return n -+} -+ -+// alreadyInChain checks whether a candidate certificate is present in a chain. -+// Rather than doing a direct byte for byte equivalency check, we check if the -+// subject, public key, and SAN, if present, are equal. This prevents loops that -+// are created by mutual cross-signatures, or other cross-signature bridge -+// oddities. -+func alreadyInChain(candidate *Certificate, chain []*Certificate) bool { -+ type pubKeyEqual interface { -+ Equal(crypto.PublicKey) bool -+ } -+ -+ var candidateSAN *pkix.Extension -+ for _, ext := range candidate.Extensions { -+ if ext.Id.Equal(oidExtensionSubjectAltName) { -+ candidateSAN = &ext -+ break -+ } -+ } -+ -+ for _, cert := range chain { -+ if !bytes.Equal(candidate.RawSubject, cert.RawSubject) { -+ continue -+ } -+ if !candidate.PublicKey.(pubKeyEqual).Equal(cert.PublicKey) { -+ continue -+ } -+ var certSAN *pkix.Extension -+ for _, ext := range cert.Extensions { -+ if ext.Id.Equal(oidExtensionSubjectAltName) { -+ certSAN = &ext -+ break -+ } -+ } -+ if candidateSAN == nil && certSAN == nil { -+ return true -+ } else if candidateSAN == nil || certSAN == nil { -+ return false -+ } -+ if bytes.Equal(candidateSAN.Value, certSAN.Value) { -+ return true -+ } -+ } -+ return false -+} -+ -+// maxChainSignatureChecks is the maximum number of CheckSignatureFrom calls -+// that an invocation of buildChains will (transitively) make. Most chains are -+// less than 15 certificates long, so this leaves space for multiple chains and -+// for failed checks due to different intermediates having the same Subject. -+const maxChainSignatureChecks = 100 -+ -+func (c *Certificate) buildChains(currentChain []*Certificate, sigChecks *int, opts *VerifyOptions) (chains [][]*Certificate, err error) { -+ var ( -+ hintErr error -+ hintCert *Certificate -+ ) -+ -+ considerCandidate := func(certType int, candidate *Certificate) { -+ if alreadyInChain(candidate, currentChain) { -+ return -+ } -+ -+ if sigChecks == nil { -+ sigChecks = new(int) -+ } -+ *sigChecks++ -+ if *sigChecks > maxChainSignatureChecks { -+ err = errors.New("x509: signature check attempts limit reached while verifying certificate chain") -+ return -+ } -+ -+ if err := c.CheckSignatureFrom(candidate); err != nil { -+ if hintErr == nil { -+ hintErr = err -+ hintCert = candidate -+ } -+ return -+ } -+ -+ err = candidate.isValid(certType, currentChain, opts) -+ if err != nil { -+ if hintErr == nil { -+ hintErr = err -+ hintCert = candidate -+ } -+ return -+ } -+ -+ switch certType { -+ case rootCertificate: -+ chains = append(chains, appendToFreshChain(currentChain, candidate)) -+ case intermediateCertificate: -+ var childChains [][]*Certificate -+ childChains, err = candidate.buildChains(appendToFreshChain(currentChain, candidate), sigChecks, opts) -+ chains = append(chains, childChains...) -+ } -+ } -+ -+ for _, root := range opts.Roots.findPotentialParents(c) { -+ considerCandidate(rootCertificate, root) -+ } -+ for _, intermediate := range opts.Intermediates.findPotentialParents(c) { -+ considerCandidate(intermediateCertificate, intermediate) -+ } -+ -+ if len(chains) > 0 { -+ err = nil -+ } -+ if len(chains) == 0 && err == nil { -+ err = UnknownAuthorityError{c, hintErr, hintCert} -+ } -+ -+ return -+} -+ -+func validHostnamePattern(host string) bool { return validHostname(host, true) } -+func validHostnameInput(host string) bool { return validHostname(host, false) } -+ -+// validHostname reports whether host is a valid hostname that can be matched or -+// matched against according to RFC 6125 2.2, with some leniency to accommodate -+// legacy values. -+func validHostname(host string, isPattern bool) bool { -+ if !isPattern { -+ host = strings.TrimSuffix(host, ".") -+ } -+ if len(host) == 0 { -+ return false -+ } -+ -+ for i, part := range strings.Split(host, ".") { -+ if part == "" { -+ // Empty label. -+ return false -+ } -+ if isPattern && i == 0 && part == "*" { -+ // Only allow full left-most wildcards, as those are the only ones -+ // we match, and matching literal '*' characters is probably never -+ // the expected behavior. -+ continue -+ } -+ for j, c := range part { -+ if 'a' <= c && c <= 'z' { -+ continue -+ } -+ if '0' <= c && c <= '9' { -+ continue -+ } -+ if 'A' <= c && c <= 'Z' { -+ continue -+ } -+ if c == '-' && j != 0 { -+ continue -+ } -+ if c == '_' { -+ // Not a valid character in hostnames, but commonly -+ // found in deployments outside the WebPKI. -+ continue -+ } -+ return false -+ } -+ } -+ -+ return true -+} -+ -+func matchExactly(hostA, hostB string) bool { -+ if hostA == "" || hostA == "." || hostB == "" || hostB == "." { -+ return false -+ } -+ return toLowerCaseASCII(hostA) == toLowerCaseASCII(hostB) -+} -+ -+func matchHostnames(pattern, host string) bool { -+ pattern = toLowerCaseASCII(pattern) -+ host = toLowerCaseASCII(strings.TrimSuffix(host, ".")) -+ -+ if len(pattern) == 0 || len(host) == 0 { -+ return false -+ } -+ -+ patternParts := strings.Split(pattern, ".") -+ hostParts := strings.Split(host, ".") -+ -+ if len(patternParts) != len(hostParts) { -+ return false -+ } -+ -+ for i, patternPart := range patternParts { -+ if i == 0 && patternPart == "*" { -+ continue -+ } -+ if patternPart != hostParts[i] { -+ return false -+ } -+ } -+ -+ return true -+} -+ -+// toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use -+// an explicitly ASCII function to avoid any sharp corners resulting from -+// performing Unicode operations on DNS labels. -+func toLowerCaseASCII(in string) string { -+ // If the string is already lower-case then there's nothing to do. -+ isAlreadyLowerCase := true -+ for _, c := range in { -+ if c == utf8.RuneError { -+ // If we get a UTF-8 error then there might be -+ // upper-case ASCII bytes in the invalid sequence. -+ isAlreadyLowerCase = false -+ break -+ } -+ if 'A' <= c && c <= 'Z' { -+ isAlreadyLowerCase = false -+ break -+ } -+ } -+ -+ if isAlreadyLowerCase { -+ return in -+ } -+ -+ out := []byte(in) -+ for i, c := range out { -+ if 'A' <= c && c <= 'Z' { -+ out[i] += 'a' - 'A' -+ } -+ } -+ return string(out) -+} -+ -+// VerifyHostname returns nil if c is a valid certificate for the named host. -+// Otherwise it returns an error describing the mismatch. -+// -+// IP addresses can be optionally enclosed in square brackets and are checked -+// against the IPAddresses field. Other names are checked case insensitively -+// against the DNSNames field. If the names are valid hostnames, the certificate -+// fields can have a wildcard as the complete left-most label (e.g. *.example.com). -+// -+// Note that the legacy Common Name field is ignored. -+func (c *Certificate) VerifyHostname(h string) error { -+ // IP addresses may be written in [ ]. -+ candidateIP := h -+ if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' { -+ candidateIP = h[1 : len(h)-1] -+ } -+ if ip := net.ParseIP(candidateIP); ip != nil { -+ // We only match IP addresses against IP SANs. -+ // See RFC 6125, Appendix B.2. -+ for _, candidate := range c.IPAddresses { -+ if ip.Equal(candidate) { -+ return nil -+ } -+ } -+ return HostnameError{c, candidateIP} -+ } -+ -+ candidateName := toLowerCaseASCII(h) // Save allocations inside the loop. -+ validCandidateName := validHostnameInput(candidateName) -+ -+ for _, match := range c.DNSNames { -+ // Ideally, we'd only match valid hostnames according to RFC 6125 like -+ // browsers (more or less) do, but in practice Go is used in a wider -+ // array of contexts and can't even assume DNS resolution. Instead, -+ // always allow perfect matches, and only apply wildcard and trailing -+ // dot processing to valid hostnames. -+ if validCandidateName && validHostnamePattern(match) { -+ if matchHostnames(match, candidateName) { -+ return nil -+ } -+ } else { -+ if matchExactly(match, candidateName) { -+ return nil -+ } -+ } -+ } -+ -+ return HostnameError{c, h} -+} -+ -+func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool { -+ usages := make([]ExtKeyUsage, len(keyUsages)) -+ copy(usages, keyUsages) -+ -+ if len(chain) == 0 { -+ return false -+ } -+ -+ usagesRemaining := len(usages) -+ -+ // We walk down the list and cross out any usages that aren't supported -+ // by each certificate. If we cross out all the usages, then the chain -+ // is unacceptable. -+ -+NextCert: -+ for i := len(chain) - 1; i >= 0; i-- { -+ cert := chain[i] -+ if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 { -+ // The certificate doesn't have any extended key usage specified. -+ continue -+ } -+ -+ for _, usage := range cert.ExtKeyUsage { -+ if usage == ExtKeyUsageAny { -+ // The certificate is explicitly good for any usage. -+ continue NextCert -+ } -+ } -+ -+ const invalidUsage ExtKeyUsage = -1 -+ -+ NextRequestedUsage: -+ for i, requestedUsage := range usages { -+ if requestedUsage == invalidUsage { -+ continue -+ } -+ -+ for _, usage := range cert.ExtKeyUsage { -+ if requestedUsage == usage { -+ continue NextRequestedUsage -+ } -+ } -+ -+ usages[i] = invalidUsage -+ usagesRemaining-- -+ if usagesRemaining == 0 { -+ return false -+ } -+ } -+ } -+ -+ return true -+} -diff --git a/src/crypto/x509/verify_test.go-e b/src/crypto/x509/verify_test.go-e -new file mode 100644 -index 0000000000..3551b470ce ---- /dev/null -+++ b/src/crypto/x509/verify_test.go-e -@@ -0,0 +1,2695 @@ -+// Copyright 2011 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. -+ -+package x509 -+ -+import ( -+ "crypto" -+ "crypto/ecdsa" -+ "crypto/elliptic" -+ "crypto/rand" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+ "encoding/pem" -+ "errors" -+ "fmt" -+ "internal/testenv" -+ "math/big" -+ "reflect" -+ "runtime" -+ "sort" -+ "strings" -+ "testing" -+ "time" -+) -+ -+type verifyTest struct { -+ name string -+ leaf string -+ intermediates []string -+ roots []string -+ currentTime int64 -+ dnsName string -+ systemSkip bool -+ systemLax bool -+ keyUsages []ExtKeyUsage -+ -+ errorCallback func(*testing.T, error) -+ expectedChains [][]string -+} -+ -+var verifyTests = []verifyTest{ -+ { -+ name: "Valid", -+ leaf: googleLeaf, -+ intermediates: []string{gtsIntermediate}, -+ roots: []string{gtsRoot}, -+ currentTime: 1677615892, -+ dnsName: "www.google.com", -+ -+ expectedChains: [][]string{ -+ {"www.google.com", "GTS CA 1C3", "GTS Root R1"}, -+ }, -+ }, -+ { -+ name: "Valid (fqdn)", -+ leaf: googleLeaf, -+ intermediates: []string{gtsIntermediate}, -+ roots: []string{gtsRoot}, -+ currentTime: 1677615892, -+ dnsName: "www.google.com.", -+ -+ expectedChains: [][]string{ -+ {"www.google.com", "GTS CA 1C3", "GTS Root R1"}, -+ }, -+ }, -+ { -+ name: "MixedCase", -+ leaf: googleLeaf, -+ intermediates: []string{gtsIntermediate}, -+ roots: []string{gtsRoot}, -+ currentTime: 1677615892, -+ dnsName: "WwW.GooGLE.coM", -+ -+ expectedChains: [][]string{ -+ {"www.google.com", "GTS CA 1C3", "GTS Root R1"}, -+ }, -+ }, -+ { -+ name: "HostnameMismatch", -+ leaf: googleLeaf, -+ intermediates: []string{gtsIntermediate}, -+ roots: []string{gtsRoot}, -+ currentTime: 1677615892, -+ dnsName: "www.example.com", -+ -+ errorCallback: expectHostnameError("certificate is valid for"), -+ }, -+ { -+ name: "IPMissing", -+ leaf: googleLeaf, -+ intermediates: []string{gtsIntermediate}, -+ roots: []string{gtsRoot}, -+ currentTime: 1677615892, -+ dnsName: "1.2.3.4", -+ -+ errorCallback: expectHostnameError("doesn't contain any IP SANs"), -+ }, -+ { -+ name: "Expired", -+ leaf: googleLeaf, -+ intermediates: []string{gtsIntermediate}, -+ roots: []string{gtsRoot}, -+ currentTime: 1, -+ dnsName: "www.example.com", -+ -+ errorCallback: expectExpired, -+ }, -+ { -+ name: "MissingIntermediate", -+ leaf: googleLeaf, -+ roots: []string{gtsRoot}, -+ currentTime: 1677615892, -+ dnsName: "www.google.com", -+ -+ // Skip when using systemVerify, since Windows -+ // *will* find the missing intermediate cert. -+ systemSkip: true, -+ errorCallback: expectAuthorityUnknown, -+ }, -+ { -+ name: "RootInIntermediates", -+ leaf: googleLeaf, -+ intermediates: []string{gtsRoot, gtsIntermediate}, -+ roots: []string{gtsRoot}, -+ currentTime: 1677615892, -+ dnsName: "www.google.com", -+ -+ expectedChains: [][]string{ -+ {"www.google.com", "GTS CA 1C3", "GTS Root R1"}, -+ }, -+ // CAPI doesn't build the chain with the duplicated GeoTrust -+ // entry so the results don't match. -+ systemLax: true, -+ }, -+ { -+ name: "dnssec-exp", -+ leaf: dnssecExpLeaf, -+ intermediates: []string{startComIntermediate}, -+ roots: []string{startComRoot}, -+ currentTime: 1302726541, -+ -+ // The StartCom root is not trusted by Windows when the default -+ // ServerAuth EKU is requested. -+ systemSkip: true, -+ -+ expectedChains: [][]string{ -+ {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"}, -+ }, -+ }, -+ { -+ name: "dnssec-exp/AnyEKU", -+ leaf: dnssecExpLeaf, -+ intermediates: []string{startComIntermediate}, -+ roots: []string{startComRoot}, -+ currentTime: 1302726541, -+ keyUsages: []ExtKeyUsage{ExtKeyUsageAny}, -+ -+ expectedChains: [][]string{ -+ {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"}, -+ }, -+ }, -+ { -+ name: "dnssec-exp/RootInIntermediates", -+ leaf: dnssecExpLeaf, -+ intermediates: []string{startComIntermediate, startComRoot}, -+ roots: []string{startComRoot}, -+ currentTime: 1302726541, -+ systemSkip: true, // see dnssec-exp test -+ -+ expectedChains: [][]string{ -+ {"dnssec-exp", "StartCom Class 1", "StartCom Certification Authority"}, -+ }, -+ }, -+ { -+ name: "InvalidHash", -+ leaf: googleLeafWithInvalidHash, -+ intermediates: []string{gtsIntermediate}, -+ roots: []string{gtsRoot}, -+ currentTime: 1677615892, -+ dnsName: "www.google.com", -+ -+ // The specific error message may not occur when using system -+ // verification. -+ systemLax: true, -+ errorCallback: expectHashError, -+ }, -+ // EKULeaf tests use an unconstrained chain leading to a leaf certificate -+ // with an E-mail Protection EKU but not a Server Auth one, checking that -+ // the EKUs on the leaf are enforced. -+ { -+ name: "EKULeaf", -+ leaf: smimeLeaf, -+ intermediates: []string{smimeIntermediate}, -+ roots: []string{smimeRoot}, -+ currentTime: 1594673418, -+ -+ errorCallback: expectUsageError, -+ }, -+ { -+ name: "EKULeafExplicit", -+ leaf: smimeLeaf, -+ intermediates: []string{smimeIntermediate}, -+ roots: []string{smimeRoot}, -+ currentTime: 1594673418, -+ keyUsages: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ -+ errorCallback: expectUsageError, -+ }, -+ { -+ name: "EKULeafValid", -+ leaf: smimeLeaf, -+ intermediates: []string{smimeIntermediate}, -+ roots: []string{smimeRoot}, -+ currentTime: 1594673418, -+ keyUsages: []ExtKeyUsage{ExtKeyUsageEmailProtection}, -+ -+ expectedChains: [][]string{ -+ {"CORPORATIVO FICTICIO ACTIVO", "EAEko Herri Administrazioen CA - CA AAPP Vascas (2)", "IZENPE S.A."}, -+ }, -+ }, -+ { -+ // Check that a name constrained intermediate works even when -+ // it lists multiple constraints. -+ name: "MultipleConstraints", -+ leaf: nameConstraintsLeaf, -+ intermediates: []string{nameConstraintsIntermediate1, nameConstraintsIntermediate2}, -+ roots: []string{globalSignRoot}, -+ currentTime: 1382387896, -+ dnsName: "secure.iddl.vt.edu", -+ -+ expectedChains: [][]string{ -+ { -+ "Technology-enhanced Learning and Online Strategies", -+ "Virginia Tech Global Qualified Server CA", -+ "Trusted Root CA G2", -+ "GlobalSign Root CA", -+ }, -+ }, -+ }, -+ { -+ // Check that SHA-384 intermediates (which are popping up) -+ // work. -+ name: "SHA-384", -+ leaf: trustAsiaLeaf, -+ intermediates: []string{trustAsiaSHA384Intermediate}, -+ roots: []string{digicertRoot}, -+ currentTime: 1558051200, -+ dnsName: "tm.cn", -+ -+ // CryptoAPI can find alternative validation paths. -+ systemLax: true, -+ -+ expectedChains: [][]string{ -+ { -+ "tm.cn", -+ "TrustAsia ECC OV TLS Pro CA", -+ "DigiCert Global Root CA", -+ }, -+ }, -+ }, -+ { -+ // Putting a certificate as a root directly should work as a -+ // way of saying “exactly this”. -+ name: "LeafInRoots", -+ leaf: selfSigned, -+ roots: []string{selfSigned}, -+ currentTime: 1471624472, -+ dnsName: "foo.example", -+ systemSkip: true, // does not chain to a system root -+ -+ expectedChains: [][]string{ -+ {"Acme Co"}, -+ }, -+ }, -+ { -+ // Putting a certificate as a root directly should not skip -+ // other checks however. -+ name: "LeafInRootsInvalid", -+ leaf: selfSigned, -+ roots: []string{selfSigned}, -+ currentTime: 1471624472, -+ dnsName: "notfoo.example", -+ systemSkip: true, // does not chain to a system root -+ -+ errorCallback: expectHostnameError("certificate is valid for"), -+ }, -+ { -+ // An X.509 v1 certificate should not be accepted as an -+ // intermediate. -+ name: "X509v1Intermediate", -+ leaf: x509v1TestLeaf, -+ intermediates: []string{x509v1TestIntermediate}, -+ roots: []string{x509v1TestRoot}, -+ currentTime: 1481753183, -+ systemSkip: true, // does not chain to a system root -+ -+ errorCallback: expectNotAuthorizedError, -+ }, -+ { -+ name: "IgnoreCNWithSANs", -+ leaf: ignoreCNWithSANLeaf, -+ dnsName: "foo.example.com", -+ roots: []string{ignoreCNWithSANRoot}, -+ currentTime: 1486684488, -+ systemSkip: true, // does not chain to a system root -+ -+ errorCallback: expectHostnameError("certificate is not valid for any names"), -+ }, -+ { -+ // Test that excluded names are respected. -+ name: "ExcludedNames", -+ leaf: excludedNamesLeaf, -+ dnsName: "bender.local", -+ intermediates: []string{excludedNamesIntermediate}, -+ roots: []string{excludedNamesRoot}, -+ currentTime: 1486684488, -+ systemSkip: true, // does not chain to a system root -+ -+ errorCallback: expectNameConstraintsError, -+ }, -+ { -+ // Test that unknown critical extensions in a leaf cause a -+ // verify error. -+ name: "CriticalExtLeaf", -+ leaf: criticalExtLeafWithExt, -+ intermediates: []string{criticalExtIntermediate}, -+ roots: []string{criticalExtRoot}, -+ currentTime: 1486684488, -+ systemSkip: true, // does not chain to a system root -+ -+ errorCallback: expectUnhandledCriticalExtension, -+ }, -+ { -+ // Test that unknown critical extensions in an intermediate -+ // cause a verify error. -+ name: "CriticalExtIntermediate", -+ leaf: criticalExtLeaf, -+ intermediates: []string{criticalExtIntermediateWithExt}, -+ roots: []string{criticalExtRoot}, -+ currentTime: 1486684488, -+ systemSkip: true, // does not chain to a system root -+ -+ errorCallback: expectUnhandledCriticalExtension, -+ }, -+ { -+ name: "ValidCN", -+ leaf: validCNWithoutSAN, -+ dnsName: "foo.example.com", -+ roots: []string{invalidCNRoot}, -+ currentTime: 1540000000, -+ systemSkip: true, // does not chain to a system root -+ -+ errorCallback: expectHostnameError("certificate relies on legacy Common Name field"), -+ }, -+ { -+ // A certificate with an AKID should still chain to a parent without SKID. -+ // See Issue 30079. -+ name: "AKIDNoSKID", -+ leaf: leafWithAKID, -+ roots: []string{rootWithoutSKID}, -+ currentTime: 1550000000, -+ dnsName: "example", -+ systemSkip: true, // does not chain to a system root -+ -+ expectedChains: [][]string{ -+ {"Acme LLC", "Acme Co"}, -+ }, -+ }, -+ { -+ // When there are two parents, one with a incorrect subject but matching SKID -+ // and one with a correct subject but missing SKID, the latter should be -+ // considered as a possible parent. -+ leaf: leafMatchingAKIDMatchingIssuer, -+ roots: []string{rootMatchingSKIDMismatchingSubject, rootMismatchingSKIDMatchingSubject}, -+ currentTime: 1550000000, -+ dnsName: "example", -+ systemSkip: true, -+ -+ expectedChains: [][]string{ -+ {"Leaf", "Root B"}, -+ }, -+ }, -+} -+ -+func expectHostnameError(msg string) func(*testing.T, error) { -+ return func(t *testing.T, err error) { -+ if _, ok := err.(HostnameError); !ok { -+ t.Fatalf("error was not a HostnameError: %v", err) -+ } -+ if !strings.Contains(err.Error(), msg) { -+ t.Fatalf("HostnameError did not contain %q: %v", msg, err) -+ } -+ } -+} -+ -+func expectExpired(t *testing.T, err error) { -+ if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != Expired { -+ t.Fatalf("error was not Expired: %v", err) -+ } -+} -+ -+func expectUsageError(t *testing.T, err error) { -+ if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != IncompatibleUsage { -+ t.Fatalf("error was not IncompatibleUsage: %v", err) -+ } -+} -+ -+func expectAuthorityUnknown(t *testing.T, err error) { -+ e, ok := err.(UnknownAuthorityError) -+ if !ok { -+ t.Fatalf("error was not UnknownAuthorityError: %v", err) -+ } -+ if e.Cert == nil { -+ t.Fatalf("error was UnknownAuthorityError, but missing Cert: %v", err) -+ } -+} -+ -+func expectHashError(t *testing.T, err error) { -+ if err == nil { -+ t.Fatalf("no error resulted from invalid hash") -+ } -+ if expected := "algorithm unimplemented"; !strings.Contains(err.Error(), expected) { -+ t.Fatalf("error resulting from invalid hash didn't contain '%s', rather it was: %v", expected, err) -+ } -+} -+ -+func expectNameConstraintsError(t *testing.T, err error) { -+ if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != CANotAuthorizedForThisName { -+ t.Fatalf("error was not a CANotAuthorizedForThisName: %v", err) -+ } -+} -+ -+func expectNotAuthorizedError(t *testing.T, err error) { -+ if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != NotAuthorizedToSign { -+ t.Fatalf("error was not a NotAuthorizedToSign: %v", err) -+ } -+} -+ -+func expectUnhandledCriticalExtension(t *testing.T, err error) { -+ if _, ok := err.(UnhandledCriticalExtension); !ok { -+ t.Fatalf("error was not an UnhandledCriticalExtension: %v", err) -+ } -+} -+ -+func certificateFromPEM(pemBytes string) (*Certificate, error) { -+ block, _ := pem.Decode([]byte(pemBytes)) -+ if block == nil { -+ return nil, errors.New("failed to decode PEM") -+ } -+ return ParseCertificate(block.Bytes) -+} -+ -+func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) { -+ opts := VerifyOptions{ -+ Intermediates: NewCertPool(), -+ DNSName: test.dnsName, -+ CurrentTime: time.Unix(test.currentTime, 0), -+ KeyUsages: test.keyUsages, -+ } -+ -+ if !useSystemRoots { -+ opts.Roots = NewCertPool() -+ for j, root := range test.roots { -+ ok := opts.Roots.AppendCertsFromPEM([]byte(root)) -+ if !ok { -+ t.Fatalf("failed to parse root #%d", j) -+ } -+ } -+ } -+ -+ for j, intermediate := range test.intermediates { -+ ok := opts.Intermediates.AppendCertsFromPEM([]byte(intermediate)) -+ if !ok { -+ t.Fatalf("failed to parse intermediate #%d", j) -+ } -+ } -+ -+ leaf, err := certificateFromPEM(test.leaf) -+ if err != nil { -+ t.Fatalf("failed to parse leaf: %v", err) -+ } -+ -+ chains, err := leaf.Verify(opts) -+ -+ if test.errorCallback == nil && err != nil { -+ if runtime.GOOS == "windows" && strings.HasSuffix(testenv.Builder(), "-2008") && err.Error() == "x509: certificate signed by unknown authority" { -+ testenv.SkipFlaky(t, 19564) -+ } -+ t.Fatalf("unexpected error: %v", err) -+ } -+ if test.errorCallback != nil { -+ if useSystemRoots && test.systemLax { -+ if err == nil { -+ t.Fatalf("expected error") -+ } -+ } else { -+ test.errorCallback(t, err) -+ } -+ } -+ -+ doesMatch := func(expectedChain []string, chain []*Certificate) bool { -+ if len(chain) != len(expectedChain) { -+ return false -+ } -+ -+ for k, cert := range chain { -+ if !strings.Contains(nameToKey(&cert.Subject), expectedChain[k]) { -+ return false -+ } -+ } -+ return true -+ } -+ -+ // Every expected chain should match one (or more) returned chain. We tolerate multiple -+ // matches, as due to root store semantics it is plausible that (at least on the system -+ // verifiers) multiple identical (looking) chains may be returned when two roots with the -+ // same subject are present. -+ for _, expectedChain := range test.expectedChains { -+ var match bool -+ for _, chain := range chains { -+ if doesMatch(expectedChain, chain) { -+ match = true -+ break -+ } -+ } -+ -+ if !match { -+ t.Errorf("No match found for %v", expectedChain) -+ } -+ } -+ -+ // Every returned chain should match 1 expected chain (or <2 if testing against the system) -+ for _, chain := range chains { -+ nMatched := 0 -+ for _, expectedChain := range test.expectedChains { -+ if doesMatch(expectedChain, chain) { -+ nMatched++ -+ } -+ } -+ // Allow additional unknown chains if systemLax is set -+ if nMatched == 0 && test.systemLax == false || nMatched > 1 { -+ t.Errorf("Got %v matches for chain %v", nMatched, chainToDebugString(chain)) -+ for _, expectedChain := range test.expectedChains { -+ if doesMatch(expectedChain, chain) { -+ t.Errorf("\t matched %v", expectedChain) -+ } -+ } -+ } -+ } -+} -+ -+func TestGoVerify(t *testing.T) { -+ // Temporarily enable SHA-1 verification since a number of test chains -+ // require it. TODO(filippo): regenerate test chains. -+ t.Setenv("GODEBUG", "x509sha1=1") -+ -+ for _, test := range verifyTests { -+ t.Run(test.name, func(t *testing.T) { -+ testVerify(t, test, false) -+ }) -+ } -+} -+ -+func TestSystemVerify(t *testing.T) { -+ if runtime.GOOS != "windows" { -+ t.Skipf("skipping verify test using system APIs on %q", runtime.GOOS) -+ } -+ -+ for _, test := range verifyTests { -+ t.Run(test.name, func(t *testing.T) { -+ if test.systemSkip { -+ t.SkipNow() -+ } -+ testVerify(t, test, true) -+ }) -+ } -+} -+ -+func chainToDebugString(chain []*Certificate) string { -+ var chainStr string -+ for _, cert := range chain { -+ if len(chainStr) > 0 { -+ chainStr += " -> " -+ } -+ chainStr += nameToKey(&cert.Subject) -+ } -+ return chainStr -+} -+ -+func nameToKey(name *pkix.Name) string { -+ return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName -+} -+ -+const gtsIntermediate = `-----BEGIN CERTIFICATE----- -+MIIFljCCA36gAwIBAgINAgO8U1lrNMcY9QFQZjANBgkqhkiG9w0BAQsFADBHMQsw -+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU -+MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjAwODEzMDAwMDQyWhcNMjcwOTMwMDAw -+MDQyWjBGMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp -+Y2VzIExMQzETMBEGA1UEAxMKR1RTIENBIDFDMzCCASIwDQYJKoZIhvcNAQEBBQAD -+ggEPADCCAQoCggEBAPWI3+dijB43+DdCkH9sh9D7ZYIl/ejLa6T/belaI+KZ9hzp -+kgOZE3wJCor6QtZeViSqejOEH9Hpabu5dOxXTGZok3c3VVP+ORBNtzS7XyV3NzsX -+lOo85Z3VvMO0Q+sup0fvsEQRY9i0QYXdQTBIkxu/t/bgRQIh4JZCF8/ZK2VWNAcm -+BA2o/X3KLu/qSHw3TT8An4Pf73WELnlXXPxXbhqW//yMmqaZviXZf5YsBvcRKgKA -+gOtjGDxQSYflispfGStZloEAoPtR28p3CwvJlk/vcEnHXG0g/Zm0tOLKLnf9LdwL -+tmsTDIwZKxeWmLnwi/agJ7u2441Rj72ux5uxiZ0CAwEAAaOCAYAwggF8MA4GA1Ud -+DwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0T -+AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUinR/r4XN7pXNPZzQ4kYU83E1HScwHwYD -+VR0jBBgwFoAU5K8rJnEaK0gnhS9SZizv8IkTcT4waAYIKwYBBQUHAQEEXDBaMCYG -+CCsGAQUFBzABhhpodHRwOi8vb2NzcC5wa2kuZ29vZy9ndHNyMTAwBggrBgEFBQcw -+AoYkaHR0cDovL3BraS5nb29nL3JlcG8vY2VydHMvZ3RzcjEuZGVyMDQGA1UdHwQt -+MCswKaAnoCWGI2h0dHA6Ly9jcmwucGtpLmdvb2cvZ3RzcjEvZ3RzcjEuY3JsMFcG -+A1UdIARQME4wOAYKKwYBBAHWeQIFAzAqMCgGCCsGAQUFBwIBFhxodHRwczovL3Br -+aS5nb29nL3JlcG9zaXRvcnkvMAgGBmeBDAECATAIBgZngQwBAgIwDQYJKoZIhvcN -+AQELBQADggIBAIl9rCBcDDy+mqhXlRu0rvqrpXJxtDaV/d9AEQNMwkYUuxQkq/BQ -+cSLbrcRuf8/xam/IgxvYzolfh2yHuKkMo5uhYpSTld9brmYZCwKWnvy15xBpPnrL -+RklfRuFBsdeYTWU0AIAaP0+fbH9JAIFTQaSSIYKCGvGjRFsqUBITTcFTNvNCCK9U -++o53UxtkOCcXCb1YyRt8OS1b887U7ZfbFAO/CVMkH8IMBHmYJvJh8VNS/UKMG2Yr -+PxWhu//2m+OBmgEGcYk1KCTd4b3rGS3hSMs9WYNRtHTGnXzGsYZbr8w0xNPM1IER -+lQCh9BIiAfq0g3GvjLeMcySsN1PCAJA/Ef5c7TaUEDu9Ka7ixzpiO2xj2YC/WXGs -+Yye5TBeg2vZzFb8q3o/zpWwygTMD0IZRcZk0upONXbVRWPeyk+gB9lm+cZv9TSjO -+z23HFtz30dZGm6fKa+l3D/2gthsjgx0QGtkJAITgRNOidSOzNIb2ILCkXhAd4FJG -+AJ2xDx8hcFH1mt0G/FX0Kw4zd8NLQsLxdxP8c4CU6x+7Nz/OAipmsHMdMqUybDKw -+juDEI/9bfU1lcKwrmz3O2+BtjjKAvpafkmO8l7tdufThcV4q5O8DIrGKZTqPwJNl -+1IXNDw9bg1kWRxYtnCQ6yICmJhSFm/Y3m6xv+cXDBlHz4n/FsRC6UfTd -+-----END CERTIFICATE-----` -+ -+const gtsRoot = `-----BEGIN CERTIFICATE----- -+MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw -+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU -+MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw -+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp -+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA -+A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo -+27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w -+Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw -+TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl -+qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH -+szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8 -+Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk -+MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92 -+wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p -+aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN -+VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID -+AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E -+FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb -+C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe -+QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy -+h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4 -+7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J -+ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef -+MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/ -+Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT -+6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ -+0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm -+2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb -+bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c -+-----END CERTIFICATE-----` -+ -+const googleLeaf = `-----BEGIN CERTIFICATE----- -+MIIFUjCCBDqgAwIBAgIQERmRWTzVoz0SMeozw2RM3DANBgkqhkiG9w0BAQsFADBG -+MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM -+QzETMBEGA1UEAxMKR1RTIENBIDFDMzAeFw0yMzAxMDIwODE5MTlaFw0yMzAzMjcw -+ODE5MThaMBkxFzAVBgNVBAMTDnd3dy5nb29nbGUuY29tMIIBIjANBgkqhkiG9w0B -+AQEFAAOCAQ8AMIIBCgKCAQEAq30odrKMT54TJikMKL8S+lwoCMT5geP0u9pWjk6a -+wdB6i3kO+UE4ijCAmhbcZKeKaLnGJ38weZNwB1ayabCYyX7hDiC/nRcZU49LX5+o -+55kDVaNn14YKkg2kCeX25HDxSwaOsNAIXKPTqiQL5LPvc4Twhl8HY51hhNWQrTEr -+N775eYbixEULvyVLq5BLbCOpPo8n0/MTjQ32ku1jQq3GIYMJC/Rf2VW5doF6t9zs -+KleflAN8OdKp0ME9OHg0T1P3yyb67T7n0SpisHbeG06AmQcKJF9g/9VPJtRf4l1Q -+WRPDC+6JUqzXCxAGmIRGZ7TNMxPMBW/7DRX6w8oLKVNb0wIDAQABo4ICZzCCAmMw -+DgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQC -+MAAwHQYDVR0OBBYEFBnboj3lf9+Xat4oEgo6ZtIMr8ZuMB8GA1UdIwQYMBaAFIp0 -+f6+Fze6VzT2c0OJGFPNxNR0nMGoGCCsGAQUFBwEBBF4wXDAnBggrBgEFBQcwAYYb -+aHR0cDovL29jc3AucGtpLmdvb2cvZ3RzMWMzMDEGCCsGAQUFBzAChiVodHRwOi8v -+cGtpLmdvb2cvcmVwby9jZXJ0cy9ndHMxYzMuZGVyMBkGA1UdEQQSMBCCDnd3dy5n -+b29nbGUuY29tMCEGA1UdIAQaMBgwCAYGZ4EMAQIBMAwGCisGAQQB1nkCBQMwPAYD -+VR0fBDUwMzAxoC+gLYYraHR0cDovL2NybHMucGtpLmdvb2cvZ3RzMWMzL1FPdkow -+TjFzVDJBLmNybDCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB2AHoyjFTYty22IOo4 -+4FIe6YQWcDIThU070ivBOlejUutSAAABhXHHOiUAAAQDAEcwRQIgBUkikUIXdo+S -+3T8PP0/cvokhUlumRE3GRWGL4WRMLpcCIQDY+bwK384mZxyXGZ5lwNRTAPNzT8Fx -+1+//nbaGK3BQMAB2AOg+0No+9QY1MudXKLyJa8kD08vREWvs62nhd31tBr1uAAAB -+hXHHOfQAAAQDAEcwRQIgLoVydNfMFKV9IoZR+M0UuJ2zOqbxIRum7Sn9RMPOBGMC -+IQD1/BgzCSDTvYvco6kpB6ifKSbg5gcb5KTnYxQYwRW14TANBgkqhkiG9w0BAQsF -+AAOCAQEA2bQQu30e3OFu0bmvQHmcqYvXBu6tF6e5b5b+hj4O+Rn7BXTTmaYX3M6p -+MsfRH4YVJJMB/dc3PROR2VtnKFC6gAZX+RKM6nXnZhIlOdmQnonS1ecOL19PliUd -+VXbwKjXqAO0Ljd9y9oXaXnyPyHmUJNI5YXAcxE+XXiOZhcZuMYyWmoEKJQ/XlSga -+zWfTn1IcKhA3IC7A1n/5bkkWD1Xi1mdWFQ6DQDMp//667zz7pKOgFMlB93aPDjvI -+c78zEqNswn6xGKXpWF5xVwdFcsx9HKhJ6UAi2bQ/KQ1yb7LPUOR6wXXWrG1cLnNP -+i8eNLnKL9PXQ+5SwJFCzfEhcIZuhzg== -+-----END CERTIFICATE-----` -+ -+// googleLeafWithInvalidHash is the same as googleLeaf, but the signature -+// algorithm in the certificate contains a nonsense OID. -+const googleLeafWithInvalidHash = `-----BEGIN CERTIFICATE----- -+MIIFUjCCBDqgAwIBAgIQERmRWTzVoz0SMeozw2RM3DANBgkqhkiG9w0BAQ4FADBG -+MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM -+QzETMBEGA1UEAxMKR1RTIENBIDFDMzAeFw0yMzAxMDIwODE5MTlaFw0yMzAzMjcw -+ODE5MThaMBkxFzAVBgNVBAMTDnd3dy5nb29nbGUuY29tMIIBIjANBgkqhkiG9w0B -+AQEFAAOCAQ8AMIIBCgKCAQEAq30odrKMT54TJikMKL8S+lwoCMT5geP0u9pWjk6a -+wdB6i3kO+UE4ijCAmhbcZKeKaLnGJ38weZNwB1ayabCYyX7hDiC/nRcZU49LX5+o -+55kDVaNn14YKkg2kCeX25HDxSwaOsNAIXKPTqiQL5LPvc4Twhl8HY51hhNWQrTEr -+N775eYbixEULvyVLq5BLbCOpPo8n0/MTjQ32ku1jQq3GIYMJC/Rf2VW5doF6t9zs -+KleflAN8OdKp0ME9OHg0T1P3yyb67T7n0SpisHbeG06AmQcKJF9g/9VPJtRf4l1Q -+WRPDC+6JUqzXCxAGmIRGZ7TNMxPMBW/7DRX6w8oLKVNb0wIDAQABo4ICZzCCAmMw -+DgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQC -+MAAwHQYDVR0OBBYEFBnboj3lf9+Xat4oEgo6ZtIMr8ZuMB8GA1UdIwQYMBaAFIp0 -+f6+Fze6VzT2c0OJGFPNxNR0nMGoGCCsGAQUFBwEBBF4wXDAnBggrBgEFBQcwAYYb -+aHR0cDovL29jc3AucGtpLmdvb2cvZ3RzMWMzMDEGCCsGAQUFBzAChiVodHRwOi8v -+cGtpLmdvb2cvcmVwby9jZXJ0cy9ndHMxYzMuZGVyMBkGA1UdEQQSMBCCDnd3dy5n -+b29nbGUuY29tMCEGA1UdIAQaMBgwCAYGZ4EMAQIBMAwGCisGAQQB1nkCBQMwPAYD -+VR0fBDUwMzAxoC+gLYYraHR0cDovL2NybHMucGtpLmdvb2cvZ3RzMWMzL1FPdkow -+TjFzVDJBLmNybDCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB2AHoyjFTYty22IOo4 -+4FIe6YQWcDIThU070ivBOlejUutSAAABhXHHOiUAAAQDAEcwRQIgBUkikUIXdo+S -+3T8PP0/cvokhUlumRE3GRWGL4WRMLpcCIQDY+bwK384mZxyXGZ5lwNRTAPNzT8Fx -+1+//nbaGK3BQMAB2AOg+0No+9QY1MudXKLyJa8kD08vREWvs62nhd31tBr1uAAAB -+hXHHOfQAAAQDAEcwRQIgLoVydNfMFKV9IoZR+M0UuJ2zOqbxIRum7Sn9RMPOBGMC -+IQD1/BgzCSDTvYvco6kpB6ifKSbg5gcb5KTnYxQYwRW14TANBgkqhkiG9w0BAQ4F -+AAOCAQEA2bQQu30e3OFu0bmvQHmcqYvXBu6tF6e5b5b+hj4O+Rn7BXTTmaYX3M6p -+MsfRH4YVJJMB/dc3PROR2VtnKFC6gAZX+RKM6nXnZhIlOdmQnonS1ecOL19PliUd -+VXbwKjXqAO0Ljd9y9oXaXnyPyHmUJNI5YXAcxE+XXiOZhcZuMYyWmoEKJQ/XlSga -+zWfTn1IcKhA3IC7A1n/5bkkWD1Xi1mdWFQ6DQDMp//667zz7pKOgFMlB93aPDjvI -+c78zEqNswn6xGKXpWF5xVwdFcsx9HKhJ6UAi2bQ/KQ1yb7LPUOR6wXXWrG1cLnNP -+i8eNLnKL9PXQ+5SwJFCzfEhcIZuhzg== -+-----END CERTIFICATE-----` -+ -+const dnssecExpLeaf = `-----BEGIN CERTIFICATE----- -+MIIGzTCCBbWgAwIBAgIDAdD6MA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ -+TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0 -+YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg -+MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTAwNzA0MTQ1MjQ1 -+WhcNMTEwNzA1MTA1NzA0WjCBwTEgMB4GA1UEDRMXMjIxMTM3LWxpOWE5dHhJRzZM -+NnNyVFMxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVQZXJzb25hIE5vdCBWYWxpZGF0 -+ZWQxKTAnBgNVBAsTIFN0YXJ0Q29tIEZyZWUgQ2VydGlmaWNhdGUgTWVtYmVyMRsw -+GQYDVQQDExJ3d3cuZG5zc2VjLWV4cC5vcmcxKDAmBgkqhkiG9w0BCQEWGWhvc3Rt -+YXN0ZXJAZG5zc2VjLWV4cC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK -+AoIBAQDEdF/22vaxrPbqpgVYMWi+alfpzBctpbfLBdPGuqOazJdCT0NbWcK8/+B4 -+X6OlSOURNIlwLzhkmwVsWdVv6dVSaN7d4yI/fJkvgfDB9+au+iBJb6Pcz8ULBfe6 -+D8HVvqKdORp6INzHz71z0sghxrQ0EAEkoWAZLh+kcn2ZHdcmZaBNUfjmGbyU6PRt -+RjdqoP+owIaC1aktBN7zl4uO7cRjlYFdusINrh2kPP02KAx2W84xjxX1uyj6oS6e -+7eBfvcwe8czW/N1rbE0CoR7h9+HnIrjnVG9RhBiZEiw3mUmF++Up26+4KTdRKbu3 -++BL4yMpfd66z0+zzqu+HkvyLpFn5AgMBAAGjggL/MIIC+zAJBgNVHRMEAjAAMAsG -+A1UdDwQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUy04I5guM -+drzfh2JQaXhgV86+4jUwHwYDVR0jBBgwFoAU60I00Jiwq5/0G2sI98xkLu8OLEUw -+LQYDVR0RBCYwJIISd3d3LmRuc3NlYy1leHAub3Jngg5kbnNzZWMtZXhwLm9yZzCC -+AUIGA1UdIASCATkwggE1MIIBMQYLKwYBBAGBtTcBAgIwggEgMC4GCCsGAQUFBwIB -+FiJodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMDQGCCsGAQUFBwIB -+FihodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9pbnRlcm1lZGlhdGUucGRmMIG3Bggr -+BgEFBQcCAjCBqjAUFg1TdGFydENvbSBMdGQuMAMCAQEagZFMaW1pdGVkIExpYWJp -+bGl0eSwgc2VlIHNlY3Rpb24gKkxlZ2FsIExpbWl0YXRpb25zKiBvZiB0aGUgU3Rh -+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUG9saWN5IGF2YWlsYWJsZSBh -+dCBodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9wb2xpY3kucGRmMGEGA1UdHwRaMFgw -+KqAooCaGJGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2NydDEtY3JsLmNybDAqoCig -+JoYkaHR0cDovL2NybC5zdGFydHNzbC5jb20vY3J0MS1jcmwuY3JsMIGOBggrBgEF -+BQcBAQSBgTB/MDkGCCsGAQUFBzABhi1odHRwOi8vb2NzcC5zdGFydHNzbC5jb20v -+c3ViL2NsYXNzMS9zZXJ2ZXIvY2EwQgYIKwYBBQUHMAKGNmh0dHA6Ly93d3cuc3Rh -+cnRzc2wuY29tL2NlcnRzL3N1Yi5jbGFzczEuc2VydmVyLmNhLmNydDAjBgNVHRIE -+HDAahhhodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS8wDQYJKoZIhvcNAQEFBQADggEB -+ACXj6SB59KRJPenn6gUdGEqcta97U769SATyiQ87i9er64qLwvIGLMa3o2Rcgl2Y -+kghUeyLdN/EXyFBYA8L8uvZREPoc7EZukpT/ZDLXy9i2S0jkOxvF2fD/XLbcjGjM -+iEYG1/6ASw0ri9C0k4oDDoJLCoeH9++yqF7SFCCMcDkJqiAGXNb4euDpa8vCCtEQ -+CSS+ObZbfkreRt3cNCf5LfCXe9OsTnCfc8Cuq81c0oLaG+SmaLUQNBuToq8e9/Zm -++b+/a3RVjxmkV5OCcGVBxsXNDn54Q6wsdw0TBMcjwoEndzpLS7yWgFbbkq5ZiGpw -+Qibb2+CfKuQ+WFV1GkVQmVA= -+-----END CERTIFICATE-----` -+ -+const startComIntermediate = `-----BEGIN CERTIFICATE----- -+MIIGNDCCBBygAwIBAgIBGDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW -+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -+dGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NDE3WhcNMTcxMDI0MjA1NDE3WjCB -+jDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsT -+IlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0 -+YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVyIENBMIIB -+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtonGrO8JUngHrJJj0PREGBiE -+gFYfka7hh/oyULTTRwbw5gdfcA4Q9x3AzhA2NIVaD5Ksg8asWFI/ujjo/OenJOJA -+pgh2wJJuniptTT9uYSAK21ne0n1jsz5G/vohURjXzTCm7QduO3CHtPn66+6CPAVv -+kvek3AowHpNz/gfK11+AnSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+vWjhwRRI/ -+ME3NO68X5Q/LoKldSKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxDKslIDlc5 -+xDEhyBDBLIf+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21TLwb0pwID -+AQABo4IBrTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD -+VR0OBBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaAFE4L7xqkQFul -+F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0cDov -+L29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8vd3d3LnN0 -+YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4YhaHR0cDovL3d3 -+dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0 -+c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYLKwYBBAGBtTcBAgEwZjAu -+BggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjA0 -+BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50ZXJtZWRpYXRl -+LnBkZjANBgkqhkiG9w0BAQUFAAOCAgEAIQlJPqWIbuALi0jaMU2P91ZXouHTYlfp -+tVbzhUV1O+VQHwSL5qBaPucAroXQ+/8gA2TLrQLhxpFy+KNN1t7ozD+hiqLjfDen -+xk+PNdb01m4Ge90h2c9W/8swIkn+iQTzheWq8ecf6HWQTd35RvdCNPdFWAwRDYSw -+xtpdPvkBnufh2lWVvnQce/xNFE+sflVHfXv0pQ1JHpXo9xLBzP92piVH0PN1Nb6X -+t1gW66pceG/sUzCv6gRNzKkC4/C2BBL2MLERPZBOVmTX3DxDX3M570uvh+v2/miI -+RHLq0gfGabDBoYvvF0nXYbFFSF87ICHpW7LM9NfpMfULFWE7epTj69m8f5SuauNi -+YpaoZHy4h/OZMn6SolK+u/hlz8nyMPyLwcKmltdfieFcNID1j0cHL7SRv7Gifl9L -+WtBbnySGBVFaaQNlQ0lxxeBvlDRr9hvYqbBMflPrj0jfyjO1SPo2ShpTpjMM0InN -+SRXNiTE8kMBy12VLUjWKRhFEuT2OKGWmPnmeXAhEKa2wNREuIU640ucQPl2Eg7PD -+wuTSxv0JS3QJ3fGz0xk+gA2iCxnwOOfFwq/iI9th4p1cbiCJSS4jarJiwUW0n6+L -+p/EiO/h94pDQehn7Skzj0n1fSoMD7SfWI55rjbRZotnvbIIp3XUZPD9MEI3vu3Un -+0q6Dp6jOW6c= -+-----END CERTIFICATE-----` -+ -+const startComRoot = `-----BEGIN CERTIFICATE----- -+MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW -+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg -+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh -+dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 -+MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi -+U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh -+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA -+A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk -+pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf -+OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C -+Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT -+Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi -+HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM -+Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w -++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ -+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 -+Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B -+26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID -+AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE -+FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j -+ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js -+LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM -+BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 -+Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy -+dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh -+cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh -+YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg -+dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp -+bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ -+YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT -+TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ -+9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 -+jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW -+FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz -+ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 -+ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L -+EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu -+L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq -+yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC -+O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V -+um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh -+NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= -+-----END CERTIFICATE-----` -+ -+const smimeLeaf = `-----BEGIN CERTIFICATE----- -+MIIIPDCCBiSgAwIBAgIQaMDxFS0pOMxZZeOBxoTJtjANBgkqhkiG9w0BAQsFADCB -+nTELMAkGA1UEBhMCRVMxFDASBgNVBAoMC0laRU5QRSBTLkEuMTowOAYDVQQLDDFB -+WlogWml1cnRhZ2lyaSBwdWJsaWtvYSAtIENlcnRpZmljYWRvIHB1YmxpY28gU0NB -+MTwwOgYDVQQDDDNFQUVrbyBIZXJyaSBBZG1pbmlzdHJhemlvZW4gQ0EgLSBDQSBB -+QVBQIFZhc2NhcyAoMikwHhcNMTcwNzEyMDg1MzIxWhcNMjEwNzEyMDg1MzIxWjCC -+AQwxDzANBgNVBAoMBklaRU5QRTE4MDYGA1UECwwvWml1cnRhZ2lyaSBrb3Jwb3Jh -+dGlib2EtQ2VydGlmaWNhZG8gY29ycG9yYXRpdm8xQzBBBgNVBAsMOkNvbmRpY2lv -+bmVzIGRlIHVzbyBlbiB3d3cuaXplbnBlLmNvbSBub2xhIGVyYWJpbGkgamFraXRl -+a28xFzAVBgNVBC4TDi1kbmkgOTk5OTk5ODlaMSQwIgYDVQQDDBtDT1JQT1JBVElW -+TyBGSUNUSUNJTyBBQ1RJVk8xFDASBgNVBCoMC0NPUlBPUkFUSVZPMREwDwYDVQQE -+DAhGSUNUSUNJTzESMBAGA1UEBRMJOTk5OTk5ODlaMIIBIjANBgkqhkiG9w0BAQEF -+AAOCAQ8AMIIBCgKCAQEAwVOMwUDfBtsH0XuxYnb+v/L774jMH8valX7RPH8cl2Lb -+SiqSo0RchW2RGA2d1yuYHlpChC9jGmt0X/g66/E/+q2hUJlfJtqVDJFwtFYV4u2S -+yzA3J36V4PRkPQrKxAsbzZriFXAF10XgiHQz9aVeMMJ9GBhmh9+DK8Tm4cMF6i8l -++AuC35KdngPF1x0ealTYrYZplpEJFO7CiW42aLi6vQkDR2R7nmZA4AT69teqBWsK -+0DZ93/f0G/3+vnWwNTBF0lB6dIXoaz8OMSyHLqGnmmAtMrzbjAr/O/WWgbB/BqhR -+qjJQ7Ui16cuDldXaWQ/rkMzsxmsAox0UF+zdQNvXUQIDAQABo4IDBDCCAwAwgccG -+A1UdEgSBvzCBvIYVaHR0cDovL3d3dy5pemVucGUuY29tgQ9pbmZvQGl6ZW5wZS5j -+b22kgZEwgY4xRzBFBgNVBAoMPklaRU5QRSBTLkEuIC0gQ0lGIEEwMTMzNzI2MC1S -+TWVyYy5WaXRvcmlhLUdhc3RlaXogVDEwNTUgRjYyIFM4MUMwQQYDVQQJDDpBdmRh -+IGRlbCBNZWRpdGVycmFuZW8gRXRvcmJpZGVhIDE0IC0gMDEwMTAgVml0b3JpYS1H -+YXN0ZWl6MB4GA1UdEQQXMBWBE2ZpY3RpY2lvQGl6ZW5wZS5ldXMwDgYDVR0PAQH/ -+BAQDAgXgMCkGA1UdJQQiMCAGCCsGAQUFBwMCBggrBgEFBQcDBAYKKwYBBAGCNxQC -+AjAdBgNVHQ4EFgQUyeoOD4cgcljKY0JvrNuX2waFQLAwHwYDVR0jBBgwFoAUwKlK -+90clh/+8taaJzoLSRqiJ66MwggEnBgNVHSAEggEeMIIBGjCCARYGCisGAQQB8zkB -+AQEwggEGMDMGCCsGAQUFBwIBFidodHRwOi8vd3d3Lml6ZW5wZS5jb20vcnBhc2Nh -+Y29ycG9yYXRpdm8wgc4GCCsGAQUFBwICMIHBGoG+Wml1cnRhZ2lyaWEgRXVza2Fs -+IEF1dG9ub21pYSBFcmtpZGVnb2tvIHNla3RvcmUgcHVibGlrb2tvIGVyYWt1bmRl -+ZW4gYmFybmUtc2FyZWV0YW4gYmFrYXJyaWsgZXJhYmlsIGRhaXRla2UuIFVzbyBy -+ZXN0cmluZ2lkbyBhbCBhbWJpdG8gZGUgcmVkZXMgaW50ZXJuYXMgZGUgRW50aWRh -+ZGVzIGRlbCBTZWN0b3IgUHVibGljbyBWYXNjbzAyBggrBgEFBQcBAQQmMCQwIgYI -+KwYBBQUHMAGGFmh0dHA6Ly9vY3NwLml6ZW5wZS5jb20wOgYDVR0fBDMwMTAvoC2g -+K4YpaHR0cDovL2NybC5pemVucGUuY29tL2NnaS1iaW4vY3JsaW50ZXJuYTIwDQYJ -+KoZIhvcNAQELBQADggIBAIy5PQ+UZlCRq6ig43vpHwlwuD9daAYeejV0Q+ZbgWAE -+GtO0kT/ytw95ZEJMNiMw3fYfPRlh27ThqiT0VDXZJDlzmn7JZd6QFcdXkCsiuv4+ -+ZoXAg/QwnA3SGUUO9aVaXyuOIIuvOfb9MzoGp9xk23SMV3eiLAaLMLqwB5DTfBdt -+BGI7L1MnGJBv8RfP/TL67aJ5bgq2ri4S8vGHtXSjcZ0+rCEOLJtmDNMnTZxancg3 -+/H5edeNd+n6Z48LO+JHRxQufbC4mVNxVLMIP9EkGUejlq4E4w6zb5NwCQczJbSWL -+i31rk2orsNsDlyaLGsWZp3JSNX6RmodU4KAUPor4jUJuUhrrm3Spb73gKlV/gcIw -+bCE7mML1Kss3x1ySaXsis6SZtLpGWKkW2iguPWPs0ydV6RPhmsCxieMwPPIJ87vS -+5IejfgyBae7RSuAIHyNFy4uI5xwvwUFf6OZ7az8qtW7ImFOgng3Ds+W9k1S2CNTx -+d0cnKTfA6IpjGo8EeHcxnIXT8NPImWaRj0qqonvYady7ci6U4m3lkNSdXNn1afgw -+mYust+gxVtOZs1gk2MUCgJ1V1X+g7r/Cg7viIn6TLkLrpS1kS1hvMqkl9M+7XqPo -+Qd95nJKOkusQpy99X4dF/lfbYAQnnjnqh3DLD2gvYObXFaAYFaiBKTiMTV2X72F+ -+-----END CERTIFICATE-----` -+ -+const smimeIntermediate = `-----BEGIN CERTIFICATE----- -+MIIHNzCCBSGgAwIBAgIQJMXIqlZvjuhMvqcFXOFkpDALBgkqhkiG9w0BAQswODEL -+MAkGA1UEBhMCRVMxFDASBgNVBAoMC0laRU5QRSBTLkEuMRMwEQYDVQQDDApJemVu -+cGUuY29tMB4XDTEwMTAyMDA4MjMzM1oXDTM3MTIxMjIzMDAwMFowgZ0xCzAJBgNV -+BAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjE6MDgGA1UECwwxQVpaIFppdXJ0 -+YWdpcmkgcHVibGlrb2EgLSBDZXJ0aWZpY2FkbyBwdWJsaWNvIFNDQTE8MDoGA1UE -+AwwzRUFFa28gSGVycmkgQWRtaW5pc3RyYXppb2VuIENBIC0gQ0EgQUFQUCBWYXNj -+YXMgKDIpMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoIM7nEdI0N1h -+rR5T4xuV/usKDoMIasaiKvfLhbwxaNtTt+a7W/6wV5bv3svQFIy3sUXjjdzV1nG2 -+To2wo/YSPQiOt8exWvOapvL21ogiof+kelWnXFjWaKJI/vThHYLgIYEMj/y4HdtU -+ojI646rZwqsb4YGAopwgmkDfUh5jOhV2IcYE3TgJAYWVkj6jku9PLaIsHiarAHjD -+PY8dig8a4SRv0gm5Yk7FXLmW1d14oxQBDeHZ7zOEXfpafxdEDO2SNaRJjpkh8XRr -+PGqkg2y1Q3gT6b4537jz+StyDIJ3omylmlJsGCwqT7p8mEqjGJ5kC5I2VnjXKuNn -+soShc72khWZVUJiJo5SGuAkNE2ZXqltBVm5Jv6QweQKsX6bkcMc4IZok4a+hx8FM -+8IBpGf/I94pU6HzGXqCyc1d46drJgDY9mXa+6YDAJFl3xeXOOW2iGCfwXqhiCrKL -+MYvyMZzqF3QH5q4nb3ZnehYvraeMFXJXDn+Utqp8vd2r7ShfQJz01KtM4hgKdgSg -+jtW+shkVVN5ng/fPN85ovfAH2BHXFfHmQn4zKsYnLitpwYM/7S1HxlT61cdQ7Nnk -+3LZTYEgAoOmEmdheklT40WAYakksXGM5VrzG7x9S7s1Tm+Vb5LSThdHC8bxxwyTb -+KsDRDNJ84N9fPDO6qHnzaL2upQ43PycCAwEAAaOCAdkwggHVMIHHBgNVHREEgb8w -+gbyGFWh0dHA6Ly93d3cuaXplbnBlLmNvbYEPaW5mb0BpemVucGUuY29tpIGRMIGO -+MUcwRQYDVQQKDD5JWkVOUEUgUy5BLiAtIENJRiBBMDEzMzcyNjAtUk1lcmMuVml0 -+b3JpYS1HYXN0ZWl6IFQxMDU1IEY2MiBTODFDMEEGA1UECQw6QXZkYSBkZWwgTWVk -+aXRlcnJhbmVvIEV0b3JiaWRlYSAxNCAtIDAxMDEwIFZpdG9yaWEtR2FzdGVpejAP -+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUwKlK90cl -+h/+8taaJzoLSRqiJ66MwHwYDVR0jBBgwFoAUHRxlDqjyJXu0kc/ksbHmvVV0bAUw -+OgYDVR0gBDMwMTAvBgRVHSAAMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly93d3cuaXpl -+bnBlLmNvbS9jcHMwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8v -+b2NzcC5pemVucGUuY29tOjgwOTQwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2Ny -+bC5pemVucGUuY29tL2NnaS1iaW4vYXJsMjALBgkqhkiG9w0BAQsDggIBAMbjc3HM -+3DG9ubWPkzsF0QsktukpujbTTcGk4h20G7SPRy1DiiTxrRzdAMWGjZioOP3/fKCS -+M539qH0M+gsySNie+iKlbSZJUyE635T1tKw+G7bDUapjlH1xyv55NC5I6wCXGC6E -+3TEP5B/E7dZD0s9E4lS511ubVZivFgOzMYo1DO96diny/N/V1enaTCpRl1qH1OyL -+xUYTijV4ph2gL6exwuG7pxfRcVNHYlrRaXWfTz3F6NBKyULxrI3P/y6JAtN1GqT4 -+VF/+vMygx22n0DufGepBwTQz6/rr1ulSZ+eMnuJiTXgh/BzQnkUsXTb8mHII25iR -+0oYF2qAsk6ecWbLiDpkHKIDHmML21MZE13MS8NSvTHoqJO4LyAmDe6SaeNHtrPlK -+b6mzE1BN2ug+ZaX8wLA5IMPFaf0jKhb/Cxu8INsxjt00brsErCc9ip1VNaH0M4bi -+1tGxfiew2436FaeyUxW7Pl6G5GgkNbuUc7QIoRy06DdU/U38BxW3uyJMY60zwHvS -+FlKAn0OvYp4niKhAJwaBVN3kowmJuOU5Rid+TUnfyxbJ9cttSgzaF3hP/N4zgMEM -+5tikXUskeckt8LUK96EH0QyssavAMECUEb/xrupyRdYWwjQGvNLq6T5+fViDGyOw -+k+lzD44wofy8paAy9uC9Owae0zMEzhcsyRm7 -+-----END CERTIFICATE-----` -+ -+const smimeRoot = `-----BEGIN CERTIFICATE----- -+MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 -+MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 -+ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD -+VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j -+b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq -+scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO -+xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H -+LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX -+uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD -+yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ -+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q -+rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN -+BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L -+hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB -+QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ -+HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu -+Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg -+QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB -+BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx -+MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -+AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA -+A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb -+laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 -+awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo -+JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw -+LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT -+VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk -+LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb -+UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ -+QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ -+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls -+QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== -+-----END CERTIFICATE-----` -+ -+var nameConstraintsLeaf = `-----BEGIN CERTIFICATE----- -+MIIHMTCCBRmgAwIBAgIIIZaV/3ezOJkwDQYJKoZIhvcNAQEFBQAwgcsxCzAJBgNV -+BAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEj -+MCEGA1UECxMaR2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1Zp -+cmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0 -+eTExMC8GA1UEAxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZl -+ciBDQTAeFw0xMzA5MTkxNDM2NTVaFw0xNTA5MTkxNDM2NTVaMIHNMQswCQYDVQQG -+EwJVUzERMA8GA1UECAwIVmlyZ2luaWExEzARBgNVBAcMCkJsYWNrc2J1cmcxPDA6 -+BgNVBAoMM1ZpcmdpbmlhIFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUg -+VW5pdmVyc2l0eTE7MDkGA1UECwwyVGVjaG5vbG9neS1lbmhhbmNlZCBMZWFybmlu -+ZyBhbmQgT25saW5lIFN0cmF0ZWdpZXMxGzAZBgNVBAMMEnNlY3VyZS5pZGRsLnZ0 -+LmVkdTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKkOyPpsOK/6IuPG -+WnIBlVwlHzeYf+cUlggqkLq0b0+vZbiTXgio9/VCuNQ8opSoss7J7o3ygV9to+9Y -+YwJKVC5WDT/y5JWpQey0CWILymViJnpNSwnxBc8A+Q8w5NUGDd/UhtPx/U8/hqbd -+WPDYj2hbOqyq8UlRhfS5pwtnv6BbCTaY11I6FhCLK7zttISyTuWCf9p9o/ggiipP -+ii/5oh4dkl+r5SfuSp5GPNHlYO8lWqys5NAPoDD4fc/kuflcK7Exx7XJ+Oqu0W0/ -+psjEY/tES1ZgDWU/ParcxxFpFmKHbD5DXsfPOObzkVWXIY6tGMutSlE1Froy/Nn0 -+OZsAOrcCAwEAAaOCAhMwggIPMIG4BggrBgEFBQcBAQSBqzCBqDBYBggrBgEFBQcw -+AoZMaHR0cDovL3d3dy5wa2kudnQuZWR1L2dsb2JhbHF1YWxpZmllZHNlcnZlci9j -+YWNlcnQvZ2xvYmFscXVhbGlmaWVkc2VydmVyLmNydDBMBggrBgEFBQcwAYZAaHR0 -+cDovL3Z0Y2EtcC5lcHJvdi5zZXRpLnZ0LmVkdTo4MDgwL2VqYmNhL3B1YmxpY3dl -+Yi9zdGF0dXMvb2NzcDAdBgNVHQ4EFgQUp7xbO6iHkvtZbPE4jmndmnAbSEcwDAYD -+VR0TAQH/BAIwADAfBgNVHSMEGDAWgBS8YmAn1eM1SBfpS6tFatDIqHdxjDBqBgNV -+HSAEYzBhMA4GDCsGAQQBtGgFAgICATAOBgwrBgEEAbRoBQICAQEwPwYMKwYBBAG0 -+aAUCAgMBMC8wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucGtpLnZ0LmVkdS9nbG9i -+YWwvY3BzLzBKBgNVHR8EQzBBMD+gPaA7hjlodHRwOi8vd3d3LnBraS52dC5lZHUv -+Z2xvYmFscXVhbGlmaWVkc2VydmVyL2NybC9jYWNybC5jcmwwDgYDVR0PAQH/BAQD -+AgTwMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAdBgNVHREEFjAUghJz -+ZWN1cmUuaWRkbC52dC5lZHUwDQYJKoZIhvcNAQEFBQADggIBAEgoYo4aUtatY3gI -+OyyKp7QlIOaLbTJZywESHqy+L5EGDdJW2DJV+mcE0LDGvqa2/1Lo+AR1ntsZwfOi -+Y718JwgVVaX/RCd5+QKP25c5/x72xI8hb/L1bgS0ED9b0YAhd7Qm1K1ot82+6mqX -+DW6WiGeDr8Z07MQ3143qQe2rBlq+QI69DYzm2GOqAIAnUIWv7tCyLUm31b4DwmrJ -+TeudVreTKUbBNB1TWRFHEPkWhjjXKZnNGRO11wHXcyBu6YekIvVZ+vmx8ePee4jJ -+3GFOi7lMuWOeq57jTVL7KOKaKLVXBb6gqo5aq+Wwt8RUD5MakrCAEeQZj7DKaFmZ -+oQCO0Pxrsl3InCGvxnGzT+bFVO9nJ/BAMj7hknFdm9Jr6Bg5q33Z+gnf909AD9QF -+ESqUSykaHu2LVdJx2MaCH1CyKnRgMw5tEwE15EXpUjCm24m8FMOYC+rNtf18pgrz -+5D8Jhh+oxK9PjcBYqXNtnioIxiMCYcV0q5d4w4BYFEh71tk7/bYB0R55CsBUVPmp -+timWNOdRd57Tfpk3USaVsumWZAf9MP3wPiC7gb4d5tYEEAG5BuDT8ruFw838wU8G -+1VvAVutSiYBg7k3NYO7AUqZ+Ax4klQX3aM9lgonmJ78Qt94UPtbptrfZ4/lSqEf8 -+GBUwDrQNTb+gsXsDkjd5lcYxNx6l -+-----END CERTIFICATE-----` -+ -+var nameConstraintsIntermediate1 = `-----BEGIN CERTIFICATE----- -+MIINLjCCDBagAwIBAgIRIqpyf/YoGgvHc8HiDAxAI8owDQYJKoZIhvcNAQEFBQAw -+XDELMAkGA1UEBhMCQkUxFTATBgNVBAsTDFRydXN0ZWQgUm9vdDEZMBcGA1UEChMQ -+R2xvYmFsU2lnbiBudi1zYTEbMBkGA1UEAxMSVHJ1c3RlZCBSb290IENBIEcyMB4X -+DTEyMTIxMzAwMDAwMFoXDTE3MTIxMzAwMDAwMFowgcsxCzAJBgNVBAYTAlVTMREw -+DwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEjMCEGA1UECxMa -+R2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1ZpcmdpbmlhIFBv -+bHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0eTExMC8GA1UE -+AxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZlciBDQTCCAiIw -+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALgIZhEaptBWADBqdJ45ueFGzMXa -+GHnzNxoxR1fQIaaRQNdCg4cw3A4dWKMeEgYLtsp65ai3Xfw62Qaus0+KJ3RhgV+r -+ihqK81NUzkls78fJlADVDI4fCTlothsrE1CTOMiy97jKHai5mVTiWxmcxpmjv7fm -+5Nhc+uHgh2hIz6npryq495mD51ZrUTIaqAQN6Pw/VHfAmR524vgriTOjtp1t4lA9 -+pXGWjF/vkhAKFFheOQSQ00rngo2wHgCqMla64UTN0oz70AsCYNZ3jDLx0kOP0YmM -+R3Ih91VA63kLqPXA0R6yxmmhhxLZ5bcyAy1SLjr1N302MIxLM/pSy6aquEnbELhz -+qyp9yGgRyGJay96QH7c4RJY6gtcoPDbldDcHI9nXngdAL4DrZkJ9OkDkJLyqG66W -+ZTF5q4EIs6yMdrywz0x7QP+OXPJrjYpbeFs6tGZCFnWPFfmHCRJF8/unofYrheq+ -+9J7Jx3U55S/k57NXbAM1RAJOuMTlfn9Etf9Dpoac9poI4Liav6rBoUQk3N3JWqnV -+HNx/NdCyJ1/6UbKMJUZsStAVglsi6lVPo289HHOE4f7iwl3SyekizVOp01wUin3y -+cnbZB/rXmZbwapSxTTSBf0EIOr9i4EGfnnhCAVA9U5uLrI5OEB69IY8PNX0071s3 -+Z2a2fio5c8m3JkdrAgMBAAGjggh5MIIIdTAOBgNVHQ8BAf8EBAMCAQYwTAYDVR0g -+BEUwQzBBBgkrBgEEAaAyATwwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xv -+YmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wEgYDVR0TAQH/BAgwBgEB/wIBADCCBtAG -+A1UdHgSCBscwggbDoIIGvzASghAzZGJsYWNrc2J1cmcub3JnMBiCFmFjY2VsZXJh -+dGV2aXJnaW5pYS5jb20wGIIWYWNjZWxlcmF0ZXZpcmdpbmlhLm9yZzALgglhY3Zj -+cC5vcmcwCYIHYmV2Lm5ldDAJggdiZXYub3JnMAuCCWNsaWdzLm9yZzAMggpjbWl3 -+ZWIub3JnMBeCFWVhc3Rlcm5icm9va3Ryb3V0Lm5ldDAXghVlYXN0ZXJuYnJvb2t0 -+cm91dC5vcmcwEYIPZWNvcnJpZG9ycy5pbmZvMBOCEWVkZ2FycmVzZWFyY2gub3Jn -+MBKCEGdldC1lZHVjYXRlZC5jb20wE4IRZ2V0LWVkdWNhdGVkLmluZm8wEYIPZ2V0 -+ZWR1Y2F0ZWQubmV0MBKCEGdldC1lZHVjYXRlZC5uZXQwEYIPZ2V0ZWR1Y2F0ZWQu -+b3JnMBKCEGdldC1lZHVjYXRlZC5vcmcwD4INaG9raWVjbHViLmNvbTAQgg5ob2tp -+ZXBob3RvLmNvbTAPgg1ob2tpZXNob3AuY29tMBGCD2hva2llc3BvcnRzLmNvbTAS -+ghBob2tpZXRpY2tldHMuY29tMBKCEGhvdGVscm9hbm9rZS5jb20wE4IRaHVtYW53 -+aWxkbGlmZS5vcmcwF4IVaW5uYXR2aXJnaW5pYXRlY2guY29tMA+CDWlzY2hwMjAx -+MS5vcmcwD4INbGFuZHJlaGFiLm9yZzAggh5uYXRpb25hbHRpcmVyZXNlYXJjaGNl -+bnRlci5jb20wFYITbmV0d29ya3ZpcmdpbmlhLm5ldDAMggpwZHJjdnQuY29tMBiC -+FnBldGVkeWVyaXZlcmNvdXJzZS5jb20wDYILcmFkaW9pcS5vcmcwFYITcml2ZXJj -+b3Vyc2Vnb2xmLmNvbTALgglzZGltaS5vcmcwEIIOc292YW1vdGlvbi5jb20wHoIc -+c3VzdGFpbmFibGUtYmlvbWF0ZXJpYWxzLmNvbTAeghxzdXN0YWluYWJsZS1iaW9t -+YXRlcmlhbHMub3JnMBWCE3RoaXNpc3RoZWZ1dHVyZS5jb20wGIIWdGhpcy1pcy10 -+aGUtZnV0dXJlLmNvbTAVghN0aGlzaXN0aGVmdXR1cmUubmV0MBiCFnRoaXMtaXMt -+dGhlLWZ1dHVyZS5uZXQwCoIIdmFkcy5vcmcwDIIKdmFsZWFmLm9yZzANggt2YXRl -+Y2guaW5mbzANggt2YXRlY2gubW9iaTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5n -+LmNvbTAcghp2YXRlY2hsaWZlbG9uZ2xlYXJuaW5nLm5ldDAcghp2YXRlY2hsaWZl -+bG9uZ2xlYXJuaW5nLm9yZzAKggh2Y29tLmVkdTASghB2aXJnaW5pYXZpZXcubmV0 -+MDSCMnZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVuaXZlcnNp -+dHkuY29tMDWCM3ZpcmdpbmlhcG9seXRlY2huaWNpbnN0aXR1dGVhbmRzdGF0ZXVu -+aXZlcnNpdHkuaW5mbzA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0dXRlYW5k -+c3RhdGV1bml2ZXJzaXR5Lm5ldDA0gjJ2aXJnaW5pYXBvbHl0ZWNobmljaW5zdGl0 -+dXRlYW5kc3RhdGV1bml2ZXJzaXR5Lm9yZzAZghd2aXJnaW5pYXB1YmxpY3JhZGlv -+Lm9yZzASghB2aXJnaW5pYXRlY2guZWR1MBOCEXZpcmdpbmlhdGVjaC5tb2JpMByC -+GnZpcmdpbmlhdGVjaGZvdW5kYXRpb24ub3JnMAiCBnZ0LmVkdTALggl2dGFyYy5v -+cmcwDIIKdnQtYXJjLm9yZzALggl2dGNyYy5jb20wCoIIdnRpcC5vcmcwDIIKdnRs -+ZWFuLm9yZzAWghR2dGtub3dsZWRnZXdvcmtzLmNvbTAYghZ2dGxpZmVsb25nbGVh -+cm5pbmcuY29tMBiCFnZ0bGlmZWxvbmdsZWFybmluZy5uZXQwGIIWdnRsaWZlbG9u -+Z2xlYXJuaW5nLm9yZzATghF2dHNwb3J0c21lZGlhLmNvbTALggl2dHdlaS5jb20w -+D4INd2l3YXR3ZXJjLmNvbTAKggh3dnRmLm9yZzAIgQZ2dC5lZHUwd6R1MHMxCzAJ -+BgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVy -+ZzE8MDoGA1UEChMzVmlyZ2luaWEgUG9seXRlY2huaWMgSW5zdGl0dXRlIGFuZCBT -+dGF0ZSBVbml2ZXJzaXR5MCcGA1UdJQQgMB4GCCsGAQUFBwMCBggrBgEFBQcDAQYI -+KwYBBQUHAwkwPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2NybC5nbG9iYWxzaWdu -+LmNvbS9ncy90cnVzdHJvb3RnMi5jcmwwgYQGCCsGAQUFBwEBBHgwdjAzBggrBgEF -+BQcwAYYnaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL3RydXN0cm9vdGcyMD8G -+CCsGAQUFBzAChjNodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC90 -+cnVzdHJvb3RnMi5jcnQwHQYDVR0OBBYEFLxiYCfV4zVIF+lLq0Vq0Miod3GMMB8G -+A1UdIwQYMBaAFBT25YsxtkWASkxt/MKHico2w5BiMA0GCSqGSIb3DQEBBQUAA4IB -+AQAyJm/lOB2Er4tHXhc/+fSufSzgjohJgYfMkvG4LknkvnZ1BjliefR8tTXX49d2 -+SCDFWfGjqyJZwavavkl/4p3oXPG/nAMDMvxh4YAT+CfEK9HH+6ICV087kD4BLegi -++aFJMj8MMdReWCzn5sLnSR1rdse2mo2arX3Uod14SW+PGrbUmTuWNyvRbz3fVmxp -+UdbGmj3laknO9YPsBGgHfv73pVVsTJkW4ZfY/7KdD/yaVv6ophpOB3coXfjl2+kd -+Z4ypn2zK+cx9IL/LSewqd/7W9cD55PCUy4X9OTbEmAccwiz3LB66mQoUGfdHdkoB -+jUY+v9vLQXmaVwI0AYL7g9LN -+-----END CERTIFICATE-----` -+ -+var nameConstraintsIntermediate2 = `-----BEGIN CERTIFICATE----- -+MIIEXTCCA0WgAwIBAgILBAAAAAABNuk6OrMwDQYJKoZIhvcNAQEFBQAwVzELMAkG -+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv -+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw0xMjA0MjUxMTAw -+MDBaFw0yNzA0MjUxMTAwMDBaMFwxCzAJBgNVBAYTAkJFMRUwEwYDVQQLEwxUcnVz -+dGVkIFJvb3QxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExGzAZBgNVBAMTElRy -+dXN0ZWQgUm9vdCBDQSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -+AKyuvqrtcMr7g7EuNbu4sKwxM127UsCmx1RxbxxgcArGS7rjiefpBH/w4LYrymjf -+vcw1ueyMNoqLo9nJMz/ORXupb35NNfE667prQYHa+tTjl1IiKpB7QUwt3wXPuTMF -+Ja1tXtjKzkqJyuJlNuPKT76HcjgNqgV1s9qG44MD5I2JvI12du8zI1bgdQ+l/KsX -+kTfbGjUvhOLOlVNWVQDpL+YMIrGqgBYxy5TUNgrAcRtwpNdS2KkF5otSmMweVb5k -+hoUVv3u8UxQH/WWbNhHq1RrIlg/0rBUfi/ziShYFSB7U+aLx5DxPphTFBiDquQGp -+tB+FC4JvnukDStFihZCZ1R8CAwEAAaOCASMwggEfMA4GA1UdDwEB/wQEAwIBBjAP -+BgNVHRMBAf8EBTADAQH/MEcGA1UdIARAMD4wPAYEVR0gADA0MDIGCCsGAQUFBwIB -+FiZodHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzAdBgNVHQ4E -+FgQUFPblizG2RYBKTG38woeJyjbDkGIwMwYDVR0fBCwwKjAooCagJIYiaHR0cDov -+L2NybC5nbG9iYWxzaWduLm5ldC9yb290LmNybDA+BggrBgEFBQcBAQQyMDAwLgYI -+KwYBBQUHMAGGImh0dHA6Ly9vY3NwMi5nbG9iYWxzaWduLmNvbS9yb290cjEwHwYD -+VR0jBBgwFoAUYHtmGkUNl8qJUC99BM00qP/8/UswDQYJKoZIhvcNAQEFBQADggEB -+AL7IG0l+k4LkcpI+a/kvZsSRwSM4uA6zGX34e78A2oytr8RG8bJwVb8+AHMUD+Xe -+2kYdh/Uj/waQXfqR0OgxQXL9Ct4ZM+JlR1avsNKXWL5AwYXAXCOB3J5PW2XOck7H -+Zw0vRbGQhjWjQx+B4KOUFg1b3ov/z6Xkr3yaCfRQhXh7KC0Bc0RXPPG5Nv5lCW+z -+tbbg0zMm3kyfQITRusMSg6IBsDJqOnjaiaKQRcXiD0Sk43ZXb2bUKMxC7+Td3QL4 -+RyHcWJbQ7YylLTS/x+jxWIcOQ0oO5/54t5PTQ14neYhOz9x4gUk2AYAW6d1vePwb -+hcC8roQwkHT7HvfYBoc74FM= -+-----END CERTIFICATE-----` -+ -+var globalSignRoot = `-----BEGIN CERTIFICATE----- -+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG -+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv -+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw -+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i -+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT -+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ -+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp -+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp -+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG -+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ -+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 -+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E -+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B -+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz -+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE -+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP -+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad -+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME -+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -+-----END CERTIFICATE-----` -+ -+const digicertRoot = `-----BEGIN CERTIFICATE----- -+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh -+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT -+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j -+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG -+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB -+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 -+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt -+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P -+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 -+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO -+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR -+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw -+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr -+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg -+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF -+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls -+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk -+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -+-----END CERTIFICATE-----` -+ -+const trustAsiaSHA384Intermediate = `-----BEGIN CERTIFICATE----- -+MIID9zCCAt+gAwIBAgIQC965p4OR4AKrGlsyW0XrDzANBgkqhkiG9w0BAQwFADBh -+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD -+QTAeFw0xODA0MjcxMjQyNTlaFw0yODA0MjcxMjQyNTlaMFoxCzAJBgNVBAYTAkNO -+MSUwIwYDVQQKExxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQD -+ExtUcnVzdEFzaWEgRUNDIE9WIFRMUyBQcm8gQ0EwdjAQBgcqhkjOPQIBBgUrgQQA -+IgNiAAQPIUn75M5BCQLKoPsSU2KTr3mDMh13usnAQ38XfKOzjXiyQ+W0inA7meYR -+xS+XMQgvnbCigEsKj3ErPIzO68uC9V/KdqMaXWBJp85Ws9A4KL92NB4Okbn5dp6v -+Qzy08PajggFeMIIBWjAdBgNVHQ4EFgQULdRyBx6HyIH/+LOvuexyH5p/3PwwHwYD -+VR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQDAgGGMB0G -+A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEA -+MDcGCCsGAQUFBwEBBCswKTAnBggrBgEFBQcwAYYbaHR0cDovL29jc3AuZGlnaWNl -+cnQtY24uY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwuZGlnaWNlcnQt -+Y24uY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDBWBgNVHSAETzBNMDcGCWCG -+SAGG/WwBATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20v -+Q1BTMAgGBmeBDAECAjAIBgZngQwBAgMwDQYJKoZIhvcNAQEMBQADggEBACVRufYd -+j81xUqngFCO+Pk8EYXie0pxHKsBZnOPygAyXKx+awUasKBAnHjmhoFPXaDGAP2oV -+OeZTWgwnURVr6wUCuTkz2/8Tgl1egC7OrVcHSa0fIIhaVo9/zRA/hr31xMG7LFBk -+GNd7jd06Up4f/UOGbcJsqJexc5QRcUeSwe1MiUDcTNiyCjZk74QCPdcfdFYM4xsa -+SlUpboB5vyT7jFePZ2v95CKjcr0EhiQ0gwxpdgoipZdfYTiMFGxCLsk6v8pUv7Tq -+PT/qadOGyC+PfLuZh1PtLp20mF06K+MzheCiv+w1NT5ofhmcObvukc68wvbvRFL6 -+rRzZxAYN36q1SX8= -+-----END CERTIFICATE-----` -+ -+const trustAsiaLeaf = `-----BEGIN CERTIFICATE----- -+MIIEwTCCBEegAwIBAgIQBOjomZfHfhgz2bVYZVuf2DAKBggqhkjOPQQDAzBaMQsw -+CQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywgSW5j -+LjEkMCIGA1UEAxMbVHJ1c3RBc2lhIEVDQyBPViBUTFMgUHJvIENBMB4XDTE5MDUx -+NzAwMDAwMFoXDTIwMDcyODEyMDAwMFowgY0xCzAJBgNVBAYTAkNOMRIwEAYDVQQI -+DAnnpo/lu7rnnIExEjAQBgNVBAcMCeWOpumXqOW4gjEqMCgGA1UECgwh5Y6m6Zeo -+5Y+B546W5Y+B56eR5oqA5pyJ6ZmQ5YWs5Y+4MRgwFgYDVQQLDA/nn6Xor4bkuqfm -+nYPpg6gxEDAOBgNVBAMMByoudG0uY24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC -+AARx/MDQ0oGnCLagQIzjIz57iqFYFmz4/W6gaU6N+GHBkzyvQU8aX02QkdlTTNYL -+TCoGFJxHB0XlZVSxrqoIPlNKo4ICuTCCArUwHwYDVR0jBBgwFoAULdRyBx6HyIH/ -++LOvuexyH5p/3PwwHQYDVR0OBBYEFGTyf5adc5smW8NvDZyummJwZRLEMBkGA1Ud -+EQQSMBCCByoudG0uY26CBXRtLmNuMA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAU -+BggrBgEFBQcDAQYIKwYBBQUHAwIwRgYDVR0fBD8wPTA7oDmgN4Y1aHR0cDovL2Ny -+bC5kaWdpY2VydC1jbi5jb20vVHJ1c3RBc2lhRUNDT1ZUTFNQcm9DQS5jcmwwTAYD -+VR0gBEUwQzA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cu -+ZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBAgIwfgYIKwYBBQUHAQEEcjBwMCcGCCsG -+AQUFBzABhhtodHRwOi8vb2NzcC5kaWdpY2VydC1jbi5jb20wRQYIKwYBBQUHMAKG -+OWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LWNuLmNvbS9UcnVzdEFzaWFFQ0NPVlRM -+U1Byb0NBLmNydDAMBgNVHRMBAf8EAjAAMIIBAwYKKwYBBAHWeQIEAgSB9ASB8QDv -+AHUA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFqxGMTnwAABAMA -+RjBEAiAz13zKEoyqd4e/96SK/fxfjl7uR+xhfoDZeyA1BvtfOwIgTY+8nJMGekv8 -+leIVdW6AGh7oqH31CIGTAbNJJWzaSFYAdgCHdb/nWXz4jEOZX73zbv9WjUdWNv9K -+tWDBtOr/XqCDDwAAAWrEYxTCAAAEAwBHMEUCIQDlWm7+limbRiurcqUwXav3NSmx -+x/aMnolLbh6+f+b1XAIgQfinHwLw6pDr4R9UkndUsX8QFF4GXS3/IwRR8HCp+pIw -+CgYIKoZIzj0EAwMDaAAwZQIwHg8JmjRtcq+OgV0vVmdVBPqehi1sQJ9PZ+51CG+Z -+0GOu+2HwS/fyLRViwSc/MZoVAjEA7NgbgpPN4OIsZn2XjMGxemtVxGFS6ZR+1364 -+EEeHB9vhZAEjQSePAfjR9aAGhXRa -+-----END CERTIFICATE-----` -+ -+const selfSigned = `-----BEGIN CERTIFICATE----- -+MIIC/DCCAeSgAwIBAgIRAK0SWRVmi67xU3z0gkgY+PkwDQYJKoZIhvcNAQELBQAw -+EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjA4MTkxNjMzNDdaFw0xNzA4MTkxNjMz -+NDdaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -+ggEKAoIBAQDWkm1kdCwxyKEt6OTmZitkmLGH8cQu9z7rUdrhW8lWNm4kh2SuaUWP -+pscBjda5iqg51aoKuWJR2rw6ElDne+X5eit2FT8zJgAU8v39lMFjbaVZfS9TFOYF -+w0Tk0Luo/PyKJpZnwhsP++iiGQiteJbndy8aLKmJ2MpLfpDGIgxEIyNb5dgoDi0D -+WReDCpE6K9WDYqvKVGnQ2Jvqqra6Gfx0tFkuqJxQuqA8aUOlPHcCH4KBZdNEoXdY -+YL3E4dCAh0YiDs80wNZx4cHqEM3L8gTEFqW2Tn1TSuPZO6gjJ9QPsuUZVjaMZuuO -+NVxqLGujZkDzARhC3fBpptMuaAfi20+BAgMBAAGjTTBLMA4GA1UdDwEB/wQEAwIF -+oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBYGA1UdEQQPMA2C -+C2Zvby5leGFtcGxlMA0GCSqGSIb3DQEBCwUAA4IBAQBPvvfnDhsHWt+/cfwdAVim -+4EDn+hYOMkTQwU0pouYIvY8QXYkZ8MBxpBtBMK4JhFU+ewSWoBAEH2dCCvx/BDxN -+UGTSJHMbsvJHcFvdmsvvRxOqQ/cJz7behx0cfoeHMwcs0/vWv8ms5wHesb5Ek7L0 -+pl01FCBGTcncVqr6RK1r4fTpeCCfRIERD+YRJz8TtPH6ydesfLL8jIV40H8NiDfG -+vRAvOtNiKtPzFeQVdbRPOskC4rcHyPeiDAMAMixeLi63+CFty4da3r5lRezeedCE -+cw3ESZzThBwWqvPOtJdpXdm+r57pDW8qD+/0lY8wfImMNkQAyCUCLg/1Lxt/hrBj -+-----END CERTIFICATE-----` -+ -+const issuerSubjectMatchRoot = `-----BEGIN CERTIFICATE----- -+MIICIDCCAYmgAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwIzEPMA0GA1UE -+ChMGR29sYW5nMRAwDgYDVQQDEwdSb290IGNhMB4XDTE1MDEwMTAwMDAwMFoXDTI1 -+MDEwMTAwMDAwMFowIzEPMA0GA1UEChMGR29sYW5nMRAwDgYDVQQDEwdSb290IGNh -+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1 -+siSSOO4mYgLHlPE+oXdqwI/VImi2XeJM2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw -++QzGj+mz36NqhGxDWb6dstB2m8PX+plZw7jl81MDvUnWs8yiQ/6twgu5AbhWKZQD -+JKcNKCEpqa6UW0r5nwIDAQABo10wWzAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYw -+FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIE -+EEA31wH7QC+4HH5UBCeMWQEwDQYJKoZIhvcNAQELBQADgYEAb4TfSeCZ1HFmHTKG -+VsvqWmsOAGrRWm4fBiMH/8vRGnTkJEMLqiqgc3Ulgry/P6n4SIis7TqUOw3TiMhn -+RGEz33Fsxa/tFoy/gvlJu+MqB1M2NyV33pGkdwl/b7KRWMQFieqO+uE7Ge/49pS3 -+eyfm5ITdK/WT9TzYhsU4AVZcn20= -+-----END CERTIFICATE-----` -+ -+const issuerSubjectMatchLeaf = `-----BEGIN CERTIFICATE----- -+MIICODCCAaGgAwIBAgIJAOjwnT/iW+qmMA0GCSqGSIb3DQEBCwUAMCMxDzANBgNV -+BAoTBkdvbGFuZzEQMA4GA1UEAxMHUm9vdCBDQTAeFw0xNTAxMDEwMDAwMDBaFw0y -+NTAxMDEwMDAwMDBaMCAxDzANBgNVBAoTBkdvbGFuZzENMAsGA1UEAxMETGVhZjCB -+nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA20Z9ky4SJwZIvAYoIat+xLaiXf4e -+UkWIejZHpQgNkkJbwoHAvpd5mED7T20U/SsTi8KlLmfY1Ame1iI4t0oLdHMrwjTx -+0ZPlltl0e/NYn2xhPMCwQdTZKyskI3dbHDu9dV3OIFTPoWOHHR4kxPMdGlCLqrYU -+Q+2Xp3Vi9BTIUtcCAwEAAaN3MHUwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQG -+CCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMBkGA1UdDgQSBBCfkRYf -+Q0M+SabebbaA159gMBsGA1UdIwQUMBKAEEA31wH7QC+4HH5UBCeMWQEwDQYJKoZI -+hvcNAQELBQADgYEAjYYF2on1HcUWFEG5NIcrXDiZ49laW3pb3gtcCEUJbxydMV8I -+ynqjmdqDCyK+TwI1kU5dXDe/iSJYfTB20i/QoO53nnfA1hnr7KBjNWqAm4AagN5k -+vEA4PCJprUYmoj3q9MKSSRYDlq5kIbl87mSRR4GqtAwJKxIasvOvULOxziQ= -+-----END CERTIFICATE-----` -+ -+const x509v1TestRoot = `-----BEGIN CERTIFICATE----- -+MIICIDCCAYmgAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwIzEPMA0GA1UE -+ChMGR29sYW5nMRAwDgYDVQQDEwdSb290IENBMB4XDTE1MDEwMTAwMDAwMFoXDTI1 -+MDEwMTAwMDAwMFowIzEPMA0GA1UEChMGR29sYW5nMRAwDgYDVQQDEwdSb290IENB -+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1 -+siSSOO4mYgLHlPE+oXdqwI/VImi2XeJM2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw -++QzGj+mz36NqhGxDWb6dstB2m8PX+plZw7jl81MDvUnWs8yiQ/6twgu5AbhWKZQD -+JKcNKCEpqa6UW0r5nwIDAQABo10wWzAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYw -+FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIE -+EEA31wH7QC+4HH5UBCeMWQEwDQYJKoZIhvcNAQELBQADgYEAcIwqeNUpQr9cOcYm -+YjpGpYkQ6b248xijCK7zI+lOeWN89zfSXn1AvfsC9pSdTMeDklWktbF/Ad0IN8Md -+h2NtN34ard0hEfHc8qW8mkXdsysVmq6cPvFYaHz+dBtkHuHDoy8YQnC0zdN/WyYB -+/1JmacUUofl+HusHuLkDxmadogI= -+-----END CERTIFICATE-----` -+ -+const x509v1TestIntermediate = `-----BEGIN CERTIFICATE----- -+MIIByjCCATMCCQCCdEMsT8ykqTANBgkqhkiG9w0BAQsFADAjMQ8wDQYDVQQKEwZH -+b2xhbmcxEDAOBgNVBAMTB1Jvb3QgQ0EwHhcNMTUwMTAxMDAwMDAwWhcNMjUwMTAx -+MDAwMDAwWjAwMQ8wDQYDVQQKEwZHb2xhbmcxHTAbBgNVBAMTFFguNTA5djEgaW50 -+ZXJtZWRpYXRlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJ2QyniAOT+5YL -+jeinEBJr3NsC/Q2QJ/VKmgvp+xRxuKTHJiVmxVijmp0vWg8AWfkmuE4p3hXQbbqM -+k5yxrk1n60ONhim2L4VXriEvCE7X2OXhTmBls5Ufr7aqIgPMikwjScCXwz8E8qI8 -+UxyAhnjeJwMYBU8TuwBImSd4LBHoQQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAIab -+DRG6FbF9kL9jb/TDHkbVBk+sl/Pxi4/XjuFyIALlARgAkeZcPmL5tNW1ImHkwsHR -+zWE77kJDibzd141u21ZbLsKvEdUJXjla43bdyMmEqf5VGpC3D4sFt3QVH7lGeRur -+x5Wlq1u3YDL/j6s1nU2dQ3ySB/oP7J+vQ9V4QeM+ -+-----END CERTIFICATE-----` -+ -+const x509v1TestLeaf = `-----BEGIN CERTIFICATE----- -+MIICMzCCAZygAwIBAgIJAPo99mqJJrpJMA0GCSqGSIb3DQEBCwUAMDAxDzANBgNV -+BAoTBkdvbGFuZzEdMBsGA1UEAxMUWC41MDl2MSBpbnRlcm1lZGlhdGUwHhcNMTUw -+MTAxMDAwMDAwWhcNMjUwMTAxMDAwMDAwWjArMQ8wDQYDVQQKEwZHb2xhbmcxGDAW -+BgNVBAMTD2Zvby5leGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC -+gYEApUh60Z+a5/oKJxG//Dn8CihSo2CJHNIIO3zEJZ1EeNSMZCynaIR6D3IPZEIR -++RG2oGt+f5EEukAPYxwasp6VeZEezoQWJ+97nPCT6DpwLlWp3i2MF8piK2R9vxkG -+Z5n0+HzYk1VM8epIrZFUXSMGTX8w1y041PX/yYLxbdEifdcCAwEAAaNaMFgwDgYD -+VR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNV -+HRMBAf8EAjAAMBkGA1UdDgQSBBBFozXe0SnzAmjy+1U6M/cvMA0GCSqGSIb3DQEB -+CwUAA4GBADYzYUvaToO/ucBskPdqXV16AaakIhhSENswYVSl97/sODaxsjishKq9 -+5R7siu+JnIFotA7IbBe633p75xEnLN88X626N/XRFG9iScLzpj0o0PWXBUiB+fxL -+/jt8qszOXCv2vYdUTPNuPqufXLWMoirpuXrr1liJDmedCcAHepY/ -+-----END CERTIFICATE-----` -+ -+const ignoreCNWithSANRoot = `-----BEGIN CERTIFICATE----- -+MIIDPzCCAiegAwIBAgIIJkzCwkNrPHMwDQYJKoZIhvcNAQELBQAwMDEQMA4GA1UE -+ChMHVEVTVElORzEcMBoGA1UEAxMTKipUZXN0aW5nKiogUm9vdCBDQTAeFw0xNTAx -+MDEwMDAwMDBaFw0yNTAxMDEwMDAwMDBaMDAxEDAOBgNVBAoTB1RFU1RJTkcxHDAa -+BgNVBAMTEyoqVGVzdGluZyoqIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB -+DwAwggEKAoIBAQC4YAf5YqlXGcikvbMWtVrNICt+V/NNWljwfvSKdg4Inm7k6BwW -+P6y4Y+n4qSYIWNU4iRkdpajufzctxQCO6ty13iw3qVktzcC5XBIiS6ymiRhhDgnY -+VQqyakVGw9MxrPwdRZVlssUv3Hmy6tU+v5Ok31SLY5z3wKgYWvSyYs0b8bKNU8kf -+2FmSHnBN16lxGdjhe3ji58F/zFMr0ds+HakrLIvVdFcQFAnQopM8FTHpoWNNzGU3 -+KaiO0jBbMFkd6uVjVnuRJ+xjuiqi/NWwiwQA+CEr9HKzGkxOF8nAsHamdmO1wW+w -+OsCrC0qWQ/f5NTOVATTJe0vj88OMTvo3071VAgMBAAGjXTBbMA4GA1UdDwEB/wQE -+AwICpDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUw -+AwEB/zAZBgNVHQ4EEgQQQDfXAftAL7gcflQEJ4xZATANBgkqhkiG9w0BAQsFAAOC -+AQEAGOn3XjxHyHbXLKrRmpwV447B7iNBXR5VlhwOgt1kWaHDL2+8f/9/h0HMkB6j -+fC+/yyuYVqYuOeavqMGVrh33D2ODuTQcFlOx5lXukP46j3j+Lm0jjZ1qNX7vlP8I -+VlUXERhbelkw8O4oikakwIY9GE8syuSgYf+VeBW/lvuAZQrdnPfabxe05Tre6RXy -+nJHMB1q07YHpbwIkcV/lfCE9pig2nPXTLwYZz9cl46Ul5RCpPUi+IKURo3x8y0FU -+aSLjI/Ya0zwUARMmyZ3RRGCyhIarPb20mKSaMf1/Nb23pS3k1QgmZhk5pAnXYsWu -+BJ6bvwEAasFiLGP6Zbdmxb2hIA== -+-----END CERTIFICATE-----` -+ -+const ignoreCNWithSANLeaf = `-----BEGIN CERTIFICATE----- -+MIIDaTCCAlGgAwIBAgIJAONakvRTxgJhMA0GCSqGSIb3DQEBCwUAMDAxEDAOBgNV -+BAoTB1RFU1RJTkcxHDAaBgNVBAMTEyoqVGVzdGluZyoqIFJvb3QgQ0EwHhcNMTUw -+MTAxMDAwMDAwWhcNMjUwMTAxMDAwMDAwWjAsMRAwDgYDVQQKEwdURVNUSU5HMRgw -+FgYDVQQDEw9mb28uZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -+ggEKAoIBAQDBqskp89V/JMIBBqcauKSOVLcMyIE/t0jgSWVrsI4sksBTabLsfMdS -+ui2n+dHQ1dRBuw3o4g4fPrWwS3nMnV3pZUHEn2TPi5N1xkjTaxObXgKIY2GKmFP3 -+rJ9vYqHT6mT4K93kCHoRcmJWWySc7S3JAOhTcdB4G+tIdQJN63E+XRYQQfNrn5HZ -+hxQoOzaguHFx+ZGSD4Ntk6BSZz5NfjqCYqYxe+iCpTpEEYhIpi8joSPSmkTMTxBW -+S1W2gXbYNQ9KjNkGM6FnQsUJrSPMrWs4v3UB/U88N5LkZeF41SqD9ySFGwbGajFV -+nyzj12+4K4D8BLhlOc0Eo/F/8GwOwvmxAgMBAAGjgYkwgYYwDgYDVR0PAQH/BAQD -+AgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAA -+MBkGA1UdDgQSBBCjeab27q+5pV43jBGANOJ1MBsGA1UdIwQUMBKAEEA31wH7QC+4 -+HH5UBCeMWQEwDwYDVR0RBAgwBocEfwAAATANBgkqhkiG9w0BAQsFAAOCAQEAGZfZ -+ErTVxxpIg64s22mQpXSk/72THVQsfsKHzlXmztM0CJzH8ccoN67ZqKxJCfdiE/FI -+Emb6BVV4cGPeIKpcxaM2dwX/Y+Y0JaxpQJvqLxs+EByRL0gPP3shgg86WWCjYLxv -+AgOn862d/JXGDrC9vIlQ/DDQcyL5g0JV5UjG2G9TUigbnrXxBw7BoWK6wmoSaHnR -+sZKEHSs3RUJvm7qqpA9Yfzm9jg+i9j32zh1xFacghAOmFRFXa9eCVeigZ/KK2mEY -+j2kBQyvnyKsXHLAKUoUOpd6t/1PHrfXnGj+HmzZNloJ/BZ1kiWb4eLvMljoLGkZn -+xZbqP3Krgjj4XNaXjg== -+-----END CERTIFICATE-----` -+ -+const excludedNamesLeaf = `-----BEGIN CERTIFICATE----- -+MIID4DCCAsigAwIBAgIHDUSFtJknhzANBgkqhkiG9w0BAQsFADCBnjELMAkGA1UE -+BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU -+MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5 -+ICgzNzM0NTE1NTYyODA2Mzk3KTEhMB8GA1UEAwwYSW50ZXJtZWRpYXRlIENBIGZv -+ciAzMzkyMB4XDTE3MDIwODIxMTUwNFoXDTE4MDIwODIwMjQ1OFowgZAxCzAJBgNV -+BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlMb3MgR2F0b3Mx -+FDASBgNVBAoMC05ldGZsaXggSW5jMS0wKwYDVQQLDCRQbGF0Zm9ybSBTZWN1cml0 -+eSAoMzczNDUxNTc0ODUwMjY5NikxEzARBgNVBAMMCjE3Mi4xNi4wLjEwggEiMA0G -+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCZ0oP1bMv6bOeqcKbzinnGpNOpenhA -+zdFFsgea62znWsH3Wg4+1Md8uPCqlaQIsaJQKZHc50eKD3bg0Io7c6kxHkBQr1b8 -+Q7cGeK3CjdqG3NwS/aizzrLKOwL693hFwwy7JY7GGCvogbhyQRKn6iV0U9zMm7bu -+/9pQVV/wx8u01u2uAlLttjyQ5LJkxo5t8cATFVqxdN5J9eY//VSDiTwXnlpQITBP -+/Ow+zYuZ3kFlzH3CtCOhOEvNG3Ar1NvP3Icq35PlHV+Eki4otnKfixwByoiGpqCB -+UEIY04VrZJjwBxk08y/3jY2B3VLYGgi+rryyCxIqkB7UpSNPMMWSG4UpAgMBAAGj -+LzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0RBBYwFIIMYmVuZGVyLmxvY2FshwSsEAAB -+MA0GCSqGSIb3DQEBCwUAA4IBAQCLW3JO8L7LKByjzj2RciPjCGH5XF87Wd20gYLq -+sNKcFwCIeyZhnQy5aZ164a5G9AIk2HLvH6HevBFPhA9Ivmyv/wYEfnPd1VcFkpgP -+hDt8MCFJ8eSjCyKdtZh1MPMLrLVymmJV+Rc9JUUYM9TIeERkpl0rskcO1YGewkYt -+qKlWE+0S16+pzsWvKn831uylqwIb8ANBPsCX4aM4muFBHavSWAHgRO+P+yXVw8Q+ -+VQDnMHUe5PbZd1/+1KKVs1K/CkBCtoHNHp1d/JT+2zUQJphwja9CcgfFdVhSnHL4 -+oEEOFtqVMIuQfR2isi08qW/JGOHc4sFoLYB8hvdaxKWSE19A -+-----END CERTIFICATE-----` -+ -+const excludedNamesIntermediate = `-----BEGIN CERTIFICATE----- -+MIIDzTCCArWgAwIBAgIHDUSFqYeczDANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UE -+BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU -+MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5 -+ICgzNzM0NTE1NDc5MDY0NjAyKTEcMBoGA1UEAwwTTG9jYWwgUm9vdCBmb3IgMzM5 -+MjAeFw0xNzAyMDgyMTE1MDRaFw0xODAyMDgyMDI0NThaMIGeMQswCQYDVQQGEwJV -+UzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJTG9zIEdhdG9zMRQwEgYD -+VQQKDAtOZXRmbGl4IEluYzEtMCsGA1UECwwkUGxhdGZvcm0gU2VjdXJpdHkgKDM3 -+MzQ1MTU1NjI4MDYzOTcpMSEwHwYDVQQDDBhJbnRlcm1lZGlhdGUgQ0EgZm9yIDMz -+OTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCOyEs6tJ/t9emQTvlx -+3FS7uJSou5rKkuqVxZdIuYQ+B2ZviBYUnMRT9bXDB0nsVdKZdp0hdchdiwNXDG/I -+CiWu48jkcv/BdynVyayOT+0pOJSYLaPYpzBx1Pb9M5651ct9GSbj6Tz0ChVonoIE -+1AIZ0kkebucZRRFHd0xbAKVRKyUzPN6HJ7WfgyauUp7RmlC35wTmrmARrFohQLlL -+7oICy+hIQePMy9x1LSFTbPxZ5AUUXVC3eUACU3vLClF/Xs8XGHebZpUXCdMQjOGS -+nq1eFguFHR1poSB8uSmmLqm4vqUH9CDhEgiBAC8yekJ8//kZQ7lUEqZj3YxVbk+Y -+E4H5AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB -+ADxrnmNX5gWChgX9K5fYwhFDj5ofxZXAKVQk+WjmkwMcmCx3dtWSm++Wdksj/ZlA -+V1cLW3ohWv1/OAZuOlw7sLf98aJpX+UUmIYYQxDubq+4/q7VA7HzEf2k/i/oN1NI -+JgtrhpPcZ/LMO6k7DYx0qlfYq8pTSfd6MI4LnWKgLc+JSPJJjmvspgio2ZFcnYr7 -+A264BwLo6v1Mos1o1JUvFFcp4GANlw0XFiWh7JXYRl8WmS5DoouUC+aNJ3lmyF6z -+LbIjZCSfgZnk/LK1KU1j91FI2bc2ULYZvAC1PAg8/zvIgxn6YM2Q7ZsdEgWw0FpS -+zMBX1/lk4wkFckeUIlkD55Y= -+-----END CERTIFICATE-----` -+ -+const excludedNamesRoot = `-----BEGIN CERTIFICATE----- -+MIIEGTCCAwGgAwIBAgIHDUSFpInn/zANBgkqhkiG9w0BAQsFADCBozELMAkGA1UE -+BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU -+MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5 -+ICgzNzMxNTA5NDM3NDYyNDg1KTEmMCQGA1UEAwwdTmFtZSBDb25zdHJhaW50cyBU -+ZXN0IFJvb3QgQ0EwHhcNMTcwMjA4MjExNTA0WhcNMTgwMjA4MjAyNDU4WjCBmTEL -+MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBH -+YXRvczEUMBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNl -+Y3VyaXR5ICgzNzM0NTE1NDc5MDY0NjAyKTEcMBoGA1UEAwwTTG9jYWwgUm9vdCBm -+b3IgMzM5MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJymcnX29ekc -+7+MLyr8QuAzoHWznmGdDd2sITwWRjM89/21cdlHCGKSpULUNdFp9HDLWvYECtxt+ -+8TuzKiQz7qAerzGUT1zI5McIjHy0e/i4xIkfiBiNeTCuB/N9QRbZlcfM80ErkaA4 -+gCAFK8qZAcWkHIl6e+KaQFMPLKk9kckgAnVDHEJe8oLNCogCJ15558b65g05p9eb -+5Lg+E98hoPRTQaDwlz3CZPfTTA2EiEZInSi8qzodFCbTpJUVTbiVUH/JtVjlibbb -+smdcx5PORK+8ZJkhLEh54AjaWOX4tB/7Tkk8stg2VBmrIARt/j4UVj7cTrIWU3bV -+m8TwHJG+YgsCAwEAAaNaMFgwDwYDVR0TAQH/BAUwAwEB/zBFBgNVHR4EPjA8oBww -+CocICgEAAP//AAAwDoIMYmVuZGVyLmxvY2FsoRwwCocICgEAAP//AAAwDoIMYmVu -+ZGVyLmxvY2FsMA0GCSqGSIb3DQEBCwUAA4IBAQAMjbheffPxtSKSv9NySW+8qmHs -+n7Mb5GGyCFu+cMZSoSaabstbml+zHEFJvWz6/1E95K4F8jKhAcu/CwDf4IZrSD2+ -+Hee0DolVSQhZpnHgPyj7ZATz48e3aJaQPUlhCEOh0wwF4Y0N4FV0t7R6woLylYRZ -+yU1yRHUqUYpN0DWFpsPbBqgM6uUAVO2ayBFhPgWUaqkmSbZ/Nq7isGvknaTmcIwT -+6mOAFN0qFb4RGzfGJW7x6z7KCULS7qVDp6fU3tRoScHFEgRubks6jzQ1W5ooSm4o -++NQCZDd5eFeU8PpNX7rgaYE4GPq+EEmLVCBYmdctr8QVdqJ//8Xu3+1phjDy -+-----END CERTIFICATE-----` -+ -+const invalidCNRoot = `-----BEGIN CERTIFICATE----- -+MIIBFjCBvgIJAIsu4r+jb70UMAoGCCqGSM49BAMCMBQxEjAQBgNVBAsMCVRlc3Qg -+cm9vdDAeFw0xODA3MTExODMyMzVaFw0yODA3MDgxODMyMzVaMBQxEjAQBgNVBAsM -+CVRlc3Qgcm9vdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABF6oDgMg0LV6YhPj -+QXaPXYCc2cIyCdqp0ROUksRz0pOLTc5iY2nraUheRUD1vRRneq7GeXOVNn7uXONg -+oCGMjNwwCgYIKoZIzj0EAwIDRwAwRAIgDSiwgIn8g1lpruYH0QD1GYeoWVunfmrI -+XzZZl0eW/ugCICgOfXeZ2GGy3wIC0352BaC3a8r5AAb2XSGNe+e9wNN6 -+-----END CERTIFICATE-----` -+ -+const validCNWithoutSAN = `-----BEGIN CERTIFICATE----- -+MIIBJzCBzwIUB7q8t9mrDAL+UB1OFaMN5BEWFKQwCgYIKoZIzj0EAwIwFDESMBAG -+A1UECwwJVGVzdCByb290MB4XDTE4MDcxMTE4NDcyNFoXDTI4MDcwODE4NDcyNFow -+GjEYMBYGA1UEAwwPZm9vLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D -+AQcDQgAEp6Z8IjOnR38Iky1fYTUu2kVndvKXcxiwARJKGtW3b0E8uwVp9AZd/+sr -+p4ULTPdFToFAeqnGHbu62bkms8pQkDAKBggqhkjOPQQDAgNHADBEAiBTbNe3WWFR -+cqUYo0sNUuoV+tCTMDJUS+0PWIW4qBqCOwIgFHdLDn5PCk9kJpfc0O2qZx03hdq0 -+h7olHCpY9yMRiz0= -+-----END CERTIFICATE-----` -+ -+const rootWithoutSKID = `-----BEGIN CERTIFICATE----- -+MIIBbzCCARSgAwIBAgIQeCkq3C8SOX/JM5PqYTl9cDAKBggqhkjOPQQDAjASMRAw -+DgYDVQQKEwdBY21lIENvMB4XDTE5MDIwNDIyNTYzNFoXDTI5MDIwMTIyNTYzNFow -+EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABISm -+jGlTr4dLOWT+BCTm2PzWRjk1DpLcSAh+Al8eB1Nc2eBWxYIH9qPirfatvqBOA4c5 -+ZwycRpFoaw6O+EmXnVujTDBKMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr -+BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBIGA1UdEQQLMAmCB2V4YW1wbGUwCgYI -+KoZIzj0EAwIDSQAwRgIhAMaBYWFCjTfn0MNyQ0QXvYT/iIFompkIqzw6wB7qjLrA -+AiEA3sn65V7G4tsjZEOpN0Jykn9uiTjqniqn/S/qmv8gIec= -+-----END CERTIFICATE-----` -+ -+const leafWithAKID = `-----BEGIN CERTIFICATE----- -+MIIBjTCCATSgAwIBAgIRAPCKYvADhKLPaWOtcTu2XYwwCgYIKoZIzj0EAwIwEjEQ -+MA4GA1UEChMHQWNtZSBDbzAeFw0xOTAyMDQyMzA2NTJaFw0yOTAyMDEyMzA2NTJa -+MBMxETAPBgNVBAoTCEFjbWUgTExDMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE -+Wk5N+/8X97YT6ClFNIE5/4yc2YwKn921l0wrIJEcT2u+Uydm7EqtCJNtZjYMAnBd -+Acp/wynpTwC6tBTsxcM0s6NqMGgwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoG -+CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUwitfkXg0JglCjW9R -+ssWvTAveakIwEgYDVR0RBAswCYIHZXhhbXBsZTAKBggqhkjOPQQDAgNHADBEAiBk -+4LpWiWPOIl5PIhX9PDVkmjpre5oyoH/3aYwG8ABYuAIgCeSfbYueOOG2AdXuMqSU -+ZZMqeJS7JldLx91sPUArY5A= -+-----END CERTIFICATE-----` -+ -+const rootMatchingSKIDMismatchingSubject = `-----BEGIN CERTIFICATE----- -+MIIBQjCB6aADAgECAgEAMAoGCCqGSM49BAMCMBExDzANBgNVBAMTBlJvb3QgQTAe -+Fw0wOTExMTAyMzAwMDBaFw0xOTExMDgyMzAwMDBaMBExDzANBgNVBAMTBlJvb3Qg -+QTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPK4p1uXq2aAeDtKDHIokg2rTcPM -+2gq3N9Y96wiW6/7puBK1+INEW//cO9x6FpzkcsHw/TriAqy4sck/iDAvf9WjMjAw -+MA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zAMBgNVHQ4EBQQDAQID -+MAoGCCqGSM49BAMCA0gAMEUCIQDgtAp7iVHxMnKxZPaLQPC+Tv2r7+DJc88k2SKH -+MPs/wQIgFjjNvBoQEl7vSHTcRGCCcFMdlN4l0Dqc9YwGa9fyrQs= -+-----END CERTIFICATE-----` -+ -+const rootMismatchingSKIDMatchingSubject = `-----BEGIN CERTIFICATE----- -+MIIBNDCB26ADAgECAgEAMAoGCCqGSM49BAMCMBExDzANBgNVBAMTBlJvb3QgQjAe -+Fw0wOTExMTAyMzAwMDBaFw0xOTExMDgyMzAwMDBaMBExDzANBgNVBAMTBlJvb3Qg -+QjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABI1YRFcIlkWzm9BdEVrIsEQJ2dT6 -+qiW8/WV9GoIhmDtX9SEDHospc0Cgm+TeD2QYW2iMrS5mvNe4GSw0Jezg/bOjJDAi -+MA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNI -+ADBFAiEAukWOiuellx8bugRiwCS5XQ6IOJ1SZcjuZxj76WojwxkCIHqa71qNw8FM -+DtA5yoL9M2pDFF6ovFWnaCe+KlzSwAW/ -+-----END CERTIFICATE-----` -+ -+const leafMatchingAKIDMatchingIssuer = `-----BEGIN CERTIFICATE----- -+MIIBNTCB26ADAgECAgEAMAoGCCqGSM49BAMCMBExDzANBgNVBAMTBlJvb3QgQjAe -+Fw0wOTExMTAyMzAwMDBaFw0xOTExMDgyMzAwMDBaMA8xDTALBgNVBAMTBExlYWYw -+WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASNWERXCJZFs5vQXRFayLBECdnU+qol -+vP1lfRqCIZg7V/UhAx6LKXNAoJvk3g9kGFtojK0uZrzXuBksNCXs4P2zoyYwJDAO -+BgNVHSMEBzAFgAMBAgMwEgYDVR0RBAswCYIHZXhhbXBsZTAKBggqhkjOPQQDAgNJ -+ADBGAiEAnV9XV7a4h0nfJB8pWv+pBUXRlRFA2uZz3mXEpee8NYACIQCWa+wL70GL -+ePBQCV1F9sE2q4ZrnsT9TZoNrSe/bMDjzA== -+-----END CERTIFICATE-----` -+ -+var unknownAuthorityErrorTests = []struct { -+ name string -+ cert string -+ expected string -+}{ -+ {"self-signed, cn", selfSignedWithCommonName, "x509: certificate signed by unknown authority (possibly because of \"empty\" while trying to verify candidate authority certificate \"test\")"}, -+ {"self-signed, no cn, org", selfSignedNoCommonNameWithOrgName, "x509: certificate signed by unknown authority (possibly because of \"empty\" while trying to verify candidate authority certificate \"ca\")"}, -+ {"self-signed, no cn, no org", selfSignedNoCommonNameNoOrgName, "x509: certificate signed by unknown authority (possibly because of \"empty\" while trying to verify candidate authority certificate \"serial:0\")"}, -+} -+ -+func TestUnknownAuthorityError(t *testing.T) { -+ for i, tt := range unknownAuthorityErrorTests { -+ t.Run(tt.name, func(t *testing.T) { -+ der, _ := pem.Decode([]byte(tt.cert)) -+ if der == nil { -+ t.Fatalf("#%d: Unable to decode PEM block", i) -+ } -+ c, err := ParseCertificate(der.Bytes) -+ if err != nil { -+ t.Fatalf("#%d: Unable to parse certificate -> %v", i, err) -+ } -+ uae := &UnknownAuthorityError{ -+ Cert: c, -+ hintErr: fmt.Errorf("empty"), -+ hintCert: c, -+ } -+ actual := uae.Error() -+ if actual != tt.expected { -+ t.Errorf("#%d: UnknownAuthorityError.Error() response invalid actual: %s expected: %s", i, actual, tt.expected) -+ } -+ }) -+ } -+} -+ -+var nameConstraintTests = []struct { -+ constraint, domain string -+ expectError bool -+ shouldMatch bool -+}{ -+ {"", "anything.com", false, true}, -+ {"example.com", "example.com", false, true}, -+ {"example.com.", "example.com", true, false}, -+ {"example.com", "example.com.", true, false}, -+ {"example.com", "ExAmPle.coM", false, true}, -+ {"example.com", "exampl1.com", false, false}, -+ {"example.com", "www.ExAmPle.coM", false, true}, -+ {"example.com", "sub.www.ExAmPle.coM", false, true}, -+ {"example.com", "notexample.com", false, false}, -+ {".example.com", "example.com", false, false}, -+ {".example.com", "www.example.com", false, true}, -+ {".example.com", "www..example.com", true, false}, -+} -+ -+func TestNameConstraints(t *testing.T) { -+ for i, test := range nameConstraintTests { -+ result, err := matchDomainConstraint(test.domain, test.constraint) -+ -+ if err != nil && !test.expectError { -+ t.Errorf("unexpected error for test #%d: domain=%s, constraint=%s, err=%s", i, test.domain, test.constraint, err) -+ continue -+ } -+ -+ if err == nil && test.expectError { -+ t.Errorf("unexpected success for test #%d: domain=%s, constraint=%s", i, test.domain, test.constraint) -+ continue -+ } -+ -+ if result != test.shouldMatch { -+ t.Errorf("unexpected result for test #%d: domain=%s, constraint=%s, result=%t", i, test.domain, test.constraint, result) -+ } -+ } -+} -+ -+const selfSignedWithCommonName = `-----BEGIN CERTIFICATE----- -+MIIDCjCCAfKgAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQKEwJjYTEL -+MAkGA1UEAxMCY2EwHhcNMTYwODI4MTcwOTE4WhcNMjEwODI3MTcwOTE4WjAcMQsw -+CQYDVQQKEwJjYTENMAsGA1UEAxMEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEP -+ADCCAQoCggEBAOH55PfRsbvmcabfLLko1w/yuapY/hk13Cgmc3WE/Z1ZStxGiVxY -+gQVH9n4W/TbUsrep/TmcC4MV7xEm5252ArcgaH6BeQ4QOTFj/6Jx0RT7U/ix+79x -+8RRysf7OlzNpGIctwZEM7i/G+0ZfqX9ULxL/EW9tppSxMX1jlXZQarnU7BERL5cH -++G2jcbU9H28FXYishqpVYE9L7xrXMm61BAwvGKB0jcVW6JdhoAOSfQbbgp7JjIlq -+czXqUsv1UdORO/horIoJptynTvuARjZzyWatya6as7wyOgEBllE6BjPK9zpn+lp3 -+tQ8dwKVqm/qBPhIrVqYG/Ec7pIv8mJfYabMCAwEAAaNZMFcwDgYDVR0PAQH/BAQD -+AgOoMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAMBgNVHRMBAf8EAjAA -+MAoGA1UdDgQDBAEAMAwGA1UdIwQFMAOAAQAwDQYJKoZIhvcNAQELBQADggEBAAAM -+XMFphzq4S5FBcRdB2fRrmcoz+jEROBWvIH/1QUJeBEBz3ZqBaJYfBtQTvqCA5Rjw -+dxyIwVd1W3q3aSulM0tO62UCU6L6YeeY/eq8FmpD7nMJo7kCrXUUAMjxbYvS3zkT -+v/NErK6SgWnkQiPJBZNX1Q9+aSbLT/sbaCTdbWqcGNRuLGJkmqfIyoxRt0Hhpqsx -+jP5cBaVl50t4qoCuVIE9cOucnxYXnI7X5HpXWvu8Pfxo4SwVjb1az8Fk5s8ZnxGe -+fPB6Q3L/pKBe0SEe5GywpwtokPLB3lAygcuHbxp/1FlQ1NQZqq+vgXRIla26bNJf -+IuYkJwt6w+LH/9HZgf8= -+-----END CERTIFICATE-----` -+const selfSignedNoCommonNameWithOrgName = `-----BEGIN CERTIFICATE----- -+MIIC+zCCAeOgAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQKEwJjYTEL -+MAkGA1UEAxMCY2EwHhcNMTYwODI4MTgxMzQ4WhcNMjEwODI3MTgxMzQ4WjANMQsw -+CQYDVQQKEwJjYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL5EjrUa -+7EtOMxWiIgTzp2FlQvncPsG329O3l3uNGnbigb8TmNMw2M8UhoDjd84pnU5RAfqd -+8t5TJyw/ybnIKBN131Q2xX+gPQ0dFyMvcO+i1CUgCxmYZomKVA2MXO1RD1hLTYGS -+gOVjc3no3MBwd8uVQp0NStqJ1QvLtNG4Uy+B28qe+ZFGGbjGqx8/CU4A8Szlpf7/ -+xAZR8w5qFUUlpA2LQYeHHJ5fQVXw7kyL1diNrKNi0G3qcY0IrBh++hT+hnEEXyXu -+g8a0Ux18hoE8D6rAr34rCZl6AWfqW5wjwm+N5Ns2ugr9U4N8uCKJYMPHb2CtdubU -+46IzVucpTfGLdaMCAwEAAaNZMFcwDgYDVR0PAQH/BAQDAgOoMB0GA1UdJQQWMBQG -+CCsGAQUFBwMCBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMAoGA1UdDgQDBAEAMAwG -+A1UdIwQFMAOAAQAwDQYJKoZIhvcNAQELBQADggEBAEn5SgVpJ3zjsdzPqK7Qd/sB -+bYd1qtPHlrszjhbHBg35C6mDgKhcv4o6N+fuC+FojZb8lIxWzJtvT9pQbfy/V6u3 -+wOb816Hm71uiP89sioIOKCvSAstj/p9doKDOUaKOcZBTw0PS2m9eja8bnleZzBvK -+rD8cNkHf74v98KvBhcwBlDifVzmkWzMG6TL1EkRXUyLKiWgoTUFSkCDV927oXXMR -+DKnszq+AVw+K8hbeV2A7GqT7YfeqOAvSbatTDnDtKOPmlCnQui8A149VgZzXv7eU -+29ssJSqjUPyp58dlV6ZuynxPho1QVZUOQgnJToXIQ3/5vIvJRXy52GJCs4/Gh/w= -+-----END CERTIFICATE-----` -+const selfSignedNoCommonNameNoOrgName = `-----BEGIN CERTIFICATE----- -+MIIC7jCCAdagAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQKEwJjYTEL -+MAkGA1UEAxMCY2EwHhcNMTYwODI4MTgxOTQ1WhcNMjEwODI3MTgxOTQ1WjAAMIIB -+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp3E+Jl6DpgzogHUW/i/AAcCM -+fnNJLOamNVKFGmmxhb4XTHxRaWoTzrlsyzIMS0WzivvJeZVe6mWbvuP2kZanKgIz -+35YXRTR9HbqkNTMuvnpUESzWxbGWE2jmt2+a/Jnz89FS4WIYRhF7nI2z8PvZOfrI -+2gETTT2tEpoF2S4soaYfm0DBeT8K0/rogAaf+oeUS6V+v3miRcAooJgpNJGu9kqm -+S0xKPn1RCFVjpiRd6YNS0xZirjYQIBMFBvoSoHjaOdgJptNRBprYPOxVJ/ItzGf0 -+kPmzPFCx2tKfxV9HLYBPgxi+fP3IIx8aIYuJn8yReWtYEMYU11hDPeAFN5Gm+wID -+AQABo1kwVzAOBgNVHQ8BAf8EBAMCA6gwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsG -+AQUFBwMBMAwGA1UdEwEB/wQCMAAwCgYDVR0OBAMEAQAwDAYDVR0jBAUwA4ABADAN -+BgkqhkiG9w0BAQsFAAOCAQEATZVOFeiCpPM5QysToLv+8k7Rjoqt6L5IxMUJGEpq -+4ENmldmwkhEKr9VnYEJY3njydnnTm97d9vOfnLj9nA9wMBODeOO3KL2uJR2oDnmM -+9z1NSe2aQKnyBb++DM3ZdikpHn/xEpGV19pYKFQVn35x3lpPh2XijqRDO/erKemb -+w67CoNRb81dy+4Q1lGpA8ORoLWh5fIq2t2eNGc4qB8vlTIKiESzAwu7u3sRfuWQi -+4R+gnfLd37FWflMHwztFbVTuNtPOljCX0LN7KcuoXYlr05RhQrmoN7fQHsrZMNLs -+8FVjHdKKu+uPstwd04Uy4BR/H2y1yerN9j/L6ZkMl98iiA== -+-----END CERTIFICATE-----` -+ -+const criticalExtRoot = `-----BEGIN CERTIFICATE----- -+MIIBqzCCAVGgAwIBAgIJAJ+mI/85cXApMAoGCCqGSM49BAMCMB0xDDAKBgNVBAoT -+A09yZzENMAsGA1UEAxMEUm9vdDAeFw0xNTAxMDEwMDAwMDBaFw0yNTAxMDEwMDAw -+MDBaMB0xDDAKBgNVBAoTA09yZzENMAsGA1UEAxMEUm9vdDBZMBMGByqGSM49AgEG -+CCqGSM49AwEHA0IABJGp9joiG2QSQA+1FczEDAsWo84rFiP3GTL+n+ugcS6TyNib -+gzMsdbJgVi+a33y0SzLZxB+YvU3/4KTk8yKLC+2jejB4MA4GA1UdDwEB/wQEAwIC -+BDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB -+/zAZBgNVHQ4EEgQQQDfXAftAL7gcflQEJ4xZATAbBgNVHSMEFDASgBBAN9cB+0Av -+uBx+VAQnjFkBMAoGCCqGSM49BAMCA0gAMEUCIFeSV00fABFceWR52K+CfIgOHotY -+FizzGiLB47hGwjMuAiEA8e0um2Kr8FPQ4wmFKaTRKHMaZizCGl3m+RG5QsE1KWo= -+-----END CERTIFICATE-----` -+ -+const criticalExtIntermediate = `-----BEGIN CERTIFICATE----- -+MIIBszCCAVmgAwIBAgIJAL2kcGZKpzVqMAoGCCqGSM49BAMCMB0xDDAKBgNVBAoT -+A09yZzENMAsGA1UEAxMEUm9vdDAeFw0xNTAxMDEwMDAwMDBaFw0yNTAxMDEwMDAw -+MDBaMCUxDDAKBgNVBAoTA09yZzEVMBMGA1UEAxMMSW50ZXJtZWRpYXRlMFkwEwYH -+KoZIzj0CAQYIKoZIzj0DAQcDQgAESqVq92iPEq01cL4o99WiXDc5GZjpjNlzMS1n -+rk8oHcVDp4tQRRQG3F4A6dF1rn/L923ha3b0fhDLlAvXZB+7EKN6MHgwDgYDVR0P -+AQH/BAQDAgIEMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNVHRMB -+Af8EBTADAQH/MBkGA1UdDgQSBBCMGmiotXbbXVd7H40UsgajMBsGA1UdIwQUMBKA -+EEA31wH7QC+4HH5UBCeMWQEwCgYIKoZIzj0EAwIDSAAwRQIhAOhhNRb6KV7h3wbE -+cdap8bojzvUcPD78fbsQPCNw1jPxAiBOeAJhlTwpKn9KHpeJphYSzydj9NqcS26Y -+xXbdbm27KQ== -+-----END CERTIFICATE-----` -+ -+const criticalExtLeafWithExt = `-----BEGIN CERTIFICATE----- -+MIIBxTCCAWugAwIBAgIJAJZAUtw5ccb1MAoGCCqGSM49BAMCMCUxDDAKBgNVBAoT -+A09yZzEVMBMGA1UEAxMMSW50ZXJtZWRpYXRlMB4XDTE1MDEwMTAwMDAwMFoXDTI1 -+MDEwMTAwMDAwMFowJDEMMAoGA1UEChMDT3JnMRQwEgYDVQQDEwtleGFtcGxlLmNv -+bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABF3ABa2+B6gUyg6ayCaRQWYY/+No -+6PceLqEavZNUeVNuz7bS74Toy8I7R3bGMkMgbKpLSPlPTroAATvebTXoBaijgYQw -+gYEwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD -+AjAMBgNVHRMBAf8EAjAAMBkGA1UdDgQSBBBRNtBL2vq8nCV3qVp7ycxMMBsGA1Ud -+IwQUMBKAEIwaaKi1dttdV3sfjRSyBqMwCgYDUQMEAQH/BAAwCgYIKoZIzj0EAwID -+SAAwRQIgVjy8GBgZFiagexEuDLqtGjIRJQtBcf7lYgf6XFPH1h4CIQCT6nHhGo6E -+I+crEm4P5q72AnA/Iy0m24l7OvLuXObAmg== -+-----END CERTIFICATE-----` -+ -+const criticalExtIntermediateWithExt = `-----BEGIN CERTIFICATE----- -+MIIB2TCCAX6gAwIBAgIIQD3NrSZtcUUwCgYIKoZIzj0EAwIwHTEMMAoGA1UEChMD -+T3JnMQ0wCwYDVQQDEwRSb290MB4XDTE1MDEwMTAwMDAwMFoXDTI1MDEwMTAwMDAw -+MFowPTEMMAoGA1UEChMDT3JnMS0wKwYDVQQDEyRJbnRlcm1lZGlhdGUgd2l0aCBD -+cml0aWNhbCBFeHRlbnNpb24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQtnmzH -+mcRm10bdDBnJE7xQEJ25cLCL5okuEphRR0Zneo6+nQZikoh+UBbtt5GV3Dms7LeP -+oF5HOplYDCd8wi/wo4GHMIGEMA4GA1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggr -+BgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQKxdv -+UuQZ6sO3XvBsxgNZ3zAbBgNVHSMEFDASgBBAN9cB+0AvuBx+VAQnjFkBMAoGA1ED -+BAEB/wQAMAoGCCqGSM49BAMCA0kAMEYCIQCQzTPd6XKex+OAPsKT/1DsoMsg8vcG -+c2qZ4Q0apT/kvgIhAKu2TnNQMIUdcO0BYQIl+Uhxc78dc9h4lO+YJB47pHGx -+-----END CERTIFICATE-----` -+ -+const criticalExtLeaf = `-----BEGIN CERTIFICATE----- -+MIIBzzCCAXWgAwIBAgIJANoWFIlhCI9MMAoGCCqGSM49BAMCMD0xDDAKBgNVBAoT -+A09yZzEtMCsGA1UEAxMkSW50ZXJtZWRpYXRlIHdpdGggQ3JpdGljYWwgRXh0ZW5z -+aW9uMB4XDTE1MDEwMTAwMDAwMFoXDTI1MDEwMTAwMDAwMFowJDEMMAoGA1UEChMD -+T3JnMRQwEgYDVQQDEwtleGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEH -+A0IABG1Lfh8A0Ho2UvZN5H0+ONil9c8jwtC0y0xIZftyQE+Fwr9XwqG3rV2g4M1h -+GnJa9lV9MPHg8+b85Hixm0ZSw7SjdzB1MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE -+FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAZBgNVHQ4EEgQQ -+UNhY4JhezH9gQYqvDMWrWDAbBgNVHSMEFDASgBArF29S5Bnqw7de8GzGA1nfMAoG -+CCqGSM49BAMCA0gAMEUCIQClA3d4tdrDu9Eb5ZBpgyC+fU1xTZB0dKQHz6M5fPZA -+2AIgN96lM+CPGicwhN24uQI6flOsO3H0TJ5lNzBYLtnQtlc= -+-----END CERTIFICATE-----` -+ -+func TestValidHostname(t *testing.T) { -+ tests := []struct { -+ host string -+ validInput, validPattern bool -+ }{ -+ {host: "example.com", validInput: true, validPattern: true}, -+ {host: "eXample123-.com", validInput: true, validPattern: true}, -+ {host: "-eXample123-.com"}, -+ {host: ""}, -+ {host: "."}, -+ {host: "example..com"}, -+ {host: ".example.com"}, -+ {host: "example.com.", validInput: true}, -+ {host: "*.example.com."}, -+ {host: "*.example.com", validPattern: true}, -+ {host: "*foo.example.com"}, -+ {host: "foo.*.example.com"}, -+ {host: "exa_mple.com", validInput: true, validPattern: true}, -+ {host: "foo,bar"}, -+ {host: "project-dev:us-central1:main"}, -+ } -+ for _, tt := range tests { -+ if got := validHostnamePattern(tt.host); got != tt.validPattern { -+ t.Errorf("validHostnamePattern(%q) = %v, want %v", tt.host, got, tt.validPattern) -+ } -+ if got := validHostnameInput(tt.host); got != tt.validInput { -+ t.Errorf("validHostnameInput(%q) = %v, want %v", tt.host, got, tt.validInput) -+ } -+ } -+} -+ -+func generateCert(cn string, isCA bool, issuer *Certificate, issuerKey crypto.PrivateKey) (*Certificate, crypto.PrivateKey, error) { -+ priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) -+ serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit) -+ -+ template := &Certificate{ -+ SerialNumber: serialNumber, -+ Subject: pkix.Name{CommonName: cn}, -+ NotBefore: time.Now().Add(-1 * time.Hour), -+ NotAfter: time.Now().Add(24 * time.Hour), -+ -+ KeyUsage: KeyUsageKeyEncipherment | KeyUsageDigitalSignature | KeyUsageCertSign, -+ ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ BasicConstraintsValid: true, -+ IsCA: isCA, -+ } -+ if issuer == nil { -+ issuer = template -+ issuerKey = priv -+ } -+ -+ derBytes, err := CreateCertificate(rand.Reader, template, issuer, priv.Public(), issuerKey) -+ if err != nil { -+ return nil, nil, err -+ } -+ cert, err := ParseCertificate(derBytes) -+ if err != nil { -+ return nil, nil, err -+ } -+ -+ return cert, priv, nil -+} -+ -+func TestPathologicalChain(t *testing.T) { -+ if testing.Short() { -+ t.Skip("skipping generation of a long chain of certificates in short mode") -+ } -+ -+ // Build a chain where all intermediates share the same subject, to hit the -+ // path building worst behavior. -+ roots, intermediates := NewCertPool(), NewCertPool() -+ -+ parent, parentKey, err := generateCert("Root CA", true, nil, nil) -+ if err != nil { -+ t.Fatal(err) -+ } -+ roots.AddCert(parent) -+ -+ for i := 1; i < 100; i++ { -+ parent, parentKey, err = generateCert("Intermediate CA", true, parent, parentKey) -+ if err != nil { -+ t.Fatal(err) -+ } -+ intermediates.AddCert(parent) -+ } -+ -+ leaf, _, err := generateCert("Leaf", false, parent, parentKey) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ start := time.Now() -+ _, err = leaf.Verify(VerifyOptions{ -+ Roots: roots, -+ Intermediates: intermediates, -+ }) -+ t.Logf("verification took %v", time.Since(start)) -+ -+ if err == nil || !strings.Contains(err.Error(), "signature check attempts limit") { -+ t.Errorf("expected verification to fail with a signature checks limit error; got %v", err) -+ } -+} -+ -+func TestLongChain(t *testing.T) { -+ if testing.Short() { -+ t.Skip("skipping generation of a long chain of certificates in short mode") -+ } -+ -+ roots, intermediates := NewCertPool(), NewCertPool() -+ -+ parent, parentKey, err := generateCert("Root CA", true, nil, nil) -+ if err != nil { -+ t.Fatal(err) -+ } -+ roots.AddCert(parent) -+ -+ for i := 1; i < 15; i++ { -+ name := fmt.Sprintf("Intermediate CA #%d", i) -+ parent, parentKey, err = generateCert(name, true, parent, parentKey) -+ if err != nil { -+ t.Fatal(err) -+ } -+ intermediates.AddCert(parent) -+ } -+ -+ leaf, _, err := generateCert("Leaf", false, parent, parentKey) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ start := time.Now() -+ if _, err := leaf.Verify(VerifyOptions{ -+ Roots: roots, -+ Intermediates: intermediates, -+ }); err != nil { -+ t.Error(err) -+ } -+ t.Logf("verification took %v", time.Since(start)) -+} -+ -+func TestSystemRootsError(t *testing.T) { -+ if runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios" { -+ t.Skip("Windows and darwin do not use (or support) systemRoots") -+ } -+ -+ defer func(oldSystemRoots *CertPool) { systemRoots = oldSystemRoots }(systemRootsPool()) -+ -+ opts := VerifyOptions{ -+ Intermediates: NewCertPool(), -+ DNSName: "www.google.com", -+ CurrentTime: time.Unix(1677615892, 0), -+ } -+ -+ if ok := opts.Intermediates.AppendCertsFromPEM([]byte(gtsIntermediate)); !ok { -+ t.Fatalf("failed to parse intermediate") -+ } -+ -+ leaf, err := certificateFromPEM(googleLeaf) -+ if err != nil { -+ t.Fatalf("failed to parse leaf: %v", err) -+ } -+ -+ systemRoots = nil -+ -+ _, err = leaf.Verify(opts) -+ if _, ok := err.(SystemRootsError); !ok { -+ t.Errorf("error was not SystemRootsError: %v", err) -+ } -+} -+ -+func TestSystemRootsErrorUnwrap(t *testing.T) { -+ var err1 = errors.New("err1") -+ err := SystemRootsError{Err: err1} -+ if !errors.Is(err, err1) { -+ t.Error("errors.Is failed, wanted success") -+ } -+} -+ -+func TestIssue51759(t *testing.T) { -+ if runtime.GOOS != "darwin" { -+ t.Skip("only affects darwin") -+ } -+ builder := testenv.Builder() -+ if builder == "" { -+ t.Skip("only run this test on the builders, as we have no reasonable way to gate tests on macOS versions elsewhere") -+ } -+ if builder == "darwin-amd64-10_14" || builder == "darwin-amd64-10_15" { -+ t.Skip("behavior only enforced in macOS 11 and after") -+ } -+ // badCertData contains a cert that we parse as valid -+ // but that macOS SecCertificateCreateWithData rejects. -+ const badCertData = "0\x82\x01U0\x82\x01\a\xa0\x03\x02\x01\x02\x02\x01\x020\x05\x06\x03+ep0R1P0N\x06\x03U\x04\x03\x13Gderpkey8dc58100b2493614ee1692831a461f3f4dd3f9b3b088e244f887f81b4906ac260\x1e\x17\r220112235755Z\x17\r220313235755Z0R1P0N\x06\x03U\x04\x03\x13Gderpkey8dc58100b2493614ee1692831a461f3f4dd3f9b3b088e244f887f81b4906ac260*0\x05\x06\x03+ep\x03!\x00bA\xd8e\xadW\xcb\xefZ\x89\xb5\"\x1eR\x9d\xba\x0e:\x1042Q@\u007f\xbd\xfb{ks\x04\xd1£\x020\x000\x05\x06\x03+ep\x03A\x00[\xa7\x06y\x86(\x94\x97\x9eLwA\x00\x01x\xaa\xbc\xbd Ê]\n(΅!ف0\xf5\x9a%I\x19<\xffo\xf1\xeaaf@\xb1\xa7\xaf\xfd\xe9R\xc7\x0f\x8d&\xd5\xfc\x0f;Ϙ\x82\x84a\xbc\r" -+ badCert, err := ParseCertificate([]byte(badCertData)) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ t.Run("leaf", func(t *testing.T) { -+ opts := VerifyOptions{} -+ expectedErr := "invalid leaf certificate" -+ _, err = badCert.Verify(opts) -+ if err == nil || err.Error() != expectedErr { -+ t.Fatalf("unexpected error: want %q, got %q", expectedErr, err) -+ } -+ }) -+ -+ goodCert, err := certificateFromPEM(googleLeaf) -+ if err != nil { -+ t.Fatal(err) -+ } -+ -+ t.Run("intermediate", func(t *testing.T) { -+ opts := VerifyOptions{ -+ Intermediates: NewCertPool(), -+ } -+ opts.Intermediates.AddCert(badCert) -+ expectedErr := "SecCertificateCreateWithData: invalid certificate" -+ _, err = goodCert.Verify(opts) -+ if err == nil || err.Error() != expectedErr { -+ t.Fatalf("unexpected error: want %q, got %q", expectedErr, err) -+ } -+ }) -+} -+ -+type trustGraphEdge struct { -+ Issuer string -+ Subject string -+ Type int -+ MutateTemplate func(*Certificate) -+} -+ -+type rootDescription struct { -+ Subject string -+ MutateTemplate func(*Certificate) -+} -+ -+type trustGraphDescription struct { -+ Roots []rootDescription -+ Leaf string -+ Graph []trustGraphEdge -+} -+ -+func genCertEdge(t *testing.T, subject string, key crypto.Signer, mutateTmpl func(*Certificate), certType int, issuer *Certificate, signer crypto.Signer) *Certificate { -+ t.Helper() -+ -+ serial, err := rand.Int(rand.Reader, big.NewInt(100)) -+ if err != nil { -+ t.Fatalf("failed to generate test serial: %s", err) -+ } -+ tmpl := &Certificate{ -+ SerialNumber: serial, -+ Subject: pkix.Name{CommonName: subject}, -+ NotBefore: time.Now().Add(-time.Hour), -+ NotAfter: time.Now().Add(time.Hour), -+ } -+ if certType == rootCertificate || certType == intermediateCertificate { -+ tmpl.IsCA, tmpl.BasicConstraintsValid = true, true -+ tmpl.KeyUsage = KeyUsageCertSign -+ } else if certType == leafCertificate { -+ tmpl.DNSNames = []string{"localhost"} -+ } -+ if mutateTmpl != nil { -+ mutateTmpl(tmpl) -+ } -+ -+ if certType == rootCertificate { -+ issuer = tmpl -+ signer = key -+ } -+ -+ d, err := CreateCertificate(rand.Reader, tmpl, issuer, key.Public(), signer) -+ if err != nil { -+ t.Fatalf("failed to generate test cert: %s", err) -+ } -+ c, err := ParseCertificate(d) -+ if err != nil { -+ t.Fatalf("failed to parse test cert: %s", err) -+ } -+ return c -+} -+ -+func buildTrustGraph(t *testing.T, d trustGraphDescription) (*CertPool, *CertPool, *Certificate) { -+ t.Helper() -+ -+ certs := map[string]*Certificate{} -+ keys := map[string]crypto.Signer{} -+ roots := []*Certificate{} -+ for _, r := range d.Roots { -+ k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ t.Fatalf("failed to generate test key: %s", err) -+ } -+ root := genCertEdge(t, r.Subject, k, r.MutateTemplate, rootCertificate, nil, nil) -+ roots = append(roots, root) -+ certs[r.Subject] = root -+ keys[r.Subject] = k -+ } -+ -+ intermediates := []*Certificate{} -+ var leaf *Certificate -+ for _, e := range d.Graph { -+ issuerCert, ok := certs[e.Issuer] -+ if !ok { -+ t.Fatalf("unknown issuer %s", e.Issuer) -+ } -+ issuerKey, ok := keys[e.Issuer] -+ if !ok { -+ t.Fatalf("unknown issuer %s", e.Issuer) -+ } -+ -+ k, ok := keys[e.Subject] -+ if !ok { -+ var err error -+ k, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ t.Fatalf("failed to generate test key: %s", err) -+ } -+ keys[e.Subject] = k -+ } -+ cert := genCertEdge(t, e.Subject, k, e.MutateTemplate, e.Type, issuerCert, issuerKey) -+ certs[e.Subject] = cert -+ if e.Subject == d.Leaf { -+ leaf = cert -+ } else { -+ intermediates = append(intermediates, cert) -+ } -+ } -+ -+ rootPool, intermediatePool := NewCertPool(), NewCertPool() -+ for i := len(roots) - 1; i >= 0; i-- { -+ rootPool.AddCert(roots[i]) -+ } -+ for i := len(intermediates) - 1; i >= 0; i-- { -+ intermediatePool.AddCert(intermediates[i]) -+ } -+ -+ return rootPool, intermediatePool, leaf -+} -+ -+func chainsToStrings(chains [][]*Certificate) []string { -+ chainStrings := []string{} -+ for _, chain := range chains { -+ names := []string{} -+ for _, c := range chain { -+ names = append(names, c.Subject.String()) -+ } -+ chainStrings = append(chainStrings, strings.Join(names, " -> ")) -+ } -+ sort.Strings(chainStrings) -+ return chainStrings -+} -+ -+func TestPathBuilding(t *testing.T) { -+ tests := []struct { -+ name string -+ graph trustGraphDescription -+ expectedChains []string -+ expectedErr string -+ }{ -+ { -+ // Build the following graph from RFC 4158, figure 7 (note that in this graph edges represent -+ // certificates where the parent is the issuer and the child is the subject.) For the certificate -+ // C->B, use an unsupported ExtKeyUsage (in this case ExtKeyUsageCodeSigning) which invalidates -+ // the path Trust Anchor -> C -> B -> EE. The remaining valid paths should be: -+ // * Trust Anchor -> A -> B -> EE -+ // * Trust Anchor -> C -> A -> B -> EE -+ // -+ // +---------+ -+ // | Trust | -+ // | Anchor | -+ // +---------+ -+ // | | -+ // v v -+ // +---+ +---+ -+ // | A |<-->| C | -+ // +---+ +---+ -+ // | | -+ // | +---+ | -+ // +->| B |<-+ -+ // +---+ -+ // | -+ // v -+ // +----+ -+ // | EE | -+ // +----+ -+ name: "bad EKU", -+ graph: trustGraphDescription{ -+ Roots: []rootDescription{{Subject: "root"}}, -+ Leaf: "leaf", -+ Graph: []trustGraphEdge{ -+ { -+ Issuer: "root", -+ Subject: "inter a", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "root", -+ Subject: "inter c", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter c", -+ Subject: "inter a", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter a", -+ Subject: "inter c", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter c", -+ Subject: "inter b", -+ Type: intermediateCertificate, -+ MutateTemplate: func(t *Certificate) { -+ t.ExtKeyUsage = []ExtKeyUsage{ExtKeyUsageCodeSigning} -+ }, -+ }, -+ { -+ Issuer: "inter a", -+ Subject: "inter b", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter b", -+ Subject: "leaf", -+ Type: leafCertificate, -+ }, -+ }, -+ }, -+ expectedChains: []string{ -+ "CN=leaf -> CN=inter b -> CN=inter a -> CN=inter c -> CN=root", -+ "CN=leaf -> CN=inter b -> CN=inter a -> CN=root", -+ }, -+ }, -+ { -+ // Build the following graph from RFC 4158, figure 7 (note that in this graph edges represent -+ // certificates where the parent is the issuer and the child is the subject.) For the certificate -+ // C->B, use a unconstrained SAN which invalidates the path Trust Anchor -> C -> B -> EE. The -+ // remaining valid paths should be: -+ // * Trust Anchor -> A -> B -> EE -+ // * Trust Anchor -> C -> A -> B -> EE -+ // -+ // +---------+ -+ // | Trust | -+ // | Anchor | -+ // +---------+ -+ // | | -+ // v v -+ // +---+ +---+ -+ // | A |<-->| C | -+ // +---+ +---+ -+ // | | -+ // | +---+ | -+ // +->| B |<-+ -+ // +---+ -+ // | -+ // v -+ // +----+ -+ // | EE | -+ // +----+ -+ name: "bad EKU", -+ graph: trustGraphDescription{ -+ Roots: []rootDescription{{Subject: "root"}}, -+ Leaf: "leaf", -+ Graph: []trustGraphEdge{ -+ { -+ Issuer: "root", -+ Subject: "inter a", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "root", -+ Subject: "inter c", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter c", -+ Subject: "inter a", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter a", -+ Subject: "inter c", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter c", -+ Subject: "inter b", -+ Type: intermediateCertificate, -+ MutateTemplate: func(t *Certificate) { -+ t.PermittedDNSDomains = []string{"good"} -+ t.DNSNames = []string{"bad"} -+ }, -+ }, -+ { -+ Issuer: "inter a", -+ Subject: "inter b", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter b", -+ Subject: "leaf", -+ Type: leafCertificate, -+ }, -+ }, -+ }, -+ expectedChains: []string{ -+ "CN=leaf -> CN=inter b -> CN=inter a -> CN=inter c -> CN=root", -+ "CN=leaf -> CN=inter b -> CN=inter a -> CN=root", -+ }, -+ }, -+ { -+ // Build the following graph, we should find both paths: -+ // * Trust Anchor -> A -> C -> EE -+ // * Trust Anchor -> A -> B -> C -> EE -+ // -+ // +---------+ -+ // | Trust | -+ // | Anchor | -+ // +---------+ -+ // | -+ // v -+ // +---+ -+ // | A | -+ // +---+ -+ // | | -+ // | +----+ -+ // | v -+ // | +---+ -+ // | | B | -+ // | +---+ -+ // | | -+ // | +---v -+ // v v -+ // +---+ -+ // | C | -+ // +---+ -+ // | -+ // v -+ // +----+ -+ // | EE | -+ // +----+ -+ name: "all paths", -+ graph: trustGraphDescription{ -+ Roots: []rootDescription{{Subject: "root"}}, -+ Leaf: "leaf", -+ Graph: []trustGraphEdge{ -+ { -+ Issuer: "root", -+ Subject: "inter a", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter a", -+ Subject: "inter b", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter a", -+ Subject: "inter c", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter b", -+ Subject: "inter c", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter c", -+ Subject: "leaf", -+ Type: leafCertificate, -+ }, -+ }, -+ }, -+ expectedChains: []string{ -+ "CN=leaf -> CN=inter c -> CN=inter a -> CN=root", -+ "CN=leaf -> CN=inter c -> CN=inter b -> CN=inter a -> CN=root", -+ }, -+ }, -+ { -+ // Build the following graph, which contains a cross-signature loop -+ // (A and C cross sign each other). Paths that include the A -> C -> A -+ // (and vice versa) loop should be ignored, resulting in the paths: -+ // * Trust Anchor -> A -> B -> EE -+ // * Trust Anchor -> C -> B -> EE -+ // * Trust Anchor -> A -> C -> B -> EE -+ // * Trust Anchor -> C -> A -> B -> EE -+ // -+ // +---------+ -+ // | Trust | -+ // | Anchor | -+ // +---------+ -+ // | | -+ // v v -+ // +---+ +---+ -+ // | A |<-->| C | -+ // +---+ +---+ -+ // | | -+ // | +---+ | -+ // +->| B |<-+ -+ // +---+ -+ // | -+ // v -+ // +----+ -+ // | EE | -+ // +----+ -+ name: "ignore cross-sig loops", -+ graph: trustGraphDescription{ -+ Roots: []rootDescription{{Subject: "root"}}, -+ Leaf: "leaf", -+ Graph: []trustGraphEdge{ -+ { -+ Issuer: "root", -+ Subject: "inter a", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "root", -+ Subject: "inter c", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter c", -+ Subject: "inter a", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter a", -+ Subject: "inter c", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter c", -+ Subject: "inter b", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter a", -+ Subject: "inter b", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter b", -+ Subject: "leaf", -+ Type: leafCertificate, -+ }, -+ }, -+ }, -+ expectedChains: []string{ -+ "CN=leaf -> CN=inter b -> CN=inter a -> CN=inter c -> CN=root", -+ "CN=leaf -> CN=inter b -> CN=inter a -> CN=root", -+ "CN=leaf -> CN=inter b -> CN=inter c -> CN=inter a -> CN=root", -+ "CN=leaf -> CN=inter b -> CN=inter c -> CN=root", -+ }, -+ }, -+ { -+ // Build a simple two node graph, where the leaf is directly issued from -+ // the root and both certificates have matching subject and public key, but -+ // the leaf has SANs. -+ name: "leaf with same subject, key, as parent but with SAN", -+ graph: trustGraphDescription{ -+ Roots: []rootDescription{{Subject: "root"}}, -+ Leaf: "root", -+ Graph: []trustGraphEdge{ -+ { -+ Issuer: "root", -+ Subject: "root", -+ Type: leafCertificate, -+ MutateTemplate: func(c *Certificate) { -+ c.DNSNames = []string{"localhost"} -+ }, -+ }, -+ }, -+ }, -+ expectedChains: []string{ -+ "CN=root -> CN=root", -+ }, -+ }, -+ { -+ // Build a basic graph with two paths from leaf to root, but the path passing -+ // through C should be ignored, because it has invalid EKU nesting. -+ name: "ignore invalid EKU path", -+ graph: trustGraphDescription{ -+ Roots: []rootDescription{{Subject: "root"}}, -+ Leaf: "leaf", -+ Graph: []trustGraphEdge{ -+ { -+ Issuer: "root", -+ Subject: "inter a", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "root", -+ Subject: "inter c", -+ Type: intermediateCertificate, -+ }, -+ { -+ Issuer: "inter c", -+ Subject: "inter b", -+ Type: intermediateCertificate, -+ MutateTemplate: func(t *Certificate) { -+ t.ExtKeyUsage = []ExtKeyUsage{ExtKeyUsageCodeSigning} -+ }, -+ }, -+ { -+ Issuer: "inter a", -+ Subject: "inter b", -+ Type: intermediateCertificate, -+ MutateTemplate: func(t *Certificate) { -+ t.ExtKeyUsage = []ExtKeyUsage{ExtKeyUsageServerAuth} -+ }, -+ }, -+ { -+ Issuer: "inter b", -+ Subject: "leaf", -+ Type: leafCertificate, -+ MutateTemplate: func(t *Certificate) { -+ t.ExtKeyUsage = []ExtKeyUsage{ExtKeyUsageServerAuth} -+ }, -+ }, -+ }, -+ }, -+ expectedChains: []string{ -+ "CN=leaf -> CN=inter b -> CN=inter a -> CN=root", -+ }, -+ }, -+ { -+ // A name constraint on the root should apply to any names that appear -+ // on the intermediate, meaning there is no valid chain. -+ name: "constrained root, invalid intermediate", -+ graph: trustGraphDescription{ -+ Roots: []rootDescription{ -+ { -+ Subject: "root", -+ MutateTemplate: func(t *Certificate) { -+ t.PermittedDNSDomains = []string{"example.com"} -+ }, -+ }, -+ }, -+ Leaf: "leaf", -+ Graph: []trustGraphEdge{ -+ { -+ Issuer: "root", -+ Subject: "inter", -+ Type: intermediateCertificate, -+ MutateTemplate: func(t *Certificate) { -+ t.DNSNames = []string{"beep.com"} -+ }, -+ }, -+ { -+ Issuer: "inter", -+ Subject: "leaf", -+ Type: leafCertificate, -+ MutateTemplate: func(t *Certificate) { -+ t.DNSNames = []string{"www.example.com"} -+ }, -+ }, -+ }, -+ }, -+ expectedErr: "x509: a root or intermediate certificate is not authorized to sign for this name: DNS name \"beep.com\" is not permitted by any constraint", -+ }, -+ { -+ // A name constraint on the intermediate does not apply to the intermediate -+ // itself, so this is a valid chain. -+ name: "constrained intermediate, non-matching SAN", -+ graph: trustGraphDescription{ -+ Roots: []rootDescription{{Subject: "root"}}, -+ Leaf: "leaf", -+ Graph: []trustGraphEdge{ -+ { -+ Issuer: "root", -+ Subject: "inter", -+ Type: intermediateCertificate, -+ MutateTemplate: func(t *Certificate) { -+ t.DNSNames = []string{"beep.com"} -+ t.PermittedDNSDomains = []string{"example.com"} -+ }, -+ }, -+ { -+ Issuer: "inter", -+ Subject: "leaf", -+ Type: leafCertificate, -+ MutateTemplate: func(t *Certificate) { -+ t.DNSNames = []string{"www.example.com"} -+ }, -+ }, -+ }, -+ }, -+ expectedChains: []string{"CN=leaf -> CN=inter -> CN=root"}, -+ }, -+ } -+ -+ for _, tc := range tests { -+ t.Run(tc.name, func(t *testing.T) { -+ roots, intermediates, leaf := buildTrustGraph(t, tc.graph) -+ chains, err := leaf.Verify(VerifyOptions{ -+ Roots: roots, -+ Intermediates: intermediates, -+ }) -+ if err != nil && err.Error() != tc.expectedErr { -+ t.Fatalf("unexpected error: got %q, want %q", err, tc.expectedErr) -+ } -+ if len(tc.expectedChains) == 0 { -+ return -+ } -+ gotChains := chainsToStrings(chains) -+ if !reflect.DeepEqual(gotChains, tc.expectedChains) { -+ t.Errorf("unexpected chains returned:\ngot:\n\t%s\nwant:\n\t%s", strings.Join(gotChains, "\n\t"), strings.Join(tc.expectedChains, "\n\t")) -+ } -+ }) -+ } -+} -+ -+func TestEKUEnforcement(t *testing.T) { -+ type ekuDescs struct { -+ EKUs []ExtKeyUsage -+ Unknown []asn1.ObjectIdentifier -+ } -+ tests := []struct { -+ name string -+ root ekuDescs -+ inters []ekuDescs -+ leaf ekuDescs -+ verifyEKUs []ExtKeyUsage -+ err string -+ }{ -+ { -+ name: "valid, full chain", -+ root: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, -+ inters: []ekuDescs{ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}}, -+ leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, -+ verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ }, -+ { -+ name: "valid, only leaf has EKU", -+ root: ekuDescs{}, -+ inters: []ekuDescs{ekuDescs{}}, -+ leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, -+ verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ }, -+ { -+ name: "invalid, serverAuth not nested", -+ root: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageClientAuth}}, -+ inters: []ekuDescs{ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}}}, -+ leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}}, -+ verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ err: "x509: certificate specifies an incompatible key usage", -+ }, -+ { -+ name: "valid, two EKUs, one path", -+ root: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, -+ inters: []ekuDescs{ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}}}, -+ leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}}, -+ verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}, -+ }, -+ { -+ name: "invalid, ladder", -+ root: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, -+ inters: []ekuDescs{ -+ ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}}, -+ ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageClientAuth}}, -+ ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}}, -+ ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, -+ }, -+ leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, -+ verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}, -+ err: "x509: certificate specifies an incompatible key usage", -+ }, -+ { -+ name: "valid, intermediate has no EKU", -+ root: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, -+ inters: []ekuDescs{ekuDescs{}}, -+ leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, -+ verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ }, -+ { -+ name: "invalid, intermediate has no EKU and no nested path", -+ root: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageClientAuth}}, -+ inters: []ekuDescs{ekuDescs{}}, -+ leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, -+ verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}, -+ err: "x509: certificate specifies an incompatible key usage", -+ }, -+ { -+ name: "invalid, intermediate has unknown EKU", -+ root: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, -+ inters: []ekuDescs{ekuDescs{Unknown: []asn1.ObjectIdentifier{{1, 2, 3}}}}, -+ leaf: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}, -+ verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ err: "x509: certificate specifies an incompatible key usage", -+ }, -+ } -+ -+ k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ t.Fatalf("failed to generate test key: %s", err) -+ } -+ -+ for _, tc := range tests { -+ t.Run(tc.name, func(t *testing.T) { -+ rootPool := NewCertPool() -+ root := genCertEdge(t, "root", k, func(c *Certificate) { -+ c.ExtKeyUsage = tc.root.EKUs -+ c.UnknownExtKeyUsage = tc.root.Unknown -+ }, rootCertificate, nil, k) -+ rootPool.AddCert(root) -+ -+ parent := root -+ interPool := NewCertPool() -+ for i, interEKUs := range tc.inters { -+ inter := genCertEdge(t, fmt.Sprintf("inter %d", i), k, func(c *Certificate) { -+ c.ExtKeyUsage = interEKUs.EKUs -+ c.UnknownExtKeyUsage = interEKUs.Unknown -+ }, intermediateCertificate, parent, k) -+ interPool.AddCert(inter) -+ parent = inter -+ } -+ -+ leaf := genCertEdge(t, "leaf", k, func(c *Certificate) { -+ c.ExtKeyUsage = tc.leaf.EKUs -+ c.UnknownExtKeyUsage = tc.leaf.Unknown -+ }, intermediateCertificate, parent, k) -+ -+ _, err := leaf.Verify(VerifyOptions{Roots: rootPool, Intermediates: interPool, KeyUsages: tc.verifyEKUs}) -+ if err == nil && tc.err != "" { -+ t.Errorf("expected error") -+ } else if err != nil && err.Error() != tc.err { -+ t.Errorf("unexpected error: want %q, got %q", err.Error(), tc.err) -+ } -+ }) -+ } -+} -+ -+func TestVerifyEKURootAsLeaf(t *testing.T) { -+ k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) -+ if err != nil { -+ t.Fatalf("failed to generate key: %s", err) -+ } -+ -+ for _, tc := range []struct { -+ rootEKUs []ExtKeyUsage -+ verifyEKUs []ExtKeyUsage -+ succeed bool -+ }{ -+ { -+ verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ succeed: true, -+ }, -+ { -+ rootEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ succeed: true, -+ }, -+ { -+ rootEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ succeed: true, -+ }, -+ { -+ rootEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ verifyEKUs: []ExtKeyUsage{ExtKeyUsageAny}, -+ succeed: true, -+ }, -+ { -+ rootEKUs: []ExtKeyUsage{ExtKeyUsageAny}, -+ verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ succeed: true, -+ }, -+ { -+ rootEKUs: []ExtKeyUsage{ExtKeyUsageClientAuth}, -+ verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}, -+ succeed: false, -+ }, -+ } { -+ t.Run(fmt.Sprintf("root EKUs %#v, verify EKUs %#v", tc.rootEKUs, tc.verifyEKUs), func(t *testing.T) { -+ tmpl := &Certificate{ -+ SerialNumber: big.NewInt(1), -+ Subject: pkix.Name{CommonName: "root"}, -+ NotBefore: time.Now().Add(-time.Hour), -+ NotAfter: time.Now().Add(time.Hour), -+ DNSNames: []string{"localhost"}, -+ ExtKeyUsage: tc.rootEKUs, -+ } -+ rootDER, err := CreateCertificate(rand.Reader, tmpl, tmpl, k.Public(), k) -+ if err != nil { -+ t.Fatalf("failed to create certificate: %s", err) -+ } -+ root, err := ParseCertificate(rootDER) -+ if err != nil { -+ t.Fatalf("failed to parse certificate: %s", err) -+ } -+ roots := NewCertPool() -+ roots.AddCert(root) -+ -+ _, err = root.Verify(VerifyOptions{Roots: roots, KeyUsages: tc.verifyEKUs}) -+ if err == nil && !tc.succeed { -+ t.Error("verification succeed") -+ } else if err != nil && tc.succeed { -+ t.Errorf("verification failed: %q", err) -+ } -+ }) -+ } -+ -+} -diff --git a/src/crypto/x509/x509.go-e b/src/crypto/x509/x509.go-e -new file mode 100644 -index 0000000000..9d80b1d8ba ---- /dev/null -+++ b/src/crypto/x509/x509.go-e -@@ -0,0 +1,2471 @@ -+// Copyright 2009 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. -+ -+// Package x509 implements a subset of the X.509 standard. -+// -+// It allows parsing and generating certificates, certificate signing -+// requests, certificate revocation lists, and encoded public and private keys. -+// It provides a certificate verifier, complete with a chain builder. -+// -+// The package targets the X.509 technical profile defined by the IETF (RFC -+// 2459/3280/5280), and as further restricted by the CA/Browser Forum Baseline -+// Requirements. There is minimal support for features outside of these -+// profiles, as the primary goal of the package is to provide compatibility -+// with the publicly trusted TLS certificate ecosystem and its policies and -+// constraints. -+// -+// On macOS and Windows, certificate verification is handled by system APIs, but -+// the package aims to apply consistent validation rules across operating -+// systems. -+package x509 -+ -+import ( -+ "bytes" -+ "crypto" -+ "crypto/ecdh" -+ "crypto/ecdsa" -+ "crypto/ed25519" -+ "crypto/elliptic" -+ "crypto/rsa" -+ "crypto/sha1" -+ "crypto/x509/pkix" -+ "encoding/asn1" -+ "encoding/pem" -+ "errors" -+ "fmt" -+ "internal/godebug" -+ "io" -+ "math/big" -+ "net" -+ "net/url" -+ "strconv" -+ "time" -+ "unicode" -+ -+ // Explicitly import these for their crypto.RegisterHash init side-effects. -+ // Keep these as blank imports, even if they're imported above. -+ _ "crypto/sha1" -+ _ "crypto/sha256" -+ _ "crypto/sha512" -+ -+ "golang.org/x/crypto/cryptobyte" -+ cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1" -+) -+ -+// pkixPublicKey reflects a PKIX public key structure. See SubjectPublicKeyInfo -+// in RFC 3280. -+type pkixPublicKey struct { -+ Algo pkix.AlgorithmIdentifier -+ BitString asn1.BitString -+} -+ -+// ParsePKIXPublicKey parses a public key in PKIX, ASN.1 DER form. The encoded -+// public key is a SubjectPublicKeyInfo structure (see RFC 5280, Section 4.1). -+// -+// It returns a *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, -+// ed25519.PublicKey (not a pointer), or *ecdh.PublicKey (for X25519). -+// More types might be supported in the future. -+// -+// This kind of key is commonly encoded in PEM blocks of type "PUBLIC KEY". -+func ParsePKIXPublicKey(derBytes []byte) (pub any, err error) { -+ var pki publicKeyInfo -+ if rest, err := asn1.Unmarshal(derBytes, &pki); err != nil { -+ if _, err := asn1.Unmarshal(derBytes, &pkcs1PublicKey{}); err == nil { -+ return nil, errors.New("x509: failed to parse public key (use ParsePKCS1PublicKey instead for this key format)") -+ } -+ return nil, err -+ } else if len(rest) != 0 { -+ return nil, errors.New("x509: trailing data after ASN.1 of public-key") -+ } -+ return parsePublicKey(&pki) -+} -+ -+func marshalPublicKey(pub any) (publicKeyBytes []byte, publicKeyAlgorithm pkix.AlgorithmIdentifier, err error) { -+ switch pub := pub.(type) { -+ case *rsa.PublicKey: -+ publicKeyBytes, err = asn1.Marshal(pkcs1PublicKey{ -+ N: pub.N, -+ E: pub.E, -+ }) -+ if err != nil { -+ return nil, pkix.AlgorithmIdentifier{}, err -+ } -+ publicKeyAlgorithm.Algorithm = oidPublicKeyRSA -+ // This is a NULL parameters value which is required by -+ // RFC 3279, Section 2.3.1. -+ publicKeyAlgorithm.Parameters = asn1.NullRawValue -+ case *ecdsa.PublicKey: -+ oid, ok := oidFromNamedCurve(pub.Curve) -+ if !ok { -+ return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: unsupported elliptic curve") -+ } -+ if !pub.Curve.IsOnCurve(pub.X, pub.Y) { -+ return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: invalid elliptic curve public key") -+ } -+ publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) -+ publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA -+ var paramBytes []byte -+ paramBytes, err = asn1.Marshal(oid) -+ if err != nil { -+ return -+ } -+ publicKeyAlgorithm.Parameters.FullBytes = paramBytes -+ case ed25519.PublicKey: -+ publicKeyBytes = pub -+ publicKeyAlgorithm.Algorithm = oidPublicKeyEd25519 -+ case *ecdh.PublicKey: -+ publicKeyBytes = pub.Bytes() -+ if pub.Curve() == ecdh.X25519() { -+ publicKeyAlgorithm.Algorithm = oidPublicKeyX25519 -+ } else { -+ oid, ok := oidFromECDHCurve(pub.Curve()) -+ if !ok { -+ return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: unsupported elliptic curve") -+ } -+ publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA -+ var paramBytes []byte -+ paramBytes, err = asn1.Marshal(oid) -+ if err != nil { -+ return -+ } -+ publicKeyAlgorithm.Parameters.FullBytes = paramBytes -+ } -+ default: -+ return nil, pkix.AlgorithmIdentifier{}, fmt.Errorf("x509: unsupported public key type: %T", pub) -+ } -+ -+ return publicKeyBytes, publicKeyAlgorithm, nil -+} -+ -+// MarshalPKIXPublicKey converts a public key to PKIX, ASN.1 DER form. -+// The encoded public key is a SubjectPublicKeyInfo structure -+// (see RFC 5280, Section 4.1). -+// -+// The following key types are currently supported: *rsa.PublicKey, -+// *ecdsa.PublicKey, ed25519.PublicKey (not a pointer), and *ecdh.PublicKey. -+// Unsupported key types result in an error. -+// -+// This kind of key is commonly encoded in PEM blocks of type "PUBLIC KEY". -+func MarshalPKIXPublicKey(pub any) ([]byte, error) { -+ var publicKeyBytes []byte -+ var publicKeyAlgorithm pkix.AlgorithmIdentifier -+ var err error -+ -+ if publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(pub); err != nil { -+ return nil, err -+ } -+ -+ pkix := pkixPublicKey{ -+ Algo: publicKeyAlgorithm, -+ BitString: asn1.BitString{ -+ Bytes: publicKeyBytes, -+ BitLength: 8 * len(publicKeyBytes), -+ }, -+ } -+ -+ ret, _ := asn1.Marshal(pkix) -+ return ret, nil -+} -+ -+// These structures reflect the ASN.1 structure of X.509 certificates.: -+ -+type certificate struct { -+ TBSCertificate tbsCertificate -+ SignatureAlgorithm pkix.AlgorithmIdentifier -+ SignatureValue asn1.BitString -+} -+ -+type tbsCertificate struct { -+ Raw asn1.RawContent -+ Version int `asn1:"optional,explicit,default:0,tag:0"` -+ SerialNumber *big.Int -+ SignatureAlgorithm pkix.AlgorithmIdentifier -+ Issuer asn1.RawValue -+ Validity validity -+ Subject asn1.RawValue -+ PublicKey publicKeyInfo -+ UniqueId asn1.BitString `asn1:"optional,tag:1"` -+ SubjectUniqueId asn1.BitString `asn1:"optional,tag:2"` -+ Extensions []pkix.Extension `asn1:"omitempty,optional,explicit,tag:3"` -+} -+ -+type dsaAlgorithmParameters struct { -+ P, Q, G *big.Int -+} -+ -+type validity struct { -+ NotBefore, NotAfter time.Time -+} -+ -+type publicKeyInfo struct { -+ Raw asn1.RawContent -+ Algorithm pkix.AlgorithmIdentifier -+ PublicKey asn1.BitString -+} -+ -+// RFC 5280, 4.2.1.1 -+type authKeyId struct { -+ Id []byte `asn1:"optional,tag:0"` -+} -+ -+type SignatureAlgorithm int -+ -+const ( -+ UnknownSignatureAlgorithm SignatureAlgorithm = iota -+ -+ MD2WithRSA // Unsupported. -+ MD5WithRSA // Only supported for signing, not verification. -+ SHA1WithRSA // Only supported for signing, and verification of CRLs, CSRs, and OCSP responses. -+ SHA256WithRSA -+ SHA384WithRSA -+ SHA512WithRSA -+ DSAWithSHA1 // Unsupported. -+ DSAWithSHA256 // Unsupported. -+ ECDSAWithSHA1 // Only supported for signing, and verification of CRLs, CSRs, and OCSP responses. -+ ECDSAWithSHA256 -+ ECDSAWithSHA384 -+ ECDSAWithSHA512 -+ SHA256WithRSAPSS -+ SHA384WithRSAPSS -+ SHA512WithRSAPSS -+ PureEd25519 -+) -+ -+func (algo SignatureAlgorithm) isRSAPSS() bool { -+ switch algo { -+ case SHA256WithRSAPSS, SHA384WithRSAPSS, SHA512WithRSAPSS: -+ return true -+ default: -+ return false -+ } -+} -+ -+func (algo SignatureAlgorithm) String() string { -+ for _, details := range signatureAlgorithmDetails { -+ if details.algo == algo { -+ return details.name -+ } -+ } -+ return strconv.Itoa(int(algo)) -+} -+ -+type PublicKeyAlgorithm int -+ -+const ( -+ UnknownPublicKeyAlgorithm PublicKeyAlgorithm = iota -+ RSA -+ DSA // Only supported for parsing. -+ ECDSA -+ Ed25519 -+) -+ -+var publicKeyAlgoName = [...]string{ -+ RSA: "RSA", -+ DSA: "DSA", -+ ECDSA: "ECDSA", -+ Ed25519: "Ed25519", -+} -+ -+func (algo PublicKeyAlgorithm) String() string { -+ if 0 < algo && int(algo) < len(publicKeyAlgoName) { -+ return publicKeyAlgoName[algo] -+ } -+ return strconv.Itoa(int(algo)) -+} -+ -+// OIDs for signature algorithms -+// -+// pkcs-1 OBJECT IDENTIFIER ::= { -+// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } -+// -+// RFC 3279 2.2.1 RSA Signature Algorithms -+// -+// md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 } -+// -+// md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 } -+// -+// sha-1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 } -+// -+// dsaWithSha1 OBJECT IDENTIFIER ::= { -+// iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3 } -+// -+// RFC 3279 2.2.3 ECDSA Signature Algorithm -+// -+// ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { -+// iso(1) member-body(2) us(840) ansi-x962(10045) -+// signatures(4) ecdsa-with-SHA1(1)} -+// -+// RFC 4055 5 PKCS #1 Version 1.5 -+// -+// sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 } -+// -+// sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 } -+// -+// sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 } -+// -+// RFC 5758 3.1 DSA Signature Algorithms -+// -+// dsaWithSha256 OBJECT IDENTIFIER ::= { -+// joint-iso-ccitt(2) country(16) us(840) organization(1) gov(101) -+// csor(3) algorithms(4) id-dsa-with-sha2(3) 2} -+// -+// RFC 5758 3.2 ECDSA Signature Algorithm -+// -+// ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) -+// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 } -+// -+// ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) -+// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 } -+// -+// ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) -+// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 } -+// -+// RFC 8410 3 Curve25519 and Curve448 Algorithm Identifiers -+// -+// id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 } -+var ( -+ oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2} -+ oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4} -+ oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5} -+ oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11} -+ oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12} -+ oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13} -+ oidSignatureRSAPSS = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 10} -+ oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3} -+ oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2} -+ oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1} -+ oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2} -+ oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3} -+ oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4} -+ oidSignatureEd25519 = asn1.ObjectIdentifier{1, 3, 101, 112} -+ -+ oidSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1} -+ oidSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2} -+ oidSHA512 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3} -+ -+ oidMGF1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 8} -+ -+ // oidISOSignatureSHA1WithRSA means the same as oidSignatureSHA1WithRSA -+ // but it's specified by ISO. Microsoft's makecert.exe has been known -+ // to produce certificates with this OID. -+ oidISOSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 29} -+) -+ -+var signatureAlgorithmDetails = []struct { -+ algo SignatureAlgorithm -+ name string -+ oid asn1.ObjectIdentifier -+ pubKeyAlgo PublicKeyAlgorithm -+ hash crypto.Hash -+}{ -+ {MD2WithRSA, "MD2-RSA", oidSignatureMD2WithRSA, RSA, crypto.Hash(0) /* no value for MD2 */}, -+ {MD5WithRSA, "MD5-RSA", oidSignatureMD5WithRSA, RSA, crypto.MD5}, -+ {SHA1WithRSA, "SHA1-RSA", oidSignatureSHA1WithRSA, RSA, crypto.SHA1}, -+ {SHA1WithRSA, "SHA1-RSA", oidISOSignatureSHA1WithRSA, RSA, crypto.SHA1}, -+ {SHA256WithRSA, "SHA256-RSA", oidSignatureSHA256WithRSA, RSA, crypto.SHA256}, -+ {SHA384WithRSA, "SHA384-RSA", oidSignatureSHA384WithRSA, RSA, crypto.SHA384}, -+ {SHA512WithRSA, "SHA512-RSA", oidSignatureSHA512WithRSA, RSA, crypto.SHA512}, -+ {SHA256WithRSAPSS, "SHA256-RSAPSS", oidSignatureRSAPSS, RSA, crypto.SHA256}, -+ {SHA384WithRSAPSS, "SHA384-RSAPSS", oidSignatureRSAPSS, RSA, crypto.SHA384}, -+ {SHA512WithRSAPSS, "SHA512-RSAPSS", oidSignatureRSAPSS, RSA, crypto.SHA512}, -+ {DSAWithSHA1, "DSA-SHA1", oidSignatureDSAWithSHA1, DSA, crypto.SHA1}, -+ {DSAWithSHA256, "DSA-SHA256", oidSignatureDSAWithSHA256, DSA, crypto.SHA256}, -+ {ECDSAWithSHA1, "ECDSA-SHA1", oidSignatureECDSAWithSHA1, ECDSA, crypto.SHA1}, -+ {ECDSAWithSHA256, "ECDSA-SHA256", oidSignatureECDSAWithSHA256, ECDSA, crypto.SHA256}, -+ {ECDSAWithSHA384, "ECDSA-SHA384", oidSignatureECDSAWithSHA384, ECDSA, crypto.SHA384}, -+ {ECDSAWithSHA512, "ECDSA-SHA512", oidSignatureECDSAWithSHA512, ECDSA, crypto.SHA512}, -+ {PureEd25519, "Ed25519", oidSignatureEd25519, Ed25519, crypto.Hash(0) /* no pre-hashing */}, -+} -+ -+// hashToPSSParameters contains the DER encoded RSA PSS parameters for the -+// SHA256, SHA384, and SHA512 hashes as defined in RFC 3447, Appendix A.2.3. -+// The parameters contain the following values: -+// - hashAlgorithm contains the associated hash identifier with NULL parameters -+// - maskGenAlgorithm always contains the default mgf1SHA1 identifier -+// - saltLength contains the length of the associated hash -+// - trailerField always contains the default trailerFieldBC value -+var hashToPSSParameters = map[crypto.Hash]asn1.RawValue{ -+ crypto.SHA256: asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 1, 5, 0, 162, 3, 2, 1, 32}}, -+ crypto.SHA384: asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 2, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 2, 5, 0, 162, 3, 2, 1, 48}}, -+ crypto.SHA512: asn1.RawValue{FullBytes: []byte{48, 52, 160, 15, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 3, 5, 0, 161, 28, 48, 26, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 8, 48, 13, 6, 9, 96, 134, 72, 1, 101, 3, 4, 2, 3, 5, 0, 162, 3, 2, 1, 64}}, -+} -+ -+// pssParameters reflects the parameters in an AlgorithmIdentifier that -+// specifies RSA PSS. See RFC 3447, Appendix A.2.3. -+type pssParameters struct { -+ // The following three fields are not marked as -+ // optional because the default values specify SHA-1, -+ // which is no longer suitable for use in signatures. -+ Hash pkix.AlgorithmIdentifier `asn1:"explicit,tag:0"` -+ MGF pkix.AlgorithmIdentifier `asn1:"explicit,tag:1"` -+ SaltLength int `asn1:"explicit,tag:2"` -+ TrailerField int `asn1:"optional,explicit,tag:3,default:1"` -+} -+ -+func getSignatureAlgorithmFromAI(ai pkix.AlgorithmIdentifier) SignatureAlgorithm { -+ if ai.Algorithm.Equal(oidSignatureEd25519) { -+ // RFC 8410, Section 3 -+ // > For all of the OIDs, the parameters MUST be absent. -+ if len(ai.Parameters.FullBytes) != 0 { -+ return UnknownSignatureAlgorithm -+ } -+ } -+ -+ if !ai.Algorithm.Equal(oidSignatureRSAPSS) { -+ for _, details := range signatureAlgorithmDetails { -+ if ai.Algorithm.Equal(details.oid) { -+ return details.algo -+ } -+ } -+ return UnknownSignatureAlgorithm -+ } -+ -+ // RSA PSS is special because it encodes important parameters -+ // in the Parameters. -+ -+ var params pssParameters -+ if _, err := asn1.Unmarshal(ai.Parameters.FullBytes, ¶ms); err != nil { -+ return UnknownSignatureAlgorithm -+ } -+ -+ var mgf1HashFunc pkix.AlgorithmIdentifier -+ if _, err := asn1.Unmarshal(params.MGF.Parameters.FullBytes, &mgf1HashFunc); err != nil { -+ return UnknownSignatureAlgorithm -+ } -+ -+ // PSS is greatly overburdened with options. This code forces them into -+ // three buckets by requiring that the MGF1 hash function always match the -+ // message hash function (as recommended in RFC 3447, Section 8.1), that the -+ // salt length matches the hash length, and that the trailer field has the -+ // default value. -+ if (len(params.Hash.Parameters.FullBytes) != 0 && !bytes.Equal(params.Hash.Parameters.FullBytes, asn1.NullBytes)) || -+ !params.MGF.Algorithm.Equal(oidMGF1) || -+ !mgf1HashFunc.Algorithm.Equal(params.Hash.Algorithm) || -+ (len(mgf1HashFunc.Parameters.FullBytes) != 0 && !bytes.Equal(mgf1HashFunc.Parameters.FullBytes, asn1.NullBytes)) || -+ params.TrailerField != 1 { -+ return UnknownSignatureAlgorithm -+ } -+ -+ switch { -+ case params.Hash.Algorithm.Equal(oidSHA256) && params.SaltLength == 32: -+ return SHA256WithRSAPSS -+ case params.Hash.Algorithm.Equal(oidSHA384) && params.SaltLength == 48: -+ return SHA384WithRSAPSS -+ case params.Hash.Algorithm.Equal(oidSHA512) && params.SaltLength == 64: -+ return SHA512WithRSAPSS -+ } -+ -+ return UnknownSignatureAlgorithm -+} -+ -+var ( -+ // RFC 3279, 2.3 Public Key Algorithms -+ // -+ // pkcs-1 OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840) -+ // rsadsi(113549) pkcs(1) 1 } -+ // -+ // rsaEncryption OBJECT IDENTIFIER ::== { pkcs1-1 1 } -+ // -+ // id-dsa OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840) -+ // x9-57(10040) x9cm(4) 1 } -+ oidPublicKeyRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} -+ oidPublicKeyDSA = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1} -+ // RFC 5480, 2.1.1 Unrestricted Algorithm Identifier and Parameters -+ // -+ // id-ecPublicKey OBJECT IDENTIFIER ::= { -+ // iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } -+ oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} -+ // RFC 8410, Section 3 -+ // -+ // id-X25519 OBJECT IDENTIFIER ::= { 1 3 101 110 } -+ // id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 } -+ oidPublicKeyX25519 = asn1.ObjectIdentifier{1, 3, 101, 110} -+ oidPublicKeyEd25519 = asn1.ObjectIdentifier{1, 3, 101, 112} -+) -+ -+// getPublicKeyAlgorithmFromOID returns the exposed PublicKeyAlgorithm -+// identifier for public key types supported in certificates and CSRs. Marshal -+// and Parse functions may support a different set of public key types. -+func getPublicKeyAlgorithmFromOID(oid asn1.ObjectIdentifier) PublicKeyAlgorithm { -+ switch { -+ case oid.Equal(oidPublicKeyRSA): -+ return RSA -+ case oid.Equal(oidPublicKeyDSA): -+ return DSA -+ case oid.Equal(oidPublicKeyECDSA): -+ return ECDSA -+ case oid.Equal(oidPublicKeyEd25519): -+ return Ed25519 -+ } -+ return UnknownPublicKeyAlgorithm -+} -+ -+// RFC 5480, 2.1.1.1. Named Curve -+// -+// secp224r1 OBJECT IDENTIFIER ::= { -+// iso(1) identified-organization(3) certicom(132) curve(0) 33 } -+// -+// secp256r1 OBJECT IDENTIFIER ::= { -+// iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) -+// prime(1) 7 } -+// -+// secp384r1 OBJECT IDENTIFIER ::= { -+// iso(1) identified-organization(3) certicom(132) curve(0) 34 } -+// -+// secp521r1 OBJECT IDENTIFIER ::= { -+// iso(1) identified-organization(3) certicom(132) curve(0) 35 } -+// -+// NB: secp256r1 is equivalent to prime256v1 -+var ( -+ oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33} -+ oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} -+ oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34} -+ oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35} -+) -+ -+func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve { -+ switch { -+ case oid.Equal(oidNamedCurveP224): -+ return elliptic.P224() -+ case oid.Equal(oidNamedCurveP256): -+ return elliptic.P256() -+ case oid.Equal(oidNamedCurveP384): -+ return elliptic.P384() -+ case oid.Equal(oidNamedCurveP521): -+ return elliptic.P521() -+ } -+ return nil -+} -+ -+func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) { -+ switch curve { -+ case elliptic.P224(): -+ return oidNamedCurveP224, true -+ case elliptic.P256(): -+ return oidNamedCurveP256, true -+ case elliptic.P384(): -+ return oidNamedCurveP384, true -+ case elliptic.P521(): -+ return oidNamedCurveP521, true -+ } -+ -+ return nil, false -+} -+ -+func oidFromECDHCurve(curve ecdh.Curve) (asn1.ObjectIdentifier, bool) { -+ switch curve { -+ case ecdh.X25519(): -+ return oidPublicKeyX25519, true -+ case ecdh.P256(): -+ return oidNamedCurveP256, true -+ case ecdh.P384(): -+ return oidNamedCurveP384, true -+ case ecdh.P521(): -+ return oidNamedCurveP521, true -+ } -+ -+ return nil, false -+} -+ -+// KeyUsage represents the set of actions that are valid for a given key. It's -+// a bitmap of the KeyUsage* constants. -+type KeyUsage int -+ -+const ( -+ KeyUsageDigitalSignature KeyUsage = 1 << iota -+ KeyUsageContentCommitment -+ KeyUsageKeyEncipherment -+ KeyUsageDataEncipherment -+ KeyUsageKeyAgreement -+ KeyUsageCertSign -+ KeyUsageCRLSign -+ KeyUsageEncipherOnly -+ KeyUsageDecipherOnly -+) -+ -+// RFC 5280, 4.2.1.12 Extended Key Usage -+// -+// anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } -+// -+// id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } -+// -+// id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } -+// id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } -+// id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } -+// id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } -+// id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } -+// id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } -+var ( -+ oidExtKeyUsageAny = asn1.ObjectIdentifier{2, 5, 29, 37, 0} -+ oidExtKeyUsageServerAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1} -+ oidExtKeyUsageClientAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2} -+ oidExtKeyUsageCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3} -+ oidExtKeyUsageEmailProtection = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4} -+ oidExtKeyUsageIPSECEndSystem = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 5} -+ oidExtKeyUsageIPSECTunnel = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 6} -+ oidExtKeyUsageIPSECUser = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 7} -+ oidExtKeyUsageTimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8} -+ oidExtKeyUsageOCSPSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9} -+ oidExtKeyUsageMicrosoftServerGatedCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3} -+ oidExtKeyUsageNetscapeServerGatedCrypto = asn1.ObjectIdentifier{2, 16, 840, 1, 113730, 4, 1} -+ oidExtKeyUsageMicrosoftCommercialCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 2, 1, 22} -+ oidExtKeyUsageMicrosoftKernelCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 61, 1, 1} -+) -+ -+// ExtKeyUsage represents an extended set of actions that are valid for a given key. -+// Each of the ExtKeyUsage* constants define a unique action. -+type ExtKeyUsage int -+ -+const ( -+ ExtKeyUsageAny ExtKeyUsage = iota -+ ExtKeyUsageServerAuth -+ ExtKeyUsageClientAuth -+ ExtKeyUsageCodeSigning -+ ExtKeyUsageEmailProtection -+ ExtKeyUsageIPSECEndSystem -+ ExtKeyUsageIPSECTunnel -+ ExtKeyUsageIPSECUser -+ ExtKeyUsageTimeStamping -+ ExtKeyUsageOCSPSigning -+ ExtKeyUsageMicrosoftServerGatedCrypto -+ ExtKeyUsageNetscapeServerGatedCrypto -+ ExtKeyUsageMicrosoftCommercialCodeSigning -+ ExtKeyUsageMicrosoftKernelCodeSigning -+) -+ -+// extKeyUsageOIDs contains the mapping between an ExtKeyUsage and its OID. -+var extKeyUsageOIDs = []struct { -+ extKeyUsage ExtKeyUsage -+ oid asn1.ObjectIdentifier -+}{ -+ {ExtKeyUsageAny, oidExtKeyUsageAny}, -+ {ExtKeyUsageServerAuth, oidExtKeyUsageServerAuth}, -+ {ExtKeyUsageClientAuth, oidExtKeyUsageClientAuth}, -+ {ExtKeyUsageCodeSigning, oidExtKeyUsageCodeSigning}, -+ {ExtKeyUsageEmailProtection, oidExtKeyUsageEmailProtection}, -+ {ExtKeyUsageIPSECEndSystem, oidExtKeyUsageIPSECEndSystem}, -+ {ExtKeyUsageIPSECTunnel, oidExtKeyUsageIPSECTunnel}, -+ {ExtKeyUsageIPSECUser, oidExtKeyUsageIPSECUser}, -+ {ExtKeyUsageTimeStamping, oidExtKeyUsageTimeStamping}, -+ {ExtKeyUsageOCSPSigning, oidExtKeyUsageOCSPSigning}, -+ {ExtKeyUsageMicrosoftServerGatedCrypto, oidExtKeyUsageMicrosoftServerGatedCrypto}, -+ {ExtKeyUsageNetscapeServerGatedCrypto, oidExtKeyUsageNetscapeServerGatedCrypto}, -+ {ExtKeyUsageMicrosoftCommercialCodeSigning, oidExtKeyUsageMicrosoftCommercialCodeSigning}, -+ {ExtKeyUsageMicrosoftKernelCodeSigning, oidExtKeyUsageMicrosoftKernelCodeSigning}, -+} -+ -+func extKeyUsageFromOID(oid asn1.ObjectIdentifier) (eku ExtKeyUsage, ok bool) { -+ for _, pair := range extKeyUsageOIDs { -+ if oid.Equal(pair.oid) { -+ return pair.extKeyUsage, true -+ } -+ } -+ return -+} -+ -+func oidFromExtKeyUsage(eku ExtKeyUsage) (oid asn1.ObjectIdentifier, ok bool) { -+ for _, pair := range extKeyUsageOIDs { -+ if eku == pair.extKeyUsage { -+ return pair.oid, true -+ } -+ } -+ return -+} -+ -+// A Certificate represents an X.509 certificate. -+type Certificate struct { -+ Raw []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature). -+ RawTBSCertificate []byte // Certificate part of raw ASN.1 DER content. -+ RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo. -+ RawSubject []byte // DER encoded Subject -+ RawIssuer []byte // DER encoded Issuer -+ -+ Signature []byte -+ SignatureAlgorithm SignatureAlgorithm -+ -+ PublicKeyAlgorithm PublicKeyAlgorithm -+ PublicKey any -+ -+ Version int -+ SerialNumber *big.Int -+ Issuer pkix.Name -+ Subject pkix.Name -+ NotBefore, NotAfter time.Time // Validity bounds. -+ KeyUsage KeyUsage -+ -+ // Extensions contains raw X.509 extensions. When parsing certificates, -+ // this can be used to extract non-critical extensions that are not -+ // parsed by this package. When marshaling certificates, the Extensions -+ // field is ignored, see ExtraExtensions. -+ Extensions []pkix.Extension -+ -+ // ExtraExtensions contains extensions to be copied, raw, into any -+ // marshaled certificates. Values override any extensions that would -+ // otherwise be produced based on the other fields. The ExtraExtensions -+ // field is not populated when parsing certificates, see Extensions. -+ ExtraExtensions []pkix.Extension -+ -+ // UnhandledCriticalExtensions contains a list of extension IDs that -+ // were not (fully) processed when parsing. Verify will fail if this -+ // slice is non-empty, unless verification is delegated to an OS -+ // library which understands all the critical extensions. -+ // -+ // Users can access these extensions using Extensions and can remove -+ // elements from this slice if they believe that they have been -+ // handled. -+ UnhandledCriticalExtensions []asn1.ObjectIdentifier -+ -+ ExtKeyUsage []ExtKeyUsage // Sequence of extended key usages. -+ UnknownExtKeyUsage []asn1.ObjectIdentifier // Encountered extended key usages unknown to this package. -+ -+ // BasicConstraintsValid indicates whether IsCA, MaxPathLen, -+ // and MaxPathLenZero are valid. -+ BasicConstraintsValid bool -+ IsCA bool -+ -+ // MaxPathLen and MaxPathLenZero indicate the presence and -+ // value of the BasicConstraints' "pathLenConstraint". -+ // -+ // When parsing a certificate, a positive non-zero MaxPathLen -+ // means that the field was specified, -1 means it was unset, -+ // and MaxPathLenZero being true mean that the field was -+ // explicitly set to zero. The case of MaxPathLen==0 with MaxPathLenZero==false -+ // should be treated equivalent to -1 (unset). -+ // -+ // When generating a certificate, an unset pathLenConstraint -+ // can be requested with either MaxPathLen == -1 or using the -+ // zero value for both MaxPathLen and MaxPathLenZero. -+ MaxPathLen int -+ // MaxPathLenZero indicates that BasicConstraintsValid==true -+ // and MaxPathLen==0 should be interpreted as an actual -+ // maximum path length of zero. Otherwise, that combination is -+ // interpreted as MaxPathLen not being set. -+ MaxPathLenZero bool -+ -+ SubjectKeyId []byte -+ AuthorityKeyId []byte -+ -+ // RFC 5280, 4.2.2.1 (Authority Information Access) -+ OCSPServer []string -+ IssuingCertificateURL []string -+ -+ // Subject Alternate Name values. (Note that these values may not be valid -+ // if invalid values were contained within a parsed certificate. For -+ // example, an element of DNSNames may not be a valid DNS domain name.) -+ DNSNames []string -+ EmailAddresses []string -+ IPAddresses []net.IP -+ URIs []*url.URL -+ -+ // Name constraints -+ PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical. -+ PermittedDNSDomains []string -+ ExcludedDNSDomains []string -+ PermittedIPRanges []*net.IPNet -+ ExcludedIPRanges []*net.IPNet -+ PermittedEmailAddresses []string -+ ExcludedEmailAddresses []string -+ PermittedURIDomains []string -+ ExcludedURIDomains []string -+ -+ // CRL Distribution Points -+ CRLDistributionPoints []string -+ -+ PolicyIdentifiers []asn1.ObjectIdentifier -+} -+ -+// ErrUnsupportedAlgorithm results from attempting to perform an operation that -+// involves algorithms that are not currently implemented. -+var ErrUnsupportedAlgorithm = errors.New("x509: cannot verify signature: algorithm unimplemented") -+ -+// An InsecureAlgorithmError indicates that the SignatureAlgorithm used to -+// generate the signature is not secure, and the signature has been rejected. -+// -+// To temporarily restore support for SHA-1 signatures, include the value -+// "x509sha1=1" in the GODEBUG environment variable. Note that this option will -+// be removed in a future release. -+type InsecureAlgorithmError SignatureAlgorithm -+ -+func (e InsecureAlgorithmError) Error() string { -+ var override string -+ if SignatureAlgorithm(e) == SHA1WithRSA || SignatureAlgorithm(e) == ECDSAWithSHA1 { -+ override = " (temporarily override with GODEBUG=x509sha1=1)" -+ } -+ return fmt.Sprintf("x509: cannot verify signature: insecure algorithm %v", SignatureAlgorithm(e)) + override -+} -+ -+// ConstraintViolationError results when a requested usage is not permitted by -+// a certificate. For example: checking a signature when the public key isn't a -+// certificate signing key. -+type ConstraintViolationError struct{} -+ -+func (ConstraintViolationError) Error() string { -+ return "x509: invalid signature: parent certificate cannot sign this kind of certificate" -+} -+ -+func (c *Certificate) Equal(other *Certificate) bool { -+ if c == nil || other == nil { -+ return c == other -+ } -+ return bytes.Equal(c.Raw, other.Raw) -+} -+ -+func (c *Certificate) hasSANExtension() bool { -+ return oidInExtensions(oidExtensionSubjectAltName, c.Extensions) -+} -+ -+// CheckSignatureFrom verifies that the signature on c is a valid signature from parent. -+// -+// This is a low-level API that performs very limited checks, and not a full -+// path verifier. Most users should use [Certificate.Verify] instead. -+func (c *Certificate) CheckSignatureFrom(parent *Certificate) error { -+ // RFC 5280, 4.2.1.9: -+ // "If the basic constraints extension is not present in a version 3 -+ // certificate, or the extension is present but the cA boolean is not -+ // asserted, then the certified public key MUST NOT be used to verify -+ // certificate signatures." -+ if parent.Version == 3 && !parent.BasicConstraintsValid || -+ parent.BasicConstraintsValid && !parent.IsCA { -+ return ConstraintViolationError{} -+ } -+ -+ if parent.KeyUsage != 0 && parent.KeyUsage&KeyUsageCertSign == 0 { -+ return ConstraintViolationError{} -+ } -+ -+ if parent.PublicKeyAlgorithm == UnknownPublicKeyAlgorithm { -+ return ErrUnsupportedAlgorithm -+ } -+ -+ return checkSignature(c.SignatureAlgorithm, c.RawTBSCertificate, c.Signature, parent.PublicKey, false) -+} -+ -+// CheckSignature verifies that signature is a valid signature over signed from -+// c's public key. -+// -+// This is a low-level API that performs no validity checks on the certificate. -+// -+// [MD5WithRSA] signatures are rejected, while [SHA1WithRSA] and [ECDSAWithSHA1] -+// signatures are currently accepted. -+func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature []byte) error { -+ return checkSignature(algo, signed, signature, c.PublicKey, true) -+} -+ -+func (c *Certificate) hasNameConstraints() bool { -+ return oidInExtensions(oidExtensionNameConstraints, c.Extensions) -+} -+ -+func (c *Certificate) getSANExtension() []byte { -+ for _, e := range c.Extensions { -+ if e.Id.Equal(oidExtensionSubjectAltName) { -+ return e.Value -+ } -+ } -+ return nil -+} -+ -+func signaturePublicKeyAlgoMismatchError(expectedPubKeyAlgo PublicKeyAlgorithm, pubKey any) error { -+ return fmt.Errorf("x509: signature algorithm specifies an %s public key, but have public key of type %T", expectedPubKeyAlgo.String(), pubKey) -+} -+ -+var x509sha1 = godebug.New("x509sha1") -+ -+// checkSignature verifies that signature is a valid signature over signed from -+// a crypto.PublicKey. -+func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey crypto.PublicKey, allowSHA1 bool) (err error) { -+ var hashType crypto.Hash -+ var pubKeyAlgo PublicKeyAlgorithm -+ -+ for _, details := range signatureAlgorithmDetails { -+ if details.algo == algo { -+ hashType = details.hash -+ pubKeyAlgo = details.pubKeyAlgo -+ } -+ } -+ -+ switch hashType { -+ case crypto.Hash(0): -+ if pubKeyAlgo != Ed25519 { -+ return ErrUnsupportedAlgorithm -+ } -+ case crypto.MD5: -+ return InsecureAlgorithmError(algo) -+ case crypto.SHA1: -+ // SHA-1 signatures are mostly disabled. See go.dev/issue/41682. -+ if !allowSHA1 { -+ if x509sha1.Value() != "1" { -+ return InsecureAlgorithmError(algo) -+ } -+ x509sha1.IncNonDefault() -+ } -+ fallthrough -+ default: -+ if !hashType.Available() { -+ return ErrUnsupportedAlgorithm -+ } -+ h := hashType.New() -+ h.Write(signed) -+ signed = h.Sum(nil) -+ } -+ -+ switch pub := publicKey.(type) { -+ case *rsa.PublicKey: -+ if pubKeyAlgo != RSA { -+ return signaturePublicKeyAlgoMismatchError(pubKeyAlgo, pub) -+ } -+ if algo.isRSAPSS() { -+ return rsa.VerifyPSS(pub, hashType, signed, signature, &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash}) -+ } else { -+ return rsa.VerifyPKCS1v15(pub, hashType, signed, signature) -+ } -+ case *ecdsa.PublicKey: -+ if pubKeyAlgo != ECDSA { -+ return signaturePublicKeyAlgoMismatchError(pubKeyAlgo, pub) -+ } -+ if !ecdsa.VerifyASN1(pub, signed, signature) { -+ return errors.New("x509: ECDSA verification failure") -+ } -+ return -+ case ed25519.PublicKey: -+ if pubKeyAlgo != Ed25519 { -+ return signaturePublicKeyAlgoMismatchError(pubKeyAlgo, pub) -+ } -+ if !ed25519.Verify(pub, signed, signature) { -+ return errors.New("x509: Ed25519 verification failure") -+ } -+ return -+ } -+ return ErrUnsupportedAlgorithm -+} -+ -+// CheckCRLSignature checks that the signature in crl is from c. -+// -+// Deprecated: Use RevocationList.CheckSignatureFrom instead. -+func (c *Certificate) CheckCRLSignature(crl *pkix.CertificateList) error { -+ algo := getSignatureAlgorithmFromAI(crl.SignatureAlgorithm) -+ return c.CheckSignature(algo, crl.TBSCertList.Raw, crl.SignatureValue.RightAlign()) -+} -+ -+type UnhandledCriticalExtension struct{} -+ -+func (h UnhandledCriticalExtension) Error() string { -+ return "x509: unhandled critical extension" -+} -+ -+type basicConstraints struct { -+ IsCA bool `asn1:"optional"` -+ MaxPathLen int `asn1:"optional,default:-1"` -+} -+ -+// RFC 5280 4.2.1.4 -+type policyInformation struct { -+ Policy asn1.ObjectIdentifier -+ // policyQualifiers omitted -+} -+ -+const ( -+ nameTypeEmail = 1 -+ nameTypeDNS = 2 -+ nameTypeURI = 6 -+ nameTypeIP = 7 -+) -+ -+// RFC 5280, 4.2.2.1 -+type authorityInfoAccess struct { -+ Method asn1.ObjectIdentifier -+ Location asn1.RawValue -+} -+ -+// RFC 5280, 4.2.1.14 -+type distributionPoint struct { -+ DistributionPoint distributionPointName `asn1:"optional,tag:0"` -+ Reason asn1.BitString `asn1:"optional,tag:1"` -+ CRLIssuer asn1.RawValue `asn1:"optional,tag:2"` -+} -+ -+type distributionPointName struct { -+ FullName []asn1.RawValue `asn1:"optional,tag:0"` -+ RelativeName pkix.RDNSequence `asn1:"optional,tag:1"` -+} -+ -+func reverseBitsInAByte(in byte) byte { -+ b1 := in>>4 | in<<4 -+ b2 := b1>>2&0x33 | b1<<2&0xcc -+ b3 := b2>>1&0x55 | b2<<1&0xaa -+ return b3 -+} -+ -+// asn1BitLength returns the bit-length of bitString by considering the -+// most-significant bit in a byte to be the "first" bit. This convention -+// matches ASN.1, but differs from almost everything else. -+func asn1BitLength(bitString []byte) int { -+ bitLen := len(bitString) * 8 -+ -+ for i := range bitString { -+ b := bitString[len(bitString)-i-1] -+ -+ for bit := uint(0); bit < 8; bit++ { -+ if (b>>bit)&1 == 1 { -+ return bitLen -+ } -+ bitLen-- -+ } -+ } -+ -+ return 0 -+} -+ -+var ( -+ oidExtensionSubjectKeyId = []int{2, 5, 29, 14} -+ oidExtensionKeyUsage = []int{2, 5, 29, 15} -+ oidExtensionExtendedKeyUsage = []int{2, 5, 29, 37} -+ oidExtensionAuthorityKeyId = []int{2, 5, 29, 35} -+ oidExtensionBasicConstraints = []int{2, 5, 29, 19} -+ oidExtensionSubjectAltName = []int{2, 5, 29, 17} -+ oidExtensionCertificatePolicies = []int{2, 5, 29, 32} -+ oidExtensionNameConstraints = []int{2, 5, 29, 30} -+ oidExtensionCRLDistributionPoints = []int{2, 5, 29, 31} -+ oidExtensionAuthorityInfoAccess = []int{1, 3, 6, 1, 5, 5, 7, 1, 1} -+ oidExtensionCRLNumber = []int{2, 5, 29, 20} -+ oidExtensionReasonCode = []int{2, 5, 29, 21} -+) -+ -+var ( -+ oidAuthorityInfoAccessOcsp = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1} -+ oidAuthorityInfoAccessIssuers = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 2} -+) -+ -+// oidInExtensions reports whether an extension with the given oid exists in -+// extensions. -+func oidInExtensions(oid asn1.ObjectIdentifier, extensions []pkix.Extension) bool { -+ for _, e := range extensions { -+ if e.Id.Equal(oid) { -+ return true -+ } -+ } -+ return false -+} -+ -+// marshalSANs marshals a list of addresses into a the contents of an X.509 -+// SubjectAlternativeName extension. -+func marshalSANs(dnsNames, emailAddresses []string, ipAddresses []net.IP, uris []*url.URL) (derBytes []byte, err error) { -+ var rawValues []asn1.RawValue -+ for _, name := range dnsNames { -+ if err := isIA5String(name); err != nil { -+ return nil, err -+ } -+ rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeDNS, Class: 2, Bytes: []byte(name)}) -+ } -+ for _, email := range emailAddresses { -+ if err := isIA5String(email); err != nil { -+ return nil, err -+ } -+ rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeEmail, Class: 2, Bytes: []byte(email)}) -+ } -+ for _, rawIP := range ipAddresses { -+ // If possible, we always want to encode IPv4 addresses in 4 bytes. -+ ip := rawIP.To4() -+ if ip == nil { -+ ip = rawIP -+ } -+ rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeIP, Class: 2, Bytes: ip}) -+ } -+ for _, uri := range uris { -+ uriStr := uri.String() -+ if err := isIA5String(uriStr); err != nil { -+ return nil, err -+ } -+ rawValues = append(rawValues, asn1.RawValue{Tag: nameTypeURI, Class: 2, Bytes: []byte(uriStr)}) -+ } -+ return asn1.Marshal(rawValues) -+} -+ -+func isIA5String(s string) error { -+ for _, r := range s { -+ // Per RFC5280 "IA5String is limited to the set of ASCII characters" -+ if r > unicode.MaxASCII { -+ return fmt.Errorf("x509: %q cannot be encoded as an IA5String", s) -+ } -+ } -+ -+ return nil -+} -+ -+func buildCertExtensions(template *Certificate, subjectIsEmpty bool, authorityKeyId []byte, subjectKeyId []byte) (ret []pkix.Extension, err error) { -+ ret = make([]pkix.Extension, 10 /* maximum number of elements. */) -+ n := 0 -+ -+ if template.KeyUsage != 0 && -+ !oidInExtensions(oidExtensionKeyUsage, template.ExtraExtensions) { -+ ret[n], err = marshalKeyUsage(template.KeyUsage) -+ if err != nil { -+ return nil, err -+ } -+ n++ -+ } -+ -+ if (len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0) && -+ !oidInExtensions(oidExtensionExtendedKeyUsage, template.ExtraExtensions) { -+ ret[n], err = marshalExtKeyUsage(template.ExtKeyUsage, template.UnknownExtKeyUsage) -+ if err != nil { -+ return nil, err -+ } -+ n++ -+ } -+ -+ if template.BasicConstraintsValid && !oidInExtensions(oidExtensionBasicConstraints, template.ExtraExtensions) { -+ ret[n], err = marshalBasicConstraints(template.IsCA, template.MaxPathLen, template.MaxPathLenZero) -+ if err != nil { -+ return nil, err -+ } -+ n++ -+ } -+ -+ if len(subjectKeyId) > 0 && !oidInExtensions(oidExtensionSubjectKeyId, template.ExtraExtensions) { -+ ret[n].Id = oidExtensionSubjectKeyId -+ ret[n].Value, err = asn1.Marshal(subjectKeyId) -+ if err != nil { -+ return -+ } -+ n++ -+ } -+ -+ if len(authorityKeyId) > 0 && !oidInExtensions(oidExtensionAuthorityKeyId, template.ExtraExtensions) { -+ ret[n].Id = oidExtensionAuthorityKeyId -+ ret[n].Value, err = asn1.Marshal(authKeyId{authorityKeyId}) -+ if err != nil { -+ return -+ } -+ n++ -+ } -+ -+ if (len(template.OCSPServer) > 0 || len(template.IssuingCertificateURL) > 0) && -+ !oidInExtensions(oidExtensionAuthorityInfoAccess, template.ExtraExtensions) { -+ ret[n].Id = oidExtensionAuthorityInfoAccess -+ var aiaValues []authorityInfoAccess -+ for _, name := range template.OCSPServer { -+ aiaValues = append(aiaValues, authorityInfoAccess{ -+ Method: oidAuthorityInfoAccessOcsp, -+ Location: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)}, -+ }) -+ } -+ for _, name := range template.IssuingCertificateURL { -+ aiaValues = append(aiaValues, authorityInfoAccess{ -+ Method: oidAuthorityInfoAccessIssuers, -+ Location: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)}, -+ }) -+ } -+ ret[n].Value, err = asn1.Marshal(aiaValues) -+ if err != nil { -+ return -+ } -+ n++ -+ } -+ -+ if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0 || len(template.URIs) > 0) && -+ !oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) { -+ ret[n].Id = oidExtensionSubjectAltName -+ // From RFC 5280, Section 4.2.1.6: -+ // “If the subject field contains an empty sequence ... then -+ // subjectAltName extension ... is marked as critical” -+ ret[n].Critical = subjectIsEmpty -+ ret[n].Value, err = marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses, template.URIs) -+ if err != nil { -+ return -+ } -+ n++ -+ } -+ -+ if len(template.PolicyIdentifiers) > 0 && -+ !oidInExtensions(oidExtensionCertificatePolicies, template.ExtraExtensions) { -+ ret[n], err = marshalCertificatePolicies(template.PolicyIdentifiers) -+ if err != nil { -+ return nil, err -+ } -+ n++ -+ } -+ -+ if (len(template.PermittedDNSDomains) > 0 || len(template.ExcludedDNSDomains) > 0 || -+ len(template.PermittedIPRanges) > 0 || len(template.ExcludedIPRanges) > 0 || -+ len(template.PermittedEmailAddresses) > 0 || len(template.ExcludedEmailAddresses) > 0 || -+ len(template.PermittedURIDomains) > 0 || len(template.ExcludedURIDomains) > 0) && -+ !oidInExtensions(oidExtensionNameConstraints, template.ExtraExtensions) { -+ ret[n].Id = oidExtensionNameConstraints -+ ret[n].Critical = template.PermittedDNSDomainsCritical -+ -+ ipAndMask := func(ipNet *net.IPNet) []byte { -+ maskedIP := ipNet.IP.Mask(ipNet.Mask) -+ ipAndMask := make([]byte, 0, len(maskedIP)+len(ipNet.Mask)) -+ ipAndMask = append(ipAndMask, maskedIP...) -+ ipAndMask = append(ipAndMask, ipNet.Mask...) -+ return ipAndMask -+ } -+ -+ serialiseConstraints := func(dns []string, ips []*net.IPNet, emails []string, uriDomains []string) (der []byte, err error) { -+ var b cryptobyte.Builder -+ -+ for _, name := range dns { -+ if err = isIA5String(name); err != nil { -+ return nil, err -+ } -+ -+ b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { -+ b.AddASN1(cryptobyte_asn1.Tag(2).ContextSpecific(), func(b *cryptobyte.Builder) { -+ b.AddBytes([]byte(name)) -+ }) -+ }) -+ } -+ -+ for _, ipNet := range ips { -+ b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { -+ b.AddASN1(cryptobyte_asn1.Tag(7).ContextSpecific(), func(b *cryptobyte.Builder) { -+ b.AddBytes(ipAndMask(ipNet)) -+ }) -+ }) -+ } -+ -+ for _, email := range emails { -+ if err = isIA5String(email); err != nil { -+ return nil, err -+ } -+ -+ b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { -+ b.AddASN1(cryptobyte_asn1.Tag(1).ContextSpecific(), func(b *cryptobyte.Builder) { -+ b.AddBytes([]byte(email)) -+ }) -+ }) -+ } -+ -+ for _, uriDomain := range uriDomains { -+ if err = isIA5String(uriDomain); err != nil { -+ return nil, err -+ } -+ -+ b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { -+ b.AddASN1(cryptobyte_asn1.Tag(6).ContextSpecific(), func(b *cryptobyte.Builder) { -+ b.AddBytes([]byte(uriDomain)) -+ }) -+ }) -+ } -+ -+ return b.Bytes() -+ } -+ -+ permitted, err := serialiseConstraints(template.PermittedDNSDomains, template.PermittedIPRanges, template.PermittedEmailAddresses, template.PermittedURIDomains) -+ if err != nil { -+ return nil, err -+ } -+ -+ excluded, err := serialiseConstraints(template.ExcludedDNSDomains, template.ExcludedIPRanges, template.ExcludedEmailAddresses, template.ExcludedURIDomains) -+ if err != nil { -+ return nil, err -+ } -+ -+ var b cryptobyte.Builder -+ b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) { -+ if len(permitted) > 0 { -+ b.AddASN1(cryptobyte_asn1.Tag(0).ContextSpecific().Constructed(), func(b *cryptobyte.Builder) { -+ b.AddBytes(permitted) -+ }) -+ } -+ -+ if len(excluded) > 0 { -+ b.AddASN1(cryptobyte_asn1.Tag(1).ContextSpecific().Constructed(), func(b *cryptobyte.Builder) { -+ b.AddBytes(excluded) -+ }) -+ } -+ }) -+ -+ ret[n].Value, err = b.Bytes() -+ if err != nil { -+ return nil, err -+ } -+ n++ -+ } -+ -+ if len(template.CRLDistributionPoints) > 0 && -+ !oidInExtensions(oidExtensionCRLDistributionPoints, template.ExtraExtensions) { -+ ret[n].Id = oidExtensionCRLDistributionPoints -+ -+ var crlDp []distributionPoint -+ for _, name := range template.CRLDistributionPoints { -+ dp := distributionPoint{ -+ DistributionPoint: distributionPointName{ -+ FullName: []asn1.RawValue{ -+ {Tag: 6, Class: 2, Bytes: []byte(name)}, -+ }, -+ }, -+ } -+ crlDp = append(crlDp, dp) -+ } -+ -+ ret[n].Value, err = asn1.Marshal(crlDp) -+ if err != nil { -+ return -+ } -+ n++ -+ } -+ -+ // Adding another extension here? Remember to update the maximum number -+ // of elements in the make() at the top of the function and the list of -+ // template fields used in CreateCertificate documentation. -+ -+ return append(ret[:n], template.ExtraExtensions...), nil -+} -+ -+func marshalKeyUsage(ku KeyUsage) (pkix.Extension, error) { -+ ext := pkix.Extension{Id: oidExtensionKeyUsage, Critical: true} -+ -+ var a [2]byte -+ a[0] = reverseBitsInAByte(byte(ku)) -+ a[1] = reverseBitsInAByte(byte(ku >> 8)) -+ -+ l := 1 -+ if a[1] != 0 { -+ l = 2 -+ } -+ -+ bitString := a[:l] -+ var err error -+ ext.Value, err = asn1.Marshal(asn1.BitString{Bytes: bitString, BitLength: asn1BitLength(bitString)}) -+ return ext, err -+} -+ -+func marshalExtKeyUsage(extUsages []ExtKeyUsage, unknownUsages []asn1.ObjectIdentifier) (pkix.Extension, error) { -+ ext := pkix.Extension{Id: oidExtensionExtendedKeyUsage} -+ -+ oids := make([]asn1.ObjectIdentifier, len(extUsages)+len(unknownUsages)) -+ for i, u := range extUsages { -+ if oid, ok := oidFromExtKeyUsage(u); ok { -+ oids[i] = oid -+ } else { -+ return ext, errors.New("x509: unknown extended key usage") -+ } -+ } -+ -+ copy(oids[len(extUsages):], unknownUsages) -+ -+ var err error -+ ext.Value, err = asn1.Marshal(oids) -+ return ext, err -+} -+ -+func marshalBasicConstraints(isCA bool, maxPathLen int, maxPathLenZero bool) (pkix.Extension, error) { -+ ext := pkix.Extension{Id: oidExtensionBasicConstraints, Critical: true} -+ // Leaving MaxPathLen as zero indicates that no maximum path -+ // length is desired, unless MaxPathLenZero is set. A value of -+ // -1 causes encoding/asn1 to omit the value as desired. -+ if maxPathLen == 0 && !maxPathLenZero { -+ maxPathLen = -1 -+ } -+ var err error -+ ext.Value, err = asn1.Marshal(basicConstraints{isCA, maxPathLen}) -+ return ext, err -+} -+ -+func marshalCertificatePolicies(policyIdentifiers []asn1.ObjectIdentifier) (pkix.Extension, error) { -+ ext := pkix.Extension{Id: oidExtensionCertificatePolicies} -+ policies := make([]policyInformation, len(policyIdentifiers)) -+ for i, policy := range policyIdentifiers { -+ policies[i].Policy = policy -+ } -+ var err error -+ ext.Value, err = asn1.Marshal(policies) -+ return ext, err -+} -+ -+func buildCSRExtensions(template *CertificateRequest) ([]pkix.Extension, error) { -+ var ret []pkix.Extension -+ -+ if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0 || len(template.URIs) > 0) && -+ !oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) { -+ sanBytes, err := marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses, template.URIs) -+ if err != nil { -+ return nil, err -+ } -+ -+ ret = append(ret, pkix.Extension{ -+ Id: oidExtensionSubjectAltName, -+ Value: sanBytes, -+ }) -+ } -+ -+ return append(ret, template.ExtraExtensions...), nil -+} -+ -+func subjectBytes(cert *Certificate) ([]byte, error) { -+ if len(cert.RawSubject) > 0 { -+ return cert.RawSubject, nil -+ } -+ -+ return asn1.Marshal(cert.Subject.ToRDNSequence()) -+} -+ -+// signingParamsForPublicKey returns the parameters to use for signing with -+// priv. If requestedSigAlgo is not zero then it overrides the default -+// signature algorithm. -+func signingParamsForPublicKey(pub any, requestedSigAlgo SignatureAlgorithm) (hashFunc crypto.Hash, sigAlgo pkix.AlgorithmIdentifier, err error) { -+ var pubType PublicKeyAlgorithm -+ -+ switch pub := pub.(type) { -+ case *rsa.PublicKey: -+ pubType = RSA -+ hashFunc = crypto.SHA256 -+ sigAlgo.Algorithm = oidSignatureSHA256WithRSA -+ sigAlgo.Parameters = asn1.NullRawValue -+ -+ case *ecdsa.PublicKey: -+ pubType = ECDSA -+ -+ switch pub.Curve { -+ case elliptic.P224(), elliptic.P256(): -+ hashFunc = crypto.SHA256 -+ sigAlgo.Algorithm = oidSignatureECDSAWithSHA256 -+ case elliptic.P384(): -+ hashFunc = crypto.SHA384 -+ sigAlgo.Algorithm = oidSignatureECDSAWithSHA384 -+ case elliptic.P521(): -+ hashFunc = crypto.SHA512 -+ sigAlgo.Algorithm = oidSignatureECDSAWithSHA512 -+ default: -+ err = errors.New("x509: unknown elliptic curve") -+ } -+ -+ case ed25519.PublicKey: -+ pubType = Ed25519 -+ sigAlgo.Algorithm = oidSignatureEd25519 -+ -+ default: -+ err = errors.New("x509: only RSA, ECDSA and Ed25519 keys supported") -+ } -+ -+ if err != nil { -+ return -+ } -+ -+ if requestedSigAlgo == 0 { -+ return -+ } -+ -+ found := false -+ for _, details := range signatureAlgorithmDetails { -+ if details.algo == requestedSigAlgo { -+ if details.pubKeyAlgo != pubType { -+ err = errors.New("x509: requested SignatureAlgorithm does not match private key type") -+ return -+ } -+ sigAlgo.Algorithm, hashFunc = details.oid, details.hash -+ if hashFunc == 0 && pubType != Ed25519 { -+ err = errors.New("x509: cannot sign with hash function requested") -+ return -+ } -+ if hashFunc == crypto.MD5 { -+ err = errors.New("x509: signing with MD5 is not supported") -+ return -+ } -+ if requestedSigAlgo.isRSAPSS() { -+ sigAlgo.Parameters = hashToPSSParameters[hashFunc] -+ } -+ found = true -+ break -+ } -+ } -+ -+ if !found { -+ err = errors.New("x509: unknown SignatureAlgorithm") -+ } -+ -+ return -+} -+ -+// emptyASN1Subject is the ASN.1 DER encoding of an empty Subject, which is -+// just an empty SEQUENCE. -+var emptyASN1Subject = []byte{0x30, 0} -+ -+// CreateCertificate creates a new X.509 v3 certificate based on a template. -+// The following members of template are currently used: -+// -+// - AuthorityKeyId -+// - BasicConstraintsValid -+// - CRLDistributionPoints -+// - DNSNames -+// - EmailAddresses -+// - ExcludedDNSDomains -+// - ExcludedEmailAddresses -+// - ExcludedIPRanges -+// - ExcludedURIDomains -+// - ExtKeyUsage -+// - ExtraExtensions -+// - IPAddresses -+// - IsCA -+// - IssuingCertificateURL -+// - KeyUsage -+// - MaxPathLen -+// - MaxPathLenZero -+// - NotAfter -+// - NotBefore -+// - OCSPServer -+// - PermittedDNSDomains -+// - PermittedDNSDomainsCritical -+// - PermittedEmailAddresses -+// - PermittedIPRanges -+// - PermittedURIDomains -+// - PolicyIdentifiers -+// - SerialNumber -+// - SignatureAlgorithm -+// - Subject -+// - SubjectKeyId -+// - URIs -+// - UnknownExtKeyUsage -+// -+// The certificate is signed by parent. If parent is equal to template then the -+// certificate is self-signed. The parameter pub is the public key of the -+// certificate to be generated and priv is the private key of the signer. -+// -+// The returned slice is the certificate in DER encoding. -+// -+// The currently supported key types are *rsa.PublicKey, *ecdsa.PublicKey and -+// ed25519.PublicKey. pub must be a supported key type, and priv must be a -+// crypto.Signer with a supported public key. -+// -+// The AuthorityKeyId will be taken from the SubjectKeyId of parent, if any, -+// unless the resulting certificate is self-signed. Otherwise the value from -+// template will be used. -+// -+// If SubjectKeyId from template is empty and the template is a CA, SubjectKeyId -+// will be generated from the hash of the public key. -+func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv any) ([]byte, error) { -+ key, ok := priv.(crypto.Signer) -+ if !ok { -+ return nil, errors.New("x509: certificate private key does not implement crypto.Signer") -+ } -+ -+ if template.SerialNumber == nil { -+ return nil, errors.New("x509: no SerialNumber given") -+ } -+ -+ // RFC 5280 Section 4.1.2.2: serial number must positive -+ // -+ // We _should_ also restrict serials to <= 20 octets, but it turns out a lot of people -+ // get this wrong, in part because the encoding can itself alter the length of the -+ // serial. For now we accept these non-conformant serials. -+ if template.SerialNumber.Sign() == -1 { -+ return nil, errors.New("x509: serial number must be positive") -+ } -+ -+ if template.BasicConstraintsValid && !template.IsCA && template.MaxPathLen != -1 && (template.MaxPathLen != 0 || template.MaxPathLenZero) { -+ return nil, errors.New("x509: only CAs are allowed to specify MaxPathLen") -+ } -+ -+ hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm) -+ if err != nil { -+ return nil, err -+ } -+ -+ publicKeyBytes, publicKeyAlgorithm, err := marshalPublicKey(pub) -+ if err != nil { -+ return nil, err -+ } -+ if getPublicKeyAlgorithmFromOID(publicKeyAlgorithm.Algorithm) == UnknownPublicKeyAlgorithm { -+ return nil, fmt.Errorf("x509: unsupported public key type: %T", pub) -+ } -+ -+ asn1Issuer, err := subjectBytes(parent) -+ if err != nil { -+ return nil, err -+ } -+ -+ asn1Subject, err := subjectBytes(template) -+ if err != nil { -+ return nil, err -+ } -+ -+ authorityKeyId := template.AuthorityKeyId -+ if !bytes.Equal(asn1Issuer, asn1Subject) && len(parent.SubjectKeyId) > 0 { -+ authorityKeyId = parent.SubjectKeyId -+ } -+ -+ subjectKeyId := template.SubjectKeyId -+ if len(subjectKeyId) == 0 && template.IsCA { -+ // SubjectKeyId generated using method 1 in RFC 5280, Section 4.2.1.2: -+ // (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the -+ // value of the BIT STRING subjectPublicKey (excluding the tag, -+ // length, and number of unused bits). -+ h := sha1.Sum(publicKeyBytes) -+ subjectKeyId = h[:] -+ } -+ -+ // Check that the signer's public key matches the private key, if available. -+ type privateKey interface { -+ Equal(crypto.PublicKey) bool -+ } -+ if privPub, ok := key.Public().(privateKey); !ok { -+ return nil, errors.New("x509: internal error: supported public key does not implement Equal") -+ } else if parent.PublicKey != nil && !privPub.Equal(parent.PublicKey) { -+ return nil, errors.New("x509: provided PrivateKey doesn't match parent's PublicKey") -+ } -+ -+ extensions, err := buildCertExtensions(template, bytes.Equal(asn1Subject, emptyASN1Subject), authorityKeyId, subjectKeyId) -+ if err != nil { -+ return nil, err -+ } -+ -+ encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes} -+ c := tbsCertificate{ -+ Version: 2, -+ SerialNumber: template.SerialNumber, -+ SignatureAlgorithm: signatureAlgorithm, -+ Issuer: asn1.RawValue{FullBytes: asn1Issuer}, -+ Validity: validity{template.NotBefore.UTC(), template.NotAfter.UTC()}, -+ Subject: asn1.RawValue{FullBytes: asn1Subject}, -+ PublicKey: publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey}, -+ Extensions: extensions, -+ } -+ -+ tbsCertContents, err := asn1.Marshal(c) -+ if err != nil { -+ return nil, err -+ } -+ c.Raw = tbsCertContents -+ -+ signed := tbsCertContents -+ if hashFunc != 0 { -+ h := hashFunc.New() -+ h.Write(signed) -+ signed = h.Sum(nil) -+ } -+ -+ var signerOpts crypto.SignerOpts = hashFunc -+ if template.SignatureAlgorithm != 0 && template.SignatureAlgorithm.isRSAPSS() { -+ signerOpts = &rsa.PSSOptions{ -+ SaltLength: rsa.PSSSaltLengthEqualsHash, -+ Hash: hashFunc, -+ } -+ } -+ -+ var signature []byte -+ signature, err = key.Sign(rand, signed, signerOpts) -+ if err != nil { -+ return nil, err -+ } -+ -+ signedCert, err := asn1.Marshal(certificate{ -+ c, -+ signatureAlgorithm, -+ asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, -+ }) -+ if err != nil { -+ return nil, err -+ } -+ -+ // Check the signature to ensure the crypto.Signer behaved correctly. -+ if err := checkSignature(getSignatureAlgorithmFromAI(signatureAlgorithm), c.Raw, signature, key.Public(), true); err != nil { -+ return nil, fmt.Errorf("x509: signature over certificate returned by signer is invalid: %w", err) -+ } -+ -+ return signedCert, nil -+} -+ -+// pemCRLPrefix is the magic string that indicates that we have a PEM encoded -+// CRL. -+var pemCRLPrefix = []byte("-----BEGIN X509 CRL") -+ -+// pemType is the type of a PEM encoded CRL. -+var pemType = "X509 CRL" -+ -+// ParseCRL parses a CRL from the given bytes. It's often the case that PEM -+// encoded CRLs will appear where they should be DER encoded, so this function -+// will transparently handle PEM encoding as long as there isn't any leading -+// garbage. -+// -+// Deprecated: Use ParseRevocationList instead. -+func ParseCRL(crlBytes []byte) (*pkix.CertificateList, error) { -+ if bytes.HasPrefix(crlBytes, pemCRLPrefix) { -+ block, _ := pem.Decode(crlBytes) -+ if block != nil && block.Type == pemType { -+ crlBytes = block.Bytes -+ } -+ } -+ return ParseDERCRL(crlBytes) -+} -+ -+// ParseDERCRL parses a DER encoded CRL from the given bytes. -+// -+// Deprecated: Use ParseRevocationList instead. -+func ParseDERCRL(derBytes []byte) (*pkix.CertificateList, error) { -+ certList := new(pkix.CertificateList) -+ if rest, err := asn1.Unmarshal(derBytes, certList); err != nil { -+ return nil, err -+ } else if len(rest) != 0 { -+ return nil, errors.New("x509: trailing data after CRL") -+ } -+ return certList, nil -+} -+ -+// CreateCRL returns a DER encoded CRL, signed by this Certificate, that -+// contains the given list of revoked certificates. -+// -+// Deprecated: this method does not generate an RFC 5280 conformant X.509 v2 CRL. -+// To generate a standards compliant CRL, use CreateRevocationList instead. -+func (c *Certificate) CreateCRL(rand io.Reader, priv any, revokedCerts []pkix.RevokedCertificate, now, expiry time.Time) (crlBytes []byte, err error) { -+ key, ok := priv.(crypto.Signer) -+ if !ok { -+ return nil, errors.New("x509: certificate private key does not implement crypto.Signer") -+ } -+ -+ hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), 0) -+ if err != nil { -+ return nil, err -+ } -+ -+ // Force revocation times to UTC per RFC 5280. -+ revokedCertsUTC := make([]pkix.RevokedCertificate, len(revokedCerts)) -+ for i, rc := range revokedCerts { -+ rc.RevocationTime = rc.RevocationTime.UTC() -+ revokedCertsUTC[i] = rc -+ } -+ -+ tbsCertList := pkix.TBSCertificateList{ -+ Version: 1, -+ Signature: signatureAlgorithm, -+ Issuer: c.Subject.ToRDNSequence(), -+ ThisUpdate: now.UTC(), -+ NextUpdate: expiry.UTC(), -+ RevokedCertificates: revokedCertsUTC, -+ } -+ -+ // Authority Key Id -+ if len(c.SubjectKeyId) > 0 { -+ var aki pkix.Extension -+ aki.Id = oidExtensionAuthorityKeyId -+ aki.Value, err = asn1.Marshal(authKeyId{Id: c.SubjectKeyId}) -+ if err != nil { -+ return -+ } -+ tbsCertList.Extensions = append(tbsCertList.Extensions, aki) -+ } -+ -+ tbsCertListContents, err := asn1.Marshal(tbsCertList) -+ if err != nil { -+ return -+ } -+ -+ signed := tbsCertListContents -+ if hashFunc != 0 { -+ h := hashFunc.New() -+ h.Write(signed) -+ signed = h.Sum(nil) -+ } -+ -+ var signature []byte -+ signature, err = key.Sign(rand, signed, hashFunc) -+ if err != nil { -+ return -+ } -+ -+ return asn1.Marshal(pkix.CertificateList{ -+ TBSCertList: tbsCertList, -+ SignatureAlgorithm: signatureAlgorithm, -+ SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, -+ }) -+} -+ -+// CertificateRequest represents a PKCS #10, certificate signature request. -+type CertificateRequest struct { -+ Raw []byte // Complete ASN.1 DER content (CSR, signature algorithm and signature). -+ RawTBSCertificateRequest []byte // Certificate request info part of raw ASN.1 DER content. -+ RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo. -+ RawSubject []byte // DER encoded Subject. -+ -+ Version int -+ Signature []byte -+ SignatureAlgorithm SignatureAlgorithm -+ -+ PublicKeyAlgorithm PublicKeyAlgorithm -+ PublicKey any -+ -+ Subject pkix.Name -+ -+ // Attributes contains the CSR attributes that can parse as -+ // pkix.AttributeTypeAndValueSET. -+ // -+ // Deprecated: Use Extensions and ExtraExtensions instead for parsing and -+ // generating the requestedExtensions attribute. -+ Attributes []pkix.AttributeTypeAndValueSET -+ -+ // Extensions contains all requested extensions, in raw form. When parsing -+ // CSRs, this can be used to extract extensions that are not parsed by this -+ // package. -+ Extensions []pkix.Extension -+ -+ // ExtraExtensions contains extensions to be copied, raw, into any CSR -+ // marshaled by CreateCertificateRequest. Values override any extensions -+ // that would otherwise be produced based on the other fields but are -+ // overridden by any extensions specified in Attributes. -+ // -+ // The ExtraExtensions field is not populated by ParseCertificateRequest, -+ // see Extensions instead. -+ ExtraExtensions []pkix.Extension -+ -+ // Subject Alternate Name values. -+ DNSNames []string -+ EmailAddresses []string -+ IPAddresses []net.IP -+ URIs []*url.URL -+} -+ -+// These structures reflect the ASN.1 structure of X.509 certificate -+// signature requests (see RFC 2986): -+ -+type tbsCertificateRequest struct { -+ Raw asn1.RawContent -+ Version int -+ Subject asn1.RawValue -+ PublicKey publicKeyInfo -+ RawAttributes []asn1.RawValue `asn1:"tag:0"` -+} -+ -+type certificateRequest struct { -+ Raw asn1.RawContent -+ TBSCSR tbsCertificateRequest -+ SignatureAlgorithm pkix.AlgorithmIdentifier -+ SignatureValue asn1.BitString -+} -+ -+// oidExtensionRequest is a PKCS #9 OBJECT IDENTIFIER that indicates requested -+// extensions in a CSR. -+var oidExtensionRequest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 14} -+ -+// newRawAttributes converts AttributeTypeAndValueSETs from a template -+// CertificateRequest's Attributes into tbsCertificateRequest RawAttributes. -+func newRawAttributes(attributes []pkix.AttributeTypeAndValueSET) ([]asn1.RawValue, error) { -+ var rawAttributes []asn1.RawValue -+ b, err := asn1.Marshal(attributes) -+ if err != nil { -+ return nil, err -+ } -+ rest, err := asn1.Unmarshal(b, &rawAttributes) -+ if err != nil { -+ return nil, err -+ } -+ if len(rest) != 0 { -+ return nil, errors.New("x509: failed to unmarshal raw CSR Attributes") -+ } -+ return rawAttributes, nil -+} -+ -+// parseRawAttributes Unmarshals RawAttributes into AttributeTypeAndValueSETs. -+func parseRawAttributes(rawAttributes []asn1.RawValue) []pkix.AttributeTypeAndValueSET { -+ var attributes []pkix.AttributeTypeAndValueSET -+ for _, rawAttr := range rawAttributes { -+ var attr pkix.AttributeTypeAndValueSET -+ rest, err := asn1.Unmarshal(rawAttr.FullBytes, &attr) -+ // Ignore attributes that don't parse into pkix.AttributeTypeAndValueSET -+ // (i.e.: challengePassword or unstructuredName). -+ if err == nil && len(rest) == 0 { -+ attributes = append(attributes, attr) -+ } -+ } -+ return attributes -+} -+ -+// parseCSRExtensions parses the attributes from a CSR and extracts any -+// requested extensions. -+func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error) { -+ // pkcs10Attribute reflects the Attribute structure from RFC 2986, Section 4.1. -+ type pkcs10Attribute struct { -+ Id asn1.ObjectIdentifier -+ Values []asn1.RawValue `asn1:"set"` -+ } -+ -+ var ret []pkix.Extension -+ requestedExts := make(map[string]bool) -+ for _, rawAttr := range rawAttributes { -+ var attr pkcs10Attribute -+ if rest, err := asn1.Unmarshal(rawAttr.FullBytes, &attr); err != nil || len(rest) != 0 || len(attr.Values) == 0 { -+ // Ignore attributes that don't parse. -+ continue -+ } -+ -+ if !attr.Id.Equal(oidExtensionRequest) { -+ continue -+ } -+ -+ var extensions []pkix.Extension -+ if _, err := asn1.Unmarshal(attr.Values[0].FullBytes, &extensions); err != nil { -+ return nil, err -+ } -+ for _, ext := range extensions { -+ oidStr := ext.Id.String() -+ if requestedExts[oidStr] { -+ return nil, errors.New("x509: certificate request contains duplicate requested extensions") -+ } -+ requestedExts[oidStr] = true -+ } -+ ret = append(ret, extensions...) -+ } -+ -+ return ret, nil -+} -+ -+// CreateCertificateRequest creates a new certificate request based on a -+// template. The following members of template are used: -+// -+// - SignatureAlgorithm -+// - Subject -+// - DNSNames -+// - EmailAddresses -+// - IPAddresses -+// - URIs -+// - ExtraExtensions -+// - Attributes (deprecated) -+// -+// priv is the private key to sign the CSR with, and the corresponding public -+// key will be included in the CSR. It must implement crypto.Signer and its -+// Public() method must return a *rsa.PublicKey or a *ecdsa.PublicKey or a -+// ed25519.PublicKey. (A *rsa.PrivateKey, *ecdsa.PrivateKey or -+// ed25519.PrivateKey satisfies this.) -+// -+// The returned slice is the certificate request in DER encoding. -+func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv any) (csr []byte, err error) { -+ key, ok := priv.(crypto.Signer) -+ if !ok { -+ return nil, errors.New("x509: certificate private key does not implement crypto.Signer") -+ } -+ -+ var hashFunc crypto.Hash -+ var sigAlgo pkix.AlgorithmIdentifier -+ hashFunc, sigAlgo, err = signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm) -+ if err != nil { -+ return nil, err -+ } -+ -+ var publicKeyBytes []byte -+ var publicKeyAlgorithm pkix.AlgorithmIdentifier -+ publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(key.Public()) -+ if err != nil { -+ return nil, err -+ } -+ -+ extensions, err := buildCSRExtensions(template) -+ if err != nil { -+ return nil, err -+ } -+ -+ // Make a copy of template.Attributes because we may alter it below. -+ attributes := make([]pkix.AttributeTypeAndValueSET, 0, len(template.Attributes)) -+ for _, attr := range template.Attributes { -+ values := make([][]pkix.AttributeTypeAndValue, len(attr.Value)) -+ copy(values, attr.Value) -+ attributes = append(attributes, pkix.AttributeTypeAndValueSET{ -+ Type: attr.Type, -+ Value: values, -+ }) -+ } -+ -+ extensionsAppended := false -+ if len(extensions) > 0 { -+ // Append the extensions to an existing attribute if possible. -+ for _, atvSet := range attributes { -+ if !atvSet.Type.Equal(oidExtensionRequest) || len(atvSet.Value) == 0 { -+ continue -+ } -+ -+ // specifiedExtensions contains all the extensions that we -+ // found specified via template.Attributes. -+ specifiedExtensions := make(map[string]bool) -+ -+ for _, atvs := range atvSet.Value { -+ for _, atv := range atvs { -+ specifiedExtensions[atv.Type.String()] = true -+ } -+ } -+ -+ newValue := make([]pkix.AttributeTypeAndValue, 0, len(atvSet.Value[0])+len(extensions)) -+ newValue = append(newValue, atvSet.Value[0]...) -+ -+ for _, e := range extensions { -+ if specifiedExtensions[e.Id.String()] { -+ // Attributes already contained a value for -+ // this extension and it takes priority. -+ continue -+ } -+ -+ newValue = append(newValue, pkix.AttributeTypeAndValue{ -+ // There is no place for the critical -+ // flag in an AttributeTypeAndValue. -+ Type: e.Id, -+ Value: e.Value, -+ }) -+ } -+ -+ atvSet.Value[0] = newValue -+ extensionsAppended = true -+ break -+ } -+ } -+ -+ rawAttributes, err := newRawAttributes(attributes) -+ if err != nil { -+ return -+ } -+ -+ // If not included in attributes, add a new attribute for the -+ // extensions. -+ if len(extensions) > 0 && !extensionsAppended { -+ attr := struct { -+ Type asn1.ObjectIdentifier -+ Value [][]pkix.Extension `asn1:"set"` -+ }{ -+ Type: oidExtensionRequest, -+ Value: [][]pkix.Extension{extensions}, -+ } -+ -+ b, err := asn1.Marshal(attr) -+ if err != nil { -+ return nil, errors.New("x509: failed to serialise extensions attribute: " + err.Error()) -+ } -+ -+ var rawValue asn1.RawValue -+ if _, err := asn1.Unmarshal(b, &rawValue); err != nil { -+ return nil, err -+ } -+ -+ rawAttributes = append(rawAttributes, rawValue) -+ } -+ -+ asn1Subject := template.RawSubject -+ if len(asn1Subject) == 0 { -+ asn1Subject, err = asn1.Marshal(template.Subject.ToRDNSequence()) -+ if err != nil { -+ return nil, err -+ } -+ } -+ -+ tbsCSR := tbsCertificateRequest{ -+ Version: 0, // PKCS #10, RFC 2986 -+ Subject: asn1.RawValue{FullBytes: asn1Subject}, -+ PublicKey: publicKeyInfo{ -+ Algorithm: publicKeyAlgorithm, -+ PublicKey: asn1.BitString{ -+ Bytes: publicKeyBytes, -+ BitLength: len(publicKeyBytes) * 8, -+ }, -+ }, -+ RawAttributes: rawAttributes, -+ } -+ -+ tbsCSRContents, err := asn1.Marshal(tbsCSR) -+ if err != nil { -+ return -+ } -+ tbsCSR.Raw = tbsCSRContents -+ -+ signed := tbsCSRContents -+ if hashFunc != 0 { -+ h := hashFunc.New() -+ h.Write(signed) -+ signed = h.Sum(nil) -+ } -+ -+ var signature []byte -+ signature, err = key.Sign(rand, signed, hashFunc) -+ if err != nil { -+ return -+ } -+ -+ return asn1.Marshal(certificateRequest{ -+ TBSCSR: tbsCSR, -+ SignatureAlgorithm: sigAlgo, -+ SignatureValue: asn1.BitString{ -+ Bytes: signature, -+ BitLength: len(signature) * 8, -+ }, -+ }) -+} -+ -+// ParseCertificateRequest parses a single certificate request from the -+// given ASN.1 DER data. -+func ParseCertificateRequest(asn1Data []byte) (*CertificateRequest, error) { -+ var csr certificateRequest -+ -+ rest, err := asn1.Unmarshal(asn1Data, &csr) -+ if err != nil { -+ return nil, err -+ } else if len(rest) != 0 { -+ return nil, asn1.SyntaxError{Msg: "trailing data"} -+ } -+ -+ return parseCertificateRequest(&csr) -+} -+ -+func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error) { -+ out := &CertificateRequest{ -+ Raw: in.Raw, -+ RawTBSCertificateRequest: in.TBSCSR.Raw, -+ RawSubjectPublicKeyInfo: in.TBSCSR.PublicKey.Raw, -+ RawSubject: in.TBSCSR.Subject.FullBytes, -+ -+ Signature: in.SignatureValue.RightAlign(), -+ SignatureAlgorithm: getSignatureAlgorithmFromAI(in.SignatureAlgorithm), -+ -+ PublicKeyAlgorithm: getPublicKeyAlgorithmFromOID(in.TBSCSR.PublicKey.Algorithm.Algorithm), -+ -+ Version: in.TBSCSR.Version, -+ Attributes: parseRawAttributes(in.TBSCSR.RawAttributes), -+ } -+ -+ var err error -+ if out.PublicKeyAlgorithm != UnknownPublicKeyAlgorithm { -+ out.PublicKey, err = parsePublicKey(&in.TBSCSR.PublicKey) -+ if err != nil { -+ return nil, err -+ } -+ } -+ -+ var subject pkix.RDNSequence -+ if rest, err := asn1.Unmarshal(in.TBSCSR.Subject.FullBytes, &subject); err != nil { -+ return nil, err -+ } else if len(rest) != 0 { -+ return nil, errors.New("x509: trailing data after X.509 Subject") -+ } -+ -+ out.Subject.FillFromRDNSequence(&subject) -+ -+ if out.Extensions, err = parseCSRExtensions(in.TBSCSR.RawAttributes); err != nil { -+ return nil, err -+ } -+ -+ for _, extension := range out.Extensions { -+ switch { -+ case extension.Id.Equal(oidExtensionSubjectAltName): -+ out.DNSNames, out.EmailAddresses, out.IPAddresses, out.URIs, err = parseSANExtension(extension.Value) -+ if err != nil { -+ return nil, err -+ } -+ } -+ } -+ -+ return out, nil -+} -+ -+// CheckSignature reports whether the signature on c is valid. -+func (c *CertificateRequest) CheckSignature() error { -+ return checkSignature(c.SignatureAlgorithm, c.RawTBSCertificateRequest, c.Signature, c.PublicKey, true) -+} -+ -+// RevocationListEntry represents an entry in the revokedCertificates -+// sequence of a CRL. -+type RevocationListEntry struct { -+ // Raw contains the raw bytes of the revokedCertificates entry. It is set when -+ // parsing a CRL; it is ignored when generating a CRL. -+ Raw []byte -+ -+ // SerialNumber represents the serial number of a revoked certificate. It is -+ // both used when creating a CRL and populated when parsing a CRL. It must not -+ // be nil. -+ SerialNumber *big.Int -+ // RevocationTime represents the time at which the certificate was revoked. It -+ // is both used when creating a CRL and populated when parsing a CRL. It must -+ // not be the zero time. -+ RevocationTime time.Time -+ // ReasonCode represents the reason for revocation, using the integer enum -+ // values specified in RFC 5280 Section 5.3.1. When creating a CRL, the zero -+ // value will result in the reasonCode extension being omitted. When parsing a -+ // CRL, the zero value may represent either the reasonCode extension being -+ // absent (which implies the default revocation reason of 0/Unspecified), or -+ // it may represent the reasonCode extension being present and explicitly -+ // containing a value of 0/Unspecified (which should not happen according to -+ // the DER encoding rules, but can and does happen anyway). -+ ReasonCode int -+ -+ // Extensions contains raw X.509 extensions. When parsing CRL entries, -+ // this can be used to extract non-critical extensions that are not -+ // parsed by this package. When marshaling CRL entries, the Extensions -+ // field is ignored, see ExtraExtensions. -+ Extensions []pkix.Extension -+ // ExtraExtensions contains extensions to be copied, raw, into any -+ // marshaled CRL entries. Values override any extensions that would -+ // otherwise be produced based on the other fields. The ExtraExtensions -+ // field is not populated when parsing CRL entries, see Extensions. -+ ExtraExtensions []pkix.Extension -+} -+ -+// RevocationList represents a Certificate Revocation List (CRL) as specified -+// by RFC 5280. -+type RevocationList struct { -+ // Raw contains the complete ASN.1 DER content of the CRL (tbsCertList, -+ // signatureAlgorithm, and signatureValue.) -+ Raw []byte -+ // RawTBSRevocationList contains just the tbsCertList portion of the ASN.1 -+ // DER. -+ RawTBSRevocationList []byte -+ // RawIssuer contains the DER encoded Issuer. -+ RawIssuer []byte -+ -+ // Issuer contains the DN of the issuing certificate. -+ Issuer pkix.Name -+ // AuthorityKeyId is used to identify the public key associated with the -+ // issuing certificate. It is populated from the authorityKeyIdentifier -+ // extension when parsing a CRL. It is ignored when creating a CRL; the -+ // extension is populated from the issuing certificate itself. -+ AuthorityKeyId []byte -+ -+ Signature []byte -+ // SignatureAlgorithm is used to determine the signature algorithm to be -+ // used when signing the CRL. If 0 the default algorithm for the signing -+ // key will be used. -+ SignatureAlgorithm SignatureAlgorithm -+ -+ // RevokedCertificateEntries represents the revokedCertificates sequence in -+ // the CRL. It is used when creating a CRL and also populated when parsing a -+ // CRL. When creating a CRL, it may be empty or nil, in which case the -+ // revokedCertificates ASN.1 sequence will be omitted from the CRL entirely. -+ RevokedCertificateEntries []RevocationListEntry -+ -+ // RevokedCertificates is used to populate the revokedCertificates -+ // sequence in the CRL if RevokedCertificateEntries is empty. It may be empty -+ // or nil, in which case an empty CRL will be created. -+ // -+ // Deprecated: Use RevokedCertificateEntries instead. -+ RevokedCertificates []pkix.RevokedCertificate -+ -+ // Number is used to populate the X.509 v2 cRLNumber extension in the CRL, -+ // which should be a monotonically increasing sequence number for a given -+ // CRL scope and CRL issuer. It is also populated from the cRLNumber -+ // extension when parsing a CRL. -+ Number *big.Int -+ -+ // ThisUpdate is used to populate the thisUpdate field in the CRL, which -+ // indicates the issuance date of the CRL. -+ ThisUpdate time.Time -+ // NextUpdate is used to populate the nextUpdate field in the CRL, which -+ // indicates the date by which the next CRL will be issued. NextUpdate -+ // must be greater than ThisUpdate. -+ NextUpdate time.Time -+ -+ // Extensions contains raw X.509 extensions. When creating a CRL, -+ // the Extensions field is ignored, see ExtraExtensions. -+ Extensions []pkix.Extension -+ -+ // ExtraExtensions contains any additional extensions to add directly to -+ // the CRL. -+ ExtraExtensions []pkix.Extension -+} -+ -+// These structures reflect the ASN.1 structure of X.509 CRLs better than -+// the existing crypto/x509/pkix variants do. These mirror the existing -+// certificate structs in this file. -+// -+// Notably, we include issuer as an asn1.RawValue, mirroring the behavior of -+// tbsCertificate and allowing raw (unparsed) subjects to be passed cleanly. -+type certificateList struct { -+ TBSCertList tbsCertificateList -+ SignatureAlgorithm pkix.AlgorithmIdentifier -+ SignatureValue asn1.BitString -+} -+ -+type tbsCertificateList struct { -+ Raw asn1.RawContent -+ Version int `asn1:"optional,default:0"` -+ Signature pkix.AlgorithmIdentifier -+ Issuer asn1.RawValue -+ ThisUpdate time.Time -+ NextUpdate time.Time `asn1:"optional"` -+ RevokedCertificates []pkix.RevokedCertificate `asn1:"optional"` -+ Extensions []pkix.Extension `asn1:"tag:0,optional,explicit"` -+} -+ -+// CreateRevocationList creates a new X.509 v2 Certificate Revocation List, -+// according to RFC 5280, based on template. -+// -+// The CRL is signed by priv which should be the private key associated with -+// the public key in the issuer certificate. -+// -+// The issuer may not be nil, and the crlSign bit must be set in KeyUsage in -+// order to use it as a CRL issuer. -+// -+// The issuer distinguished name CRL field and authority key identifier -+// extension are populated using the issuer certificate. issuer must have -+// SubjectKeyId set. -+func CreateRevocationList(rand io.Reader, template *RevocationList, issuer *Certificate, priv crypto.Signer) ([]byte, error) { -+ if template == nil { -+ return nil, errors.New("x509: template can not be nil") -+ } -+ if issuer == nil { -+ return nil, errors.New("x509: issuer can not be nil") -+ } -+ if (issuer.KeyUsage & KeyUsageCRLSign) == 0 { -+ return nil, errors.New("x509: issuer must have the crlSign key usage bit set") -+ } -+ if len(issuer.SubjectKeyId) == 0 { -+ return nil, errors.New("x509: issuer certificate doesn't contain a subject key identifier") -+ } -+ if template.NextUpdate.Before(template.ThisUpdate) { -+ return nil, errors.New("x509: template.ThisUpdate is after template.NextUpdate") -+ } -+ if template.Number == nil { -+ return nil, errors.New("x509: template contains nil Number field") -+ } -+ -+ hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(priv.Public(), template.SignatureAlgorithm) -+ if err != nil { -+ return nil, err -+ } -+ -+ var revokedCerts []pkix.RevokedCertificate -+ // Only process the deprecated RevokedCertificates field if it is populated -+ // and the new RevokedCertificateEntries field is not populated. -+ if len(template.RevokedCertificates) > 0 && len(template.RevokedCertificateEntries) == 0 { -+ // Force revocation times to UTC per RFC 5280. -+ revokedCerts = make([]pkix.RevokedCertificate, len(template.RevokedCertificates)) -+ for i, rc := range template.RevokedCertificates { -+ rc.RevocationTime = rc.RevocationTime.UTC() -+ revokedCerts[i] = rc -+ } -+ } else { -+ // Convert the ReasonCode field to a proper extension, and force revocation -+ // times to UTC per RFC 5280. -+ revokedCerts = make([]pkix.RevokedCertificate, len(template.RevokedCertificateEntries)) -+ for i, rce := range template.RevokedCertificateEntries { -+ if rce.SerialNumber == nil { -+ return nil, errors.New("x509: template contains entry with nil SerialNumber field") -+ } -+ if rce.RevocationTime.IsZero() { -+ return nil, errors.New("x509: template contains entry with zero RevocationTime field") -+ } -+ -+ rc := pkix.RevokedCertificate{ -+ SerialNumber: rce.SerialNumber, -+ RevocationTime: rce.RevocationTime.UTC(), -+ } -+ -+ // Copy over any extra extensions, except for a Reason Code extension, -+ // because we'll synthesize that ourselves to ensure it is correct. -+ exts := make([]pkix.Extension, 0, len(rce.ExtraExtensions)) -+ for _, ext := range rce.ExtraExtensions { -+ if ext.Id.Equal(oidExtensionReasonCode) { -+ return nil, errors.New("x509: template contains entry with ReasonCode ExtraExtension; use ReasonCode field instead") -+ } -+ exts = append(exts, ext) -+ } -+ -+ // Only add a reasonCode extension if the reason is non-zero, as per -+ // RFC 5280 Section 5.3.1. -+ if rce.ReasonCode != 0 { -+ reasonBytes, err := asn1.Marshal(asn1.Enumerated(rce.ReasonCode)) -+ if err != nil { -+ return nil, err -+ } -+ -+ exts = append(exts, pkix.Extension{ -+ Id: oidExtensionReasonCode, -+ Value: reasonBytes, -+ }) -+ } -+ -+ if len(exts) > 0 { -+ rc.Extensions = exts -+ } -+ revokedCerts[i] = rc -+ } -+ } -+ -+ aki, err := asn1.Marshal(authKeyId{Id: issuer.SubjectKeyId}) -+ if err != nil { -+ return nil, err -+ } -+ -+ if numBytes := template.Number.Bytes(); len(numBytes) > 20 || (len(numBytes) == 20 && numBytes[0]&0x80 != 0) { -+ return nil, errors.New("x509: CRL number exceeds 20 octets") -+ } -+ crlNum, err := asn1.Marshal(template.Number) -+ if err != nil { -+ return nil, err -+ } -+ -+ // Correctly use the issuer's subject sequence if one is specified. -+ issuerSubject, err := subjectBytes(issuer) -+ if err != nil { -+ return nil, err -+ } -+ -+ tbsCertList := tbsCertificateList{ -+ Version: 1, // v2 -+ Signature: signatureAlgorithm, -+ Issuer: asn1.RawValue{FullBytes: issuerSubject}, -+ ThisUpdate: template.ThisUpdate.UTC(), -+ NextUpdate: template.NextUpdate.UTC(), -+ Extensions: []pkix.Extension{ -+ { -+ Id: oidExtensionAuthorityKeyId, -+ Value: aki, -+ }, -+ { -+ Id: oidExtensionCRLNumber, -+ Value: crlNum, -+ }, -+ }, -+ } -+ if len(revokedCerts) > 0 { -+ tbsCertList.RevokedCertificates = revokedCerts -+ } -+ -+ if len(template.ExtraExtensions) > 0 { -+ tbsCertList.Extensions = append(tbsCertList.Extensions, template.ExtraExtensions...) -+ } -+ -+ tbsCertListContents, err := asn1.Marshal(tbsCertList) -+ if err != nil { -+ return nil, err -+ } -+ -+ // Optimization to only marshal this struct once, when signing and -+ // then embedding in certificateList below. -+ tbsCertList.Raw = tbsCertListContents -+ -+ input := tbsCertListContents -+ if hashFunc != 0 { -+ h := hashFunc.New() -+ h.Write(tbsCertListContents) -+ input = h.Sum(nil) -+ } -+ var signerOpts crypto.SignerOpts = hashFunc -+ if template.SignatureAlgorithm.isRSAPSS() { -+ signerOpts = &rsa.PSSOptions{ -+ SaltLength: rsa.PSSSaltLengthEqualsHash, -+ Hash: hashFunc, -+ } -+ } -+ -+ signature, err := priv.Sign(rand, input, signerOpts) -+ if err != nil { -+ return nil, err -+ } -+ -+ return asn1.Marshal(certificateList{ -+ TBSCertList: tbsCertList, -+ SignatureAlgorithm: signatureAlgorithm, -+ SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, -+ }) -+} -+ -+// CheckSignatureFrom verifies that the signature on rl is a valid signature -+// from issuer. -+func (rl *RevocationList) CheckSignatureFrom(parent *Certificate) error { -+ if parent.Version == 3 && !parent.BasicConstraintsValid || -+ parent.BasicConstraintsValid && !parent.IsCA { -+ return ConstraintViolationError{} -+ } -+ -+ if parent.KeyUsage != 0 && parent.KeyUsage&KeyUsageCRLSign == 0 { -+ return ConstraintViolationError{} -+ } -+ -+ if parent.PublicKeyAlgorithm == UnknownPublicKeyAlgorithm { -+ return ErrUnsupportedAlgorithm -+ } -+ -+ return parent.CheckSignature(rl.SignatureAlgorithm, rl.RawTBSRevocationList, rl.Signature) -+} ->>>>>>> 70a351c141 (wip) -======= ->>>>>>> 80d9391199 (wip) -diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go -index 0c2cbf3182..e01c24292e 100644 ---- a/src/crypto/x509/x509_test.go -+++ b/src/crypto/x509/x509_test.go -@@ -12,7 +12,7 @@ import ( - "crypto/ecdsa" - "crypto/ed25519" - "crypto/elliptic" -- "crypto/internal/boring" -+ boring "crypto/internal/backend" - "crypto/internal/backend/boringtest" - "crypto/rand" - "crypto/rsa" -@@ -653,7 +653,7 @@ func TestCreateSelfSignedCertificate(t *testing.T) { - extraExtensionData := []byte("extra extension") -<<<<<<< HEAD - -======= - ->>>>>>> 0023bf4c7a (rebase) - for _, test := range tests { -- if boring.Enabled && test.sigAlgo.isRSAPSS() { -+ if boring.Enabled() && test.sigAlgo.isRSAPSS() { - key, _ := test.priv.(*rsa.PrivateKey) - if key.PublicKey.N.BitLen() < 2048 { - t.Logf("skipping short key with BoringCrypto: %d", key.PublicKey.N.BitLen()) -@@ -3716,7 +3716,7 @@ func TestRevocationListCheckSignatureFrom(t *testing.T) { - var testCurve elliptic.Curve - // If OpenSSL supports P224, use the default upstream behavior, - // otherwise test with P384 -- if !boring.Enabled || boringtest.Supports(t, "CurveP224") { -+ if !boring.Enabled() || boringtest.Supports(t, "CurveP224") { - testCurve = elliptic.P224() - } else { - testCurve = elliptic.P384() -diff --git a/src/go.mod b/src/go.mod -<<<<<<< HEAD -index 3b24053b94..c4bc3c1e96 100644 -======= -<<<<<<< HEAD -<<<<<<< HEAD -index 25829e17f2..e19ef07e84 100644 -======= -index 25829e17f2..d8be04ccd3 100644 ->>>>>>> 0023bf4c7a (rebase) -======= -index 25829e17f2..c6a0d5eb02 100644 ->>>>>>> 0b8240ca10 (support opensslv2, update strict fips checks) ->>>>>>> 86a5d8fade (Support openssl/v2 module) ---- a/src/go.mod -+++ b/src/go.mod -@@ -3,6 +3,7 @@ module std - go 1.21 -<<<<<<< HEAD - - require ( -+ github.com/golang-fips/openssl-fips v0.0.0-20230801192317-b175be2ccd46 -======= - - require ( -<<<<<<< HEAD -+ github.com/golang-fips/openssl/v2 v2.0.0-rc.2.0.20230807174113-66d32c6ed196 ->>>>>>> 0023bf4c7a (rebase) -======= -+ github.com/golang-fips/openssl/v2 v2.0.0-rc.2.0.20230825145541-7544e9a0711b ->>>>>>> 0b8240ca10 (support opensslv2, update strict fips checks) - golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d - golang.org/x/net v0.12.1-0.20231027154334-5ca955b1789c - ) -diff --git a/src/go.sum b/src/go.sum -<<<<<<< HEAD -index caf8ff010d..16a5d8c7da 100644 -======= -<<<<<<< HEAD -<<<<<<< HEAD -index e474b8be31..0dab3e78f9 100644 ->>>>>>> 86a5d8fade (Support openssl/v2 module) ---- a/src/go.sum -+++ b/src/go.sum -@@ -1,3 +1,5 @@ -+github.com/golang-fips/openssl-fips v0.0.0-20230801192317-b175be2ccd46 h1:1oaM7kpYYlqwc6sIROINgj5fUW4CGZGEBwfzIc+TnJI= -+github.com/golang-fips/openssl-fips v0.0.0-20230801192317-b175be2ccd46/go.mod h1:V2IU8imz/VkScnIbTOrdYsZ5R88ZFypCE0LzhRJ3HsI= - golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d h1:LiA25/KWKuXfIq5pMIBq1s5hz3HQxhJJSu/SUGlD+SM= - golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= - golang.org/x/net v0.12.1-0.20231027154334-5ca955b1789c h1:d+VvAxu4S13DWtf73R5eY//VaCk3aUcVdyYjM1SX7zw= -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/LICENSE b/src/vendor/github.com/golang-fips/openssl-fips/LICENSE -new file mode 100644 -index 0000000000..97e8515401 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/LICENSE -======= -index e474b8be31..3f33a5d91d 100644 -======= -index e474b8be31..0c87e9b273 100644 ->>>>>>> 0b8240ca10 (support opensslv2, update strict fips checks) ---- a/src/go.sum -+++ b/src/go.sum -@@ -1,3 +1,5 @@ -+github.com/golang-fips/openssl/v2 v2.0.0-rc.2.0.20230825145541-7544e9a0711b h1:tMz1iZ8n4ppQW9SOPzA1/7TcI5sixnWGSOra+R1qiic= -+github.com/golang-fips/openssl/v2 v2.0.0-rc.2.0.20230825145541-7544e9a0711b/go.mod h1:7tuBqX2Zov8Yq5mJ2yzlKhpnxOnWyEzi38AzeWRuQdg= - golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d h1:LiA25/KWKuXfIq5pMIBq1s5hz3HQxhJJSu/SUGlD+SM= - golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= - golang.org/x/net v0.12.1-0.20230712162946-57553cbff163 h1:1EDKNuaCsog7zGLEml1qRuO4gt23jORUQX2f0IKZ860= -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/.gitleaks.toml b/src/vendor/github.com/golang-fips/openssl/v2/.gitleaks.toml -new file mode 100644 -index 0000000000..aed2e22df2 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/.gitleaks.toml -@@ -0,0 +1,9 @@ -+# -+# GitLeaks Repo Specific Configuration -+# -+# This allowlist is used to ignore false positives during secret scans. -+ -+[allowlist] -+paths = [ -+ 'ecdh_test.go', -+] -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/LICENSE b/src/vendor/github.com/golang-fips/openssl/v2/LICENSE -new file mode 100644 -index 0000000000..97e8515401 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/LICENSE ->>>>>>> 0023bf4c7a (rebase) -@@ -0,0 +1,20 @@ -+The MIT License (MIT) -+ -+Copyright (c) 2022 The Golang FIPS Authors -+ -+Permission is hereby granted, free of charge, to any person obtaining a copy of -+this software and associated documentation files (the "Software"), to deal in -+the Software without restriction, including without limitation the rights to -+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -+the Software, and to permit persons to whom the Software is furnished to do so, -+subject to the following conditions: -+ -+The above copyright notice and this permission notice shall be included in all -+copies or substantial portions of the Software. -+ -+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -\ No newline at end of file -<<<<<<< HEAD -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/aes.go b/src/vendor/github.com/golang-fips/openssl-fips/openssl/aes.go -new file mode 100644 -index 0000000000..079fc3c4ad ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/aes.go -@@ -0,0 +1,516 @@ -+// 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 -+// +build linux,!android,!cmd_go_bootstrap,!msan,!no_openssl -======= -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/README.md b/src/vendor/github.com/golang-fips/openssl/v2/README.md -new file mode 100644 -index 0000000000..e12474e6b5 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/README.md -@@ -0,0 +1,62 @@ -+# Go OpenSSL bindings for FIPS compliance -+ -+[![Go Reference](https://pkg.go.dev/badge/github.com/golang-fips/openssl.svg)](https://pkg.go.dev/github.com/golang-fips/openssl) -+ -+The `openssl` package implements Go crypto primitives using OpenSSL shared libraries and cgo. When configured correctly, OpenSSL can be executed in FIPS mode, making the `openssl` package FIPS compliant. -+ -+The `openssl` package is designed to be used as a drop-in replacement for the [boring](https://pkg.go.dev/crypto/internal/boring) package in order to facilitate integrating `openssl` inside a forked Go toolchain. -+ -+## Disclaimer -+ -+A program directly or indirectly using this package in FIPS mode can claim it is using a FIPS-certified cryptographic module (OpenSSL), but it can't claim the program as a whole is FIPS certified without passing the certification process, nor claim it is FIPS compliant without ensuring all crypto APIs and workflows are implemented in a FIPS-compliant manner. -+ -+## Background -+ -+FIPS 140-2 is a U.S. government computer security standard used to approve cryptographic modules. FIPS compliance may come up when working with U.S. government and other regulated industries. -+ -+### Go FIPS compliance -+ -+The Go `crypto` package is not FIPS certified, and the Go team has stated that it won't be, e.g. in [golang/go/issues/21734](https://github.com/golang/go/issues/21734#issuecomment-326980213) Adam Langley says: -+ -+> The status of FIPS 140 for Go itself remains "no plans, basically zero chance". -+ -+On the other hand, Google maintains a branch that uses cgo and BoringSSL to implement various crypto primitives: https://github.com/golang/go/blob/dev.boringcrypto/README.boringcrypto.md. As BoringSSL is FIPS 140-2 certified, an application using that branch is more likely to be FIPS 140-2 compliant, yet Google does not provide any liability about the suitability of this code in relation to the FIPS 140-2 standard. -+ -+## Features -+ -+### Multiple OpenSSL versions supported -+ -+The `openssl` package has support for multiple OpenSSL versions, namely 1.0.2, 1.1.0, 1.1.1 and 3.0.x. -+ -+All supported OpenSSL versions pass a small set of automatic tests that ensure they can be built and that there are no major regressions. -+These tests do not validate the cryptographic correctness of the `openssl` package. -+ -+On top of that, the [golang-fips Go fork](https://github.com/golang-fips/go) -maintained by Red Hat- and the [Microsoft Go fork](https://github.com/microsoft/go), tests a subset of the supported OpenSSL versions when integrated with the Go `crypto` package. -+These tests are much more exhaustive and validate a specific OpenSSL version can produce working applications. -+ -+### Building without OpenSSL headers -+ -+The `openssl` package does not use any symbol from the OpenSSL headers. There is no need that have them installed to build an application which imports this library. -+ -+The CI tests in this repository verify that all the functions and constants defined in our headers match the ones in the OpenSSL headers for every supported OpenSSL version. -+ -+### Portable OpenSSL -+ -+The OpenSSL bindings are implemented in such a way that the OpenSSL version available when building a program does not have to match with the OpenSSL version used when running it. -+In fact, OpenSSL doesn't need to be present on the builder. -+For example, using the `openssl` package and `go build .` on a Windows host with `GOOS=linux` can produce a program that successfully runs on Linux and uses OpenSSL. -+ -+This feature does not require any additional configuration, but it only works with OpenSSL versions known and supported by the Go toolchain that integrates the `openssl` package. -+ -+## Limitations -+ -+- Only Unix, Unix-like and Windows platforms are supported. -+- The build must set `CGO_ENABLED=1`. -+ -+## Acknowledgements -+ -+The work done to support FIPS compatibility mode leverages code and ideas from other open-source projects: -+ -+- All crypto stubs are a mirror of Google's [dev.boringcrypto branch](https://github.com/golang/go/tree/dev.boringcrypto) and the release branch ports of that branch. -+- The mapping between BoringSSL and OpenSSL APIs is taken from the former [Red Hat Go fork](https://pagure.io/go). -+- The portable OpenSSL implementation is ported from Microsoft's [.NET runtime](https://github.com/dotnet/runtime) cryptography module. -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/aes.go b/src/vendor/github.com/golang-fips/openssl/v2/aes.go -new file mode 100644 -index 0000000000..a7c3aea683 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/aes.go -<<<<<<< HEAD -@@ -0,0 +1,549 @@ -+//go:build linux && !cmd_go_bootstrap ->>>>>>> 0023bf4c7a (rebase) -======= -@@ -0,0 +1,552 @@ -+//go:build !cmd_go_bootstrap ->>>>>>> 0b8240ca10 (support opensslv2, update strict fips checks) -+ -+package openssl -+ -+// #include "goopenssl.h" -+import "C" -+import ( -+ "crypto/cipher" -<<<<<<< HEAD -+ "errors" -+ "runtime" -+ "strconv" -+ "unsafe" -+) -+ -======= -+ "encoding/binary" -+ "errors" -+ "runtime" -+ "strconv" -+ "sync" -+ "unsafe" -+) -+ -+type cipherKind int8 -+ -+const ( -+ cipherAES128_ECB cipherKind = iota -+ cipherAES192_ECB -+ cipherAES256_ECB -+ cipherAES128_CBC -+ cipherAES192_CBC -+ cipherAES256_CBC -+ cipherAES128_CTR -+ cipherAES192_CTR -+ cipherAES256_CTR -+ cipherAES128_GCM -+ cipherAES192_GCM -+ cipherAES256_GCM -+) -+ -+// cacheCipher is a cache of cipherKind to GO_EVP_CIPHER_PTR. -+var cacheCipher sync.Map -+ -+// newCipher returns a cipher object for the given k. -+func newCipher(k cipherKind) (cipher C.GO_EVP_CIPHER_PTR) { -+ if v, ok := cacheCipher.Load(k); ok { -+ return v.(C.GO_EVP_CIPHER_PTR) -+ } -+ defer func() { -+ if cipher != nil && vMajor == 3 { -+ // On OpenSSL 3, directly operating on a EVP_CIPHER object -+ // not created by EVP_CIPHER has negative performance -+ // implications, as cipher operations will have -+ // to fetch it on every call. Better to just fetch it once here. -+ cipher = C.go_openssl_EVP_CIPHER_fetch(nil, C.go_openssl_EVP_CIPHER_get0_name(cipher), nil) -+ } -+ cacheCipher.Store(k, cipher) -+ }() -+ switch k { -+ case cipherAES128_CBC: -+ cipher = C.go_openssl_EVP_aes_128_cbc() -+ case cipherAES192_CBC: -+ cipher = C.go_openssl_EVP_aes_192_cbc() -+ case cipherAES256_CBC: -+ cipher = C.go_openssl_EVP_aes_256_cbc() -+ case cipherAES128_ECB: -+ cipher = C.go_openssl_EVP_aes_128_ecb() -+ case cipherAES192_ECB: -+ cipher = C.go_openssl_EVP_aes_192_ecb() -+ case cipherAES256_ECB: -+ cipher = C.go_openssl_EVP_aes_256_ecb() -+ case cipherAES128_CTR: -+ cipher = C.go_openssl_EVP_aes_128_ctr() -+ case cipherAES192_CTR: -+ cipher = C.go_openssl_EVP_aes_192_ctr() -+ case cipherAES256_CTR: -+ cipher = C.go_openssl_EVP_aes_256_ctr() -+ case cipherAES128_GCM: -+ cipher = C.go_openssl_EVP_aes_128_gcm() -+ case cipherAES192_GCM: -+ cipher = C.go_openssl_EVP_aes_192_gcm() -+ case cipherAES256_GCM: -+ cipher = C.go_openssl_EVP_aes_256_gcm() -+ } -+ return cipher -+} -+ ->>>>>>> 0023bf4c7a (rebase) -+type aesKeySizeError int -+ -+func (k aesKeySizeError) Error() string { -+ return "crypto/aes: invalid key size " + strconv.Itoa(int(k)) -+} -+ -+const aesBlockSize = 16 -+ -+type aesCipher struct { -+ key []byte -<<<<<<< HEAD -+ enc_ctx *C.EVP_CIPHER_CTX -+ dec_ctx *C.EVP_CIPHER_CTX -+ cipher *C.EVP_CIPHER -======= -+ enc_ctx C.GO_EVP_CIPHER_CTX_PTR -+ dec_ctx C.GO_EVP_CIPHER_CTX_PTR -+ kind cipherKind ->>>>>>> 0023bf4c7a (rebase) -+} -+ -+type extraModes interface { -+ // Copied out of crypto/aes/modes.go. -+ NewCBCEncrypter(iv []byte) cipher.BlockMode -+ NewCBCDecrypter(iv []byte) cipher.BlockMode -+ NewCTR(iv []byte) cipher.Stream -+ NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) -+ -+ // Invented for BoringCrypto. -+ NewGCMTLS() (cipher.AEAD, error) -+} -+ -+var _ extraModes = (*aesCipher)(nil) -+ -+func NewAESCipher(key []byte) (cipher.Block, error) { -+ c := &aesCipher{key: make([]byte, len(key))} -+ copy(c.key, key) -+ -+ switch len(c.key) * 8 { -+ case 128: -<<<<<<< HEAD -+ c.cipher = C._goboringcrypto_EVP_aes_128_ecb() -+ case 192: -+ c.cipher = C._goboringcrypto_EVP_aes_192_ecb() -+ case 256: -+ c.cipher = C._goboringcrypto_EVP_aes_256_ecb() -======= -+ c.kind = cipherAES128_ECB -+ case 192: -+ c.kind = cipherAES192_ECB -+ case 256: -+ c.kind = cipherAES256_ECB ->>>>>>> 0023bf4c7a (rebase) -+ default: -+ return nil, errors.New("crypto/cipher: Invalid key size") -+ } -+ -+ runtime.SetFinalizer(c, (*aesCipher).finalize) -+ -+ return c, nil -+} -+ -+func (c *aesCipher) finalize() { -+ if c.enc_ctx != nil { -<<<<<<< HEAD -+ C._goboringcrypto_EVP_CIPHER_CTX_free(c.enc_ctx) -+ } -+ if c.dec_ctx != nil { -+ C._goboringcrypto_EVP_CIPHER_CTX_free(c.dec_ctx) -======= -+ C.go_openssl_EVP_CIPHER_CTX_free(c.enc_ctx) -+ } -+ if c.dec_ctx != nil { -+ C.go_openssl_EVP_CIPHER_CTX_free(c.dec_ctx) ->>>>>>> 0023bf4c7a (rebase) -+ } -+} -+ -+func (c *aesCipher) BlockSize() int { return aesBlockSize } -+ -+func (c *aesCipher) Encrypt(dst, src []byte) { -+ if len(src) < aesBlockSize { -+ panic("crypto/aes: input not full block") -+ } -+ if len(dst) < aesBlockSize { -+ panic("crypto/aes: output not full block") -+ } -+ // Only check for overlap between the parts of src and dst that will actually be used. -+ // This matches Go standard library behavior. -+ if inexactOverlap(dst[:aesBlockSize], src[:aesBlockSize]) { -+ panic("crypto/cipher: invalid buffer overlap") -+ } -+ if c.enc_ctx == nil { -<<<<<<< HEAD -+ c.enc_ctx = C._goboringcrypto_EVP_CIPHER_CTX_new() -+ if c.enc_ctx == nil { -+ panic("cipher: unable to create EVP cipher ctx") -+ } -+ -+ k := (*C.uchar)(unsafe.Pointer(&c.key[0])) -+ -+ if C.int(1) != C._goboringcrypto_EVP_CipherInit_ex(c.enc_ctx, c.cipher, nil, k, nil, C.GO_AES_ENCRYPT) { -+ panic("cipher: unable to initialize EVP cipher ctx") -+ } -+ } -+ -+ outlen := C.int(0) -+ C._goboringcrypto_EVP_CipherUpdate(c.enc_ctx, (*C.uchar)(unsafe.Pointer(&dst[0])), &outlen, (*C.uchar)(unsafe.Pointer(&src[0])), C.int(aesBlockSize)) -======= -+ var err error -+ c.enc_ctx, err = newCipherCtx(c.kind, C.GO_AES_ENCRYPT, c.key, nil) -+ if err != nil { -+ panic(err) -+ } -+ } -+ -+ if C.go_openssl_EVP_EncryptUpdate_wrapper(c.enc_ctx, base(dst), base(src), aesBlockSize) != 1 { -+ panic("crypto/cipher: EncryptUpdate failed") -+ } ->>>>>>> 0023bf4c7a (rebase) -+ runtime.KeepAlive(c) -+} -+ -+func (c *aesCipher) Decrypt(dst, src []byte) { -+ if len(src) < aesBlockSize { -+ panic("crypto/aes: input not full block") -+ } -+ if len(dst) < aesBlockSize { -+ panic("crypto/aes: output not full block") -+ } -+ // Only check for overlap between the parts of src and dst that will actually be used. -+ // This matches Go standard library behavior. -+ if inexactOverlap(dst[:aesBlockSize], src[:aesBlockSize]) { -+ panic("crypto/cipher: invalid buffer overlap") -+ } -+ if c.dec_ctx == nil { -<<<<<<< HEAD -+ c.dec_ctx = C._goboringcrypto_EVP_CIPHER_CTX_new() -+ if c.dec_ctx == nil { -+ panic("cipher: unable to create EVP cipher ctx") -+ } -+ -+ k := (*C.uchar)(unsafe.Pointer(&c.key[0])) -+ -+ if C.int(1) != C._goboringcrypto_EVP_CipherInit_ex(c.dec_ctx, c.cipher, nil, k, nil, C.GO_AES_DECRYPT) { -+ panic("cipher: unable to initialize EVP cipher ctx") -+ } -+ } -+ // Workaround - padding detection is broken but we don't need it -+ // since we check for full blocks -+ if C._goboringcrypto_EVP_CIPHER_CTX_set_padding(c.dec_ctx, 0) != 1 { -+ panic("crypto/cipher: could not disable cipher padding") -+ } -+ outlen := C.int(0) -+ C._goboringcrypto_EVP_CipherUpdate(c.dec_ctx, (*C.uchar)(unsafe.Pointer(&dst[0])), &outlen, (*C.uchar)(unsafe.Pointer(&src[0])), C.int(aesBlockSize)) -======= -+ var err error -+ c.dec_ctx, err = newCipherCtx(c.kind, C.GO_AES_DECRYPT, c.key, nil) -+ if err != nil { -+ panic(err) -+ } -+ if C.go_openssl_EVP_CIPHER_CTX_set_padding(c.dec_ctx, 0) != 1 { -+ panic("crypto/cipher: could not disable cipher padding") -+ } -+ } -+ -+ C.go_openssl_EVP_DecryptUpdate_wrapper(c.dec_ctx, base(dst), base(src), aesBlockSize) ->>>>>>> 0023bf4c7a (rebase) -+ runtime.KeepAlive(c) -+} -+ -+type aesCBC struct { -<<<<<<< HEAD -+ key []byte -+ mode C.int -+ iv [aesBlockSize]byte -+ ctx *C.EVP_CIPHER_CTX -======= -+ ctx C.GO_EVP_CIPHER_CTX_PTR ->>>>>>> 0023bf4c7a (rebase) -+} -+ -+func (x *aesCBC) BlockSize() int { return aesBlockSize } -+ -+func (x *aesCBC) CryptBlocks(dst, src []byte) { -+ if inexactOverlap(dst, src) { -+ panic("crypto/cipher: invalid buffer overlap") -+ } -+ if len(src)%aesBlockSize != 0 { -+ panic("crypto/cipher: input not full blocks") -+ } -+ if len(dst) < len(src) { -+ panic("crypto/cipher: output smaller than input") -+ } -+ if len(src) > 0 { -<<<<<<< HEAD -+ outlen := C.int(0) -+ // Workaround - padding detection is broken but we don't need it -+ // since we check for full blocks -+ if C._goboringcrypto_EVP_CIPHER_CTX_set_padding(x.ctx, 0) != 1 { -+ panic("crypto/cipher: could not disable cipher padding") -+ } -+ if C._goboringcrypto_EVP_CipherUpdate( -+ x.ctx, -+ base(dst), &outlen, -+ base(src), C.int(len(src)), -+ ) != 1 { -======= -+ if C.go_openssl_EVP_CipherUpdate_wrapper(x.ctx, base(dst), base(src), C.int(len(src))) != 1 { ->>>>>>> 0023bf4c7a (rebase) -+ panic("crypto/cipher: CipherUpdate failed") -+ } -+ runtime.KeepAlive(x) -+ } -+} -+ -+func (x *aesCBC) SetIV(iv []byte) { -+ if len(iv) != aesBlockSize { -+ panic("cipher: incorrect length IV") -+ } -<<<<<<< HEAD -+ copy(x.iv[:], iv) -+ if C.int(1) != C._goboringcrypto_EVP_CipherInit_ex(x.ctx, nil, nil, nil, (*C.uchar)(unsafe.Pointer(&x.iv[0])), -1) { -======= -+ if C.go_openssl_EVP_CipherInit_ex(x.ctx, nil, nil, nil, base(iv), -1) != 1 { ->>>>>>> 0023bf4c7a (rebase) -+ panic("cipher: unable to initialize EVP cipher ctx") -+ } -+} -+ -+func (c *aesCipher) NewCBCEncrypter(iv []byte) cipher.BlockMode { -<<<<<<< HEAD -+ x := &aesCBC{key: c.key, mode: C.GO_AES_ENCRYPT} -+ copy(x.iv[:], iv) -+ -+ x.ctx = C._goboringcrypto_EVP_CIPHER_CTX_new() -+ if x.ctx == nil { -+ panic("cipher: unable to create EVP cipher ctx") -+ } -+ -+ k := (*C.uchar)(unsafe.Pointer(&x.key[0])) -+ vec := (*C.uchar)(unsafe.Pointer(&x.iv[0])) -+ -+ var cipher *C.EVP_CIPHER -+ switch len(c.key) * 8 { -+ case 128: -+ cipher = C._goboringcrypto_EVP_aes_128_cbc() -+ case 192: -+ cipher = C._goboringcrypto_EVP_aes_192_cbc() -+ case 256: -+ cipher = C._goboringcrypto_EVP_aes_256_cbc() -+ default: -+ panic("crypto/boring: unsupported key length") -+ } -+ if C.int(1) != C._goboringcrypto_EVP_CipherInit_ex(x.ctx, cipher, nil, k, vec, x.mode) { -+ panic("cipher: unable to initialize EVP cipher ctx") -======= -+ x := new(aesCBC) -+ -+ var cipher cipherKind -+ switch len(c.key) * 8 { -+ case 128: -+ cipher = cipherAES128_CBC -+ case 192: -+ cipher = cipherAES192_CBC -+ case 256: -+ cipher = cipherAES256_CBC -+ default: -+ panic("openssl: unsupported key length") -+ } -+ var err error -+ x.ctx, err = newCipherCtx(cipher, C.GO_AES_ENCRYPT, c.key, iv) -+ if err != nil { -+ panic(err) ->>>>>>> 0023bf4c7a (rebase) -+ } -+ -+ runtime.SetFinalizer(x, (*aesCBC).finalize) -+ -<<<<<<< HEAD -======= -+ if C.go_openssl_EVP_CIPHER_CTX_set_padding(x.ctx, 0) != 1 { -+ panic("cipher: unable to set padding") -+ } ->>>>>>> 0023bf4c7a (rebase) -+ return x -+} -+ -+func (c *aesCBC) finalize() { -<<<<<<< HEAD -+ C._goboringcrypto_EVP_CIPHER_CTX_free(c.ctx) -+} -+ -+func (c *aesCipher) NewCBCDecrypter(iv []byte) cipher.BlockMode { -+ x := &aesCBC{key: c.key, mode: C.GO_AES_DECRYPT} -+ copy(x.iv[:], iv) -+ -+ x.ctx = C._goboringcrypto_EVP_CIPHER_CTX_new() -+ if x.ctx == nil { -+ panic("cipher: unable to create EVP cipher ctx") -+ } -+ -+ k := (*C.uchar)(unsafe.Pointer(&x.key[0])) -+ vec := (*C.uchar)(unsafe.Pointer(&x.iv[0])) -+ -+ var cipher *C.EVP_CIPHER -+ switch len(c.key) * 8 { -+ case 128: -+ cipher = C._goboringcrypto_EVP_aes_128_cbc() -+ case 192: -+ cipher = C._goboringcrypto_EVP_aes_192_cbc() -+ case 256: -+ cipher = C._goboringcrypto_EVP_aes_256_cbc() -+ default: -+ panic("crypto/boring: unsupported key length") -+ } -+ if C.int(1) != C._goboringcrypto_EVP_CipherInit_ex(x.ctx, cipher, nil, k, vec, x.mode) { -+ panic("cipher: unable to initialize EVP cipher ctx") -+ } -+ if C.int(1) != C._goboringcrypto_EVP_CIPHER_CTX_set_padding(x.ctx, 0) { -+ panic("cipher: unable to set padding") -+ } -+ -+ runtime.SetFinalizer(x, (*aesCBC).finalize) -======= -+ C.go_openssl_EVP_CIPHER_CTX_free(c.ctx) -+} -+ -+func (c *aesCipher) NewCBCDecrypter(iv []byte) cipher.BlockMode { -+ x := new(aesCBC) -+ -+ var cipher cipherKind -+ switch len(c.key) * 8 { -+ case 128: -+ cipher = cipherAES128_CBC -+ case 192: -+ cipher = cipherAES192_CBC -+ case 256: -+ cipher = cipherAES256_CBC -+ default: -+ panic("openssl: unsupported key length") -+ } -+ -+ var err error -+ x.ctx, err = newCipherCtx(cipher, C.GO_AES_DECRYPT, c.key, iv) -+ if err != nil { -+ panic(err) -+ } -+ -+ runtime.SetFinalizer(x, (*aesCBC).finalize) -+ -+ if C.go_openssl_EVP_CIPHER_CTX_set_padding(x.ctx, 0) != 1 { -+ panic("cipher: unable to set padding") -+ } ->>>>>>> 0023bf4c7a (rebase) -+ return x -+} -+ -+type aesCTR struct { -<<<<<<< HEAD -+ key []byte -+ iv [aesBlockSize]byte -+ ctx *C.EVP_CIPHER_CTX -+ num C.uint -+ ecount_buf [16]C.uint8_t -======= -+ ctx C.GO_EVP_CIPHER_CTX_PTR ->>>>>>> 0023bf4c7a (rebase) -+} -+ -+func (x *aesCTR) XORKeyStream(dst, src []byte) { -+ if inexactOverlap(dst, src) { -+ panic("crypto/cipher: invalid buffer overlap") -+ } -+ if len(dst) < len(src) { -+ panic("crypto/cipher: output smaller than input") -+ } -+ if len(src) == 0 { -+ return -+ } -<<<<<<< HEAD -+ C._goboringcrypto_EVP_AES_ctr128_enc( -+ x.ctx, -+ (*C.uint8_t)(unsafe.Pointer(&src[0])), -+ (*C.uint8_t)(unsafe.Pointer(&dst[0])), -+ C.size_t(len(src))) -======= -+ if C.go_openssl_EVP_EncryptUpdate_wrapper(x.ctx, base(dst), base(src), C.int(len(src))) != 1 { -+ panic("crypto/cipher: EncryptUpdate failed") -+ } ->>>>>>> 0023bf4c7a (rebase) -+ runtime.KeepAlive(x) -+} -+ -+func (c *aesCipher) NewCTR(iv []byte) cipher.Stream { -<<<<<<< HEAD -+ x := &aesCTR{key: c.key} -+ copy(x.iv[:], iv) -+ -+ x.ctx = C._goboringcrypto_EVP_CIPHER_CTX_new() -+ if x.ctx == nil { -+ panic("cipher: unable to create EVP cipher ctx") -+ } -+ -+ k := (*C.uchar)(unsafe.Pointer(&x.key[0])) -+ vec := (*C.uchar)(unsafe.Pointer(&x.iv[0])) -+ -+ switch len(c.key) * 8 { -+ case 128: -+ if C.int(1) != C._goboringcrypto_EVP_EncryptInit_ex(x.ctx, C._goboringcrypto_EVP_aes_128_ctr(), nil, k, vec) { -+ panic("cipher: unable to initialize EVP cipher ctx") -+ } -+ case 192: -+ if C.int(1) != C._goboringcrypto_EVP_EncryptInit_ex(x.ctx, C._goboringcrypto_EVP_aes_192_ctr(), nil, k, vec) { -+ panic("cipher: unable to initialize EVP cipher ctx") -+ } -+ case 256: -+ if C.int(1) != C._goboringcrypto_EVP_EncryptInit_ex(x.ctx, C._goboringcrypto_EVP_aes_256_ctr(), nil, k, vec) { -+ panic("cipher: unable to initialize EVP cipher ctx") -+ } -======= -+ x := new(aesCTR) -+ -+ var cipher cipherKind -+ switch len(c.key) * 8 { -+ case 128: -+ cipher = cipherAES128_CTR -+ case 192: -+ cipher = cipherAES192_CTR -+ case 256: -+ cipher = cipherAES256_CTR -+ default: -+ panic("openssl: unsupported key length") -+ } -+ var err error -+ x.ctx, err = newCipherCtx(cipher, C.GO_AES_ENCRYPT, c.key, iv) -+ if err != nil { -+ panic(err) ->>>>>>> 0023bf4c7a (rebase) -+ } -+ -+ runtime.SetFinalizer(x, (*aesCTR).finalize) -+ -+ return x -+} -+ -+func (c *aesCTR) finalize() { -<<<<<<< HEAD -+ C._goboringcrypto_EVP_CIPHER_CTX_free(c.ctx) -+} -+ -+type aesGCM struct { -+ key []byte -+ tls bool -+} -+ -+const ( -+ gcmBlockSize = 16 -+ gcmTagSize = 16 -+ gcmStandardNonceSize = 12 -======= -+ C.go_openssl_EVP_CIPHER_CTX_free(c.ctx) -+} -+ -+type aesGCM struct { -+ ctx C.GO_EVP_CIPHER_CTX_PTR -+ tls bool -+ minNextNonce uint64 -+} -+ -+const ( -+ gcmTagSize = 16 -+ gcmStandardNonceSize = 12 -+ gcmTlsAddSize = 13 -+ gcmTlsFixedNonceSize = 4 ->>>>>>> 0023bf4c7a (rebase) -+) -+ -+type aesNonceSizeError int -+ -+func (n aesNonceSizeError) Error() string { -+ return "crypto/aes: invalid GCM nonce size " + strconv.Itoa(int(n)) -+} -+ -+type noGCM struct { -+ cipher.Block -+} -+ -+func (c *aesCipher) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) { -<<<<<<< HEAD -+ if !ExecutingTest() || IsStrictFips() { -+ if nonceSize != gcmStandardNonceSize { -+ return nil, errors.New("crypto/aes: GCM nonce size can't be non-standard") -+ } -+ if tagSize != gcmTagSize { -+ return nil, errors.New("crypto/aes: GCM tag size can't be non-standard") -+ } -+ } else { -+ // Be more lenient if we're running via a test binary so that -+ // we don't have to be as invasive with skipping tests in the standard -+ // library. -+ if nonceSize != gcmStandardNonceSize && tagSize != gcmTagSize { -+ return nil, errors.New("crypto/aes: GCM tag and nonce sizes can't be non-standard at the same time") -+ } -+ // Fall back to standard library for GCM with non-standard nonce or tag size. -+ if nonceSize != gcmStandardNonceSize { -+ return cipher.NewGCMWithNonceSize(&noGCM{c}, nonceSize) -+ } -+ if tagSize != gcmTagSize { -+ return cipher.NewGCMWithTagSize(&noGCM{c}, tagSize) -+ } -======= -+ if nonceSize != gcmStandardNonceSize && tagSize != gcmTagSize { -+ return nil, errors.New("crypto/aes: GCM tag and nonce sizes can't be non-standard at the same time") -+ } -+ // Fall back to standard library for GCM with non-standard nonce or tag size. -+ if nonceSize != gcmStandardNonceSize { -+ return cipher.NewGCMWithNonceSize(&noGCM{c}, nonceSize) -+ } -+ if tagSize != gcmTagSize { -+ return cipher.NewGCMWithTagSize(&noGCM{c}, tagSize) ->>>>>>> 0023bf4c7a (rebase) -+ } -+ return c.newGCM(false) -+} -+ -+// NewGCMTLS returns a GCM cipher specific to TLS -+// and should not be used for non-TLS purposes. -+func NewGCMTLS(c cipher.Block) (cipher.AEAD, error) { -+ return c.(*aesCipher).NewGCMTLS() -+} -+ -+func (c *aesCipher) NewGCMTLS() (cipher.AEAD, error) { -+ return c.newGCM(true) -+} -+ -+func (c *aesCipher) newGCM(tls bool) (cipher.AEAD, error) { -<<<<<<< HEAD -+ keyLen := len(c.key) * 8 -+ -+ if keyLen != 128 && keyLen != 256 { -+ if ExecutingTest() { -+ // Fall back to standard library for GCM with non-standard key size. -+ return cipher.NewGCMWithNonceSize(&noGCM{c}, gcmStandardNonceSize) -+ } -+ // Return error for GCM with non-standard key size. -+ return nil, fail("GCM invoked with non-standard key size") -+ } -+ -+ g := &aesGCM{key: c.key, tls: tls} -+ if g.NonceSize() != gcmStandardNonceSize { -+ panic("boringcrypto: internal confusion about nonce size") -+ } -+ if g.Overhead() != gcmTagSize { -+ panic("boringcrypto: internal confusion about tag size") -+ } -+ -+ return g, nil -+} -+ -======= -+ var cipher cipherKind -+ switch len(c.key) * 8 { -+ case 128: -+ cipher = cipherAES128_GCM -+ case 192: -+ cipher = cipherAES192_GCM -+ case 256: -+ cipher = cipherAES256_GCM -+ default: -+ panic("openssl: unsupported key length") -+ } -+ ctx, err := newCipherCtx(cipher, -1, c.key, nil) -+ if err != nil { -+ return nil, err -+ } -+ g := &aesGCM{ctx: ctx, tls: tls} -+ runtime.SetFinalizer(g, (*aesGCM).finalize) -+ return g, nil -+} -+ -+func (g *aesGCM) finalize() { -+ C.go_openssl_EVP_CIPHER_CTX_free(g.ctx) -+} -+ ->>>>>>> 0023bf4c7a (rebase) -+func (g *aesGCM) NonceSize() int { -+ return gcmStandardNonceSize -+} -+ -+func (g *aesGCM) Overhead() int { -+ return gcmTagSize -+} -+ -<<<<<<< HEAD -+// base returns the address of the underlying array in b, -+// being careful not to panic when b has zero length. -+func base(b []byte) *C.uint8_t { -+ if len(b) == 0 { -+ return nil -+ } -+ return (*C.uint8_t)(unsafe.Pointer(&b[0])) -+} -+ -======= ->>>>>>> 0023bf4c7a (rebase) -+func (g *aesGCM) Seal(dst, nonce, plaintext, additionalData []byte) []byte { -+ if len(nonce) != gcmStandardNonceSize { -+ panic("cipher: incorrect nonce length given to GCM") -+ } -+ if uint64(len(plaintext)) > ((1<<32)-2)*aesBlockSize || len(plaintext)+gcmTagSize < len(plaintext) { -+ panic("cipher: message too large for GCM") -+ } -+ if len(dst)+len(plaintext)+gcmTagSize < len(dst) { -+ panic("cipher: message too large for buffer") -+ } -<<<<<<< HEAD -+ -+ // Make room in dst to append plaintext+overhead. -+ n := len(dst) -+ for cap(dst) < n+len(plaintext)+gcmTagSize { -+ dst = append(dst[:cap(dst)], 0) -+ } -+ dst = dst[:n+len(plaintext)+gcmTagSize] -+ -+ // Check delayed until now to make sure len(dst) is accurate. -+ if inexactOverlap(dst[n:], plaintext) { -+ panic("cipher: invalid buffer overlap") -+ } -+ -+ var ciphertextLen C.size_t -+ -+ if ok := C._goboringcrypto_EVP_CIPHER_CTX_seal( -+ (*C.uint8_t)(unsafe.Pointer(&dst[n])), -+ base(nonce), base(additionalData), C.size_t(len(additionalData)), -+ base(plaintext), C.size_t(len(plaintext)), &ciphertextLen, -+ base(g.key), C.int(len(g.key)*8)); ok != 1 { -+ panic("boringcrypto: EVP_CIPHER_CTX_seal fail") -+ } -+ runtime.KeepAlive(g) -+ -+ if ciphertextLen != C.size_t(len(plaintext)+gcmTagSize) { -+ panic("boringcrypto: [seal] internal confusion about GCM tag size") -+ } -+ return dst[:n+int(ciphertextLen)] -======= -+ if g.tls { -+ if len(additionalData) != gcmTlsAddSize { -+ panic("cipher: incorrect additional data length given to GCM TLS") -+ } -+ // BoringCrypto enforces strictly monotonically increasing explicit nonces -+ // and to fail after 2^64 - 1 keys as per FIPS 140-2 IG A.5, -+ // but OpenSSL does not perform this check, so it is implemented here. -+ const maxUint64 = 1<<64 - 1 -+ counter := binary.BigEndian.Uint64(nonce[gcmTlsFixedNonceSize:]) -+ if counter == maxUint64 { -+ panic("cipher: nonce counter must be less than 2^64 - 1") -+ } -+ if counter < g.minNextNonce { -+ panic("cipher: nonce counter must be strictly monotonically increasing") -+ } -+ defer func() { -+ g.minNextNonce = counter + 1 -+ }() -+ } -+ -+ // Make room in dst to append plaintext+overhead. -+ ret, out := sliceForAppend(dst, len(plaintext)+gcmTagSize) -+ -+ // Check delayed until now to make sure len(dst) is accurate. -+ if inexactOverlap(out, plaintext) { -+ panic("cipher: invalid buffer overlap") -+ } -+ -+ // Encrypt additional data. -+ // When sealing a TLS payload, OpenSSL app sets the additional data using -+ // 'EVP_CIPHER_CTX_ctrl(g.ctx, C.EVP_CTRL_AEAD_TLS1_AAD, C.EVP_AEAD_TLS1_AAD_LEN, base(additionalData))'. -+ // This makes the explicit nonce component to monotonically increase on every Seal operation without -+ // relying in the explicit nonce being securely set externally, -+ // and it also gives some interesting speed gains. -+ // Unfortunately we can't use it because Go expects AEAD.Seal to honor the provided nonce. -+ if C.go_openssl_EVP_CIPHER_CTX_seal_wrapper(g.ctx, base(out), base(nonce), -+ base(plaintext), C.int(len(plaintext)), -+ base(additionalData), C.int(len(additionalData))) != 1 { -+ -+ panic(fail("EVP_CIPHER_CTX_seal")) -+ } -+ runtime.KeepAlive(g) -+ return ret ->>>>>>> 0023bf4c7a (rebase) -+} -+ -+var errOpen = errors.New("cipher: message authentication failed") -+ -+func (g *aesGCM) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { -+ if len(nonce) != gcmStandardNonceSize { -+ panic("cipher: incorrect nonce length given to GCM") -+ } -+ if len(ciphertext) < gcmTagSize { -+ return nil, errOpen -+ } -+ if uint64(len(ciphertext)) > ((1<<32)-2)*aesBlockSize+gcmTagSize { -+ return nil, errOpen -+ } -<<<<<<< HEAD -+ -+ // Make room in dst to append ciphertext without tag. -+ n := len(dst) -+ for cap(dst) < n+len(ciphertext)-gcmTagSize { -+ dst = append(dst[:cap(dst)], 0) -+ } -+ dst = dst[:n+len(ciphertext)-gcmTagSize] -+ -+ // Check delayed until now to make sure len(dst) is accurate. -+ if inexactOverlap(dst[n:], ciphertext) { -+ panic("cipher: invalid buffer overlap") -+ } -+ -+ tag := ciphertext[len(ciphertext)-gcmTagSize:] -+ -+ var outLen C.size_t -+ -+ ok := C._goboringcrypto_EVP_CIPHER_CTX_open( -+ base(ciphertext), C.int(len(ciphertext)-gcmTagSize), -+ base(additionalData), C.int(len(additionalData)), -+ base(tag), base(g.key), C.int(len(g.key)*8), -+ base(nonce), C.int(len(nonce)), -+ base(dst[n:]), &outLen) -+ runtime.KeepAlive(g) -+ if ok == 0 { -+ // Zero output buffer on error. -+ for i := range dst { -+ dst[i] = 0 -+ } -+ return nil, errOpen -+ } -+ if outLen != C.size_t(len(ciphertext)-gcmTagSize) { -+ panic("boringcrypto: [open] internal confusion about GCM tag size") -+ } -+ return dst[:n+int(outLen)], nil -+} -+ -======= -+ // BoringCrypto does not do any TLS check when decrypting, neither do we. -+ -+ tag := ciphertext[len(ciphertext)-gcmTagSize:] -+ ciphertext = ciphertext[:len(ciphertext)-gcmTagSize] -+ -+ // Make room in dst to append ciphertext without tag. -+ ret, out := sliceForAppend(dst, len(ciphertext)) -+ -+ // Check delayed until now to make sure len(dst) is accurate. -+ if inexactOverlap(out, ciphertext) { -+ panic("cipher: invalid buffer overlap") -+ } -+ -+ ok := C.go_openssl_EVP_CIPHER_CTX_open_wrapper( -+ g.ctx, base(out), base(nonce), -+ base(ciphertext), C.int(len(ciphertext)), -+ base(additionalData), C.int(len(additionalData)), base(tag)) -+ runtime.KeepAlive(g) -+ if ok == 0 { -+ // Zero output buffer on error. -+ for i := range out { -+ out[i] = 0 -+ } -+ return nil, errOpen -+ } -+ return ret, nil -+} -+ -+// sliceForAppend is a mirror of crypto/cipher.sliceForAppend. -+func sliceForAppend(in []byte, n int) (head, tail []byte) { -+ if total := len(in) + n; cap(in) >= total { -+ head = in[:total] -+ } else { -+ head = make([]byte, total) -+ copy(head, in) -+ } -+ tail = head[len(in):] -+ return -+} -+ -+func newCipherCtx(kind cipherKind, mode C.int, key, iv []byte) (C.GO_EVP_CIPHER_CTX_PTR, error) { -+ cipher := newCipher(kind) -+ if cipher == nil { -+ panic("openssl: unsupported cipher: " + strconv.Itoa(int(kind))) -+ } -+ ctx := C.go_openssl_EVP_CIPHER_CTX_new() -+ if ctx == nil { -+ return nil, fail("unable to create EVP cipher ctx") -+ } -+ if C.go_openssl_EVP_CipherInit_ex(ctx, cipher, nil, base(key), base(iv), mode) != 1 { -+ C.go_openssl_EVP_CIPHER_CTX_free(ctx) -+ return nil, fail("unable to initialize EVP cipher ctx") -+ } -+ return ctx, nil -+} -+ -+// The following two functions are a mirror of golang.org/x/crypto/internal/subtle. -+ ->>>>>>> 0023bf4c7a (rebase) -+func anyOverlap(x, y []byte) bool { -+ return len(x) > 0 && len(y) > 0 && -+ uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && -+ uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) -+} -+ -+func inexactOverlap(x, y []byte) bool { -+ if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { -+ return false -+ } -+ return anyOverlap(x, y) -+} -<<<<<<< HEAD -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/doc.go b/src/vendor/github.com/golang-fips/openssl-fips/openssl/doc.go -new file mode 100644 -index 0000000000..cdc7f6a47b ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/doc.go -@@ -0,0 +1,17 @@ -+// 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. -+ -+// package openssl provides access to OpenSSL implementation functions. -+package openssl -+ -+// Enabled returns whether or not the boring package is enabled. When -+// the boring package is enabled that means FIPS mode is enabled. -+func Enabled() bool { -+ return enabled -+} -+ -+// A BigInt is the raw words from a BigInt. -+// This definition allows us to avoid importing math/big. -+// Conversion between BigInt and *big.Int is in crypto/internal/boring/bbig. -+type BigInt []uint -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/ecdh.go b/src/vendor/github.com/golang-fips/openssl-fips/openssl/ecdh.go -new file mode 100644 -index 0000000000..56adf47bf6 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/ecdh.go -@@ -0,0 +1,213 @@ -+// 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 -+// +build linux,!android,!cmd_go_bootstrap,!msan,!no_openssl -======= -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/bbig/big.go b/src/vendor/github.com/golang-fips/openssl/v2/bbig/big.go -new file mode 100644 -index 0000000000..a81cbdbef9 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/bbig/big.go -@@ -0,0 +1,37 @@ -+// Copyright 2022 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. -+ -+// This is a mirror of -+// https://github.com/golang/go/blob/36b87f273cc43e21685179dc1664ebb5493d26ae/src/crypto/internal/boring/bbig/big.go. -+ -+package bbig -+ -+import ( -+ "math/big" -+ "unsafe" -+ -+ "github.com/golang-fips/openssl/v2" -+) -+ -+func Enc(b *big.Int) openssl.BigInt { -+ if b == nil { -+ return nil -+ } -+ x := b.Bits() -+ if len(x) == 0 { -+ return openssl.BigInt{} -+ } -+ return unsafe.Slice((*uint)(&x[0]), len(x)) -+} -+ -+func Dec(b openssl.BigInt) *big.Int { -+ if b == nil { -+ return nil -+ } -+ if len(b) == 0 { -+ return new(big.Int) -+ } -+ x := unsafe.Slice((*big.Word)(&b[0]), len(b)) -+ return new(big.Int).SetBits(x) -+} -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/big.go b/src/vendor/github.com/golang-fips/openssl/v2/big.go -new file mode 100644 -index 0000000000..6461f241f8 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/big.go -@@ -0,0 +1,11 @@ -+package openssl -+ -+// This file does not have build constraints to -+// facilitate using BigInt in Go crypto. -+// Go crypto references BigInt unconditionally, -+// even if it is not finally used. -+ -+// A BigInt is the raw words from a BigInt. -+// This definition allows us to avoid importing math/big. -+// Conversion between BigInt and *big.Int is in openssl/bbig. -+type BigInt []uint -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/ec.go b/src/vendor/github.com/golang-fips/openssl/v2/ec.go -new file mode 100644 -index 0000000000..eac2f8bbee ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/ec.go -@@ -0,0 +1,59 @@ -+//go:build !cmd_go_bootstrap -+ -+package openssl -+ -+// #include "goopenssl.h" -+import "C" -+ -+var ( -+ paramPubKey = C.CString("pub") -+ paramPrivKey = C.CString("priv") -+ paramGroup = C.CString("group") -+ paramECPubX = C.CString("qx") -+ paramECPubY = C.CString("qy") -+) -+ -+func curveNID(curve string) (C.int, error) { -+ switch curve { -+ case "P-224": -+ return C.GO_NID_secp224r1, nil -+ case "P-256": -+ return C.GO_NID_X9_62_prime256v1, nil -+ case "P-384": -+ return C.GO_NID_secp384r1, nil -+ case "P-521": -+ return C.GO_NID_secp521r1, nil -+ } -+ return 0, errUnknownCurve -+} -+ -+// encodeEcPoint encodes pt. -+func encodeEcPoint(group C.GO_EC_GROUP_PTR, pt C.GO_EC_POINT_PTR) ([]byte, error) { -+ // Get encoded point size. -+ n := C.go_openssl_EC_POINT_point2oct(group, pt, C.GO_POINT_CONVERSION_UNCOMPRESSED, nil, 0, nil) -+ if n == 0 { -+ return nil, newOpenSSLError("EC_POINT_point2oct") -+ } -+ // Encode point into bytes. -+ bytes := make([]byte, n) -+ n = C.go_openssl_EC_POINT_point2oct(group, pt, C.GO_POINT_CONVERSION_UNCOMPRESSED, base(bytes), n, nil) -+ if n == 0 { -+ return nil, newOpenSSLError("EC_POINT_point2oct") -+ } -+ return bytes, nil -+} -+ -+// generateAndEncodeEcPublicKey calls newPubKeyPointFn to generate a public key point and then encodes it. -+func generateAndEncodeEcPublicKey(nid C.int, newPubKeyPointFn func(group C.GO_EC_GROUP_PTR) (C.GO_EC_POINT_PTR, error)) ([]byte, error) { -+ group := C.go_openssl_EC_GROUP_new_by_curve_name(nid) -+ if group == nil { -+ return nil, newOpenSSLError("EC_GROUP_new_by_curve_name") -+ } -+ defer C.go_openssl_EC_GROUP_free(group) -+ pt, err := newPubKeyPointFn(group) -+ if err != nil { -+ return nil, err -+ } -+ defer C.go_openssl_EC_POINT_free(pt) -+ return encodeEcPoint(group, pt) -+} -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/ecdh.go b/src/vendor/github.com/golang-fips/openssl/v2/ecdh.go -new file mode 100644 -index 0000000000..62e23333ce ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/ecdh.go -@@ -0,0 +1,323 @@ -<<<<<<< HEAD -+//go:build linux && !cmd_go_bootstrap ->>>>>>> 0023bf4c7a (rebase) -======= -+//go:build !cmd_go_bootstrap ->>>>>>> 0b8240ca10 (support opensslv2, update strict fips checks) -+ -+package openssl -+ -+// #include "goopenssl.h" -+import "C" -+import ( -+ "errors" -+ "runtime" -+ "unsafe" -+) -+ -<<<<<<< HEAD -+var ( -+ paramPrivKey = C.CString("priv") -+) -+ -+type PublicKeyECDH struct { -+ _pkey *C.GO_EVP_PKEY -+ bytes []byte -+ -+ // priv is only set when PublicKeyECDH is derived from a private key, -+ // in which case priv's finalizer is responsible for freeing _pkey. -+ // This ensures priv is not finalized while the public key is alive, -+ // which could cause use-after-free and double-free behavior. -+ // -+ // We could avoid this altogether by using EVP_PKEY_up_ref -+ // when instantiating a derived public key, unfortunately -+ // it is not available on OpenSSL 1.0.2. -+ priv *PrivateKeyECDH -+} -+ -+func (k *PublicKeyECDH) finalize() { -+ if k.priv == nil { -+ C._goboringcrypto_EVP_PKEY_free(k._pkey) -+ } -+} -+ -+type PrivateKeyECDH struct { -+ _pkey *C.GO_EVP_PKEY -======= -+type PublicKeyECDH struct { -+ _pkey C.GO_EVP_PKEY_PTR -+ bytes []byte -+} -+ -+func (k *PublicKeyECDH) finalize() { -+ C.go_openssl_EVP_PKEY_free(k._pkey) -+} -+ -+type PrivateKeyECDH struct { -+ _pkey C.GO_EVP_PKEY_PTR ->>>>>>> 0023bf4c7a (rebase) -+ curve string -+ hasPublicKey bool -+} -+ -+func (k *PrivateKeyECDH) finalize() { -<<<<<<< HEAD -+ C._goboringcrypto_EVP_PKEY_free(k._pkey) -======= -+ C.go_openssl_EVP_PKEY_free(k._pkey) ->>>>>>> 0023bf4c7a (rebase) -+} -+ -+func NewPublicKeyECDH(curve string, bytes []byte) (*PublicKeyECDH, error) { -+ if len(bytes) < 1 { -+ return nil, errors.New("NewPublicKeyECDH: missing key") -+ } -+ pkey, err := newECDHPkey(curve, bytes, false) -+ if err != nil { -+ return nil, err -+ } -<<<<<<< HEAD -+ k := &PublicKeyECDH{pkey, append([]byte(nil), bytes...), nil} -======= -+ k := &PublicKeyECDH{pkey, append([]byte(nil), bytes...)} ->>>>>>> 0023bf4c7a (rebase) -+ runtime.SetFinalizer(k, (*PublicKeyECDH).finalize) -+ return k, nil -+} -+ -+func (k *PublicKeyECDH) Bytes() []byte { return k.bytes } -+ -+func NewPrivateKeyECDH(curve string, bytes []byte) (*PrivateKeyECDH, error) { -+ pkey, err := newECDHPkey(curve, bytes, true) -+ if err != nil { -+ return nil, err -+ } -+ k := &PrivateKeyECDH{pkey, curve, false} -+ runtime.SetFinalizer(k, (*PrivateKeyECDH).finalize) -+ return k, nil -+} -+ -+func (k *PrivateKeyECDH) PublicKey() (*PublicKeyECDH, error) { -+ defer runtime.KeepAlive(k) -+ if !k.hasPublicKey { -+ err := deriveEcdhPublicKey(k._pkey, k.curve) -+ if err != nil { -+ return nil, err -+ } -+ k.hasPublicKey = true -+ } -<<<<<<< HEAD -+ var bytes []byte -+ var cbytes *C.uchar -+ -+ n := C._goboringcrypto_EVP_PKEY_get1_encoded_ecdh_public_key(k._pkey, &cbytes) -+ if n == 0 { -+ return nil, NewOpenSSLError("EVP_PKEY_get1_encoded_ecdh_public_key") -+ } -+ bytes = C.GoBytes(unsafe.Pointer(cbytes), C.int(n)) -+ C.free(unsafe.Pointer(cbytes)) -+ -+ pub := &PublicKeyECDH{k._pkey, bytes, k} -======= -+ var pkey C.GO_EVP_PKEY_PTR -+ defer func() { -+ C.go_openssl_EVP_PKEY_free(pkey) -+ }() -+ -+ var bytes []byte -+ switch vMajor { -+ case 1: -+ pkey = C.go_openssl_EVP_PKEY_new() -+ if pkey == nil { -+ return nil, newOpenSSLError("EVP_PKEY_new") -+ } -+ key := getECKey(k._pkey) -+ if C.go_openssl_EVP_PKEY_set1_EC_KEY(pkey, key) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_set1_EC_KEY") -+ } -+ pt := C.go_openssl_EC_KEY_get0_public_key(key) -+ if pt == nil { -+ return nil, newOpenSSLError("EC_KEY_get0_public_key") -+ } -+ group := C.go_openssl_EC_KEY_get0_group(key) -+ var err error -+ bytes, err = encodeEcPoint(group, pt) -+ if err != nil { -+ return nil, err -+ } -+ case 3: -+ pkey = k._pkey -+ if C.go_openssl_EVP_PKEY_up_ref(pkey) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_up_ref") -+ } -+ -+ var cbytes *C.uchar -+ n := C.go_openssl_EVP_PKEY_get1_encoded_public_key(k._pkey, &cbytes) -+ if n == 0 { -+ return nil, newOpenSSLError("EVP_PKEY_get_octet_string_param") -+ } -+ bytes = C.GoBytes(unsafe.Pointer(cbytes), C.int(n)) -+ cryptoFree(unsafe.Pointer(cbytes)) -+ default: -+ panic(errUnsupportedVersion()) -+ } -+ pub := &PublicKeyECDH{pkey, bytes} -+ pkey = nil ->>>>>>> 0023bf4c7a (rebase) -+ runtime.SetFinalizer(pub, (*PublicKeyECDH).finalize) -+ return pub, nil -+} -+ -<<<<<<< HEAD -+func newECDHPkey(curve string, bytes []byte, isPrivate bool) (*C.GO_EVP_PKEY, error) { -======= -+func newECDHPkey(curve string, bytes []byte, isPrivate bool) (C.GO_EVP_PKEY_PTR, error) { ->>>>>>> 0023bf4c7a (rebase) -+ nid, err := curveNID(curve) -+ if err != nil { -+ return nil, err -+ } -<<<<<<< HEAD -+ -+ var isPrivateValue C.int -+ if isPrivate { -+ isPrivateValue = 1 -+ } else { -+ if len(bytes) > 0 && bytes[0] != 0x04 { -+ return nil, errors.New("crypto/ecdh: point is compressed") -+ } else if len(bytes) == 1 && bytes[0] == 0x00 { -+ return nil, errors.New("crypto/ecdh: point at infinity") -+ } -+ } -+ -+ key := C._goboringcrypto_EVP_PKEY_new_for_ecdh(nid, base(bytes), C.size_t(len(bytes)), isPrivateValue) -+ if key == nil { -+ return nil, NewOpenSSLError("EVP_PKEY_new_for_ecdh") -+ } -+ return key, nil -======= -+ switch vMajor { -+ case 1: -+ return newECDHPkey1(nid, bytes, isPrivate) -+ case 3: -+ return newECDHPkey3(nid, bytes, isPrivate) -+ default: -+ panic(errUnsupportedVersion()) -+ } -+} -+ -+func newECDHPkey1(nid C.int, bytes []byte, isPrivate bool) (pkey C.GO_EVP_PKEY_PTR, err error) { -+ if vMajor != 1 { -+ panic("incorrect vMajor version") -+ } -+ key := C.go_openssl_EC_KEY_new_by_curve_name(nid) -+ if key == nil { -+ return nil, newOpenSSLError("EC_KEY_new_by_curve_name") -+ } -+ defer func() { -+ if pkey == nil { -+ C.go_openssl_EC_KEY_free(key) -+ } -+ }() -+ if isPrivate { -+ priv := C.go_openssl_BN_bin2bn(base(bytes), C.int(len(bytes)), nil) -+ if priv == nil { -+ return nil, newOpenSSLError("BN_bin2bn") -+ } -+ defer C.go_openssl_BN_clear_free(priv) -+ if C.go_openssl_EC_KEY_set_private_key(key, priv) != 1 { -+ return nil, newOpenSSLError("EC_KEY_set_private_key") -+ } -+ } else { -+ group := C.go_openssl_EC_KEY_get0_group(key) -+ pub := C.go_openssl_EC_POINT_new(group) -+ if pub == nil { -+ return nil, newOpenSSLError("EC_POINT_new") -+ } -+ defer C.go_openssl_EC_POINT_free(pub) -+ if C.go_openssl_EC_POINT_oct2point(group, pub, base(bytes), C.size_t(len(bytes)), nil) != 1 { -+ return nil, errors.New("point not on curve") -+ } -+ if C.go_openssl_EC_KEY_set_public_key(key, pub) != 1 { -+ return nil, newOpenSSLError("EC_KEY_set_public_key") -+ } -+ } -+ return newEVPPKEY(key) -+} -+ -+func newECDHPkey3(nid C.int, bytes []byte, isPrivate bool) (C.GO_EVP_PKEY_PTR, error) { -+ if vMajor != 3 { -+ panic("incorrect vMajor version") -+ } -+ bld := C.go_openssl_OSSL_PARAM_BLD_new() -+ if bld == nil { -+ return nil, newOpenSSLError("OSSL_PARAM_BLD_new") -+ } -+ defer C.go_openssl_OSSL_PARAM_BLD_free(bld) -+ C.go_openssl_OSSL_PARAM_BLD_push_utf8_string(bld, paramGroup, C.go_openssl_OBJ_nid2sn(nid), 0) -+ var selection C.int -+ if isPrivate { -+ priv := C.go_openssl_BN_bin2bn(base(bytes), C.int(len(bytes)), nil) -+ if priv == nil { -+ return nil, newOpenSSLError("BN_bin2bn") -+ } -+ defer C.go_openssl_BN_clear_free(priv) -+ if C.go_openssl_OSSL_PARAM_BLD_push_BN(bld, paramPrivKey, priv) != 1 { -+ return nil, newOpenSSLError("OSSL_PARAM_BLD_push_BN") -+ } -+ selection = C.GO_EVP_PKEY_KEYPAIR -+ } else { -+ cbytes := C.CBytes(bytes) -+ defer C.free(cbytes) -+ C.go_openssl_OSSL_PARAM_BLD_push_octet_string(bld, paramPubKey, cbytes, C.size_t(len(bytes))) -+ selection = C.GO_EVP_PKEY_PUBLIC_KEY -+ } -+ params := C.go_openssl_OSSL_PARAM_BLD_to_param(bld) -+ if params == nil { -+ return nil, newOpenSSLError("OSSL_PARAM_BLD_to_param") -+ } -+ defer C.go_openssl_OSSL_PARAM_free(params) -+ return newEvpFromParams(C.GO_EVP_PKEY_EC, selection, params) ->>>>>>> 0023bf4c7a (rebase) -+} -+ -+// deriveEcdhPublicKey sets the raw public key of pkey by deriving it from -+// the raw private key. -<<<<<<< HEAD -+func deriveEcdhPublicKey(pkey *C.GO_EVP_PKEY, curve string) error { -+ nid, _ := curveNID(curve) -+ if C._goboringcrypto_EVP_PKEY_set_ecdh_public_key_from_private(pkey, nid) != 1 { -+ return NewOpenSSLError("EVP_PKEY_set_ecdh_public_key_from_private") -======= -+func deriveEcdhPublicKey(pkey C.GO_EVP_PKEY_PTR, curve string) error { -+ derive := func(group C.GO_EC_GROUP_PTR, priv C.GO_BIGNUM_PTR) (C.GO_EC_POINT_PTR, error) { -+ // OpenSSL does not expose any method to generate the public -+ // key from the private key [1], so we have to calculate it here. -+ // [1] https://github.com/openssl/openssl/issues/18437#issuecomment-1144717206 -+ pt := C.go_openssl_EC_POINT_new(group) -+ if pt == nil { -+ return nil, newOpenSSLError("EC_POINT_new") -+ } -+ if C.go_openssl_EC_POINT_mul(group, pt, priv, nil, nil, nil) == 0 { -+ C.go_openssl_EC_POINT_free(pt) -+ return nil, newOpenSSLError("EC_POINT_mul") -+ } -+ return pt, nil -+ } -+ switch vMajor { -+ case 1: -+ key := getECKey(pkey) -+ priv := C.go_openssl_EC_KEY_get0_private_key(key) -+ if priv == nil { -+ return newOpenSSLError("EC_KEY_get0_private_key") -+ } -+ group := C.go_openssl_EC_KEY_get0_group(key) -+ pub, err := derive(group, priv) -+ if err != nil { -+ return err -+ } -+ defer C.go_openssl_EC_POINT_free(pub) -+ if C.go_openssl_EC_KEY_set_public_key(key, pub) != 1 { -+ return newOpenSSLError("EC_KEY_set_public_key") -+ } -+ case 3: -+ var priv C.GO_BIGNUM_PTR -+ if C.go_openssl_EVP_PKEY_get_bn_param(pkey, paramPrivKey, &priv) != 1 { -+ return newOpenSSLError("EVP_PKEY_get_bn_param") -+ } -+ defer C.go_openssl_BN_clear_free(priv) -+ nid, _ := curveNID(curve) -+ pubBytes, err := generateAndEncodeEcPublicKey(nid, func(group C.GO_EC_GROUP_PTR) (C.GO_EC_POINT_PTR, error) { -+ return derive(group, priv) -+ }) -+ if err != nil { -+ return err -+ } -+ if C.go_openssl_EVP_PKEY_set1_encoded_public_key(pkey, base(pubBytes), C.size_t(len(pubBytes))) != 1 { -+ return newOpenSSLError("EVP_PKEY_set1_encoded_public_key") -+ } -+ default: -+ panic(errUnsupportedVersion()) ->>>>>>> 0023bf4c7a (rebase) -+ } -+ return nil -+} -+ -<<<<<<< HEAD -+func encodeEcPoint(group *C.GO_EC_GROUP, pt *C.GO_EC_POINT) ([]byte, error) { -+ // Get encoded point size. -+ n := C._goboringcrypto_EC_POINT_point2oct(group, pt, C.GO_POINT_CONVERSION_UNCOMPRESSED, nil, 0, nil) -+ if n == 0 { -+ return nil, NewOpenSSLError("EC_POINT_point2oct") -+ } -+ // Encode point into bytes. -+ bytes := make([]byte, n) -+ n = C._goboringcrypto_EC_POINT_point2oct(group, pt, C.GO_POINT_CONVERSION_UNCOMPRESSED, base(bytes), n, nil) -+ if n == 0 { -+ return nil, NewOpenSSLError("EC_POINT_point2oct") -+ } -+ return bytes, nil -+} -+ -+func ECDH(priv *PrivateKeyECDH, pub *PublicKeyECDH) ([]byte, error) { -+ defer runtime.KeepAlive(priv) -+ defer runtime.KeepAlive(pub) -+ ctx := C._goboringcrypto_EVP_PKEY_CTX_new(priv._pkey, nil) -+ if ctx == nil { -+ return nil, NewOpenSSLError("EVP_PKEY_CTX_new") -+ } -+ defer C._goboringcrypto_EVP_PKEY_CTX_free(ctx) -+ if C._goboringcrypto_EVP_PKEY_derive_init(ctx) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_derive_init") -+ } -+ if C._goboringcrypto_EVP_PKEY_derive_set_peer_ex(ctx, pub._pkey, 1) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_derive_set_peer_ex") -+ } -+ var outLen C.size_t -+ if C._goboringcrypto_EVP_PKEY_derive(ctx, nil, &outLen) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_derive_init") -+ } -+ out := make([]byte, outLen) -+ if C._goboringcrypto_EVP_PKEY_derive(ctx, base(out), &outLen) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_derive_init") -======= -+func ECDH(priv *PrivateKeyECDH, pub *PublicKeyECDH) ([]byte, error) { -+ defer runtime.KeepAlive(priv) -+ defer runtime.KeepAlive(pub) -+ ctx := C.go_openssl_EVP_PKEY_CTX_new(priv._pkey, nil) -+ if ctx == nil { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_new") -+ } -+ defer C.go_openssl_EVP_PKEY_CTX_free(ctx) -+ if C.go_openssl_EVP_PKEY_derive_init(ctx) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_derive_init") -+ } -+ if C.go_openssl_EVP_PKEY_derive_set_peer(ctx, pub._pkey) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_derive_set_peer") -+ } -+ var outLen C.size_t -+ if C.go_openssl_EVP_PKEY_derive(ctx, nil, &outLen) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_derive_init") -+ } -+ out := make([]byte, outLen) -+ if C.go_openssl_EVP_PKEY_derive(ctx, base(out), &outLen) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_derive_init") ->>>>>>> 0023bf4c7a (rebase) -+ } -+ return out, nil -+} -+ -+func GenerateKeyECDH(curve string) (*PrivateKeyECDH, []byte, error) { -+ pkey, err := generateEVPPKey(C.GO_EVP_PKEY_EC, 0, curve) -+ if err != nil { -+ return nil, nil, err -+ } -+ var k *PrivateKeyECDH -+ defer func() { -+ if k == nil { -<<<<<<< HEAD -+ C._goboringcrypto_EVP_PKEY_free(pkey) -+ } -+ }() -+ var priv *C.GO_BIGNUM -+ if openSSLVersion() < OPENSSL_VERSION_3_0_0 { -+ key := getECKey(pkey) -+ priv = C._goboringcrypto_EC_KEY_get0_private_key(key) -+ if priv == nil { -+ return nil, nil, NewOpenSSLError("EC_KEY_get0_private_key") -+ } -+ } else { -+ if C._goboringcrypto_EVP_PKEY_get_bn_param(pkey, paramPrivKey, &priv) != 1 { -+ return nil, nil, NewOpenSSLError("EVP_PKEY_get_bn_param") -+ } -+ defer C._goboringcrypto_BN_free(priv) -======= -+ C.go_openssl_EVP_PKEY_free(pkey) -+ } -+ }() -+ var priv C.GO_BIGNUM_PTR -+ switch vMajor { -+ case 1: -+ key := getECKey(pkey) -+ priv = C.go_openssl_EC_KEY_get0_private_key(key) -+ if priv == nil { -+ return nil, nil, newOpenSSLError("EC_KEY_get0_private_key") -+ } -+ case 3: -+ if C.go_openssl_EVP_PKEY_get_bn_param(pkey, paramPrivKey, &priv) != 1 { -+ return nil, nil, newOpenSSLError("EVP_PKEY_get_bn_param") -+ } -+ defer C.go_openssl_BN_clear_free(priv) -+ default: -+ panic(errUnsupportedVersion()) ->>>>>>> 0023bf4c7a (rebase) -+ } -+ // We should not leak bit length of the secret scalar in the key. -+ // For this reason, we use BN_bn2binpad instead of BN_bn2bin with fixed length. -+ // The fixed length is the order of the large prime subgroup of the curve, -+ // returned by EVP_PKEY_get_bits, which is generally the upper bound for -+ // generating a private ECDH key. -<<<<<<< HEAD -+ bits := C._goboringcrypto_EVP_PKEY_get_bits(pkey) -+ bytes := make([]byte, (bits+7)/8) -+ if C._goboringcrypto_BN_bn2binpad(priv, base(bytes), C.int(len(bytes))) == 0 { -+ return nil, nil, NewOpenSSLError("BN_bn2binpad") -======= -+ bits := C.go_openssl_EVP_PKEY_get_bits(pkey) -+ bytes := make([]byte, (bits+7)/8) -<<<<<<< HEAD -+ if C.go_openssl_BN_bn2binpad(priv, base(bytes), C.int(len(bytes))) == 0 { -+ return nil, nil, newOpenSSLError("BN_bn2binpad") ->>>>>>> 0023bf4c7a (rebase) -======= -+ if err := bnToBinPad(priv, bytes); err != nil { -+ return nil, nil, err ->>>>>>> 0b8240ca10 (support opensslv2, update strict fips checks) -+ } -+ k = &PrivateKeyECDH{pkey, curve, true} -+ runtime.SetFinalizer(k, (*PrivateKeyECDH).finalize) -+ return k, bytes, nil -+} -<<<<<<< HEAD -diff --git a/src/crypto/internal/boring/ecdsa.go b/src/vendor/github.com/golang-fips/openssl-fips/openssl/ecdsa.go -similarity index 60% -rename from src/crypto/internal/boring/ecdsa.go -rename to src/vendor/github.com/golang-fips/openssl-fips/openssl/ecdsa.go -index e15f3682c7..5e1e789da0 100644 ---- a/src/crypto/internal/boring/ecdsa.go -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/ecdsa.go -@@ -2,19 +2,24 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build boringcrypto && linux && (amd64 || arm64) && !android && !cmd_go_bootstrap && !msan -+//go:build linux && !android && !cmd_go_bootstrap && !msan && !no_openssl -+// +build linux,!android,!cmd_go_bootstrap,!msan,!no_openssl - --package boring -+package openssl - --// #include "goboringcrypto.h" -+// #include "goopenssl.h" - import "C" - import ( -+ "crypto" -+ "encoding/asn1" - "errors" -+ "math/big" - "runtime" -+ "unsafe" - ) - - type ecdsaSignature struct { -- R, S BigInt -+ R, S *big.Int - } - - type PrivateKeyECDSA struct { -@@ -34,11 +39,15 @@ func (k *PublicKeyECDSA) finalize() { - } - - var errUnknownCurve = errors.New("boringcrypto: unknown elliptic curve") -+var errUnsupportedCurve = errors.New("boringcrypto: unsupported elliptic curve") - - func curveNID(curve string) (C.int, error) { - switch curve { - case "P-224": -- return C.GO_NID_secp224r1, nil -+ if ExecutingTest() { -+ return C.GO_NID_secp224r1, nil -+ } -+ return 0, errUnsupportedCurve - case "P-256": - return C.GO_NID_X9_62_prime256v1, nil - case "P-384": -@@ -70,13 +79,13 @@ func newECKey(curve string, X, Y BigInt) (*C.GO_EC_KEY, error) { - } - key := C._goboringcrypto_EC_KEY_new_by_curve_name(nid) - if key == nil { -- return nil, fail("EC_KEY_new_by_curve_name") -+ return nil, NewOpenSSLError("EC_KEY_new_by_curve_name failed") - } - group := C._goboringcrypto_EC_KEY_get0_group(key) - pt := C._goboringcrypto_EC_POINT_new(group) - if pt == nil { - C._goboringcrypto_EC_KEY_free(key) -- return nil, fail("EC_POINT_new") -+ return nil, NewOpenSSLError("EC_POINT_new failed") - } - bx := bigToBN(X) - by := bigToBN(Y) -@@ -91,7 +100,7 @@ func newECKey(curve string, X, Y BigInt) (*C.GO_EC_KEY, error) { - C._goboringcrypto_EC_POINT_free(pt) - if !ok { - C._goboringcrypto_EC_KEY_free(key) -- return nil, fail("EC_POINT_set_affine_coordinates_GFp") -+ return nil, NewOpenSSLError("EC_POINT_free failed") - } - return key, nil - } -@@ -108,7 +117,7 @@ func NewPrivateKeyECDSA(curve string, X, Y BigInt, D BigInt) (*PrivateKeyECDSA, - } - if !ok { - C._goboringcrypto_EC_KEY_free(key) -- return nil, fail("EC_KEY_set_private_key") -+ return nil, NewOpenSSLError("EC_KEY_set_private_key failed") - } - k := &PrivateKeyECDSA{key} - // Note: Because of the finalizer, any time k.key is passed to cgo, -@@ -119,19 +128,55 @@ func NewPrivateKeyECDSA(curve string, X, Y BigInt, D BigInt) (*PrivateKeyECDSA, - return k, nil - } - -+func HashSignECDSA(priv *PrivateKeyECDSA, hash []byte, h crypto.Hash) (*big.Int, *big.Int, error) { -+ size := C._goboringcrypto_ECDSA_size(priv.key) -+ sig := make([]byte, size) -+ var sigLen C.size_t -+ md := cryptoHashToMD(h) -+ if md == nil { -+ panic("boring: invalid hash") -+ } -+ if C._goboringcrypto_ECDSA_sign(md, base(hash), C.size_t(len(hash)), (*C.uint8_t)(unsafe.Pointer(&sig[0])), &sigLen, priv.key) == 0 { -+ return nil, nil, NewOpenSSLError("ECDSA_sign failed") -+ } -+ runtime.KeepAlive(priv) -+ sig = sig[:sigLen] -+ var esig ecdsaSignature -+ if _, err := asn1.Unmarshal(sig, &esig); err != nil { -+ return nil, nil, err -+ } -+ return esig.R, esig.S, nil -+} -+ - func SignMarshalECDSA(priv *PrivateKeyECDSA, hash []byte) ([]byte, error) { - size := C._goboringcrypto_ECDSA_size(priv.key) - sig := make([]byte, size) - var sigLen C.uint -- if C._goboringcrypto_ECDSA_sign(0, base(hash), C.size_t(len(hash)), base(sig), &sigLen, priv.key) == 0 { -- return nil, fail("ECDSA_sign") -+ ok := C._goboringcrypto_internal_ECDSA_sign(0, base(hash), C.size_t(len(hash)), (*C.uint8_t)(unsafe.Pointer(&sig[0])), &sigLen, priv.key) > 0 -+ if !ok { -+ return nil, NewOpenSSLError(("ECDSA_sign failed")) - } -+ - runtime.KeepAlive(priv) - return sig[:sigLen], nil - } - - func VerifyECDSA(pub *PublicKeyECDSA, hash []byte, sig []byte) bool { -- ok := C._goboringcrypto_ECDSA_verify(0, base(hash), C.size_t(len(hash)), base(sig), C.size_t(len(sig)), pub.key) != 0 -+ ok := C._goboringcrypto_internal_ECDSA_verify(0, base(hash), C.size_t(len(hash)), (*C.uint8_t)(unsafe.Pointer(&sig[0])), C.uint(len(sig)), pub.key) > 0 -+ runtime.KeepAlive(pub) -+ return ok -+} -+ -+func HashVerifyECDSA(pub *PublicKeyECDSA, msg []byte, r, s *big.Int, h crypto.Hash) bool { -+ md := cryptoHashToMD(h) -+ if md == nil { -+ panic("boring: invalid hash") -+ } -+ sig, err := asn1.Marshal(ecdsaSignature{r, s}) -+ if err != nil { -+ return false -+ } -+ ok := C._goboringcrypto_ECDSA_verify(md, base(msg), C.size_t(len(msg)), (*C.uint8_t)(unsafe.Pointer(&sig[0])), C.uint(len(sig)), pub.key) > 0 - runtime.KeepAlive(pub) - return ok - } -@@ -143,30 +188,30 @@ func GenerateKeyECDSA(curve string) (X, Y, D BigInt, err error) { - } - key := C._goboringcrypto_EC_KEY_new_by_curve_name(nid) - if key == nil { -- return nil, nil, nil, fail("EC_KEY_new_by_curve_name") -+ return nil, nil, nil, NewOpenSSLError("EC_KEY_new_by_curve_name failed") - } - defer C._goboringcrypto_EC_KEY_free(key) -- if C._goboringcrypto_EC_KEY_generate_key_fips(key) == 0 { -- return nil, nil, nil, fail("EC_KEY_generate_key_fips") -+ if C._goboringcrypto_EC_KEY_generate_key(key) == 0 { -+ return nil, nil, nil, NewOpenSSLError("EC_KEY_generate_key failed") - } - group := C._goboringcrypto_EC_KEY_get0_group(key) - pt := C._goboringcrypto_EC_KEY_get0_public_key(key) - bd := C._goboringcrypto_EC_KEY_get0_private_key(key) - if pt == nil || bd == nil { -- return nil, nil, nil, fail("EC_KEY_get0_private_key") -+ return nil, nil, nil, NewOpenSSLError("EC_KEY_get0_private_key failed") - } - bx := C._goboringcrypto_BN_new() - if bx == nil { -- return nil, nil, nil, fail("BN_new") -+ return nil, nil, nil, NewOpenSSLError("BN_new failed") - } - defer C._goboringcrypto_BN_free(bx) - by := C._goboringcrypto_BN_new() - if by == nil { -- return nil, nil, nil, fail("BN_new") -+ return nil, nil, nil, NewOpenSSLError("BN_new failed") - } - defer C._goboringcrypto_BN_free(by) - if C._goboringcrypto_EC_POINT_get_affine_coordinates_GFp(group, pt, bx, by, nil) == 0 { -- return nil, nil, nil, fail("EC_POINT_get_affine_coordinates_GFp") -+ return nil, nil, nil, NewOpenSSLError("EC_POINT_get_affine_coordinates_GFp failed") - } - return bnToBig(bx), bnToBig(by), bnToBig(bd), nil - } -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/evp.go b/src/vendor/github.com/golang-fips/openssl-fips/openssl/evp.go -new file mode 100644 -index 0000000000..46d2bdd068 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/evp.go -@@ -0,0 +1,51 @@ -+//go:build linux && !android && !cmd_go_bootstrap && !msan && !no_openssl -+// +build linux,!android,!cmd_go_bootstrap,!msan,!no_openssl -======= -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/ecdsa.go b/src/vendor/github.com/golang-fips/openssl/v2/ecdsa.go -new file mode 100644 -index 0000000000..46b16abf48 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/ecdsa.go -@@ -0,0 +1,217 @@ -<<<<<<< HEAD -+//go:build linux && !cmd_go_bootstrap ->>>>>>> 0023bf4c7a (rebase) -======= -+//go:build !cmd_go_bootstrap ->>>>>>> 0b8240ca10 (support opensslv2, update strict fips checks) -+ -+package openssl -+ -+// #include "goopenssl.h" -+import "C" -<<<<<<< HEAD -+ -+func generateEVPPKey(id C.int, bits int, curve string) (*C.GO_EVP_PKEY, error) { -+ if (bits == 0 && curve == "") || (bits != 0 && curve != "") { -+ return nil, fail("incorrect generateEVPPKey parameters") -+ } -+ ctx := C._goboringcrypto_EVP_PKEY_CTX_new_id(id, nil) -+ if ctx == nil { -+ return nil, NewOpenSSLError("EVP_PKEY_CTX_new_id failed") -+ } -+ defer C._goboringcrypto_EVP_PKEY_CTX_free(ctx) -+ if C._goboringcrypto_EVP_PKEY_keygen_init(ctx) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_keygen_init failed") -+ } -+ if bits != 0 { -+ if C._goboringcrypto_EVP_PKEY_CTX_ctrl(ctx, id, -1, C.GO_EVP_PKEY_CTRL_RSA_KEYGEN_BITS, C.int(bits), nil) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_CTX_ctrl failed") -======= -+import ( -+ "crypto" -+ "errors" -+ "runtime" -+) -+ -+type PrivateKeyECDSA struct { -+ // _pkey MUST NOT be accessed directly. Instead, use the withKey method. -+ _pkey C.GO_EVP_PKEY_PTR -+} -+ -+func (k *PrivateKeyECDSA) finalize() { -+ C.go_openssl_EVP_PKEY_free(k._pkey) -+} -+ -+func (k *PrivateKeyECDSA) withKey(f func(C.GO_EVP_PKEY_PTR) C.int) C.int { -+ defer runtime.KeepAlive(k) -+ return f(k._pkey) -+} -+ -+type PublicKeyECDSA struct { -+ // _pkey MUST NOT be accessed directly. Instead, use the withKey method. -+ _pkey C.GO_EVP_PKEY_PTR -+} -+ -+func (k *PublicKeyECDSA) finalize() { -+ C.go_openssl_EVP_PKEY_free(k._pkey) -+} -+ -+func (k *PublicKeyECDSA) withKey(f func(C.GO_EVP_PKEY_PTR) C.int) C.int { -+ defer runtime.KeepAlive(k) -+ return f(k._pkey) -+} -+ -+var errUnknownCurve = errors.New("openssl: unknown elliptic curve") -+ -+func NewPublicKeyECDSA(curve string, X, Y BigInt) (*PublicKeyECDSA, error) { -+ pkey, err := newECDSAKey(curve, X, Y, nil) -+ if err != nil { -+ return nil, err -+ } -+ k := &PublicKeyECDSA{_pkey: pkey} -+ runtime.SetFinalizer(k, (*PublicKeyECDSA).finalize) -+ return k, nil -+} -+ -+func NewPrivateKeyECDSA(curve string, X, Y, D BigInt) (*PrivateKeyECDSA, error) { -+ pkey, err := newECDSAKey(curve, X, Y, D) -+ if err != nil { -+ return nil, err -+ } -+ k := &PrivateKeyECDSA{_pkey: pkey} -+ runtime.SetFinalizer(k, (*PrivateKeyECDSA).finalize) -+ return k, nil -+} -+ -+func GenerateKeyECDSA(curve string) (X, Y, D BigInt, err error) { -+ // Generate the private key. -+ pkey, err := generateEVPPKey(C.GO_EVP_PKEY_EC, 0, curve) -+ if err != nil { -+ return nil, nil, nil, err -+ } -+ defer C.go_openssl_EVP_PKEY_free(pkey) -+ -+ var bx, by, bd C.GO_BIGNUM_PTR -+ defer func() { -+ C.go_openssl_BN_free(bx) -+ C.go_openssl_BN_free(by) -+ }() -+ switch vMajor { -+ case 1: -+ // Retrieve the internal EC_KEY, which holds the X, Y, and D coordinates. -+ key := getECKey(pkey) -+ group := C.go_openssl_EC_KEY_get0_group(key) -+ pt := C.go_openssl_EC_KEY_get0_public_key(key) -+ // Allocate two big numbers to store the X and Y coordinates. -+ bx, by = C.go_openssl_BN_new(), C.go_openssl_BN_new() -+ if bx == nil || by == nil { -+ return nil, nil, nil, newOpenSSLError("BN_new failed") -+ } -+ // Get X and Y. -+ if C.go_openssl_EC_POINT_get_affine_coordinates_GFp(group, pt, bx, by, nil) == 0 { -+ return nil, nil, nil, newOpenSSLError("EC_POINT_get_affine_coordinates_GFp failed") -+ } -+ // Get Z. We don't need to free it, get0 does not increase the reference count. -+ bd = C.go_openssl_EC_KEY_get0_private_key(key) -+ case 3: -+ if C.go_openssl_EVP_PKEY_get_bn_param(pkey, paramECPubX, &bx) != 1 || -+ C.go_openssl_EVP_PKEY_get_bn_param(pkey, paramECPubY, &by) != 1 || -+ C.go_openssl_EVP_PKEY_get_bn_param(pkey, paramPrivKey, &bd) != 1 { -+ return nil, nil, nil, newOpenSSLError("EVP_PKEY_get_bn_param") -+ } -+ defer C.go_openssl_BN_clear_free(bd) -+ default: -+ panic(errUnsupportedVersion()) -+ } -+ -+ // Get D. -+ return bnToBig(bx), bnToBig(by), bnToBig(bd), nil -+} -+ -+func SignMarshalECDSA(priv *PrivateKeyECDSA, hash []byte) ([]byte, error) { -+ return evpSign(priv.withKey, 0, 0, 0, hash) -+} -+ -+func HashSignECDSA(priv *PrivateKeyECDSA, h crypto.Hash, msg []byte) ([]byte, error) { -+ return evpHashSign(priv.withKey, h, msg) -+} -+ -+func VerifyECDSA(pub *PublicKeyECDSA, hash []byte, sig []byte) bool { -+ return evpVerify(pub.withKey, 0, 0, 0, sig, hash) == nil -+} -+ -+func HashVerifyECDSA(pub *PublicKeyECDSA, h crypto.Hash, msg, sig []byte) bool { -+ return evpHashVerify(pub.withKey, h, msg, sig) == nil -+} -+ -+func newECDSAKey(curve string, X, Y, D BigInt) (C.GO_EVP_PKEY_PTR, error) { -+ nid, err := curveNID(curve) -+ if err != nil { -+ return nil, err -+ } -+ var bx, by, bd C.GO_BIGNUM_PTR -+ defer func() { -+ C.go_openssl_BN_free(bx) -+ C.go_openssl_BN_free(by) -+ C.go_openssl_BN_clear_free(bd) -+ }() -+ bx = bigToBN(X) -+ by = bigToBN(Y) -+ bd = bigToBN(D) -+ if bx == nil || by == nil || (D != nil && bd == nil) { -+ return nil, newOpenSSLError("BN_lebin2bn failed") -+ } -+ switch vMajor { -+ case 1: -+ return newECDSAKey1(nid, bx, by, bd) -+ case 3: -+ return newECDSAKey3(nid, bx, by, bd) -+ default: -+ panic(errUnsupportedVersion()) -+ } -+} -+ -+func newECDSAKey1(nid C.int, bx, by, bd C.GO_BIGNUM_PTR) (pkey C.GO_EVP_PKEY_PTR, err error) { -+ if vMajor != 1 { -+ panic("incorrect vMajor version") -+ } -+ key := C.go_openssl_EC_KEY_new_by_curve_name(nid) -+ if key == nil { -+ return nil, newOpenSSLError("EC_KEY_new_by_curve_name failed") -+ } -+ defer func() { -+ if pkey == nil { -+ defer C.go_openssl_EC_KEY_free(key) -+ } -+ }() -+ if C.go_openssl_EC_KEY_set_public_key_affine_coordinates(key, bx, by) != 1 { -+ return nil, newOpenSSLError("EC_KEY_set_public_key_affine_coordinates failed") -+ } -+ if bd != nil && C.go_openssl_EC_KEY_set_private_key(key, bd) != 1 { -+ return nil, newOpenSSLError("EC_KEY_set_private_key failed") -+ } -+ return newEVPPKEY(key) -+} -+ -+func newECDSAKey3(nid C.int, bx, by, bd C.GO_BIGNUM_PTR) (C.GO_EVP_PKEY_PTR, error) { -+ if vMajor != 3 { -+ panic("incorrect vMajor version") -+ } -+ // Create the encoded public key public key from bx and by. -+ pubBytes, err := generateAndEncodeEcPublicKey(nid, func(group C.GO_EC_GROUP_PTR) (C.GO_EC_POINT_PTR, error) { -+ pt := C.go_openssl_EC_POINT_new(group) -+ if pt == nil { -+ return nil, newOpenSSLError("EC_POINT_new") -+ } -+ if C.go_openssl_EC_POINT_set_affine_coordinates(group, pt, bx, by, nil) != 1 { -+ C.go_openssl_EC_POINT_free(pt) -+ return nil, newOpenSSLError("EC_POINT_set_affine_coordinates") -+ } -+ return pt, nil -+ }) -+ if err != nil { -+ return nil, err -+ } -+ // Construct the parameters. -+ bld := C.go_openssl_OSSL_PARAM_BLD_new() -+ if bld == nil { -+ return nil, newOpenSSLError("OSSL_PARAM_BLD_new") -+ } -+ defer C.go_openssl_OSSL_PARAM_BLD_free(bld) -+ C.go_openssl_OSSL_PARAM_BLD_push_utf8_string(bld, paramGroup, C.go_openssl_OBJ_nid2sn(nid), 0) -+ cbytes := C.CBytes(pubBytes) -+ defer C.free(cbytes) -+ C.go_openssl_OSSL_PARAM_BLD_push_octet_string(bld, paramPubKey, cbytes, C.size_t(len(pubBytes))) -+ var selection C.int -+ if bd != nil { -+ if C.go_openssl_OSSL_PARAM_BLD_push_BN(bld, paramPrivKey, bd) != 1 { -+ return nil, newOpenSSLError("OSSL_PARAM_BLD_push_BN") -+ } -+ selection = C.GO_EVP_PKEY_KEYPAIR -+ } else { -+ selection = C.GO_EVP_PKEY_PUBLIC_KEY -+ } -+ params := C.go_openssl_OSSL_PARAM_BLD_to_param(bld) -+ if params == nil { -+ return nil, newOpenSSLError("OSSL_PARAM_BLD_to_param") -+ } -+ defer C.go_openssl_OSSL_PARAM_free(params) -+ return newEvpFromParams(C.GO_EVP_PKEY_EC, selection, params) -+} -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/evp.go b/src/vendor/github.com/golang-fips/openssl/v2/evp.go -new file mode 100644 -index 0000000000..da71d9b389 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/evp.go -@@ -0,0 +1,455 @@ -+//go:build !cmd_go_bootstrap -+ -+package openssl -+ -+// #include "goopenssl.h" -+import "C" -+import ( -+ "crypto" -+ "errors" -+ "hash" -+ "strconv" -+ "sync" -+ "unsafe" -+) -+ -+// cacheMD is a cache of crypto.Hash to GO_EVP_MD_PTR. -+var cacheMD sync.Map -+ -+// hashToMD converts a hash.Hash implementation from this package to a GO_EVP_MD_PTR. -+func hashToMD(h hash.Hash) C.GO_EVP_MD_PTR { -+ var ch crypto.Hash -+ switch h.(type) { -+ case *sha1Hash: -+ ch = crypto.SHA1 -+ case *sha224Hash: -+ ch = crypto.SHA224 -+ case *sha256Hash: -+ ch = crypto.SHA256 -+ case *sha384Hash: -+ ch = crypto.SHA384 -+ case *sha512Hash: -+ ch = crypto.SHA512 -+ case *sha3_224Hash: -+ ch = crypto.SHA3_224 -+ case *sha3_256Hash: -+ ch = crypto.SHA3_256 -+ case *sha3_384Hash: -+ ch = crypto.SHA3_384 -+ case *sha3_512Hash: -+ ch = crypto.SHA3_512 -+ } -+ if ch != 0 { -+ return cryptoHashToMD(ch) -+ } -+ return nil -+} -+ -+// cryptoHashToMD converts a crypto.Hash to a GO_EVP_MD_PTR. -+func cryptoHashToMD(ch crypto.Hash) (md C.GO_EVP_MD_PTR) { -+ if v, ok := cacheMD.Load(ch); ok { -+ return v.(C.GO_EVP_MD_PTR) -+ } -+ defer func() { -+ if md != nil && vMajor == 3 { -+ // On OpenSSL 3, directly operating on a EVP_MD object -+ // not created by EVP_MD_fetch has negative performance -+ // implications, as digest operations will have -+ // to fetch it on every call. Better to just fetch it once here. -+ md = C.go_openssl_EVP_MD_fetch(nil, C.go_openssl_EVP_MD_get0_name(md), nil) -+ } -+ cacheMD.Store(ch, md) -+ }() -+ // SupportsHash returns false for MD5 and MD5SHA1 because we don't -+ // provide a hash.Hash implementation for them. Yet, they can -+ // still be used when signing/verifying with an RSA key. -+ switch ch { -+ case crypto.MD5: -+ return C.go_openssl_EVP_md5() -+ case crypto.MD5SHA1: -+ if vMajor == 1 && vMinor == 0 { -+ return C.go_openssl_EVP_md5_sha1_backport() -+ } else { -+ return C.go_openssl_EVP_md5_sha1() -+ } -+ } -+ if !SupportsHash(ch) { -+ return nil -+ } -+ switch ch { -+ case crypto.SHA1: -+ return C.go_openssl_EVP_sha1() -+ case crypto.SHA224: -+ return C.go_openssl_EVP_sha224() -+ case crypto.SHA256: -+ return C.go_openssl_EVP_sha256() -+ case crypto.SHA384: -+ return C.go_openssl_EVP_sha384() -+ case crypto.SHA512: -+ return C.go_openssl_EVP_sha512() -+ case crypto.SHA3_224: -+ return C.go_openssl_EVP_sha3_224() -+ case crypto.SHA3_256: -+ return C.go_openssl_EVP_sha3_256() -+ case crypto.SHA3_384: -+ return C.go_openssl_EVP_sha3_384() -+ case crypto.SHA3_512: -+ return C.go_openssl_EVP_sha3_512() -+ } -+ return nil -+} -+ -+func generateEVPPKey(id C.int, bits int, curve string) (C.GO_EVP_PKEY_PTR, error) { -+ if (bits == 0 && curve == "") || (bits != 0 && curve != "") { -+ return nil, fail("incorrect generateEVPPKey parameters") -+ } -+ ctx := C.go_openssl_EVP_PKEY_CTX_new_id(id, nil) -+ if ctx == nil { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_new_id failed") -+ } -+ defer C.go_openssl_EVP_PKEY_CTX_free(ctx) -+ if C.go_openssl_EVP_PKEY_keygen_init(ctx) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_keygen_init failed") -+ } -+ if bits != 0 { -+ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, id, -1, C.GO_EVP_PKEY_CTRL_RSA_KEYGEN_BITS, C.int(bits), nil) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") ->>>>>>> 0023bf4c7a (rebase) -+ } -+ } -+ if curve != "" { -+ nid, err := curveNID(curve) -+ if err != nil { -+ return nil, err -+ } -<<<<<<< HEAD -+ if C._goboringcrypto_EVP_PKEY_CTX_ctrl(ctx, id, -1, C.GO_EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, nil) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_CTX_ctrl failed") -+ } -+ } -+ var pkey *C.GO_EVP_PKEY -+ if C._goboringcrypto_EVP_PKEY_keygen(ctx, &pkey) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_keygen failed") -======= -+ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, id, -1, C.GO_EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, nil) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") -+ } -+ } -+ var pkey C.GO_EVP_PKEY_PTR -+ if C.go_openssl_EVP_PKEY_keygen(ctx, &pkey) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_keygen failed") -+ } -+ return pkey, nil -+} -+ -+type withKeyFunc func(func(C.GO_EVP_PKEY_PTR) C.int) C.int -+type initFunc func(C.GO_EVP_PKEY_CTX_PTR) error -+type cryptFunc func(C.GO_EVP_PKEY_CTX_PTR, *C.uchar, *C.size_t, *C.uchar, C.size_t) error -+type verifyFunc func(C.GO_EVP_PKEY_CTX_PTR, *C.uchar, C.size_t, *C.uchar, C.size_t) error -+ -+func setupEVP(withKey withKeyFunc, padding C.int, -+ h, mgfHash hash.Hash, label []byte, saltLen C.int, ch crypto.Hash, -+ init initFunc) (ctx C.GO_EVP_PKEY_CTX_PTR, err error) { -+ defer func() { -+ if err != nil { -+ if ctx != nil { -+ C.go_openssl_EVP_PKEY_CTX_free(ctx) -+ ctx = nil -+ } -+ } -+ }() -+ -+ withKey(func(pkey C.GO_EVP_PKEY_PTR) C.int { -+ ctx = C.go_openssl_EVP_PKEY_CTX_new(pkey, nil) -+ return 1 -+ }) -+ if ctx == nil { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_new failed") -+ } -+ if err := init(ctx); err != nil { -+ return nil, err -+ } -+ if padding == 0 { -+ return ctx, nil -+ } -+ // Each padding type has its own requirements in terms of when to apply the padding, -+ // so it can't be just set at this point. -+ setPadding := func() error { -+ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, C.GO_EVP_PKEY_RSA, -1, C.GO_EVP_PKEY_CTRL_RSA_PADDING, padding, nil) != 1 { -+ return newOpenSSLError("EVP_PKEY_CTX_ctrl failed") -+ } -+ return nil -+ } -+ switch padding { -+ case C.GO_RSA_PKCS1_OAEP_PADDING: -+ md := hashToMD(h) -+ if md == nil { -+ return nil, errors.New("crypto/rsa: unsupported hash function") -+ } -+ var mgfMD C.GO_EVP_MD_PTR -+ if mgfHash != nil { -+ // mgfHash is optional, but if it is set it must match a supported hash function. -+ mgfMD = hashToMD(mgfHash) -+ if mgfMD == nil { -+ return nil, errors.New("crypto/rsa: unsupported hash function") -+ } -+ } -+ // setPadding must happen before setting EVP_PKEY_CTRL_RSA_OAEP_MD. -+ if err := setPadding(); err != nil { -+ return nil, err -+ } -+ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, C.GO_EVP_PKEY_RSA, -1, C.GO_EVP_PKEY_CTRL_RSA_OAEP_MD, 0, unsafe.Pointer(md)) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") -+ } -+ if mgfHash != nil { -+ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, C.GO_EVP_PKEY_RSA, -1, C.GO_EVP_PKEY_CTRL_RSA_MGF1_MD, 0, unsafe.Pointer(mgfMD)) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") -+ } -+ } -+ // ctx takes ownership of label, so malloc a copy for OpenSSL to free. -+ // OpenSSL does not take ownership of the label if the length is zero, -+ // so better avoid the allocation. -+ var clabel *C.uchar -+ if len(label) > 0 { -+ clabel = (*C.uchar)(cryptoMalloc(len(label))) -+ copy((*[1 << 30]byte)(unsafe.Pointer(clabel))[:len(label)], label) -+ } -+ var ret C.int -+ if vMajor == 3 { -+ ret = C.go_openssl_EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, unsafe.Pointer(clabel), C.int(len(label))) -+ } else { -+ ret = C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, C.GO_EVP_PKEY_RSA, -1, C.GO_EVP_PKEY_CTRL_RSA_OAEP_LABEL, C.int(len(label)), unsafe.Pointer(clabel)) -+ } -+ if ret != 1 { -+ cryptoFree(unsafe.Pointer(clabel)) -+ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") -+ } -+ case C.GO_RSA_PKCS1_PSS_PADDING: -+ md := cryptoHashToMD(ch) -+ if md == nil { -+ return nil, errors.New("crypto/rsa: unsupported hash function") -+ } -+ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, C.GO_EVP_PKEY_RSA, -1, C.GO_EVP_PKEY_CTRL_MD, 0, unsafe.Pointer(md)) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") -+ } -+ // setPadding must happen after setting EVP_PKEY_CTRL_MD. -+ if err := setPadding(); err != nil { -+ return nil, err -+ } -+ if saltLen != 0 { -+ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, C.GO_EVP_PKEY_RSA, -1, C.GO_EVP_PKEY_CTRL_RSA_PSS_SALTLEN, saltLen, nil) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") -+ } -+ } -+ -+ case C.GO_RSA_PKCS1_PADDING: -+ if ch != 0 { -+ // We support unhashed messages. -+ md := cryptoHashToMD(ch) -+ if md == nil { -+ return nil, errors.New("crypto/rsa: unsupported hash function") -+ } -+ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, -1, -1, C.GO_EVP_PKEY_CTRL_MD, 0, unsafe.Pointer(md)) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") -+ } -+ if err := setPadding(); err != nil { -+ return nil, err -+ } -+ } -+ default: -+ if err := setPadding(); err != nil { -+ return nil, err -+ } -+ } -+ return ctx, nil -+} -+ -+func cryptEVP(withKey withKeyFunc, padding C.int, -+ h, mgfHash hash.Hash, label []byte, saltLen C.int, ch crypto.Hash, -+ init initFunc, crypt cryptFunc, in []byte) ([]byte, error) { -+ -+ ctx, err := setupEVP(withKey, padding, h, mgfHash, label, saltLen, ch, init) -+ if err != nil { -+ return nil, err -+ } -+ defer C.go_openssl_EVP_PKEY_CTX_free(ctx) -+ pkeySize := withKey(func(pkey C.GO_EVP_PKEY_PTR) C.int { -+ return C.go_openssl_EVP_PKEY_get_size(pkey) -+ }) -+ outLen := C.size_t(pkeySize) -+ out := make([]byte, pkeySize) -+ if err := crypt(ctx, base(out), &outLen, base(in), C.size_t(len(in))); err != nil { -+ return nil, err -+ } -+ // The size returned by EVP_PKEY_get_size() is only preliminary and not exact, -+ // so the final contents of the out buffer may be smaller. -+ return out[:outLen], nil -+} -+ -+func verifyEVP(withKey withKeyFunc, padding C.int, -+ h hash.Hash, label []byte, saltLen C.int, ch crypto.Hash, -+ init initFunc, verify verifyFunc, -+ sig, in []byte) error { -+ -+ ctx, err := setupEVP(withKey, padding, h, nil, label, saltLen, ch, init) -+ if err != nil { -+ return err -+ } -+ defer C.go_openssl_EVP_PKEY_CTX_free(ctx) -+ return verify(ctx, base(sig), C.size_t(len(sig)), base(in), C.size_t(len(in))) -+} -+ -+func evpEncrypt(withKey withKeyFunc, padding C.int, h, mgfHash hash.Hash, label, msg []byte) ([]byte, error) { -+ encryptInit := func(ctx C.GO_EVP_PKEY_CTX_PTR) error { -+ if ret := C.go_openssl_EVP_PKEY_encrypt_init(ctx); ret != 1 { -+ return newOpenSSLError("EVP_PKEY_encrypt_init failed") -+ } -+ return nil -+ } -+ encrypt := func(ctx C.GO_EVP_PKEY_CTX_PTR, out *C.uchar, outLen *C.size_t, in *C.uchar, inLen C.size_t) error { -+ if ret := C.go_openssl_EVP_PKEY_encrypt(ctx, out, outLen, in, inLen); ret != 1 { -+ return newOpenSSLError("EVP_PKEY_encrypt failed") -+ } -+ return nil -+ } -+ return cryptEVP(withKey, padding, h, mgfHash, label, 0, 0, encryptInit, encrypt, msg) -+} -+ -+func evpDecrypt(withKey withKeyFunc, padding C.int, h, mgfHash hash.Hash, label, msg []byte) ([]byte, error) { -+ decryptInit := func(ctx C.GO_EVP_PKEY_CTX_PTR) error { -+ if ret := C.go_openssl_EVP_PKEY_decrypt_init(ctx); ret != 1 { -+ return newOpenSSLError("EVP_PKEY_decrypt_init failed") -+ } -+ return nil -+ } -+ decrypt := func(ctx C.GO_EVP_PKEY_CTX_PTR, out *C.uchar, outLen *C.size_t, in *C.uchar, inLen C.size_t) error { -+ if ret := C.go_openssl_EVP_PKEY_decrypt(ctx, out, outLen, in, inLen); ret != 1 { -+ return newOpenSSLError("EVP_PKEY_decrypt failed") -+ } -+ return nil -+ } -+ return cryptEVP(withKey, padding, h, mgfHash, label, 0, 0, decryptInit, decrypt, msg) -+} -+ -+func evpSign(withKey withKeyFunc, padding C.int, saltLen C.int, h crypto.Hash, hashed []byte) ([]byte, error) { -+ signtInit := func(ctx C.GO_EVP_PKEY_CTX_PTR) error { -+ if ret := C.go_openssl_EVP_PKEY_sign_init(ctx); ret != 1 { -+ return newOpenSSLError("EVP_PKEY_sign_init failed") -+ } -+ return nil -+ } -+ sign := func(ctx C.GO_EVP_PKEY_CTX_PTR, out *C.uchar, outLen *C.size_t, in *C.uchar, inLen C.size_t) error { -+ if ret := C.go_openssl_EVP_PKEY_sign(ctx, out, outLen, in, inLen); ret != 1 { -+ return newOpenSSLError("EVP_PKEY_sign failed") -+ } -+ return nil -+ } -+ return cryptEVP(withKey, padding, nil, nil, nil, saltLen, h, signtInit, sign, hashed) -+} -+ -+func evpVerify(withKey withKeyFunc, padding C.int, saltLen C.int, h crypto.Hash, sig, hashed []byte) error { -+ verifyInit := func(ctx C.GO_EVP_PKEY_CTX_PTR) error { -+ if ret := C.go_openssl_EVP_PKEY_verify_init(ctx); ret != 1 { -+ return newOpenSSLError("EVP_PKEY_verify_init failed") -+ } -+ return nil -+ } -+ verify := func(ctx C.GO_EVP_PKEY_CTX_PTR, out *C.uchar, outLen C.size_t, in *C.uchar, inLen C.size_t) error { -+ if ret := C.go_openssl_EVP_PKEY_verify(ctx, out, outLen, in, inLen); ret != 1 { -+ return newOpenSSLError("EVP_PKEY_verify failed") -+ } -+ return nil -+ } -+ return verifyEVP(withKey, padding, nil, nil, saltLen, h, verifyInit, verify, sig, hashed) -+} -+ -+func evpHashSign(withKey withKeyFunc, h crypto.Hash, msg []byte) ([]byte, error) { -+ md := cryptoHashToMD(h) -+ if md == nil { -+ return nil, errors.New("unsupported hash function: " + strconv.Itoa(int(h))) -+ } -+ var out []byte -+ var outLen C.size_t -+ ctx := C.go_openssl_EVP_MD_CTX_new() -+ if ctx == nil { -+ return nil, newOpenSSLError("EVP_MD_CTX_new failed") -+ } -+ defer C.go_openssl_EVP_MD_CTX_free(ctx) -+ if withKey(func(key C.GO_EVP_PKEY_PTR) C.int { -+ return C.go_openssl_EVP_DigestSignInit(ctx, nil, md, nil, key) -+ }) != 1 { -+ return nil, newOpenSSLError("EVP_DigestSignInit failed") -+ } -+ if C.go_openssl_EVP_DigestUpdate(ctx, unsafe.Pointer(base(msg)), C.size_t(len(msg))) != 1 { -+ return nil, newOpenSSLError("EVP_DigestUpdate failed") -+ } -+ // Obtain the signature length -+ if C.go_openssl_EVP_DigestSignFinal(ctx, nil, &outLen) != 1 { -+ return nil, newOpenSSLError("EVP_DigestSignFinal failed") -+ } -+ out = make([]byte, outLen) -+ // Obtain the signature -+ if C.go_openssl_EVP_DigestSignFinal(ctx, base(out), &outLen) != 1 { -+ return nil, newOpenSSLError("EVP_DigestSignFinal failed") -+ } -+ return out[:outLen], nil -+} -+ -+func evpHashVerify(withKey withKeyFunc, h crypto.Hash, msg, sig []byte) error { -+ md := cryptoHashToMD(h) -+ if md == nil { -+ return errors.New("unsupported hash function: " + strconv.Itoa(int(h))) -+ } -+ ctx := C.go_openssl_EVP_MD_CTX_new() -+ if ctx == nil { -+ return newOpenSSLError("EVP_MD_CTX_new failed") -+ } -+ defer C.go_openssl_EVP_MD_CTX_free(ctx) -+ if withKey(func(key C.GO_EVP_PKEY_PTR) C.int { -+ return C.go_openssl_EVP_DigestVerifyInit(ctx, nil, md, nil, key) -+ }) != 1 { -+ return newOpenSSLError("EVP_DigestVerifyInit failed") -+ } -+ if C.go_openssl_EVP_DigestUpdate(ctx, unsafe.Pointer(base(msg)), C.size_t(len(msg))) != 1 { -+ return newOpenSSLError("EVP_DigestUpdate failed") -+ } -+ if C.go_openssl_EVP_DigestVerifyFinal(ctx, base(sig), C.size_t(len(sig))) != 1 { -+ return newOpenSSLError("EVP_DigestVerifyFinal failed") -+ } -+ return nil -+} -+ -+func newEVPPKEY(key C.GO_EC_KEY_PTR) (C.GO_EVP_PKEY_PTR, error) { -+ pkey := C.go_openssl_EVP_PKEY_new() -+ if pkey == nil { -+ return nil, newOpenSSLError("EVP_PKEY_new failed") -+ } -+ if C.go_openssl_EVP_PKEY_assign(pkey, C.GO_EVP_PKEY_EC, unsafe.Pointer(key)) != 1 { -+ C.go_openssl_EVP_PKEY_free(pkey) -+ return nil, newOpenSSLError("EVP_PKEY_assign failed") +diff --git a/src/crypto/rand/rand_unix.go b/src/crypto/rand/rand_unix.go +index 40fce36314..c30be35635 100644 +--- a/src/crypto/rand/rand_unix.go ++++ b/src/crypto/rand/rand_unix.go +@@ -10,7 +10,7 @@ + package rand + + import ( +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "errors" + "io" + "os" +@@ -23,7 +23,7 @@ import ( + const urandomDevice = "/dev/urandom" + + func init() { +- if boring.Enabled { ++ if boring.Enabled() { + Reader = boring.RandReader + return + } +diff --git a/src/crypto/rsa/boring.go b/src/crypto/rsa/boring.go +index b9f9d3154f..85c2a45848 100644 +--- a/src/crypto/rsa/boring.go ++++ b/src/crypto/rsa/boring.go +@@ -2,13 +2,13 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build boringcrypto ++//go:build !no_openssl + + package rsa + + import ( +- "crypto/internal/boring" +- "crypto/internal/boring/bbig" ++ boring "crypto/internal/backend" ++ "crypto/internal/backend/bbig" + "crypto/internal/boring/bcache" + "math/big" + ) +diff --git a/src/crypto/rsa/boring_test.go b/src/crypto/rsa/boring_test.go +index 2234d079f0..4e7fd9de4a 100644 +--- a/src/crypto/rsa/boring_test.go ++++ b/src/crypto/rsa/boring_test.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build boringcrypto ++//go:build !no_openssl + + // Note: Can run these tests against the non-BoringCrypto + // version of the code by using "CGO_ENABLED=0 go test". +diff --git a/src/crypto/rsa/notboring.go b/src/crypto/rsa/notboring.go +index 2abc043640..a83be6dfdb 100644 +--- a/src/crypto/rsa/notboring.go ++++ b/src/crypto/rsa/notboring.go +@@ -2,15 +2,15 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build !boringcrypto ++//go:build no_openssl + + package rsa + +-import "crypto/internal/boring" ++import boring "crypto/internal/backend" + + func boringPublicKey(*PublicKey) (*boring.PublicKeyRSA, error) { +- panic("boringcrypto: not available") ++ panic("!no_openssl: not available") + } + func boringPrivateKey(*PrivateKey) (*boring.PrivateKeyRSA, error) { +- panic("boringcrypto: not available") ++ panic("!no_openssl: not available") + } +diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go +index 55fea1ab93..8524c02547 100644 +--- a/src/crypto/rsa/pkcs1v15.go ++++ b/src/crypto/rsa/pkcs1v15.go +@@ -6,7 +6,7 @@ package rsa + + import ( + "crypto" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/randutil" + "crypto/subtle" + "errors" +@@ -49,7 +49,7 @@ func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, erro + return nil, ErrMessageTooLong + } + +- if boring.Enabled && random == boring.RandReader { ++ if boring.Enabled() && random == boring.RandReader { + bkey, err := boringPublicKey(pub) + if err != nil { + return nil, err +@@ -69,7 +69,7 @@ func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, erro + em[len(em)-len(msg)-1] = 0 + copy(mm, msg) + +- if boring.Enabled { ++ if boring.Enabled() { + var bkey *boring.PublicKeyRSA + bkey, err = boringPublicKey(pub) + if err != nil { +@@ -94,7 +94,7 @@ func DecryptPKCS1v15(random io.Reader, priv *PrivateKey, ciphertext []byte) ([]b + return nil, err + } + +- if boring.Enabled { ++ if boring.Enabled() { + bkey, err := boringPrivateKey(priv) + if err != nil { + return nil, err +@@ -188,7 +188,7 @@ func decryptPKCS1v15(priv *PrivateKey, ciphertext []byte) (valid int, em []byte, + return + } + +- if boring.Enabled { ++ if boring.Enabled() { + var bkey *boring.PrivateKeyRSA + bkey, err = boringPrivateKey(priv) + if err != nil { +@@ -296,7 +296,7 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [ + return nil, ErrMessageTooLong + } + +- if boring.Enabled { ++ if boring.Enabled() { + bkey, err := boringPrivateKey(priv) + if err != nil { + return nil, err +@@ -322,7 +322,7 @@ func SignPKCS1v15(random io.Reader, priv *PrivateKey, hash crypto.Hash, hashed [ + // returning a nil error. If hash is zero then hashed is used directly. This + // isn't advisable except for interoperability. + func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) error { +- if boring.Enabled { ++ if boring.Enabled() { + bkey, err := boringPublicKey(pub) + if err != nil { + return err +diff --git a/src/crypto/rsa/pkcs1v15_test.go b/src/crypto/rsa/pkcs1v15_test.go +index 39a4fc184a..0853178e3a 100644 +--- a/src/crypto/rsa/pkcs1v15_test.go ++++ b/src/crypto/rsa/pkcs1v15_test.go +@@ -7,7 +7,7 @@ package rsa_test + import ( + "bytes" + "crypto" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/backend/boringtest" + "crypto/rand" + . "crypto/rsa" +@@ -56,7 +56,7 @@ var decryptPKCS1v15Tests = []DecryptPKCS1v15Test{ + } + + func TestDecryptPKCS1v15(t *testing.T) { +- if boring.Enabled && !boringtest.Supports(t, "PKCSv1.5") { ++ if boring.Enabled() && !boringtest.Supports(t, "PKCSv1.5") { + t.Skip("skipping PKCS#1 v1.5 encryption test with BoringCrypto") + } + +@@ -84,7 +84,7 @@ func TestDecryptPKCS1v15(t *testing.T) { + } + + func TestEncryptPKCS1v15(t *testing.T) { +- if boring.Enabled && !boringtest.Supports(t, "PKCSv1.5") { ++ if boring.Enabled() && !boringtest.Supports(t, "PKCSv1.5") { + t.Skip("skipping PKCS#1 v1.5 encryption test with BoringCrypto") + } + +@@ -149,7 +149,7 @@ var decryptPKCS1v15SessionKeyTests = []DecryptPKCS1v15Test{ + } + + func TestEncryptPKCS1v15SessionKey(t *testing.T) { +- if boring.Enabled && !boringtest.Supports(t, "PKCSv1.5") { ++ if boring.Enabled() && !boringtest.Supports(t, "PKCSv1.5") { + t.Skip("skipping PKCS#1 v1.5 encryption test with BoringCrypto") + } + +@@ -167,7 +167,7 @@ func TestEncryptPKCS1v15SessionKey(t *testing.T) { + } + + func TestEncryptPKCS1v15DecrypterSessionKey(t *testing.T) { +- if boring.Enabled && !boringtest.Supports(t, "PKCSv1.5") { ++ if boring.Enabled() && !boringtest.Supports(t, "PKCSv1.5") { + t.Skip("skipping PKCS#1 v1.5 encryption test with BoringCrypto") + } + +@@ -277,7 +277,7 @@ func TestUnpaddedSignature(t *testing.T) { + } + + func TestShortSessionKey(t *testing.T) { +- if boring.Enabled && !boringtest.Supports(t, "PKCSv1.5") { ++ if boring.Enabled() && !boringtest.Supports(t, "PKCSv1.5") { + t.Skip("skipping PKCS#1 v1.5 encryption test with BoringCrypto") + } + +diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go +index 3a377cc9db..ce78a13d6f 100644 +--- a/src/crypto/rsa/pss.go ++++ b/src/crypto/rsa/pss.go +@@ -9,7 +9,7 @@ package rsa + import ( + "bytes" + "crypto" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "errors" + "hash" + "io" +@@ -214,7 +214,7 @@ func signPSSWithSalt(priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) ([ + return nil, err + } + +- if boring.Enabled { ++ if boring.Enabled() { + bkey, err := boringPrivateKey(priv) + if err != nil { + return nil, err +@@ -296,7 +296,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, + // well-specified number of random bytes is included in the signature, in a + // well-specified way. + +- if boring.Enabled && rand == boring.RandReader { ++ if boring.Enabled() && rand == boring.RandReader { + bkey, err := boringPrivateKey(priv) + if err != nil { + return nil, err +@@ -339,7 +339,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, + // argument may be nil, in which case sensible defaults are used. opts.Hash is + // ignored. + func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error { +- if boring.Enabled { ++ if boring.Enabled() { + bkey, err := boringPublicKey(pub) + if err != nil { + return err +diff --git a/src/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go +index 1226149321..befd1612b5 100644 +--- a/src/crypto/rsa/pss_test.go ++++ b/src/crypto/rsa/pss_test.go +@@ -79,7 +79,7 @@ func TestEMSAPSS(t *testing.T) { + // TestPSSGolden tests all the test vectors in pss-vect.txt from + // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip + func TestPSSGolden(t *testing.T) { +- if boring.Enabled && !boringtest.Supports(t, "SHA1") { ++ if boring.Enabled() && !boringtest.Supports(t, "SHA1") { + t.Skip("skipping PSS test with BoringCrypto: SHA-1 not allowed") + } + inFile, err := os.Open("testdata/pss-vect.txt.bz2") +@@ -173,7 +173,7 @@ func TestPSSGolden(t *testing.T) { + // TestPSSOpenSSL ensures that we can verify a PSS signature from OpenSSL with + // the default options. OpenSSL sets the salt length to be maximal. + func TestPSSOpenSSL(t *testing.T) { +- if boring.Enabled { ++ if boring.Enabled() { + t.Skip("skipping PSS test with BoringCrypto: too short key") + } + +@@ -209,7 +209,7 @@ func TestPSSNilOpts(t *testing.T) { + } + + func TestPSSSigning(t *testing.T) { +- if boring.Enabled && !boringtest.Supports(t, "SHA1") { ++ if boring.Enabled() && !boringtest.Supports(t, "SHA1") { + t.Skip("skipping PSS test with BoringCrypto: too short key") + } + +diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go +index f0aef1f542..e6bf6a5e88 100644 +--- a/src/crypto/rsa/rsa.go ++++ b/src/crypto/rsa/rsa.go +@@ -28,8 +28,8 @@ package rsa + import ( + "crypto" + "crypto/internal/bigmod" +- "crypto/internal/boring" +- "crypto/internal/boring/bbig" ++ boring "crypto/internal/backend" ++ "crypto/internal/backend/bbig" + "crypto/internal/randutil" + "crypto/rand" + "crypto/subtle" +@@ -294,7 +294,7 @@ func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) { + func GenerateMultiPrimeKey(random io.Reader, nprimes int, bits int) (*PrivateKey, error) { + randutil.MaybeReadByte(random) + +- if boring.Enabled && random == boring.RandReader && nprimes == 2 && ++ if boring.Enabled() && random == boring.RandReader && nprimes == 2 && + (bits == 2048 || bits == 3072 || bits == 4096) { + bN, bE, bD, bP, bQ, bDp, bDq, bQinv, err := boring.GenerateKeyRSA(bits) + if err != nil { +@@ -529,7 +529,7 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l + return nil, ErrMessageTooLong + } + +- if boring.Enabled && random == boring.RandReader { ++ if boring.Enabled() && random == boring.RandReader { + bkey, err := boringPublicKey(pub) + if err != nil { + return nil, err +@@ -558,7 +558,7 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l + mgf1XOR(db, hash, seed) + mgf1XOR(seed, hash, db) + +- if boring.Enabled { ++ if boring.Enabled() { + var bkey *boring.PublicKeyRSA + bkey, err = boringPublicKey(pub) + if err != nil { +@@ -719,7 +719,7 @@ func decryptOAEP(hash, mgfHash hash.Hash, random io.Reader, priv *PrivateKey, ci + return nil, ErrDecryption + } + +- if boring.Enabled { ++ if boring.Enabled() { + bkey, err := boringPrivateKey(priv) + if err != nil { + return nil, err +diff --git a/src/crypto/rsa/rsa_test.go b/src/crypto/rsa/rsa_test.go +index b994daec19..4b7427e1ae 100644 +--- a/src/crypto/rsa/rsa_test.go ++++ b/src/crypto/rsa/rsa_test.go +@@ -8,7 +8,7 @@ import ( + "bufio" + "bytes" + "crypto" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/rand" + . "crypto/rsa" + "crypto/sha1" +@@ -34,7 +34,7 @@ func TestKeyGeneration(t *testing.T) { + if bits := priv.N.BitLen(); bits != size { + t.Errorf("key too short (%d vs %d)", bits, size) + } +- if boring.Enabled && size < 1024 { ++ if boring.Enabled() && size < 1024 { + t.Logf("skipping short key with BoringCrypto: %d", size) + continue + } +@@ -120,12 +120,12 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) { + t.Errorf("private exponent too large") + } + +- if boring.Enabled { ++ if boring.Enabled() { + // Cannot call encrypt/decrypt with raw RSA. PKCSv1.5 + // not supported in some configurations. Test with + // OAEP if possible (i.e., key size is equal to or + // longer than 2048 bits). +- if bits := priv.N.BitLen(); boring.Enabled && bits < 2048 { ++ if bits := priv.N.BitLen(); boring.Enabled() && bits < 2048 { + t.Logf("skipping short key with BoringCrypto: %d", bits) + return + } +@@ -167,7 +167,7 @@ func testKeyBasics(t *testing.T, priv *PrivateKey) { + } + + func TestAllocations(t *testing.T) { +- if boring.Enabled { ++ if boring.Enabled() { + t.Skip("skipping allocations test with BoringCrypto") + } + testenv.SkipIfOptimizationOff(t) +@@ -213,7 +213,7 @@ func TestEverything(t *testing.T) { + if bits := priv.N.BitLen(); bits != size { + t.Errorf("key too short (%d vs %d)", bits, size) + } +- if boring.Enabled && size < 2048 { ++ if boring.Enabled() && size < 2048 { + t.Skip("skipping short key with BoringCrypto") + } + testEverything(t, priv) +@@ -667,7 +667,7 @@ func TestEncryptOAEP(t *testing.T) { + n := new(big.Int) + for i, test := range testEncryptOAEPData { + n.SetString(test.modulus, 16) +- if boring.Enabled { ++ if boring.Enabled() { + t.Log("skipping test in FIPS mode due to short keys and unpadded RSA operations not allowed with FIPS") + continue + } +@@ -694,7 +694,7 @@ func TestDecryptOAEP(t *testing.T) { + d := new(big.Int) + for i, test := range testEncryptOAEPData { + n.SetString(test.modulus, 16) +- if boring.Enabled && !boringtest.Supports(t, "RSA1024") && n.BitLen() < 2048 { ++ if boring.Enabled() && !boringtest.Supports(t, "RSA1024") && n.BitLen() < 2048 { + t.Logf("skipping encryption tests with BoringCrypto: too short key: %d", n.BitLen()) + continue + } +@@ -741,7 +741,7 @@ func Test2DecryptOAEP(t *testing.T) { + sha1 := crypto.SHA1 + sha256 := crypto.SHA256 + +- if boring.Enabled && n.BitLen() < 2048 { ++ if boring.Enabled() && n.BitLen() < 2048 { + t.Skipf("skipping encryption tests with BoringCrypto: too short key: %d", n.BitLen()) + } + +@@ -760,7 +760,7 @@ func TestEncryptDecryptOAEP(t *testing.T) { + d := new(big.Int) + for i, test := range testEncryptOAEPData { + n.SetString(test.modulus, 16) +- if boring.Enabled && !boringtest.Supports(t, "RSA1024") && n.BitLen() < 2048 { ++ if boring.Enabled() && !boringtest.Supports(t, "RSA1024") && n.BitLen() < 2048 { + t.Logf("skipping encryption tests with BoringCrypto: too short key: %d", n.BitLen()) + continue + } +diff --git a/src/crypto/sha1/boring.go b/src/crypto/sha1/boring.go +index b5786d1bf4..9bd03f3940 100644 +--- a/src/crypto/sha1/boring.go ++++ b/src/crypto/sha1/boring.go +@@ -12,11 +12,11 @@ + package sha1 + + import ( +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "hash" + ) + +-const boringEnabled = boring.Enabled ++var boringEnabled = boring.Enabled() + + func boringNewSHA1() hash.Hash { return boring.NewSHA1() } + +diff --git a/src/crypto/sha1/notboring.go b/src/crypto/sha1/notboring.go +index 42ef87937f..c1a3205539 100644 +--- a/src/crypto/sha1/notboring.go ++++ b/src/crypto/sha1/notboring.go +@@ -11,10 +11,10 @@ import ( + "hash" + ) + +-const boringEnabled = false ++var boringEnabled = false + +-func boringNewSHA1() hash.Hash { panic("boringcrypto: not available") } ++func boringNewSHA1() hash.Hash { panic("!no_openssl: not available") } + + func boringUnreachable() {} + +-func boringSHA1([]byte) [20]byte { panic("boringcrypto: not available") } ++func boringSHA1([]byte) [20]byte { panic("!no_openssl: not available") } +diff --git a/src/crypto/sha1/sha1_test.go b/src/crypto/sha1/sha1_test.go +index 85ed126091..71f4b46663 100644 +--- a/src/crypto/sha1/sha1_test.go ++++ b/src/crypto/sha1/sha1_test.go +@@ -8,7 +8,7 @@ package sha1 + + import ( + "bytes" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/rand" + "encoding" + "fmt" +@@ -78,7 +78,7 @@ func TestGolden(t *testing.T) { + io.WriteString(c, g.in[len(g.in)/2:]) + sum = c.Sum(nil) + case 3: +- if boring.Enabled { ++ if boring.Enabled() { + continue + } + io.WriteString(c, g.in[0:len(g.in)/2]) +@@ -145,7 +145,7 @@ func TestBlockSize(t *testing.T) { + + // Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match. + func TestBlockGeneric(t *testing.T) { +- if boring.Enabled { ++ if boring.Enabled() { + t.Skip("BoringCrypto doesn't expose digest") + } + for i := 1; i < 30; i++ { // arbitrary factor +@@ -218,7 +218,7 @@ func TestLargeHashes(t *testing.T) { + } + + func TestAllocations(t *testing.T) { +- if boring.Enabled { ++ if boring.Enabled() { + t.Skip("BoringCrypto doesn't allocate the same way as stdlib") + } + in := []byte("hello, world!") +diff --git a/src/crypto/sha256/sha256.go b/src/crypto/sha256/sha256.go +index 2deafbc9fc..282c326b32 100644 +--- a/src/crypto/sha256/sha256.go ++++ b/src/crypto/sha256/sha256.go +@@ -8,7 +8,7 @@ package sha256 + + import ( + "crypto" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "encoding/binary" + "errors" + "hash" +@@ -148,7 +148,7 @@ func (d *digest) Reset() { + // encoding.BinaryUnmarshaler to marshal and unmarshal the internal + // state of the hash. + func New() hash.Hash { +- if boring.Enabled { ++ if boring.Enabled() { + return boring.NewSHA256() + } + d := new(digest) +@@ -158,7 +158,7 @@ func New() hash.Hash { + + // New224 returns a new hash.Hash computing the SHA224 checksum. + func New224() hash.Hash { +- if boring.Enabled { ++ if boring.Enabled() { + return boring.NewSHA224() + } + d := new(digest) +@@ -251,7 +251,7 @@ func (d *digest) checkSum() [Size]byte { + + // Sum256 returns the SHA256 checksum of the data. + func Sum256(data []byte) [Size]byte { +- if boring.Enabled { ++ if boring.Enabled() { + return boring.SHA256(data) + } + var d digest +@@ -262,7 +262,7 @@ func Sum256(data []byte) [Size]byte { + + // Sum224 returns the SHA224 checksum of the data. + func Sum224(data []byte) [Size224]byte { +- if boring.Enabled { ++ if boring.Enabled() { + return boring.SHA224(data) + } + var d digest +diff --git a/src/crypto/sha256/sha256_test.go b/src/crypto/sha256/sha256_test.go +index 7304678346..a073d31119 100644 +--- a/src/crypto/sha256/sha256_test.go ++++ b/src/crypto/sha256/sha256_test.go +@@ -8,7 +8,7 @@ package sha256 + + import ( + "bytes" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/rand" + "encoding" + "fmt" +@@ -217,7 +217,7 @@ func TestBlockSize(t *testing.T) { + + // Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match. + func TestBlockGeneric(t *testing.T) { +- if boring.Enabled { ++ if boring.Enabled() { + t.Skip("BoringCrypto doesn't expose digest") + } + gen, asm := New().(*digest), New().(*digest) +@@ -294,7 +294,7 @@ func TestLargeHashes(t *testing.T) { + } + + func TestAllocations(t *testing.T) { +- if boring.Enabled { ++ if boring.Enabled() { + t.Skip("BoringCrypto doesn't allocate the same way as stdlib") + } + in := []byte("hello, world!") +diff --git a/src/crypto/sha512/sha512.go b/src/crypto/sha512/sha512.go +index 9ae1b3aae2..e56eedb201 100644 +--- a/src/crypto/sha512/sha512.go ++++ b/src/crypto/sha512/sha512.go +@@ -12,7 +12,7 @@ package sha512 + + import ( + "crypto" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "encoding/binary" + "errors" + "hash" +@@ -206,7 +206,7 @@ func consumeUint64(b []byte) ([]byte, uint64) { + + // New returns a new hash.Hash computing the SHA-512 checksum. + func New() hash.Hash { +- if boring.Enabled { ++ if boring.Enabled() { + return boring.NewSHA512() + } + d := &digest{function: crypto.SHA512} +@@ -230,7 +230,7 @@ func New512_256() hash.Hash { + + // New384 returns a new hash.Hash computing the SHA-384 checksum. + func New384() hash.Hash { +- if boring.Enabled { ++ if boring.Enabled() { + return boring.NewSHA384() + } + d := &digest{function: crypto.SHA384} +@@ -341,7 +341,7 @@ func (d *digest) checkSum() [Size]byte { + + // Sum512 returns the SHA512 checksum of the data. + func Sum512(data []byte) [Size]byte { +- if boring.Enabled { ++ if boring.Enabled() { + return boring.SHA512(data) + } + d := digest{function: crypto.SHA512} +@@ -352,7 +352,7 @@ func Sum512(data []byte) [Size]byte { + + // Sum384 returns the SHA384 checksum of the data. + func Sum384(data []byte) [Size384]byte { +- if boring.Enabled { ++ if boring.Enabled() { + return boring.SHA384(data) + } + d := digest{function: crypto.SHA384} +diff --git a/src/crypto/sha512/sha512_test.go b/src/crypto/sha512/sha512_test.go +index 921cdbb7bb..a35165bcbf 100644 +--- a/src/crypto/sha512/sha512_test.go ++++ b/src/crypto/sha512/sha512_test.go +@@ -8,7 +8,7 @@ package sha512 + + import ( + "bytes" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/rand" + "encoding" + "encoding/hex" +@@ -823,7 +823,7 @@ func TestBlockSize(t *testing.T) { + + // Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match. + func TestBlockGeneric(t *testing.T) { +- if boring.Enabled { ++ if boring.Enabled() { + t.Skip("BoringCrypto doesn't expose digest") + } + gen, asm := New().(*digest), New().(*digest) +@@ -893,7 +893,7 @@ func TestLargeHashes(t *testing.T) { + } + + func TestAllocations(t *testing.T) { +- if boring.Enabled { ++ if boring.Enabled() { + t.Skip("BoringCrypto doesn't allocate the same way as stdlib") + } + in := []byte("hello, world!") +diff --git a/src/crypto/tls/boring.go b/src/crypto/tls/boring.go +index 140b1a3dd8..fe6fa96d28 100644 +--- a/src/crypto/tls/boring.go ++++ b/src/crypto/tls/boring.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build boringcrypto ++//go:build !no_openssl + + package tls + +@@ -12,7 +12,7 @@ import ( + ) + + func init() { +- if boring.Enabled && !boring.ExecutingTest() { ++ if boring.Enabled() && !boring.ExecutingTest() { + fipstls.Force() + } + } +diff --git a/src/crypto/tls/boring_test.go b/src/crypto/tls/boring_test.go +index 7bfe3f9417..49702f59ba 100644 +--- a/src/crypto/tls/boring_test.go ++++ b/src/crypto/tls/boring_test.go +@@ -2,14 +2,14 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build boringcrypto ++//go:build !no_openssl + + package tls + + import ( + "crypto/ecdsa" + "crypto/elliptic" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/backend/boringtest" + "crypto/internal/boring/fipstls" + "crypto/rand" +@@ -46,7 +46,7 @@ func TestBoringServerProtocolVersion(t *testing.T) { + test("VersionTLS10", VersionTLS10, "") + test("VersionTLS11", VersionTLS11, "") + test("VersionTLS12", VersionTLS12, "") +- if boring.Enabled && !boring.SupportsHKDF() { ++ if boring.Enabled() && !boring.SupportsHKDF() { + test("VersionTLS13", VersionTLS13, "client offered only unsupported versions") + } else { + test("VersionTLS13", VersionTLS13, "") +@@ -238,7 +238,7 @@ func TestBoringServerSignatureAndHash(t *testing.T) { + + clientConfig := testConfig.Clone() + +- if boring.Enabled { ++ if boring.Enabled() { + serverConfig.Rand = boring.RandReader + clientConfig.Rand = boring.RandReader + } +@@ -369,7 +369,7 @@ func TestBoringCertAlgs(t *testing.T) { + serverConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}} + serverConfig.BuildNameToCertificate() + +- if boring.Enabled { ++ if boring.Enabled() { + serverConfig.Rand = boring.RandReader + clientConfig.Rand = boring.RandReader + } +@@ -400,13 +400,13 @@ func TestBoringCertAlgs(t *testing.T) { + serverConfig := testConfig.Clone() + serverConfig.ClientCAs = pool + serverConfig.ClientAuth = RequireAndVerifyClientCert +- if boring.Enabled { ++ if boring.Enabled() { + serverConfig.Certificates[0].Certificate = [][]byte{testRSA2048Certificate} + serverConfig.Certificates[0].PrivateKey = testRSA2048PrivateKey + serverConfig.BuildNameToCertificate() + } + +- if boring.Enabled { ++ if boring.Enabled() { + serverConfig.Rand = boring.RandReader + clientConfig.Rand = boring.RandReader + } +@@ -432,8 +432,8 @@ func TestBoringCertAlgs(t *testing.T) { + // exhaustive test with computed answers. + r1pool := x509.NewCertPool() + r1pool.AddCert(R1.cert) +- testServerCert(t, "basic", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, !(L2_I.notBoring && boring.Enabled)) +- testClientCert(t, "basic (client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, !(L2_I.notBoring && boring.Enabled)) ++ testServerCert(t, "basic", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, !(L2_I.notBoring && boring.Enabled())) ++ testClientCert(t, "basic (client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, !(L2_I.notBoring && boring.Enabled())) + fipstls.Force() + testServerCert(t, "basic (fips)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false) + testClientCert(t, "basic (fips, client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false) +@@ -454,7 +454,7 @@ func TestBoringCertAlgs(t *testing.T) { + leaf = L2_I + } + for i := 0; i < 64; i++ { +- reachable := map[string]bool{leaf.parentOrg: !(leaf.notBoring && boring.Enabled)} ++ reachable := map[string]bool{leaf.parentOrg: !(leaf.notBoring && boring.Enabled())} + reachableFIPS := map[string]bool{leaf.parentOrg: leaf.fipsOK} + list := [][]byte{leaf.der} + listName := leaf.name +@@ -462,7 +462,7 @@ func TestBoringCertAlgs(t *testing.T) { + if cond != 0 { + list = append(list, c.der) + listName += "," + c.name +- if reachable[c.org] && !(c.notBoring && boring.Enabled) { ++ if reachable[c.org] && !(c.notBoring && boring.Enabled()) { + reachable[c.parentOrg] = true + } + if reachableFIPS[c.org] && c.fipsOK { +@@ -486,7 +486,7 @@ func TestBoringCertAlgs(t *testing.T) { + if cond != 0 { + rootName += "," + c.name + pool.AddCert(c.cert) +- if reachable[c.org] && !(c.notBoring && boring.Enabled) { ++ if reachable[c.org] && !(c.notBoring && boring.Enabled()) { + shouldVerify = true + } + if reachableFIPS[c.org] && c.fipsOK { +diff --git a/src/crypto/tls/cipher_suites.go b/src/crypto/tls/cipher_suites.go +index 669208bb86..15a44e8cf6 100644 +--- a/src/crypto/tls/cipher_suites.go ++++ b/src/crypto/tls/cipher_suites.go +@@ -10,7 +10,7 @@ import ( + "crypto/cipher" + "crypto/des" + "crypto/hmac" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/rc4" + "crypto/sha1" + "crypto/sha256" +@@ -422,7 +422,7 @@ func macSHA1(key []byte) hash.Hash { + h := sha1.New + // The BoringCrypto SHA1 does not have a constant-time + // checksum function, so don't try to use it. +- if !boring.Enabled { ++ if !boring.Enabled() { + h = newConstantTimeHash(h) + } + return hmac.New(h, key) +@@ -514,7 +514,7 @@ func aeadAESGCM(key, noncePrefix []byte) aead { + panic(err) + } + var aead cipher.AEAD +- if boring.Enabled { ++ if boring.Enabled() { + aead, err = boring.NewGCMTLS(aes) + } else { + boring.Unreachable() +diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go +index 5edbd19995..a72d4855c1 100644 +--- a/src/crypto/tls/common.go ++++ b/src/crypto/tls/common.go +@@ -12,7 +12,7 @@ import ( + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/rand" + "crypto/rsa" + "crypto/sha512" +@@ -1032,7 +1032,7 @@ const roleServer = false + func (c *Config) supportedVersions(isClient bool) []uint16 { + versions := make([]uint16, 0, len(supportedVersions)) + for _, v := range supportedVersions { +- if boring.Enabled && !boring.SupportsHKDF() && v > VersionTLS12 { ++ if boring.Enabled() && !boring.SupportsHKDF() && v > VersionTLS12 { + continue + } + if needFIPS() && (v < fipsMinVersion(c) || v > fipsMaxVersion(c)) { +diff --git a/src/crypto/tls/key_schedule.go b/src/crypto/tls/key_schedule.go +index e7a360fdd4..9ea9eed2fb 100644 +--- a/src/crypto/tls/key_schedule.go ++++ b/src/crypto/tls/key_schedule.go +@@ -7,7 +7,7 @@ package tls + import ( + "crypto/ecdh" + "crypto/hmac" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "errors" + "fmt" + "hash" +@@ -60,7 +60,7 @@ func (c *cipherSuiteTLS13) expandLabel(secret []byte, label string, context []by + panic(fmt.Errorf("failed to construct HKDF label: %s", err)) + } + out := make([]byte, length) +- if boring.Enabled { ++ if boring.Enabled() { + reader, err := boring.ExpandHKDF(c.hash.New, secret, hkdfLabelBytes) + if err != nil { + panic("tls: HKDF-Expand-Label invocation failed unexpectedly") +@@ -91,7 +91,7 @@ func (c *cipherSuiteTLS13) extract(newSecret, currentSecret []byte) []byte { + if newSecret == nil { + newSecret = make([]byte, c.hash.Size()) + } +- if boring.Enabled { ++ if boring.Enabled() { + ikm, err := boring.ExtractHKDF(c.hash.New, newSecret, currentSecret) + if err != nil { + panic("tls: HKDF-Extract invocation failed unexpectedly") +diff --git a/src/crypto/tls/notboring.go b/src/crypto/tls/notboring.go +index 7d85b39c59..fe2719485b 100644 +--- a/src/crypto/tls/notboring.go ++++ b/src/crypto/tls/notboring.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build !boringcrypto ++//go:build no_openssl + + package tls + +diff --git a/src/crypto/x509/boring.go b/src/crypto/x509/boring.go +index 095b58c315..ac06591ea8 100644 +--- a/src/crypto/x509/boring.go ++++ b/src/crypto/x509/boring.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build boringcrypto ++//go:build !no_openssl + + package x509 + +diff --git a/src/crypto/x509/boring_test.go b/src/crypto/x509/boring_test.go +index 102acda578..07b3c7095e 100644 +--- a/src/crypto/x509/boring_test.go ++++ b/src/crypto/x509/boring_test.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build boringcrypto ++//go:build !no_openssl + + package x509 + +diff --git a/src/crypto/x509/notboring.go b/src/crypto/x509/notboring.go +index c83a7272c9..0c7dea2f1f 100644 +--- a/src/crypto/x509/notboring.go ++++ b/src/crypto/x509/notboring.go +@@ -2,7 +2,7 @@ + // Use of this source code is governed by a BSD-style + // license that can be found in the LICENSE file. + +-//go:build !boringcrypto ++//go:build no_openssl + + package x509 + +diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go +index 0c2cbf3182..e01c24292e 100644 +--- a/src/crypto/x509/x509_test.go ++++ b/src/crypto/x509/x509_test.go +@@ -12,7 +12,7 @@ import ( + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" +- "crypto/internal/boring" ++ boring "crypto/internal/backend" + "crypto/internal/backend/boringtest" + "crypto/rand" + "crypto/rsa" +@@ -653,7 +653,7 @@ func TestCreateSelfSignedCertificate(t *testing.T) { + extraExtensionData := []byte("extra extension") + + for _, test := range tests { +- if boring.Enabled && test.sigAlgo.isRSAPSS() { ++ if boring.Enabled() && test.sigAlgo.isRSAPSS() { + key, _ := test.priv.(*rsa.PrivateKey) + if key.PublicKey.N.BitLen() < 2048 { + t.Logf("skipping short key with BoringCrypto: %d", key.PublicKey.N.BitLen()) +@@ -3716,7 +3716,7 @@ func TestRevocationListCheckSignatureFrom(t *testing.T) { + var testCurve elliptic.Curve + // If OpenSSL supports P224, use the default upstream behavior, + // otherwise test with P384 +- if !boring.Enabled || boringtest.Supports(t, "CurveP224") { ++ if !boring.Enabled() || boringtest.Supports(t, "CurveP224") { + testCurve = elliptic.P224() + } else { + testCurve = elliptic.P384() +diff --git a/src/go.mod b/src/go.mod +<<<<<<< HEAD +<<<<<<< HEAD +index 3b24053b94..c4bc3c1e96 100644 +======= +<<<<<<< HEAD +<<<<<<< HEAD +index 25829e17f2..e19ef07e84 100644 +======= +index 25829e17f2..d8be04ccd3 100644 >>>>>>> 0023bf4c7a (rebase) -+ } -+ return pkey, nil -+} -+ -+// getECKey returns the EC_KEY from pkey. -+// If pkey does not contain an EC_KEY it panics. -+// The returned key should not be freed. +======= +index 25829e17f2..c6a0d5eb02 100644 +>>>>>>> 0b8240ca10 (support opensslv2, update strict fips checks) +>>>>>>> 86a5d8fade (Support openssl/v2 module) +======= +index 25829e17f2..c6a0d5eb02 100644 +>>>>>>> 3004231545 (fix config, regen 001) +--- a/src/go.mod ++++ b/src/go.mod +@@ -3,6 +3,7 @@ module std + go 1.21 + + require ( ++ github.com/golang-fips/openssl/v2 v2.0.0-rc.2.0.20230825145541-7544e9a0711b + golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d + golang.org/x/net v0.12.1-0.20231027154334-5ca955b1789c + ) +diff --git a/src/go.sum b/src/go.sum +<<<<<<< HEAD +<<<<<<< HEAD +index caf8ff010d..16a5d8c7da 100644 +======= +<<<<<<< HEAD <<<<<<< HEAD -+func getECKey(pkey *C.GO_EVP_PKEY) (key *C.GO_EC_KEY) { -+ key = C._goboringcrypto_EVP_PKEY_get0_EC_KEY(pkey) +index e474b8be31..0dab3e78f9 100644 +>>>>>>> 86a5d8fade (Support openssl/v2 module) +--- a/src/go.sum ++++ b/src/go.sum +@@ -1,3 +1,5 @@ ++github.com/golang-fips/openssl-fips v0.0.0-20230801192317-b175be2ccd46 h1:1oaM7kpYYlqwc6sIROINgj5fUW4CGZGEBwfzIc+TnJI= ++github.com/golang-fips/openssl-fips v0.0.0-20230801192317-b175be2ccd46/go.mod h1:V2IU8imz/VkScnIbTOrdYsZ5R88ZFypCE0LzhRJ3HsI= + golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d h1:LiA25/KWKuXfIq5pMIBq1s5hz3HQxhJJSu/SUGlD+SM= + golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= + golang.org/x/net v0.12.1-0.20231027154334-5ca955b1789c h1:d+VvAxu4S13DWtf73R5eY//VaCk3aUcVdyYjM1SX7zw= +diff --git a/src/vendor/github.com/golang-fips/openssl-fips/LICENSE b/src/vendor/github.com/golang-fips/openssl-fips/LICENSE +new file mode 100644 +index 0000000000..97e8515401 +--- /dev/null ++++ b/src/vendor/github.com/golang-fips/openssl-fips/LICENSE +======= +index e474b8be31..3f33a5d91d 100644 +======= ======= -+func getECKey(pkey C.GO_EVP_PKEY_PTR) (key C.GO_EC_KEY_PTR) { -+ if vMajor == 1 && vMinor == 0 { -+ if key0 := C.go_openssl_EVP_PKEY_get0(pkey); key0 != nil { -+ key = C.GO_EC_KEY_PTR(key0) -+ } -+ } else { -+ key = C.go_openssl_EVP_PKEY_get0_EC_KEY(pkey) -+ } ->>>>>>> 0023bf4c7a (rebase) -+ if key == nil { -+ panic("pkey does not contain an EC_KEY") -+ } -+ return key -+} -<<<<<<< HEAD -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/goopenssl.h b/src/vendor/github.com/golang-fips/openssl-fips/openssl/goopenssl.h +>>>>>>> 3004231545 (fix config, regen 001) +index e474b8be31..0c87e9b273 100644 +--- a/src/go.sum ++++ b/src/go.sum +@@ -1,3 +1,5 @@ ++github.com/golang-fips/openssl/v2 v2.0.0-rc.2.0.20230825145541-7544e9a0711b h1:tMz1iZ8n4ppQW9SOPzA1/7TcI5sixnWGSOra+R1qiic= ++github.com/golang-fips/openssl/v2 v2.0.0-rc.2.0.20230825145541-7544e9a0711b/go.mod h1:7tuBqX2Zov8Yq5mJ2yzlKhpnxOnWyEzi38AzeWRuQdg= + golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d h1:LiA25/KWKuXfIq5pMIBq1s5hz3HQxhJJSu/SUGlD+SM= + golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= + golang.org/x/net v0.12.1-0.20230712162946-57553cbff163 h1:1EDKNuaCsog7zGLEml1qRuO4gt23jORUQX2f0IKZ860= +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/.gitleaks.toml b/src/vendor/github.com/golang-fips/openssl/v2/.gitleaks.toml new file mode 100644 -index 0000000000..a900b3f9e7 +index 0000000000..aed2e22df2 --- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/goopenssl.h -@@ -0,0 +1,1099 @@ -+// 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. -+// +build linux -+// +build !android -+// +build !no_openssl -+// +build !cmd_go_bootstrap -+// +build !msan -+ -+// This header file describes the OpenSSL ABI as built for use in Go. -+ -+#include // size_t -+#include // uint8_t -+#include // memset -+ -+#include -+ -+#if OPENSSL_VERSION_NUMBER < 0x30000000 -+#define OPENSSL_DLSYM_CALL(handle, func) dlsym(handle, func) -+#else -+#define __USE_GNU -+#define OPENSSL_DLSYM_CALL(handle, func) dlvsym(handle, func, "OPENSSL_3.0.0") -+#endif -+ -+#include -+ -+#define unlikely(x) __builtin_expect(!!(x), 0) -+#define DEFINEFUNC(ret, func, args, argscall) \ -+ typedef ret(*_goboringcrypto_PTR_##func) args; \ -+ static _goboringcrypto_PTR_##func _g_##func = 0; \ -+ static inline ret _goboringcrypto_##func args \ -+ { \ -+ if (unlikely(!_g_##func)) \ -+ { \ -+ _g_##func = OPENSSL_DLSYM_CALL(handle, #func); \ -+ } \ -+ return _g_##func argscall; \ -+ } -+ -+#define DEFINEFUNCINTERNAL(ret, func, args, argscall) \ -+ typedef ret(*_goboringcrypto_internal_PTR_##func) args; \ -+ static _goboringcrypto_internal_PTR_##func _g_internal_##func = 0; \ -+ static inline ret _goboringcrypto_internal_##func args \ -+ { \ -+ if (unlikely(!_g_internal_##func)) \ -+ { \ -+ _g_internal_##func = OPENSSL_DLSYM_CALL(handle, #func); \ -+ } \ -+ return _g_internal_##func argscall; \ -+ } -+ -+#define DEFINEMACRO(ret, func, args, argscall) \ -+ static inline ret _goboringcrypto_##func args \ -+ { \ -+ return func argscall; \ -+ } -+ -+ -+static void* handle; -+static void* -+_goboringcrypto_DLOPEN_OPENSSL(void) -+{ -+ if (handle) -+ { -+ return handle; -+ } -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+ handle = dlopen("libcrypto.so.10", RTLD_NOW | RTLD_GLOBAL); -+#elif OPENSSL_VERSION_NUMBER < 0x30000000L -+ handle = dlopen("libcrypto.so.1.1", RTLD_NOW | RTLD_GLOBAL); -+#else -+ handle = dlopen("libcrypto.so.3", RTLD_NOW | RTLD_GLOBAL); -+#endif -+ return handle; -+} -+ -+#include -+#include -+ -+DEFINEFUNCINTERNAL(void, OPENSSL_init, (void), ()) -+ -+static unsigned long _goboringcrypto_internal_OPENSSL_VERSION_NUMBER(void) { -+ return OPENSSL_VERSION_NUMBER; -+} -+ -+static void -+_goboringcrypto_OPENSSL_setup(void) { -+ _goboringcrypto_internal_OPENSSL_init(); -+} -+ -+#include -+DEFINEFUNCINTERNAL(void, ERR_print_errors_fp, (FILE* fp), (fp)) -+#if OPENSSL_VERSION_NUMBER < 0x30000000 -+DEFINEFUNCINTERNAL(unsigned long, ERR_get_error_line_data, -+ (const char **file, int *line, const char **data, int *flags), -+ (file, line, data, flags)) -+static inline unsigned long -+_goboringcrypto_internal_ERR_get_error_all(const char **file, int *line, const char **func, const char **data, int *flags) -+{ -+ unsigned long e = _goboringcrypto_internal_ERR_get_error_line_data(file, line, data, flags); -+ if (e == 0 && func != NULL) { -+ *func = "unknown"; -+ } -+ return e; -+} -+#else -+DEFINEFUNCINTERNAL(unsigned long, ERR_get_error_all, -+ (const char **file, int *line, const char **func, const char **data, int *flags), -+ (file, line, func, data, flags)) -+#endif -+DEFINEFUNCINTERNAL(void, ERR_error_string_n, (unsigned long e, unsigned char *buf, size_t len), (e, buf, len)) -+ -+#include -+ -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+DEFINEFUNC(int, CRYPTO_num_locks, (void), ()) -+#else -+static inline int -+_goboringcrypto_CRYPTO_num_locks(void) { -+ return CRYPTO_num_locks(); /* defined as macro */ -+} -+#endif -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+DEFINEFUNC(void, CRYPTO_set_id_callback, (unsigned long (*id_function)(void)), (id_function)) -+#else -+static inline void -+_goboringcrypto_CRYPTO_set_id_callback(unsigned long (*id_function)(void)) { -+ CRYPTO_set_id_callback(id_function); /* defined as macro */ -+} -+#endif -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+DEFINEFUNC(void, CRYPTO_set_locking_callback, -+ (void (*locking_function)(int mode, int n, const char *file, int line)), -+ (locking_function)) -+#else -+static inline void -+_goboringcrypto_CRYPTO_set_locking_callback(void (*locking_function)(int mode, int n, const char *file, int line)) { -+ CRYPTO_set_locking_callback(locking_function); /* defined as macro */ -+} -+#endif -+ -+int _goboringcrypto_OPENSSL_thread_setup(void); -+ -+#if OPENSSL_VERSION_NUMBER < 0x30000000L -+DEFINEFUNC(int, FIPS_mode, (void), ()) -+DEFINEFUNC(int, FIPS_mode_set, (int r), (r)) -+#else -+DEFINEFUNC(int, EVP_default_properties_is_fips_enabled, (OSSL_LIB_CTX *libctx), (libctx)) -+static inline int _goboringcrypto_FIPS_mode(void) { -+ return _goboringcrypto_EVP_default_properties_is_fips_enabled(NULL); -+} -+#endif -+ -+#include -+ -+DEFINEFUNC(int, RAND_set_rand_method, (const RAND_METHOD *rand), (rand)) -+DEFINEFUNC(const RAND_METHOD*, RAND_get_rand_method, (void), ()) -+DEFINEFUNC(int, RAND_bytes, (uint8_t * arg0, size_t arg1), (arg0, arg1)) -+ -+int _goboringcrypto_stub_openssl_rand(void); -+int _goboringcrypto_restore_openssl_rand(void); -+int fbytes(unsigned char *buf, int num); -+ -+ -+#include -+ -+enum -+{ -+ GO_NID_md5_sha1 = NID_md5_sha1, -+ -+ GO_NID_secp224r1 = NID_secp224r1, -+ GO_NID_X9_62_prime256v1 = NID_X9_62_prime256v1, -+ GO_NID_secp384r1 = NID_secp384r1, -+ GO_NID_secp521r1 = NID_secp521r1, -+ -+ GO_NID_sha224 = NID_sha224, -+ GO_NID_sha256 = NID_sha256, -+ GO_NID_sha384 = NID_sha384, -+ GO_NID_sha512 = NID_sha512, -+}; -+ -+#include -+ -+typedef SHA_CTX GO_SHA_CTX; -+ -+DEFINEFUNC(int, SHA1_Init, (GO_SHA_CTX * arg0), (arg0)) -+DEFINEFUNC(int, SHA1_Update, (GO_SHA_CTX * arg0, const void *arg1, size_t arg2), (arg0, arg1, arg2)) -+DEFINEFUNC(int, SHA1_Final, (uint8_t * arg0, GO_SHA_CTX *arg1), (arg0, arg1)) -+ -+typedef SHA256_CTX GO_SHA256_CTX; -+ -+DEFINEFUNC(int, SHA224_Init, (GO_SHA256_CTX * arg0), (arg0)) -+DEFINEFUNC(int, SHA224_Update, (GO_SHA256_CTX * arg0, const void *arg1, size_t arg2), (arg0, arg1, arg2)) -+DEFINEFUNC(int, SHA224_Final, (uint8_t * arg0, GO_SHA256_CTX *arg1), (arg0, arg1)) -+ -+DEFINEFUNC(int, SHA256_Init, (GO_SHA256_CTX * arg0), (arg0)) -+DEFINEFUNC(int, SHA256_Update, (GO_SHA256_CTX * arg0, const void *arg1, size_t arg2), (arg0, arg1, arg2)) -+DEFINEFUNC(int, SHA256_Final, (uint8_t * arg0, GO_SHA256_CTX *arg1), (arg0, arg1)) -+ -+typedef SHA512_CTX GO_SHA512_CTX; -+DEFINEFUNC(int, SHA384_Init, (GO_SHA512_CTX * arg0), (arg0)) -+DEFINEFUNC(int, SHA384_Update, (GO_SHA512_CTX * arg0, const void *arg1, size_t arg2), (arg0, arg1, arg2)) -+DEFINEFUNC(int, SHA384_Final, (uint8_t * arg0, GO_SHA512_CTX *arg1), (arg0, arg1)) -+ -+DEFINEFUNC(int, SHA512_Init, (GO_SHA512_CTX * arg0), (arg0)) -+DEFINEFUNC(int, SHA512_Update, (GO_SHA512_CTX * arg0, const void *arg1, size_t arg2), (arg0, arg1, arg2)) -+DEFINEFUNC(int, SHA512_Final, (uint8_t * arg0, GO_SHA512_CTX *arg1), (arg0, arg1)) -+ -+#include -+ -+typedef EVP_MD GO_EVP_MD; -+DEFINEFUNC(const GO_EVP_MD *, EVP_md4, (void), ()) -+DEFINEFUNC(const GO_EVP_MD *, EVP_md5, (void), ()) -+DEFINEFUNC(const GO_EVP_MD *, EVP_sha1, (void), ()) -+DEFINEFUNC(const GO_EVP_MD *, EVP_sha224, (void), ()) -+DEFINEFUNC(const GO_EVP_MD *, EVP_sha256, (void), ()) -+DEFINEFUNC(const GO_EVP_MD *, EVP_sha384, (void), ()) -+DEFINEFUNC(const GO_EVP_MD *, EVP_sha512, (void), ()) -+DEFINEFUNC(const GO_EVP_MD *, EVP_md_null, (void), ()) -+#if OPENSSL_VERSION_NUMBER < 0x30000000L -+DEFINEFUNCINTERNAL(int, EVP_MD_type, (const GO_EVP_MD *arg0), (arg0)) -+DEFINEFUNCINTERNAL(int, EVP_MD_size, (const GO_EVP_MD *arg0), (arg0)) -+static inline int -+_goboringcrypto_EVP_MD_get_size(const GO_EVP_MD *arg0) -+{ -+ return _goboringcrypto_internal_EVP_MD_size(arg0); -+} -+#else -+DEFINEFUNCINTERNAL(int, EVP_MD_get_type, (const GO_EVP_MD *arg0), (arg0)) -+DEFINEFUNC(int, EVP_MD_get_size, (const GO_EVP_MD *arg0), (arg0)) -+#endif -+DEFINEFUNCINTERNAL(const GO_EVP_MD*, EVP_md5_sha1, (void), ()) -+ -+# include -+DEFINEFUNCINTERNAL(int, MD5_Init, (MD5_CTX *c), (c)) -+DEFINEFUNCINTERNAL(int, MD5_Update, (MD5_CTX *c, const void *data, size_t len), (c, data, len)) -+DEFINEFUNCINTERNAL(int, MD5_Final, (unsigned char *md, MD5_CTX *c), (md, c)) -+ -+static inline int -+_goboringcrypto_EVP_MD_type(const GO_EVP_MD *md) { -+#if OPENSSL_VERSION_NUMBER < 0x30000000L -+ return _goboringcrypto_internal_EVP_MD_type(md); -+#else -+ return _goboringcrypto_internal_EVP_MD_get_type(md); -+#endif -+} -+ -+const GO_EVP_MD* _goboringcrypto_backport_EVP_md5_sha1(void); -+static inline const GO_EVP_MD* -+_goboringcrypto_EVP_md5_sha1(void) { -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+ return _goboringcrypto_backport_EVP_md5_sha1(); -+#else -+ return _goboringcrypto_internal_EVP_md5_sha1(); -+#endif -+} -+ -+#include -+ -+typedef HMAC_CTX GO_HMAC_CTX; -+ -+DEFINEFUNC(int, HMAC_Init_ex, -+ (GO_HMAC_CTX * arg0, const void *arg1, int arg2, const GO_EVP_MD *arg3, ENGINE *arg4), -+ (arg0, arg1, arg2, arg3, arg4)) -+DEFINEFUNC(int, HMAC_Update, (GO_HMAC_CTX * arg0, const uint8_t *arg1, size_t arg2), (arg0, arg1, arg2)) -+DEFINEFUNC(int, HMAC_Final, (GO_HMAC_CTX * arg0, uint8_t *arg1, unsigned int *arg2), (arg0, arg1, arg2)) -+DEFINEFUNC(size_t, HMAC_CTX_copy, (GO_HMAC_CTX *dest, GO_HMAC_CTX *src), (dest, src)) -+ -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+DEFINEFUNCINTERNAL(void, HMAC_CTX_cleanup, (GO_HMAC_CTX * arg0), (arg0)) -+static inline void -+_goboringcrypto_HMAC_CTX_free(HMAC_CTX *ctx) { -+ if (ctx != NULL) { -+ _goboringcrypto_internal_HMAC_CTX_cleanup(ctx); -+ free(ctx); -+ } -+} -+#else -+DEFINEFUNC(void, HMAC_CTX_free, (GO_HMAC_CTX * arg0), (arg0)) -+#endif -+ -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+static inline size_t -+_goboringcrypto_HMAC_size(const GO_HMAC_CTX* arg0) { -+ return _goboringcrypto_EVP_MD_get_size(arg0->md); -+} -+#else -+DEFINEFUNCINTERNAL(const EVP_MD*, HMAC_CTX_get_md, (const GO_HMAC_CTX* ctx), (ctx)) -+static inline size_t -+_goboringcrypto_HMAC_size(const GO_HMAC_CTX* arg0) { -+ const EVP_MD* md; -+ md = _goboringcrypto_internal_HMAC_CTX_get_md(arg0); -+ return _goboringcrypto_EVP_MD_get_size(md); -+} -+#endif -+ -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+DEFINEFUNCINTERNAL(void, HMAC_CTX_init, (GO_HMAC_CTX * arg0), (arg0)) -+static inline GO_HMAC_CTX* -+_goboringcrypto_HMAC_CTX_new(void) { -+ GO_HMAC_CTX* ctx = malloc(sizeof(GO_HMAC_CTX)); -+ if (ctx != NULL) -+ _goboringcrypto_internal_HMAC_CTX_init(ctx); -+ return ctx; -+} -+#else -+DEFINEFUNC(GO_HMAC_CTX*, HMAC_CTX_new, (void), ()) -+#endif -+ -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+static inline int -+_goboringcrypto_HMAC_CTX_reset(GO_HMAC_CTX* ctx) { -+ _goboringcrypto_internal_HMAC_CTX_cleanup(ctx); -+ _goboringcrypto_internal_HMAC_CTX_init(ctx); -+ return 0; -+} -+#else -+DEFINEFUNC(int, HMAC_CTX_reset, (GO_HMAC_CTX * arg0), (arg0)) -+#endif -+ -+int _goboringcrypto_HMAC_CTX_copy_ex(GO_HMAC_CTX *dest, const GO_HMAC_CTX *src); -+ -+#include -+#include -+ -+DEFINEFUNC(EVP_CIPHER_CTX *, EVP_CIPHER_CTX_new, (void), ()) -+DEFINEFUNC(int, EVP_CIPHER_CTX_set_padding, (EVP_CIPHER_CTX *x, int padding), (x, padding)) -+DEFINEFUNC(int, EVP_CipherInit_ex, -+ (EVP_CIPHER_CTX * ctx, const EVP_CIPHER *type, ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc), -+ (ctx, type, impl, key, iv, enc)) -+DEFINEFUNC(int, EVP_CipherUpdate, -+ (EVP_CIPHER_CTX * ctx, unsigned char *out, int *outl, const unsigned char *in, int inl), -+ (ctx, out, outl, in, inl)) -+ -+void _goboringcrypto_EVP_AES_ctr128_enc(EVP_CIPHER_CTX *ctx, const uint8_t *in, uint8_t *out, size_t len); -+ -+int _goboringcrypto_EVP_AES_encrypt(EVP_CIPHER_CTX *ctx, const uint8_t *in, size_t in_len, uint8_t *out); -+ -+enum -+{ -+ GO_AES_ENCRYPT = 1, -+ GO_AES_DECRYPT = 0 -+}; -+void _goboringcrypto_EVP_AES_cbc_encrypt(EVP_CIPHER_CTX *ctx, const uint8_t *arg0, uint8_t *arg1, size_t arg2, const uint8_t *a, const int arg5); -+DEFINEFUNC(void, AES_cbc_encrypt, -+ (const unsigned char *in, unsigned char *out, -+ size_t length, const AES_KEY *key, -+ unsigned char *ivec, const int enc), -+ (in, out, length, key, ivec, enc)) -+ -+void EVP_AES_cbc_enc(EVP_CIPHER_CTX *ctx, const uint8_t *in, uint8_t *out, size_t len); -+ -+void EVP_AES_cbc_dec(EVP_CIPHER_CTX *ctx, const uint8_t *in, uint8_t *out, size_t len); -+ -+typedef ENGINE GO_ENGINE; -+ -+#include -+ -+typedef BN_CTX GO_BN_CTX; -+typedef BIGNUM GO_BIGNUM; -+ -+DEFINEFUNC(GO_BIGNUM *, BN_new, (void), ()) -+DEFINEFUNC(void, BN_free, (GO_BIGNUM * arg0), (arg0)) -+DEFINEFUNC(void, BN_clear_free, (GO_BIGNUM * arg0), (arg0)) -+DEFINEFUNC(int, BN_set_word, (BIGNUM *a, BN_ULONG w), (a, w)) -+DEFINEFUNC(unsigned int, BN_num_bits, (const GO_BIGNUM *arg0), (arg0)) -+DEFINEFUNC(int, BN_is_negative, (const GO_BIGNUM *arg0), (arg0)) -+DEFINEFUNC(GO_BIGNUM *, BN_bin2bn, (const uint8_t *arg0, size_t arg1, GO_BIGNUM *arg2), (arg0, arg1, arg2)) -+ -+static inline int -+_goboringcrypto_BN_num_bytes(const GO_BIGNUM* a) { -+ return ((_goboringcrypto_BN_num_bits(a)+7)/8); -+} -+ -+#if OPENSSL_VERSION_NUMBER >= 0x10100000L -+DEFINEFUNC(GO_BIGNUM *, BN_lebin2bn, (const unsigned char *s, int len, GO_BIGNUM *ret), (s, len, ret)) -+DEFINEFUNC(int, BN_bn2lebinpad, (const GO_BIGNUM *a, unsigned char *to, int tolen), (a, to, tolen)) -+DEFINEFUNC(int, BN_bn2binpad, (const GO_BIGNUM *a, unsigned char *to, int tolen), (a, to, tolen)) -+#else -+DEFINEFUNCINTERNAL(int, BN_bn2bin, (const GO_BIGNUM *a, unsigned char *to), (a, to)) -+ -+static inline GO_BIGNUM * -+_goboringcrypto_BN_lebin2bn(const unsigned char *s, int len, GO_BIGNUM *ret) -+{ -+ unsigned char *copy; -+ size_t i; -+ GO_BIGNUM *result; -+ -+ copy = malloc(len); -+ if (!copy) -+ return NULL; -+ for (i = 0; i < len; i++) -+ copy[i] = s[len - i - 1]; -+ -+ result = _goboringcrypto_BN_bin2bn(copy, len, ret); -+ free(copy); -+ return result; -+} -+ -+static inline int -+_goboringcrypto_BN_bn2binpad(const GO_BIGNUM *a, unsigned char *to, int tolen) -+{ -+ int size = _goboringcrypto_BN_num_bytes(a); -+ int i; -+ -+ if (size > tolen) -+ return -1; -+ -+ memset(to, 0, tolen - size); -+ if (_goboringcrypto_internal_BN_bn2bin(a, to + tolen - size) != size) -+ return -1; -+ -+ return tolen; -+} -+ -+static inline int -+_goboringcrypto_BN_bn2lebinpad(const GO_BIGNUM *a, unsigned char *to, int tolen) -+{ -+ int size = _goboringcrypto_BN_bn2binpad(a, to, tolen); -+ int i; -+ -+ if (size != tolen) -+ return -1; -+ -+ /* reverse bytes */ -+ for (i = 0; i < tolen / 2; i++) { -+ unsigned char tmp; -+ -+ tmp = to[i]; -+ to[i] = to[tolen - i - 1]; -+ to[tolen - i - 1] = tmp; -+ } -+ -+ return tolen; -+} -+#endif -+ -+#include -+ -+enum { -+ GO_EVP_PKEY_EC = EVP_PKEY_EC, -+}; -+ -+typedef EC_GROUP GO_EC_GROUP; -+ -+DEFINEFUNC(GO_EC_GROUP *, EC_GROUP_new_by_curve_name, (int arg0), (arg0)) -+DEFINEFUNC(void, EC_GROUP_free, (GO_EC_GROUP * arg0), (arg0)) -+ -+typedef EC_POINT GO_EC_POINT; -+ -+DEFINEFUNC(GO_EC_POINT *, EC_POINT_new, (const GO_EC_GROUP *arg0), (arg0)) -+DEFINEFUNC(void, EC_POINT_free, (GO_EC_POINT * arg0), (arg0)) -+DEFINEFUNC(int, EC_POINT_get_affine_coordinates_GFp, -+ (const GO_EC_GROUP *arg0, const GO_EC_POINT *arg1, GO_BIGNUM *arg2, GO_BIGNUM *arg3, GO_BN_CTX *arg4), -+ (arg0, arg1, arg2, arg3, arg4)) -+DEFINEFUNC(int, EC_POINT_set_affine_coordinates_GFp, -+ (const GO_EC_GROUP *arg0, GO_EC_POINT *arg1, const GO_BIGNUM *arg2, const GO_BIGNUM *arg3, GO_BN_CTX *arg4), -+ (arg0, arg1, arg2, arg3, arg4)) -+ -+typedef EC_KEY GO_EC_KEY; -+ -+DEFINEFUNC(GO_EC_KEY *, EC_KEY_new, (void), ()) -+DEFINEFUNC(GO_EC_KEY *, EC_KEY_new_by_curve_name, (int arg0), (arg0)) -+DEFINEFUNC(void, EC_KEY_free, (GO_EC_KEY * arg0), (arg0)) -+DEFINEFUNC(const GO_EC_GROUP *, EC_KEY_get0_group, (const GO_EC_KEY *arg0), (arg0)) -+DEFINEFUNC(int, EC_KEY_set_group, (GO_EC_KEY *arg0, const EC_GROUP *arg1), (arg0, arg1)) -+DEFINEFUNC(int, EC_KEY_generate_key, (GO_EC_KEY * arg0), (arg0)) -+DEFINEFUNC(int, EC_KEY_set_private_key, (GO_EC_KEY * arg0, const GO_BIGNUM *arg1), (arg0, arg1)) -+DEFINEFUNC(int, EC_KEY_set_public_key, (GO_EC_KEY * arg0, const GO_EC_POINT *arg1), (arg0, arg1)) -+DEFINEFUNC(const GO_BIGNUM *, EC_KEY_get0_private_key, (const GO_EC_KEY *arg0), (arg0)) -+DEFINEFUNC(const GO_EC_POINT *, EC_KEY_get0_public_key, (const GO_EC_KEY *arg0), (arg0)) -+DEFINEFUNC(size_t, EC_POINT_point2oct, (const GO_EC_GROUP *group, const GO_EC_POINT *p, point_conversion_form_t form, unsigned char *buf, size_t len, GO_BN_CTX *ctx), (group, p, form, buf, len, ctx)) -+DEFINEFUNC(int, EC_POINT_oct2point, (const GO_EC_GROUP *group, GO_EC_POINT *p, const unsigned char *buf, size_t len, GO_BN_CTX *ctx), (group, p, buf, len, ctx)) -+ -+#if OPENSSL_VERSION_NUMBER >= 0x10100000L -+DEFINEFUNC(int, EC_KEY_oct2key, (GO_EC_KEY *arg0, const unsigned char *arg1, size_t arg2, BN_CTX *arg3), (arg0, arg1, arg2, arg3)) -+#else -+static inline int -+_goboringcrypto_EC_KEY_oct2key(GO_EC_KEY *eckey, const unsigned char *buf, size_t len, BN_CTX *ctx) -+{ -+ const GO_EC_GROUP *group = _goboringcrypto_EC_KEY_get0_group(eckey); -+ GO_EC_POINT *pubkey; -+ int ret = 1; -+ -+ pubkey = _goboringcrypto_EC_POINT_new(group); -+ if (!pubkey) -+ return 0; -+ -+ if (_goboringcrypto_EC_POINT_oct2point(group, pubkey, buf, len, ctx) != 1 || -+ _goboringcrypto_EC_KEY_set_public_key(eckey, pubkey) != 1) -+ ret = 0; -+ -+ _goboringcrypto_EC_POINT_free(pubkey); -+ return ret; -+} -+#endif -+ -+// TODO: EC_KEY_check_fips? -+ -+#include -+ -+typedef ECDSA_SIG GO_ECDSA_SIG; -+ -+DEFINEFUNC(GO_ECDSA_SIG *, ECDSA_SIG_new, (void), ()) -+DEFINEFUNC(void, ECDSA_SIG_free, (GO_ECDSA_SIG * arg0), (arg0)) -+DEFINEFUNC(GO_ECDSA_SIG *, ECDSA_do_sign, (const uint8_t *arg0, size_t arg1, const GO_EC_KEY *arg2), (arg0, arg1, arg2)) -+DEFINEFUNC(int, ECDSA_do_verify, (const uint8_t *arg0, size_t arg1, const GO_ECDSA_SIG *arg2, GO_EC_KEY *arg3), (arg0, arg1, arg2, arg3)) -+DEFINEFUNC(size_t, ECDSA_size, (const GO_EC_KEY *arg0), (arg0)) -+ -+DEFINEFUNCINTERNAL(int, ECDSA_sign, -+ (int type, const unsigned char *dgst, size_t dgstlen, unsigned char *sig, unsigned int *siglen, EC_KEY *eckey), -+ (type, dgst, dgstlen, sig, siglen, eckey)) -+ -+DEFINEFUNCINTERNAL(int, ECDSA_verify, -+ (int type, const unsigned char *dgst, size_t dgstlen, const unsigned char *sig, unsigned int siglen, EC_KEY *eckey), -+ (type, dgst, dgstlen, sig, siglen, eckey)) -+ -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+DEFINEFUNC(EVP_MD_CTX*, EVP_MD_CTX_create, (void), ()) -+#else -+DEFINEFUNCINTERNAL(EVP_MD_CTX*, EVP_MD_CTX_new, (void), ()) -+static inline EVP_MD_CTX* _goboringcrypto_EVP_MD_CTX_create(void) { -+ return _goboringcrypto_internal_EVP_MD_CTX_new(); -+} -+#endif -+ -+DEFINEFUNCINTERNAL(int, EVP_PKEY_assign, -+ (EVP_PKEY *pkey, int type, void *eckey), -+ (pkey, type, eckey)) -+ -+static inline int -+_goboringcrypto_EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, GO_EC_KEY *eckey) { -+ return _goboringcrypto_internal_EVP_PKEY_assign(pkey, EVP_PKEY_EC, (char *)(eckey)); -+} -+ -+static inline int -+_goboringcrypto_EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *rsa) { -+ return _goboringcrypto_internal_EVP_PKEY_assign(pkey, EVP_PKEY_RSA, (char *)(rsa)); -+} -+ -+DEFINEFUNC(int, EVP_DigestSignInit, -+ (EVP_MD_CTX* ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey), -+ (ctx, pctx, type, e, pkey)) -+ -+DEFINEFUNC(int, EVP_DigestUpdate, -+ (EVP_MD_CTX* ctx, const void *d, size_t cnt), -+ (ctx, d, cnt)) -+DEFINEFUNC(int, EVP_DigestSignFinal, -+ (EVP_MD_CTX* ctx, unsigned char *sig, size_t *siglen), -+ (ctx, sig, siglen)) -+ -+DEFINEFUNC(int, EVP_DigestVerifyInit, -+ (EVP_MD_CTX* ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey), -+ (ctx, pctx, type, e, pkey)) -+DEFINEFUNC(int, EVP_DigestVerifyFinal, -+ (EVP_MD_CTX* ctx, const uint8_t *sig, unsigned int siglen), -+ (ctx, sig, siglen)) -+ -+typedef RSA GO_RSA; -+int _goboringcrypto_EVP_sign(EVP_MD* md, EVP_PKEY_CTX *ctx, const uint8_t *msg, size_t msgLen, uint8_t *sig, size_t *slen, EVP_PKEY *eckey); -+int _goboringcrypto_EVP_sign_raw(EVP_MD *md, EVP_PKEY_CTX *ctx, const uint8_t *msg, -+ size_t msgLen, uint8_t *sig, size_t *slen, -+ GO_RSA *key); -+ -+int _goboringcrypto_EVP_verify(EVP_MD* md, EVP_PKEY_CTX *ctx, const uint8_t *msg, size_t msgLen, const uint8_t *sig, unsigned int slen, EVP_PKEY *key); -+int _goboringcrypto_EVP_verify_raw(const uint8_t *msg, size_t msgLen, -+ const uint8_t *sig, unsigned int slen, -+ GO_RSA *key); -+ -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+DEFINEFUNCINTERNAL(void, EVP_MD_CTX_destroy, (EVP_MD_CTX *ctx), (ctx)) -+static inline void _goboringcrypto_EVP_MD_CTX_free(EVP_MD_CTX *ctx) { -+ return _goboringcrypto_internal_EVP_MD_CTX_destroy(ctx); -+} -+#else -+DEFINEFUNC(void, EVP_MD_CTX_free, (EVP_MD_CTX *ctx), (ctx)) -+#endif -+ -+int _goboringcrypto_ECDSA_sign(EVP_MD *md, const uint8_t *arg1, size_t arg2, uint8_t *arg3, size_t *arg4, GO_EC_KEY *arg5); -+int _goboringcrypto_ECDSA_verify(EVP_MD *md, const uint8_t *arg1, size_t arg2, const uint8_t *arg3, unsigned int arg4, GO_EC_KEY *arg5); -+ -+#include -+ -+// Note: order of struct fields here is unchecked. -+typedef BN_GENCB GO_BN_GENCB; -+ -+int _goboringcrypto_EVP_RSA_sign(EVP_MD* md, const uint8_t *msg, unsigned int msgLen, uint8_t *sig, size_t *slen, RSA *rsa); -+int _goboringcrypto_EVP_RSA_verify(EVP_MD* md, const uint8_t *msg, unsigned int msgLen, const uint8_t *sig, unsigned int slen, GO_RSA *rsa); -+ -+DEFINEFUNC(GO_RSA *, RSA_new, (void), ()) -+DEFINEFUNC(void, RSA_free, (GO_RSA * arg0), (arg0)) -+DEFINEFUNC(int, RSA_private_encrypt, -+ (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding), -+ (flen, from, to, rsa, padding)) -+DEFINEFUNC(int, RSA_public_decrypt, -+ (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding), -+ (flen, from, to, rsa, padding)) -+DEFINEFUNC(int, RSA_sign, -+ (int arg0, const uint8_t *arg1, unsigned int arg2, uint8_t *arg3, unsigned int *arg4, GO_RSA *arg5), -+ (arg0, arg1, arg2, arg3, arg4, arg5)) -+DEFINEFUNC(int, RSA_verify, -+ (int arg0, const uint8_t *arg1, unsigned int arg2, const uint8_t *arg3, unsigned int arg4, GO_RSA *arg5), -+ (arg0, arg1, arg2, arg3, arg4, arg5)) -+DEFINEFUNC(int, RSA_generate_key_ex, -+ (GO_RSA * arg0, int arg1, GO_BIGNUM *arg2, GO_BN_GENCB *arg3), -+ (arg0, arg1, arg2, arg3)) -+ -+DEFINEFUNCINTERNAL(int, RSA_set0_factors, -+ (GO_RSA * rsa, GO_BIGNUM *p, GO_BIGNUM *q), -+ (rsa, p, q)) ++++ b/src/vendor/github.com/golang-fips/openssl/v2/.gitleaks.toml +@@ -0,0 +1,9 @@ ++# ++# GitLeaks Repo Specific Configuration ++# ++# This allowlist is used to ignore false positives during secret scans. + -+static inline int -+_goboringcrypto_RSA_set0_factors(GO_RSA * r, GO_BIGNUM *p, GO_BIGNUM *q) { -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+ /* If the fields p and q in r are NULL, the corresponding input -+ * parameters MUST be non-NULL. -+ */ -+ if ((r->p == NULL && p == NULL) -+ || (r->q == NULL && q == NULL)) -+ return 0; ++[allowlist] ++paths = [ ++ 'ecdh_test.go', ++] +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/LICENSE b/src/vendor/github.com/golang-fips/openssl/v2/LICENSE +new file mode 100644 +index 0000000000..97e8515401 +--- /dev/null ++++ b/src/vendor/github.com/golang-fips/openssl/v2/LICENSE +@@ -0,0 +1,20 @@ ++The MIT License (MIT) + -+ if (p != NULL) { -+ _goboringcrypto_BN_clear_free(r->p); -+ r->p = p; -+ } -+ if (q != NULL) { -+ _goboringcrypto_BN_clear_free(r->q); -+ r->q = q; -+ } ++Copyright (c) 2022 The Golang FIPS Authors + -+ return 1; -+#else -+ return _goboringcrypto_internal_RSA_set0_factors(r, p, q); -+#endif -+} ++Permission is hereby granted, free of charge, to any person obtaining a copy of ++this software and associated documentation files (the "Software"), to deal in ++the Software without restriction, including without limitation the rights to ++use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ++the Software, and to permit persons to whom the Software is furnished to do so, ++subject to the following conditions: + -+DEFINEFUNCINTERNAL(int, RSA_set0_crt_params, -+ (GO_RSA * rsa, GO_BIGNUM *dmp1, GO_BIGNUM *dmp2, GO_BIGNUM *iqmp), -+ (rsa, dmp1, dmp2, iqmp)) ++The above copyright notice and this permission notice shall be included in all ++copies or substantial portions of the Software. + -+static inline int -+_goboringcrypto_RSA_set0_crt_params(GO_RSA * r, GO_BIGNUM *dmp1, GO_BIGNUM *dmq1, GO_BIGNUM *iqmp) { -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+ /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input -+ * parameters MUST be non-NULL. -+ */ -+ if ((r->dmp1 == NULL && dmp1 == NULL) -+ || (r->dmq1 == NULL && dmq1 == NULL) -+ || (r->iqmp == NULL && iqmp == NULL)) -+ return 0; ++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ++FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ++COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ++IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ++CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +\ No newline at end of file +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/README.md b/src/vendor/github.com/golang-fips/openssl/v2/README.md +new file mode 100644 +index 0000000000..e12474e6b5 +--- /dev/null ++++ b/src/vendor/github.com/golang-fips/openssl/v2/README.md +@@ -0,0 +1,62 @@ ++# Go OpenSSL bindings for FIPS compliance + -+ if (dmp1 != NULL) { -+ _goboringcrypto_BN_clear_free(r->dmp1); -+ r->dmp1 = dmp1; -+ } -+ if (dmq1 != NULL) { -+ _goboringcrypto_BN_clear_free(r->dmq1); -+ r->dmq1 = dmq1; -+ } -+ if (iqmp != NULL) { -+ _goboringcrypto_BN_clear_free(r->iqmp); -+ r->iqmp = iqmp; -+ } ++[![Go Reference](https://pkg.go.dev/badge/github.com/golang-fips/openssl.svg)](https://pkg.go.dev/github.com/golang-fips/openssl) + -+ return 1; -+#else -+ return _goboringcrypto_internal_RSA_set0_crt_params(r, dmp1, dmq1, iqmp); -+#endif -+} ++The `openssl` package implements Go crypto primitives using OpenSSL shared libraries and cgo. When configured correctly, OpenSSL can be executed in FIPS mode, making the `openssl` package FIPS compliant. + -+DEFINEFUNCINTERNAL(void, RSA_get0_crt_params, -+ (const GO_RSA *r, const GO_BIGNUM **dmp1, const GO_BIGNUM **dmq1, const GO_BIGNUM **iqmp), -+ (r, dmp1, dmq1, iqmp)) -+static inline void -+_goboringcrypto_RSA_get0_crt_params(const GO_RSA *r, const GO_BIGNUM **dmp1, const GO_BIGNUM **dmq1, const GO_BIGNUM **iqmp) { -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+ if (dmp1 != NULL) -+ *dmp1 = r->dmp1; -+ if (dmq1 != NULL) -+ *dmq1 = r->dmq1; -+ if (iqmp != NULL) -+ *iqmp = r->iqmp; -+#else -+ _goboringcrypto_internal_RSA_get0_crt_params(r, dmp1, dmq1, iqmp); -+#endif -+} ++The `openssl` package is designed to be used as a drop-in replacement for the [boring](https://pkg.go.dev/crypto/internal/boring) package in order to facilitate integrating `openssl` inside a forked Go toolchain. + ++## Disclaimer + -+DEFINEFUNCINTERNAL(int, RSA_set0_key, -+ (GO_RSA * r, GO_BIGNUM *n, GO_BIGNUM *e, GO_BIGNUM *d), -+ (r, n, e, d)) -+static inline int -+_goboringcrypto_RSA_set0_key(GO_RSA * r, GO_BIGNUM *n, GO_BIGNUM *e, GO_BIGNUM *d) { -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+ /* If the fields n and e in r are NULL, the corresponding input -+ * parameters MUST be non-NULL for n and e. d may be -+ * left NULL (in case only the public key is used). -+ */ -+ if ((r->n == NULL && n == NULL) -+ || (r->e == NULL && e == NULL)) -+ return 0; ++A program directly or indirectly using this package in FIPS mode can claim it is using a FIPS-certified cryptographic module (OpenSSL), but it can't claim the program as a whole is FIPS certified without passing the certification process, nor claim it is FIPS compliant without ensuring all crypto APIs and workflows are implemented in a FIPS-compliant manner. + -+ if (n != NULL) { -+ _goboringcrypto_BN_free(r->n); -+ r->n = n; -+ } -+ if (e != NULL) { -+ _goboringcrypto_BN_free(r->e); -+ r->e = e; -+ } -+ if (d != NULL) { -+ _goboringcrypto_BN_clear_free(r->d); -+ r->d = d; -+ } ++## Background + -+ return 1; -+#else -+ return _goboringcrypto_internal_RSA_set0_key(r, n, e, d); -+#endif -+} ++FIPS 140-2 is a U.S. government computer security standard used to approve cryptographic modules. FIPS compliance may come up when working with U.S. government and other regulated industries. + -+DEFINEFUNCINTERNAL(void, RSA_get0_factors, -+ (const GO_RSA *rsa, const GO_BIGNUM **p, const GO_BIGNUM **q), -+ (rsa, p, q)) -+static inline void -+_goboringcrypto_RSA_get0_factors(const GO_RSA *rsa, const GO_BIGNUM **p, const GO_BIGNUM **q) { -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+ if (p) -+ *p = rsa->p; -+ if (q) -+ *q = rsa->q; -+#else -+ _goboringcrypto_internal_RSA_get0_factors(rsa, p, q); -+#endif -+} ++### Go FIPS compliance + -+DEFINEFUNCINTERNAL(void, RSA_get0_key, -+ (const GO_RSA *rsa, const GO_BIGNUM **n, const GO_BIGNUM **e, const GO_BIGNUM **d), -+ (rsa, n, e, d)) -+static inline void -+_goboringcrypto_RSA_get0_key(const GO_RSA *rsa, const GO_BIGNUM **n, const GO_BIGNUM **e, const GO_BIGNUM **d) { -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+ if (n) -+ *n = rsa->n; -+ if (e) -+ *e = rsa->e; -+ if (d) -+ *d = rsa->d; -+#else -+ _goboringcrypto_internal_RSA_get0_key(rsa, n, e, d); -+#endif -+} ++The Go `crypto` package is not FIPS certified, and the Go team has stated that it won't be, e.g. in [golang/go/issues/21734](https://github.com/golang/go/issues/21734#issuecomment-326980213) Adam Langley says: + -+int _goboringcrypto_RSA_generate_key_fips(GO_RSA *, int, GO_BN_GENCB *); -+enum -+{ -+ GO_RSA_PKCS1_PADDING = 1, -+ GO_RSA_NO_PADDING = 3, -+ GO_RSA_PKCS1_OAEP_PADDING = 4, -+ GO_RSA_PKCS1_PSS_PADDING = 6, -+}; ++> The status of FIPS 140 for Go itself remains "no plans, basically zero chance". + -+enum { -+ GO_RSA_PSS_SALTLEN_AUTO = -2, -+ GO_RSA_PSS_SALTLEN_DIGEST = -1, -+}; ++On the other hand, Google maintains a branch that uses cgo and BoringSSL to implement various crypto primitives: https://github.com/golang/go/blob/dev.boringcrypto/README.boringcrypto.md. As BoringSSL is FIPS 140-2 certified, an application using that branch is more likely to be FIPS 140-2 compliant, yet Google does not provide any liability about the suitability of this code in relation to the FIPS 140-2 standard. + -+int _goboringcrypto_RSA_sign_pss_mgf1(GO_RSA *, unsigned int *out_len, uint8_t *out, unsigned int max_out, const uint8_t *in, unsigned int in_len, GO_EVP_MD *md, const GO_EVP_MD *mgf1_md, int salt_len); -+ -+int _goboringcrypto_RSA_verify_pss_mgf1(GO_RSA *, const uint8_t *msg, unsigned int msg_len, GO_EVP_MD *md, const GO_EVP_MD *mgf1_md, int salt_len, const uint8_t *sig, unsigned int sig_len); -+ -+DEFINEFUNC(unsigned int, RSA_size, (const GO_RSA *arg0), (arg0)) -+DEFINEFUNC(int, RSA_check_key, (const GO_RSA *arg0), (arg0)) -+ -+DEFINEFUNC(int, EVP_EncryptInit_ex, -+ (EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl, const unsigned char *key, const unsigned char *iv), -+ (ctx, type, impl, key, iv)) -+DEFINEFUNC(int, EVP_EncryptUpdate, -+ (EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl), -+ (ctx, out, outl, in, inl)) -+DEFINEFUNC(int, EVP_EncryptFinal_ex, -+ (EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl), -+ (ctx, out, outl)) -+ -+DEFINEFUNC(int, EVP_DecryptInit_ex, -+ (EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl, const unsigned char *key, const unsigned char *iv), -+ (ctx, type, impl, key, iv)) -+DEFINEFUNC(int, EVP_DecryptUpdate, -+ (EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl), -+ (ctx, out, outl, in, inl)) -+DEFINEFUNC(int, EVP_DecryptFinal_ex, -+ (EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl), -+ (ctx, outm, outl)) -+ -+DEFINEFUNC(const EVP_CIPHER*, EVP_aes_128_gcm, (void), ()) -+DEFINEFUNC(const EVP_CIPHER*, EVP_aes_128_cbc, (void), ()) -+DEFINEFUNC(const EVP_CIPHER*, EVP_aes_128_ctr, (void), ()) -+DEFINEFUNC(const EVP_CIPHER*, EVP_aes_128_ecb, (void), ()) -+DEFINEFUNC(const EVP_CIPHER*, EVP_aes_192_cbc, (void), ()) -+DEFINEFUNC(const EVP_CIPHER*, EVP_aes_192_ctr, (void), ()) -+DEFINEFUNC(const EVP_CIPHER*, EVP_aes_192_ecb, (void), ()) -+DEFINEFUNC(const EVP_CIPHER*, EVP_aes_192_gcm, (void), ()) -+DEFINEFUNC(const EVP_CIPHER*, EVP_aes_256_cbc, (void), ()) -+DEFINEFUNC(const EVP_CIPHER*, EVP_aes_256_ctr, (void), ()) -+DEFINEFUNC(const EVP_CIPHER*, EVP_aes_256_ecb, (void), ()) -+DEFINEFUNC(const EVP_CIPHER*, EVP_aes_256_gcm, (void), ()) -+ -+DEFINEFUNC(void, EVP_CIPHER_CTX_free, (EVP_CIPHER_CTX* arg0), (arg0)) -+DEFINEFUNC(int, EVP_CIPHER_CTX_ctrl, (EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr), (ctx, type, arg, ptr)) -+ -+int _goboringcrypto_EVP_CIPHER_CTX_seal( -+ uint8_t *out, uint8_t *nonce, -+ uint8_t *aad, size_t aad_len, -+ uint8_t *plaintext, size_t plaintext_len, -+ size_t *ciphertext_len, uint8_t *key, int key_size); -+ -+int _goboringcrypto_EVP_CIPHER_CTX_open( -+ uint8_t *ciphertext, int ciphertext_len, -+ uint8_t *aad, int aad_len, -+ uint8_t *tag, uint8_t *key, int key_size, -+ uint8_t *nonce, int nonce_len, -+ uint8_t *plaintext, size_t *plaintext_len); -+ -+typedef EVP_PKEY GO_EVP_PKEY; -+ -+DEFINEFUNC(GO_EVP_PKEY *, EVP_PKEY_new, (void), ()) -+DEFINEFUNC(void, EVP_PKEY_free, (GO_EVP_PKEY * arg0), (arg0)) -+DEFINEFUNC(int, EVP_PKEY_set1_RSA, (GO_EVP_PKEY * arg0, GO_RSA *arg1), (arg0, arg1)) -+DEFINEFUNC(int, EVP_PKEY_set1_EC_KEY, (GO_EVP_PKEY * arg0, GO_EC_KEY *arg1), (arg0, arg1)) -+DEFINEFUNC(int, EVP_PKEY_verify, -+ (EVP_PKEY_CTX *ctx, const unsigned char *sig, unsigned int siglen, const unsigned char *tbs, size_t tbslen), -+ (ctx, sig, siglen, tbs, tbslen)) -+ -+typedef EVP_PKEY_CTX GO_EVP_PKEY_CTX; -+ -+DEFINEFUNC(GO_EVP_PKEY_CTX *, EVP_PKEY_CTX_new, (GO_EVP_PKEY * arg0, ENGINE *arg1), (arg0, arg1)) -+DEFINEFUNC(GO_EVP_PKEY_CTX *, EVP_PKEY_CTX_new_id, (int arg0, ENGINE *arg1), (arg0, arg1)) -+DEFINEFUNC(void, EVP_PKEY_CTX_free, (GO_EVP_PKEY_CTX * arg0), (arg0)) -+DEFINEFUNC(int, EVP_PKEY_CTX_ctrl, -+ (EVP_PKEY_CTX * ctx, int keytype, int optype, int cmd, int p1, void *p2), -+ (ctx, keytype, optype, cmd, p1, p2)) -+DEFINEFUNCINTERNAL(int, RSA_pkey_ctx_ctrl, -+ (EVP_PKEY_CTX *ctx, int optype, int cmd, int p1, void *p2), -+ (ctx, optype, cmd, p1, p2)) ++## Features + -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_set_rsa_padding(GO_EVP_PKEY_CTX* ctx, int pad) { -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+ return _goboringcrypto_EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -1, EVP_PKEY_CTRL_RSA_PADDING, pad, NULL); -+#else -+ return _goboringcrypto_internal_RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_RSA_PADDING, pad, NULL); -+#endif -+} ++### Multiple OpenSSL versions supported + -+#if OPENSSL_VERSION_NUMBER < 0x30000000 -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_set0_rsa_oaep_label(GO_EVP_PKEY_CTX *ctx, uint8_t *l, int llen) -+{ -+ return _goboringcrypto_EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, EVP_PKEY_CTRL_RSA_OAEP_LABEL, llen, (void *)l); -+} -+#else -+DEFINEFUNC(int, EVP_PKEY_CTX_set0_rsa_oaep_label, -+ (GO_EVP_PKEY_CTX *ctx, uint8_t *l, int llen), -+ (ctx, l, llen)) -+#endif ++The `openssl` package has support for multiple OpenSSL versions, namely 1.0.2, 1.1.0, 1.1.1 and 3.0.x. + -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_set_rsa_oaep_md(GO_EVP_PKEY_CTX *ctx, const GO_EVP_MD *md) -+{ -+ return _goboringcrypto_EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT, EVP_PKEY_CTRL_RSA_OAEP_MD, 0, (void *)md); -+} ++All supported OpenSSL versions pass a small set of automatic tests that ensure they can be built and that there are no major regressions. ++These tests do not validate the cryptographic correctness of the `openssl` package. + -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(GO_EVP_PKEY_CTX * arg0, int arg1) { -+ return _goboringcrypto_EVP_PKEY_CTX_ctrl(arg0, EVP_PKEY_RSA, -+ (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), -+ EVP_PKEY_CTRL_RSA_PSS_SALTLEN, -+ arg1, NULL); -+} ++On top of that, the [golang-fips Go fork](https://github.com/golang-fips/go) -maintained by Red Hat- and the [Microsoft Go fork](https://github.com/microsoft/go), tests a subset of the supported OpenSSL versions when integrated with the Go `crypto` package. ++These tests are much more exhaustive and validate a specific OpenSSL version can produce working applications. + -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) { -+ return _goboringcrypto_EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD, 0, (void *)md); -+} ++### Building without OpenSSL headers + -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(GO_EVP_PKEY_CTX * ctx, const GO_EVP_MD *md) { -+ return _goboringcrypto_EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, -+ EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT, -+ EVP_PKEY_CTRL_RSA_MGF1_MD, 0, (void *)md); -+} -+ -+DEFINEFUNC(int, EVP_PKEY_decrypt, -+ (GO_EVP_PKEY_CTX * arg0, uint8_t *arg1, size_t *arg2, const uint8_t *arg3, size_t arg4), -+ (arg0, arg1, arg2, arg3, arg4)) -+DEFINEFUNC(int, EVP_PKEY_encrypt, -+ (GO_EVP_PKEY_CTX * arg0, uint8_t *arg1, size_t *arg2, const uint8_t *arg3, size_t arg4), -+ (arg0, arg1, arg2, arg3, arg4)) -+DEFINEFUNC(int, EVP_PKEY_decrypt_init, (GO_EVP_PKEY_CTX * arg0), (arg0)) -+DEFINEFUNC(int, EVP_PKEY_encrypt_init, (GO_EVP_PKEY_CTX * arg0), (arg0)) -+DEFINEFUNC(int, EVP_PKEY_sign_init, (GO_EVP_PKEY_CTX * arg0), (arg0)) -+DEFINEFUNC(int, EVP_PKEY_verify_init, (GO_EVP_PKEY_CTX * arg0), (arg0)) -+DEFINEFUNC(int, EVP_PKEY_sign, -+ (GO_EVP_PKEY_CTX * arg0, uint8_t *arg1, size_t *arg2, const uint8_t *arg3, size_t arg4), -+ (arg0, arg1, arg2, arg3, arg4)) -+ -+DEFINEFUNC(int, EVP_PKEY_derive_init, (GO_EVP_PKEY_CTX *arg0), (arg0)) -+DEFINEFUNC(int, EVP_PKEY_derive, (GO_EVP_PKEY_CTX *arg0, unsigned char *arg1, size_t *arg2), (arg0, arg1, arg2)) -+#if OPENSSL_VERSION_NUMBER >= 0x30000000L -+DEFINEFUNC(int, EVP_PKEY_derive_set_peer_ex, (GO_EVP_PKEY_CTX *arg0, GO_EVP_PKEY *arg1, int arg2), (arg0, arg1, arg2)); -+#else -+DEFINEFUNCINTERNAL(int, EVP_PKEY_derive_set_peer, (EVP_PKEY_CTX *ctx, EVP_PKEY *peer), (ctx, peer)) -+# if OPENSSL_VERSION_NUMBER >= 0x10100000L -+DEFINEFUNC(int, EVP_PKEY_public_check, (EVP_PKEY_CTX *arg0), (arg0)) ++The `openssl` package does not use any symbol from the OpenSSL headers. There is no need that have them installed to build an application which imports this library. + -+static inline int -+_goboringcrypto_EVP_PKEY_derive_set_peer_ex(GO_EVP_PKEY_CTX *ctx, GO_EVP_PKEY *key, int validate) -+{ -+ EVP_PKEY_CTX *check_ctx = _goboringcrypto_EVP_PKEY_CTX_new(key, NULL); -+ if (check_ctx == NULL) { -+ return -1; -+ } -+ int ok = _goboringcrypto_EVP_PKEY_public_check(check_ctx); -+ _goboringcrypto_EVP_PKEY_CTX_free(check_ctx); -+ if (ok != 1) { -+ return -1; -+ } -+ return _goboringcrypto_internal_EVP_PKEY_derive_set_peer(ctx, key); -+} -+# else -+static inline int -+_goboringcrypto_EVP_PKEY_derive_set_peer_ex(GO_EVP_PKEY_CTX *ctx, GO_EVP_PKEY *key, int validate) -+{ -+ /* No way to validate public key in OpenSSL 1.0.2 */ -+ (void)validate; -+ return _goboringcrypto_internal_EVP_PKEY_derive_set_peer(ctx, key); -+} -+# endif -+#endif ++The CI tests in this repository verify that all the functions and constants defined in our headers match the ones in the OpenSSL headers for every supported OpenSSL version. + -+#if OPENSSL_VERSION_NUMBER >= 0x10101000L -+#include ++### Portable OpenSSL + -+enum { -+ GO_EVP_PKEY_HKDF = EVP_PKEY_HKDF, -+}; ++The OpenSSL bindings are implemented in such a way that the OpenSSL version available when building a program does not have to match with the OpenSSL version used when running it. ++In fact, OpenSSL doesn't need to be present on the builder. ++For example, using the `openssl` package and `go build .` on a Windows host with `GOOS=linux` can produce a program that successfully runs on Linux and uses OpenSSL. + -+enum { -+ GO_EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY = EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY, -+ GO_EVP_PKEY_HKDEF_MODE_EXPAND_ONLY = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY, -+}; ++This feature does not require any additional configuration, but it only works with OpenSSL versions known and supported by the Go toolchain that integrates the `openssl` package. + -+#if OPENSSL_VERSION_NUMBER >= 0x30000000 -+DEFINEFUNC(int, EVP_PKEY_CTX_set_hkdf_mode, (GO_EVP_PKEY_CTX *arg0, int arg1), (arg0, arg1)) -+DEFINEFUNC(int, EVP_PKEY_CTX_set_hkdf_md, (GO_EVP_PKEY_CTX *arg0, const GO_EVP_MD *arg1), (arg0, arg1)) -+DEFINEFUNC(int, EVP_PKEY_CTX_set1_hkdf_salt, (GO_EVP_PKEY_CTX *arg0, unsigned char *arg1, int arg2), (arg0, arg1, arg2)) -+DEFINEFUNC(int, EVP_PKEY_CTX_set1_hkdf_key, (GO_EVP_PKEY_CTX *arg0, unsigned char *arg1, int arg2), (arg0, arg1, arg2)) -+DEFINEFUNC(int, EVP_PKEY_CTX_add1_hkdf_info, (GO_EVP_PKEY_CTX *arg0, unsigned char *arg1, int arg2), (arg0, arg1, arg2)) -+enum { -+ GO_EVP_PKEY_KEYPAIR = EVP_PKEY_KEYPAIR, -+ GO_EVP_PKEY_PUBLIC_KEY = EVP_PKEY_PUBLIC_KEY, -+}; ++## Limitations + -+#else -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_set_hkdf_mode(GO_EVP_PKEY_CTX *pctx, int mode) -+{ -+ return _goboringcrypto_EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, -+ EVP_PKEY_CTRL_HKDF_MODE, mode, NULL); -+} ++- Only Unix, Unix-like and Windows platforms are supported. ++- The build must set `CGO_ENABLED=1`. + -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_set_hkdf_md(GO_EVP_PKEY_CTX *pctx, const GO_EVP_MD *md) -+{ -+ return _goboringcrypto_EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, -+ EVP_PKEY_CTRL_HKDF_MD, 0, (void *)(md)); -+} ++## Acknowledgements + -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_set1_hkdf_salt(GO_EVP_PKEY_CTX *pctx, unsigned char *salt, int saltlen) -+{ -+ return _goboringcrypto_EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, -+ EVP_PKEY_CTRL_HKDF_SALT, saltlen, (void *)(salt)); -+} ++The work done to support FIPS compatibility mode leverages code and ideas from other open-source projects: + -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_set1_hkdf_key(GO_EVP_PKEY_CTX *pctx, unsigned char *key, int keylen) -+{ -+ return _goboringcrypto_EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, -+ EVP_PKEY_CTRL_HKDF_KEY, keylen, (void *)(key)); -+} ++- All crypto stubs are a mirror of Google's [dev.boringcrypto branch](https://github.com/golang/go/tree/dev.boringcrypto) and the release branch ports of that branch. ++- The mapping between BoringSSL and OpenSSL APIs is taken from the former [Red Hat Go fork](https://pagure.io/go). ++- The portable OpenSSL implementation is ported from Microsoft's [.NET runtime](https://github.com/dotnet/runtime) cryptography module. +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/aes.go b/src/vendor/github.com/golang-fips/openssl/v2/aes.go +new file mode 100644 +index 0000000000..a7c3aea683 +--- /dev/null ++++ b/src/vendor/github.com/golang-fips/openssl/v2/aes.go +@@ -0,0 +1,552 @@ ++//go:build !cmd_go_bootstrap + -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_add1_hkdf_info(GO_EVP_PKEY_CTX *pctx, unsigned char *info, int infolen) -+{ -+ return _goboringcrypto_EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DERIVE, -+ EVP_PKEY_CTRL_HKDF_INFO, infolen, (void *)(info)); -+} -+// These symbols are not present in older versions of OpenSSL but we define them here -+// to fix compilation errors. -+enum { -+ GO_EVP_PKEY_KEYPAIR, -+ GO_EVP_PKEY_PUBLIC_KEY, -+}; ++package openssl + -+#endif ++// #include "goopenssl.h" ++import "C" ++import ( ++ "crypto/cipher" ++ "encoding/binary" ++ "errors" ++ "runtime" ++ "strconv" ++ "sync" ++ "unsafe" ++) + ++type cipherKind int8 + -+#else ++const ( ++ cipherAES128_ECB cipherKind = iota ++ cipherAES192_ECB ++ cipherAES256_ECB ++ cipherAES128_CBC ++ cipherAES192_CBC ++ cipherAES256_CBC ++ cipherAES128_CTR ++ cipherAES192_CTR ++ cipherAES256_CTR ++ cipherAES128_GCM ++ cipherAES192_GCM ++ cipherAES256_GCM ++) + -+/* As HKDF is not supported in earlier OpenSSL versions than 1.1.1 and -+ * fallback implementation cannot be provided in a FIPS compliant -+ * manner, we only provide stub definitions of the above symbols. At -+ * run-time, HKDF operations in hkdf.go (see newHKDF) will return an -+ * error depending on the OpenSSL version. -+ */ ++// cacheCipher is a cache of cipherKind to GO_EVP_CIPHER_PTR. ++var cacheCipher sync.Map + -+enum { -+ GO_EVP_PKEY_HKDF, -+}; ++// newCipher returns a cipher object for the given k. ++func newCipher(k cipherKind) (cipher C.GO_EVP_CIPHER_PTR) { ++ if v, ok := cacheCipher.Load(k); ok { ++ return v.(C.GO_EVP_CIPHER_PTR) ++ } ++ defer func() { ++ if cipher != nil && vMajor == 3 { ++ // On OpenSSL 3, directly operating on a EVP_CIPHER object ++ // not created by EVP_CIPHER has negative performance ++ // implications, as cipher operations will have ++ // to fetch it on every call. Better to just fetch it once here. ++ cipher = C.go_openssl_EVP_CIPHER_fetch(nil, C.go_openssl_EVP_CIPHER_get0_name(cipher), nil) ++ } ++ cacheCipher.Store(k, cipher) ++ }() ++ switch k { ++ case cipherAES128_CBC: ++ cipher = C.go_openssl_EVP_aes_128_cbc() ++ case cipherAES192_CBC: ++ cipher = C.go_openssl_EVP_aes_192_cbc() ++ case cipherAES256_CBC: ++ cipher = C.go_openssl_EVP_aes_256_cbc() ++ case cipherAES128_ECB: ++ cipher = C.go_openssl_EVP_aes_128_ecb() ++ case cipherAES192_ECB: ++ cipher = C.go_openssl_EVP_aes_192_ecb() ++ case cipherAES256_ECB: ++ cipher = C.go_openssl_EVP_aes_256_ecb() ++ case cipherAES128_CTR: ++ cipher = C.go_openssl_EVP_aes_128_ctr() ++ case cipherAES192_CTR: ++ cipher = C.go_openssl_EVP_aes_192_ctr() ++ case cipherAES256_CTR: ++ cipher = C.go_openssl_EVP_aes_256_ctr() ++ case cipherAES128_GCM: ++ cipher = C.go_openssl_EVP_aes_128_gcm() ++ case cipherAES192_GCM: ++ cipher = C.go_openssl_EVP_aes_192_gcm() ++ case cipherAES256_GCM: ++ cipher = C.go_openssl_EVP_aes_256_gcm() ++ } ++ return cipher ++} + -+enum { -+ GO_EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY, -+ GO_EVP_PKEY_HKDEF_MODE_EXPAND_ONLY, -+}; ++type aesKeySizeError int + -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_set_hkdf_mode(GO_EVP_PKEY_CTX *arg0, int arg1) -+{ -+ return -1; ++func (k aesKeySizeError) Error() string { ++ return "crypto/aes: invalid key size " + strconv.Itoa(int(k)) +} + -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_set_hkdf_md(GO_EVP_PKEY_CTX *arg0, const GO_EVP_MD *arg1) -+{ -+ return -1; -+} ++const aesBlockSize = 16 + -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_set1_hkdf_salt(GO_EVP_PKEY_CTX *arg0, unsigned char *arg1, int arg2) -+{ -+ return -1; ++type aesCipher struct { ++ key []byte ++ enc_ctx C.GO_EVP_CIPHER_CTX_PTR ++ dec_ctx C.GO_EVP_CIPHER_CTX_PTR ++ kind cipherKind +} + -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_set1_hkdf_key(GO_EVP_PKEY_CTX *arg0, unsigned char *arg1, int arg2) -+{ -+ return -1; -+} ++type extraModes interface { ++ // Copied out of crypto/aes/modes.go. ++ NewCBCEncrypter(iv []byte) cipher.BlockMode ++ NewCBCDecrypter(iv []byte) cipher.BlockMode ++ NewCTR(iv []byte) cipher.Stream ++ NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) + -+static inline int -+_goboringcrypto_EVP_PKEY_CTX_add1_hkdf_info(GO_EVP_PKEY_CTX *arg0, unsigned char *arg1, int arg2) -+{ -+ return -1; ++ // Invented for BoringCrypto. ++ NewGCMTLS() (cipher.AEAD, error) +} -+#endif + -+enum { -+ GO_EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID = EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, -+ GO_EVP_PKEY_CTRL_RSA_KEYGEN_BITS = EVP_PKEY_CTRL_RSA_KEYGEN_BITS, -+}; ++var _ extraModes = (*aesCipher)(nil) + -+DEFINEFUNC(int, EC_POINT_mul, (const GO_EC_GROUP *group, GO_EC_POINT *r, const GO_BIGNUM *n, const GO_EC_POINT *q, const GO_BIGNUM *m, GO_BN_CTX *ctx), (group, r, n, q, m, ctx)) -+#if OPENSSL_VERSION_NUMBER >= 0x30000000 -+DEFINEFUNC(int, EVP_PKEY_get_bits, (const GO_EVP_PKEY *pkey), (pkey)); -+#else -+DEFINEFUNCINTERNAL(int, EVP_PKEY_bits, (const GO_EVP_PKEY *pkey), (pkey)); -+static int -+_goboringcrypto_EVP_PKEY_get_bits(const GO_EVP_PKEY *pkey) -+{ -+ return _goboringcrypto_internal_EVP_PKEY_bits(pkey); -+} -+#endif -+DEFINEFUNC(int, EVP_PKEY_get_bn_param, (const GO_EVP_PKEY *pkey, const char *key_name, GO_BIGNUM **bn), (pkey, key_name, bn)) -+DEFINEFUNC(int, EVP_PKEY_keygen_init, (GO_EVP_PKEY_CTX *ctx), (ctx)) -+DEFINEFUNC(int, EVP_PKEY_keygen, (GO_EVP_PKEY_CTX *ctx, GO_EVP_PKEY **ppkey), (ctx, ppkey)) ++func NewAESCipher(key []byte) (cipher.Block, error) { ++ c := &aesCipher{key: make([]byte, len(key))} ++ copy(c.key, key) + -+// This is not used when running against openssl < 3. -+enum { -+ GO_POINT_CONVERSION_UNCOMPRESSED = 4, -+}; ++ switch len(c.key) * 8 { ++ case 128: ++ c.kind = cipherAES128_ECB ++ case 192: ++ c.kind = cipherAES192_ECB ++ case 256: ++ c.kind = cipherAES256_ECB ++ default: ++ return nil, errors.New("crypto/cipher: Invalid key size") ++ } + -+#if OPENSSL_VERSION_NUMBER >= 0x10100000L -+DEFINEFUNC(int, EVP_PKEY_set1_encoded_public_key, (GO_EVP_PKEY *pkey, const unsigned char *pub, size_t publen), (pkey, pub, publen)) -+DEFINEFUNC(size_t, EVP_PKEY_get1_encoded_public_key, (GO_EVP_PKEY *pkey, unsigned char **ppub), (pkey, ppub)) ++ runtime.SetFinalizer(c, (*aesCipher).finalize) + -+DEFINEFUNC(const GO_EC_KEY *, EVP_PKEY_get0_EC_KEY, (const GO_EVP_PKEY *pkey), (pkey)) -+#else -+DEFINEFUNCINTERNAL(void *, EVP_PKEY_get0, (const GO_EVP_PKEY *pkey), (pkey)) -+static const GO_EC_KEY * -+_goboringcrypto_EVP_PKEY_get0_EC_KEY(const GO_EVP_PKEY *pkey) -+{ -+ return _goboringcrypto_internal_EVP_PKEY_get0(pkey); ++ return c, nil +} -+#endif -+ -+GO_EVP_PKEY *_goboringcrypto_EVP_PKEY_new_for_ecdh(int nid, const uint8_t *bytes, size_t len, int is_private); -+size_t _goboringcrypto_EVP_PKEY_get1_encoded_ecdh_public_key(GO_EVP_PKEY *pkey, unsigned char **result); -+int _goboringcrypto_EVP_PKEY_set_ecdh_public_key_from_private(GO_EVP_PKEY *pkey, int nid); -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/hkdf.go b/src/vendor/github.com/golang-fips/openssl-fips/openssl/hkdf.go -new file mode 100644 -index 0000000000..2e21224264 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/hkdf.go -@@ -0,0 +1,108 @@ -+// 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 -+// +build linux,!android,!cmd_go_bootstrap,!msan,!no_openssl -======= + -+func newEvpFromParams(id C.int, selection C.int, params C.GO_OSSL_PARAM_PTR) (C.GO_EVP_PKEY_PTR, error) { -+ ctx := C.go_openssl_EVP_PKEY_CTX_new_id(id, nil) -+ if ctx == nil { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_new_id") -+ } -+ defer C.go_openssl_EVP_PKEY_CTX_free(ctx) -+ if C.go_openssl_EVP_PKEY_fromdata_init(ctx) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_fromdata_init") ++func (c *aesCipher) finalize() { ++ if c.enc_ctx != nil { ++ C.go_openssl_EVP_CIPHER_CTX_free(c.enc_ctx) + } -+ var pkey C.GO_EVP_PKEY_PTR -+ if C.go_openssl_EVP_PKEY_fromdata(ctx, &pkey, selection, params) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_fromdata") ++ if c.dec_ctx != nil { ++ C.go_openssl_EVP_CIPHER_CTX_free(c.dec_ctx) + } -+ return pkey, nil +} -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/goopenssl.c b/src/vendor/github.com/golang-fips/openssl/v2/goopenssl.c -new file mode 100644 -index 0000000000..ec4adc1539 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/goopenssl.c -@@ -0,0 +1,218 @@ -+//go:build unix || windows -+ -+#include "goopenssl.h" + -+#ifdef _WIN32 -+# include -+# define dlsym (void*)GetProcAddress -+#else -+# include // dlsym -+#endif -+#include // fprintf ++func (c *aesCipher) BlockSize() int { return aesBlockSize } + -+// Approach taken from .Net System.Security.Cryptography.Native -+// https://github.com/dotnet/runtime/blob/f64246ce08fb7a58221b2b7c8e68f69c02522b0d/src/libraries/Native/Unix/System.Security.Cryptography.Native/opensslshim.c ++func (c *aesCipher) Encrypt(dst, src []byte) { ++ if len(src) < aesBlockSize { ++ panic("crypto/aes: input not full block") ++ } ++ if len(dst) < aesBlockSize { ++ panic("crypto/aes: output not full block") ++ } ++ // Only check for overlap between the parts of src and dst that will actually be used. ++ // This matches Go standard library behavior. ++ if inexactOverlap(dst[:aesBlockSize], src[:aesBlockSize]) { ++ panic("crypto/cipher: invalid buffer overlap") ++ } ++ if c.enc_ctx == nil { ++ var err error ++ c.enc_ctx, err = newCipherCtx(c.kind, C.GO_AES_ENCRYPT, c.key, nil) ++ if err != nil { ++ panic(err) ++ } ++ } + -+#define DEFINEFUNC(ret, func, args, argscall) ret (*_g_##func)args; -+#define DEFINEFUNC_LEGACY_1_1(ret, func, args, argscall) DEFINEFUNC(ret, func, args, argscall) -+#define DEFINEFUNC_LEGACY_1_0(ret, func, args, argscall) DEFINEFUNC(ret, func, args, argscall) -+#define DEFINEFUNC_LEGACY_1(ret, func, args, argscall) DEFINEFUNC(ret, func, args, argscall) -+#define DEFINEFUNC_1_1(ret, func, args, argscall) DEFINEFUNC(ret, func, args, argscall) -+#define DEFINEFUNC_1_1_1(ret, func, args, argscall) DEFINEFUNC(ret, func, args, argscall) -+#define DEFINEFUNC_3_0(ret, func, args, argscall) DEFINEFUNC(ret, func, args, argscall) -+#define DEFINEFUNC_RENAMED_1_1(ret, func, oldfunc, args, argscall) DEFINEFUNC(ret, func, args, argscall) -+#define DEFINEFUNC_RENAMED_3_0(ret, func, oldfunc, args, argscall) DEFINEFUNC(ret, func, args, argscall) ++ if C.go_openssl_EVP_EncryptUpdate_wrapper(c.enc_ctx, base(dst), base(src), aesBlockSize) != 1 { ++ panic("crypto/cipher: EncryptUpdate failed") ++ } ++ runtime.KeepAlive(c) ++} + -+FOR_ALL_OPENSSL_FUNCTIONS ++func (c *aesCipher) Decrypt(dst, src []byte) { ++ if len(src) < aesBlockSize { ++ panic("crypto/aes: input not full block") ++ } ++ if len(dst) < aesBlockSize { ++ panic("crypto/aes: output not full block") ++ } ++ // Only check for overlap between the parts of src and dst that will actually be used. ++ // This matches Go standard library behavior. ++ if inexactOverlap(dst[:aesBlockSize], src[:aesBlockSize]) { ++ panic("crypto/cipher: invalid buffer overlap") ++ } ++ if c.dec_ctx == nil { ++ var err error ++ c.dec_ctx, err = newCipherCtx(c.kind, C.GO_AES_DECRYPT, c.key, nil) ++ if err != nil { ++ panic(err) ++ } ++ if C.go_openssl_EVP_CIPHER_CTX_set_padding(c.dec_ctx, 0) != 1 { ++ panic("crypto/cipher: could not disable cipher padding") ++ } ++ } + -+#undef DEFINEFUNC -+#undef DEFINEFUNC_LEGACY_1_1 -+#undef DEFINEFUNC_LEGACY_1_0 -+#undef DEFINEFUNC_LEGACY_1 -+#undef DEFINEFUNC_1_1 -+#undef DEFINEFUNC_1_1_1 -+#undef DEFINEFUNC_3_0 -+#undef DEFINEFUNC_RENAMED_1_1 -+#undef DEFINEFUNC_RENAMED_3_0 ++ C.go_openssl_EVP_DecryptUpdate_wrapper(c.dec_ctx, base(dst), base(src), aesBlockSize) ++ runtime.KeepAlive(c) ++} + -+int -+go_openssl_fips_enabled(void* handle) -+{ -+ // For OpenSSL 1.x. -+ int (*FIPS_mode)(void); -+ FIPS_mode = (int (*)(void))dlsym(handle, "FIPS_mode"); -+ if (FIPS_mode != NULL) -+ return FIPS_mode(); ++type aesCBC struct { ++ ctx C.GO_EVP_CIPHER_CTX_PTR ++} + -+ // For OpenSSL 3.x. -+ int (*EVP_default_properties_is_fips_enabled)(void*); -+ int (*OSSL_PROVIDER_available)(void*, const char*); -+ EVP_default_properties_is_fips_enabled = (int (*)(void*))dlsym(handle, "EVP_default_properties_is_fips_enabled"); -+ OSSL_PROVIDER_available = (int (*)(void*, const char*))dlsym(handle, "OSSL_PROVIDER_available"); -+ if (EVP_default_properties_is_fips_enabled != NULL && OSSL_PROVIDER_available != NULL && -+ EVP_default_properties_is_fips_enabled(NULL) == 1 && OSSL_PROVIDER_available(NULL, "fips") == 1) -+ return 1; ++func (x *aesCBC) BlockSize() int { return aesBlockSize } + -+ return 0; ++func (x *aesCBC) CryptBlocks(dst, src []byte) { ++ if inexactOverlap(dst, src) { ++ panic("crypto/cipher: invalid buffer overlap") ++ } ++ if len(src)%aesBlockSize != 0 { ++ panic("crypto/cipher: input not full blocks") ++ } ++ if len(dst) < len(src) { ++ panic("crypto/cipher: output smaller than input") ++ } ++ if len(src) > 0 { ++ if C.go_openssl_EVP_CipherUpdate_wrapper(x.ctx, base(dst), base(src), C.int(len(src))) != 1 { ++ panic("crypto/cipher: CipherUpdate failed") ++ } ++ runtime.KeepAlive(x) ++ } +} + -+// Load all the functions stored in FOR_ALL_OPENSSL_FUNCTIONS -+// and assign them to their corresponding function pointer -+// defined in goopenssl.h. -+void -+go_openssl_load_functions(void* handle, int major, int minor, int patch) -+{ -+#define DEFINEFUNC_INTERNAL(name, func) \ -+ _g_##name = dlsym(handle, func); \ -+ if (_g_##name == NULL) { \ -+ fprintf(stderr, "Cannot get required symbol " #func " from libcrypto version %d.%d\n", major, minor); \ -+ abort(); \ -+ } -+#define DEFINEFUNC(ret, func, args, argscall) \ -+ DEFINEFUNC_INTERNAL(func, #func) -+#define DEFINEFUNC_LEGACY_1_1(ret, func, args, argscall) \ -+ if (major == 1 && minor == 1) \ -+ { \ -+ DEFINEFUNC_INTERNAL(func, #func) \ -+ } -+#define DEFINEFUNC_LEGACY_1_0(ret, func, args, argscall) \ -+ if (major == 1 && minor == 0) \ -+ { \ -+ DEFINEFUNC_INTERNAL(func, #func) \ -+ } -+#define DEFINEFUNC_LEGACY_1(ret, func, args, argscall) \ -+ if (major == 1) \ -+ { \ -+ DEFINEFUNC_INTERNAL(func, #func) \ -+ } -+#define DEFINEFUNC_1_1(ret, func, args, argscall) \ -+ if (major == 3 || (major == 1 && minor == 1)) \ -+ { \ -+ DEFINEFUNC_INTERNAL(func, #func) \ -+ } -+#define DEFINEFUNC_1_1_1(ret, func, args, argscall) \ -+ if (major == 3 || (major == 1 && minor == 1 && patch == 1)) \ -+ { \ -+ DEFINEFUNC_INTERNAL(func, #func) \ -+ } -+#define DEFINEFUNC_3_0(ret, func, args, argscall) \ -+ if (major == 3) \ -+ { \ -+ DEFINEFUNC_INTERNAL(func, #func) \ -+ } -+#define DEFINEFUNC_RENAMED_1_1(ret, func, oldfunc, args, argscall) \ -+ if (major == 1 && minor == 0) \ -+ { \ -+ DEFINEFUNC_INTERNAL(func, #oldfunc) \ -+ } \ -+ else \ -+ { \ -+ DEFINEFUNC_INTERNAL(func, #func) \ -+ } -+#define DEFINEFUNC_RENAMED_3_0(ret, func, oldfunc, args, argscall) \ -+ if (major == 1) \ -+ { \ -+ DEFINEFUNC_INTERNAL(func, #oldfunc) \ -+ } \ -+ else \ -+ { \ -+ DEFINEFUNC_INTERNAL(func, #func) \ -+ } ++func (x *aesCBC) SetIV(iv []byte) { ++ if len(iv) != aesBlockSize { ++ panic("cipher: incorrect length IV") ++ } ++ if C.go_openssl_EVP_CipherInit_ex(x.ctx, nil, nil, nil, base(iv), -1) != 1 { ++ panic("cipher: unable to initialize EVP cipher ctx") ++ } ++} + -+FOR_ALL_OPENSSL_FUNCTIONS ++func (c *aesCipher) NewCBCEncrypter(iv []byte) cipher.BlockMode { ++ x := new(aesCBC) + -+#undef DEFINEFUNC -+#undef DEFINEFUNC_LEGACY_1_1 -+#undef DEFINEFUNC_LEGACY_1_0 -+#undef DEFINEFUNC_LEGACY_1 -+#undef DEFINEFUNC_1_1 -+#undef DEFINEFUNC_1_1_1 -+#undef DEFINEFUNC_3_0 -+#undef DEFINEFUNC_RENAMED_1_1 -+#undef DEFINEFUNC_RENAMED_3_0 ++ var cipher cipherKind ++ switch len(c.key) * 8 { ++ case 128: ++ cipher = cipherAES128_CBC ++ case 192: ++ cipher = cipherAES192_CBC ++ case 256: ++ cipher = cipherAES256_CBC ++ default: ++ panic("openssl: unsupported key length") ++ } ++ var err error ++ x.ctx, err = newCipherCtx(cipher, C.GO_AES_ENCRYPT, c.key, iv) ++ if err != nil { ++ panic(err) ++ } ++ ++ runtime.SetFinalizer(x, (*aesCBC).finalize) ++ ++ if C.go_openssl_EVP_CIPHER_CTX_set_padding(x.ctx, 0) != 1 { ++ panic("cipher: unable to set padding") ++ } ++ return x +} + -+static unsigned long -+version_num(void* handle) -+{ -+ unsigned long (*fn)(void); -+ // OPENSSL_version_num is defined in OpenSSL 1.1.0 and 1.1.1. -+ fn = (unsigned long (*)(void))dlsym(handle, "OpenSSL_version_num"); -+ if (fn != NULL) -+ return fn(); ++func (c *aesCBC) finalize() { ++ C.go_openssl_EVP_CIPHER_CTX_free(c.ctx) ++} + -+ // SSLeay is defined in OpenSSL 1.0.2. -+ fn = (unsigned long (*)(void))dlsym(handle, "SSLeay"); -+ if (fn != NULL) -+ return fn(); ++func (c *aesCipher) NewCBCDecrypter(iv []byte) cipher.BlockMode { ++ x := new(aesCBC) + -+ return 0; -+} ++ var cipher cipherKind ++ switch len(c.key) * 8 { ++ case 128: ++ cipher = cipherAES128_CBC ++ case 192: ++ cipher = cipherAES192_CBC ++ case 256: ++ cipher = cipherAES256_CBC ++ default: ++ panic("openssl: unsupported key length") ++ } + -+int -+go_openssl_version_major(void* handle) -+{ -+ unsigned int (*fn)(void); -+ // OPENSSL_version_major is supported since OpenSSL 3. -+ fn = (unsigned int (*)(void))dlsym(handle, "OPENSSL_version_major"); -+ if (fn != NULL) -+ return (int)fn(); ++ var err error ++ x.ctx, err = newCipherCtx(cipher, C.GO_AES_DECRYPT, c.key, iv) ++ if err != nil { ++ panic(err) ++ } + -+ // If OPENSSL_version_major is not defined, try with OpenSSL 1 functions. -+ unsigned long num = version_num(handle); -+ if (num < 0x10000000L || num >= 0x20000000L) -+ return -1; ++ runtime.SetFinalizer(x, (*aesCBC).finalize) + -+ return 1; ++ if C.go_openssl_EVP_CIPHER_CTX_set_padding(x.ctx, 0) != 1 { ++ panic("cipher: unable to set padding") ++ } ++ return x +} + -+int -+go_openssl_version_minor(void* handle) -+{ -+ unsigned int (*fn)(void); -+ // OPENSSL_version_minor is supported since OpenSSL 3. -+ fn = (unsigned int (*)(void))dlsym(handle, "OPENSSL_version_minor"); -+ if (fn != NULL) -+ return (int)fn(); -+ -+ // If OPENSSL_version_minor is not defined, try with OpenSSL 1 functions. -+ unsigned long num = version_num(handle); -+ // OpenSSL version number follows this schema: -+ // MNNFFPPS: major minor fix patch status. -+ if (num < 0x10000000L || num >= 0x10200000L) -+ { -+ // We only support minor version 0 and 1, -+ // so there is no need to implement an algorithm -+ // that decodes the version number into individual components. -+ return -1; -+ } ++type aesCTR struct { ++ ctx C.GO_EVP_CIPHER_CTX_PTR ++} + -+ if (num >= 0x10100000L) -+ return 1; -+ -+ return 0; ++func (x *aesCTR) XORKeyStream(dst, src []byte) { ++ if inexactOverlap(dst, src) { ++ panic("crypto/cipher: invalid buffer overlap") ++ } ++ if len(dst) < len(src) { ++ panic("crypto/cipher: output smaller than input") ++ } ++ if len(src) == 0 { ++ return ++ } ++ if C.go_openssl_EVP_EncryptUpdate_wrapper(x.ctx, base(dst), base(src), C.int(len(src))) != 1 { ++ panic("crypto/cipher: EncryptUpdate failed") ++ } ++ runtime.KeepAlive(x) +} + -+int -+go_openssl_version_patch(void* handle) -+{ -+ unsigned int (*fn)(void); -+ // OPENSSL_version_patch is supported since OpenSSL 3. -+ fn = (unsigned int (*)(void))dlsym(handle, "OPENSSL_version_patch"); -+ if (fn != NULL) -+ return (int)fn(); ++func (c *aesCipher) NewCTR(iv []byte) cipher.Stream { ++ x := new(aesCTR) + -+ // If OPENSSL_version_patch is not defined, try with OpenSSL 1 functions. -+ unsigned long num = version_num(handle); -+ // OpenSSL version number follows this schema: -+ // MNNFFPPS: major minor fix patch status. -+ if (num < 0x10000000L || num >= 0x10200000L) -+ { -+ // We only support minor version 0 and 1, -+ // so there is no need to implement an algorithm -+ // that decodes the version number into individual components. -+ return -1; -+ } ++ var cipher cipherKind ++ switch len(c.key) * 8 { ++ case 128: ++ cipher = cipherAES128_CTR ++ case 192: ++ cipher = cipherAES192_CTR ++ case 256: ++ cipher = cipherAES256_CTR ++ default: ++ panic("openssl: unsupported key length") ++ } ++ var err error ++ x.ctx, err = newCipherCtx(cipher, C.GO_AES_ENCRYPT, c.key, iv) ++ if err != nil { ++ panic(err) ++ } + -+ return (num >> 12) & 0xff; ++ runtime.SetFinalizer(x, (*aesCTR).finalize) ++ ++ return x +} -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/goopenssl.h b/src/vendor/github.com/golang-fips/openssl/v2/goopenssl.h -new file mode 100644 -index 0000000000..dc2ce35cd7 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/goopenssl.h -@@ -0,0 +1,183 @@ -+// This header file describes the OpenSSL ABI as built for use in Go. + -+#include // size_t ++func (c *aesCTR) finalize() { ++ C.go_openssl_EVP_CIPHER_CTX_free(c.ctx) ++} + -+#include "shims.h" ++type aesGCM struct { ++ ctx C.GO_EVP_CIPHER_CTX_PTR ++ tls bool ++ minNextNonce uint64 ++} + ++const ( ++ gcmTagSize = 16 ++ gcmStandardNonceSize = 12 ++ gcmTlsAddSize = 13 ++ gcmTlsFixedNonceSize = 4 ++) + -+static inline void -+go_openssl_do_leak_check(void) -+{ -+#ifndef __has_feature -+#define __has_feature(x) 0 -+#endif ++type aesNonceSizeError int + -+#if (defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__) || \ -+ __has_feature(address_sanitizer) -+ extern void __lsan_do_leak_check(void); -+ __lsan_do_leak_check(); -+#endif ++func (n aesNonceSizeError) Error() string { ++ return "crypto/aes: invalid GCM nonce size " + strconv.Itoa(int(n)) +} + -+int go_openssl_fips_enabled(void* handle); -+int go_openssl_version_major(void* handle); -+int go_openssl_version_minor(void* handle); -+int go_openssl_version_patch(void* handle); -+int go_openssl_thread_setup(void); -+void go_openssl_load_functions(void* handle, int major, int minor, int patch); -+const GO_EVP_MD_PTR go_openssl_EVP_md5_sha1_backport(void); -+ -+// Define pointers to all the used OpenSSL functions. -+// Calling C function pointers from Go is currently not supported. -+// It is possible to circumvent this by using a C function wrapper. -+// https://pkg.go.dev/cmd/cgo -+#define DEFINEFUNC(ret, func, args, argscall) \ -+ extern ret (*_g_##func)args; \ -+ static inline ret go_openssl_##func args \ -+ { \ -+ return _g_##func argscall; \ -+ } -+#define DEFINEFUNC_LEGACY_1_1(ret, func, args, argscall) \ -+ DEFINEFUNC(ret, func, args, argscall) -+#define DEFINEFUNC_LEGACY_1_0(ret, func, args, argscall) \ -+ DEFINEFUNC(ret, func, args, argscall) -+#define DEFINEFUNC_LEGACY_1(ret, func, args, argscall) \ -+ DEFINEFUNC(ret, func, args, argscall) -+#define DEFINEFUNC_1_1(ret, func, args, argscall) \ -+ DEFINEFUNC(ret, func, args, argscall) -+#define DEFINEFUNC_1_1_1(ret, func, args, argscall) \ -+ DEFINEFUNC(ret, func, args, argscall) -+#define DEFINEFUNC_3_0(ret, func, args, argscall) \ -+ DEFINEFUNC(ret, func, args, argscall) -+#define DEFINEFUNC_RENAMED_1_1(ret, func, oldfunc, args, argscall) \ -+ DEFINEFUNC(ret, func, args, argscall) -+#define DEFINEFUNC_RENAMED_3_0(ret, func, oldfunc, args, argscall) \ -+ DEFINEFUNC(ret, func, args, argscall) -+ -+FOR_ALL_OPENSSL_FUNCTIONS ++type noGCM struct { ++ cipher.Block ++} + -+#undef DEFINEFUNC -+#undef DEFINEFUNC_LEGACY_1_1 -+#undef DEFINEFUNC_LEGACY_1_0 -+#undef DEFINEFUNC_LEGACY_1 -+#undef DEFINEFUNC_1_1 -+#undef DEFINEFUNC_1_1_1 -+#undef DEFINEFUNC_3_0 -+#undef DEFINEFUNC_RENAMED_1_1 -+#undef DEFINEFUNC_RENAMED_3_0 ++func (c *aesCipher) NewGCM(nonceSize, tagSize int) (cipher.AEAD, error) { ++ if nonceSize != gcmStandardNonceSize && tagSize != gcmTagSize { ++ return nil, errors.New("crypto/aes: GCM tag and nonce sizes can't be non-standard at the same time") ++ } ++ // Fall back to standard library for GCM with non-standard nonce or tag size. ++ if nonceSize != gcmStandardNonceSize { ++ return cipher.NewGCMWithNonceSize(&noGCM{c}, nonceSize) ++ } ++ if tagSize != gcmTagSize { ++ return cipher.NewGCMWithTagSize(&noGCM{c}, tagSize) ++ } ++ return c.newGCM(false) ++} + -+// go_sha_sum copies ctx into ctx2 and calls EVP_DigestFinal using ctx2. -+// This is necessary because Go hash.Hash mandates that Sum has no effect -+// on the underlying stream. In particular it is OK to Sum, then Write more, -+// then Sum again, and the second Sum acts as if the first didn't happen. -+// It is written in C because Sum() tend to be in the hot path, -+// and doing one cgo call instead of two is a significant performance win. -+static inline int -+go_sha_sum(GO_EVP_MD_CTX_PTR ctx, GO_EVP_MD_CTX_PTR ctx2, unsigned char *out) -+{ -+ if (go_openssl_EVP_MD_CTX_copy(ctx2, ctx) != 1) -+ return 0; -+ // TODO: use EVP_DigestFinal_ex once we know why it leaks -+ // memory on OpenSSL 1.0.2. -+ return go_openssl_EVP_DigestFinal(ctx2, out, NULL); ++// NewGCMTLS returns a GCM cipher specific to TLS ++// and should not be used for non-TLS purposes. ++func NewGCMTLS(c cipher.Block) (cipher.AEAD, error) { ++ return c.(*aesCipher).NewGCMTLS() +} + -+// These wrappers allocate out_len on the C stack to avoid having to pass a pointer from Go, which would escape to the heap. -+// Use them only in situations where the output length can be safely discarded. -+static inline int -+go_openssl_EVP_EncryptUpdate_wrapper(GO_EVP_CIPHER_CTX_PTR ctx, unsigned char *out, const unsigned char *in, int in_len) -+{ -+ int len; -+ return go_openssl_EVP_EncryptUpdate(ctx, out, &len, in, in_len); ++func (c *aesCipher) NewGCMTLS() (cipher.AEAD, error) { ++ return c.newGCM(true) +} + -+static inline int -+go_openssl_EVP_DecryptUpdate_wrapper(GO_EVP_CIPHER_CTX_PTR ctx, unsigned char *out, const unsigned char *in, int in_len) -+{ -+ int len; -+ return go_openssl_EVP_DecryptUpdate(ctx, out, &len, in, in_len); ++func (c *aesCipher) newGCM(tls bool) (cipher.AEAD, error) { ++ var cipher cipherKind ++ switch len(c.key) * 8 { ++ case 128: ++ cipher = cipherAES128_GCM ++ case 192: ++ cipher = cipherAES192_GCM ++ case 256: ++ cipher = cipherAES256_GCM ++ default: ++ panic("openssl: unsupported key length") ++ } ++ ctx, err := newCipherCtx(cipher, -1, c.key, nil) ++ if err != nil { ++ return nil, err ++ } ++ g := &aesGCM{ctx: ctx, tls: tls} ++ runtime.SetFinalizer(g, (*aesGCM).finalize) ++ return g, nil +} + -+static inline int -+go_openssl_EVP_CipherUpdate_wrapper(GO_EVP_CIPHER_CTX_PTR ctx, unsigned char *out, const unsigned char *in, int in_len) -+{ -+ int len; -+ return go_openssl_EVP_CipherUpdate(ctx, out, &len, in, in_len); ++func (g *aesGCM) finalize() { ++ C.go_openssl_EVP_CIPHER_CTX_free(g.ctx) +} + ++func (g *aesGCM) NonceSize() int { ++ return gcmStandardNonceSize ++} + -+// These wrappers allocate out_len on the C stack, and check that it matches the expected -+// value, to avoid having to pass a pointer from Go, which would escape to the heap. ++func (g *aesGCM) Overhead() int { ++ return gcmTagSize ++} + -+static inline int -+go_openssl_EVP_CIPHER_CTX_seal_wrapper(const GO_EVP_CIPHER_CTX_PTR ctx, -+ unsigned char *out, -+ const unsigned char *nonce, -+ const unsigned char *in, int in_len, -+ const unsigned char *aad, int aad_len) -+{ -+ if (in_len == 0) in = (const unsigned char *)""; -+ if (aad_len == 0) aad = (const unsigned char *)""; ++func (g *aesGCM) Seal(dst, nonce, plaintext, additionalData []byte) []byte { ++ if len(nonce) != gcmStandardNonceSize { ++ panic("cipher: incorrect nonce length given to GCM") ++ } ++ if uint64(len(plaintext)) > ((1<<32)-2)*aesBlockSize || len(plaintext)+gcmTagSize < len(plaintext) { ++ panic("cipher: message too large for GCM") ++ } ++ if len(dst)+len(plaintext)+gcmTagSize < len(dst) { ++ panic("cipher: message too large for buffer") ++ } ++ if g.tls { ++ if len(additionalData) != gcmTlsAddSize { ++ panic("cipher: incorrect additional data length given to GCM TLS") ++ } ++ // BoringCrypto enforces strictly monotonically increasing explicit nonces ++ // and to fail after 2^64 - 1 keys as per FIPS 140-2 IG A.5, ++ // but OpenSSL does not perform this check, so it is implemented here. ++ const maxUint64 = 1<<64 - 1 ++ counter := binary.BigEndian.Uint64(nonce[gcmTlsFixedNonceSize:]) ++ if counter == maxUint64 { ++ panic("cipher: nonce counter must be less than 2^64 - 1") ++ } ++ if counter < g.minNextNonce { ++ panic("cipher: nonce counter must be strictly monotonically increasing") ++ } ++ defer func() { ++ g.minNextNonce = counter + 1 ++ }() ++ } + -+ if (go_openssl_EVP_CipherInit_ex(ctx, NULL, NULL, NULL, nonce, GO_AES_ENCRYPT) != 1) -+ return 0; ++ // Make room in dst to append plaintext+overhead. ++ ret, out := sliceForAppend(dst, len(plaintext)+gcmTagSize) + -+ int discard_len, out_len; -+ if (go_openssl_EVP_EncryptUpdate(ctx, NULL, &discard_len, aad, aad_len) != 1 -+ || go_openssl_EVP_EncryptUpdate(ctx, out, &out_len, in, in_len) != 1 -+ || go_openssl_EVP_EncryptFinal_ex(ctx, out + out_len, &discard_len) != 1) -+ { -+ return 0; -+ } ++ // Check delayed until now to make sure len(dst) is accurate. ++ if inexactOverlap(out, plaintext) { ++ panic("cipher: invalid buffer overlap") ++ } + -+ if (in_len != out_len) -+ return 0; ++ // Encrypt additional data. ++ // When sealing a TLS payload, OpenSSL app sets the additional data using ++ // 'EVP_CIPHER_CTX_ctrl(g.ctx, C.EVP_CTRL_AEAD_TLS1_AAD, C.EVP_AEAD_TLS1_AAD_LEN, base(additionalData))'. ++ // This makes the explicit nonce component to monotonically increase on every Seal operation without ++ // relying in the explicit nonce being securely set externally, ++ // and it also gives some interesting speed gains. ++ // Unfortunately we can't use it because Go expects AEAD.Seal to honor the provided nonce. ++ if C.go_openssl_EVP_CIPHER_CTX_seal_wrapper(g.ctx, base(out), base(nonce), ++ base(plaintext), C.int(len(plaintext)), ++ base(additionalData), C.int(len(additionalData))) != 1 { + -+ return go_openssl_EVP_CIPHER_CTX_ctrl(ctx, GO_EVP_CTRL_GCM_GET_TAG, 16, out + out_len); ++ panic(fail("EVP_CIPHER_CTX_seal")) ++ } ++ runtime.KeepAlive(g) ++ return ret +} + -+static inline int -+go_openssl_EVP_CIPHER_CTX_open_wrapper(const GO_EVP_CIPHER_CTX_PTR ctx, -+ unsigned char *out, -+ const unsigned char *nonce, -+ const unsigned char *in, int in_len, -+ const unsigned char *aad, int aad_len, -+ const unsigned char *tag) -+{ -+ if (in_len == 0) in = (const unsigned char *)""; -+ if (aad_len == 0) aad = (const unsigned char *)""; ++var errOpen = errors.New("cipher: message authentication failed") + -+ if (go_openssl_EVP_CipherInit_ex(ctx, NULL, NULL, NULL, nonce, GO_AES_DECRYPT) != 1) -+ return 0; ++func (g *aesGCM) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { ++ if len(nonce) != gcmStandardNonceSize { ++ panic("cipher: incorrect nonce length given to GCM") ++ } ++ if len(ciphertext) < gcmTagSize { ++ return nil, errOpen ++ } ++ if uint64(len(ciphertext)) > ((1<<32)-2)*aesBlockSize+gcmTagSize { ++ return nil, errOpen ++ } ++ // BoringCrypto does not do any TLS check when decrypting, neither do we. + -+ int discard_len, out_len; -+ if (go_openssl_EVP_DecryptUpdate(ctx, NULL, &discard_len, aad, aad_len) != 1 -+ || go_openssl_EVP_DecryptUpdate(ctx, out, &out_len, in, in_len) != 1) -+ { -+ return 0; -+ } ++ tag := ciphertext[len(ciphertext)-gcmTagSize:] ++ ciphertext = ciphertext[:len(ciphertext)-gcmTagSize] + -+ if (go_openssl_EVP_CIPHER_CTX_ctrl(ctx, GO_EVP_CTRL_GCM_SET_TAG, 16, (unsigned char *)(tag)) != 1) -+ return 0; ++ // Make room in dst to append ciphertext without tag. ++ ret, out := sliceForAppend(dst, len(ciphertext)) + -+ if (go_openssl_EVP_DecryptFinal_ex(ctx, out + out_len, &discard_len) != 1) -+ return 0; ++ // Check delayed until now to make sure len(dst) is accurate. ++ if inexactOverlap(out, ciphertext) { ++ panic("cipher: invalid buffer overlap") ++ } + -+ if (out_len != in_len) -+ return 0; ++ ok := C.go_openssl_EVP_CIPHER_CTX_open_wrapper( ++ g.ctx, base(out), base(nonce), ++ base(ciphertext), C.int(len(ciphertext)), ++ base(additionalData), C.int(len(additionalData)), base(tag)) ++ runtime.KeepAlive(g) ++ if ok == 0 { ++ // Zero output buffer on error. ++ for i := range out { ++ out[i] = 0 ++ } ++ return nil, errOpen ++ } ++ return ret, nil ++} + -+ return 1; ++// sliceForAppend is a mirror of crypto/cipher.sliceForAppend. ++func sliceForAppend(in []byte, n int) (head, tail []byte) { ++ if total := len(in) + n; cap(in) >= total { ++ head = in[:total] ++ } else { ++ head = make([]byte, total) ++ copy(head, in) ++ } ++ tail = head[len(in):] ++ return +} + -+// Hand-roll custom wrappers for CRYPTO_malloc and CRYPTO_free which cast the -+// function pointers to the correct signatures for OpenSSL 1.0.2. ++func newCipherCtx(kind cipherKind, mode C.int, key, iv []byte) (C.GO_EVP_CIPHER_CTX_PTR, error) { ++ cipher := newCipher(kind) ++ if cipher == nil { ++ panic("openssl: unsupported cipher: " + strconv.Itoa(int(kind))) ++ } ++ ctx := C.go_openssl_EVP_CIPHER_CTX_new() ++ if ctx == nil { ++ return nil, fail("unable to create EVP cipher ctx") ++ } ++ if C.go_openssl_EVP_CipherInit_ex(ctx, cipher, nil, base(key), base(iv), mode) != 1 { ++ C.go_openssl_EVP_CIPHER_CTX_free(ctx) ++ return nil, fail("unable to initialize EVP cipher ctx") ++ } ++ return ctx, nil ++} + -+static inline void * -+go_openssl_CRYPTO_malloc_legacy102(int num, const char *file, int line) { -+ return ((void *(*)(int, const char *, int))_g_CRYPTO_malloc)(num, file, line); ++// The following two functions are a mirror of golang.org/x/crypto/internal/subtle. ++ ++func anyOverlap(x, y []byte) bool { ++ return len(x) > 0 && len(y) > 0 && ++ uintptr(unsafe.Pointer(&x[0])) <= uintptr(unsafe.Pointer(&y[len(y)-1])) && ++ uintptr(unsafe.Pointer(&y[0])) <= uintptr(unsafe.Pointer(&x[len(x)-1])) +} + -+static inline void -+go_openssl_CRYPTO_free_legacy102(void *str) { -+ ((void (*)(void *))_g_CRYPTO_free)(str); ++func inexactOverlap(x, y []byte) bool { ++ if len(x) == 0 || len(y) == 0 || &x[0] == &y[0] { ++ return false ++ } ++ return anyOverlap(x, y) +} -\ No newline at end of file -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/hkdf.go b/src/vendor/github.com/golang-fips/openssl/v2/hkdf.go +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/bbig/big.go b/src/vendor/github.com/golang-fips/openssl/v2/bbig/big.go new file mode 100644 -index 0000000000..18b92059cc +index 0000000000..a81cbdbef9 --- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/hkdf.go -@@ -0,0 +1,176 @@ -+//go:build !cmd_go_bootstrap ++++ b/src/vendor/github.com/golang-fips/openssl/v2/bbig/big.go +@@ -0,0 +1,37 @@ ++// Copyright 2022 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. + -+package openssl ++// This is a mirror of ++// https://github.com/golang/go/blob/36b87f273cc43e21685179dc1664ebb5493d26ae/src/crypto/internal/boring/bbig/big.go. ++ ++package bbig + -+// #include "goopenssl.h" -+import "C" +import ( -+ "errors" -+ "hash" -+ "io" -+ "runtime" ++ "math/big" + "unsafe" -+) -+ -+func SupportsHKDF() bool { -+ return vMajor > 1 || -+ (vMajor >= 1 && vMinor > 1) || -+ (vMajor >= 1 && vMinor >= 1 && vPatch >= 1) -+} + -+func newHKDF(h func() hash.Hash, mode C.int) (*hkdf, error) { -+ if !SupportsHKDF() { -+ return nil, errUnsupportedVersion() -+ } ++ "github.com/golang-fips/openssl/v2" ++) + -+ ch := h() -+ md := hashToMD(ch) -+ if md == nil { -+ return nil, errors.New("unsupported hash function") ++func Enc(b *big.Int) openssl.BigInt { ++ if b == nil { ++ return nil + } -+ -+ ctx := C.go_openssl_EVP_PKEY_CTX_new_id(C.GO_EVP_PKEY_HKDF, nil) -+ if ctx == nil { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_new_id") ++ x := b.Bits() ++ if len(x) == 0 { ++ return openssl.BigInt{} + } -+ defer func() { -+ C.go_openssl_EVP_PKEY_CTX_free(ctx) -+ }() ++ return unsafe.Slice((*uint)(&x[0]), len(x)) ++} + -+ if C.go_openssl_EVP_PKEY_derive_init(ctx) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_derive_init") ++func Dec(b openssl.BigInt) *big.Int { ++ if b == nil { ++ return nil + } -+ switch vMajor { -+ case 3: -+ if C.go_openssl_EVP_PKEY_CTX_set_hkdf_mode(ctx, mode) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_set_hkdf_mode") -+ } -+ if C.go_openssl_EVP_PKEY_CTX_set_hkdf_md(ctx, md) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_set_hkdf_md") -+ } -+ case 1: -+ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, -1, C.GO1_EVP_PKEY_OP_DERIVE, -+ C.GO_EVP_PKEY_CTRL_HKDF_MODE, -+ C.int(mode), nil) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_set_hkdf_mode") -+ } -+ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, -1, C.GO1_EVP_PKEY_OP_DERIVE, -+ C.GO_EVP_PKEY_CTRL_HKDF_MD, -+ 0, unsafe.Pointer(md)) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_set_hkdf_md") -+ } ++ if len(b) == 0 { ++ return new(big.Int) + } ++ x := unsafe.Slice((*big.Word)(&b[0]), len(b)) ++ return new(big.Int).SetBits(x) ++} +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/big.go b/src/vendor/github.com/golang-fips/openssl/v2/big.go +new file mode 100644 +index 0000000000..6461f241f8 +--- /dev/null ++++ b/src/vendor/github.com/golang-fips/openssl/v2/big.go +@@ -0,0 +1,11 @@ ++package openssl + -+ c := &hkdf{ctx: ctx, hashLen: ch.Size()} -+ ctx = nil ++// This file does not have build constraints to ++// facilitate using BigInt in Go crypto. ++// Go crypto references BigInt unconditionally, ++// even if it is not finally used. + -+ runtime.SetFinalizer(c, (*hkdf).finalize) ++// A BigInt is the raw words from a BigInt. ++// This definition allows us to avoid importing math/big. ++// Conversion between BigInt and *big.Int is in openssl/bbig. ++type BigInt []uint +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/ec.go b/src/vendor/github.com/golang-fips/openssl/v2/ec.go +new file mode 100644 +index 0000000000..eac2f8bbee +--- /dev/null ++++ b/src/vendor/github.com/golang-fips/openssl/v2/ec.go +@@ -0,0 +1,59 @@ ++//go:build !cmd_go_bootstrap + -+ return c, nil -+} ++package openssl + -+type hkdf struct { -+ ctx C.GO_EVP_PKEY_CTX_PTR ++// #include "goopenssl.h" ++import "C" + -+ hashLen int -+ buf []byte -+} ++var ( ++ paramPubKey = C.CString("pub") ++ paramPrivKey = C.CString("priv") ++ paramGroup = C.CString("group") ++ paramECPubX = C.CString("qx") ++ paramECPubY = C.CString("qy") ++) + -+func (c *hkdf) finalize() { -+ if c.ctx != nil { -+ C.go_openssl_EVP_PKEY_CTX_free(c.ctx) ++func curveNID(curve string) (C.int, error) { ++ switch curve { ++ case "P-224": ++ return C.GO_NID_secp224r1, nil ++ case "P-256": ++ return C.GO_NID_X9_62_prime256v1, nil ++ case "P-384": ++ return C.GO_NID_secp384r1, nil ++ case "P-521": ++ return C.GO_NID_secp521r1, nil + } ++ return 0, errUnknownCurve +} + -+func (c *hkdf) Read(p []byte) (int, error) { -+ defer runtime.KeepAlive(c) -+ -+ // EVP_PKEY_derive doesn't support incremental output, each call -+ // derives the key from scratch and returns the requested bytes. -+ // To implement io.Reader, we need to ask for len(c.buf) + len(p) -+ // bytes and copy the last derived len(p) bytes to p. -+ // We use c.buf to know how many bytes we've already derived and -+ // to avoid allocating the whole output buffer on each call. -+ prevLen := len(c.buf) -+ needLen := len(p) -+ remains := 255*c.hashLen - prevLen -+ // Check whether enough data can be generated. -+ if remains < needLen { -+ return 0, errors.New("hkdf: entropy limit reached") ++// encodeEcPoint encodes pt. ++func encodeEcPoint(group C.GO_EC_GROUP_PTR, pt C.GO_EC_POINT_PTR) ([]byte, error) { ++ // Get encoded point size. ++ n := C.go_openssl_EC_POINT_point2oct(group, pt, C.GO_POINT_CONVERSION_UNCOMPRESSED, nil, 0, nil) ++ if n == 0 { ++ return nil, newOpenSSLError("EC_POINT_point2oct") + } -+ c.buf = append(c.buf, make([]byte, needLen)...) -+ outLen := C.size_t(prevLen + needLen) -+ if C.go_openssl_EVP_PKEY_derive(c.ctx, base(c.buf), &outLen) != 1 { -+ return 0, newOpenSSLError("EVP_PKEY_derive") ++ // Encode point into bytes. ++ bytes := make([]byte, n) ++ n = C.go_openssl_EC_POINT_point2oct(group, pt, C.GO_POINT_CONVERSION_UNCOMPRESSED, base(bytes), n, nil) ++ if n == 0 { ++ return nil, newOpenSSLError("EC_POINT_point2oct") + } -+ n := copy(p, c.buf[prevLen:outLen]) -+ return n, nil ++ return bytes, nil +} + -+func ExtractHKDF(h func() hash.Hash, secret, salt []byte) ([]byte, error) { -+ c, err := newHKDF(h, C.GO_EVP_KDF_HKDF_MODE_EXTRACT_ONLY) -+ if err != nil { -+ return nil, err -+ } -+ switch vMajor { -+ case 3: -+ if C.go_openssl_EVP_PKEY_CTX_set1_hkdf_key(c.ctx, -+ base(secret), C.int(len(secret))) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_set1_hkdf_key") -+ } -+ if C.go_openssl_EVP_PKEY_CTX_set1_hkdf_salt(c.ctx, -+ base(salt), C.int(len(salt))) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_set1_hkdf_salt") -+ } -+ case 1: -+ if C.go_openssl_EVP_PKEY_CTX_ctrl(c.ctx, -1, C.GO1_EVP_PKEY_OP_DERIVE, -+ C.GO_EVP_PKEY_CTRL_HKDF_KEY, -+ C.int(len(secret)), unsafe.Pointer(base(secret))) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_set1_hkdf_key") -+ } -+ if C.go_openssl_EVP_PKEY_CTX_ctrl(c.ctx, -1, C.GO1_EVP_PKEY_OP_DERIVE, -+ C.GO_EVP_PKEY_CTRL_HKDF_SALT, -+ C.int(len(salt)), unsafe.Pointer(base(salt))) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_set1_hkdf_salt") -+ } -+ } -+ var outLen C.size_t -+ if C.go_openssl_EVP_PKEY_derive(c.ctx, nil, &outLen) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_derive_init") -+ } -+ out := make([]byte, outLen) -+ if C.go_openssl_EVP_PKEY_derive(c.ctx, base(out), &outLen) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_derive") ++// generateAndEncodeEcPublicKey calls newPubKeyPointFn to generate a public key point and then encodes it. ++func generateAndEncodeEcPublicKey(nid C.int, newPubKeyPointFn func(group C.GO_EC_GROUP_PTR) (C.GO_EC_POINT_PTR, error)) ([]byte, error) { ++ group := C.go_openssl_EC_GROUP_new_by_curve_name(nid) ++ if group == nil { ++ return nil, newOpenSSLError("EC_GROUP_new_by_curve_name") + } -+ return out[:outLen], nil -+} -+ -+func ExpandHKDF(h func() hash.Hash, pseudorandomKey, info []byte) (io.Reader, error) { -+ c, err := newHKDF(h, C.GO_EVP_KDF_HKDF_MODE_EXPAND_ONLY) ++ defer C.go_openssl_EC_GROUP_free(group) ++ pt, err := newPubKeyPointFn(group) + if err != nil { + return nil, err + } -+ switch vMajor { -+ case 3: -+ if C.go_openssl_EVP_PKEY_CTX_set1_hkdf_key(c.ctx, -+ base(pseudorandomKey), C.int(len(pseudorandomKey))) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_set1_hkdf_key") -+ } -+ if C.go_openssl_EVP_PKEY_CTX_add1_hkdf_info(c.ctx, -+ base(info), C.int(len(info))) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_add1_hkdf_info") -+ } -+ case 1: -+ if C.go_openssl_EVP_PKEY_CTX_ctrl(c.ctx, -1, C.GO1_EVP_PKEY_OP_DERIVE, -+ C.GO_EVP_PKEY_CTRL_HKDF_KEY, -+ C.int(len(pseudorandomKey)), unsafe.Pointer(base(pseudorandomKey))) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_set1_hkdf_key") -+ } -+ if C.go_openssl_EVP_PKEY_CTX_ctrl(c.ctx, -1, C.GO1_EVP_PKEY_OP_DERIVE, -+ C.GO_EVP_PKEY_CTRL_HKDF_INFO, -+ C.int(len(info)), unsafe.Pointer(base(info))) != 1 { -+ return nil, newOpenSSLError("EVP_PKEY_CTX_add1_hkdf_info") -+ } -+ } -+ return c, nil ++ defer C.go_openssl_EC_POINT_free(pt) ++ return encodeEcPoint(group, pt) +} -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/hmac.go b/src/vendor/github.com/golang-fips/openssl/v2/hmac.go +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/ecdh.go b/src/vendor/github.com/golang-fips/openssl/v2/ecdh.go new file mode 100644 -index 0000000000..ef8116ce66 +index 0000000000..62e23333ce --- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/hmac.go -@@ -0,0 +1,238 @@ -<<<<<<< HEAD -+//go:build linux && !cmd_go_bootstrap ->>>>>>> 0023bf4c7a (rebase) -======= ++++ b/src/vendor/github.com/golang-fips/openssl/v2/ecdh.go +@@ -0,0 +1,323 @@ +//go:build !cmd_go_bootstrap ->>>>>>> 0b8240ca10 (support opensslv2, update strict fips checks) + +package openssl + +// #include "goopenssl.h" +import "C" +import ( -+ "hash" -<<<<<<< HEAD -+ "io" ++ "errors" + "runtime" ++ "unsafe" +) + -+type hkdf struct { -+ ctx *C.GO_EVP_PKEY_CTX ++type PublicKeyECDH struct { ++ _pkey C.GO_EVP_PKEY_PTR ++ bytes []byte +} + -+func SupportsHKDF() bool { -+ return openSSLVersion() >= OPENSSL_VERSION_1_1_1 ++func (k *PublicKeyECDH) finalize() { ++ C.go_openssl_EVP_PKEY_free(k._pkey) +} + -+func newHKDF(h func() hash.Hash, mode C.int) (*hkdf, error) { -+ if openSSLVersion() < OPENSSL_VERSION_1_1_1 { -+ return nil, NewOpenSSLError("HKDF is not supported") -+ } -+ -+ ch := h() -+ md := hashToMD(ch) -+ if md == nil { -+ return nil, NewOpenSSLError("Unknown hash algorithm") -+ } ++type PrivateKeyECDH struct { ++ _pkey C.GO_EVP_PKEY_PTR ++ curve string ++ hasPublicKey bool ++} + -+ ctx := C._goboringcrypto_EVP_PKEY_CTX_new_id(C.GO_EVP_PKEY_HKDF, nil) -+ if ctx == nil { -+ return nil, NewOpenSSLError("EVP_PKEY_CTX_new_id failed") -+ } -+ c := &hkdf{ctx: ctx} -+ runtime.SetFinalizer(c, (*hkdf).finalize) -+ defer runtime.KeepAlive(c) ++func (k *PrivateKeyECDH) finalize() { ++ C.go_openssl_EVP_PKEY_free(k._pkey) ++} + -+ if C._goboringcrypto_EVP_PKEY_derive_init(ctx) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_derive_init failed") -+ } -+ if C._goboringcrypto_EVP_PKEY_CTX_set_hkdf_mode(ctx, mode) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_CTX_set_hkdf_mode failed") ++func NewPublicKeyECDH(curve string, bytes []byte) (*PublicKeyECDH, error) { ++ if len(bytes) < 1 { ++ return nil, errors.New("NewPublicKeyECDH: missing key") + } -+ if C._goboringcrypto_EVP_PKEY_CTX_set_hkdf_md(ctx, md) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_CTX_set_hkdf_md failed") ++ pkey, err := newECDHPkey(curve, bytes, false) ++ if err != nil { ++ return nil, err + } -+ -+ return c, nil ++ k := &PublicKeyECDH{pkey, append([]byte(nil), bytes...)} ++ runtime.SetFinalizer(k, (*PublicKeyECDH).finalize) ++ return k, nil +} + -+func (c *hkdf) finalize() { -+ if c.ctx != nil { -+ C._goboringcrypto_EVP_PKEY_CTX_free(c.ctx) ++func (k *PublicKeyECDH) Bytes() []byte { return k.bytes } ++ ++func NewPrivateKeyECDH(curve string, bytes []byte) (*PrivateKeyECDH, error) { ++ pkey, err := newECDHPkey(curve, bytes, true) ++ if err != nil { ++ return nil, err + } ++ k := &PrivateKeyECDH{pkey, curve, false} ++ runtime.SetFinalizer(k, (*PrivateKeyECDH).finalize) ++ return k, nil +} + -+func (c *hkdf) Read(p []byte) (int, error) { -+ defer runtime.KeepAlive(c) ++func (k *PrivateKeyECDH) PublicKey() (*PublicKeyECDH, error) { ++ defer runtime.KeepAlive(k) ++ if !k.hasPublicKey { ++ err := deriveEcdhPublicKey(k._pkey, k.curve) ++ if err != nil { ++ return nil, err ++ } ++ k.hasPublicKey = true ++ } ++ var pkey C.GO_EVP_PKEY_PTR ++ defer func() { ++ C.go_openssl_EVP_PKEY_free(pkey) ++ }() ++ ++ var bytes []byte ++ switch vMajor { ++ case 1: ++ pkey = C.go_openssl_EVP_PKEY_new() ++ if pkey == nil { ++ return nil, newOpenSSLError("EVP_PKEY_new") ++ } ++ key := getECKey(k._pkey) ++ if C.go_openssl_EVP_PKEY_set1_EC_KEY(pkey, key) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_set1_EC_KEY") ++ } ++ pt := C.go_openssl_EC_KEY_get0_public_key(key) ++ if pt == nil { ++ return nil, newOpenSSLError("EC_KEY_get0_public_key") ++ } ++ group := C.go_openssl_EC_KEY_get0_group(key) ++ var err error ++ bytes, err = encodeEcPoint(group, pt) ++ if err != nil { ++ return nil, err ++ } ++ case 3: ++ pkey = k._pkey ++ if C.go_openssl_EVP_PKEY_up_ref(pkey) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_up_ref") ++ } + -+ outLen := C.size_t(len(p)) -+ if C._goboringcrypto_EVP_PKEY_derive(c.ctx, base(p), &outLen) != 1 { -+ return 0, NewOpenSSLError("EVP_PKEY_derive failed") ++ var cbytes *C.uchar ++ n := C.go_openssl_EVP_PKEY_get1_encoded_public_key(k._pkey, &cbytes) ++ if n == 0 { ++ return nil, newOpenSSLError("EVP_PKEY_get_octet_string_param") ++ } ++ bytes = C.GoBytes(unsafe.Pointer(cbytes), C.int(n)) ++ cryptoFree(unsafe.Pointer(cbytes)) ++ default: ++ panic(errUnsupportedVersion()) + } -+ return int(outLen), nil ++ pub := &PublicKeyECDH{pkey, bytes} ++ pkey = nil ++ runtime.SetFinalizer(pub, (*PublicKeyECDH).finalize) ++ return pub, nil +} + -+func ExtractHKDF(h func() hash.Hash, secret, salt []byte) ([]byte, error) { -+ c, err := newHKDF(h, C.GO_EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) ++func newECDHPkey(curve string, bytes []byte, isPrivate bool) (C.GO_EVP_PKEY_PTR, error) { ++ nid, err := curveNID(curve) + if err != nil { + return nil, err + } -+ if C._goboringcrypto_EVP_PKEY_CTX_set1_hkdf_key(c.ctx, base(secret), C.int(len(secret))) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_CTX_set1_hkdf_key failed") -+ } -+ if C._goboringcrypto_EVP_PKEY_CTX_set1_hkdf_salt(c.ctx, base(salt), C.int(len(salt))) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_CTX_set1_hkdf_salt failed") -+ } -+ var outLen C.size_t -+ if C._goboringcrypto_EVP_PKEY_derive(c.ctx, nil, &outLen) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_derive_init failed") -+ } -+ out := make([]byte, outLen) -+ if C._goboringcrypto_EVP_PKEY_derive(c.ctx, base(out), &outLen) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_derive failed") ++ switch vMajor { ++ case 1: ++ return newECDHPkey1(nid, bytes, isPrivate) ++ case 3: ++ return newECDHPkey3(nid, bytes, isPrivate) ++ default: ++ panic(errUnsupportedVersion()) + } -+ return out[:outLen], nil +} + -+func ExpandHKDF(h func() hash.Hash, pseudorandomKey, info []byte) (io.Reader, error) { -+ c, err := newHKDF(h, C.GO_EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) -+ if err != nil { -+ return nil, err ++func newECDHPkey1(nid C.int, bytes []byte, isPrivate bool) (pkey C.GO_EVP_PKEY_PTR, err error) { ++ if vMajor != 1 { ++ panic("incorrect vMajor version") + } -+ if C._goboringcrypto_EVP_PKEY_CTX_set1_hkdf_key(c.ctx, base(pseudorandomKey), C.int(len(pseudorandomKey))) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_CTX_set1_hkdf_key failed") ++ key := C.go_openssl_EC_KEY_new_by_curve_name(nid) ++ if key == nil { ++ return nil, newOpenSSLError("EC_KEY_new_by_curve_name") + } -+ if C._goboringcrypto_EVP_PKEY_CTX_add1_hkdf_info(c.ctx, base(info), C.int(len(info))) != 1 { -+ return nil, NewOpenSSLError("EVP_PKEY_CTX_add1_hkdf_info failed") ++ defer func() { ++ if pkey == nil { ++ C.go_openssl_EC_KEY_free(key) ++ } ++ }() ++ if isPrivate { ++ priv := C.go_openssl_BN_bin2bn(base(bytes), C.int(len(bytes)), nil) ++ if priv == nil { ++ return nil, newOpenSSLError("BN_bin2bn") ++ } ++ defer C.go_openssl_BN_clear_free(priv) ++ if C.go_openssl_EC_KEY_set_private_key(key, priv) != 1 { ++ return nil, newOpenSSLError("EC_KEY_set_private_key") ++ } ++ } else { ++ group := C.go_openssl_EC_KEY_get0_group(key) ++ pub := C.go_openssl_EC_POINT_new(group) ++ if pub == nil { ++ return nil, newOpenSSLError("EC_POINT_new") ++ } ++ defer C.go_openssl_EC_POINT_free(pub) ++ if C.go_openssl_EC_POINT_oct2point(group, pub, base(bytes), C.size_t(len(bytes)), nil) != 1 { ++ return nil, errors.New("point not on curve") ++ } ++ if C.go_openssl_EC_KEY_set_public_key(key, pub) != 1 { ++ return nil, newOpenSSLError("EC_KEY_set_public_key") ++ } + } -+ return c, nil ++ return newEVPPKEY(key) +} -diff --git a/src/crypto/internal/boring/hmac.go b/src/vendor/github.com/golang-fips/openssl-fips/openssl/hmac.go -similarity index 69% -rename from src/crypto/internal/boring/hmac.go -rename to src/vendor/github.com/golang-fips/openssl-fips/openssl/hmac.go -index 6241a65f5f..6f001777ae 100644 ---- a/src/crypto/internal/boring/hmac.go -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/hmac.go -@@ -2,14 +2,14 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build boringcrypto && linux && (amd64 || arm64) && !android && !cmd_go_bootstrap && !msan -+//go:build linux && !android && !cmd_go_bootstrap && !msan && !no_openssl -+// +build linux,!android,!cmd_go_bootstrap,!msan,!no_openssl - --package boring -+package openssl - --// #include "goboringcrypto.h" -+// #include "goopenssl.h" - import "C" - import ( -- "bytes" - "crypto" - "hash" - "runtime" -@@ -67,13 +67,25 @@ func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { - return nil - } - -- // Note: Could hash down long keys here using EVP_Digest. -- hkey := bytes.Clone(key) -+ var hkey []byte -+ if key != nil && len(key) > 0 { -+ // Note: Could hash down long keys here using EVP_Digest. -+ hkey = make([]byte, len(key)) -+ copy(hkey, key) -+ } else { -+ // This is supported in BoringSSL/Standard lib and as such -+ // we must support it here. When using HMAC with a null key -+ // HMAC_Init will try and reuse the key from the ctx. This is -+ // not the bahavior previously implemented, so as a workaround -+ // we pass an "empty" key. -+ hkey = make([]byte, C.EVP_MAX_MD_SIZE) -+ } - hmac := &boringHMAC{ - md: md, - size: ch.Size(), - blockSize: ch.BlockSize(), - key: hkey, -+ ctx: C._goboringcrypto_HMAC_CTX_new(), - } - hmac.Reset() - return hmac -@@ -81,8 +93,8 @@ func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { - - type boringHMAC struct { - md *C.GO_EVP_MD -- ctx C.GO_HMAC_CTX -- ctx2 C.GO_HMAC_CTX -+ ctx *C.GO_HMAC_CTX -+ ctx2 *C.GO_HMAC_CTX - size int - blockSize int - key []byte -@@ -91,9 +103,7 @@ type boringHMAC struct { - } - - func (h *boringHMAC) Reset() { -- if h.needCleanup { -- C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx) -- } else { -+ if !h.needCleanup { - h.needCleanup = true - // Note: Because of the finalizer, any time h.ctx is passed to cgo, - // that call must be followed by a call to runtime.KeepAlive(h), -@@ -101,13 +111,13 @@ func (h *boringHMAC) Reset() { - // call returns. - runtime.SetFinalizer(h, (*boringHMAC).finalize) - } -- C._goboringcrypto_HMAC_CTX_init(&h.ctx) -+ C._goboringcrypto_HMAC_CTX_reset(h.ctx) - -- if C._goboringcrypto_HMAC_Init(&h.ctx, unsafe.Pointer(base(h.key)), C.int(len(h.key)), h.md) == 0 { -+ if C._goboringcrypto_HMAC_Init_ex(h.ctx, unsafe.Pointer(base(h.key)), C.int(len(h.key)), h.md, nil) == 0 { - panic("boringcrypto: HMAC_Init failed") - } -- if int(C._goboringcrypto_HMAC_size(&h.ctx)) != h.size { -- println("boringcrypto: HMAC size:", C._goboringcrypto_HMAC_size(&h.ctx), "!=", h.size) -+ if int(C._goboringcrypto_HMAC_size(h.ctx)) != h.size { -+ println("boringcrypto: HMAC size:", C._goboringcrypto_HMAC_size(h.ctx), "!=", h.size) - panic("boringcrypto: HMAC size mismatch") - } - runtime.KeepAlive(h) // Next line will keep h alive too; just making doubly sure. -@@ -115,12 +125,12 @@ func (h *boringHMAC) Reset() { - } - - func (h *boringHMAC) finalize() { -- C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx) -+ C._goboringcrypto_HMAC_CTX_free(h.ctx) - } - - func (h *boringHMAC) Write(p []byte) (int, error) { - if len(p) > 0 { -- C._goboringcrypto_HMAC_Update(&h.ctx, (*C.uint8_t)(unsafe.Pointer(&p[0])), C.size_t(len(p))) -+ C._goboringcrypto_HMAC_Update(h.ctx, (*C.uint8_t)(unsafe.Pointer(&p[0])), C.size_t(len(p))) - } - runtime.KeepAlive(h) - return len(p), nil -@@ -143,11 +153,11 @@ func (h *boringHMAC) Sum(in []byte) []byte { - // that Sum has no effect on the underlying stream. - // In particular it is OK to Sum, then Write more, then Sum again, - // and the second Sum acts as if the first didn't happen. -- C._goboringcrypto_HMAC_CTX_init(&h.ctx2) -- if C._goboringcrypto_HMAC_CTX_copy_ex(&h.ctx2, &h.ctx) == 0 { -+ h.ctx2 = C._goboringcrypto_HMAC_CTX_new() -+ if C._goboringcrypto_HMAC_CTX_copy_ex(h.ctx2, h.ctx) == 0 { - panic("boringcrypto: HMAC_CTX_copy_ex failed") - } -- C._goboringcrypto_HMAC_Final(&h.ctx2, (*C.uint8_t)(unsafe.Pointer(&h.sum[0])), nil) -- C._goboringcrypto_HMAC_CTX_cleanup(&h.ctx2) -+ C._goboringcrypto_HMAC_Final(h.ctx2, (*C.uint8_t)(unsafe.Pointer(&h.sum[0])), nil) -+ C._goboringcrypto_HMAC_CTX_free(h.ctx2) - return append(in, h.sum...) - } -diff --git a/src/crypto/internal/boring/notboring.go b/src/vendor/github.com/golang-fips/openssl-fips/openssl/notboring.go -similarity index 63% -rename from src/crypto/internal/boring/notboring.go -rename to src/vendor/github.com/golang-fips/openssl-fips/openssl/notboring.go -index 1c5e4c742d..2fa4a38e44 100644 ---- a/src/crypto/internal/boring/notboring.go -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/notboring.go -@@ -2,32 +2,34 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build !(boringcrypto && linux && (amd64 || arm64) && !android && !cmd_go_bootstrap && !msan && cgo) -+//go:build !linux || !cgo || android || cmd_go_bootstrap || msan || no_openssl -+// +build !linux !cgo android cmd_go_bootstrap msan no_openssl - --package boring -+package openssl - - import ( - "crypto" - "crypto/cipher" -- "crypto/internal/boring/sig" - "hash" -+ "io" - ) - --const available = false -+var enabled = false - - // Unreachable marks code that should be unreachable - // when BoringCrypto is in use. It is a no-op without BoringCrypto. - func Unreachable() { -- // Code that's unreachable when using BoringCrypto -- // is exactly the code we want to detect for reporting -- // standard Go crypto. -- sig.StandardCrypto() - } - - // UnreachableExceptTests marks code that should be unreachable - // when BoringCrypto is in use. It is a no-op without BoringCrypto. - func UnreachableExceptTests() {} - -+func ExecutingTest() bool { return false } -+ -+// This is a noop withotu BoringCrytpo. -+func PanicIfStrictFIPS(v interface{}) {} + - type randReader int - - func (randReader) Read(b []byte) (int, error) { panic("boringcrypto: not available") } -@@ -40,16 +42,9 @@ func NewSHA256() hash.Hash { panic("boringcrypto: not available") } - func NewSHA384() hash.Hash { panic("boringcrypto: not available") } - func NewSHA512() hash.Hash { panic("boringcrypto: not available") } - --func SHA1([]byte) [20]byte { panic("boringcrypto: not available") } --func SHA224([]byte) [28]byte { panic("boringcrypto: not available") } --func SHA256([]byte) [32]byte { panic("boringcrypto: not available") } --func SHA384([]byte) [48]byte { panic("boringcrypto: not available") } --func SHA512([]byte) [64]byte { panic("boringcrypto: not available") } -- - func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { panic("boringcrypto: not available") } - - func NewAESCipher(key []byte) (cipher.Block, error) { panic("boringcrypto: not available") } --func NewGCMTLS(cipher.Block) (cipher.AEAD, error) { panic("boringcrypto: not available") } - - type PublicKeyECDSA struct{ _ int } - type PrivateKeyECDSA struct{ _ int } -@@ -63,17 +58,39 @@ func NewPrivateKeyECDSA(curve string, X, Y, D BigInt) (*PrivateKeyECDSA, error) - func NewPublicKeyECDSA(curve string, X, Y BigInt) (*PublicKeyECDSA, error) { - panic("boringcrypto: not available") - } --func SignMarshalECDSA(priv *PrivateKeyECDSA, hash []byte) ([]byte, error) { -+func SignECDSA(priv *PrivateKeyECDSA, hash []byte, h crypto.Hash) (r, s BigInt, err error) { -+ panic("boringcrypto: not available") -+} -+func SignMarshalECDSA(priv *PrivateKeyECDSA, hash []byte, h crypto.Hash) ([]byte, error) { -+ panic("boringcrypto: not available") -+} -+func VerifyECDSA(pub *PublicKeyECDSA, hash []byte, r, s BigInt, h crypto.Hash) bool { -+ panic("boringcrypto: not available") ++func newECDHPkey3(nid C.int, bytes []byte, isPrivate bool) (C.GO_EVP_PKEY_PTR, error) { ++ if vMajor != 3 { ++ panic("incorrect vMajor version") ++ } ++ bld := C.go_openssl_OSSL_PARAM_BLD_new() ++ if bld == nil { ++ return nil, newOpenSSLError("OSSL_PARAM_BLD_new") ++ } ++ defer C.go_openssl_OSSL_PARAM_BLD_free(bld) ++ C.go_openssl_OSSL_PARAM_BLD_push_utf8_string(bld, paramGroup, C.go_openssl_OBJ_nid2sn(nid), 0) ++ var selection C.int ++ if isPrivate { ++ priv := C.go_openssl_BN_bin2bn(base(bytes), C.int(len(bytes)), nil) ++ if priv == nil { ++ return nil, newOpenSSLError("BN_bin2bn") ++ } ++ defer C.go_openssl_BN_clear_free(priv) ++ if C.go_openssl_OSSL_PARAM_BLD_push_BN(bld, paramPrivKey, priv) != 1 { ++ return nil, newOpenSSLError("OSSL_PARAM_BLD_push_BN") ++ } ++ selection = C.GO_EVP_PKEY_KEYPAIR ++ } else { ++ cbytes := C.CBytes(bytes) ++ defer C.free(cbytes) ++ C.go_openssl_OSSL_PARAM_BLD_push_octet_string(bld, paramPubKey, cbytes, C.size_t(len(bytes))) ++ selection = C.GO_EVP_PKEY_PUBLIC_KEY ++ } ++ params := C.go_openssl_OSSL_PARAM_BLD_to_param(bld) ++ if params == nil { ++ return nil, newOpenSSLError("OSSL_PARAM_BLD_to_param") ++ } ++ defer C.go_openssl_OSSL_PARAM_free(params) ++ return newEvpFromParams(C.GO_EVP_PKEY_EC, selection, params) +} + -+type PublicKeyECDH struct{ _ int } -+type PrivateKeyECDH struct{ _ int } -+ -+func (pc *PublicKeyECDH) Bytes() []byte { panic("boringcrypto: not available") } -+func (pc *PrivateKeyECDH) PublicKey() (*PublicKeyECDH, error) { panic("boringcrypto: not available") } -+ -+func NewPublicKeyECDH(curve string, bytes []byte) (*PublicKeyECDH, error) { -+ panic("boringcrypto: not available") -+} -+func NewPrivateKeyECDH(curve string, bytes []byte) (*PrivateKeyECDH, error) { -+ panic("boringcrypto: not available") ++// deriveEcdhPublicKey sets the raw public key of pkey by deriving it from ++// the raw private key. ++func deriveEcdhPublicKey(pkey C.GO_EVP_PKEY_PTR, curve string) error { ++ derive := func(group C.GO_EC_GROUP_PTR, priv C.GO_BIGNUM_PTR) (C.GO_EC_POINT_PTR, error) { ++ // OpenSSL does not expose any method to generate the public ++ // key from the private key [1], so we have to calculate it here. ++ // [1] https://github.com/openssl/openssl/issues/18437#issuecomment-1144717206 ++ pt := C.go_openssl_EC_POINT_new(group) ++ if pt == nil { ++ return nil, newOpenSSLError("EC_POINT_new") ++ } ++ if C.go_openssl_EC_POINT_mul(group, pt, priv, nil, nil, nil) == 0 { ++ C.go_openssl_EC_POINT_free(pt) ++ return nil, newOpenSSLError("EC_POINT_mul") ++ } ++ return pt, nil ++ } ++ switch vMajor { ++ case 1: ++ key := getECKey(pkey) ++ priv := C.go_openssl_EC_KEY_get0_private_key(key) ++ if priv == nil { ++ return newOpenSSLError("EC_KEY_get0_private_key") ++ } ++ group := C.go_openssl_EC_KEY_get0_group(key) ++ pub, err := derive(group, priv) ++ if err != nil { ++ return err ++ } ++ defer C.go_openssl_EC_POINT_free(pub) ++ if C.go_openssl_EC_KEY_set_public_key(key, pub) != 1 { ++ return newOpenSSLError("EC_KEY_set_public_key") ++ } ++ case 3: ++ var priv C.GO_BIGNUM_PTR ++ if C.go_openssl_EVP_PKEY_get_bn_param(pkey, paramPrivKey, &priv) != 1 { ++ return newOpenSSLError("EVP_PKEY_get_bn_param") ++ } ++ defer C.go_openssl_BN_clear_free(priv) ++ nid, _ := curveNID(curve) ++ pubBytes, err := generateAndEncodeEcPublicKey(nid, func(group C.GO_EC_GROUP_PTR) (C.GO_EC_POINT_PTR, error) { ++ return derive(group, priv) ++ }) ++ if err != nil { ++ return err ++ } ++ if C.go_openssl_EVP_PKEY_set1_encoded_public_key(pkey, base(pubBytes), C.size_t(len(pubBytes))) != 1 { ++ return newOpenSSLError("EVP_PKEY_set1_encoded_public_key") ++ } ++ default: ++ panic(errUnsupportedVersion()) ++ } ++ return nil +} ++ +func ECDH(priv *PrivateKeyECDH, pub *PublicKeyECDH) ([]byte, error) { - panic("boringcrypto: not available") - } --func VerifyECDSA(pub *PublicKeyECDSA, hash []byte, sig []byte) bool { -+func GenerateKeyECDH(curve string) (*PrivateKeyECDH, []byte, error) { - panic("boringcrypto: not available") - } - - type PublicKeyRSA struct{ _ int } - type PrivateKeyRSA struct{ _ int } - --func DecryptRSAOAEP(h, mgfHash hash.Hash, priv *PrivateKeyRSA, ciphertext, label []byte) ([]byte, error) { -+func DecryptRSAOAEP(h hash.Hash, priv *PrivateKeyRSA, ciphertext, label []byte) ([]byte, error) { - panic("boringcrypto: not available") - } - func DecryptRSAPKCS1(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) { -@@ -82,7 +99,7 @@ func DecryptRSAPKCS1(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) { - func DecryptRSANoPadding(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) { - panic("boringcrypto: not available") - } --func EncryptRSAOAEP(h, mgfHash hash.Hash, pub *PublicKeyRSA, msg, label []byte) ([]byte, error) { -+func EncryptRSAOAEP(h hash.Hash, pub *PublicKeyRSA, msg, label []byte) ([]byte, error) { - panic("boringcrypto: not available") - } - func EncryptRSAPKCS1(pub *PublicKeyRSA, msg []byte) ([]byte, error) { -@@ -98,25 +115,23 @@ func NewPrivateKeyRSA(N, E, D, P, Q, Dp, Dq, Qinv BigInt) (*PrivateKeyRSA, error - panic("boringcrypto: not available") - } - func NewPublicKeyRSA(N, E BigInt) (*PublicKeyRSA, error) { panic("boringcrypto: not available") } --func SignRSAPKCS1v15(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte) ([]byte, error) { -+func SignRSAPKCS1v15(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte, msgHashed bool) ([]byte, error) { - panic("boringcrypto: not available") - } - func SignRSAPSS(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte, saltLen int) ([]byte, error) { - panic("boringcrypto: not available") - } --func VerifyRSAPKCS1v15(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte) error { -+func VerifyRSAPKCS1v15(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte, msgHashed bool) error { - panic("boringcrypto: not available") - } - func VerifyRSAPSS(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte, saltLen int) error { - panic("boringcrypto: not available") - } - --type PublicKeyECDH struct{} --type PrivateKeyECDH struct{} -+func ExtractHKDF(h func() hash.Hash, secret, salt []byte) ([]byte, error) { -+ panic("boringcrypto: not available") ++ defer runtime.KeepAlive(priv) ++ defer runtime.KeepAlive(pub) ++ ctx := C.go_openssl_EVP_PKEY_CTX_new(priv._pkey, nil) ++ if ctx == nil { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_new") ++ } ++ defer C.go_openssl_EVP_PKEY_CTX_free(ctx) ++ if C.go_openssl_EVP_PKEY_derive_init(ctx) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_derive_init") ++ } ++ if C.go_openssl_EVP_PKEY_derive_set_peer(ctx, pub._pkey) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_derive_set_peer") ++ } ++ var outLen C.size_t ++ if C.go_openssl_EVP_PKEY_derive(ctx, nil, &outLen) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_derive_init") ++ } ++ out := make([]byte, outLen) ++ if C.go_openssl_EVP_PKEY_derive(ctx, base(out), &outLen) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_derive_init") ++ } ++ return out, nil +} - --func ECDH(*PrivateKeyECDH, *PublicKeyECDH) ([]byte, error) { panic("boringcrypto: not available") } --func GenerateKeyECDH(string) (*PrivateKeyECDH, []byte, error) { panic("boringcrypto: not available") } --func NewPrivateKeyECDH(string, []byte) (*PrivateKeyECDH, error) { panic("boringcrypto: not available") } --func NewPublicKeyECDH(string, []byte) (*PublicKeyECDH, error) { panic("boringcrypto: not available") } --func (*PublicKeyECDH) Bytes() []byte { panic("boringcrypto: not available") } --func (*PrivateKeyECDH) PublicKey() (*PublicKeyECDH, error) { panic("boringcrypto: not available") } -+func ExpandHKDF(h func() hash.Hash, pseudorandomKey, info []byte) (io.Reader, error) { -+ panic("boringcrypto: not available") ++ ++func GenerateKeyECDH(curve string) (*PrivateKeyECDH, []byte, error) { ++ pkey, err := generateEVPPKey(C.GO_EVP_PKEY_EC, 0, curve) ++ if err != nil { ++ return nil, nil, err ++ } ++ var k *PrivateKeyECDH ++ defer func() { ++ if k == nil { ++ C.go_openssl_EVP_PKEY_free(pkey) ++ } ++ }() ++ var priv C.GO_BIGNUM_PTR ++ switch vMajor { ++ case 1: ++ key := getECKey(pkey) ++ priv = C.go_openssl_EC_KEY_get0_private_key(key) ++ if priv == nil { ++ return nil, nil, newOpenSSLError("EC_KEY_get0_private_key") ++ } ++ case 3: ++ if C.go_openssl_EVP_PKEY_get_bn_param(pkey, paramPrivKey, &priv) != 1 { ++ return nil, nil, newOpenSSLError("EVP_PKEY_get_bn_param") ++ } ++ defer C.go_openssl_BN_clear_free(priv) ++ default: ++ panic(errUnsupportedVersion()) ++ } ++ // We should not leak bit length of the secret scalar in the key. ++ // For this reason, we use BN_bn2binpad instead of BN_bn2bin with fixed length. ++ // The fixed length is the order of the large prime subgroup of the curve, ++ // returned by EVP_PKEY_get_bits, which is generally the upper bound for ++ // generating a private ECDH key. ++ bits := C.go_openssl_EVP_PKEY_get_bits(pkey) ++ bytes := make([]byte, (bits+7)/8) ++ if err := bnToBinPad(priv, bytes); err != nil { ++ return nil, nil, err ++ } ++ k = &PrivateKeyECDH{pkey, curve, true} ++ runtime.SetFinalizer(k, (*PrivateKeyECDH).finalize) ++ return k, bytes, nil +} -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl.go b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl.go +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/ecdsa.go b/src/vendor/github.com/golang-fips/openssl/v2/ecdsa.go new file mode 100644 -index 0000000000..e93b042e5e +index 0000000000..46b16abf48 --- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl.go -@@ -0,0 +1,288 @@ -+// 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 -+// +build linux,!android,!cmd_go_bootstrap,!msan,!no_openssl ++++ b/src/vendor/github.com/golang-fips/openssl/v2/ecdsa.go +@@ -0,0 +1,217 @@ ++//go:build !cmd_go_bootstrap + +package openssl + -+/* -+#cgo LDFLAGS: -ldl -+ -+#include "goopenssl.h" -+*/ -======= ++// #include "goopenssl.h" ++import "C" ++import ( ++ "crypto" ++ "errors" + "runtime" -+ "sync" -+ "unsafe" +) + -+var paramDigest = C.CString("digest") -+ -+var ( -+ fetchHMACOnce sync.Once -+ evpHMAC C.GO_EVP_MAC_PTR -+) ++type PrivateKeyECDSA struct { ++ // _pkey MUST NOT be accessed directly. Instead, use the withKey method. ++ _pkey C.GO_EVP_PKEY_PTR ++} + -+// NewHMAC returns a new HMAC using OpenSSL. -+// The function h must return a hash implemented by -+// OpenSSL (for example, h could be openssl.NewSHA256). -+// If h is not recognized, NewHMAC returns nil. -+func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { -+ ch := h() -+ md := hashToMD(ch) -+ if md == nil { -+ return nil -+ } ++func (k *PrivateKeyECDSA) finalize() { ++ C.go_openssl_EVP_PKEY_free(k._pkey) ++} + -+ if len(key) == 0 { -+ // This is supported in OpenSSL/Standard lib and as such -+ // we must support it here. When using HMAC with a null key -+ // HMAC_Init will try and reuse the key from the ctx. This is -+ // not the behavior previously implemented, so as a workaround -+ // we pass an "empty" key. -+ key = make([]byte, C.GO_EVP_MAX_MD_SIZE) -+ } ++func (k *PrivateKeyECDSA) withKey(f func(C.GO_EVP_PKEY_PTR) C.int) C.int { ++ defer runtime.KeepAlive(k) ++ return f(k._pkey) ++} + -+ switch vMajor { -+ case 1: -+ return newHMAC1(key, ch, md) -+ case 3: -+ return newHMAC3(key, ch, md) -+ default: -+ panic(errUnsupportedVersion()) -+ } ++type PublicKeyECDSA struct { ++ // _pkey MUST NOT be accessed directly. Instead, use the withKey method. ++ _pkey C.GO_EVP_PKEY_PTR +} + -+// hmacCtx3 is used for OpenSSL 1. -+type hmacCtx1 struct { -+ ctx C.GO_HMAC_CTX_PTR ++func (k *PublicKeyECDSA) finalize() { ++ C.go_openssl_EVP_PKEY_free(k._pkey) +} + -+// hmacCtx3 is used for OpenSSL 3. -+type hmacCtx3 struct { -+ ctx C.GO_EVP_MAC_CTX_PTR -+ key []byte // only set for OpenSSL 3.0.0, 3.0.1, and 3.0.2. ++func (k *PublicKeyECDSA) withKey(f func(C.GO_EVP_PKEY_PTR) C.int) C.int { ++ defer runtime.KeepAlive(k) ++ return f(k._pkey) +} + -+type opensslHMAC struct { -+ ctx1 hmacCtx1 -+ ctx3 hmacCtx3 -+ size int -+ blockSize int -+ sum []byte ++var errUnknownCurve = errors.New("openssl: unknown elliptic curve") ++ ++func NewPublicKeyECDSA(curve string, X, Y BigInt) (*PublicKeyECDSA, error) { ++ pkey, err := newECDSAKey(curve, X, Y, nil) ++ if err != nil { ++ return nil, err ++ } ++ k := &PublicKeyECDSA{_pkey: pkey} ++ runtime.SetFinalizer(k, (*PublicKeyECDSA).finalize) ++ return k, nil +} + -+func newHMAC1(key []byte, h hash.Hash, md C.GO_EVP_MD_PTR) *opensslHMAC { -+ ctx := hmacCtxNew() -+ if ctx == nil { -+ panic("openssl: EVP_MAC_CTX_new failed") -+ } -+ if C.go_openssl_HMAC_Init_ex(ctx, unsafe.Pointer(&key[0]), C.int(len(key)), md, nil) == 0 { -+ panic(newOpenSSLError("HMAC_Init_ex failed")) -+ } -+ hmac := &opensslHMAC{ -+ size: h.Size(), -+ blockSize: h.BlockSize(), -+ ctx1: hmacCtx1{ctx}, ++func NewPrivateKeyECDSA(curve string, X, Y, D BigInt) (*PrivateKeyECDSA, error) { ++ pkey, err := newECDSAKey(curve, X, Y, D) ++ if err != nil { ++ return nil, err + } -+ runtime.SetFinalizer(hmac, (*opensslHMAC).finalize) -+ return hmac ++ k := &PrivateKeyECDSA{_pkey: pkey} ++ runtime.SetFinalizer(k, (*PrivateKeyECDSA).finalize) ++ return k, nil +} + -+func newHMAC3(key []byte, h hash.Hash, md C.GO_EVP_MD_PTR) *opensslHMAC { -+ fetchHMACOnce.Do(func() { -+ name := C.CString("HMAC") -+ evpHMAC = C.go_openssl_EVP_MAC_fetch(nil, name, nil) -+ C.free(unsafe.Pointer(name)) -+ }) -+ if evpHMAC == nil { -+ panic("openssl: HMAC not supported") -+ } -+ ctx := C.go_openssl_EVP_MAC_CTX_new(evpHMAC) -+ if ctx == nil { -+ panic("openssl: EVP_MAC_CTX_new failed") -+ } -+ digest := C.go_openssl_EVP_MD_get0_name(md) -+ bld := C.go_openssl_OSSL_PARAM_BLD_new() -+ if bld == nil { -+ panic(newOpenSSLError("OSSL_PARAM_BLD_new")) -+ } -+ defer C.go_openssl_OSSL_PARAM_BLD_free(bld) -+ C.go_openssl_OSSL_PARAM_BLD_push_utf8_string(bld, paramDigest, digest, 0) -+ params := C.go_openssl_OSSL_PARAM_BLD_to_param(bld) -+ if params == nil { -+ panic(newOpenSSLError("OSSL_PARAM_BLD_to_param")) -+ } -+ defer C.go_openssl_OSSL_PARAM_free(params) -+ if C.go_openssl_EVP_MAC_init(ctx, base(key), C.size_t(len(key)), params) == 0 { -+ panic(newOpenSSLError("EVP_MAC_init failed")) -+ } -+ var hkey []byte -+ if vMinor == 0 && vPatch <= 2 { -+ // EVP_MAC_init only resets the ctx internal state if a key is passed -+ // when using OpenSSL 3.0.0, 3.0.1, and 3.0.2. Save a copy of the key -+ // in the context so Reset can use it later. New OpenSSL versions -+ // do not have this issue so it isn't necessary to save the key. -+ // See https://github.com/openssl/openssl/issues/17811. -+ hkey = make([]byte, len(key)) -+ copy(hkey, key) -+ } -+ hmac := &opensslHMAC{ -+ size: h.Size(), -+ blockSize: h.BlockSize(), -+ ctx3: hmacCtx3{ctx, hkey}, ++func GenerateKeyECDSA(curve string) (X, Y, D BigInt, err error) { ++ // Generate the private key. ++ pkey, err := generateEVPPKey(C.GO_EVP_PKEY_EC, 0, curve) ++ if err != nil { ++ return nil, nil, nil, err + } -+ runtime.SetFinalizer(hmac, (*opensslHMAC).finalize) -+ return hmac -+} ++ defer C.go_openssl_EVP_PKEY_free(pkey) + -+func (h *opensslHMAC) Reset() { ++ var bx, by, bd C.GO_BIGNUM_PTR ++ defer func() { ++ C.go_openssl_BN_free(bx) ++ C.go_openssl_BN_free(by) ++ }() + switch vMajor { + case 1: -+ if C.go_openssl_HMAC_Init_ex(h.ctx1.ctx, nil, 0, nil, nil) == 0 { -+ panic(newOpenSSLError("HMAC_Init_ex failed")) ++ // Retrieve the internal EC_KEY, which holds the X, Y, and D coordinates. ++ key := getECKey(pkey) ++ group := C.go_openssl_EC_KEY_get0_group(key) ++ pt := C.go_openssl_EC_KEY_get0_public_key(key) ++ // Allocate two big numbers to store the X and Y coordinates. ++ bx, by = C.go_openssl_BN_new(), C.go_openssl_BN_new() ++ if bx == nil || by == nil { ++ return nil, nil, nil, newOpenSSLError("BN_new failed") ++ } ++ // Get X and Y. ++ if C.go_openssl_EC_POINT_get_affine_coordinates_GFp(group, pt, bx, by, nil) == 0 { ++ return nil, nil, nil, newOpenSSLError("EC_POINT_get_affine_coordinates_GFp failed") + } ++ // Get Z. We don't need to free it, get0 does not increase the reference count. ++ bd = C.go_openssl_EC_KEY_get0_private_key(key) + case 3: -+ if C.go_openssl_EVP_MAC_init(h.ctx3.ctx, base(h.ctx3.key), C.size_t(len(h.ctx3.key)), nil) == 0 { -+ panic(newOpenSSLError("EVP_MAC_init failed")) ++ if C.go_openssl_EVP_PKEY_get_bn_param(pkey, paramECPubX, &bx) != 1 || ++ C.go_openssl_EVP_PKEY_get_bn_param(pkey, paramECPubY, &by) != 1 || ++ C.go_openssl_EVP_PKEY_get_bn_param(pkey, paramPrivKey, &bd) != 1 { ++ return nil, nil, nil, newOpenSSLError("EVP_PKEY_get_bn_param") + } ++ defer C.go_openssl_BN_clear_free(bd) + default: + panic(errUnsupportedVersion()) + } + -+ runtime.KeepAlive(h) // Next line will keep h alive too; just making doubly sure. -+ h.sum = nil ++ // Get D. ++ return bnToBig(bx), bnToBig(by), bnToBig(bd), nil +} + -+func (h *opensslHMAC) finalize() { -+ switch vMajor { -+ case 1: -+ hmacCtxFree(h.ctx1.ctx) -+ case 3: -+ C.go_openssl_EVP_MAC_CTX_free(h.ctx3.ctx) -+ default: -+ panic(errUnsupportedVersion()) -+ } ++func SignMarshalECDSA(priv *PrivateKeyECDSA, hash []byte) ([]byte, error) { ++ return evpSign(priv.withKey, 0, 0, 0, hash) +} + -+func (h *opensslHMAC) Write(p []byte) (int, error) { -+ if len(p) > 0 { -+ switch vMajor { -+ case 1: -+ C.go_openssl_HMAC_Update(h.ctx1.ctx, base(p), C.size_t(len(p))) -+ case 3: -+ C.go_openssl_EVP_MAC_update(h.ctx3.ctx, base(p), C.size_t(len(p))) -+ default: -+ panic(errUnsupportedVersion()) -+ } -+ } -+ runtime.KeepAlive(h) -+ return len(p), nil ++func HashSignECDSA(priv *PrivateKeyECDSA, h crypto.Hash, msg []byte) ([]byte, error) { ++ return evpHashSign(priv.withKey, h, msg) +} + -+func (h *opensslHMAC) Size() int { -+ return h.size ++func VerifyECDSA(pub *PublicKeyECDSA, hash []byte, sig []byte) bool { ++ return evpVerify(pub.withKey, 0, 0, 0, sig, hash) == nil +} + -+func (h *opensslHMAC) BlockSize() int { -+ return h.blockSize ++func HashVerifyECDSA(pub *PublicKeyECDSA, h crypto.Hash, msg, sig []byte) bool { ++ return evpHashVerify(pub.withKey, h, msg, sig) == nil +} + -+func (h *opensslHMAC) Sum(in []byte) []byte { -+ if h.sum == nil { -+ size := h.Size() -+ h.sum = make([]byte, size) ++func newECDSAKey(curve string, X, Y, D BigInt) (C.GO_EVP_PKEY_PTR, error) { ++ nid, err := curveNID(curve) ++ if err != nil { ++ return nil, err ++ } ++ var bx, by, bd C.GO_BIGNUM_PTR ++ defer func() { ++ C.go_openssl_BN_free(bx) ++ C.go_openssl_BN_free(by) ++ C.go_openssl_BN_clear_free(bd) ++ }() ++ bx = bigToBN(X) ++ by = bigToBN(Y) ++ bd = bigToBN(D) ++ if bx == nil || by == nil || (D != nil && bd == nil) { ++ return nil, newOpenSSLError("BN_lebin2bn failed") + } -+ // Make copy of context because Go hash.Hash mandates -+ // that Sum has no effect on the underlying stream. -+ // In particular it is OK to Sum, then Write more, then Sum again, -+ // and the second Sum acts as if the first didn't happen. + switch vMajor { + case 1: -+ ctx2 := hmacCtxNew() -+ if ctx2 == nil { -+ panic("openssl: HMAC_CTX_new failed") -+ } -+ defer hmacCtxFree(ctx2) -+ if C.go_openssl_HMAC_CTX_copy(ctx2, h.ctx1.ctx) == 0 { -+ panic("openssl: HMAC_CTX_copy failed") -+ } -+ C.go_openssl_HMAC_Final(ctx2, base(h.sum), nil) ++ return newECDSAKey1(nid, bx, by, bd) + case 3: -+ ctx2 := C.go_openssl_EVP_MAC_CTX_dup(h.ctx3.ctx) -+ if ctx2 == nil { -+ panic("openssl: EVP_MAC_CTX_dup failed") -+ } -+ defer C.go_openssl_EVP_MAC_CTX_free(ctx2) -+ C.go_openssl_EVP_MAC_final(ctx2, base(h.sum), nil, C.size_t(len(h.sum))) ++ return newECDSAKey3(nid, bx, by, bd) + default: + panic(errUnsupportedVersion()) + } -+ return append(in, h.sum...) +} + -+func hmacCtxNew() C.GO_HMAC_CTX_PTR { -+ if vMajor == 1 && vMinor == 0 { -+ // 0x120 is the sizeof value when building against OpenSSL 1.0.2 on Ubuntu 16.04. -+ ctx := (C.GO_HMAC_CTX_PTR)(C.malloc(0x120)) -+ if ctx != nil { -+ C.go_openssl_HMAC_CTX_init(ctx) ++func newECDSAKey1(nid C.int, bx, by, bd C.GO_BIGNUM_PTR) (pkey C.GO_EVP_PKEY_PTR, err error) { ++ if vMajor != 1 { ++ panic("incorrect vMajor version") ++ } ++ key := C.go_openssl_EC_KEY_new_by_curve_name(nid) ++ if key == nil { ++ return nil, newOpenSSLError("EC_KEY_new_by_curve_name failed") ++ } ++ defer func() { ++ if pkey == nil { ++ defer C.go_openssl_EC_KEY_free(key) + } -+ return ctx ++ }() ++ if C.go_openssl_EC_KEY_set_public_key_affine_coordinates(key, bx, by) != 1 { ++ return nil, newOpenSSLError("EC_KEY_set_public_key_affine_coordinates failed") + } -+ return C.go_openssl_HMAC_CTX_new() ++ if bd != nil && C.go_openssl_EC_KEY_set_private_key(key, bd) != 1 { ++ return nil, newOpenSSLError("EC_KEY_set_private_key failed") ++ } ++ return newEVPPKEY(key) +} + -+func hmacCtxFree(ctx C.GO_HMAC_CTX_PTR) { -+ if vMajor == 1 && vMinor == 0 { -+ C.go_openssl_HMAC_CTX_cleanup(ctx) -+ C.free(unsafe.Pointer(ctx)) -+ return ++func newECDSAKey3(nid C.int, bx, by, bd C.GO_BIGNUM_PTR) (C.GO_EVP_PKEY_PTR, error) { ++ if vMajor != 3 { ++ panic("incorrect vMajor version") ++ } ++ // Create the encoded public key public key from bx and by. ++ pubBytes, err := generateAndEncodeEcPublicKey(nid, func(group C.GO_EC_GROUP_PTR) (C.GO_EC_POINT_PTR, error) { ++ pt := C.go_openssl_EC_POINT_new(group) ++ if pt == nil { ++ return nil, newOpenSSLError("EC_POINT_new") ++ } ++ if C.go_openssl_EC_POINT_set_affine_coordinates(group, pt, bx, by, nil) != 1 { ++ C.go_openssl_EC_POINT_free(pt) ++ return nil, newOpenSSLError("EC_POINT_set_affine_coordinates") ++ } ++ return pt, nil ++ }) ++ if err != nil { ++ return nil, err ++ } ++ // Construct the parameters. ++ bld := C.go_openssl_OSSL_PARAM_BLD_new() ++ if bld == nil { ++ return nil, newOpenSSLError("OSSL_PARAM_BLD_new") ++ } ++ defer C.go_openssl_OSSL_PARAM_BLD_free(bld) ++ C.go_openssl_OSSL_PARAM_BLD_push_utf8_string(bld, paramGroup, C.go_openssl_OBJ_nid2sn(nid), 0) ++ cbytes := C.CBytes(pubBytes) ++ defer C.free(cbytes) ++ C.go_openssl_OSSL_PARAM_BLD_push_octet_string(bld, paramPubKey, cbytes, C.size_t(len(pubBytes))) ++ var selection C.int ++ if bd != nil { ++ if C.go_openssl_OSSL_PARAM_BLD_push_BN(bld, paramPrivKey, bd) != 1 { ++ return nil, newOpenSSLError("OSSL_PARAM_BLD_push_BN") ++ } ++ selection = C.GO_EVP_PKEY_KEYPAIR ++ } else { ++ selection = C.GO_EVP_PKEY_PUBLIC_KEY ++ } ++ params := C.go_openssl_OSSL_PARAM_BLD_to_param(bld) ++ if params == nil { ++ return nil, newOpenSSLError("OSSL_PARAM_BLD_to_param") + } -+ C.go_openssl_HMAC_CTX_free(ctx) ++ defer C.go_openssl_OSSL_PARAM_free(params) ++ return newEvpFromParams(C.GO_EVP_PKEY_EC, selection, params) +} -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/init.go b/src/vendor/github.com/golang-fips/openssl/v2/init.go +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/evp.go b/src/vendor/github.com/golang-fips/openssl/v2/evp.go new file mode 100644 -index 0000000000..21126ff550 +index 0000000000..da71d9b389 --- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/init.go -@@ -0,0 +1,63 @@ ++++ b/src/vendor/github.com/golang-fips/openssl/v2/evp.go +@@ -0,0 +1,455 @@ +//go:build !cmd_go_bootstrap + +package openssl @@ -32416,2615 +5146,2019 @@ index 0000000000..21126ff550 +// #include "goopenssl.h" +import "C" +import ( ++ "crypto" + "errors" ++ "hash" ++ "strconv" ++ "sync" ++ "unsafe" +) + -+// opensslInit loads and initialize OpenSSL. -+// If successful, it returns the major and minor OpenSSL version -+// as reported by the OpenSSL API. -+// -+// See Init() for details about file. -+func opensslInit(file string) (major, minor, patch int, err error) { -+ // Load the OpenSSL shared library using dlopen. -+ handle, err := dlopen(file) -+ if err != nil { -+ return 0, 0, 0, err ++// cacheMD is a cache of crypto.Hash to GO_EVP_MD_PTR. ++var cacheMD sync.Map ++ ++// hashToMD converts a hash.Hash implementation from this package to a GO_EVP_MD_PTR. ++func hashToMD(h hash.Hash) C.GO_EVP_MD_PTR { ++ var ch crypto.Hash ++ switch h.(type) { ++ case *sha1Hash: ++ ch = crypto.SHA1 ++ case *sha224Hash: ++ ch = crypto.SHA224 ++ case *sha256Hash: ++ ch = crypto.SHA256 ++ case *sha384Hash: ++ ch = crypto.SHA384 ++ case *sha512Hash: ++ ch = crypto.SHA512 ++ case *sha3_224Hash: ++ ch = crypto.SHA3_224 ++ case *sha3_256Hash: ++ ch = crypto.SHA3_256 ++ case *sha3_384Hash: ++ ch = crypto.SHA3_384 ++ case *sha3_512Hash: ++ ch = crypto.SHA3_512 ++ } ++ if ch != 0 { ++ return cryptoHashToMD(ch) + } ++ return nil ++} + -+ // Retrieve the loaded OpenSSL version and check if it is supported. -+ // Notice that major and minor could not match with the version parameter -+ // in case the name of the shared library file differs from the OpenSSL -+ // version it contains. -+ major = int(C.go_openssl_version_major(handle)) -+ minor = int(C.go_openssl_version_minor(handle)) -+ patch = int(C.go_openssl_version_patch(handle)) -+ if major == -1 || minor == -1 || patch == -1 { -+ return 0, 0, 0, errors.New("openssl: can't retrieve OpenSSL version") ++// cryptoHashToMD converts a crypto.Hash to a GO_EVP_MD_PTR. ++func cryptoHashToMD(ch crypto.Hash) (md C.GO_EVP_MD_PTR) { ++ if v, ok := cacheMD.Load(ch); ok { ++ return v.(C.GO_EVP_MD_PTR) + } -+ var supported bool -+ if major == 1 { -+ supported = minor == 0 || minor == 1 -+ } else if major == 3 { -+ // OpenSSL guarantees API and ABI compatibility within the same major version since OpenSSL 3. -+ supported = true ++ defer func() { ++ if md != nil && vMajor == 3 { ++ // On OpenSSL 3, directly operating on a EVP_MD object ++ // not created by EVP_MD_fetch has negative performance ++ // implications, as digest operations will have ++ // to fetch it on every call. Better to just fetch it once here. ++ md = C.go_openssl_EVP_MD_fetch(nil, C.go_openssl_EVP_MD_get0_name(md), nil) ++ } ++ cacheMD.Store(ch, md) ++ }() ++ // SupportsHash returns false for MD5 and MD5SHA1 because we don't ++ // provide a hash.Hash implementation for them. Yet, they can ++ // still be used when signing/verifying with an RSA key. ++ switch ch { ++ case crypto.MD5: ++ return C.go_openssl_EVP_md5() ++ case crypto.MD5SHA1: ++ if vMajor == 1 && vMinor == 0 { ++ return C.go_openssl_EVP_md5_sha1_backport() ++ } else { ++ return C.go_openssl_EVP_md5_sha1() ++ } + } -+ if !supported { -+ return 0, 0, 0, errUnsupportedVersion() ++ if !SupportsHash(ch) { ++ return nil ++ } ++ switch ch { ++ case crypto.SHA1: ++ return C.go_openssl_EVP_sha1() ++ case crypto.SHA224: ++ return C.go_openssl_EVP_sha224() ++ case crypto.SHA256: ++ return C.go_openssl_EVP_sha256() ++ case crypto.SHA384: ++ return C.go_openssl_EVP_sha384() ++ case crypto.SHA512: ++ return C.go_openssl_EVP_sha512() ++ case crypto.SHA3_224: ++ return C.go_openssl_EVP_sha3_224() ++ case crypto.SHA3_256: ++ return C.go_openssl_EVP_sha3_256() ++ case crypto.SHA3_384: ++ return C.go_openssl_EVP_sha3_384() ++ case crypto.SHA3_512: ++ return C.go_openssl_EVP_sha3_512() + } ++ return nil ++} + -+ // Load the OpenSSL functions. -+ // See shims.go for the complete list of supported functions. -+ C.go_openssl_load_functions(handle, C.int(major), C.int(minor), C.int(patch)) ++func generateEVPPKey(id C.int, bits int, curve string) (C.GO_EVP_PKEY_PTR, error) { ++ if (bits == 0 && curve == "") || (bits != 0 && curve != "") { ++ return nil, fail("incorrect generateEVPPKey parameters") ++ } ++ ctx := C.go_openssl_EVP_PKEY_CTX_new_id(id, nil) ++ if ctx == nil { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_new_id failed") ++ } ++ defer C.go_openssl_EVP_PKEY_CTX_free(ctx) ++ if C.go_openssl_EVP_PKEY_keygen_init(ctx) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_keygen_init failed") ++ } ++ if bits != 0 { ++ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, id, -1, C.GO_EVP_PKEY_CTRL_RSA_KEYGEN_BITS, C.int(bits), nil) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") ++ } ++ } ++ if curve != "" { ++ nid, err := curveNID(curve) ++ if err != nil { ++ return nil, err ++ } ++ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, id, -1, C.GO_EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, nil) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") ++ } ++ } ++ var pkey C.GO_EVP_PKEY_PTR ++ if C.go_openssl_EVP_PKEY_keygen(ctx, &pkey) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_keygen failed") ++ } ++ return pkey, nil ++} ++ ++type withKeyFunc func(func(C.GO_EVP_PKEY_PTR) C.int) C.int ++type initFunc func(C.GO_EVP_PKEY_CTX_PTR) error ++type cryptFunc func(C.GO_EVP_PKEY_CTX_PTR, *C.uchar, *C.size_t, *C.uchar, C.size_t) error ++type verifyFunc func(C.GO_EVP_PKEY_CTX_PTR, *C.uchar, C.size_t, *C.uchar, C.size_t) error ++ ++func setupEVP(withKey withKeyFunc, padding C.int, ++ h, mgfHash hash.Hash, label []byte, saltLen C.int, ch crypto.Hash, ++ init initFunc) (ctx C.GO_EVP_PKEY_CTX_PTR, err error) { ++ defer func() { ++ if err != nil { ++ if ctx != nil { ++ C.go_openssl_EVP_PKEY_CTX_free(ctx) ++ ctx = nil ++ } ++ } ++ }() ++ ++ withKey(func(pkey C.GO_EVP_PKEY_PTR) C.int { ++ ctx = C.go_openssl_EVP_PKEY_CTX_new(pkey, nil) ++ return 1 ++ }) ++ if ctx == nil { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_new failed") ++ } ++ if err := init(ctx); err != nil { ++ return nil, err ++ } ++ if padding == 0 { ++ return ctx, nil ++ } ++ // Each padding type has its own requirements in terms of when to apply the padding, ++ // so it can't be just set at this point. ++ setPadding := func() error { ++ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, C.GO_EVP_PKEY_RSA, -1, C.GO_EVP_PKEY_CTRL_RSA_PADDING, padding, nil) != 1 { ++ return newOpenSSLError("EVP_PKEY_CTX_ctrl failed") ++ } ++ return nil ++ } ++ switch padding { ++ case C.GO_RSA_PKCS1_OAEP_PADDING: ++ md := hashToMD(h) ++ if md == nil { ++ return nil, errors.New("crypto/rsa: unsupported hash function") ++ } ++ var mgfMD C.GO_EVP_MD_PTR ++ if mgfHash != nil { ++ // mgfHash is optional, but if it is set it must match a supported hash function. ++ mgfMD = hashToMD(mgfHash) ++ if mgfMD == nil { ++ return nil, errors.New("crypto/rsa: unsupported hash function") ++ } ++ } ++ // setPadding must happen before setting EVP_PKEY_CTRL_RSA_OAEP_MD. ++ if err := setPadding(); err != nil { ++ return nil, err ++ } ++ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, C.GO_EVP_PKEY_RSA, -1, C.GO_EVP_PKEY_CTRL_RSA_OAEP_MD, 0, unsafe.Pointer(md)) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") ++ } ++ if mgfHash != nil { ++ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, C.GO_EVP_PKEY_RSA, -1, C.GO_EVP_PKEY_CTRL_RSA_MGF1_MD, 0, unsafe.Pointer(mgfMD)) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") ++ } ++ } ++ // ctx takes ownership of label, so malloc a copy for OpenSSL to free. ++ // OpenSSL does not take ownership of the label if the length is zero, ++ // so better avoid the allocation. ++ var clabel *C.uchar ++ if len(label) > 0 { ++ clabel = (*C.uchar)(cryptoMalloc(len(label))) ++ copy((*[1 << 30]byte)(unsafe.Pointer(clabel))[:len(label)], label) ++ } ++ var ret C.int ++ if vMajor == 3 { ++ ret = C.go_openssl_EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, unsafe.Pointer(clabel), C.int(len(label))) ++ } else { ++ ret = C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, C.GO_EVP_PKEY_RSA, -1, C.GO_EVP_PKEY_CTRL_RSA_OAEP_LABEL, C.int(len(label)), unsafe.Pointer(clabel)) ++ } ++ if ret != 1 { ++ cryptoFree(unsafe.Pointer(clabel)) ++ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") ++ } ++ case C.GO_RSA_PKCS1_PSS_PADDING: ++ md := cryptoHashToMD(ch) ++ if md == nil { ++ return nil, errors.New("crypto/rsa: unsupported hash function") ++ } ++ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, C.GO_EVP_PKEY_RSA, -1, C.GO_EVP_PKEY_CTRL_MD, 0, unsafe.Pointer(md)) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") ++ } ++ // setPadding must happen after setting EVP_PKEY_CTRL_MD. ++ if err := setPadding(); err != nil { ++ return nil, err ++ } ++ if saltLen != 0 { ++ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, C.GO_EVP_PKEY_RSA, -1, C.GO_EVP_PKEY_CTRL_RSA_PSS_SALTLEN, saltLen, nil) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") ++ } ++ } + -+ // Initialize OpenSSL. -+ C.go_openssl_OPENSSL_init() -+ if major == 1 && minor == 0 { -+ if C.go_openssl_thread_setup() != 1 { -+ return 0, 0, 0, fail("openssl: thread setup") ++ case C.GO_RSA_PKCS1_PADDING: ++ if ch != 0 { ++ // We support unhashed messages. ++ md := cryptoHashToMD(ch) ++ if md == nil { ++ return nil, errors.New("crypto/rsa: unsupported hash function") ++ } ++ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, -1, -1, C.GO_EVP_PKEY_CTRL_MD, 0, unsafe.Pointer(md)) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_ctrl failed") ++ } ++ if err := setPadding(); err != nil { ++ return nil, err ++ } + } -+ C.go_openssl_OPENSSL_add_all_algorithms_conf() -+ C.go_openssl_ERR_load_crypto_strings() -+ } else { -+ flags := C.uint64_t(C.GO_OPENSSL_INIT_ADD_ALL_CIPHERS | C.GO_OPENSSL_INIT_ADD_ALL_DIGESTS | C.GO_OPENSSL_INIT_LOAD_CONFIG | C.GO_OPENSSL_INIT_LOAD_CRYPTO_STRINGS) -+ if C.go_openssl_OPENSSL_init_crypto(flags, nil) != 1 { -+ return 0, 0, 0, fail("openssl: init crypto") ++ default: ++ if err := setPadding(); err != nil { ++ return nil, err + } + } -+ return major, minor, patch, nil ++ return ctx, nil +} -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/init_unix.go b/src/vendor/github.com/golang-fips/openssl/v2/init_unix.go -new file mode 100644 -index 0000000000..dbf5ac448f ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/init_unix.go -@@ -0,0 +1,31 @@ -+//go:build unix && !cmd_go_bootstrap + -+package openssl -+ -+// #cgo LDFLAGS: -ldl -+// #include -+// #include -+import "C" -+import ( -+ "errors" -+ "unsafe" -+) ++func cryptEVP(withKey withKeyFunc, padding C.int, ++ h, mgfHash hash.Hash, label []byte, saltLen C.int, ch crypto.Hash, ++ init initFunc, crypt cryptFunc, in []byte) ([]byte, error) { + -+func dlopen(file string) (handle unsafe.Pointer, err error) { -+ cv := C.CString(file) -+ defer C.free(unsafe.Pointer(cv)) -+ handle = C.dlopen(cv, C.RTLD_LAZY|C.RTLD_LOCAL) -+ if handle == nil { -+ errstr := C.GoString(C.dlerror()) -+ return nil, errors.New("openssl: can't load " + file + ": " + errstr) ++ ctx, err := setupEVP(withKey, padding, h, mgfHash, label, saltLen, ch, init) ++ if err != nil { ++ return nil, err + } -+ return handle, nil -+} -+ -+func dlclose(handle unsafe.Pointer) error { -+ if C.dlclose(handle) != 0 { -+ errstr := C.GoString(C.dlerror()) -+ return errors.New("openssl: can't close libcrypto: " + errstr) ++ defer C.go_openssl_EVP_PKEY_CTX_free(ctx) ++ pkeySize := withKey(func(pkey C.GO_EVP_PKEY_PTR) C.int { ++ return C.go_openssl_EVP_PKEY_get_size(pkey) ++ }) ++ outLen := C.size_t(pkeySize) ++ out := make([]byte, pkeySize) ++ if err := crypt(ctx, base(out), &outLen, base(in), C.size_t(len(in))); err != nil { ++ return nil, err + } -+ return nil ++ // The size returned by EVP_PKEY_get_size() is only preliminary and not exact, ++ // so the final contents of the out buffer may be smaller. ++ return out[:outLen], nil +} -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/init_windows.go b/src/vendor/github.com/golang-fips/openssl/v2/init_windows.go -new file mode 100644 -index 0000000000..3778e21227 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/init_windows.go -@@ -0,0 +1,36 @@ -+//go:build !cmd_go_bootstrap -+ -+package openssl + -+import ( -+ "syscall" -+ "unsafe" -+) ++func verifyEVP(withKey withKeyFunc, padding C.int, ++ h hash.Hash, label []byte, saltLen C.int, ch crypto.Hash, ++ init initFunc, verify verifyFunc, ++ sig, in []byte) error { + -+type dlopenError struct { -+ file string -+ err error ++ ctx, err := setupEVP(withKey, padding, h, nil, label, saltLen, ch, init) ++ if err != nil { ++ return err ++ } ++ defer C.go_openssl_EVP_PKEY_CTX_free(ctx) ++ return verify(ctx, base(sig), C.size_t(len(sig)), base(in), C.size_t(len(in))) +} + -+func (e *dlopenError) Error() string { -+ return "openssl: can't load " + e.file + ": " + e.err.Error() ++func evpEncrypt(withKey withKeyFunc, padding C.int, h, mgfHash hash.Hash, label, msg []byte) ([]byte, error) { ++ encryptInit := func(ctx C.GO_EVP_PKEY_CTX_PTR) error { ++ if ret := C.go_openssl_EVP_PKEY_encrypt_init(ctx); ret != 1 { ++ return newOpenSSLError("EVP_PKEY_encrypt_init failed") ++ } ++ return nil ++ } ++ encrypt := func(ctx C.GO_EVP_PKEY_CTX_PTR, out *C.uchar, outLen *C.size_t, in *C.uchar, inLen C.size_t) error { ++ if ret := C.go_openssl_EVP_PKEY_encrypt(ctx, out, outLen, in, inLen); ret != 1 { ++ return newOpenSSLError("EVP_PKEY_encrypt failed") ++ } ++ return nil ++ } ++ return cryptEVP(withKey, padding, h, mgfHash, label, 0, 0, encryptInit, encrypt, msg) +} + -+func (e *dlopenError) Unwrap() error { -+ return e.err ++func evpDecrypt(withKey withKeyFunc, padding C.int, h, mgfHash hash.Hash, label, msg []byte) ([]byte, error) { ++ decryptInit := func(ctx C.GO_EVP_PKEY_CTX_PTR) error { ++ if ret := C.go_openssl_EVP_PKEY_decrypt_init(ctx); ret != 1 { ++ return newOpenSSLError("EVP_PKEY_decrypt_init failed") ++ } ++ return nil ++ } ++ decrypt := func(ctx C.GO_EVP_PKEY_CTX_PTR, out *C.uchar, outLen *C.size_t, in *C.uchar, inLen C.size_t) error { ++ if ret := C.go_openssl_EVP_PKEY_decrypt(ctx, out, outLen, in, inLen); ret != 1 { ++ return newOpenSSLError("EVP_PKEY_decrypt failed") ++ } ++ return nil ++ } ++ return cryptEVP(withKey, padding, h, mgfHash, label, 0, 0, decryptInit, decrypt, msg) +} + -+func dlopen(file string) (handle unsafe.Pointer, err error) { -+ // As Windows generally does not ship with a system OpenSSL library, let -+ // alone a FIPS 140 certified one, use the default library search order so -+ // that we preferentially load the DLL bundled with the application. -+ h, err := syscall.LoadLibrary(file) -+ if err != nil { -+ return nil, &dlopenError{file: file, err: err} ++func evpSign(withKey withKeyFunc, padding C.int, saltLen C.int, h crypto.Hash, hashed []byte) ([]byte, error) { ++ signtInit := func(ctx C.GO_EVP_PKEY_CTX_PTR) error { ++ if ret := C.go_openssl_EVP_PKEY_sign_init(ctx); ret != 1 { ++ return newOpenSSLError("EVP_PKEY_sign_init failed") ++ } ++ return nil + } -+ return unsafe.Pointer(h), nil ++ sign := func(ctx C.GO_EVP_PKEY_CTX_PTR, out *C.uchar, outLen *C.size_t, in *C.uchar, inLen C.size_t) error { ++ if ret := C.go_openssl_EVP_PKEY_sign(ctx, out, outLen, in, inLen); ret != 1 { ++ return newOpenSSLError("EVP_PKEY_sign failed") ++ } ++ return nil ++ } ++ return cryptEVP(withKey, padding, nil, nil, nil, saltLen, h, signtInit, sign, hashed) +} + -+func dlclose(handle unsafe.Pointer) error { -+ return syscall.FreeLibrary(syscall.Handle(handle)) ++func evpVerify(withKey withKeyFunc, padding C.int, saltLen C.int, h crypto.Hash, sig, hashed []byte) error { ++ verifyInit := func(ctx C.GO_EVP_PKEY_CTX_PTR) error { ++ if ret := C.go_openssl_EVP_PKEY_verify_init(ctx); ret != 1 { ++ return newOpenSSLError("EVP_PKEY_verify_init failed") ++ } ++ return nil ++ } ++ verify := func(ctx C.GO_EVP_PKEY_CTX_PTR, out *C.uchar, outLen C.size_t, in *C.uchar, inLen C.size_t) error { ++ if ret := C.go_openssl_EVP_PKEY_verify(ctx, out, outLen, in, inLen); ret != 1 { ++ return newOpenSSLError("EVP_PKEY_verify failed") ++ } ++ return nil ++ } ++ return verifyEVP(withKey, padding, nil, nil, saltLen, h, verifyInit, verify, sig, hashed) +} -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/openssl.go b/src/vendor/github.com/golang-fips/openssl/v2/openssl.go -new file mode 100644 -index 0000000000..5c9324d858 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/openssl.go -@@ -0,0 +1,408 @@ -+//go:build !cmd_go_bootstrap -+ -+// Package openssl provides access to OpenSSL cryptographic functions. -+package openssl -+ -+// #include "goopenssl.h" -<<<<<<< HEAD -+// #include -+// #cgo LDFLAGS: -ldl ->>>>>>> 0023bf4c7a (rebase) -======= ->>>>>>> 0b8240ca10 (support opensslv2, update strict fips checks) -+import "C" -+import ( -+ "encoding/binary" -+ "errors" -<<<<<<< HEAD -+ "fmt" -+ "math/bits" -+ "os" -+ "runtime" -+ "unsafe" -+) -+ -+const ( -+ fipsOn = C.int(1) -+ fipsOff = C.int(0) -+) -+ -+const GoStrictFipsEnv = "GOLANG_STRICT_FIPS" + -+const ( -+ OPENSSL_VERSION_1_1_0 = uint64(C.ulong(0x10100000)) -+ OPENSSL_VERSION_1_1_1 = uint64(C.ulong(0x10101000)) -+ 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 crypto API will allow existing go crypto APIs to be used even -+// if they aren't FIPS compliant. However, all the underlying crypto operations -+// will still be done by OpenSSL. -+var strictFIPS = false -+ -+var nativeEndian binary.ByteOrder -+ -+func init() { -+ runtime.LockOSThread() -+ defer runtime.UnlockOSThread() -+ -+ buf := [2]byte{} -+ *(*uint16)(unsafe.Pointer(&buf[0])) = uint16(0xABCD) ++func evpHashSign(withKey withKeyFunc, h crypto.Hash, msg []byte) ([]byte, error) { ++ md := cryptoHashToMD(h) ++ if md == nil { ++ return nil, errors.New("unsupported hash function: " + strconv.Itoa(int(h))) ++ } ++ var out []byte ++ var outLen C.size_t ++ ctx := C.go_openssl_EVP_MD_CTX_new() ++ if ctx == nil { ++ return nil, newOpenSSLError("EVP_MD_CTX_new failed") ++ } ++ defer C.go_openssl_EVP_MD_CTX_free(ctx) ++ if withKey(func(key C.GO_EVP_PKEY_PTR) C.int { ++ return C.go_openssl_EVP_DigestSignInit(ctx, nil, md, nil, key) ++ }) != 1 { ++ return nil, newOpenSSLError("EVP_DigestSignInit failed") ++ } ++ if C.go_openssl_EVP_DigestUpdate(ctx, unsafe.Pointer(base(msg)), C.size_t(len(msg))) != 1 { ++ return nil, newOpenSSLError("EVP_DigestUpdate failed") ++ } ++ // Obtain the signature length ++ if C.go_openssl_EVP_DigestSignFinal(ctx, nil, &outLen) != 1 { ++ return nil, newOpenSSLError("EVP_DigestSignFinal failed") ++ } ++ out = make([]byte, outLen) ++ // Obtain the signature ++ if C.go_openssl_EVP_DigestSignFinal(ctx, base(out), &outLen) != 1 { ++ return nil, newOpenSSLError("EVP_DigestSignFinal failed") ++ } ++ return out[:outLen], nil ++} + -+ switch buf { -+ case [2]byte{0xCD, 0xAB}: -+ nativeEndian = binary.LittleEndian -+ case [2]byte{0xAB, 0xCD}: -+ nativeEndian = binary.BigEndian -+ default: -+ panic("Could not determine native endianness.") ++func evpHashVerify(withKey withKeyFunc, h crypto.Hash, msg, sig []byte) error { ++ md := cryptoHashToMD(h) ++ if md == nil { ++ return errors.New("unsupported hash function: " + strconv.Itoa(int(h))) ++ } ++ ctx := C.go_openssl_EVP_MD_CTX_new() ++ if ctx == nil { ++ return newOpenSSLError("EVP_MD_CTX_new failed") + } -+ -+ // Check if we can `dlopen` OpenSSL -+ if C._goboringcrypto_DLOPEN_OPENSSL() == C.NULL { -+ return ++ defer C.go_openssl_EVP_MD_CTX_free(ctx) ++ if withKey(func(key C.GO_EVP_PKEY_PTR) C.int { ++ return C.go_openssl_EVP_DigestVerifyInit(ctx, nil, md, nil, key) ++ }) != 1 { ++ return newOpenSSLError("EVP_DigestVerifyInit failed") + } -+ -+ // 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() ++ if C.go_openssl_EVP_DigestUpdate(ctx, unsafe.Pointer(base(msg)), C.size_t(len(msg))) != 1 { ++ return newOpenSSLError("EVP_DigestUpdate failed") + } ++ if C.go_openssl_EVP_DigestVerifyFinal(ctx, base(sig), C.size_t(len(sig))) != 1 { ++ return newOpenSSLError("EVP_DigestVerifyFinal failed") ++ } ++ return nil +} + -+func openSSLVersion() uint64 { -+ return uint64(C._goboringcrypto_internal_OPENSSL_VERSION_NUMBER()) -+} -+ -+func enableBoringFIPSMode() { -+ enabled = true -+ -+ if os.Getenv(GoStrictFipsEnv) == "1" { -+ strictFIPS = true ++func newEVPPKEY(key C.GO_EC_KEY_PTR) (C.GO_EVP_PKEY_PTR, error) { ++ pkey := C.go_openssl_EVP_PKEY_new() ++ if pkey == nil { ++ return nil, newOpenSSLError("EVP_PKEY_new failed") + } -+ -+ if C._goboringcrypto_OPENSSL_thread_setup() != 1 { -+ panic("boringcrypto: OpenSSL thread setup failed") ++ if C.go_openssl_EVP_PKEY_assign(pkey, C.GO_EVP_PKEY_EC, unsafe.Pointer(key)) != 1 { ++ C.go_openssl_EVP_PKEY_free(pkey) ++ return nil, newOpenSSLError("EVP_PKEY_assign failed") + } ++ return pkey, nil +} + -+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") ++// getECKey returns the EC_KEY from pkey. ++// If pkey does not contain an EC_KEY it panics. ++// The returned key should not be freed. ++func getECKey(pkey C.GO_EVP_PKEY_PTR) (key C.GO_EC_KEY_PTR) { ++ if vMajor == 1 && vMinor == 0 { ++ if key0 := C.go_openssl_EVP_PKEY_get0(pkey); key0 != nil { ++ key = C.GO_EC_KEY_PTR(key0) + } -+ return fipsConfigured -+ + } else { -+ return os.Getenv("GOLANG_FIPS") == "1" || fipsConfigured ++ key = C.go_openssl_EVP_PKEY_get0_EC_KEY(pkey) + } -+} -+ -+var randstub bool -+ -+func RandStubbed() bool { -+ return randstub -+} -+ -+func StubOpenSSLRand() { -+ if !randstub { -+ randstub = true -+ C._goboringcrypto_stub_openssl_rand() ++ if key == nil { ++ panic("pkey does not contain an EC_KEY") + } ++ return key +} + -+func RestoreOpenSSLRand() { -+ if randstub { -+ randstub = false -+ C._goboringcrypto_restore_openssl_rand() ++func newEvpFromParams(id C.int, selection C.int, params C.GO_OSSL_PARAM_PTR) (C.GO_EVP_PKEY_PTR, error) { ++ ctx := C.go_openssl_EVP_PKEY_CTX_new_id(id, nil) ++ if ctx == nil { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_new_id") + } -+} -+ -+func hasSuffix(s, t string) bool { -+ return len(s) > len(t) && s[len(s)-len(t):] == t -+} -+ -+func PanicIfStrictFIPS(msg string) { -+ if IsStrictFips() { -+ panic(msg) ++ defer C.go_openssl_EVP_PKEY_CTX_free(ctx) ++ if C.go_openssl_EVP_PKEY_fromdata_init(ctx) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_fromdata_init") + } ++ var pkey C.GO_EVP_PKEY_PTR ++ if C.go_openssl_EVP_PKEY_fromdata(ctx, &pkey, selection, params) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_fromdata") ++ } ++ return pkey, nil +} +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/goopenssl.c b/src/vendor/github.com/golang-fips/openssl/v2/goopenssl.c +new file mode 100644 +index 0000000000..ec4adc1539 +--- /dev/null ++++ b/src/vendor/github.com/golang-fips/openssl/v2/goopenssl.c +@@ -0,0 +1,218 @@ ++//go:build unix || windows + -+func IsStrictFips() bool { -+ return os.Getenv(GoStrictFipsEnv) == "1" || strictFIPS -+} -+ -+func NewOpenSSLError(msg string) error { -+ var e C.ulong -+ message := fmt.Sprintf("\n%v\nopenssl error(s):", msg) -+ 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])), C.size_t(len(buf))) -+ 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]))) ++#include "goopenssl.h" + -+ } -+ return errors.New(message) -+} ++#ifdef _WIN32 ++# include ++# define dlsym (void*)GetProcAddress ++#else ++# include // dlsym ++#endif ++#include // fprintf + -+// Unreachable marks code that should be unreachable -+// when FIPS mode. It panics only when -+// the system is in FIPS mode. -+func Unreachable() { -+ if Enabled() { -+ panic("openssl: invalid code execution") -+ } -+} ++// Approach taken from .Net System.Security.Cryptography.Native ++// https://github.com/dotnet/runtime/blob/f64246ce08fb7a58221b2b7c8e68f69c02522b0d/src/libraries/Native/Unix/System.Security.Cryptography.Native/opensslshim.c + -+// UnreachableExceptTests marks code that should be unreachable -+// when FIPS mode is active. It panics only when the system is in FIPS mode -+// and not executing under tests. -+func UnreachableExceptTests() { -+ name := os.Args[0] -+ if Enabled() && !ExecutingTest() { -+ println("openssl: unexpected code execution in", name) -+ panic("openssl: invalid code execution") -+ } -+} ++#define DEFINEFUNC(ret, func, args, argscall) ret (*_g_##func)args; ++#define DEFINEFUNC_LEGACY_1_1(ret, func, args, argscall) DEFINEFUNC(ret, func, args, argscall) ++#define DEFINEFUNC_LEGACY_1_0(ret, func, args, argscall) DEFINEFUNC(ret, func, args, argscall) ++#define DEFINEFUNC_LEGACY_1(ret, func, args, argscall) DEFINEFUNC(ret, func, args, argscall) ++#define DEFINEFUNC_1_1(ret, func, args, argscall) DEFINEFUNC(ret, func, args, argscall) ++#define DEFINEFUNC_1_1_1(ret, func, args, argscall) DEFINEFUNC(ret, func, args, argscall) ++#define DEFINEFUNC_3_0(ret, func, args, argscall) DEFINEFUNC(ret, func, args, argscall) ++#define DEFINEFUNC_RENAMED_1_1(ret, func, oldfunc, args, argscall) DEFINEFUNC(ret, func, args, argscall) ++#define DEFINEFUNC_RENAMED_3_0(ret, func, oldfunc, args, argscall) DEFINEFUNC(ret, func, args, argscall) + -+// ExecutingTest returns a boolean indicating if we're -+// executing under a test binary or not. -+func ExecutingTest() bool { -+ name := os.Args[0] -+ return hasSuffix(name, "_test") || hasSuffix(name, ".test") -======= -+ "math/bits" -+ "runtime" -+ "strconv" -+ "strings" -+ "sync" -+ "unsafe" -+) ++FOR_ALL_OPENSSL_FUNCTIONS + -+var ( -+ // vMajor and vMinor hold the major/minor OpenSSL version. -+ // It is only populated if Init has been called. -+ vMajor, vMinor, vPatch int -+) ++#undef DEFINEFUNC ++#undef DEFINEFUNC_LEGACY_1_1 ++#undef DEFINEFUNC_LEGACY_1_0 ++#undef DEFINEFUNC_LEGACY_1 ++#undef DEFINEFUNC_1_1 ++#undef DEFINEFUNC_1_1_1 ++#undef DEFINEFUNC_3_0 ++#undef DEFINEFUNC_RENAMED_1_1 ++#undef DEFINEFUNC_RENAMED_3_0 + -+var ( -+ initOnce sync.Once -+ initErr error -+) ++int ++go_openssl_fips_enabled(void* handle) ++{ ++ // For OpenSSL 1.x. ++ int (*FIPS_mode)(void); ++ FIPS_mode = (int (*)(void))dlsym(handle, "FIPS_mode"); ++ if (FIPS_mode != NULL) ++ return FIPS_mode(); + -+var nativeEndian binary.ByteOrder ++ // For OpenSSL 3.x. ++ int (*EVP_default_properties_is_fips_enabled)(void*); ++ int (*OSSL_PROVIDER_available)(void*, const char*); ++ EVP_default_properties_is_fips_enabled = (int (*)(void*))dlsym(handle, "EVP_default_properties_is_fips_enabled"); ++ OSSL_PROVIDER_available = (int (*)(void*, const char*))dlsym(handle, "OSSL_PROVIDER_available"); ++ if (EVP_default_properties_is_fips_enabled != NULL && OSSL_PROVIDER_available != NULL && ++ EVP_default_properties_is_fips_enabled(NULL) == 1 && OSSL_PROVIDER_available(NULL, "fips") == 1) ++ return 1; + -+// CheckVersion checks if the OpenSSL version can be loaded -+// and if the FIPS mode is enabled. -+// This function can be called before Init. -+func CheckVersion(version string) (exists, fips bool) { -+ handle, _ := dlopen(version) -+ if handle == nil { -+ return false, false -+ } -+ defer dlclose(handle) -+ fips = C.go_openssl_fips_enabled(handle) == 1 -+ return true, fips ++ return 0; +} + -+// Init loads and initializes OpenSSL from the shared library at path. -+// It must be called before any other OpenSSL call, except CheckVersion. -+// -+// Only the first call to Init is effective. -+// Subsequent calls will return the same error result as the one from the first call. -+// -+// The file is passed to dlopen() verbatim to load the OpenSSL shared library. -+// For example, `file=libcrypto.so.1.1.1k-fips` makes Init look for the shared -+// library libcrypto.so.1.1.1k-fips. -+func Init(file string) error { -+ initOnce.Do(func() { -+ buf := [2]byte{} -+ *(*uint16)(unsafe.Pointer(&buf[0])) = uint16(0xABCD) ++// Load all the functions stored in FOR_ALL_OPENSSL_FUNCTIONS ++// and assign them to their corresponding function pointer ++// defined in goopenssl.h. ++void ++go_openssl_load_functions(void* handle, int major, int minor, int patch) ++{ ++#define DEFINEFUNC_INTERNAL(name, func) \ ++ _g_##name = dlsym(handle, func); \ ++ if (_g_##name == NULL) { \ ++ fprintf(stderr, "Cannot get required symbol " #func " from libcrypto version %d.%d\n", major, minor); \ ++ abort(); \ ++ } ++#define DEFINEFUNC(ret, func, args, argscall) \ ++ DEFINEFUNC_INTERNAL(func, #func) ++#define DEFINEFUNC_LEGACY_1_1(ret, func, args, argscall) \ ++ if (major == 1 && minor == 1) \ ++ { \ ++ DEFINEFUNC_INTERNAL(func, #func) \ ++ } ++#define DEFINEFUNC_LEGACY_1_0(ret, func, args, argscall) \ ++ if (major == 1 && minor == 0) \ ++ { \ ++ DEFINEFUNC_INTERNAL(func, #func) \ ++ } ++#define DEFINEFUNC_LEGACY_1(ret, func, args, argscall) \ ++ if (major == 1) \ ++ { \ ++ DEFINEFUNC_INTERNAL(func, #func) \ ++ } ++#define DEFINEFUNC_1_1(ret, func, args, argscall) \ ++ if (major == 3 || (major == 1 && minor == 1)) \ ++ { \ ++ DEFINEFUNC_INTERNAL(func, #func) \ ++ } ++#define DEFINEFUNC_1_1_1(ret, func, args, argscall) \ ++ if (major == 3 || (major == 1 && minor == 1 && patch == 1)) \ ++ { \ ++ DEFINEFUNC_INTERNAL(func, #func) \ ++ } ++#define DEFINEFUNC_3_0(ret, func, args, argscall) \ ++ if (major == 3) \ ++ { \ ++ DEFINEFUNC_INTERNAL(func, #func) \ ++ } ++#define DEFINEFUNC_RENAMED_1_1(ret, func, oldfunc, args, argscall) \ ++ if (major == 1 && minor == 0) \ ++ { \ ++ DEFINEFUNC_INTERNAL(func, #oldfunc) \ ++ } \ ++ else \ ++ { \ ++ DEFINEFUNC_INTERNAL(func, #func) \ ++ } ++#define DEFINEFUNC_RENAMED_3_0(ret, func, oldfunc, args, argscall) \ ++ if (major == 1) \ ++ { \ ++ DEFINEFUNC_INTERNAL(func, #oldfunc) \ ++ } \ ++ else \ ++ { \ ++ DEFINEFUNC_INTERNAL(func, #func) \ ++ } + -+ switch buf { -+ case [2]byte{0xCD, 0xAB}: -+ nativeEndian = binary.LittleEndian -+ case [2]byte{0xAB, 0xCD}: -+ nativeEndian = binary.BigEndian -+ default: -+ panic("Could not determine native endianness.") -+ } -+ vMajor, vMinor, vPatch, initErr = opensslInit(file) -+ }) -+ return initErr ++FOR_ALL_OPENSSL_FUNCTIONS ++ ++#undef DEFINEFUNC ++#undef DEFINEFUNC_LEGACY_1_1 ++#undef DEFINEFUNC_LEGACY_1_0 ++#undef DEFINEFUNC_LEGACY_1 ++#undef DEFINEFUNC_1_1 ++#undef DEFINEFUNC_1_1_1 ++#undef DEFINEFUNC_3_0 ++#undef DEFINEFUNC_RENAMED_1_1 ++#undef DEFINEFUNC_RENAMED_3_0 +} + -+func errUnsupportedVersion() error { -+ return errors.New("openssl: OpenSSL version: " + strconv.Itoa(vMajor) + "." + strconv.Itoa(vMinor) + "." + strconv.Itoa(vPatch)) ->>>>>>> 0023bf4c7a (rebase) -+} ++static unsigned long ++version_num(void* handle) ++{ ++ unsigned long (*fn)(void); ++ // OPENSSL_version_num is defined in OpenSSL 1.1.0 and 1.1.1. ++ fn = (unsigned long (*)(void))dlsym(handle, "OpenSSL_version_num"); ++ if (fn != NULL) ++ return fn(); ++ ++ // SSLeay is defined in OpenSSL 1.0.2. ++ fn = (unsigned long (*)(void))dlsym(handle, "SSLeay"); ++ if (fn != NULL) ++ return fn(); + -+type fail string ++ return 0; ++} + -<<<<<<< HEAD -+func (e fail) Error() string { return "boringcrypto: " + string(e) + " failed" } ++int ++go_openssl_version_major(void* handle) ++{ ++ unsigned int (*fn)(void); ++ // OPENSSL_version_major is supported since OpenSSL 3. ++ fn = (unsigned int (*)(void))dlsym(handle, "OPENSSL_version_major"); ++ if (fn != NULL) ++ return (int)fn(); + -+const wordBytes = bits.UintSize / 8 ++ // If OPENSSL_version_major is not defined, try with OpenSSL 1 functions. ++ unsigned long num = version_num(handle); ++ if (num < 0x10000000L || num >= 0x20000000L) ++ return -1; + -+// Reverse each limb of z. -+func (z BigInt) byteSwap() { -+ for i, d := range z { -+ var n uint = 0 -+ for j := 0; j < wordBytes; j++ { -+ n |= uint(byte(d)) << (8 * (wordBytes - j - 1)) -+ d >>= 8 -+ } -+ z[i] = n -+ } ++ return 1; +} + -+func wbase(b BigInt) *C.uint8_t { -+ if len(b) == 0 { -+ return nil -+ } -+ return (*C.uint8_t)(unsafe.Pointer(&b[0])) -+} ++int ++go_openssl_version_minor(void* handle) ++{ ++ unsigned int (*fn)(void); ++ // OPENSSL_version_minor is supported since OpenSSL 3. ++ fn = (unsigned int (*)(void))dlsym(handle, "OPENSSL_version_minor"); ++ if (fn != NULL) ++ return (int)fn(); + -+func bigToBN(x BigInt) *C.GO_BIGNUM { -+ if nativeEndian == binary.BigEndian { -+ z := make(BigInt, len(x)) -+ copy(z, x) -+ z.byteSwap() -+ x = z -+ } -+ // Limbs are always ordered in LSB first, so we can safely apply -+ // BN_lebin2bn regardless of host endianness. -+ return C._goboringcrypto_BN_lebin2bn(wbase(x), C.int(len(x)*wordBytes), nil) -+} ++ // If OPENSSL_version_minor is not defined, try with OpenSSL 1 functions. ++ unsigned long num = version_num(handle); ++ // OpenSSL version number follows this schema: ++ // MNNFFPPS: major minor fix patch status. ++ if (num < 0x10000000L || num >= 0x10200000L) ++ { ++ // We only support minor version 0 and 1, ++ // so there is no need to implement an algorithm ++ // that decodes the version number into individual components. ++ return -1; ++ } + -+func bnToBig(bn *C.GO_BIGNUM) BigInt { -+ x := make(BigInt, (C._goboringcrypto_BN_num_bytes(bn)+wordBytes-1)/wordBytes) -+ // Limbs are always ordered in LSB first, so we can safely apply -+ // BN_bn2lebinpad regardless of host endianness. -+ if C._goboringcrypto_BN_bn2lebinpad(bn, wbase(x), C.int(len(x)*wordBytes)) == 0 { -+ panic("boringcrypto: bignum conversion failed") -+ } -+ if nativeEndian == binary.BigEndian { -+ x.byteSwap() -+ } -+ return x ++ if (num >= 0x10100000L) ++ return 1; ++ ++ return 0; +} + -+func bigToBn(bnp **C.GO_BIGNUM, b BigInt) bool { -+ if *bnp != nil { -+ C._goboringcrypto_BN_free(*bnp) -+ *bnp = nil -+ } -+ if b == nil { -+ return true -+ } -+ bn := bigToBN(b) -+ if bn == nil { -+ return false -+ } -+ *bnp = bn -+ return true -+} ++int ++go_openssl_version_patch(void* handle) ++{ ++ unsigned int (*fn)(void); ++ // OPENSSL_version_patch is supported since OpenSSL 3. ++ fn = (unsigned int (*)(void))dlsym(handle, "OPENSSL_version_patch"); ++ if (fn != NULL) ++ return (int)fn(); + -+// noescape hides a pointer from escape analysis. noescape is -+// the identity function but escape analysis doesn't think the -+// output depends on the input. noescape is inlined and currently -======= -+func (e fail) Error() string { return "openssl: " + string(e) + " failed" } ++ // If OPENSSL_version_patch is not defined, try with OpenSSL 1 functions. ++ unsigned long num = version_num(handle); ++ // OpenSSL version number follows this schema: ++ // MNNFFPPS: major minor fix patch status. ++ if (num < 0x10000000L || num >= 0x10200000L) ++ { ++ // We only support minor version 0 and 1, ++ // so there is no need to implement an algorithm ++ // that decodes the version number into individual components. ++ return -1; ++ } + -+// VersionText returns the version text of the OpenSSL currently loaded. -+func VersionText() string { -+ return C.GoString(C.go_openssl_OpenSSL_version(0)) ++ return (num >> 12) & 0xff; +} +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/goopenssl.h b/src/vendor/github.com/golang-fips/openssl/v2/goopenssl.h +new file mode 100644 +index 0000000000..dc2ce35cd7 +--- /dev/null ++++ b/src/vendor/github.com/golang-fips/openssl/v2/goopenssl.h +@@ -0,0 +1,183 @@ ++// This header file describes the OpenSSL ABI as built for use in Go. + -+var ( -+ providerNameFips = C.CString("fips") -+ providerNameDefault = C.CString("default") -+) -+ -+// FIPS returns true if OpenSSL is running in FIPS mode, else returns false. -+func FIPS() bool { -+ switch vMajor { -+ case 1: -+ return C.go_openssl_FIPS_mode() == 1 -+ case 3: -+ // If FIPS is not enabled via default properties, then we are sure FIPS is not used. -+ if C.go_openssl_EVP_default_properties_is_fips_enabled(nil) == 0 { -+ return false -+ } -+ // EVP_default_properties_is_fips_enabled can return true even if the FIPS provider isn't loaded, -+ // it is only based on the default properties. -+ // We can be sure that the FIPS provider is available if we can fetch an algorithm, e.g., SHA2-256, -+ // explicitly setting `fips=yes`. -+ return C.go_openssl_OSSL_PROVIDER_available(nil, providerNameFips) == 1 -+ default: -+ panic(errUnsupportedVersion()) -+ } -+} ++#include // size_t + -+// SetFIPS enables or disables FIPS mode. -+// -+// For OpenSSL 3, the `fips` provider is loaded if enabled is true, -+// else the `default` provider is loaded. -+func SetFIPS(enabled bool) error { -+ var mode C.int -+ if enabled { -+ mode = C.int(1) -+ } else { -+ mode = C.int(0) -+ } -+ switch vMajor { -+ case 1: -+ if C.go_openssl_FIPS_mode_set(mode) != 1 { -+ return newOpenSSLError("FIPS_mode_set") -+ } -+ return nil -+ case 3: -+ var provName *C.char -+ if enabled { -+ provName = providerNameFips -+ } else { -+ provName = providerNameDefault -+ } -+ // Check if there is any provider that matches props. -+ if C.go_openssl_OSSL_PROVIDER_available(nil, provName) != 1 { -+ // If not, fallback to provName provider. -+ if C.go_openssl_OSSL_PROVIDER_load(nil, provName) == nil { -+ return newOpenSSLError("OSSL_PROVIDER_try_load") -+ } -+ // Make sure we now have a provider available. -+ if C.go_openssl_OSSL_PROVIDER_available(nil, provName) != 1 { -+ return fail("SetFIPS(" + strconv.FormatBool(enabled) + ") not supported") -+ } -+ } -+ if C.go_openssl_EVP_default_properties_enable_fips(nil, mode) != 1 { -+ return newOpenSSLError("openssl: EVP_default_properties_enable_fips") -+ } -+ return nil -+ default: -+ panic(errUnsupportedVersion()) -+ } -+} ++#include "shims.h" + -+// noescape hides a pointer from escape analysis. noescape is -+// the identity function but escape analysis doesn't think the -+// output depends on the input. noescape is inlined and currently ->>>>>>> 0023bf4c7a (rebase) -+// compiles down to zero instructions. -+// USE CAREFULLY! -+// -+//go:nosplit -+func noescape(p unsafe.Pointer) unsafe.Pointer { -+ x := uintptr(p) -+ return unsafe.Pointer(x ^ 0) -+} + -+var zero byte ++static inline void ++go_openssl_do_leak_check(void) ++{ ++#ifndef __has_feature ++#define __has_feature(x) 0 ++#endif + -+// addr converts p to its base addr, including a noescape along the way. -+// If p is nil, addr returns a non-nil pointer, so that the result can always -+// be dereferenced. -+// -+//go:nosplit -+func addr(p []byte) *byte { -+ if len(p) == 0 { -+ return &zero -+ } -+ return (*byte)(noescape(unsafe.Pointer(&p[0]))) ++#if (defined(__SANITIZE_ADDRESS__) && __SANITIZE_ADDRESS__) || \ ++ __has_feature(address_sanitizer) ++ extern void __lsan_do_leak_check(void); ++ __lsan_do_leak_check(); ++#endif +} -<<<<<<< HEAD -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_ecdsa_signature.c b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_ecdsa_signature.c -new file mode 100644 -index 0000000000..714d18f1e8 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_ecdsa_signature.c -@@ -0,0 +1,46 @@ -+// +build linux -+// +build !android -+// +build !no_openssl -+// +build !cmd_go_bootstrap -+// +build !msan + -+#include "goopenssl.h" ++int go_openssl_fips_enabled(void* handle); ++int go_openssl_version_major(void* handle); ++int go_openssl_version_minor(void* handle); ++int go_openssl_version_patch(void* handle); ++int go_openssl_thread_setup(void); ++void go_openssl_load_functions(void* handle, int major, int minor, int patch); ++const GO_EVP_MD_PTR go_openssl_EVP_md5_sha1_backport(void); ++ ++// Define pointers to all the used OpenSSL functions. ++// Calling C function pointers from Go is currently not supported. ++// It is possible to circumvent this by using a C function wrapper. ++// https://pkg.go.dev/cmd/cgo ++#define DEFINEFUNC(ret, func, args, argscall) \ ++ extern ret (*_g_##func)args; \ ++ static inline ret go_openssl_##func args \ ++ { \ ++ return _g_##func argscall; \ ++ } ++#define DEFINEFUNC_LEGACY_1_1(ret, func, args, argscall) \ ++ DEFINEFUNC(ret, func, args, argscall) ++#define DEFINEFUNC_LEGACY_1_0(ret, func, args, argscall) \ ++ DEFINEFUNC(ret, func, args, argscall) ++#define DEFINEFUNC_LEGACY_1(ret, func, args, argscall) \ ++ DEFINEFUNC(ret, func, args, argscall) ++#define DEFINEFUNC_1_1(ret, func, args, argscall) \ ++ DEFINEFUNC(ret, func, args, argscall) ++#define DEFINEFUNC_1_1_1(ret, func, args, argscall) \ ++ DEFINEFUNC(ret, func, args, argscall) ++#define DEFINEFUNC_3_0(ret, func, args, argscall) \ ++ DEFINEFUNC(ret, func, args, argscall) ++#define DEFINEFUNC_RENAMED_1_1(ret, func, oldfunc, args, argscall) \ ++ DEFINEFUNC(ret, func, args, argscall) ++#define DEFINEFUNC_RENAMED_3_0(ret, func, oldfunc, args, argscall) \ ++ DEFINEFUNC(ret, func, args, argscall) + -+int _goboringcrypto_ECDSA_sign(EVP_MD *md, const uint8_t *msg, size_t msgLen, -+ uint8_t *sig, size_t *slen, -+ GO_EC_KEY *eckey) { -+ int result; -+ EVP_PKEY *key = _goboringcrypto_EVP_PKEY_new(); -+ if (!key) { -+ return 0; -+ } -+ if (!_goboringcrypto_EVP_PKEY_set1_EC_KEY(key, eckey)) { -+ result = 0; -+ goto err; -+ } -+ result = _goboringcrypto_EVP_sign(md, NULL, msg, msgLen, sig, slen, key); -+err: -+ _goboringcrypto_EVP_PKEY_free(key); -+ return result; -+} -+ -+int _goboringcrypto_ECDSA_verify(EVP_MD *md, const uint8_t *msg, size_t msgLen, -+ const uint8_t *sig, unsigned int slen, -+ GO_EC_KEY *eckey) { -+ -+ int result; -+ EVP_PKEY *key = _goboringcrypto_EVP_PKEY_new(); -+ if (!key) { -+ return 0; -+ } -+ if (!_goboringcrypto_EVP_PKEY_set1_EC_KEY(key, eckey)) { -+ result = 0; -+ goto err; -+ } ++FOR_ALL_OPENSSL_FUNCTIONS + -+ result = _goboringcrypto_EVP_verify(md, NULL, msg, msgLen, sig, slen, key); ++#undef DEFINEFUNC ++#undef DEFINEFUNC_LEGACY_1_1 ++#undef DEFINEFUNC_LEGACY_1_0 ++#undef DEFINEFUNC_LEGACY_1 ++#undef DEFINEFUNC_1_1 ++#undef DEFINEFUNC_1_1_1 ++#undef DEFINEFUNC_3_0 ++#undef DEFINEFUNC_RENAMED_1_1 ++#undef DEFINEFUNC_RENAMED_3_0 + -+err: -+ _goboringcrypto_EVP_PKEY_free(key); -+ return result; ++// go_sha_sum copies ctx into ctx2 and calls EVP_DigestFinal using ctx2. ++// This is necessary because Go hash.Hash mandates that Sum has no effect ++// on the underlying stream. In particular it is OK to Sum, then Write more, ++// then Sum again, and the second Sum acts as if the first didn't happen. ++// It is written in C because Sum() tend to be in the hot path, ++// and doing one cgo call instead of two is a significant performance win. ++static inline int ++go_sha_sum(GO_EVP_MD_CTX_PTR ctx, GO_EVP_MD_CTX_PTR ctx2, unsigned char *out) ++{ ++ if (go_openssl_EVP_MD_CTX_copy(ctx2, ctx) != 1) ++ return 0; ++ // TODO: use EVP_DigestFinal_ex once we know why it leaks ++ // memory on OpenSSL 1.0.2. ++ return go_openssl_EVP_DigestFinal(ctx2, out, NULL); +} -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_evp.c b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_evp.c -new file mode 100644 -index 0000000000..24a9615108 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_evp.c -@@ -0,0 +1,140 @@ -+// +build linux -+// +build !android -+// +build !no_openssl -+// +build !cmd_go_bootstrap -+// +build !msan -+ -+#include "goopenssl.h" + -+int _goboringcrypto_EVP_sign(EVP_MD *md, EVP_PKEY_CTX *ctx, const uint8_t *msg, -+ size_t msgLen, uint8_t *sig, size_t *slen, -+ EVP_PKEY *key) { -+ EVP_MD_CTX *mdctx = NULL; -+ int ret = 0; -+ -+ if (!(mdctx = _goboringcrypto_EVP_MD_CTX_create())) -+ goto err; -+ -+ if (1 != _goboringcrypto_EVP_DigestSignInit(mdctx, &ctx, md, NULL, key)) -+ goto err; -+ -+ if (1 != _goboringcrypto_EVP_DigestUpdate(mdctx, msg, msgLen)) -+ goto err; -+ -+ /* Obtain the signature length */ -+ if (1 != _goboringcrypto_EVP_DigestSignFinal(mdctx, NULL, slen)) -+ goto err; -+ /* Obtain the signature */ -+ if (1 != _goboringcrypto_EVP_DigestSignFinal(mdctx, sig, slen)) -+ goto err; -+ -+ /* Success */ -+ ret = 1; -+ -+err: -+ if (mdctx) -+ _goboringcrypto_EVP_MD_CTX_free(mdctx); -+ -+ return ret; ++// These wrappers allocate out_len on the C stack to avoid having to pass a pointer from Go, which would escape to the heap. ++// Use them only in situations where the output length can be safely discarded. ++static inline int ++go_openssl_EVP_EncryptUpdate_wrapper(GO_EVP_CIPHER_CTX_PTR ctx, unsigned char *out, const unsigned char *in, int in_len) ++{ ++ int len; ++ return go_openssl_EVP_EncryptUpdate(ctx, out, &len, in, in_len); +} + -+int _goboringcrypto_EVP_sign_raw(EVP_MD *md, EVP_PKEY_CTX *ctx, const uint8_t *msg, -+ size_t msgLen, uint8_t *sig, size_t *slen, -+ GO_RSA *rsa_key) { -+ int ret = 0; -+ GO_EVP_PKEY *pk = _goboringcrypto_EVP_PKEY_new(); -+ if (!pk) -+ return 0; -+ -+ if (!(_goboringcrypto_EVP_PKEY_set1_RSA(pk, rsa_key))) -+ goto err; -+ -+ if (!ctx && !(ctx = _goboringcrypto_EVP_PKEY_CTX_new(pk, NULL))) -+ goto err; -+ -+ if (1 != _goboringcrypto_EVP_PKEY_sign_init(ctx)) -+ goto err; -+ -+ if (_goboringcrypto_EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) -+ goto err; -+ -+ if (1 != _goboringcrypto_EVP_PKEY_sign(ctx, sig, slen, msg, msgLen)) -+ goto err; -+ -+ /* Success */ -+ ret = 1; -+ -+err: -+ if (ctx) -+ _goboringcrypto_EVP_PKEY_CTX_free(ctx); -+ if (pk) -+ _goboringcrypto_EVP_PKEY_free(pk); ++static inline int ++go_openssl_EVP_DecryptUpdate_wrapper(GO_EVP_CIPHER_CTX_PTR ctx, unsigned char *out, const unsigned char *in, int in_len) ++{ ++ int len; ++ return go_openssl_EVP_DecryptUpdate(ctx, out, &len, in, in_len); ++} + -+ return ret; ++static inline int ++go_openssl_EVP_CipherUpdate_wrapper(GO_EVP_CIPHER_CTX_PTR ctx, unsigned char *out, const unsigned char *in, int in_len) ++{ ++ int len; ++ return go_openssl_EVP_CipherUpdate(ctx, out, &len, in, in_len); +} + -+int _goboringcrypto_EVP_verify(EVP_MD *md, EVP_PKEY_CTX *ctx, -+ const uint8_t *msg, size_t msgLen, -+ const uint8_t *sig, unsigned int slen, -+ EVP_PKEY *key) { -+ EVP_MD_CTX *mdctx = NULL; -+ int ret = 0; + -+ if (!(mdctx = _goboringcrypto_EVP_MD_CTX_create())) -+ goto err; -+ if (1 != _goboringcrypto_EVP_DigestVerifyInit(mdctx, &ctx, md, NULL, key)) -+ goto err; ++// These wrappers allocate out_len on the C stack, and check that it matches the expected ++// value, to avoid having to pass a pointer from Go, which would escape to the heap. + -+ if (1 != _goboringcrypto_EVP_DigestUpdate(mdctx, msg, msgLen)) -+ goto err; ++static inline int ++go_openssl_EVP_CIPHER_CTX_seal_wrapper(const GO_EVP_CIPHER_CTX_PTR ctx, ++ unsigned char *out, ++ const unsigned char *nonce, ++ const unsigned char *in, int in_len, ++ const unsigned char *aad, int aad_len) ++{ ++ if (in_len == 0) in = (const unsigned char *)""; ++ if (aad_len == 0) aad = (const unsigned char *)""; + -+ if (1 != _goboringcrypto_EVP_DigestVerifyFinal(mdctx, sig, slen)) { -+ goto err; -+ } ++ if (go_openssl_EVP_CipherInit_ex(ctx, NULL, NULL, NULL, nonce, GO_AES_ENCRYPT) != 1) ++ return 0; + -+ /* Success */ -+ ret = 1; ++ int discard_len, out_len; ++ if (go_openssl_EVP_EncryptUpdate(ctx, NULL, &discard_len, aad, aad_len) != 1 ++ || go_openssl_EVP_EncryptUpdate(ctx, out, &out_len, in, in_len) != 1 ++ || go_openssl_EVP_EncryptFinal_ex(ctx, out + out_len, &discard_len) != 1) ++ { ++ return 0; ++ } + -+err: -+ if (mdctx) -+ _goboringcrypto_EVP_MD_CTX_free(mdctx); ++ if (in_len != out_len) ++ return 0; + -+ return ret; ++ return go_openssl_EVP_CIPHER_CTX_ctrl(ctx, GO_EVP_CTRL_GCM_GET_TAG, 16, out + out_len); +} + -+int _goboringcrypto_EVP_verify_raw(const uint8_t *msg, size_t msgLen, -+ const uint8_t *sig, unsigned int slen, -+ GO_RSA *rsa_key) { ++static inline int ++go_openssl_EVP_CIPHER_CTX_open_wrapper(const GO_EVP_CIPHER_CTX_PTR ctx, ++ unsigned char *out, ++ const unsigned char *nonce, ++ const unsigned char *in, int in_len, ++ const unsigned char *aad, int aad_len, ++ const unsigned char *tag) ++{ ++ if (in_len == 0) in = (const unsigned char *)""; ++ if (aad_len == 0) aad = (const unsigned char *)""; + -+ int ret = 0; -+ EVP_PKEY_CTX *ctx; -+ GO_EVP_PKEY *pk = _goboringcrypto_EVP_PKEY_new(); -+ if (!pk) -+ return 0; ++ if (go_openssl_EVP_CipherInit_ex(ctx, NULL, NULL, NULL, nonce, GO_AES_DECRYPT) != 1) ++ return 0; + -+ if (!(_goboringcrypto_EVP_PKEY_set1_RSA(pk, rsa_key))) -+ goto err; ++ int discard_len, out_len; ++ if (go_openssl_EVP_DecryptUpdate(ctx, NULL, &discard_len, aad, aad_len) != 1 ++ || go_openssl_EVP_DecryptUpdate(ctx, out, &out_len, in, in_len) != 1) ++ { ++ return 0; ++ } + -+ if (!(ctx = _goboringcrypto_EVP_PKEY_CTX_new(pk, NULL))) -+ goto err; ++ if (go_openssl_EVP_CIPHER_CTX_ctrl(ctx, GO_EVP_CTRL_GCM_SET_TAG, 16, (unsigned char *)(tag)) != 1) ++ return 0; + -+ if (1 != _goboringcrypto_EVP_PKEY_verify_init(ctx)) -+ goto err; ++ if (go_openssl_EVP_DecryptFinal_ex(ctx, out + out_len, &discard_len) != 1) ++ return 0; + -+ if (_goboringcrypto_EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0) -+ goto err; ++ if (out_len != in_len) ++ return 0; + -+ if (1 != _goboringcrypto_EVP_PKEY_verify(ctx, sig, slen, msg, msgLen)) -+ goto err; ++ return 1; ++} + -+ /* Success */ -+ ret = 1; ++// Hand-roll custom wrappers for CRYPTO_malloc and CRYPTO_free which cast the ++// function pointers to the correct signatures for OpenSSL 1.0.2. + -+err: -+ if (ctx) -+ _goboringcrypto_EVP_PKEY_CTX_free(ctx); -+ if (pk) -+ _goboringcrypto_EVP_PKEY_free(pk); ++static inline void * ++go_openssl_CRYPTO_malloc_legacy102(int num, const char *file, int line) { ++ return ((void *(*)(int, const char *, int))_g_CRYPTO_malloc)(num, file, line); ++} + -+ return ret; ++static inline void ++go_openssl_CRYPTO_free_legacy102(void *str) { ++ ((void (*)(void *))_g_CRYPTO_free)(str); +} -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_lock_setup.c b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_lock_setup.c +\ No newline at end of file +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/hkdf.go b/src/vendor/github.com/golang-fips/openssl/v2/hkdf.go new file mode 100644 -index 0000000000..49d40a7486 +index 0000000000..18b92059cc --- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_lock_setup.c -@@ -0,0 +1,49 @@ -+// +build linux -+// +build !android -+// +build !no_openssl -+// +build !cmd_go_bootstrap -+// +build !msan -+ -+#include "goopenssl.h" -+#include -+#include -+#include -+#include -+#include -+ -+#define _GNU_SOURCE -+#include -+ -+#define MUTEX_TYPE pthread_mutex_t -+#define MUTEX_SETUP(x) pthread_mutex_init(&(x), NULL) -+#define MUTEX_CLEANUP(x) pthread_mutex_destroy(&(x)) -+#define MUTEX_LOCK(x) pthread_mutex_lock(&(x)) -+#define MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x)) -+#define THREAD_ID pthread_self() ++++ b/src/vendor/github.com/golang-fips/openssl/v2/hkdf.go +@@ -0,0 +1,176 @@ ++//go:build !cmd_go_bootstrap + -+/* This array will store all of the mutexes available to OpenSSL. */ -+static MUTEX_TYPE *mutex_buf = NULL; ++package openssl + -+static void locking_function(int mode, int n, const char *file, int line) { -+ if (mode & CRYPTO_LOCK) -+ MUTEX_LOCK(mutex_buf[n]); -+ else -+ MUTEX_UNLOCK(mutex_buf[n]); -+} ++// #include "goopenssl.h" ++import "C" ++import ( ++ "errors" ++ "hash" ++ "io" ++ "runtime" ++ "unsafe" ++) + -+static unsigned long id_function(void) { -+ return ((unsigned long)syscall(__NR_gettid)); ++func SupportsHKDF() bool { ++ return vMajor > 1 || ++ (vMajor >= 1 && vMinor > 1) || ++ (vMajor >= 1 && vMinor >= 1 && vPatch >= 1) +} + -+int _goboringcrypto_OPENSSL_thread_setup(void) { -+ int i; -+ -+ mutex_buf = malloc(_goboringcrypto_CRYPTO_num_locks() * sizeof(MUTEX_TYPE)); -+ if (!mutex_buf) -+ return 0; -+ for (i = 0; i < _goboringcrypto_CRYPTO_num_locks(); i++) -+ MUTEX_SETUP(mutex_buf[i]); -+ _goboringcrypto_CRYPTO_set_id_callback(id_function); -+ _goboringcrypto_CRYPTO_set_locking_callback(locking_function); -+ return 1; -+} -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_aead_gcm.c b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_aead_gcm.c -new file mode 100644 -index 0000000000..7eb645ef21 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_aead_gcm.c -@@ -0,0 +1,171 @@ -+// This file contains a port of the BoringSSL AEAD interface. -+// +build linux -+// +build !android -+// +build !no_openssl -+// +build !cmd_go_bootstrap -+// +build !msan ++func newHKDF(h func() hash.Hash, mode C.int) (*hkdf, error) { ++ if !SupportsHKDF() { ++ return nil, errUnsupportedVersion() ++ } + -+#include "goopenssl.h" -+#include -+ -+int _goboringcrypto_EVP_CIPHER_CTX_seal(uint8_t *out, uint8_t *iv, uint8_t *aad, -+ size_t aad_len, uint8_t *plaintext, -+ size_t plaintext_len, -+ size_t *ciphertext_len, uint8_t *key, -+ int key_size) { -+ -+ EVP_CIPHER_CTX *ctx; -+ int len; -+ int ret; -+ -+ if (plaintext_len == 0) { -+ plaintext = ""; -+ } -+ -+ if (aad_len == 0) { -+ aad = ""; -+ } -+ -+ // Create and initialise the context. -+ if (!(ctx = _goboringcrypto_EVP_CIPHER_CTX_new())) { -+ goto err; -+ } -+ -+ switch (key_size) { -+ case 128: -+ if (!_goboringcrypto_EVP_EncryptInit_ex( -+ ctx, _goboringcrypto_EVP_aes_128_gcm(), NULL, NULL, NULL)) { -+ goto err; -+ } -+ break; -+ case 256: -+ if (!_goboringcrypto_EVP_EncryptInit_ex( -+ ctx, _goboringcrypto_EVP_aes_256_gcm(), NULL, NULL, NULL)) { -+ goto err; -+ } -+ break; -+ default: -+ goto err; -+ } -+ -+ // Initialize IV. -+ if (!_goboringcrypto_EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL)) { -+ goto err; -+ } -+ if (!_goboringcrypto_EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 12, -+ 0)) { -+ goto err; -+ } -+ if (!_goboringcrypto_EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IV_FIXED, -1, -+ iv)) { -+ goto err; -+ } -+ if (!_goboringcrypto_EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_IV_GEN, 0, iv)) { -+ goto err; -+ } -+ -+ // Provide AAD data. -+ if (!_goboringcrypto_EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len)) { -+ goto err; -+ } -+ -+ if (!_goboringcrypto_EVP_EncryptUpdate(ctx, out, &len, plaintext, -+ plaintext_len)) { -+ goto err; -+ } -+ *ciphertext_len = len; -+ -+ if (!_goboringcrypto_EVP_EncryptFinal_ex(ctx, out + len, &len)) { -+ goto err; -+ } -+ *ciphertext_len += len; -+ -+ if (!_goboringcrypto_EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, -+ out + (*ciphertext_len))) { -+ goto err; -+ } -+ *ciphertext_len += 16; -+ ret = 1; -+ -+err: -+ _goboringcrypto_EVP_CIPHER_CTX_free(ctx); -+ -+ if (ret > 0) { -+ return ret; -+ } else { -+ return 0; -+ } -+} ++ ch := h() ++ md := hashToMD(ch) ++ if md == nil { ++ return nil, errors.New("unsupported hash function") ++ } + -+int _goboringcrypto_EVP_CIPHER_CTX_open(uint8_t *ciphertext, int ciphertext_len, -+ uint8_t *aad, int aad_len, uint8_t *tag, -+ uint8_t *key, int key_size, uint8_t *iv, -+ int iv_len, uint8_t *plaintext, -+ size_t *plaintext_len) { ++ ctx := C.go_openssl_EVP_PKEY_CTX_new_id(C.GO_EVP_PKEY_HKDF, nil) ++ if ctx == nil { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_new_id") ++ } ++ defer func() { ++ C.go_openssl_EVP_PKEY_CTX_free(ctx) ++ }() + -+ EVP_CIPHER_CTX *ctx; -+ int len; -+ int ret; ++ if C.go_openssl_EVP_PKEY_derive_init(ctx) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_derive_init") ++ } ++ switch vMajor { ++ case 3: ++ if C.go_openssl_EVP_PKEY_CTX_set_hkdf_mode(ctx, mode) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_set_hkdf_mode") ++ } ++ if C.go_openssl_EVP_PKEY_CTX_set_hkdf_md(ctx, md) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_set_hkdf_md") ++ } ++ case 1: ++ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, -1, C.GO1_EVP_PKEY_OP_DERIVE, ++ C.GO_EVP_PKEY_CTRL_HKDF_MODE, ++ C.int(mode), nil) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_set_hkdf_mode") ++ } ++ if C.go_openssl_EVP_PKEY_CTX_ctrl(ctx, -1, C.GO1_EVP_PKEY_OP_DERIVE, ++ C.GO_EVP_PKEY_CTRL_HKDF_MD, ++ 0, unsafe.Pointer(md)) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_set_hkdf_md") ++ } ++ } + -+ if (aad_len == 0) { -+ aad = ""; -+ } ++ c := &hkdf{ctx: ctx, hashLen: ch.Size()} ++ ctx = nil + -+ // Create and initialise the context. -+ if (!(ctx = _goboringcrypto_EVP_CIPHER_CTX_new())) -+ return 0; ++ runtime.SetFinalizer(c, (*hkdf).finalize) + -+ switch (key_size) { -+ case 128: -+ if (!_goboringcrypto_EVP_DecryptInit_ex( -+ ctx, _goboringcrypto_EVP_aes_128_gcm(), NULL, NULL, NULL)) { -+ goto err; -+ } -+ break; -+ case 256: -+ if (!_goboringcrypto_EVP_DecryptInit_ex( -+ ctx, _goboringcrypto_EVP_aes_256_gcm(), NULL, NULL, NULL)) { -+ goto err; -+ } -+ break; -+ } -+ -+ // Initialize key and nonce. -+ if (!_goboringcrypto_EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) { -+ goto err; -+ } -+ -+ // Provide any AAD data. -+ if (!_goboringcrypto_EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len)) { -+ goto err; -+ } -+ -+ // Provide the message to be decrypted, and obtain the plaintext output. -+ if (!_goboringcrypto_EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, -+ ciphertext_len)) { -+ goto err; -+ } -+ *plaintext_len = len; -+ -+ // Set expected tag value. Works in OpenSSL 1.0.1d and later. -+ if (!_goboringcrypto_EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, -+ tag)) { -+ goto err; -+ } -+ -+ // Finalise the decryption. A positive return value indicates success, -+ // anything else is a failure - the plaintext is not trustworthy. -+ ret = _goboringcrypto_EVP_DecryptFinal_ex(ctx, plaintext + len, &len); -+ -+err: -+ _goboringcrypto_EVP_CIPHER_CTX_free(ctx); -+ -+ if (ret > 0) { -+ // Success -+ *plaintext_len += len; -+ return ret; -+ } else { -+ // Verify failed -+ return 0; -+ } ++ return c, nil +} -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_ctr128.c b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_ctr128.c -new file mode 100644 -index 0000000000..df4ebe3297 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_ctr128.c -@@ -0,0 +1,13 @@ -+// +build linux -+// +build !android -+// +build !no_openssl -+// +build !cmd_go_bootstrap -+// +build !msan + -+#include "goopenssl.h" ++type hkdf struct { ++ ctx C.GO_EVP_PKEY_CTX_PTR + -+void _goboringcrypto_EVP_AES_ctr128_enc(EVP_CIPHER_CTX *ctx, const uint8_t *in, -+ uint8_t *out, size_t in_len) { -+ int len; -+ _goboringcrypto_EVP_EncryptUpdate(ctx, out, &len, in, in_len); ++ hashLen int ++ buf []byte +} -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_ecdh.c b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_ecdh.c -new file mode 100644 -index 0000000000..8205b040c5 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_ecdh.c -@@ -0,0 +1,342 @@ -+// +build linux -+// +build !android -+// +build !no_openssl -+// +build !cmd_go_bootstrap -+// +build !msan -+ -+#include "goopenssl.h" -+ -+static GO_EC_POINT * -+public_key_from_private(const GO_EC_GROUP *group, const GO_BIGNUM *priv) -+{ -+ // OpenSSL does not expose any method to generate the public -+ // key from the private key [1], so we have to calculate it here. -+ // [1] https://github.com/openssl/openssl/issues/18437#issuecomment-1144717206 -+ GO_EC_POINT *point; -+ -+ point = _goboringcrypto_EC_POINT_new(group); -+ if (!point) -+ return NULL; + -+ if (_goboringcrypto_EC_POINT_mul(group, point, priv, NULL, NULL, NULL) != 1) { -+ _goboringcrypto_EC_POINT_free(point); -+ return NULL; ++func (c *hkdf) finalize() { ++ if c.ctx != nil { ++ C.go_openssl_EVP_PKEY_CTX_free(c.ctx) + } -+ -+ return point; +} + -+static size_t -+encode_point(const GO_EC_GROUP *group, const GO_EC_POINT *point, -+ unsigned char **result) -+{ -+ size_t len; -+ -+ len = _goboringcrypto_EC_POINT_point2oct(group, point, -+ GO_POINT_CONVERSION_UNCOMPRESSED, -+ NULL, 0, NULL); -+ if (!len) -+ return 0; -+ -+ *result = malloc(len); -+ if (!*result) -+ return 0; -+ -+ len = _goboringcrypto_EC_POINT_point2oct(group, point, -+ GO_POINT_CONVERSION_UNCOMPRESSED, -+ *result, len, NULL); -+ if (!len) { -+ free(*result); -+ return 0; -+ } -+ -+ return len; -+} -+ -+#if OPENSSL_VERSION_NUMBER >= 0x30000000 -+ -+DEFINEFUNCINTERNAL(const char *, OBJ_nid2sn, (int n), (n)) -+DEFINEFUNCINTERNAL(OSSL_PARAM_BLD *, OSSL_PARAM_BLD_new, (void), ()) -+DEFINEFUNCINTERNAL(int, OSSL_PARAM_BLD_push_octet_string, -+ (OSSL_PARAM_BLD *bld, const char *key, const void *buf, size_t bsize), -+ (bld, key, buf, bsize)) -+DEFINEFUNCINTERNAL(int, OSSL_PARAM_BLD_push_utf8_string, -+ (OSSL_PARAM_BLD *bld, const char *key, const char *buf, size_t bsize), -+ (bld, key, buf, bsize)) -+DEFINEFUNCINTERNAL(OSSL_PARAM *, OSSL_PARAM_BLD_to_param, (OSSL_PARAM_BLD *bld), (bld)) -+DEFINEFUNCINTERNAL(void, OSSL_PARAM_BLD_free, (OSSL_PARAM_BLD *bld), (bld)) -+DEFINEFUNCINTERNAL(void, OSSL_PARAM_free, (OSSL_PARAM *params), (params)) -+DEFINEFUNCINTERNAL(int, OSSL_PARAM_BLD_push_BN, -+ (OSSL_PARAM_BLD *bld, const char *key, const BIGNUM *bn), -+ (bld, key, bn)) -+DEFINEFUNCINTERNAL(int, EVP_PKEY_fromdata_init, (GO_EVP_PKEY_CTX *ctx), (ctx)) -+DEFINEFUNCINTERNAL(int, EVP_PKEY_fromdata, (GO_EVP_PKEY_CTX *ctx, GO_EVP_PKEY **pkey, int selection, OSSL_PARAM params[]), (ctx, pkey, selection, params)) -+ -+GO_EVP_PKEY * -+_goboringcrypto_EVP_PKEY_new_for_ecdh(int nid, const uint8_t *bytes, size_t len, int is_private) -+{ -+ OSSL_PARAM_BLD *bld; -+ const char *group_name; -+ OSSL_PARAM *params = NULL; -+ EVP_PKEY_CTX *ctx = NULL; -+ EVP_PKEY *result = NULL; -+ int selection; -+ -+ /* EVP_PKEY_fromdata in earlier 3.0 releases does not check -+ * that the given point is on the curve. We do that manually -+ * with EC_POINT_oct2point. -+ */ -+ if (!is_private) { -+ EC_GROUP *group; -+ EC_POINT *point; -+ int ok; -+ -+ group = _goboringcrypto_EC_GROUP_new_by_curve_name(nid); -+ if (!group) -+ return NULL; -+ -+ point = _goboringcrypto_EC_POINT_new(group); -+ if (!point) { -+ _goboringcrypto_EC_GROUP_free(group); -+ return NULL; -+ } -+ -+ ok = _goboringcrypto_EC_POINT_oct2point(group, point, bytes, len, NULL); -+ -+ _goboringcrypto_EC_POINT_free(point); -+ _goboringcrypto_EC_GROUP_free(group); ++func (c *hkdf) Read(p []byte) (int, error) { ++ defer runtime.KeepAlive(c) + -+ if (!ok) -+ return NULL; ++ // EVP_PKEY_derive doesn't support incremental output, each call ++ // derives the key from scratch and returns the requested bytes. ++ // To implement io.Reader, we need to ask for len(c.buf) + len(p) ++ // bytes and copy the last derived len(p) bytes to p. ++ // We use c.buf to know how many bytes we've already derived and ++ // to avoid allocating the whole output buffer on each call. ++ prevLen := len(c.buf) ++ needLen := len(p) ++ remains := 255*c.hashLen - prevLen ++ // Check whether enough data can be generated. ++ if remains < needLen { ++ return 0, errors.New("hkdf: entropy limit reached") ++ } ++ c.buf = append(c.buf, make([]byte, needLen)...) ++ outLen := C.size_t(prevLen + needLen) ++ if C.go_openssl_EVP_PKEY_derive(c.ctx, base(c.buf), &outLen) != 1 { ++ return 0, newOpenSSLError("EVP_PKEY_derive") + } ++ n := copy(p, c.buf[prevLen:outLen]) ++ return n, nil ++} + -+ bld = _goboringcrypto_internal_OSSL_PARAM_BLD_new(); -+ if (bld == NULL) -+ return NULL; -+ -+ group_name = _goboringcrypto_internal_OBJ_nid2sn(nid); -+ if (!_goboringcrypto_internal_OSSL_PARAM_BLD_push_utf8_string(bld, "group", group_name, strlen(group_name))) -+ goto err; -+ -+ if (is_private) { -+ BIGNUM *priv; -+ -+ priv = _goboringcrypto_BN_bin2bn(bytes, len, NULL); -+ if (!priv) -+ goto err; -+ -+ if (!_goboringcrypto_internal_OSSL_PARAM_BLD_push_BN(bld, "priv", priv)) { -+ _goboringcrypto_BN_clear_free(priv); -+ goto err; ++func ExtractHKDF(h func() hash.Hash, secret, salt []byte) ([]byte, error) { ++ c, err := newHKDF(h, C.GO_EVP_KDF_HKDF_MODE_EXTRACT_ONLY) ++ if err != nil { ++ return nil, err ++ } ++ switch vMajor { ++ case 3: ++ if C.go_openssl_EVP_PKEY_CTX_set1_hkdf_key(c.ctx, ++ base(secret), C.int(len(secret))) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_set1_hkdf_key") + } -+ -+ params = _goboringcrypto_internal_OSSL_PARAM_BLD_to_param(bld); -+ if (!params) { -+ _goboringcrypto_BN_clear_free(priv); -+ goto err; ++ if C.go_openssl_EVP_PKEY_CTX_set1_hkdf_salt(c.ctx, ++ base(salt), C.int(len(salt))) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_set1_hkdf_salt") ++ } ++ case 1: ++ if C.go_openssl_EVP_PKEY_CTX_ctrl(c.ctx, -1, C.GO1_EVP_PKEY_OP_DERIVE, ++ C.GO_EVP_PKEY_CTRL_HKDF_KEY, ++ C.int(len(secret)), unsafe.Pointer(base(secret))) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_set1_hkdf_key") ++ } ++ if C.go_openssl_EVP_PKEY_CTX_ctrl(c.ctx, -1, C.GO1_EVP_PKEY_OP_DERIVE, ++ C.GO_EVP_PKEY_CTRL_HKDF_SALT, ++ C.int(len(salt)), unsafe.Pointer(base(salt))) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_set1_hkdf_salt") + } -+ -+ _goboringcrypto_BN_clear_free(priv); -+ selection = GO_EVP_PKEY_KEYPAIR; -+ } else { -+ if (!_goboringcrypto_internal_OSSL_PARAM_BLD_push_octet_string(bld, "pub", bytes, len)) -+ goto err; -+ -+ params = _goboringcrypto_internal_OSSL_PARAM_BLD_to_param(bld); -+ if (!params) -+ goto err; -+ -+ selection = GO_EVP_PKEY_PUBLIC_KEY; + } -+ -+ ctx = _goboringcrypto_EVP_PKEY_CTX_new_id(GO_EVP_PKEY_EC, NULL); -+ if (!ctx) -+ goto err; -+ -+ if (_goboringcrypto_internal_EVP_PKEY_fromdata_init(ctx) != 1) -+ goto err; -+ -+ if (_goboringcrypto_internal_EVP_PKEY_fromdata(ctx, &result, selection, ¶ms[0]) != 1) -+ goto err; -+ -+err: -+ _goboringcrypto_internal_OSSL_PARAM_BLD_free(bld); -+ _goboringcrypto_internal_OSSL_PARAM_free(params); -+ _goboringcrypto_EVP_PKEY_CTX_free(ctx); -+ return result; -+} -+ -+DEFINEFUNCINTERNAL(void, CRYPTO_free, (void *addr, const char *file, int line), (addr, file, line)) -+ -+size_t -+_goboringcrypto_EVP_PKEY_get1_encoded_ecdh_public_key(GO_EVP_PKEY *pkey, -+ unsigned char **result) -+{ -+ unsigned char *res; -+ size_t len; -+ -+ len = _goboringcrypto_EVP_PKEY_get1_encoded_public_key(pkey, &res); -+ if (!len) -+ return 0; -+ -+ *result = malloc(len); -+ if (!*result) { -+ _goboringcrypto_internal_CRYPTO_free(res, __FILE__, __LINE__); -+ return 0; ++ var outLen C.size_t ++ if C.go_openssl_EVP_PKEY_derive(c.ctx, nil, &outLen) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_derive_init") + } -+ memcpy(*result, res, len); -+ _goboringcrypto_internal_CRYPTO_free(res, __FILE__, __LINE__); -+ return len; -+} -+ -+int -+_goboringcrypto_EVP_PKEY_set_ecdh_public_key_from_private(GO_EVP_PKEY *pkey, int nid) -+{ -+ GO_BIGNUM *priv = NULL; -+ GO_EC_GROUP *group = NULL; -+ GO_EC_POINT *point = NULL; -+ size_t len; -+ unsigned char *pub = NULL; -+ int result = 0; -+ -+ if (_goboringcrypto_EVP_PKEY_get_bn_param(pkey, "priv", &priv) != 1) -+ return 0; -+ -+ group = _goboringcrypto_EC_GROUP_new_by_curve_name(nid); -+ if (!group) -+ goto err; -+ -+ point = public_key_from_private(group, priv); -+ if (!point) -+ goto err; -+ -+ len = encode_point(group, point, &pub); -+ if (!len) -+ goto err; -+ -+ if (_goboringcrypto_EVP_PKEY_set1_encoded_public_key(pkey, pub, len) != 1) -+ goto err; -+ -+ result = 1; -+ -+err: -+ _goboringcrypto_EC_GROUP_free(group); -+ _goboringcrypto_EC_POINT_free(point); -+ _goboringcrypto_BN_free(priv); -+ free(pub); -+ return result; ++ out := make([]byte, outLen) ++ if C.go_openssl_EVP_PKEY_derive(c.ctx, base(out), &outLen) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_derive") ++ } ++ return out[:outLen], nil +} + -+#else -+ -+GO_EVP_PKEY * -+_goboringcrypto_EVP_PKEY_new_for_ecdh(int nid, const uint8_t *bytes, size_t len, int is_private) -+{ -+ GO_EVP_PKEY *result = NULL; -+ GO_EC_KEY *key = NULL; -+ -+ key = _goboringcrypto_EC_KEY_new_by_curve_name(nid); -+ if (!key) -+ goto err; -+ -+ if (is_private) { -+ BIGNUM *priv; -+ -+ priv = _goboringcrypto_BN_bin2bn(bytes, len, NULL); -+ if (!priv) -+ goto err; -+ if (_goboringcrypto_EC_KEY_set_private_key(key, priv) != 1) { -+ _goboringcrypto_BN_clear_free(priv); -+ goto err; ++func ExpandHKDF(h func() hash.Hash, pseudorandomKey, info []byte) (io.Reader, error) { ++ c, err := newHKDF(h, C.GO_EVP_KDF_HKDF_MODE_EXPAND_ONLY) ++ if err != nil { ++ return nil, err ++ } ++ switch vMajor { ++ case 3: ++ if C.go_openssl_EVP_PKEY_CTX_set1_hkdf_key(c.ctx, ++ base(pseudorandomKey), C.int(len(pseudorandomKey))) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_set1_hkdf_key") + } -+ _goboringcrypto_BN_clear_free(priv); -+ } else { -+ const EC_GROUP *group = _goboringcrypto_EC_KEY_get0_group(key); -+ EC_POINT *pub; -+ -+ pub = _goboringcrypto_EC_POINT_new(group); -+ if (!pub) { -+ goto err; ++ if C.go_openssl_EVP_PKEY_CTX_add1_hkdf_info(c.ctx, ++ base(info), C.int(len(info))) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_add1_hkdf_info") + } -+ if (_goboringcrypto_EC_POINT_oct2point(group, pub, bytes, len, NULL) != 1) { -+ _goboringcrypto_EC_POINT_free(pub); -+ goto err; ++ case 1: ++ if C.go_openssl_EVP_PKEY_CTX_ctrl(c.ctx, -1, C.GO1_EVP_PKEY_OP_DERIVE, ++ C.GO_EVP_PKEY_CTRL_HKDF_KEY, ++ C.int(len(pseudorandomKey)), unsafe.Pointer(base(pseudorandomKey))) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_set1_hkdf_key") + } -+ if (_goboringcrypto_EC_KEY_set_public_key(key, pub) != 1) { -+ _goboringcrypto_EC_POINT_free(pub); -+ goto err; ++ if C.go_openssl_EVP_PKEY_CTX_ctrl(c.ctx, -1, C.GO1_EVP_PKEY_OP_DERIVE, ++ C.GO_EVP_PKEY_CTRL_HKDF_INFO, ++ C.int(len(info)), unsafe.Pointer(base(info))) != 1 { ++ return nil, newOpenSSLError("EVP_PKEY_CTX_add1_hkdf_info") + } -+ _goboringcrypto_EC_POINT_free(pub); + } ++ return c, nil ++} +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/hmac.go b/src/vendor/github.com/golang-fips/openssl/v2/hmac.go +new file mode 100644 +index 0000000000..ef8116ce66 +--- /dev/null ++++ b/src/vendor/github.com/golang-fips/openssl/v2/hmac.go +@@ -0,0 +1,238 @@ ++//go:build !cmd_go_bootstrap + -+ result = _goboringcrypto_EVP_PKEY_new(); -+ if (!result) -+ goto err; -+ -+ if (_goboringcrypto_EVP_PKEY_assign_EC_KEY(result, key) != 1) { -+ _goboringcrypto_EVP_PKEY_free(result); -+ result = NULL; -+ goto err; -+ } -+ key = NULL; ++package openssl + -+err: -+ _goboringcrypto_EC_KEY_free(key); -+ return result; -+} ++// #include "goopenssl.h" ++import "C" ++import ( ++ "hash" ++ "runtime" ++ "sync" ++ "unsafe" ++) + -+size_t -+_goboringcrypto_EVP_PKEY_get1_encoded_ecdh_public_key(GO_EVP_PKEY *pkey, -+ unsigned char **result) -+{ -+ const GO_EC_KEY *key; -+ const GO_EC_POINT *point; -+ const GO_EC_GROUP *group; -+ size_t len; ++var paramDigest = C.CString("digest") + -+ key = _goboringcrypto_EVP_PKEY_get0_EC_KEY(pkey); -+ if (!key) -+ return 0; ++var ( ++ fetchHMACOnce sync.Once ++ evpHMAC C.GO_EVP_MAC_PTR ++) + -+ point = _goboringcrypto_EC_KEY_get0_public_key(key); -+ if (!point) -+ return 0; ++// NewHMAC returns a new HMAC using OpenSSL. ++// The function h must return a hash implemented by ++// OpenSSL (for example, h could be openssl.NewSHA256). ++// If h is not recognized, NewHMAC returns nil. ++func NewHMAC(h func() hash.Hash, key []byte) hash.Hash { ++ ch := h() ++ md := hashToMD(ch) ++ if md == nil { ++ return nil ++ } + -+ group = _goboringcrypto_EC_KEY_get0_group(key); -+ if (!group) -+ return 0; ++ if len(key) == 0 { ++ // This is supported in OpenSSL/Standard lib and as such ++ // we must support it here. When using HMAC with a null key ++ // HMAC_Init will try and reuse the key from the ctx. This is ++ // not the behavior previously implemented, so as a workaround ++ // we pass an "empty" key. ++ key = make([]byte, C.GO_EVP_MAX_MD_SIZE) ++ } + -+ return encode_point(group, point, result); ++ switch vMajor { ++ case 1: ++ return newHMAC1(key, ch, md) ++ case 3: ++ return newHMAC3(key, ch, md) ++ default: ++ panic(errUnsupportedVersion()) ++ } +} + -+int -+_goboringcrypto_EVP_PKEY_set_ecdh_public_key_from_private(GO_EVP_PKEY *pkey, int nid) -+{ -+ GO_EC_KEY *key; -+ const GO_BIGNUM *priv; -+ const GO_EC_GROUP *group; -+ GO_EC_POINT *point; -+ -+ key = (GO_EC_KEY *)_goboringcrypto_EVP_PKEY_get0_EC_KEY(pkey); -+ if (!key) -+ return 0; ++// hmacCtx3 is used for OpenSSL 1. ++type hmacCtx1 struct { ++ ctx C.GO_HMAC_CTX_PTR ++} + -+ priv = _goboringcrypto_EC_KEY_get0_private_key(key); -+ if (!priv) -+ return 0; ++// hmacCtx3 is used for OpenSSL 3. ++type hmacCtx3 struct { ++ ctx C.GO_EVP_MAC_CTX_PTR ++ key []byte // only set for OpenSSL 3.0.0, 3.0.1, and 3.0.2. ++} + -+ group = _goboringcrypto_EC_KEY_get0_group(key); -+ point = public_key_from_private(group, priv); -+ if (!point) -+ return 0; ++type opensslHMAC struct { ++ ctx1 hmacCtx1 ++ ctx3 hmacCtx3 ++ size int ++ blockSize int ++ sum []byte ++} + -+ if (_goboringcrypto_EC_KEY_set_public_key(key, point) != 1) { -+ _goboringcrypto_EC_POINT_free(point); -+ return 0; ++func newHMAC1(key []byte, h hash.Hash, md C.GO_EVP_MD_PTR) *opensslHMAC { ++ ctx := hmacCtxNew() ++ if ctx == nil { ++ panic("openssl: EVP_MAC_CTX_new failed") + } -+ -+ _goboringcrypto_EC_POINT_free(point); -+ return 1; ++ if C.go_openssl_HMAC_Init_ex(ctx, unsafe.Pointer(&key[0]), C.int(len(key)), md, nil) == 0 { ++ panic(newOpenSSLError("HMAC_Init_ex failed")) ++ } ++ hmac := &opensslHMAC{ ++ size: h.Size(), ++ blockSize: h.BlockSize(), ++ ctx1: hmacCtx1{ctx}, ++ } ++ runtime.SetFinalizer(hmac, (*opensslHMAC).finalize) ++ return hmac +} + -+#endif -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_evp_md5_sha1.c b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_evp_md5_sha1.c -new file mode 100644 -index 0000000000..2eedd5b8c6 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_evp_md5_sha1.c -@@ -0,0 +1,90 @@ -+// This file contains a backport of the EVP_md5_sha1 method. -+// +build linux -+// +build !android -+// +build !no_openssl -+// +build !cmd_go_bootstrap -+// +build !msan -======= -+ -+// base returns the address of the underlying array in b, -+// being careful not to panic when b has zero length. -+func base(b []byte) *C.uchar { -+ if len(b) == 0 { -+ return nil ++func newHMAC3(key []byte, h hash.Hash, md C.GO_EVP_MD_PTR) *opensslHMAC { ++ fetchHMACOnce.Do(func() { ++ name := C.CString("HMAC") ++ evpHMAC = C.go_openssl_EVP_MAC_fetch(nil, name, nil) ++ C.free(unsafe.Pointer(name)) ++ }) ++ if evpHMAC == nil { ++ panic("openssl: HMAC not supported") + } -+ return (*C.uchar)(unsafe.Pointer(&b[0])) ++ ctx := C.go_openssl_EVP_MAC_CTX_new(evpHMAC) ++ if ctx == nil { ++ panic("openssl: EVP_MAC_CTX_new failed") ++ } ++ digest := C.go_openssl_EVP_MD_get0_name(md) ++ bld := C.go_openssl_OSSL_PARAM_BLD_new() ++ if bld == nil { ++ panic(newOpenSSLError("OSSL_PARAM_BLD_new")) ++ } ++ defer C.go_openssl_OSSL_PARAM_BLD_free(bld) ++ C.go_openssl_OSSL_PARAM_BLD_push_utf8_string(bld, paramDigest, digest, 0) ++ params := C.go_openssl_OSSL_PARAM_BLD_to_param(bld) ++ if params == nil { ++ panic(newOpenSSLError("OSSL_PARAM_BLD_to_param")) ++ } ++ defer C.go_openssl_OSSL_PARAM_free(params) ++ if C.go_openssl_EVP_MAC_init(ctx, base(key), C.size_t(len(key)), params) == 0 { ++ panic(newOpenSSLError("EVP_MAC_init failed")) ++ } ++ var hkey []byte ++ if vMinor == 0 && vPatch <= 2 { ++ // EVP_MAC_init only resets the ctx internal state if a key is passed ++ // when using OpenSSL 3.0.0, 3.0.1, and 3.0.2. Save a copy of the key ++ // in the context so Reset can use it later. New OpenSSL versions ++ // do not have this issue so it isn't necessary to save the key. ++ // See https://github.com/openssl/openssl/issues/17811. ++ hkey = make([]byte, len(key)) ++ copy(hkey, key) ++ } ++ hmac := &opensslHMAC{ ++ size: h.Size(), ++ blockSize: h.BlockSize(), ++ ctx3: hmacCtx3{ctx, hkey}, ++ } ++ runtime.SetFinalizer(hmac, (*opensslHMAC).finalize) ++ return hmac +} + -+func sbase(b []byte) *C.char { -+ if len(b) == 0 { -+ return nil ++func (h *opensslHMAC) Reset() { ++ switch vMajor { ++ case 1: ++ if C.go_openssl_HMAC_Init_ex(h.ctx1.ctx, nil, 0, nil, nil) == 0 { ++ panic(newOpenSSLError("HMAC_Init_ex failed")) ++ } ++ case 3: ++ if C.go_openssl_EVP_MAC_init(h.ctx3.ctx, base(h.ctx3.key), C.size_t(len(h.ctx3.key)), nil) == 0 { ++ panic(newOpenSSLError("EVP_MAC_init failed")) ++ } ++ default: ++ panic(errUnsupportedVersion()) ++ } ++ ++ runtime.KeepAlive(h) // Next line will keep h alive too; just making doubly sure. ++ h.sum = nil ++} ++ ++func (h *opensslHMAC) finalize() { ++ switch vMajor { ++ case 1: ++ hmacCtxFree(h.ctx1.ctx) ++ case 3: ++ C.go_openssl_EVP_MAC_CTX_free(h.ctx3.ctx) ++ default: ++ panic(errUnsupportedVersion()) + } -+ return (*C.char)(unsafe.Pointer(&b[0])) +} + -+func newOpenSSLError(msg string) error { -+ var b strings.Builder -+ b.WriteString(msg) -+ b.WriteString("\nopenssl error(s):") -+ for { -+ var ( -+ e C.ulong -+ file *C.char -+ line C.int -+ ) ++func (h *opensslHMAC) Write(p []byte) (int, error) { ++ if len(p) > 0 { + switch vMajor { + case 1: -+ e = C.go_openssl_ERR_get_error_line(&file, &line) ++ C.go_openssl_HMAC_Update(h.ctx1.ctx, base(p), C.size_t(len(p))) + case 3: -+ e = C.go_openssl_ERR_get_error_all(&file, &line, nil, nil, nil) ++ C.go_openssl_EVP_MAC_update(h.ctx3.ctx, base(p), C.size_t(len(p))) + default: + panic(errUnsupportedVersion()) + } -+ if e == 0 { -+ break -+ } -+ b.WriteByte('\n') -+ var buf [256]byte -+ C.go_openssl_ERR_error_string_n(e, (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))) -+ b.WriteString(string(buf[:]) + "\n\t" + C.GoString(file) + ":" + strconv.Itoa(int(line))) + } -+ return errors.New(b.String()) ++ runtime.KeepAlive(h) ++ return len(p), nil +} + -+var unknownFile = "\000" ++func (h *opensslHMAC) Size() int { ++ return h.size ++} + -+// caller reports file and line number information about function invocations on -+// the calling goroutine's stack, in a form suitable for passing to C code. -+// The argument skip is the number of stack frames to ascend, with 0 identifying -+// the caller of caller. The return values report the file name and line number -+// within the file of the corresponding call. The returned file is a C string -+// with static storage duration. -+func caller(skip int) (file *C.char, line C.int) { -+ _, f, l, ok := runtime.Caller(skip + 1) -+ if !ok { -+ f = unknownFile -+ } -+ // The underlying bytes of the file string are null-terminated rodata with -+ // static lifetimes, so can be safely passed to C without worrying about -+ // leaking memory or use-after-free. -+ return (*C.char)(noescape(unsafe.Pointer(unsafe.StringData(f)))), C.int(l) ++func (h *opensslHMAC) BlockSize() int { ++ return h.blockSize +} + -+// cryptoMalloc allocates n bytes of memory on the OpenSSL heap, which may be -+// different from the heap which C.malloc allocates on. The allocated object -+// must be freed using cryptoFree. cryptoMalloc is equivalent to the -+// OPENSSL_malloc macro. -+// -+// Like C.malloc, this function is guaranteed to never return nil. If OpenSSL's -+// malloc indicates out of memory, it crashes the program. -+// -+// Only objects which the OpenSSL library will take ownership of (i.e. will be -+// freed by OPENSSL_free / CRYPTO_free) need to be allocated on the OpenSSL -+// heap. -+func cryptoMalloc(n int) unsafe.Pointer { -+ file, line := caller(1) -+ var p unsafe.Pointer -+ if vMajor == 1 && vMinor == 0 { -+ p = C.go_openssl_CRYPTO_malloc_legacy102(C.int(n), file, line) -+ } else { -+ p = C.go_openssl_CRYPTO_malloc(C.size_t(n), file, line) ++func (h *opensslHMAC) Sum(in []byte) []byte { ++ if h.sum == nil { ++ size := h.Size() ++ h.sum = make([]byte, size) + } -+ if p == nil { -+ // Un-recover()-ably crash the program in the same manner as the -+ // C.malloc() wrapper function. -+ runtime_throw("openssl: CRYPTO_malloc failed") ++ // Make copy of context because Go hash.Hash mandates ++ // that Sum has no effect on the underlying stream. ++ // In particular it is OK to Sum, then Write more, then Sum again, ++ // and the second Sum acts as if the first didn't happen. ++ switch vMajor { ++ case 1: ++ ctx2 := hmacCtxNew() ++ if ctx2 == nil { ++ panic("openssl: HMAC_CTX_new failed") ++ } ++ defer hmacCtxFree(ctx2) ++ if C.go_openssl_HMAC_CTX_copy(ctx2, h.ctx1.ctx) == 0 { ++ panic("openssl: HMAC_CTX_copy failed") ++ } ++ C.go_openssl_HMAC_Final(ctx2, base(h.sum), nil) ++ case 3: ++ ctx2 := C.go_openssl_EVP_MAC_CTX_dup(h.ctx3.ctx) ++ if ctx2 == nil { ++ panic("openssl: EVP_MAC_CTX_dup failed") ++ } ++ defer C.go_openssl_EVP_MAC_CTX_free(ctx2) ++ C.go_openssl_EVP_MAC_final(ctx2, base(h.sum), nil, C.size_t(len(h.sum))) ++ default: ++ panic(errUnsupportedVersion()) + } -+ return p ++ return append(in, h.sum...) +} + -+// cryptoFree frees an object allocated on the OpenSSL heap, which may be -+// different from the heap which C.malloc allocates on. cryptoFree is equivalent -+// to the OPENSSL_free macro. -+func cryptoFree(p unsafe.Pointer) { ++func hmacCtxNew() C.GO_HMAC_CTX_PTR { + if vMajor == 1 && vMinor == 0 { -+ C.go_openssl_CRYPTO_free_legacy102(p) -+ return -+ } -+ file, line := caller(1) -+ C.go_openssl_CRYPTO_free(p, file, line) -+} -+ -+const wordBytes = bits.UintSize / 8 -+ -+// Reverse each limb of z. -+func (z BigInt) byteSwap() { -+ for i, d := range z { -+ var n uint = 0 -+ for j := 0; j < wordBytes; j++ { -+ n |= uint(byte(d)) << (8 * (wordBytes - j - 1)) -+ d >>= 8 ++ // 0x120 is the sizeof value when building against OpenSSL 1.0.2 on Ubuntu 16.04. ++ ctx := (C.GO_HMAC_CTX_PTR)(C.malloc(0x120)) ++ if ctx != nil { ++ C.go_openssl_HMAC_CTX_init(ctx) + } -+ z[i] = n ++ return ctx + } ++ return C.go_openssl_HMAC_CTX_new() +} + -+func wbase(b BigInt) *C.uchar { -+ if len(b) == 0 { -+ return nil ++func hmacCtxFree(ctx C.GO_HMAC_CTX_PTR) { ++ if vMajor == 1 && vMinor == 0 { ++ C.go_openssl_HMAC_CTX_cleanup(ctx) ++ C.free(unsafe.Pointer(ctx)) ++ return + } -+ return (*C.uchar)(unsafe.Pointer(&b[0])) -+} -+ -+// bignum_st_1_0_2 is bignum_st (BIGNUM) memory layout in OpenSSL 1.0.2. -+type bignum_st_1_0_2 struct { -+ d unsafe.Pointer // Pointer to an array of BN_ULONG bit chunks -+ top C.int // Index of last used d +1 -+ dmax C.int -+ neg C.int -+ flags C.int ++ C.go_openssl_HMAC_CTX_free(ctx) +} +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/init.go b/src/vendor/github.com/golang-fips/openssl/v2/init.go +new file mode 100644 +index 0000000000..21126ff550 +--- /dev/null ++++ b/src/vendor/github.com/golang-fips/openssl/v2/init.go +@@ -0,0 +1,63 @@ ++//go:build !cmd_go_bootstrap + -+func bigToBN(x BigInt) C.GO_BIGNUM_PTR { -+ if len(x) == 0 { -+ return nil -+ } -+ -+ if vMajor == 1 && vMinor == 0 { -+ // OpenSSL 1.0.x does not export bn_lebin2bn on all platforms, -+ // so we have to emulate it. -+ bn := C.go_openssl_BN_new() -+ if bn == nil { -+ return nil -+ } -+ if C.go_openssl_bn_expand2(bn, C.int(len(x))) == nil { -+ C.go_openssl_BN_free(bn) -+ panic(newOpenSSLError("BN_expand2")) -+ } -+ // The bytes of a BigInt are laid out in memory in the same order as a -+ // BIGNUM, regardless of host endianness. -+ bns := (*bignum_st_1_0_2)(unsafe.Pointer(bn)) -+ d := unsafe.Slice((*uint)(bns.d), len(x)) -+ bns.top = C.int(copy(d, x)) -+ return bn -+ } ++package openssl + -+ if nativeEndian == binary.BigEndian { -+ z := make(BigInt, len(x)) -+ copy(z, x) -+ z.byteSwap() -+ x = z -+ } -+ // Limbs are always ordered in LSB first, so we can safely apply -+ // BN_lebin2bn regardless of host endianness. -+ return C.go_openssl_BN_lebin2bn(wbase(x), C.int(len(x)*wordBytes), nil) -+} ++// #include "goopenssl.h" ++import "C" ++import ( ++ "errors" ++) + -+func bnToBig(bn C.GO_BIGNUM_PTR) BigInt { -+ if bn == nil { -+ return nil ++// opensslInit loads and initialize OpenSSL. ++// If successful, it returns the major and minor OpenSSL version ++// as reported by the OpenSSL API. ++// ++// See Init() for details about file. ++func opensslInit(file string) (major, minor, patch int, err error) { ++ // Load the OpenSSL shared library using dlopen. ++ handle, err := dlopen(file) ++ if err != nil { ++ return 0, 0, 0, err + } + -+ if vMajor == 1 && vMinor == 0 { -+ // OpenSSL 1.0.x does not export bn_bn2lebinpad on all platforms, -+ // so we have to emulate it. -+ bns := (*bignum_st_1_0_2)(unsafe.Pointer(bn)) -+ d := unsafe.Slice((*uint)(bns.d), bns.top) -+ x := make(BigInt, len(d)) -+ copy(x, d) -+ return x ++ // Retrieve the loaded OpenSSL version and check if it is supported. ++ // Notice that major and minor could not match with the version parameter ++ // in case the name of the shared library file differs from the OpenSSL ++ // version it contains. ++ major = int(C.go_openssl_version_major(handle)) ++ minor = int(C.go_openssl_version_minor(handle)) ++ patch = int(C.go_openssl_version_patch(handle)) ++ if major == -1 || minor == -1 || patch == -1 { ++ return 0, 0, 0, errors.New("openssl: can't retrieve OpenSSL version") + } -+ -+ // Limbs are always ordered in LSB first, so we can safely apply -+ // BN_bn2lebinpad regardless of host endianness. -+ x := make(BigInt, C.go_openssl_BN_num_bits(bn)) -+ if C.go_openssl_BN_bn2lebinpad(bn, wbase(x), C.int(len(x)*wordBytes)) == 0 { -+ panic("openssl: bignum conversion failed") ++ var supported bool ++ if major == 1 { ++ supported = minor == 0 || minor == 1 ++ } else if major == 3 { ++ // OpenSSL guarantees API and ABI compatibility within the same major version since OpenSSL 3. ++ supported = true + } -+ if nativeEndian == binary.BigEndian { -+ x.byteSwap() ++ if !supported { ++ return 0, 0, 0, errUnsupportedVersion() + } -+ return x -+} + -+func bnNumBytes(bn C.GO_BIGNUM_PTR) int { -+ return (int(C.go_openssl_BN_num_bits(bn)) + 7) / 8 -+} ++ // Load the OpenSSL functions. ++ // See shims.go for the complete list of supported functions. ++ C.go_openssl_load_functions(handle, C.int(major), C.int(minor), C.int(patch)) + -+// bnToBinPad converts the absolute value of bn into big-endian form and stores -+// it at to, padding with zeroes if necessary. If len(to) is not large enough to -+// hold the result, an error is returned. -+func bnToBinPad(bn C.GO_BIGNUM_PTR, to []byte) error { -+ if vMajor == 1 && vMinor == 0 { -+ // OpenSSL 1.0.x does not export bn_bn2binpad on all platforms, -+ // so we have to emulate it. -+ n := bnNumBytes(bn) -+ pad := len(to) - n -+ if pad < 0 { -+ return errors.New("openssl: destination buffer too small") -+ } -+ for i := 0; i < pad; i++ { -+ to[i] = 0 ++ // Initialize OpenSSL. ++ C.go_openssl_OPENSSL_init() ++ if major == 1 && minor == 0 { ++ if C.go_openssl_thread_setup() != 1 { ++ return 0, 0, 0, fail("openssl: thread setup") + } -+ if int(C.go_openssl_BN_bn2bin(bn, base(to[pad:]))) != n { -+ return errors.New("openssl: BN_bn2bin short write") ++ C.go_openssl_OPENSSL_add_all_algorithms_conf() ++ C.go_openssl_ERR_load_crypto_strings() ++ } else { ++ flags := C.uint64_t(C.GO_OPENSSL_INIT_ADD_ALL_CIPHERS | C.GO_OPENSSL_INIT_ADD_ALL_DIGESTS | C.GO_OPENSSL_INIT_LOAD_CONFIG | C.GO_OPENSSL_INIT_LOAD_CRYPTO_STRINGS) ++ if C.go_openssl_OPENSSL_init_crypto(flags, nil) != 1 { ++ return 0, 0, 0, fail("openssl: init crypto") + } -+ return nil -+ } -+ -+ if C.go_openssl_BN_bn2binpad(bn, base(to), C.int(len(to))) < 0 { -+ return newOpenSSLError("BN_bn2binpad") + } -+ return nil -+} -+ -+func CheckLeaks() { -+ C.go_openssl_do_leak_check() ++ return major, minor, patch, nil +} -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/pbkdf2.go b/src/vendor/github.com/golang-fips/openssl/v2/pbkdf2.go +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/init_unix.go b/src/vendor/github.com/golang-fips/openssl/v2/init_unix.go new file mode 100644 -index 0000000000..a895eab2d5 +index 0000000000..dbf5ac448f --- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/pbkdf2.go -@@ -0,0 +1,28 @@ -+//go:build !cmd_go_bootstrap ++++ b/src/vendor/github.com/golang-fips/openssl/v2/init_unix.go +@@ -0,0 +1,31 @@ ++//go:build unix && !cmd_go_bootstrap + +package openssl + -+// #include "goopenssl.h" ++// #cgo LDFLAGS: -ldl ++// #include ++// #include +import "C" +import ( + "errors" -+ "hash" ++ "unsafe" +) + -+func PBKDF2(password, salt []byte, iter, keyLen int, h func() hash.Hash) ([]byte, error) { -+ md := hashToMD(h()) -+ if md == nil { -+ return nil, errors.New("unsupported hash function") -+ } -+ if len(password) == 0 && vMajor == 1 && vMinor == 0 { -+ // x/crypto/pbkdf2 supports empty passwords, but OpenSSL 1.0.2 -+ // does not. As a workaround, we pass an "empty" password. -+ password = make([]byte, C.GO_EVP_MAX_MD_SIZE) ++func dlopen(file string) (handle unsafe.Pointer, err error) { ++ cv := C.CString(file) ++ defer C.free(unsafe.Pointer(cv)) ++ handle = C.dlopen(cv, C.RTLD_LAZY|C.RTLD_LOCAL) ++ if handle == nil { ++ errstr := C.GoString(C.dlerror()) ++ return nil, errors.New("openssl: can't load " + file + ": " + errstr) + } -+ out := make([]byte, keyLen) -+ ok := C.go_openssl_PKCS5_PBKDF2_HMAC(sbase(password), C.int(len(password)), base(salt), C.int(len(salt)), C.int(iter), md, C.int(keyLen), base(out)) -+ if ok != 1 { -+ return nil, newOpenSSLError("PKCS5_PBKDF2_HMAC") ++ return handle, nil ++} ++ ++func dlclose(handle unsafe.Pointer) error { ++ if C.dlclose(handle) != 0 { ++ errstr := C.GoString(C.dlerror()) ++ return errors.New("openssl: can't close libcrypto: " + errstr) + } -+ return out, nil ++ return nil +} -diff --git a/src/vendor/github.com/golang-fips/openssl/v2/port_evp_md5_sha1.c b/src/vendor/github.com/golang-fips/openssl/v2/port_evp_md5_sha1.c +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/init_windows.go b/src/vendor/github.com/golang-fips/openssl/v2/init_windows.go new file mode 100644 -index 0000000000..50d49b1f10 +index 0000000000..3778e21227 --- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl/v2/port_evp_md5_sha1.c -<<<<<<< HEAD -@@ -0,0 +1,128 @@ -+//go:build linux ->>>>>>> 0023bf4c7a (rebase) ++++ b/src/vendor/github.com/golang-fips/openssl/v2/init_windows.go +@@ -0,0 +1,36 @@ ++//go:build !cmd_go_bootstrap + -======= -@@ -0,0 +1,126 @@ ->>>>>>> 0b8240ca10 (support opensslv2, update strict fips checks) -+// The following is a partial backport of crypto/evp/m_md5_sha1.c, -+// commit cbc8a839959418d8a2c2e3ec6bdf394852c9501e on the -+// OpenSSL_1_1_0-stable branch. The ctrl function has been removed. ++package openssl + -<<<<<<< HEAD -+#include "goopenssl.h" ++import ( ++ "syscall" ++ "unsafe" ++) + -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+// New in OpenSSL 1.1. -+static inline void * -+_goboringcrypto_internal_EVP_MD_CTX_md_data(EVP_MD_CTX *ctx) { -+ return ctx->md_data; ++type dlopenError struct { ++ file string ++ err error +} + -======= ->>>>>>> 0023bf4c7a (rebase) -+/* -+ * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. -+ * -+ * Licensed under the OpenSSL license (the "License"). You may not use -+ * this file except in compliance with the License. You can obtain a copy -+ * in the file LICENSE in the source distribution or at -+ * https://www.openssl.org/source/license.html -+ */ -+ -<<<<<<< HEAD -+#if !defined(OPENSSL_NO_MD5) -+ -+#include -+#include -+#include -+#include -+#include -+#include ++func (e *dlopenError) Error() string { ++ return "openssl: can't load " + e.file + ": " + e.err.Error() ++} + -+struct md5_sha1_ctx { -+ MD5_CTX md5; -+ SHA_CTX sha1; -+}; ++func (e *dlopenError) Unwrap() error { ++ return e.err ++} + -+static int _goboringcrypto_internal_init(EVP_MD_CTX *ctx) { -+ struct md5_sha1_ctx *mctx = _goboringcrypto_internal_EVP_MD_CTX_md_data(ctx); -+ if (!_goboringcrypto_internal_MD5_Init(&mctx->md5)) -+ return 0; -+ return _goboringcrypto_SHA1_Init(&mctx->sha1); ++func dlopen(file string) (handle unsafe.Pointer, err error) { ++ // As Windows generally does not ship with a system OpenSSL library, let ++ // alone a FIPS 140 certified one, use the default library search order so ++ // that we preferentially load the DLL bundled with the application. ++ h, err := syscall.LoadLibrary(file) ++ if err != nil { ++ return nil, &dlopenError{file: file, err: err} ++ } ++ return unsafe.Pointer(h), nil +} + -+static int _goboringcrypto_internal_update(EVP_MD_CTX *ctx, const void *data, -+ size_t count) { -+ struct md5_sha1_ctx *mctx = _goboringcrypto_internal_EVP_MD_CTX_md_data(ctx); -+ if (!_goboringcrypto_internal_MD5_Update(&mctx->md5, data, count)) -+ return 0; -+ return _goboringcrypto_SHA1_Update(&mctx->sha1, data, count); ++func dlclose(handle unsafe.Pointer) error { ++ return syscall.FreeLibrary(syscall.Handle(handle)) +} +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/openssl.go b/src/vendor/github.com/golang-fips/openssl/v2/openssl.go +new file mode 100644 +index 0000000000..5c9324d858 +--- /dev/null ++++ b/src/vendor/github.com/golang-fips/openssl/v2/openssl.go +@@ -0,0 +1,408 @@ ++//go:build !cmd_go_bootstrap + -+static int _goboringcrypto_internal_final(EVP_MD_CTX *ctx, unsigned char *md) { -+ struct md5_sha1_ctx *mctx = _goboringcrypto_internal_EVP_MD_CTX_md_data(ctx); -+ if (!_goboringcrypto_internal_MD5_Final(md, &mctx->md5)) -+ return 0; -+ return _goboringcrypto_SHA1_Final(md + MD5_DIGEST_LENGTH, &mctx->sha1); -======= -+#include "goopenssl.h" ++// Package openssl provides access to OpenSSL cryptographic functions. ++package openssl + -+#define NID_md5_sha1 114 ++// #include "goopenssl.h" ++import "C" ++import ( ++ "encoding/binary" ++ "errors" ++ "math/bits" ++ "runtime" ++ "strconv" ++ "strings" ++ "sync" ++ "unsafe" ++) + -+#define MD5_CBLOCK 64 -+#define MD5_LBLOCK (MD5_CBLOCK/4) -+#define MD5_DIGEST_LENGTH 16 -+#define SHA_LBLOCK 16 -+#define SHA_DIGEST_LENGTH 20 ++var ( ++ // vMajor and vMinor hold the major/minor OpenSSL version. ++ // It is only populated if Init has been called. ++ vMajor, vMinor, vPatch int ++) + -+#define EVP_PKEY_NULL_method NULL,NULL,{0,0,0,0} ++var ( ++ initOnce sync.Once ++ initErr error ++) + -+// Change: MD5_LONG and SHA_LONG have been expanded to unsigned int, -+// which is always 32 bits. This avoids adding some obscure logic -+// to support 16-bit platforms. ++var nativeEndian binary.ByteOrder + -+# define MD5_LONG unsigned int -+# define SHA_LONG unsigned int ++// CheckVersion checks if the OpenSSL version can be loaded ++// and if the FIPS mode is enabled. ++// This function can be called before Init. ++func CheckVersion(version string) (exists, fips bool) { ++ handle, _ := dlopen(version) ++ if handle == nil { ++ return false, false ++ } ++ defer dlclose(handle) ++ fips = C.go_openssl_fips_enabled(handle) == 1 ++ return true, fips ++} + -+typedef struct env_md_st EVP_MD; -+typedef struct env_md_ctx_st EVP_MD_CTX; ++// Init loads and initializes OpenSSL from the shared library at path. ++// It must be called before any other OpenSSL call, except CheckVersion. ++// ++// Only the first call to Init is effective. ++// Subsequent calls will return the same error result as the one from the first call. ++// ++// The file is passed to dlopen() verbatim to load the OpenSSL shared library. ++// For example, `file=libcrypto.so.1.1.1k-fips` makes Init look for the shared ++// library libcrypto.so.1.1.1k-fips. ++func Init(file string) error { ++ initOnce.Do(func() { ++ buf := [2]byte{} ++ *(*uint16)(unsafe.Pointer(&buf[0])) = uint16(0xABCD) + -+struct env_md_ctx_st { -+ void *digest; -+ void *engine; -+ unsigned long flags; -+ void *md_data; -+ void *pctx; -+ void *update; -+} /* EVP_MD_CTX */ ; ++ switch buf { ++ case [2]byte{0xCD, 0xAB}: ++ nativeEndian = binary.LittleEndian ++ case [2]byte{0xAB, 0xCD}: ++ nativeEndian = binary.BigEndian ++ default: ++ panic("Could not determine native endianness.") ++ } ++ vMajor, vMinor, vPatch, initErr = opensslInit(file) ++ }) ++ return initErr ++} + -+struct env_md_st { -+ int type; -+ int pkey_type; -+ int md_size; -+ unsigned long flags; -+ int (*init) (EVP_MD_CTX *ctx); -+ int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count); -+ int (*final) (EVP_MD_CTX *ctx, unsigned char *md); -+ void *copy; -+ void *cleanup; -+ void *sign; -+ void *verify; -+ int required_pkey_type[5]; -+ int block_size; -+ int ctx_size; -+ void *md_ctrl; -+} /* EVP_MD */ ; ++func errUnsupportedVersion() error { ++ return errors.New("openssl: OpenSSL version: " + strconv.Itoa(vMajor) + "." + strconv.Itoa(vMinor) + "." + strconv.Itoa(vPatch)) ++} + -+typedef struct MD5state_st { -+ MD5_LONG A, B, C, D; -+ MD5_LONG Nl, Nh; -+ MD5_LONG data[MD5_LBLOCK]; -+ MD5_LONG num; -+} MD5_CTX; ++type fail string + -+typedef struct SHAstate_st { -+ SHA_LONG h0, h1, h2, h3, h4; -+ SHA_LONG Nl, Nh; -+ SHA_LONG data[SHA_LBLOCK]; -+ SHA_LONG num; -+} SHA_CTX; ++func (e fail) Error() string { return "openssl: " + string(e) + " failed" } + -+struct md5_sha1_ctx { -+ MD5_CTX md5; -+ SHA_CTX sha1; -+}; ++// VersionText returns the version text of the OpenSSL currently loaded. ++func VersionText() string { ++ return C.GoString(C.go_openssl_OpenSSL_version(0)) ++} + -+static int md5_sha1_init(EVP_MD_CTX *ctx) { -+ struct md5_sha1_ctx *mctx = ctx->md_data; -+ if (!go_openssl_MD5_Init(&mctx->md5)) -+ return 0; -+ return go_openssl_SHA1_Init(&mctx->sha1); ++var ( ++ providerNameFips = C.CString("fips") ++ providerNameDefault = C.CString("default") ++) ++ ++// FIPS returns true if OpenSSL is running in FIPS mode, else returns false. ++func FIPS() bool { ++ switch vMajor { ++ case 1: ++ return C.go_openssl_FIPS_mode() == 1 ++ case 3: ++ // If FIPS is not enabled via default properties, then we are sure FIPS is not used. ++ if C.go_openssl_EVP_default_properties_is_fips_enabled(nil) == 0 { ++ return false ++ } ++ // EVP_default_properties_is_fips_enabled can return true even if the FIPS provider isn't loaded, ++ // it is only based on the default properties. ++ // We can be sure that the FIPS provider is available if we can fetch an algorithm, e.g., SHA2-256, ++ // explicitly setting `fips=yes`. ++ return C.go_openssl_OSSL_PROVIDER_available(nil, providerNameFips) == 1 ++ default: ++ panic(errUnsupportedVersion()) ++ } +} + -+static int md5_sha1_update(EVP_MD_CTX *ctx, const void *data, -+ size_t count) { -+ struct md5_sha1_ctx *mctx = ctx->md_data; -+ if (!go_openssl_MD5_Update(&mctx->md5, data, count)) -+ return 0; -+ return go_openssl_SHA1_Update(&mctx->sha1, data, count); ++// SetFIPS enables or disables FIPS mode. ++// ++// For OpenSSL 3, the `fips` provider is loaded if enabled is true, ++// else the `default` provider is loaded. ++func SetFIPS(enabled bool) error { ++ var mode C.int ++ if enabled { ++ mode = C.int(1) ++ } else { ++ mode = C.int(0) ++ } ++ switch vMajor { ++ case 1: ++ if C.go_openssl_FIPS_mode_set(mode) != 1 { ++ return newOpenSSLError("FIPS_mode_set") ++ } ++ return nil ++ case 3: ++ var provName *C.char ++ if enabled { ++ provName = providerNameFips ++ } else { ++ provName = providerNameDefault ++ } ++ // Check if there is any provider that matches props. ++ if C.go_openssl_OSSL_PROVIDER_available(nil, provName) != 1 { ++ // If not, fallback to provName provider. ++ if C.go_openssl_OSSL_PROVIDER_load(nil, provName) == nil { ++ return newOpenSSLError("OSSL_PROVIDER_try_load") ++ } ++ // Make sure we now have a provider available. ++ if C.go_openssl_OSSL_PROVIDER_available(nil, provName) != 1 { ++ return fail("SetFIPS(" + strconv.FormatBool(enabled) + ") not supported") ++ } ++ } ++ if C.go_openssl_EVP_default_properties_enable_fips(nil, mode) != 1 { ++ return newOpenSSLError("openssl: EVP_default_properties_enable_fips") ++ } ++ return nil ++ default: ++ panic(errUnsupportedVersion()) ++ } +} + -+static int md5_sha1_final(EVP_MD_CTX *ctx, unsigned char *md) { -+ struct md5_sha1_ctx *mctx = ctx->md_data; -+ if (!go_openssl_MD5_Final(md, &mctx->md5)) -+ return 0; -+ return go_openssl_SHA1_Final(md + MD5_DIGEST_LENGTH, &mctx->sha1); ->>>>>>> 0023bf4c7a (rebase) ++// noescape hides a pointer from escape analysis. noescape is ++// the identity function but escape analysis doesn't think the ++// output depends on the input. noescape is inlined and currently ++// compiles down to zero instructions. ++// USE CAREFULLY! ++// ++//go:nosplit ++func noescape(p unsafe.Pointer) unsafe.Pointer { ++ x := uintptr(p) ++ return unsafe.Pointer(x ^ 0) +} + -+// Change: Removed: -+// static int ctrl(EVP_MD_CTX *ctx, int cmd, int mslen, void *ms) ++var zero byte + -+static const EVP_MD md5_sha1_md = { -+ NID_md5_sha1, -+ NID_md5_sha1, -+ MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, -+ 0, -<<<<<<< HEAD -+ _goboringcrypto_internal_init, -+ _goboringcrypto_internal_update, -+ _goboringcrypto_internal_final, -======= -+ md5_sha1_init, -+ md5_sha1_update, -+ md5_sha1_final, ->>>>>>> 0023bf4c7a (rebase) -+ NULL, -+ NULL, -+ EVP_PKEY_NULL_method, // Change: inserted -+ MD5_CBLOCK, -+ sizeof(EVP_MD *) + sizeof(struct md5_sha1_ctx), -+ NULL, // Change: was ctrl -+}; ++// addr converts p to its base addr, including a noescape along the way. ++// If p is nil, addr returns a non-nil pointer, so that the result can always ++// be dereferenced. ++// ++//go:nosplit ++func addr(p []byte) *byte { ++ if len(p) == 0 { ++ return &zero ++ } ++ return (*byte)(noescape(unsafe.Pointer(&p[0]))) ++} + -+// Change: Apply name mangling. -<<<<<<< HEAD -+const GO_EVP_MD *_goboringcrypto_backport_EVP_md5_sha1(void) { -+ return &md5_sha1_md; ++// base returns the address of the underlying array in b, ++// being careful not to panic when b has zero length. ++func base(b []byte) *C.uchar { ++ if len(b) == 0 { ++ return nil ++ } ++ return (*C.uchar)(unsafe.Pointer(&b[0])) +} -+#endif -+#endif -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_hmac.c b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_hmac.c -new file mode 100644 -index 0000000000..362d9e532e ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_hmac.c -@@ -0,0 +1,16 @@ -+// This file contains HMAC portability wrappers. -+// +build linux -+// +build !android -+// +build !no_openssl -+// +build !cmd_go_bootstrap -+// +build !msan + -+#include "goopenssl.h" ++func sbase(b []byte) *C.char { ++ if len(b) == 0 { ++ return nil ++ } ++ return (*C.char)(unsafe.Pointer(&b[0])) ++} + -+// Not in OpenSSL 1.1. However, HMAC_CTX_copy expects an initialized -+// target in OpenSSL 1.1. -+int _goboringcrypto_HMAC_CTX_copy_ex(GO_HMAC_CTX *dest, -+ const GO_HMAC_CTX *src) { -+ // HMAC_CTX_copy lacks the const qualifier for the second parameter. -+ return _goboringcrypto_HMAC_CTX_copy(dest, (GO_HMAC_CTX *)src); ++func newOpenSSLError(msg string) error { ++ var b strings.Builder ++ b.WriteString(msg) ++ b.WriteString("\nopenssl error(s):") ++ for { ++ var ( ++ e C.ulong ++ file *C.char ++ line C.int ++ ) ++ switch vMajor { ++ case 1: ++ e = C.go_openssl_ERR_get_error_line(&file, &line) ++ case 3: ++ e = C.go_openssl_ERR_get_error_all(&file, &line, nil, nil, nil) ++ default: ++ panic(errUnsupportedVersion()) ++ } ++ if e == 0 { ++ break ++ } ++ b.WriteByte('\n') ++ var buf [256]byte ++ C.go_openssl_ERR_error_string_n(e, (*C.char)(unsafe.Pointer(&buf[0])), C.size_t(len(buf))) ++ b.WriteString(string(buf[:]) + "\n\t" + C.GoString(file) + ":" + strconv.Itoa(int(line))) ++ } ++ return errors.New(b.String()) +} -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_rsa.c b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_rsa.c -new file mode 100644 -index 0000000000..bf39656b45 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_port_rsa.c -@@ -0,0 +1,219 @@ -+// This file contains RSA portability wrappers. -+// +build linux -+// +build !android -+// +build !no_openssl -+// +build !cmd_go_bootstrap -+// +build !msan + -+#include "goopenssl.h" ++var unknownFile = "\000" + -+// Only in BoringSSL. -+int _goboringcrypto_RSA_generate_key_fips(GO_RSA *rsa, int size, -+ GO_BN_GENCB *cb) { -+ // BoringSSL's RSA_generate_key_fips hard-codes e to 65537. -+ BIGNUM *e = _goboringcrypto_BN_new(); -+ if (e == NULL) -+ return 0; -+ int ret = _goboringcrypto_BN_set_word(e, RSA_F4) && -+ _goboringcrypto_RSA_generate_key_ex(rsa, size, e, cb); -+ _goboringcrypto_BN_free(e); -+ return ret; -+} -+ -+int _goboringcrypto_RSA_digest_and_sign_pss_mgf1( -+ GO_RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out, -+ const uint8_t *in, size_t in_len, EVP_MD *md, const EVP_MD *mgf1_md, -+ int salt_len) { -+ EVP_PKEY_CTX *ctx; -+ unsigned int siglen; -+ -+ int ret = 0; -+ EVP_PKEY *key = _goboringcrypto_EVP_PKEY_new(); -+ if (!key) { -+ goto err; -+ } -+ if (!_goboringcrypto_EVP_PKEY_set1_RSA(key, rsa)) -+ goto err; -+ ctx = _goboringcrypto_EVP_PKEY_CTX_new(key, NULL /* no engine */); -+ if (!ctx) -+ goto err; -+ -+ EVP_MD_CTX *mdctx = NULL; -+ if (!(mdctx = _goboringcrypto_EVP_MD_CTX_create())) -+ goto err; -+ -+ if (1 != _goboringcrypto_EVP_DigestSignInit(mdctx, &ctx, md, NULL, key)) -+ goto err; -+ -+ if (_goboringcrypto_EVP_PKEY_sign_init(ctx) <= 0) -+ goto err; -+ if (_goboringcrypto_EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) -+ goto err; -+ if (_goboringcrypto_EVP_PKEY_CTX_set_rsa_padding(ctx, -+ RSA_PKCS1_PSS_PADDING) <= 0) -+ goto err; -+ if (_goboringcrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, salt_len) <= 0) -+ goto err; -+ if (mgf1_md) -+ if (_goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, mgf1_md) <= 0) -+ goto err; -+ if (1 != _goboringcrypto_EVP_DigestUpdate(mdctx, in, in_len)) -+ goto err; -+ -+ /* Obtain the signature length */ -+ if (1 != _goboringcrypto_EVP_DigestSignFinal(mdctx, NULL, out_len)) -+ goto err; -+ /* Obtain the signature */ -+ if (1 != _goboringcrypto_EVP_DigestSignFinal(mdctx, out, out_len)) -+ goto err; -+ -+ ret = 1; -+ -+err: -+ if (mdctx) -+ _goboringcrypto_EVP_MD_CTX_free(mdctx); -+ if (ctx) -+ _goboringcrypto_EVP_PKEY_CTX_free(ctx); -+ if (key) -+ _goboringcrypto_EVP_PKEY_free(key); -+ -+ return ret; -+} -+ -+int _goboringcrypto_RSA_sign_pss_mgf1(GO_RSA *rsa, unsigned int *out_len, -+ uint8_t *out, unsigned int max_out, -+ const uint8_t *in, unsigned int in_len, -+ EVP_MD *md, const EVP_MD *mgf1_md, -+ int salt_len) { -+ EVP_PKEY_CTX *ctx; -+ EVP_PKEY *pkey; -+ size_t siglen; -+ -+ int ret = 0; -+ pkey = _goboringcrypto_EVP_PKEY_new(); -+ if (!pkey) -+ goto err; -+ -+ if (_goboringcrypto_EVP_PKEY_set1_RSA(pkey, rsa) <= 0) -+ goto err; -+ -+ ctx = _goboringcrypto_EVP_PKEY_CTX_new(pkey, NULL /* no engine */); -+ if (!ctx) -+ goto err; -+ -+ if (_goboringcrypto_EVP_PKEY_sign_init(ctx) <= 0) -+ goto err; -+ if (_goboringcrypto_EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) -+ goto err; -+ if (_goboringcrypto_EVP_PKEY_CTX_set_rsa_padding(ctx, -+ RSA_PKCS1_PSS_PADDING) <= 0) -+ goto err; -+ if (_goboringcrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, salt_len) <= 0) -+ goto err; -+ if (mgf1_md) -+ if (_goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, mgf1_md) <= 0) -+ goto err; -+ /* Determine buffer length */ -+ if (_goboringcrypto_EVP_PKEY_sign(ctx, NULL, &siglen, in, in_len) <= 0) -+ goto err; -+ -+ if (max_out < siglen) -+ goto err; -+ -+ if (_goboringcrypto_EVP_PKEY_sign(ctx, out, &siglen, in, in_len) <= 0) -+ goto err; -+ -+ *out_len = siglen; -+ ret = 1; -+ -+err: -+ if (ctx) -+ _goboringcrypto_EVP_PKEY_CTX_free(ctx); -+ if (pkey) -+ _goboringcrypto_EVP_PKEY_free(pkey); -+ -+ return ret; -+} -+ -+int _goboringcrypto_RSA_verify_pss_mgf1(RSA *rsa, const uint8_t *msg, -+ unsigned int msg_len, EVP_MD *md, -+ const EVP_MD *mgf1_md, int salt_len, -+ const uint8_t *sig, -+ unsigned int sig_len) { -+ EVP_PKEY_CTX *ctx; -+ EVP_PKEY *pkey; -+ -+ int ret = 0; -+ -+ pkey = _goboringcrypto_EVP_PKEY_new(); -+ if (!pkey) -+ goto err; -+ -+ if (_goboringcrypto_EVP_PKEY_set1_RSA(pkey, rsa) <= 0) -+ goto err; -+ -+ ctx = _goboringcrypto_EVP_PKEY_CTX_new(pkey, NULL /* no engine */); -+ if (!ctx) -+ goto err; -+ -+ if (_goboringcrypto_EVP_PKEY_verify_init(ctx) <= 0) -+ goto err; -+ if (_goboringcrypto_EVP_PKEY_CTX_set_rsa_padding(ctx, -+ RSA_PKCS1_PSS_PADDING) <= 0) -+ goto err; -+ if (_goboringcrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, salt_len) <= 0) -+ goto err; -+ if (_goboringcrypto_EVP_PKEY_CTX_set_signature_md(ctx, md) <= 0) -+ goto err; -+ if (mgf1_md) -+ if (_goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, mgf1_md) <= 0) -+ goto err; -+ if (_goboringcrypto_EVP_PKEY_verify(ctx, sig, sig_len, msg, msg_len) <= 0) -+ goto err; -+ -+ ret = 1; -+ -+err: -+ if (ctx) -+ _goboringcrypto_EVP_PKEY_CTX_free(ctx); -+ if (pkey) -+ _goboringcrypto_EVP_PKEY_free(pkey); -+ -+ return ret; -+} -+ -+int _goboringcrypto_EVP_RSA_sign(EVP_MD *md, const uint8_t *msg, -+ unsigned int msgLen, uint8_t *sig, -+ size_t *slen, RSA *rsa) { -+ int result; -+ EVP_PKEY *key = _goboringcrypto_EVP_PKEY_new(); -+ if (!key) { -+ return 0; -+ } -+ if (!_goboringcrypto_EVP_PKEY_set1_RSA(key, rsa)) { -+ result = 0; -+ goto err; -+ } -+ result = _goboringcrypto_EVP_sign(md, NULL, msg, msgLen, sig, slen, key); -+err: -+ _goboringcrypto_EVP_PKEY_free(key); -+ return result; -+} -+ -+int _goboringcrypto_EVP_RSA_verify(EVP_MD *md, const uint8_t *msg, -+ unsigned int msgLen, const uint8_t *sig, -+ unsigned int slen, GO_RSA *rsa) { -+ int result; -+ EVP_PKEY *key = _goboringcrypto_EVP_PKEY_new(); -+ if (!key) { -+ return 0; -+ } -+ if (!_goboringcrypto_EVP_PKEY_set1_RSA(key, rsa)) { -+ result = 0; -+ goto err; -+ } -+ result = _goboringcrypto_EVP_verify(md, NULL, msg, msgLen, sig, slen, key); -+err: -+ _goboringcrypto_EVP_PKEY_free(key); -+ return result; -+} -diff --git a/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_stub_rand.c b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_stub_rand.c -new file mode 100644 -index 0000000000..22bd865a35 ---- /dev/null -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/openssl_stub_rand.c -@@ -0,0 +1,45 @@ -+// +build linux -+// +build !android -+// +build !no_openssl -+// +build !cmd_go_bootstrap -+// +build !msan ++// caller reports file and line number information about function invocations on ++// the calling goroutine's stack, in a form suitable for passing to C code. ++// The argument skip is the number of stack frames to ascend, with 0 identifying ++// the caller of caller. The return values report the file name and line number ++// within the file of the corresponding call. The returned file is a C string ++// with static storage duration. ++func caller(skip int) (file *C.char, line C.int) { ++ _, f, l, ok := runtime.Caller(skip + 1) ++ if !ok { ++ f = unknownFile ++ } ++ // The underlying bytes of the file string are null-terminated rodata with ++ // static lifetimes, so can be safely passed to C without worrying about ++ // leaking memory or use-after-free. ++ return (*C.char)(noescape(unsafe.Pointer(unsafe.StringData(f)))), C.int(l) ++} + -+#include "goopenssl.h" -+#include ++// cryptoMalloc allocates n bytes of memory on the OpenSSL heap, which may be ++// different from the heap which C.malloc allocates on. The allocated object ++// must be freed using cryptoFree. cryptoMalloc is equivalent to the ++// OPENSSL_malloc macro. ++// ++// Like C.malloc, this function is guaranteed to never return nil. If OpenSSL's ++// malloc indicates out of memory, it crashes the program. ++// ++// Only objects which the OpenSSL library will take ownership of (i.e. will be ++// freed by OPENSSL_free / CRYPTO_free) need to be allocated on the OpenSSL ++// heap. ++func cryptoMalloc(n int) unsafe.Pointer { ++ file, line := caller(1) ++ var p unsafe.Pointer ++ if vMajor == 1 && vMinor == 0 { ++ p = C.go_openssl_CRYPTO_malloc_legacy102(C.int(n), file, line) ++ } else { ++ p = C.go_openssl_CRYPTO_malloc(C.size_t(n), file, line) ++ } ++ if p == nil { ++ // Un-recover()-ably crash the program in the same manner as the ++ // C.malloc() wrapper function. ++ runtime_throw("openssl: CRYPTO_malloc failed") ++ } ++ return p ++} + -+static RAND_METHOD fake_rand; -+static const RAND_METHOD *old_rand; ++// cryptoFree frees an object allocated on the OpenSSL heap, which may be ++// different from the heap which C.malloc allocates on. cryptoFree is equivalent ++// to the OPENSSL_free macro. ++func cryptoFree(p unsafe.Pointer) { ++ if vMajor == 1 && vMinor == 0 { ++ C.go_openssl_CRYPTO_free_legacy102(p) ++ return ++ } ++ file, line := caller(1) ++ C.go_openssl_CRYPTO_free(p, file, line) ++} + -+int _goboringcrypto_stub_openssl_rand(void) { -+ /* save old rand method */ -+ if ((old_rand = _goboringcrypto_RAND_get_rand_method()) == NULL) -+ return 0; ++const wordBytes = bits.UintSize / 8 + -+ fake_rand.seed = old_rand->seed; -+ fake_rand.cleanup = old_rand->cleanup; -+ fake_rand.add = old_rand->add; -+ fake_rand.status = old_rand->status; -+ /* use own random function */ -+ fake_rand.bytes = fbytes; -+ fake_rand.pseudorand = old_rand->bytes; -+ /* set new RAND_METHOD */ -+ if (!_goboringcrypto_RAND_set_rand_method(&fake_rand)) -+ return 0; -+ return 1; ++// Reverse each limb of z. ++func (z BigInt) byteSwap() { ++ for i, d := range z { ++ var n uint = 0 ++ for j := 0; j < wordBytes; j++ { ++ n |= uint(byte(d)) << (8 * (wordBytes - j - 1)) ++ d >>= 8 ++ } ++ z[i] = n ++ } +} + -+int _goboringcrypto_restore_openssl_rand(void) { -+ if (!_goboringcrypto_RAND_set_rand_method(old_rand)) -+ return 0; -+ else -+ return 1; ++func wbase(b BigInt) *C.uchar { ++ if len(b) == 0 { ++ return nil ++ } ++ return (*C.uchar)(unsafe.Pointer(&b[0])) +} + -+int fbytes(unsigned char *buf, int num) { -+ // return old_rand->bytes(buf, num); -+ int i; -+ for (i = 0; i < num; i++) { -+ buf[i] = 1; -+ } -+ return 1; ++// bignum_st_1_0_2 is bignum_st (BIGNUM) memory layout in OpenSSL 1.0.2. ++type bignum_st_1_0_2 struct { ++ d unsafe.Pointer // Pointer to an array of BN_ULONG bit chunks ++ top C.int // Index of last used d +1 ++ dmax C.int ++ neg C.int ++ flags C.int +} -diff --git a/src/crypto/internal/boring/rand.go b/src/vendor/github.com/golang-fips/openssl-fips/openssl/rand.go -similarity index 71% -rename from src/crypto/internal/boring/rand.go -rename to src/vendor/github.com/golang-fips/openssl-fips/openssl/rand.go -index 7639c01909..b3668b8823 100644 ---- a/src/crypto/internal/boring/rand.go -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/rand.go -@@ -2,11 +2,12 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build boringcrypto && linux && (amd64 || arm64) && !android && !cmd_go_bootstrap && !msan -+//go:build linux && !android && !cmd_go_bootstrap && !msan && !no_openssl -+// +build linux,!android,!cmd_go_bootstrap,!msan,!no_openssl - --package boring -+package openssl - --// #include "goboringcrypto.h" -+// #include "goopenssl.h" - import "C" - import "unsafe" - -@@ -16,7 +17,7 @@ func (randReader) Read(b []byte) (int, error) { - // Note: RAND_bytes should never fail; the return value exists only for historical reasons. - // We check it even so. - if len(b) > 0 && C._goboringcrypto_RAND_bytes((*C.uint8_t)(unsafe.Pointer(&b[0])), C.size_t(len(b))) == 0 { -- return 0, fail("RAND_bytes") -+ return 0, NewOpenSSLError("RAND_bytes") - } - return len(b), nil - } -diff --git a/src/crypto/internal/boring/rsa.go b/src/vendor/github.com/golang-fips/openssl-fips/openssl/rsa.go -similarity index 52% -rename from src/crypto/internal/boring/rsa.go -rename to src/vendor/github.com/golang-fips/openssl-fips/openssl/rsa.go -index fa693ea319..75ba7a8a59 100644 ---- a/src/crypto/internal/boring/rsa.go -+++ b/src/vendor/github.com/golang-fips/openssl-fips/openssl/rsa.go -@@ -2,15 +2,15 @@ - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - --//go:build boringcrypto && linux && (amd64 || arm64) && !android && !cmd_go_bootstrap && !msan -+//go:build linux && !android && !cmd_go_bootstrap && !msan && !no_openssl -+// +build linux,!android,!cmd_go_bootstrap,!msan,!no_openssl - --package boring -+package openssl - --// #include "goboringcrypto.h" -+// #include "goopenssl.h" - import "C" - import ( - "crypto" -- "crypto/subtle" - "errors" - "hash" - "runtime" -@@ -25,12 +25,12 @@ func GenerateKeyRSA(bits int) (N, E, D, P, Q, Dp, Dq, Qinv BigInt, err error) { - - key := C._goboringcrypto_RSA_new() - if key == nil { -- return bad(fail("RSA_new")) -+ return bad(NewOpenSSLError("RSA_new failed")) - } - defer C._goboringcrypto_RSA_free(key) - - if C._goboringcrypto_RSA_generate_key_fips(key, C.int(bits), nil) == 0 { -- return bad(fail("RSA_generate_key_fips")) -+ return bad(NewOpenSSLError("RSA_generate_key_fips failed")) - } - - var n, e, d, p, q, dp, dq, qinv *C.GO_BIGNUM -@@ -48,12 +48,12 @@ type PublicKeyRSA struct { - func NewPublicKeyRSA(N, E BigInt) (*PublicKeyRSA, error) { - key := C._goboringcrypto_RSA_new() - if key == nil { -- return nil, fail("RSA_new") -- } -- if !bigToBn(&key.n, N) || -- !bigToBn(&key.e, E) { -- return nil, fail("BN_bin2bn") -+ return nil, NewOpenSSLError("RSA_new failed") - } -+ var n, e *C.GO_BIGNUM -+ n = bigToBN(N) -+ e = bigToBN(E) -+ C._goboringcrypto_RSA_set0_key(key, n, e, nil) - k := &PublicKeyRSA{_key: key} - runtime.SetFinalizer(k, (*PublicKeyRSA).finalize) - return k, nil -@@ -79,17 +79,23 @@ type PrivateKeyRSA struct { - func NewPrivateKeyRSA(N, E, D, P, Q, Dp, Dq, Qinv BigInt) (*PrivateKeyRSA, error) { - key := C._goboringcrypto_RSA_new() - if key == nil { -- return nil, fail("RSA_new") -- } -- if !bigToBn(&key.n, N) || -- !bigToBn(&key.e, E) || -- !bigToBn(&key.d, D) || -- !bigToBn(&key.p, P) || -- !bigToBn(&key.q, Q) || -- !bigToBn(&key.dmp1, Dp) || -- !bigToBn(&key.dmq1, Dq) || -- !bigToBn(&key.iqmp, Qinv) { -- return nil, fail("BN_bin2bn") -+ return nil, NewOpenSSLError("RSA_new failed") -+ } -+ var n, e, d, p, q, dp, dq, qinv *C.GO_BIGNUM -+ n = bigToBN(N) -+ e = bigToBN(E) -+ d = bigToBN(D) -+ C._goboringcrypto_RSA_set0_key(key, n, e, d) -+ if P != nil && Q != nil { -+ p = bigToBN(P) -+ q = bigToBN(Q) -+ C._goboringcrypto_RSA_set0_factors(key, p, q) -+ } -+ if Dp != nil && Dq != nil && Qinv != nil { -+ dp = bigToBN(Dp) -+ dq = bigToBN(Dq) -+ qinv = bigToBN(Qinv) -+ C._goboringcrypto_RSA_set0_crt_params(key, dp, dq, qinv) - } - k := &PrivateKeyRSA{_key: key} - runtime.SetFinalizer(k, (*PrivateKeyRSA).finalize) -@@ -109,7 +115,7 @@ func (k *PrivateKeyRSA) withKey(f func(*C.GO_RSA) C.int) C.int { - } - - func setupRSA(withKey func(func(*C.GO_RSA) C.int) C.int, -- padding C.int, h, mgfHash hash.Hash, label []byte, saltLen int, ch crypto.Hash, -+ padding C.int, h hash.Hash, label []byte, saltLen int, ch crypto.Hash, - init func(*C.GO_EVP_PKEY_CTX) C.int) (pkey *C.GO_EVP_PKEY, ctx *C.GO_EVP_PKEY_CTX, err error) { - defer func() { - if err != nil { -@@ -126,7 +132,7 @@ func setupRSA(withKey func(func(*C.GO_RSA) C.int) C.int, - - pkey = C._goboringcrypto_EVP_PKEY_new() - if pkey == nil { -- return nil, nil, fail("EVP_PKEY_new") -+ return nil, nil, NewOpenSSLError("EVP_PKEY_new failed") - } - if withKey(func(key *C.GO_RSA) C.int { - return C._goboringcrypto_EVP_PKEY_set1_RSA(pkey, key) -@@ -135,43 +141,47 @@ func setupRSA(withKey func(func(*C.GO_RSA) C.int) C.int, - } - ctx = C._goboringcrypto_EVP_PKEY_CTX_new(pkey, nil) - if ctx == nil { -- return nil, nil, fail("EVP_PKEY_CTX_new") -+ return nil, nil, NewOpenSSLError("EVP_PKEY_CTX_new failed") - } - if init(ctx) == 0 { -- return nil, nil, fail("EVP_PKEY_operation_init") -+ return nil, nil, NewOpenSSLError("EVP_PKEY_operation_init failed") - } - if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_padding(ctx, padding) == 0 { -- return nil, nil, fail("EVP_PKEY_CTX_set_rsa_padding") -+ return nil, nil, NewOpenSSLError("EVP_PKEY_CTX_set_rsa_padding failed") - } - if padding == C.GO_RSA_PKCS1_OAEP_PADDING { - md := hashToMD(h) - if md == nil { - return nil, nil, errors.New("crypto/rsa: unsupported hash function") - } -- mgfMD := hashToMD(mgfHash) -- if mgfMD == nil { -- return nil, nil, errors.New("crypto/rsa: unsupported hash function") -- } - if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) == 0 { -- return nil, nil, fail("EVP_PKEY_set_rsa_oaep_md") -- } -- if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, mgfMD) == 0 { -- return nil, nil, fail("EVP_PKEY_set_rsa_mgf1_md") -+ return nil, nil, NewOpenSSLError("EVP_PKEY_set_rsa_oaep_md failed") - } - // ctx takes ownership of label, so malloc a copy for BoringCrypto to free. -- clabel := (*C.uint8_t)(C._goboringcrypto_OPENSSL_malloc(C.size_t(len(label)))) -- if clabel == nil { -- return nil, nil, fail("OPENSSL_malloc") -+ var clabel *C.uint8_t -+ clabel = nil -+ // OpenSSL 1.1.1 does not take ownership of the label if the length is zero. -+ // Depending on the malloc implementation, if clabel is allocated with malloc(0), -+ // metadata for the size-zero allocation is never cleaned up, which is a memory leak. -+ // As such, we must only allocate clabel if the label is of non zero length. -+ if (len(label) > 0) || (openSSLVersion() > OPENSSL_VERSION_3_0_0) { -+ clabel = (*C.uint8_t)(C.malloc(C.size_t(len(label)))) -+ if clabel == nil { -+ return nil, nil, fail("OPENSSL_malloc") -+ } -+ copy((*[1 << 30]byte)(unsafe.Pointer(clabel))[:len(label)], label) - } -- copy((*[1 << 30]byte)(unsafe.Pointer(clabel))[:len(label)], label) -- if C._goboringcrypto_EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, clabel, C.size_t(len(label))) == 0 { -- return nil, nil, fail("EVP_PKEY_CTX_set0_rsa_oaep_label") -+ if C._goboringcrypto_EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, clabel, C.int(len(label))) != 1 { -+ if clabel != nil { -+ C.free(unsafe.Pointer(clabel)) -+ } -+ return nil, nil, NewOpenSSLError("EVP_PKEY_CTX_set0_rsa_oaep_label failed") - } - } - if padding == C.GO_RSA_PKCS1_PSS_PADDING { - if saltLen != 0 { - if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, C.int(saltLen)) == 0 { -- return nil, nil, fail("EVP_PKEY_set_rsa_pss_saltlen") -+ return nil, nil, NewOpenSSLError("EVP_PKEY_set_rsa_pss_saltlen failed") - } - } - md := cryptoHashToMD(ch) -@@ -179,7 +189,7 @@ func setupRSA(withKey func(func(*C.GO_RSA) C.int) C.int, - return nil, nil, errors.New("crypto/rsa: unsupported hash function") - } - if C._goboringcrypto_EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, md) == 0 { -- return nil, nil, fail("EVP_PKEY_set_rsa_mgf1_md") -+ return nil, nil, NewOpenSSLError("EVP_PKEY_set_rsa_mgf1_md failed") - } - } - -@@ -187,12 +197,12 @@ func setupRSA(withKey func(func(*C.GO_RSA) C.int) C.int, - } - - func cryptRSA(withKey func(func(*C.GO_RSA) C.int) C.int, -- padding C.int, h, mgfHash hash.Hash, label []byte, saltLen int, ch crypto.Hash, -+ padding C.int, h hash.Hash, label []byte, saltLen int, ch crypto.Hash, - init func(*C.GO_EVP_PKEY_CTX) C.int, - crypt func(*C.GO_EVP_PKEY_CTX, *C.uint8_t, *C.size_t, *C.uint8_t, C.size_t) C.int, - in []byte) ([]byte, error) { - -- pkey, ctx, err := setupRSA(withKey, padding, h, mgfHash, label, saltLen, ch, init) -+ pkey, ctx, err := setupRSA(withKey, padding, h, label, saltLen, ch, init) - if err != nil { - return nil, err - } -@@ -201,37 +211,37 @@ func cryptRSA(withKey func(func(*C.GO_RSA) C.int) C.int, - - var outLen C.size_t - if crypt(ctx, nil, &outLen, base(in), C.size_t(len(in))) == 0 { -- return nil, fail("EVP_PKEY_decrypt/encrypt") -+ return nil, NewOpenSSLError("EVP_PKEY_decrypt/encrypt failed") - } - out := make([]byte, outLen) -- if crypt(ctx, base(out), &outLen, base(in), C.size_t(len(in))) == 0 { -- return nil, fail("EVP_PKEY_decrypt/encrypt") -+ if crypt(ctx, base(out), &outLen, base(in), C.size_t(len(in))) <= 0 { -+ return nil, NewOpenSSLError("EVP_PKEY_decrypt/encrypt failed") - } - return out[:outLen], nil - } - --func DecryptRSAOAEP(h, mgfHash hash.Hash, priv *PrivateKeyRSA, ciphertext, label []byte) ([]byte, error) { -- return cryptRSA(priv.withKey, C.GO_RSA_PKCS1_OAEP_PADDING, h, mgfHash, label, 0, 0, decryptInit, decrypt, ciphertext) -+func DecryptRSAOAEP(h hash.Hash, priv *PrivateKeyRSA, ciphertext, label []byte) ([]byte, error) { -+ return cryptRSA(priv.withKey, C.GO_RSA_PKCS1_OAEP_PADDING, h, label, 0, 0, decryptInit, decrypt, ciphertext) - } - --func EncryptRSAOAEP(h, mgfHash hash.Hash, pub *PublicKeyRSA, msg, label []byte) ([]byte, error) { -- return cryptRSA(pub.withKey, C.GO_RSA_PKCS1_OAEP_PADDING, h, mgfHash, label, 0, 0, encryptInit, encrypt, msg) -+func EncryptRSAOAEP(h hash.Hash, pub *PublicKeyRSA, msg, label []byte) ([]byte, error) { -+ return cryptRSA(pub.withKey, C.GO_RSA_PKCS1_OAEP_PADDING, h, label, 0, 0, encryptInit, encrypt, msg) - } - - func DecryptRSAPKCS1(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) { -- return cryptRSA(priv.withKey, C.GO_RSA_PKCS1_PADDING, nil, nil, nil, 0, 0, decryptInit, decrypt, ciphertext) -+ return cryptRSA(priv.withKey, C.GO_RSA_PKCS1_PADDING, nil, nil, 0, 0, decryptInit, decrypt, ciphertext) - } - - func EncryptRSAPKCS1(pub *PublicKeyRSA, msg []byte) ([]byte, error) { -- return cryptRSA(pub.withKey, C.GO_RSA_PKCS1_PADDING, nil, nil, nil, 0, 0, encryptInit, encrypt, msg) -+ return cryptRSA(pub.withKey, C.GO_RSA_PKCS1_PADDING, nil, nil, 0, 0, encryptInit, encrypt, msg) - } - - func DecryptRSANoPadding(priv *PrivateKeyRSA, ciphertext []byte) ([]byte, error) { -- return cryptRSA(priv.withKey, C.GO_RSA_NO_PADDING, nil, nil, nil, 0, 0, decryptInit, decrypt, ciphertext) -+ return cryptRSA(priv.withKey, C.GO_RSA_NO_PADDING, nil, nil, 0, 0, decryptInit, decrypt, ciphertext) - } - - func EncryptRSANoPadding(pub *PublicKeyRSA, msg []byte) ([]byte, error) { -- return cryptRSA(pub.withKey, C.GO_RSA_NO_PADDING, nil, nil, nil, 0, 0, encryptInit, encrypt, msg) -+ return cryptRSA(pub.withKey, C.GO_RSA_NO_PADDING, nil, nil, 0, 0, encryptInit, encrypt, msg) - } - - // These dumb wrappers work around the fact that cgo functions cannot be used as values directly. -@@ -252,6 +262,10 @@ func encrypt(ctx *C.GO_EVP_PKEY_CTX, out *C.uint8_t, outLen *C.size_t, in *C.uin - return C._goboringcrypto_EVP_PKEY_encrypt(ctx, out, outLen, in, inLen) - } - -+// These should match crypto/rsa/pss.go -+const saltLengthAuto = 0 -+const saltLengthEqualsHash = -1 + - var invalidSaltLenErr = errors.New("crypto/rsa: PSSOptions.SaltLength cannot be negative") - - func SignRSAPSS(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte, saltLen int) ([]byte, error) { -@@ -259,27 +273,24 @@ func SignRSAPSS(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte, saltLen int) - if md == nil { - return nil, errors.New("crypto/rsa: unsupported hash function") - } -- -- // A salt length of -2 is valid in BoringSSL, but not in crypto/rsa, so reject -- // it, and lengths < -2, before we convert to the BoringSSL sentinel values. -- if saltLen <= -2 { -- return nil, invalidSaltLenErr -- } -- -- // BoringSSL uses sentinel salt length values like we do, but the values don't -- // fully match what we use. We both use -1 for salt length equal to hash length, -- // but BoringSSL uses -2 to mean maximal size where we use 0. In the latter -- // case convert to the BoringSSL version. -- if saltLen == 0 { -- saltLen = -2 -+ switch saltLen { -+ case saltLengthAuto: -+ saltLen = C.GO_RSA_PSS_SALTLEN_AUTO -+ case saltLengthEqualsHash: -+ saltLen = C.GO_RSA_PSS_SALTLEN_DIGEST -+ default: -+ // If we get here saltLen is either > 0 or < -1, in the -+ // latter case we fail out. -+ if saltLen <= 0 { -+ return nil, invalidSaltLenErr ++func bigToBN(x BigInt) C.GO_BIGNUM_PTR { ++ if len(x) == 0 { ++ return nil ++ } ++ ++ if vMajor == 1 && vMinor == 0 { ++ // OpenSSL 1.0.x does not export bn_lebin2bn on all platforms, ++ // so we have to emulate it. ++ bn := C.go_openssl_BN_new() ++ if bn == nil { ++ return nil + } - } -- - var out []byte -- var outLen C.size_t -+ var outLen C.uint - if priv.withKey(func(key *C.GO_RSA) C.int { - out = make([]byte, C._goboringcrypto_RSA_size(key)) -- return C._goboringcrypto_RSA_sign_pss_mgf1(key, &outLen, base(out), C.size_t(len(out)), -- base(hashed), C.size_t(len(hashed)), md, nil, C.int(saltLen)) -+ return C._goboringcrypto_RSA_sign_pss_mgf1(key, &outLen, base(out), C.uint(len(out)), -+ base(hashed), C.uint(len(hashed)), md, nil, C.int(saltLen)) - }) == 0 { - return nil, fail("RSA_sign_pss_mgf1") - } -@@ -292,88 +303,133 @@ func VerifyRSAPSS(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte, saltLen - if md == nil { - return errors.New("crypto/rsa: unsupported hash function") - } -- -- // A salt length of -2 is valid in BoringSSL, but not in crypto/rsa, so reject -- // it, and lengths < -2, before we convert to the BoringSSL sentinel values. -- if saltLen <= -2 { -- return invalidSaltLenErr -- } -- -- // BoringSSL uses sentinel salt length values like we do, but the values don't -- // fully match what we use. We both use -1 for salt length equal to hash length, -- // but BoringSSL uses -2 to mean maximal size where we use 0. In the latter -- // case convert to the BoringSSL version. -- if saltLen == 0 { -- saltLen = -2 -+ switch saltLen { -+ case saltLengthAuto: -+ saltLen = C.GO_RSA_PSS_SALTLEN_AUTO -+ case saltLengthEqualsHash: -+ saltLen = C.GO_RSA_PSS_SALTLEN_DIGEST -+ default: -+ // If we get here saltLen is either > 0 or < -1, in the -+ // latter case we fail out. -+ if saltLen <= 0 { -+ return invalidSaltLenErr ++ if C.go_openssl_bn_expand2(bn, C.int(len(x))) == nil { ++ C.go_openssl_BN_free(bn) ++ panic(newOpenSSLError("BN_expand2")) + } - } -- - if pub.withKey(func(key *C.GO_RSA) C.int { -- return C._goboringcrypto_RSA_verify_pss_mgf1(key, base(hashed), C.size_t(len(hashed)), -- md, nil, C.int(saltLen), base(sig), C.size_t(len(sig))) -+ return C._goboringcrypto_RSA_verify_pss_mgf1(key, base(hashed), C.uint(len(hashed)), -+ md, nil, C.int(saltLen), base(sig), C.uint(len(sig))) - }) == 0 { - return fail("RSA_verify_pss_mgf1") - } - return nil - } - --func SignRSAPKCS1v15(priv *PrivateKeyRSA, h crypto.Hash, hashed []byte) ([]byte, error) { -- if h == 0 { -- // No hashing. -+func SignRSAPKCS1v15(priv *PrivateKeyRSA, h crypto.Hash, msg []byte, msgIsHashed bool) ([]byte, error) { -+ if h == 0 && ExecutingTest() { -+ return signRSAPKCS1v15Raw(priv, msg, C._goboringcrypto_EVP_md_null()) ++ // The bytes of a BigInt are laid out in memory in the same order as a ++ // BIGNUM, regardless of host endianness. ++ bns := (*bignum_st_1_0_2)(unsafe.Pointer(bn)) ++ d := unsafe.Slice((*uint)(bns.d), len(x)) ++ bns.top = C.int(copy(d, x)) ++ return bn ++ } ++ ++ if nativeEndian == binary.BigEndian { ++ z := make(BigInt, len(x)) ++ copy(z, x) ++ z.byteSwap() ++ x = z ++ } ++ // Limbs are always ordered in LSB first, so we can safely apply ++ // BN_lebin2bn regardless of host endianness. ++ return C.go_openssl_BN_lebin2bn(wbase(x), C.int(len(x)*wordBytes), nil) ++} ++ ++func bnToBig(bn C.GO_BIGNUM_PTR) BigInt { ++ if bn == nil { ++ return nil + } + -+ md := cryptoHashToMD(h) -+ if md == nil { -+ return nil, errors.New("crypto/rsa: unsupported hash function: " + strconv.Itoa(int(h))) ++ if vMajor == 1 && vMinor == 0 { ++ // OpenSSL 1.0.x does not export bn_bn2lebinpad on all platforms, ++ // so we have to emulate it. ++ bns := (*bignum_st_1_0_2)(unsafe.Pointer(bn)) ++ d := unsafe.Slice((*uint)(bns.d), bns.top) ++ x := make(BigInt, len(d)) ++ copy(x, d) ++ return x + } + -+ if msgIsHashed { - var out []byte -- var outLen C.size_t -+ var outLen C.uint -+ PanicIfStrictFIPS("You must provide a raw unhashed message for PKCS1v15 signing and use HashSignPKCS1v15 instead of SignPKCS1v15") -+ nid := C._goboringcrypto_EVP_MD_type(md) - if priv.withKey(func(key *C.GO_RSA) C.int { - out = make([]byte, C._goboringcrypto_RSA_size(key)) -- return C._goboringcrypto_RSA_sign_raw(key, &outLen, base(out), C.size_t(len(out)), -- base(hashed), C.size_t(len(hashed)), C.GO_RSA_PKCS1_PADDING) -+ return C._goboringcrypto_RSA_sign(nid, base(msg), C.uint(len(msg)), base(out), &outLen, key) - }) == 0 { -- return nil, fail("RSA_sign_raw") -+ return nil, NewOpenSSLError("RSA_sign") - } -+ runtime.KeepAlive(priv) - return out[:outLen], nil - } - -- md := cryptoHashToMD(h) -- if md == nil { -- return nil, errors.New("crypto/rsa: unsupported hash function: " + strconv.Itoa(int(h))) -+ var out []byte -+ var outLen C.size_t ++ // Limbs are always ordered in LSB first, so we can safely apply ++ // BN_bn2lebinpad regardless of host endianness. ++ x := make(BigInt, C.go_openssl_BN_num_bits(bn)) ++ if C.go_openssl_BN_bn2lebinpad(bn, wbase(x), C.int(len(x)*wordBytes)) == 0 { ++ panic("openssl: bignum conversion failed") ++ } ++ if nativeEndian == binary.BigEndian { ++ x.byteSwap() ++ } ++ return x ++} + -+ if priv.withKey(func(key *C.GO_RSA) C.int { -+ return C._goboringcrypto_EVP_RSA_sign(md, base(msg), C.uint(len(msg)), base(out), &outLen, key) -+ }) == 0 { -+ return nil, NewOpenSSLError("RSA_sign") - } -- nid := C._goboringcrypto_EVP_MD_type(md) -+ return out[:outLen], nil ++func bnNumBytes(bn C.GO_BIGNUM_PTR) int { ++ return (int(C.go_openssl_BN_num_bits(bn)) + 7) / 8 +} + -+func signRSAPKCS1v15Raw(priv *PrivateKeyRSA, msg []byte, md *C.GO_EVP_MD) ([]byte, error) { - var out []byte -- var outLen C.uint -+ var outLen C.size_t -+ PanicIfStrictFIPS("You must provide a raw unhashed message for PKCS1v15 signing and use HashSignPKCS1v15 instead of SignPKCS1v15") ++// bnToBinPad converts the absolute value of bn into big-endian form and stores ++// it at to, padding with zeroes if necessary. If len(to) is not large enough to ++// hold the result, an error is returned. ++func bnToBinPad(bn C.GO_BIGNUM_PTR, to []byte) error { ++ if vMajor == 1 && vMinor == 0 { ++ // OpenSSL 1.0.x does not export bn_bn2binpad on all platforms, ++ // so we have to emulate it. ++ n := bnNumBytes(bn) ++ pad := len(to) - n ++ if pad < 0 { ++ return errors.New("openssl: destination buffer too small") ++ } ++ for i := 0; i < pad; i++ { ++ to[i] = 0 ++ } ++ if int(C.go_openssl_BN_bn2bin(bn, base(to[pad:]))) != n { ++ return errors.New("openssl: BN_bn2bin short write") ++ } ++ return nil ++ } + - if priv.withKey(func(key *C.GO_RSA) C.int { - out = make([]byte, C._goboringcrypto_RSA_size(key)) -- return C._goboringcrypto_RSA_sign(nid, base(hashed), C.uint(len(hashed)), -- base(out), &outLen, key) -+ outLen = C.size_t(len(out)) -+ return C._goboringcrypto_EVP_sign_raw(md, nil, base(msg), -+ C.size_t(len(msg)), base(out), &outLen, key) - }) == 0 { -- return nil, fail("RSA_sign") -+ return nil, NewOpenSSLError("RSA_sign") - } -+ runtime.KeepAlive(priv) - return out[:outLen], nil - } - --func VerifyRSAPKCS1v15(pub *PublicKeyRSA, h crypto.Hash, hashed, sig []byte) error { -- if h == 0 { -- var out []byte -- var outLen C.size_t -+func VerifyRSAPKCS1v15(pub *PublicKeyRSA, h crypto.Hash, msg, sig []byte, msgIsHashed bool) error { -+ if h == 0 && ExecutingTest() { -+ return verifyRSAPKCS1v15Raw(pub, msg, sig) ++ if C.go_openssl_BN_bn2binpad(bn, base(to), C.int(len(to))) < 0 { ++ return newOpenSSLError("BN_bn2binpad") + } ++ return nil ++} + -+ md := cryptoHashToMD(h) ++func CheckLeaks() { ++ C.go_openssl_do_leak_check() ++} +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/pbkdf2.go b/src/vendor/github.com/golang-fips/openssl/v2/pbkdf2.go +new file mode 100644 +index 0000000000..a895eab2d5 +--- /dev/null ++++ b/src/vendor/github.com/golang-fips/openssl/v2/pbkdf2.go +@@ -0,0 +1,28 @@ ++//go:build !cmd_go_bootstrap ++ ++package openssl ++ ++// #include "goopenssl.h" ++import "C" ++import ( ++ "errors" ++ "hash" ++) ++ ++func PBKDF2(password, salt []byte, iter, keyLen int, h func() hash.Hash) ([]byte, error) { ++ md := hashToMD(h()) + if md == nil { -+ return errors.New("crypto/rsa: unsupported hash function") ++ return nil, errors.New("unsupported hash function") ++ } ++ if len(password) == 0 && vMajor == 1 && vMinor == 0 { ++ // x/crypto/pbkdf2 supports empty passwords, but OpenSSL 1.0.2 ++ // does not. As a workaround, we pass an "empty" password. ++ password = make([]byte, C.GO_EVP_MAX_MD_SIZE) ++ } ++ out := make([]byte, keyLen) ++ ok := C.go_openssl_PKCS5_PBKDF2_HMAC(sbase(password), C.int(len(password)), base(salt), C.int(len(salt)), C.int(iter), md, C.int(keyLen), base(out)) ++ if ok != 1 { ++ return nil, newOpenSSLError("PKCS5_PBKDF2_HMAC") + } ++ return out, nil ++} +diff --git a/src/vendor/github.com/golang-fips/openssl/v2/port_evp_md5_sha1.c b/src/vendor/github.com/golang-fips/openssl/v2/port_evp_md5_sha1.c +new file mode 100644 +index 0000000000..50d49b1f10 +--- /dev/null ++++ b/src/vendor/github.com/golang-fips/openssl/v2/port_evp_md5_sha1.c +@@ -0,0 +1,126 @@ ++// The following is a partial backport of crypto/evp/m_md5_sha1.c, ++// commit cbc8a839959418d8a2c2e3ec6bdf394852c9501e on the ++// OpenSSL_1_1_0-stable branch. The ctrl function has been removed. + -+ if pub.withKey(func(key *C.GO_RSA) C.int { -+ size := int(C._goboringcrypto_RSA_size(key)) -+ if len(sig) < size { -======= ++/* ++ * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. ++ * ++ * Licensed under the OpenSSL license (the "License"). You may not use ++ * this file except in compliance with the License. You can obtain a copy ++ * in the file LICENSE in the source distribution or at ++ * https://www.openssl.org/source/license.html ++ */ ++ ++#include "goopenssl.h" ++ ++#define NID_md5_sha1 114 ++ ++#define MD5_CBLOCK 64 ++#define MD5_LBLOCK (MD5_CBLOCK/4) ++#define MD5_DIGEST_LENGTH 16 ++#define SHA_LBLOCK 16 ++#define SHA_DIGEST_LENGTH 20 ++ ++#define EVP_PKEY_NULL_method NULL,NULL,{0,0,0,0} ++ ++// Change: MD5_LONG and SHA_LONG have been expanded to unsigned int, ++// which is always 32 bits. This avoids adding some obscure logic ++// to support 16-bit platforms. ++ ++# define MD5_LONG unsigned int ++# define SHA_LONG unsigned int ++ ++typedef struct env_md_st EVP_MD; ++typedef struct env_md_ctx_st EVP_MD_CTX; ++ ++struct env_md_ctx_st { ++ void *digest; ++ void *engine; ++ unsigned long flags; ++ void *md_data; ++ void *pctx; ++ void *update; ++} /* EVP_MD_CTX */ ; ++ ++struct env_md_st { ++ int type; ++ int pkey_type; ++ int md_size; ++ unsigned long flags; ++ int (*init) (EVP_MD_CTX *ctx); ++ int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count); ++ int (*final) (EVP_MD_CTX *ctx, unsigned char *md); ++ void *copy; ++ void *cleanup; ++ void *sign; ++ void *verify; ++ int required_pkey_type[5]; ++ int block_size; ++ int ctx_size; ++ void *md_ctrl; ++} /* EVP_MD */ ; ++ ++typedef struct MD5state_st { ++ MD5_LONG A, B, C, D; ++ MD5_LONG Nl, Nh; ++ MD5_LONG data[MD5_LBLOCK]; ++ MD5_LONG num; ++} MD5_CTX; ++ ++typedef struct SHAstate_st { ++ SHA_LONG h0, h1, h2, h3, h4; ++ SHA_LONG Nl, Nh; ++ SHA_LONG data[SHA_LBLOCK]; ++ SHA_LONG num; ++} SHA_CTX; ++ ++struct md5_sha1_ctx { ++ MD5_CTX md5; ++ SHA_CTX sha1; ++}; ++ ++static int md5_sha1_init(EVP_MD_CTX *ctx) { ++ struct md5_sha1_ctx *mctx = ctx->md_data; ++ if (!go_openssl_MD5_Init(&mctx->md5)) ++ return 0; ++ return go_openssl_SHA1_Init(&mctx->sha1); ++} ++ ++static int md5_sha1_update(EVP_MD_CTX *ctx, const void *data, ++ size_t count) { ++ struct md5_sha1_ctx *mctx = ctx->md_data; ++ if (!go_openssl_MD5_Update(&mctx->md5, data, count)) ++ return 0; ++ return go_openssl_SHA1_Update(&mctx->sha1, data, count); ++} ++ ++static int md5_sha1_final(EVP_MD_CTX *ctx, unsigned char *md) { ++ struct md5_sha1_ctx *mctx = ctx->md_data; ++ if (!go_openssl_MD5_Final(md, &mctx->md5)) ++ return 0; ++ return go_openssl_SHA1_Final(md + MD5_DIGEST_LENGTH, &mctx->sha1); ++} ++ ++// Change: Removed: ++// static int ctrl(EVP_MD_CTX *ctx, int cmd, int mslen, void *ms) ++ ++static const EVP_MD md5_sha1_md = { ++ NID_md5_sha1, ++ NID_md5_sha1, ++ MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, ++ 0, ++ md5_sha1_init, ++ md5_sha1_update, ++ md5_sha1_final, ++ NULL, ++ NULL, ++ EVP_PKEY_NULL_method, // Change: inserted ++ MD5_CBLOCK, ++ sizeof(EVP_MD *) + sizeof(struct md5_sha1_ctx), ++ NULL, // Change: was ctrl ++}; ++ ++// Change: Apply name mangling. +const GO_EVP_MD_PTR go_openssl_EVP_md5_sha1_backport(void) { + return (const GO_EVP_MD_PTR)&md5_sha1_md; +} @@ -35359,7 +7493,6 @@ index 0000000000..5aef65b84f + if pub.withKey(func(pkey C.GO_EVP_PKEY_PTR) C.int { + size := C.go_openssl_EVP_PKEY_get_size(pkey) + if len(sig) < int(size) { ->>>>>>> 0023bf4c7a (rebase) + return 0 + } + return 1 @@ -35367,6 +7500,7 @@ index 0000000000..5aef65b84f + return errors.New("crypto/rsa: verification error") + } <<<<<<< HEAD +<<<<<<< HEAD + + if msgIsHashed { + PanicIfStrictFIPS("You must provide a raw unhashed message for PKCS1v15 verification and use HashVerifyPKCS1v15 instead of VerifyPKCS1v15") @@ -35695,6 +7829,8 @@ index 4de656b0e8..273a9d49d6 100644 ======= >>>>>>> 3d69c3eee6 (Update to latest openssl/v2) ======= +======= +>>>>>>> 3004231545 (fix config, regen 001) + return evpVerify(pub.withKey, C.GO_RSA_PKCS1_PADDING, 0, h, sig, hashed) +} + @@ -37070,4 +9206,3 @@ index 2b5f965f8f..4d1ce8b9cf 100644 # golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d ## explicit; go 1.17 golang.org/x/crypto/chacha20 ->>>>>>> 0023bf4c7a (rebase)