Commit 8ee02618 authored by Adam Langley's avatar Adam Langley

crypto/x509: make verification of an empty certificate consistent across platforms.

Platform-specific verification needs the ASN.1 contents of a certificate
but that might not be provided if the Certificate was not created by
ParseCertificate. In order to avoid a panic on Windows, and to make
behaviour consistent across platforms, this change causes verification
to fail when the ASN.1 contents of a certificate are not available.

Fixes #12184

Change-Id: I4395d74934e675c179eaf4cded1094a756e478bb
Reviewed-on: https://go-review.googlesource.com/14053Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 5d5889c4
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package x509 package x509
import ( import (
"errors"
"fmt" "fmt"
"net" "net"
"runtime" "runtime"
...@@ -122,6 +123,10 @@ func (SystemRootsError) Error() string { ...@@ -122,6 +123,10 @@ func (SystemRootsError) Error() string {
return "x509: failed to load system roots and no roots provided" return "x509: failed to load system roots and no roots provided"
} }
// 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. It's a structure // VerifyOptions contains parameters for Certificate.Verify. It's a structure
// because other PKIX verification APIs have ended up needing many options. // because other PKIX verification APIs have ended up needing many options.
type VerifyOptions struct { type VerifyOptions struct {
...@@ -210,6 +215,19 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V ...@@ -210,6 +215,19 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
// //
// WARNING: this doesn't do any revocation checking. // WARNING: this doesn't do any revocation checking.
func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) { func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
// Platform-specific verification needs the ASN.1 contents so
// this makes the behaviour consistent across platforms.
if len(c.Raw) == 0 {
return nil, errNotParsed
}
if opts.Intermediates != nil {
for _, intermediate := range opts.Intermediates.certs {
if len(intermediate.Raw) == 0 {
return nil, errNotParsed
}
}
}
// Use Windows's own verification and chain building. // Use Windows's own verification and chain building.
if opts.Roots == nil && runtime.GOOS == "windows" { if opts.Roots == nil && runtime.GOOS == "windows" {
return c.systemVerify(&opts) return c.systemVerify(&opts)
......
...@@ -1159,6 +1159,12 @@ func TestASN1BitLength(t *testing.T) { ...@@ -1159,6 +1159,12 @@ func TestASN1BitLength(t *testing.T) {
} }
} }
func TestVerifyEmptyCertificate(t *testing.T) {
if _, err := new(Certificate).Verify(VerifyOptions{}); err != errNotParsed {
t.Errorf("Verifying empty certificate resulted in unexpected error: %q (wanted %q)", err, errNotParsed)
}
}
// These CSR was generated with OpenSSL: // These CSR was generated with OpenSSL:
// openssl req -out CSR.csr -new -sha256 -nodes -keyout privateKey.key -config openssl.cnf // openssl req -out CSR.csr -new -sha256 -nodes -keyout privateKey.key -config openssl.cnf
// //
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment