golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.23k stars 17.57k forks source link

crypto/x509: potentially anomalous path building results #65085

Open woodruffw opened 8 months ago

woodruffw commented 8 months ago

Go version

go1.21.5 linux/amd64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/runner/.cache/go-build'
GOENV='/home/runner/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/runner/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/runner/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/hostedtoolcache/go/1.21.5/x64'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/hostedtoolcache/go/1.21.5/x64/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.21.5'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build1019109943=/tmp/go-build -gno-record-gcc-switches'

What did you do?

Hi there! I'm opening this to root-cause a handful of potentially anomalous path building results with crypto/x509, which we found with x509-limbo.

First, a disclaimer: I suspect that many of the results above are expected or are non-issues from crypto/x509's perspective, since many are "pedantic" checks against a strict reading of RFC 5280. For example, rfc5280::nc::not-allowed-in-ee-critical is technically disallowed under RFC 5280, but all other implementations appear to broadly ignore it.

There are, however, some discrepancies for which crypto/x509 is the outlier. A sampling of anomalous positives (chains built where other implementations fail):

There are also some anomalous negatives (chains that fail to build where success is expected), but crypto/x509 is largely in consensus with other implementations around them (the main outlier is OpenSSL).

What did you see happen?

The full rendering of potentially anomalous results is here: https://x509-limbo.com/anomalous-results/gocryptox509-go1.21.5/

As mentioned above, some of these are almost certainly intended behavior on crypto/x509's part as part of handling real-world chains, especially outside of the Web PKI. However, I could find a document or docstring anywhere that explicitly enumerated these (in absolute fairness, nobody does this 🙂), so I figured I would open this up for general review and consideration.

What did you expect to see?

In cases involving critical or out-of-policy extensions that crypto/x509 appears to otherwise ignore, I expected to see chain build failures rather than successes. However, see qualifications above 🙂

seankhliao commented 8 months ago

cc @golang/security

gopherbot commented 8 months ago

Change https://go.dev/cl/561615 mentions this issue: crypto/x509: rfc 5280 alignments

rolandshoemaker commented 8 months ago

@woodruffw it looks like the anomalous findings page has disappeared, are those still recorded somewhere?

woodruffw commented 8 months ago

@woodruffw it looks like the anomalous findings page has disappeared, are those still recorded somewhere?

My apologies for that -- it looks like our CI hiccuped somewhere and didn't render the latest Go results. I'll look into that now.

woodruffw commented 8 months ago

Sorry again for that! We've fixed it with https://github.com/C2SP/x509-limbo/pull/193, and the render is here: https://x509-limbo.com/anomalous-results/gocryptox509-go1.21.6/

(NB the URL has changed slightly, since we've gone from go1.21.5 to go1.21.6.)

rolandshoemaker commented 8 months ago

Perfect, thanks for the (extremely) quick fix!

rolandshoemaker commented 7 months ago

Ignoring the CABF stuff, did some quick searching for publicly trusted certificates that exhibit the various issues. This is how many certificates I found, listed from least to most, with comments where applicable:


? rfc5280::ee-critical-aia-invalid (seems reasonable to reject)
? rfc5280::nc::permitted-dns-match-noncritical (probably want to do this anyway, mistakingly marking non-crit seems acceptable?)
? rfc5280::pc::ica-noncritical-pc (seems plausible we can reject)
? rfc5280::root-non-critical-basic-constraints (seems unlikely)
0 rfc5280::ca-empty-subject
0 rfc5280::ee-empty-issuer
0 rfc5280::nc::not-allowed-in-ee-critical
0 rfc5280::nc::not-allowed-in-ee-noncritical
0 rfc5280::root-inconsistent-ca-extensions
0 rfc5280::san::noncritical-with-empty-subject
0 rfc5280::ski::critical-ski
3 rfc5280::aki::cross-signed-root-missing-aki
7 rfc5280::leaf-ku-keycertsign
7 rfc5280::serial::too-long (we tried to fix this previously)
8 rfc5280::ski::root-missing-ski (various trusted verisign roots)
9 rfc5280::ski::intermediate-missing-ski(various trusted intermediates)
46 rfc5280::serial::zero (many important roots)
130 rfc5280::aki::intermediate-missing-aki
1,196 rfc5280::aki::leaf-missing-aki
alex commented 7 months ago

@rolandshoemaker what's the dataset this is based on, CT?

rolandshoemaker commented 7 months ago

I used the censys dataset, so mostly CT.

gopherbot commented 7 months ago

Change https://go.dev/cl/562343 mentions this issue: crypto/x509: reject negative serial numbers

gopherbot commented 7 months ago

Change https://go.dev/cl/562341 mentions this issue: crypto/x509: reject critical AKI

gopherbot commented 7 months ago

Change https://go.dev/cl/562342 mentions this issue: crypto/x509: reject critical AIA extensions

gopherbot commented 7 months ago

Change https://go.dev/cl/562344 mentions this issue: crypto/x509: reject critical SKI extensions

gopherbot commented 7 months ago

Change https://go.dev/cl/562975 mentions this issue: crypto/x509: reject serial numbers longer than 20 octets

woodruffw commented 5 months ago

We've added another testcase to x509-limbo that has a standout anomalous result for crypto/x509: https://x509-limbo.com/testcases/webpki/#webpkisansan-wildcard-only-tld

In particular, when a leaf certificate has a SAN with DNS:*, most implementations reject that cert for any domain, while crypto/x509 appears to reject it for TLDs and other single-label hosts. crypto/x509 should probably be rejecting this instead (like OpenSSL, etc.).

(In terms of standards justification, DNS:* is neither a valid DNS name nor a valid wildcard pattern per RFC 6125, at least according to my reading, since RFC 6125 requires at least one label.)

woodruffw commented 4 months ago

Gentle ping on this finding as well: https://github.com/golang/go/issues/65085#issuecomment-2045790617 -- I believe this one is also worthy of a patch 🙂

rolandshoemaker commented 4 months ago

Thanks for the nudge, agreed this should get into the next release.

gopherbot commented 4 months ago

Change https://go.dev/cl/585076 mentions this issue: crypto/x509: don't match bare wildcard

woodruffw commented 2 months ago

We've added another x509-limbo case that has an anomalous result in Go, and may be worth addressing: https://x509-limbo.com/testcases/rfc5280/#rfc5280ekuee-eku-empty

In particular, RFC 5280 says that an EKU, if present, has one or more usages listed in it, but crypto/x509 allows an empty EKU to satisfy during path validation (seemingly treating it the same as "no EKU present"). PyCA Cryptography and the various Rust X.509 validators reject this, while OpenSSL doesn't.