Check for trailing data in extensions.

X509V3_EXT_d2i should notice if an extension has extra data at the end.

Update-Note: Some previously accepted invalid certicates may be
rejected, either in certificate verification or in X509_get_ext_d2i.

Bug: 352
Change-Id: Iacbb74a52d15bf3318b4cb8271d44b0f0a2df137
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/50285
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/x509/test/make_invalid_extensions.go b/crypto/x509/test/make_invalid_extensions.go
index 3d20942..d0c2cee 100644
--- a/crypto/x509/test/make_invalid_extensions.go
+++ b/crypto/x509/test/make_invalid_extensions.go
@@ -59,7 +59,7 @@
 	key      *ecdsa.PrivateKey
 }
 
-func generateCertificateOrPanic(path string, subject, issuer *templateAndKey) {
+func generateCertificateOrPanic(path string, subject, issuer *templateAndKey) []byte {
 	cert, err := x509.CreateCertificate(rand.Reader, &subject.template, &issuer.template, &subject.key.PublicKey, issuer.key)
 	if err != nil {
 		panic(err)
@@ -73,6 +73,7 @@
 	if err != nil {
 		panic(err)
 	}
+	return cert
 }
 
 func main() {
@@ -96,6 +97,7 @@
 			ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
 			KeyUsage:              x509.KeyUsageCertSign,
 			SignatureAlgorithm:    x509.ECDSAWithSHA256,
+			SubjectKeyId:          []byte("root"),
 		},
 		key: rootKey,
 	}
@@ -110,6 +112,7 @@
 			ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
 			KeyUsage:              x509.KeyUsageCertSign,
 			SignatureAlgorithm:    x509.ECDSAWithSHA256,
+			SubjectKeyId:          []byte("intermediate"),
 		},
 		key: intermediateKey,
 	}
@@ -125,6 +128,8 @@
 			KeyUsage:              x509.KeyUsageCertSign,
 			SignatureAlgorithm:    x509.ECDSAWithSHA256,
 			DNSNames:              []string{"www.example.com"},
+			SubjectKeyId:          []byte("leaf"),
+			PermittedDNSDomains:   []string{"www.example.com"},
 		},
 		key: leafKey,
 	}
@@ -132,10 +137,15 @@
 	// Generate a valid certificate chain from the templates.
 	generateCertificateOrPanic("invalid_extension_root.pem", &root, &root)
 	generateCertificateOrPanic("invalid_extension_intermediate.pem", &intermediate, &root)
-	generateCertificateOrPanic("invalid_extension_leaf.pem", &leaf, &intermediate)
+	leafDER := generateCertificateOrPanic("invalid_extension_leaf.pem", &leaf, &intermediate)
 
-	// Make copies of each of the three certificates with invalid extensions.
-	// These copies may be substituted into the valid chain.
+	leafCert, err := x509.ParseCertificate(leafDER)
+	if err != nil {
+		panic(err)
+	}
+
+	// Make copies of the certificates with invalid extensions. These copies may
+	// be substituted into the valid chain.
 	for _, ext := range extensions {
 		invalidExtension := []pkix.Extension{{Id: ext.oid, Value: []byte("INVALID")}}
 
@@ -150,6 +160,24 @@
 		leafInvalid := leaf
 		leafInvalid.template.ExtraExtensions = invalidExtension
 		generateCertificateOrPanic(fmt.Sprintf("invalid_extension_leaf_%s.pem", ext.name), &leafInvalid, &intermediate)
+
+		// Additionally generate a copy of the leaf certificate with extra data in
+		// the extension.
+		var trailingDataExtension []pkix.Extension
+		for _, leafExt := range leafCert.Extensions {
+			if leafExt.Id.Equal(ext.oid) {
+				newValue := make([]byte, len(leafExt.Value)+1)
+				copy(newValue, leafExt.Value)
+				trailingDataExtension = append(trailingDataExtension, pkix.Extension{Id: ext.oid, Critical: leafExt.Critical, Value: newValue})
+			}
+		}
+		if len(trailingDataExtension) != 1 {
+			panic(fmt.Sprintf("could not find sample extension %s", ext.name))
+		}
+
+		leafTrailingData := leaf
+		leafTrailingData.template.ExtraExtensions = trailingDataExtension
+		generateCertificateOrPanic(fmt.Sprintf("trailing_data_leaf_%s.pem", ext.name), &leafTrailingData, &intermediate)
 	}
 }