]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/x509: make verification of an empty certificate consistent across platforms.
authorAdam Langley <agl@golang.org>
Sun, 30 Aug 2015 16:45:26 +0000 (09:45 -0700)
committerAdam Langley <agl@golang.org>
Wed, 30 Sep 2015 00:51:51 +0000 (00:51 +0000)
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/14053
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/crypto/x509/verify.go
src/crypto/x509/x509_test.go

index 21b870c1712cc712ed3c2dc89baa37af9ccce1c8..27e9bbfbcc6029392b048cd95e80c4162925b343 100644 (file)
@@ -5,6 +5,7 @@
 package x509
 
 import (
+       "errors"
        "fmt"
        "net"
        "runtime"
@@ -122,6 +123,10 @@ func (SystemRootsError) Error() string {
        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
 // because other PKIX verification APIs have ended up needing many options.
 type VerifyOptions struct {
@@ -210,6 +215,19 @@ func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *V
 //
 // WARNING: this 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 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.
        if opts.Roots == nil && runtime.GOOS == "windows" {
                return c.systemVerify(&opts)
index fbd77dde8a9998f3a6e56b8ee1936b1319750ce1..36dbc479319250010f900285a4834bb53625e7d7 100644 (file)
@@ -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:
 //  openssl req -out CSR.csr -new -sha256 -nodes -keyout privateKey.key -config openssl.cnf
 //