Compare commits

...
4 Commits
Author SHA1 Message Date
Gopher Robot 8e447d8cc5 go.mod: update golang.org/x dependencies
Update golang.org/x dependencies to their latest tagged versions.
Once this CL is submitted, and post-submit testing succeeds on all
first-class ports across all supported Go versions, this repository
will be tagged with its next minor version.

Change-Id: If19e251a79af033583e6968766b7a831741cebb7
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/502518
Reviewed-by: Heschi Kreinick <heschi@google.com>
Run-TryBot: Gopher Robot <gobot@golang.org>
Reviewed-by: Carlos Amedee <carlos@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Gopher Robot <gobot@golang.org>
2023-06-12 19:51:08 +00:00
Heschi Kreinick 22c9997952 go.mod: tell x repo tagging to ignore dep on net
CL 475438 introduced a cycle between net and crypto. This direction is
less important, so have the tagging process ignore it.

Change-Id: Ie424fef0238702a5a16aba79bb60f86f39dc66eb
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/502595
Auto-Submit: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
Run-TryBot: Heschi Kreinick <heschi@google.com>
2023-06-12 17:20:30 +00:00
Roland Shoemaker d0b316056b x509roots: add new module
Adds the nss parser, under x509roots/nss, and the fallback
module/package, with the initial generated bundle.

Fixes golang/go#57792

Change-Id: Iebb1052e49126fa5baba1236f4ebc8dd8a823179
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/462036
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
Auto-Submit: Roland Shoemaker <roland@golang.org>
2023-06-09 17:23:14 +00:00
Stefan Klein 16222386f4 Add support for "hmac-sha2-512-etm@openssh.com"
Change-Id: I0203881afd7ad72e68f76650817451d7e292c91b
GitHub-Last-Rev: 42b4119e1987e7a46aa06a2b142d5fd3ef6f216a
GitHub-Pull-Request: golang/crypto#129
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/226982
Run-TryBot: Han-Wen Nienhuys <hanwen@google.com>
Reviewed-by: Han-Wen Nienhuys <hanwen@google.com>
Auto-Submit: Han-Wen Nienhuys <hanwen@google.com>
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2023-06-05 16:42:04 +00:00
10 changed files with 5403 additions and 8 deletions
+4 -4
View File
@@ -3,9 +3,9 @@ module golang.org/x/crypto
go 1.17
require (
golang.org/x/net v0.10.0
golang.org/x/sys v0.8.0
golang.org/x/term v0.8.0
golang.org/x/net v0.10.0 // tagx:ignore
golang.org/x/sys v0.9.0
golang.org/x/term v0.9.0
)
require golang.org/x/text v0.9.0 // indirect
require golang.org/x/text v0.10.0 // indirect
+6 -3
View File
@@ -18,19 +18,22 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28=
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+1 -1
View File
@@ -85,7 +85,7 @@ var supportedHostKeyAlgos = []string{
// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
// because they have reached the end of their useful life.
var supportedMACs = []string{
"hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
"hmac-sha2-512-etm@openssh.com", "hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
}
var supportedCompressions = []string{compressionNone}
+4
View File
@@ -10,6 +10,7 @@ import (
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"hash"
)
@@ -46,6 +47,9 @@ func (t truncatingMAC) Size() int {
func (t truncatingMAC) BlockSize() int { return t.hmac.BlockSize() }
var macModes = map[string]*macMode{
"hmac-sha2-512-etm@openssh.com": {64, true, func(key []byte) hash.Hash {
return hmac.New(sha512.New, key)
}},
"hmac-sha2-256-etm@openssh.com": {32, true, func(key []byte) hash.Hash {
return hmac.New(sha256.New, key)
}},
File diff suppressed because it is too large Load Diff
+32
View File
@@ -0,0 +1,32 @@
// 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.
//go:build go1.20
// +build go1.20
// Package fallback embeds a set of fallback X.509 trusted roots in the
// application by automatically invoking [x509.SetFallbackRoots]. This allows
// the application to work correctly even if the operating system does not
// provide a verifier or system roots pool.
//
// To use it, import the package like
//
// import _ "golang.org/x/crypto/x509roots/fallback"
//
// It's recommended that only binaries, and not libraries, import this package.
//
// This package must be kept up to date for security and compatibility reasons.
// Use govulncheck to be notified of when new versions of the package are
// available.
package fallback
import "crypto/x509"
func init() {
p := x509.NewCertPool()
for _, c := range bundle {
p.AddCert(c)
}
x509.SetFallbackRoots(p)
}
+3
View File
@@ -0,0 +1,3 @@
module golang.org/x/crypto/x509roots/fallback
go 1.20
+136
View File
@@ -0,0 +1,136 @@
// 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.
//go:build gen
// +build gen
//go:generate go run gen_fallback_bundle.go
package main
import (
"bytes"
"crypto/sha256"
"encoding/pem"
"flag"
"fmt"
"go/format"
"io"
"log"
"net/http"
"os"
"sort"
"time"
"golang.org/x/crypto/x509roots/nss"
)
const tmpl = `// Code generated by gen.go at %s; DO NOT EDIT.
// list hash: %x
package fallback
import "crypto/x509"
import "encoding/pem"
func mustParse(b []byte) []*x509.Certificate {
var roots []*x509.Certificate
for len(b) > 0 {
var block *pem.Block
block, b = pem.Decode(b)
if block == nil {
break
}
if block.Type != "CERTIFICATE" {
panic("unexpected PEM block type: "+block.Type)
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
panic(err)
}
roots = append(roots, cert)
}
return roots
}
var bundle = mustParse([]byte(pemRoots))
// Format of the PEM list is:
// * Subject common name
// * SHA256 hash
// * PEM block
`
var (
certDataURL = flag.String("certdata-url", "https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt", "URL to the raw certdata.txt file to parse (only one of certdata-url and certdata-path may be specified)")
certDataPath = flag.String("certdata-path", "", "Path to the NSS certdata.txt file to parse (only one of certdata-url and certdata-path may be specified)")
output = flag.String("output", "fallback/bundle.go", "Path to file to write output to")
)
func main() {
flag.Parse()
if *certDataPath != "" && *certDataURL != "" {
log.Fatal("Only one of --certdata-url and --certdata-path may be supplied")
}
var certdata io.Reader
if *certDataPath != "" {
f, err := os.Open(*certDataPath)
if err != nil {
log.Fatalf("unable to open %q: %s", *certDataPath, err)
}
defer f.Close()
certdata = f
} else {
resp, err := http.Get(*certDataURL)
if err != nil {
log.Fatalf("failed to request %q: %s", *certDataURL, err)
}
defer resp.Body.Close()
certdata = resp.Body
}
certs, err := nss.Parse(certdata)
if err != nil {
log.Fatalf("failed to parse %q: %s", *certDataPath, err)
}
sort.Slice(certs, func(i, j int) bool {
return certs[i].X509.Subject.String() < certs[j].X509.Subject.String()
})
h := sha256.New()
for _, c := range certs {
h.Write(c.X509.Raw)
}
listHash := h.Sum(nil)
b := bytes.NewBuffer(nil)
b.Write([]byte(fmt.Sprintf(tmpl, time.Now().Format(time.RFC1123), listHash)))
b.Write([]byte("const pemRoots = `\n"))
for _, c := range certs {
if len(c.Constraints) > 0 {
// Until the constrained roots API lands, skip anything that has any
// additional constraints. Once that API is available, we can add
// build constraints that support both the current version and the
// new version.
continue
}
b.Write([]byte(fmt.Sprintf("# %s\n# %x\n", c.X509.Subject.String(), sha256.Sum256(c.X509.Raw))))
pem.Encode(b, &pem.Block{Type: "CERTIFICATE", Bytes: c.X509.Raw})
}
b.Write([]byte("`\n"))
formatted, err := format.Source(b.Bytes())
if err != nil {
log.Fatalf("failed to format source: %s", err)
}
if err := os.WriteFile(*output, formatted, 0644); err != nil {
log.Fatalf("failed to write to %q: %s", *output, err)
}
}
+259
View File
@@ -0,0 +1,259 @@
// 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 nss provides functionality for parsing NSS certdata.txt
// formatted certificate lists and extracting serverAuth roots. Most
// users should not use this package themselves, and should instead
// rely on the golang.org/x/crypto/x509roots/fallback package which
// calls x509.SetFallbackRoots on a pre-parsed set of roots.
package nss
import (
"bufio"
"bytes"
"crypto/sha1"
"crypto/x509"
"errors"
"fmt"
"io"
"strconv"
"strings"
"time"
)
// Constraint is a constraint to be applied to a certificate or
// certificate chain.
type Constraint interface {
Kind() Kind
}
// Kind is the constraint kind, using the NSS enumeration.
type Kind int
const (
CKA_NSS_SERVER_DISTRUST_AFTER Kind = iota
)
// DistrustAfter is a Constraint that indicates a certificate has a
// CKA_NSS_SERVER_DISTRUST_AFTER constraint. This constraint defines a date
// after which any certificate issued which is rooted by the constrained
// certificate should be distrusted.
type DistrustAfter time.Time
func (DistrustAfter) Kind() Kind {
return CKA_NSS_SERVER_DISTRUST_AFTER
}
// A Certificate represents a single trusted serverAuth certificate in the NSS
// certdata.txt list and any constraints that should be applied to chains
// rooted by it.
type Certificate struct {
// Certificate is the parsed certificate
X509 *x509.Certificate
// Constraints contains a list of additional constraints that should be
// applied to any certificates that chain to Certificate. If there are
// any unknown constraints in the slice, Certificate should not be
// trusted.
Constraints []Constraint
}
func parseMulitLineOctal(s *bufio.Scanner) ([]byte, error) {
buf := bytes.NewBuffer(nil)
for s.Scan() {
if s.Text() == "END" {
break
}
b, err := strconv.Unquote(fmt.Sprintf("\"%s\"", s.Text()))
if err != nil {
return nil, err
}
buf.Write([]byte(b))
}
return buf.Bytes(), nil
}
type certObj struct {
c *x509.Certificate
DistrustAfter *time.Time
}
func parseCertClass(s *bufio.Scanner) ([sha1.Size]byte, *certObj, error) {
var h [sha1.Size]byte
co := &certObj{}
for s.Scan() {
l := s.Text()
if l == "" {
// assume an empty newline indicates the end of a block
break
}
if strings.HasPrefix(l, "CKA_VALUE") {
b, err := parseMulitLineOctal(s)
if err != nil {
return h, nil, err
}
co.c, err = x509.ParseCertificate(b)
if err != nil {
return h, nil, err
}
h = sha1.Sum(b)
} else if strings.HasPrefix(l, "CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_FALSE") {
// we don't want it
return h, nil, nil
} else if l == "CKA_NSS_SERVER_DISTRUST_AFTER MULTILINE_OCTAL" {
dateStr, err := parseMulitLineOctal(s)
if err != nil {
return h, nil, err
}
t, err := time.Parse("060102150405Z0700", string(dateStr))
if err != nil {
return h, nil, err
}
co.DistrustAfter = &t
}
}
if co.c == nil {
return h, nil, errors.New("malformed CKO_CERTIFICATE object")
}
return h, co, nil
}
type trustObj struct {
trusted bool
}
func parseTrustClass(s *bufio.Scanner) ([sha1.Size]byte, *trustObj, error) {
var h [sha1.Size]byte
to := &trustObj{trusted: false} // default to untrusted
for s.Scan() {
l := s.Text()
if l == "" {
// assume an empty newline indicates the end of a block
break
}
if l == "CKA_CERT_SHA1_HASH MULTILINE_OCTAL" {
hash, err := parseMulitLineOctal(s)
if err != nil {
return h, nil, err
}
copy(h[:], hash)
} else if l == "CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR" {
// we only care about server auth
to.trusted = true
}
}
return h, to, nil
}
// Parse parses a NSS certdata.txt formatted file, returning only
// trusted serverAuth roots, as well as any additional constraints. This parser
// is very opinionated, only returning roots that are currently trusted for
// serverAuth. As such roots returned by this package should only be used for
// making trust decisions about serverAuth certificates, as the trust status for
// other uses is not considered. Using the roots returned by this package for
// trust decisions should be done carefully.
//
// Some roots returned by the parser may include additional constraints
// (currently only DistrustAfter) which need to be considered when verifying
// certificates which chain to them.
//
// Parse is not intended to be a general purpose parser for certdata.txt.
func Parse(r io.Reader) ([]*Certificate, error) {
// certdata.txt is a rather strange format. It is essentially a list of
// textual PKCS#11 objects, delimited by empty lines. There are two main
// types of objects, certificates (CKO_CERTIFICATE) and trust definitions
// (CKO_NSS_TRUST). These objects appear to alternate, but this ordering is
// not defined anywhere, and should probably not be relied on. A single root
// certificate requires both the certificate object and the trust definition
// object in order to be properly understood.
//
// The list contains not just serverAuth certificates, so we need to be
// careful to only extract certificates which have the serverAuth trust bit
// set. Similarly there are a number of trust related bool fields that
// appear to _always_ be CKA_TRUE, but it seems unsafe to assume this is the
// case, so we should always double check.
//
// Since we only really care about a couple of fields, this parser throws
// away a lot of information, essentially just consuming CKA_CLASS objects
// and looking for the individual fields we care about. We could write a
// siginificantly more complex parser, which handles the entire format, but
// it feels like that would be over engineered for the little information
// that we really care about.
scanner := bufio.NewScanner(r)
type nssEntry struct {
cert *certObj
trust *trustObj
}
entries := map[[sha1.Size]byte]*nssEntry{}
for scanner.Scan() {
// scan until we hit CKA_CLASS
if !strings.HasPrefix(scanner.Text(), "CKA_CLASS") {
continue
}
f := strings.Fields(scanner.Text())
if len(f) != 3 {
return nil, errors.New("malformed CKA_CLASS")
}
switch f[2] {
case "CKO_CERTIFICATE":
h, co, err := parseCertClass(scanner)
if err != nil {
return nil, err
}
if co != nil {
e, ok := entries[h]
if !ok {
e = &nssEntry{}
entries[h] = e
}
e.cert = co
}
case "CKO_NSS_TRUST":
h, to, err := parseTrustClass(scanner)
if err != nil {
return nil, err
}
if to != nil {
e, ok := entries[h]
if !ok {
e = &nssEntry{}
entries[h] = e
}
e.trust = to
}
}
}
if err := scanner.Err(); err != nil {
return nil, err
}
var certs []*Certificate
for h, e := range entries {
if e.cert == nil && e.trust != nil {
// We may skip some certificates which are distrusted due to mozilla
// policy (CKA_NSS_MOZILLA_CA_POLICY CK_BBOOL CK_FALSE), which means
// we might get entries that appear to have a trust object, but no
// certificate. We can just continue on here.
continue
} else if e.cert != nil && e.trust == nil {
return nil, fmt.Errorf("missing trust object for certificate with SHA1 hash: %x", h)
}
if !e.trust.trusted {
continue
}
nssCert := &Certificate{X509: e.cert.c}
if e.cert.DistrustAfter != nil {
nssCert.Constraints = append(nssCert.Constraints, DistrustAfter(*e.cert.DistrustAfter))
}
certs = append(certs, nssCert)
}
return certs, nil
}
File diff suppressed because it is too large Load Diff