Source file src/crypto/x509/verify_test.go

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package x509
     6  
     7  import (
     8  	"crypto"
     9  	"crypto/dsa"
    10  	"crypto/ecdsa"
    11  	"crypto/elliptic"
    12  	"crypto/rand"
    13  	"crypto/rsa"
    14  	"crypto/x509/pkix"
    15  	"encoding/asn1"
    16  	"encoding/pem"
    17  	"errors"
    18  	"fmt"
    19  	"internal/testenv"
    20  	"log"
    21  	"math/big"
    22  	"net"
    23  	"os"
    24  	"os/exec"
    25  	"runtime"
    26  	"slices"
    27  	"strconv"
    28  	"strings"
    29  	"testing"
    30  	"time"
    31  )
    32  
    33  type verifyTest struct {
    34  	name          string
    35  	leaf          string
    36  	intermediates []string
    37  	roots         []string
    38  	currentTime   int64
    39  	dnsName       string
    40  	systemSkip    bool
    41  	systemLax     bool
    42  	keyUsages     []ExtKeyUsage
    43  
    44  	errorCallback  func(*testing.T, error)
    45  	expectedChains [][]string
    46  }
    47  
    48  var verifyTests = []verifyTest{
    49  	{
    50  		name:          "Valid",
    51  		leaf:          googleLeaf,
    52  		intermediates: []string{gtsIntermediate},
    53  		roots:         []string{gtsRoot},
    54  		currentTime:   1677615892,
    55  		dnsName:       "www.google.com",
    56  
    57  		expectedChains: [][]string{
    58  			{"www.google.com", "GTS CA 1C3", "GTS Root R1"},
    59  		},
    60  	},
    61  	{
    62  		name:          "Valid (fqdn)",
    63  		leaf:          googleLeaf,
    64  		intermediates: []string{gtsIntermediate},
    65  		roots:         []string{gtsRoot},
    66  		currentTime:   1677615892,
    67  		dnsName:       "www.google.com.",
    68  
    69  		expectedChains: [][]string{
    70  			{"www.google.com", "GTS CA 1C3", "GTS Root R1"},
    71  		},
    72  	},
    73  	{
    74  		name:          "MixedCase",
    75  		leaf:          googleLeaf,
    76  		intermediates: []string{gtsIntermediate},
    77  		roots:         []string{gtsRoot},
    78  		currentTime:   1677615892,
    79  		dnsName:       "WwW.GooGLE.coM",
    80  
    81  		expectedChains: [][]string{
    82  			{"www.google.com", "GTS CA 1C3", "GTS Root R1"},
    83  		},
    84  	},
    85  	{
    86  		name:          "HostnameMismatch",
    87  		leaf:          googleLeaf,
    88  		intermediates: []string{gtsIntermediate},
    89  		roots:         []string{gtsRoot},
    90  		currentTime:   1677615892,
    91  		dnsName:       "www.example.com",
    92  
    93  		errorCallback: expectHostnameError("certificate is valid for"),
    94  	},
    95  	{
    96  		name:        "TooManyDNS",
    97  		leaf:        generatePEMCertWithRepeatSAN(1677615892, 200, "fake.dns"),
    98  		roots:       []string{generatePEMCertWithRepeatSAN(1677615892, 200, "fake.dns")},
    99  		currentTime: 1677615892,
   100  		dnsName:     "www.example.com",
   101  		systemSkip:  true, // does not chain to a system root
   102  
   103  		errorCallback: expectHostnameError("certificate is valid for 200 names, but none matched"),
   104  	},
   105  	{
   106  		name:        "TooManyIPs",
   107  		leaf:        generatePEMCertWithRepeatSAN(1677615892, 150, "4.3.2.1"),
   108  		roots:       []string{generatePEMCertWithRepeatSAN(1677615892, 150, "4.3.2.1")},
   109  		currentTime: 1677615892,
   110  		dnsName:     "1.2.3.4",
   111  		systemSkip:  true, // does not chain to a system root
   112  
   113  		errorCallback: expectHostnameError("certificate is valid for 150 IP SANs, but none matched"),
   114  	},
   115  	{
   116  		name:          "IPMissing",
   117  		leaf:          googleLeaf,
   118  		intermediates: []string{gtsIntermediate},
   119  		roots:         []string{gtsRoot},
   120  		currentTime:   1677615892,
   121  		dnsName:       "1.2.3.4",
   122  
   123  		errorCallback: expectHostnameError("doesn't contain any IP SANs"),
   124  	},
   125  	{
   126  		name:          "Expired",
   127  		leaf:          googleLeaf,
   128  		intermediates: []string{gtsIntermediate},
   129  		roots:         []string{gtsRoot},
   130  		currentTime:   1,
   131  		dnsName:       "www.example.com",
   132  
   133  		errorCallback: expectExpired,
   134  	},
   135  	{
   136  		name:        "MissingIntermediate",
   137  		leaf:        googleLeaf,
   138  		roots:       []string{gtsRoot},
   139  		currentTime: 1677615892,
   140  		dnsName:     "www.google.com",
   141  
   142  		// Skip when using systemVerify, since Windows
   143  		// *will* find the missing intermediate cert.
   144  		systemSkip:    true,
   145  		errorCallback: expectAuthorityUnknown,
   146  	},
   147  	{
   148  		name:          "RootInIntermediates",
   149  		leaf:          googleLeaf,
   150  		intermediates: []string{gtsRoot, gtsIntermediate},
   151  		roots:         []string{gtsRoot},
   152  		currentTime:   1677615892,
   153  		dnsName:       "www.google.com",
   154  
   155  		expectedChains: [][]string{
   156  			{"www.google.com", "GTS CA 1C3", "GTS Root R1"},
   157  		},
   158  		// CAPI doesn't build the chain with the duplicated GeoTrust
   159  		// entry so the results don't match.
   160  		systemLax: true,
   161  	},
   162  	{
   163  		name:          "InvalidHash",
   164  		leaf:          googleLeafWithInvalidHash,
   165  		intermediates: []string{gtsIntermediate},
   166  		roots:         []string{gtsRoot},
   167  		currentTime:   1677615892,
   168  		dnsName:       "www.google.com",
   169  
   170  		// The specific error message may not occur when using system
   171  		// verification.
   172  		systemLax:     true,
   173  		errorCallback: expectHashError,
   174  	},
   175  	// EKULeaf tests use an unconstrained chain leading to a leaf certificate
   176  	// with an E-mail Protection EKU but not a Server Auth one, checking that
   177  	// the EKUs on the leaf are enforced.
   178  	{
   179  		name:          "EKULeaf",
   180  		leaf:          smimeLeaf,
   181  		intermediates: []string{smimeIntermediate},
   182  		roots:         []string{smimeRoot},
   183  		currentTime:   1594673418,
   184  
   185  		errorCallback: expectUsageError,
   186  	},
   187  	{
   188  		name:          "EKULeafExplicit",
   189  		leaf:          smimeLeaf,
   190  		intermediates: []string{smimeIntermediate},
   191  		roots:         []string{smimeRoot},
   192  		currentTime:   1594673418,
   193  		keyUsages:     []ExtKeyUsage{ExtKeyUsageServerAuth},
   194  
   195  		errorCallback: expectUsageError,
   196  	},
   197  	{
   198  		name:          "EKULeafValid",
   199  		leaf:          smimeLeaf,
   200  		intermediates: []string{smimeIntermediate},
   201  		roots:         []string{smimeRoot},
   202  		currentTime:   1594673418,
   203  		keyUsages:     []ExtKeyUsage{ExtKeyUsageEmailProtection},
   204  
   205  		expectedChains: [][]string{
   206  			{"CORPORATIVO FICTICIO ACTIVO", "EAEko Herri Administrazioen CA - CA AAPP Vascas (2)", "IZENPE S.A."},
   207  		},
   208  	},
   209  	{
   210  		// Check that a name constrained intermediate works even when
   211  		// it lists multiple constraints.
   212  		name:          "MultipleConstraints",
   213  		leaf:          nameConstraintsLeaf,
   214  		intermediates: []string{nameConstraintsIntermediate1, nameConstraintsIntermediate2},
   215  		roots:         []string{globalSignRoot},
   216  		currentTime:   1524771953,
   217  		dnsName:       "udctest.ads.vt.edu",
   218  
   219  		expectedChains: [][]string{
   220  			{
   221  				"udctest.ads.vt.edu",
   222  				"Virginia Tech Global Qualified Server CA",
   223  				"Trusted Root CA SHA256 G2",
   224  				"GlobalSign",
   225  			},
   226  		},
   227  	},
   228  	{
   229  		// Check that SHA-384 intermediates (which are popping up)
   230  		// work.
   231  		name:          "SHA-384",
   232  		leaf:          trustAsiaLeaf,
   233  		intermediates: []string{trustAsiaSHA384Intermediate},
   234  		roots:         []string{digicertRoot},
   235  		currentTime:   1558051200,
   236  		dnsName:       "tm.cn",
   237  
   238  		// CryptoAPI can find alternative validation paths.
   239  		systemLax: true,
   240  
   241  		expectedChains: [][]string{
   242  			{
   243  				"tm.cn",
   244  				"TrustAsia ECC OV TLS Pro CA",
   245  				"DigiCert Global Root CA",
   246  			},
   247  		},
   248  	},
   249  	{
   250  		// Putting a certificate as a root directly should work as a
   251  		// way of saying “exactly this”.
   252  		name:        "LeafInRoots",
   253  		leaf:        selfSigned,
   254  		roots:       []string{selfSigned},
   255  		currentTime: 1471624472,
   256  		dnsName:     "foo.example",
   257  		systemSkip:  true, // does not chain to a system root
   258  
   259  		expectedChains: [][]string{
   260  			{"Acme Co"},
   261  		},
   262  	},
   263  	{
   264  		// Putting a certificate as a root directly should not skip
   265  		// other checks however.
   266  		name:        "LeafInRootsInvalid",
   267  		leaf:        selfSigned,
   268  		roots:       []string{selfSigned},
   269  		currentTime: 1471624472,
   270  		dnsName:     "notfoo.example",
   271  		systemSkip:  true, // does not chain to a system root
   272  
   273  		errorCallback: expectHostnameError("certificate is valid for"),
   274  	},
   275  	{
   276  		// An X.509 v1 certificate should not be accepted as an
   277  		// intermediate.
   278  		name:          "X509v1Intermediate",
   279  		leaf:          x509v1TestLeaf,
   280  		intermediates: []string{x509v1TestIntermediate},
   281  		roots:         []string{x509v1TestRoot},
   282  		currentTime:   1481753183,
   283  		systemSkip:    true, // does not chain to a system root
   284  
   285  		errorCallback: expectNotAuthorizedError,
   286  	},
   287  	{
   288  		name:        "IgnoreCNWithSANs",
   289  		leaf:        ignoreCNWithSANLeaf,
   290  		dnsName:     "foo.example.com",
   291  		roots:       []string{ignoreCNWithSANRoot},
   292  		currentTime: 1486684488,
   293  		systemSkip:  true, // does not chain to a system root
   294  
   295  		errorCallback: expectHostnameError("certificate is not valid for any names"),
   296  	},
   297  	{
   298  		// Test that excluded names are respected.
   299  		name:          "ExcludedNames",
   300  		leaf:          excludedNamesLeaf,
   301  		dnsName:       "bender.local",
   302  		intermediates: []string{excludedNamesIntermediate},
   303  		roots:         []string{excludedNamesRoot},
   304  		currentTime:   1486684488,
   305  		systemSkip:    true, // does not chain to a system root
   306  
   307  		errorCallback: expectNameConstraintsError,
   308  	},
   309  	{
   310  		// Test that unknown critical extensions in a leaf cause a
   311  		// verify error.
   312  		name:          "CriticalExtLeaf",
   313  		leaf:          criticalExtLeafWithExt,
   314  		intermediates: []string{criticalExtIntermediate},
   315  		roots:         []string{criticalExtRoot},
   316  		currentTime:   1486684488,
   317  		systemSkip:    true, // does not chain to a system root
   318  
   319  		errorCallback: expectUnhandledCriticalExtension,
   320  	},
   321  	{
   322  		// Test that unknown critical extensions in an intermediate
   323  		// cause a verify error.
   324  		name:          "CriticalExtIntermediate",
   325  		leaf:          criticalExtLeaf,
   326  		intermediates: []string{criticalExtIntermediateWithExt},
   327  		roots:         []string{criticalExtRoot},
   328  		currentTime:   1486684488,
   329  		systemSkip:    true, // does not chain to a system root
   330  
   331  		errorCallback: expectUnhandledCriticalExtension,
   332  	},
   333  	{
   334  		name:        "ValidCN",
   335  		leaf:        validCNWithoutSAN,
   336  		dnsName:     "foo.example.com",
   337  		roots:       []string{invalidCNRoot},
   338  		currentTime: 1540000000,
   339  		systemSkip:  true, // does not chain to a system root
   340  
   341  		errorCallback: expectHostnameError("certificate relies on legacy Common Name field"),
   342  	},
   343  	{
   344  		// A certificate with an AKID should still chain to a parent without SKID.
   345  		// See Issue 30079.
   346  		name:        "AKIDNoSKID",
   347  		leaf:        leafWithAKID,
   348  		roots:       []string{rootWithoutSKID},
   349  		currentTime: 1550000000,
   350  		dnsName:     "example",
   351  		systemSkip:  true, // does not chain to a system root
   352  
   353  		expectedChains: [][]string{
   354  			{"Acme LLC", "Acme Co"},
   355  		},
   356  	},
   357  	{
   358  		// When there are two parents, one with an incorrect subject but matching SKID
   359  		// and one with a correct subject but missing SKID, the latter should be
   360  		// considered as a possible parent.
   361  		leaf:        leafMatchingAKIDMatchingIssuer,
   362  		roots:       []string{rootMatchingSKIDMismatchingSubject, rootMismatchingSKIDMatchingSubject},
   363  		currentTime: 1550000000,
   364  		dnsName:     "example",
   365  		systemSkip:  true,
   366  
   367  		expectedChains: [][]string{
   368  			{"Leaf", "Root B"},
   369  		},
   370  	},
   371  }
   372  
   373  func expectHostnameError(msg string) func(*testing.T, error) {
   374  	return func(t *testing.T, err error) {
   375  		if _, ok := err.(HostnameError); !ok {
   376  			t.Fatalf("error was not a HostnameError: %v", err)
   377  		}
   378  		if !strings.Contains(err.Error(), msg) {
   379  			t.Fatalf("HostnameError did not contain %q: %v", msg, err)
   380  		}
   381  	}
   382  }
   383  
   384  func expectExpired(t *testing.T, err error) {
   385  	if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != Expired {
   386  		t.Fatalf("error was not Expired: %v", err)
   387  	}
   388  }
   389  
   390  func expectUsageError(t *testing.T, err error) {
   391  	if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != IncompatibleUsage {
   392  		t.Fatalf("error was not IncompatibleUsage: %v", err)
   393  	}
   394  }
   395  
   396  func expectAuthorityUnknown(t *testing.T, err error) {
   397  	e, ok := err.(UnknownAuthorityError)
   398  	if !ok {
   399  		t.Fatalf("error was not UnknownAuthorityError: %v", err)
   400  	}
   401  	if e.Cert == nil {
   402  		t.Fatalf("error was UnknownAuthorityError, but missing Cert: %v", err)
   403  	}
   404  }
   405  
   406  func expectHashError(t *testing.T, err error) {
   407  	if err == nil {
   408  		t.Fatalf("no error resulted from invalid hash")
   409  	}
   410  	if expected := "algorithm unimplemented"; !strings.Contains(err.Error(), expected) {
   411  		t.Fatalf("error resulting from invalid hash didn't contain '%s', rather it was: %v", expected, err)
   412  	}
   413  }
   414  
   415  func expectNameConstraintsError(t *testing.T, err error) {
   416  	if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != CANotAuthorizedForThisName {
   417  		t.Fatalf("error was not a CANotAuthorizedForThisName: %v", err)
   418  	}
   419  }
   420  
   421  func expectNotAuthorizedError(t *testing.T, err error) {
   422  	if inval, ok := err.(CertificateInvalidError); !ok || inval.Reason != NotAuthorizedToSign {
   423  		t.Fatalf("error was not a NotAuthorizedToSign: %v", err)
   424  	}
   425  }
   426  
   427  func expectUnhandledCriticalExtension(t *testing.T, err error) {
   428  	if _, ok := err.(UnhandledCriticalExtension); !ok {
   429  		t.Fatalf("error was not an UnhandledCriticalExtension: %v", err)
   430  	}
   431  }
   432  
   433  func certificateFromPEM(pemBytes string) (*Certificate, error) {
   434  	block, _ := pem.Decode([]byte(pemBytes))
   435  	if block == nil {
   436  		return nil, errors.New("failed to decode PEM")
   437  	}
   438  	return ParseCertificate(block.Bytes)
   439  }
   440  
   441  func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) {
   442  	opts := VerifyOptions{
   443  		Intermediates: NewCertPool(),
   444  		DNSName:       test.dnsName,
   445  		CurrentTime:   time.Unix(test.currentTime, 0),
   446  		KeyUsages:     test.keyUsages,
   447  	}
   448  
   449  	if !useSystemRoots {
   450  		opts.Roots = NewCertPool()
   451  		for j, root := range test.roots {
   452  			ok := opts.Roots.AppendCertsFromPEM([]byte(root))
   453  			if !ok {
   454  				t.Fatalf("failed to parse root #%d", j)
   455  			}
   456  		}
   457  	}
   458  
   459  	for j, intermediate := range test.intermediates {
   460  		ok := opts.Intermediates.AppendCertsFromPEM([]byte(intermediate))
   461  		if !ok {
   462  			t.Fatalf("failed to parse intermediate #%d", j)
   463  		}
   464  	}
   465  
   466  	leaf, err := certificateFromPEM(test.leaf)
   467  	if err != nil {
   468  		t.Fatalf("failed to parse leaf: %v", err)
   469  	}
   470  
   471  	chains, err := leaf.Verify(opts)
   472  
   473  	if test.errorCallback == nil && err != nil {
   474  		if runtime.GOOS == "windows" && strings.HasSuffix(testenv.Builder(), "-2008") && err.Error() == "x509: certificate signed by unknown authority" {
   475  			testenv.SkipFlaky(t, 19564)
   476  		}
   477  		t.Fatalf("unexpected error: %v", err)
   478  	}
   479  	if test.errorCallback != nil {
   480  		if useSystemRoots && test.systemLax {
   481  			if err == nil {
   482  				t.Fatalf("expected error")
   483  			}
   484  		} else {
   485  			test.errorCallback(t, err)
   486  		}
   487  	}
   488  
   489  	doesMatch := func(expectedChain []string, chain []*Certificate) bool {
   490  		if len(chain) != len(expectedChain) {
   491  			return false
   492  		}
   493  
   494  		for k, cert := range chain {
   495  			if !strings.Contains(nameToKey(&cert.Subject), expectedChain[k]) {
   496  				return false
   497  			}
   498  		}
   499  		return true
   500  	}
   501  
   502  	// Every expected chain should match one (or more) returned chain. We tolerate multiple
   503  	// matches, as due to root store semantics it is plausible that (at least on the system
   504  	// verifiers) multiple identical (looking) chains may be returned when two roots with the
   505  	// same subject are present.
   506  	for _, expectedChain := range test.expectedChains {
   507  		var match bool
   508  		for _, chain := range chains {
   509  			if doesMatch(expectedChain, chain) {
   510  				match = true
   511  				break
   512  			}
   513  		}
   514  
   515  		if !match {
   516  			t.Errorf("No match found for %v", expectedChain)
   517  		}
   518  	}
   519  
   520  	// Every returned chain should match 1 expected chain (or <2 if testing against the system)
   521  	for _, chain := range chains {
   522  		nMatched := 0
   523  		for _, expectedChain := range test.expectedChains {
   524  			if doesMatch(expectedChain, chain) {
   525  				nMatched++
   526  			}
   527  		}
   528  		// Allow additional unknown chains if systemLax is set
   529  		if nMatched == 0 && test.systemLax == false || nMatched > 1 {
   530  			t.Errorf("Got %v matches for chain %v", nMatched, chainToDebugString(chain))
   531  			for _, expectedChain := range test.expectedChains {
   532  				if doesMatch(expectedChain, chain) {
   533  					t.Errorf("\t matched %v", expectedChain)
   534  				}
   535  			}
   536  		}
   537  	}
   538  }
   539  
   540  func TestGoVerify(t *testing.T) {
   541  	for _, test := range verifyTests {
   542  		t.Run(test.name, func(t *testing.T) {
   543  			testVerify(t, test, false)
   544  		})
   545  	}
   546  }
   547  
   548  func TestSystemVerify(t *testing.T) {
   549  	if runtime.GOOS != "windows" {
   550  		t.Skipf("skipping verify test using system APIs on %q", runtime.GOOS)
   551  	}
   552  
   553  	for _, test := range verifyTests {
   554  		t.Run(test.name, func(t *testing.T) {
   555  			if test.systemSkip {
   556  				t.SkipNow()
   557  			}
   558  			testVerify(t, test, true)
   559  		})
   560  	}
   561  }
   562  
   563  func chainToDebugString(chain []*Certificate) string {
   564  	var chainStr string
   565  	for _, cert := range chain {
   566  		if len(chainStr) > 0 {
   567  			chainStr += " -> "
   568  		}
   569  		chainStr += nameToKey(&cert.Subject)
   570  	}
   571  	return chainStr
   572  }
   573  
   574  func nameToKey(name *pkix.Name) string {
   575  	return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
   576  }
   577  
   578  func generatePEMCertWithRepeatSAN(currentTime int64, count int, san string) string {
   579  	cert := Certificate{
   580  		NotBefore: time.Unix(currentTime, 0),
   581  		NotAfter:  time.Unix(currentTime, 0),
   582  	}
   583  	if ip := net.ParseIP(san); ip != nil {
   584  		cert.IPAddresses = slices.Repeat([]net.IP{ip}, count)
   585  	} else {
   586  		cert.DNSNames = slices.Repeat([]string{san}, count)
   587  	}
   588  	privKey, err := rsa.GenerateKey(rand.Reader, 4096)
   589  	if err != nil {
   590  		log.Fatal(err)
   591  	}
   592  	certBytes, err := CreateCertificate(rand.Reader, &cert, &cert, &privKey.PublicKey, privKey)
   593  	if err != nil {
   594  		log.Fatal(err)
   595  	}
   596  	return string(pem.EncodeToMemory(&pem.Block{
   597  		Type:  "CERTIFICATE",
   598  		Bytes: certBytes,
   599  	}))
   600  }
   601  
   602  const gtsIntermediate = `-----BEGIN CERTIFICATE-----
   603  MIIFljCCA36gAwIBAgINAgO8U1lrNMcY9QFQZjANBgkqhkiG9w0BAQsFADBHMQsw
   604  CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
   605  MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjAwODEzMDAwMDQyWhcNMjcwOTMwMDAw
   606  MDQyWjBGMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
   607  Y2VzIExMQzETMBEGA1UEAxMKR1RTIENBIDFDMzCCASIwDQYJKoZIhvcNAQEBBQAD
   608  ggEPADCCAQoCggEBAPWI3+dijB43+DdCkH9sh9D7ZYIl/ejLa6T/belaI+KZ9hzp
   609  kgOZE3wJCor6QtZeViSqejOEH9Hpabu5dOxXTGZok3c3VVP+ORBNtzS7XyV3NzsX
   610  lOo85Z3VvMO0Q+sup0fvsEQRY9i0QYXdQTBIkxu/t/bgRQIh4JZCF8/ZK2VWNAcm
   611  BA2o/X3KLu/qSHw3TT8An4Pf73WELnlXXPxXbhqW//yMmqaZviXZf5YsBvcRKgKA
   612  gOtjGDxQSYflispfGStZloEAoPtR28p3CwvJlk/vcEnHXG0g/Zm0tOLKLnf9LdwL
   613  tmsTDIwZKxeWmLnwi/agJ7u2441Rj72ux5uxiZ0CAwEAAaOCAYAwggF8MA4GA1Ud
   614  DwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0T
   615  AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUinR/r4XN7pXNPZzQ4kYU83E1HScwHwYD
   616  VR0jBBgwFoAU5K8rJnEaK0gnhS9SZizv8IkTcT4waAYIKwYBBQUHAQEEXDBaMCYG
   617  CCsGAQUFBzABhhpodHRwOi8vb2NzcC5wa2kuZ29vZy9ndHNyMTAwBggrBgEFBQcw
   618  AoYkaHR0cDovL3BraS5nb29nL3JlcG8vY2VydHMvZ3RzcjEuZGVyMDQGA1UdHwQt
   619  MCswKaAnoCWGI2h0dHA6Ly9jcmwucGtpLmdvb2cvZ3RzcjEvZ3RzcjEuY3JsMFcG
   620  A1UdIARQME4wOAYKKwYBBAHWeQIFAzAqMCgGCCsGAQUFBwIBFhxodHRwczovL3Br
   621  aS5nb29nL3JlcG9zaXRvcnkvMAgGBmeBDAECATAIBgZngQwBAgIwDQYJKoZIhvcN
   622  AQELBQADggIBAIl9rCBcDDy+mqhXlRu0rvqrpXJxtDaV/d9AEQNMwkYUuxQkq/BQ
   623  cSLbrcRuf8/xam/IgxvYzolfh2yHuKkMo5uhYpSTld9brmYZCwKWnvy15xBpPnrL
   624  RklfRuFBsdeYTWU0AIAaP0+fbH9JAIFTQaSSIYKCGvGjRFsqUBITTcFTNvNCCK9U
   625  +o53UxtkOCcXCb1YyRt8OS1b887U7ZfbFAO/CVMkH8IMBHmYJvJh8VNS/UKMG2Yr
   626  PxWhu//2m+OBmgEGcYk1KCTd4b3rGS3hSMs9WYNRtHTGnXzGsYZbr8w0xNPM1IER
   627  lQCh9BIiAfq0g3GvjLeMcySsN1PCAJA/Ef5c7TaUEDu9Ka7ixzpiO2xj2YC/WXGs
   628  Yye5TBeg2vZzFb8q3o/zpWwygTMD0IZRcZk0upONXbVRWPeyk+gB9lm+cZv9TSjO
   629  z23HFtz30dZGm6fKa+l3D/2gthsjgx0QGtkJAITgRNOidSOzNIb2ILCkXhAd4FJG
   630  AJ2xDx8hcFH1mt0G/FX0Kw4zd8NLQsLxdxP8c4CU6x+7Nz/OAipmsHMdMqUybDKw
   631  juDEI/9bfU1lcKwrmz3O2+BtjjKAvpafkmO8l7tdufThcV4q5O8DIrGKZTqPwJNl
   632  1IXNDw9bg1kWRxYtnCQ6yICmJhSFm/Y3m6xv+cXDBlHz4n/FsRC6UfTd
   633  -----END CERTIFICATE-----`
   634  
   635  const gtsRoot = `-----BEGIN CERTIFICATE-----
   636  MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw
   637  CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
   638  MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
   639  MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
   640  Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA
   641  A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo
   642  27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w
   643  Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw
   644  TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl
   645  qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH
   646  szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8
   647  Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk
   648  MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92
   649  wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p
   650  aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN
   651  VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID
   652  AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
   653  FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb
   654  C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe
   655  QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy
   656  h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4
   657  7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J
   658  ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef
   659  MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/
   660  Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT
   661  6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ
   662  0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm
   663  2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb
   664  bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c
   665  -----END CERTIFICATE-----`
   666  
   667  const googleLeaf = `-----BEGIN CERTIFICATE-----
   668  MIIFUjCCBDqgAwIBAgIQERmRWTzVoz0SMeozw2RM3DANBgkqhkiG9w0BAQsFADBG
   669  MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
   670  QzETMBEGA1UEAxMKR1RTIENBIDFDMzAeFw0yMzAxMDIwODE5MTlaFw0yMzAzMjcw
   671  ODE5MThaMBkxFzAVBgNVBAMTDnd3dy5nb29nbGUuY29tMIIBIjANBgkqhkiG9w0B
   672  AQEFAAOCAQ8AMIIBCgKCAQEAq30odrKMT54TJikMKL8S+lwoCMT5geP0u9pWjk6a
   673  wdB6i3kO+UE4ijCAmhbcZKeKaLnGJ38weZNwB1ayabCYyX7hDiC/nRcZU49LX5+o
   674  55kDVaNn14YKkg2kCeX25HDxSwaOsNAIXKPTqiQL5LPvc4Twhl8HY51hhNWQrTEr
   675  N775eYbixEULvyVLq5BLbCOpPo8n0/MTjQ32ku1jQq3GIYMJC/Rf2VW5doF6t9zs
   676  KleflAN8OdKp0ME9OHg0T1P3yyb67T7n0SpisHbeG06AmQcKJF9g/9VPJtRf4l1Q
   677  WRPDC+6JUqzXCxAGmIRGZ7TNMxPMBW/7DRX6w8oLKVNb0wIDAQABo4ICZzCCAmMw
   678  DgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQC
   679  MAAwHQYDVR0OBBYEFBnboj3lf9+Xat4oEgo6ZtIMr8ZuMB8GA1UdIwQYMBaAFIp0
   680  f6+Fze6VzT2c0OJGFPNxNR0nMGoGCCsGAQUFBwEBBF4wXDAnBggrBgEFBQcwAYYb
   681  aHR0cDovL29jc3AucGtpLmdvb2cvZ3RzMWMzMDEGCCsGAQUFBzAChiVodHRwOi8v
   682  cGtpLmdvb2cvcmVwby9jZXJ0cy9ndHMxYzMuZGVyMBkGA1UdEQQSMBCCDnd3dy5n
   683  b29nbGUuY29tMCEGA1UdIAQaMBgwCAYGZ4EMAQIBMAwGCisGAQQB1nkCBQMwPAYD
   684  VR0fBDUwMzAxoC+gLYYraHR0cDovL2NybHMucGtpLmdvb2cvZ3RzMWMzL1FPdkow
   685  TjFzVDJBLmNybDCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB2AHoyjFTYty22IOo4
   686  4FIe6YQWcDIThU070ivBOlejUutSAAABhXHHOiUAAAQDAEcwRQIgBUkikUIXdo+S
   687  3T8PP0/cvokhUlumRE3GRWGL4WRMLpcCIQDY+bwK384mZxyXGZ5lwNRTAPNzT8Fx
   688  1+//nbaGK3BQMAB2AOg+0No+9QY1MudXKLyJa8kD08vREWvs62nhd31tBr1uAAAB
   689  hXHHOfQAAAQDAEcwRQIgLoVydNfMFKV9IoZR+M0UuJ2zOqbxIRum7Sn9RMPOBGMC
   690  IQD1/BgzCSDTvYvco6kpB6ifKSbg5gcb5KTnYxQYwRW14TANBgkqhkiG9w0BAQsF
   691  AAOCAQEA2bQQu30e3OFu0bmvQHmcqYvXBu6tF6e5b5b+hj4O+Rn7BXTTmaYX3M6p
   692  MsfRH4YVJJMB/dc3PROR2VtnKFC6gAZX+RKM6nXnZhIlOdmQnonS1ecOL19PliUd
   693  VXbwKjXqAO0Ljd9y9oXaXnyPyHmUJNI5YXAcxE+XXiOZhcZuMYyWmoEKJQ/XlSga
   694  zWfTn1IcKhA3IC7A1n/5bkkWD1Xi1mdWFQ6DQDMp//667zz7pKOgFMlB93aPDjvI
   695  c78zEqNswn6xGKXpWF5xVwdFcsx9HKhJ6UAi2bQ/KQ1yb7LPUOR6wXXWrG1cLnNP
   696  i8eNLnKL9PXQ+5SwJFCzfEhcIZuhzg==
   697  -----END CERTIFICATE-----`
   698  
   699  // googleLeafWithInvalidHash is the same as googleLeaf, but the signature
   700  // algorithm in the certificate contains a nonsense OID.
   701  const googleLeafWithInvalidHash = `-----BEGIN CERTIFICATE-----
   702  MIIFUjCCBDqgAwIBAgIQERmRWTzVoz0SMeozw2RM3DANBgkqhkiG9w0BAQ4FADBG
   703  MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
   704  QzETMBEGA1UEAxMKR1RTIENBIDFDMzAeFw0yMzAxMDIwODE5MTlaFw0yMzAzMjcw
   705  ODE5MThaMBkxFzAVBgNVBAMTDnd3dy5nb29nbGUuY29tMIIBIjANBgkqhkiG9w0B
   706  AQEFAAOCAQ8AMIIBCgKCAQEAq30odrKMT54TJikMKL8S+lwoCMT5geP0u9pWjk6a
   707  wdB6i3kO+UE4ijCAmhbcZKeKaLnGJ38weZNwB1ayabCYyX7hDiC/nRcZU49LX5+o
   708  55kDVaNn14YKkg2kCeX25HDxSwaOsNAIXKPTqiQL5LPvc4Twhl8HY51hhNWQrTEr
   709  N775eYbixEULvyVLq5BLbCOpPo8n0/MTjQ32ku1jQq3GIYMJC/Rf2VW5doF6t9zs
   710  KleflAN8OdKp0ME9OHg0T1P3yyb67T7n0SpisHbeG06AmQcKJF9g/9VPJtRf4l1Q
   711  WRPDC+6JUqzXCxAGmIRGZ7TNMxPMBW/7DRX6w8oLKVNb0wIDAQABo4ICZzCCAmMw
   712  DgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQC
   713  MAAwHQYDVR0OBBYEFBnboj3lf9+Xat4oEgo6ZtIMr8ZuMB8GA1UdIwQYMBaAFIp0
   714  f6+Fze6VzT2c0OJGFPNxNR0nMGoGCCsGAQUFBwEBBF4wXDAnBggrBgEFBQcwAYYb
   715  aHR0cDovL29jc3AucGtpLmdvb2cvZ3RzMWMzMDEGCCsGAQUFBzAChiVodHRwOi8v
   716  cGtpLmdvb2cvcmVwby9jZXJ0cy9ndHMxYzMuZGVyMBkGA1UdEQQSMBCCDnd3dy5n
   717  b29nbGUuY29tMCEGA1UdIAQaMBgwCAYGZ4EMAQIBMAwGCisGAQQB1nkCBQMwPAYD
   718  VR0fBDUwMzAxoC+gLYYraHR0cDovL2NybHMucGtpLmdvb2cvZ3RzMWMzL1FPdkow
   719  TjFzVDJBLmNybDCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB2AHoyjFTYty22IOo4
   720  4FIe6YQWcDIThU070ivBOlejUutSAAABhXHHOiUAAAQDAEcwRQIgBUkikUIXdo+S
   721  3T8PP0/cvokhUlumRE3GRWGL4WRMLpcCIQDY+bwK384mZxyXGZ5lwNRTAPNzT8Fx
   722  1+//nbaGK3BQMAB2AOg+0No+9QY1MudXKLyJa8kD08vREWvs62nhd31tBr1uAAAB
   723  hXHHOfQAAAQDAEcwRQIgLoVydNfMFKV9IoZR+M0UuJ2zOqbxIRum7Sn9RMPOBGMC
   724  IQD1/BgzCSDTvYvco6kpB6ifKSbg5gcb5KTnYxQYwRW14TANBgkqhkiG9w0BAQ4F
   725  AAOCAQEA2bQQu30e3OFu0bmvQHmcqYvXBu6tF6e5b5b+hj4O+Rn7BXTTmaYX3M6p
   726  MsfRH4YVJJMB/dc3PROR2VtnKFC6gAZX+RKM6nXnZhIlOdmQnonS1ecOL19PliUd
   727  VXbwKjXqAO0Ljd9y9oXaXnyPyHmUJNI5YXAcxE+XXiOZhcZuMYyWmoEKJQ/XlSga
   728  zWfTn1IcKhA3IC7A1n/5bkkWD1Xi1mdWFQ6DQDMp//667zz7pKOgFMlB93aPDjvI
   729  c78zEqNswn6xGKXpWF5xVwdFcsx9HKhJ6UAi2bQ/KQ1yb7LPUOR6wXXWrG1cLnNP
   730  i8eNLnKL9PXQ+5SwJFCzfEhcIZuhzg==
   731  -----END CERTIFICATE-----`
   732  
   733  const smimeLeaf = `-----BEGIN CERTIFICATE-----
   734  MIIIPDCCBiSgAwIBAgIQaMDxFS0pOMxZZeOBxoTJtjANBgkqhkiG9w0BAQsFADCB
   735  nTELMAkGA1UEBhMCRVMxFDASBgNVBAoMC0laRU5QRSBTLkEuMTowOAYDVQQLDDFB
   736  WlogWml1cnRhZ2lyaSBwdWJsaWtvYSAtIENlcnRpZmljYWRvIHB1YmxpY28gU0NB
   737  MTwwOgYDVQQDDDNFQUVrbyBIZXJyaSBBZG1pbmlzdHJhemlvZW4gQ0EgLSBDQSBB
   738  QVBQIFZhc2NhcyAoMikwHhcNMTcwNzEyMDg1MzIxWhcNMjEwNzEyMDg1MzIxWjCC
   739  AQwxDzANBgNVBAoMBklaRU5QRTE4MDYGA1UECwwvWml1cnRhZ2lyaSBrb3Jwb3Jh
   740  dGlib2EtQ2VydGlmaWNhZG8gY29ycG9yYXRpdm8xQzBBBgNVBAsMOkNvbmRpY2lv
   741  bmVzIGRlIHVzbyBlbiB3d3cuaXplbnBlLmNvbSBub2xhIGVyYWJpbGkgamFraXRl
   742  a28xFzAVBgNVBC4TDi1kbmkgOTk5OTk5ODlaMSQwIgYDVQQDDBtDT1JQT1JBVElW
   743  TyBGSUNUSUNJTyBBQ1RJVk8xFDASBgNVBCoMC0NPUlBPUkFUSVZPMREwDwYDVQQE
   744  DAhGSUNUSUNJTzESMBAGA1UEBRMJOTk5OTk5ODlaMIIBIjANBgkqhkiG9w0BAQEF
   745  AAOCAQ8AMIIBCgKCAQEAwVOMwUDfBtsH0XuxYnb+v/L774jMH8valX7RPH8cl2Lb
   746  SiqSo0RchW2RGA2d1yuYHlpChC9jGmt0X/g66/E/+q2hUJlfJtqVDJFwtFYV4u2S
   747  yzA3J36V4PRkPQrKxAsbzZriFXAF10XgiHQz9aVeMMJ9GBhmh9+DK8Tm4cMF6i8l
   748  +AuC35KdngPF1x0ealTYrYZplpEJFO7CiW42aLi6vQkDR2R7nmZA4AT69teqBWsK
   749  0DZ93/f0G/3+vnWwNTBF0lB6dIXoaz8OMSyHLqGnmmAtMrzbjAr/O/WWgbB/BqhR
   750  qjJQ7Ui16cuDldXaWQ/rkMzsxmsAox0UF+zdQNvXUQIDAQABo4IDBDCCAwAwgccG
   751  A1UdEgSBvzCBvIYVaHR0cDovL3d3dy5pemVucGUuY29tgQ9pbmZvQGl6ZW5wZS5j
   752  b22kgZEwgY4xRzBFBgNVBAoMPklaRU5QRSBTLkEuIC0gQ0lGIEEwMTMzNzI2MC1S
   753  TWVyYy5WaXRvcmlhLUdhc3RlaXogVDEwNTUgRjYyIFM4MUMwQQYDVQQJDDpBdmRh
   754  IGRlbCBNZWRpdGVycmFuZW8gRXRvcmJpZGVhIDE0IC0gMDEwMTAgVml0b3JpYS1H
   755  YXN0ZWl6MB4GA1UdEQQXMBWBE2ZpY3RpY2lvQGl6ZW5wZS5ldXMwDgYDVR0PAQH/
   756  BAQDAgXgMCkGA1UdJQQiMCAGCCsGAQUFBwMCBggrBgEFBQcDBAYKKwYBBAGCNxQC
   757  AjAdBgNVHQ4EFgQUyeoOD4cgcljKY0JvrNuX2waFQLAwHwYDVR0jBBgwFoAUwKlK
   758  90clh/+8taaJzoLSRqiJ66MwggEnBgNVHSAEggEeMIIBGjCCARYGCisGAQQB8zkB
   759  AQEwggEGMDMGCCsGAQUFBwIBFidodHRwOi8vd3d3Lml6ZW5wZS5jb20vcnBhc2Nh
   760  Y29ycG9yYXRpdm8wgc4GCCsGAQUFBwICMIHBGoG+Wml1cnRhZ2lyaWEgRXVza2Fs
   761  IEF1dG9ub21pYSBFcmtpZGVnb2tvIHNla3RvcmUgcHVibGlrb2tvIGVyYWt1bmRl
   762  ZW4gYmFybmUtc2FyZWV0YW4gYmFrYXJyaWsgZXJhYmlsIGRhaXRla2UuIFVzbyBy
   763  ZXN0cmluZ2lkbyBhbCBhbWJpdG8gZGUgcmVkZXMgaW50ZXJuYXMgZGUgRW50aWRh
   764  ZGVzIGRlbCBTZWN0b3IgUHVibGljbyBWYXNjbzAyBggrBgEFBQcBAQQmMCQwIgYI
   765  KwYBBQUHMAGGFmh0dHA6Ly9vY3NwLml6ZW5wZS5jb20wOgYDVR0fBDMwMTAvoC2g
   766  K4YpaHR0cDovL2NybC5pemVucGUuY29tL2NnaS1iaW4vY3JsaW50ZXJuYTIwDQYJ
   767  KoZIhvcNAQELBQADggIBAIy5PQ+UZlCRq6ig43vpHwlwuD9daAYeejV0Q+ZbgWAE
   768  GtO0kT/ytw95ZEJMNiMw3fYfPRlh27ThqiT0VDXZJDlzmn7JZd6QFcdXkCsiuv4+
   769  ZoXAg/QwnA3SGUUO9aVaXyuOIIuvOfb9MzoGp9xk23SMV3eiLAaLMLqwB5DTfBdt
   770  BGI7L1MnGJBv8RfP/TL67aJ5bgq2ri4S8vGHtXSjcZ0+rCEOLJtmDNMnTZxancg3
   771  /H5edeNd+n6Z48LO+JHRxQufbC4mVNxVLMIP9EkGUejlq4E4w6zb5NwCQczJbSWL
   772  i31rk2orsNsDlyaLGsWZp3JSNX6RmodU4KAUPor4jUJuUhrrm3Spb73gKlV/gcIw
   773  bCE7mML1Kss3x1ySaXsis6SZtLpGWKkW2iguPWPs0ydV6RPhmsCxieMwPPIJ87vS
   774  5IejfgyBae7RSuAIHyNFy4uI5xwvwUFf6OZ7az8qtW7ImFOgng3Ds+W9k1S2CNTx
   775  d0cnKTfA6IpjGo8EeHcxnIXT8NPImWaRj0qqonvYady7ci6U4m3lkNSdXNn1afgw
   776  mYust+gxVtOZs1gk2MUCgJ1V1X+g7r/Cg7viIn6TLkLrpS1kS1hvMqkl9M+7XqPo
   777  Qd95nJKOkusQpy99X4dF/lfbYAQnnjnqh3DLD2gvYObXFaAYFaiBKTiMTV2X72F+
   778  -----END CERTIFICATE-----`
   779  
   780  const smimeIntermediate = `-----BEGIN CERTIFICATE-----
   781  MIIHNzCCBSGgAwIBAgIQJMXIqlZvjuhMvqcFXOFkpDALBgkqhkiG9w0BAQswODEL
   782  MAkGA1UEBhMCRVMxFDASBgNVBAoMC0laRU5QRSBTLkEuMRMwEQYDVQQDDApJemVu
   783  cGUuY29tMB4XDTEwMTAyMDA4MjMzM1oXDTM3MTIxMjIzMDAwMFowgZ0xCzAJBgNV
   784  BAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjE6MDgGA1UECwwxQVpaIFppdXJ0
   785  YWdpcmkgcHVibGlrb2EgLSBDZXJ0aWZpY2FkbyBwdWJsaWNvIFNDQTE8MDoGA1UE
   786  AwwzRUFFa28gSGVycmkgQWRtaW5pc3RyYXppb2VuIENBIC0gQ0EgQUFQUCBWYXNj
   787  YXMgKDIpMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoIM7nEdI0N1h
   788  rR5T4xuV/usKDoMIasaiKvfLhbwxaNtTt+a7W/6wV5bv3svQFIy3sUXjjdzV1nG2
   789  To2wo/YSPQiOt8exWvOapvL21ogiof+kelWnXFjWaKJI/vThHYLgIYEMj/y4HdtU
   790  ojI646rZwqsb4YGAopwgmkDfUh5jOhV2IcYE3TgJAYWVkj6jku9PLaIsHiarAHjD
   791  PY8dig8a4SRv0gm5Yk7FXLmW1d14oxQBDeHZ7zOEXfpafxdEDO2SNaRJjpkh8XRr
   792  PGqkg2y1Q3gT6b4537jz+StyDIJ3omylmlJsGCwqT7p8mEqjGJ5kC5I2VnjXKuNn
   793  soShc72khWZVUJiJo5SGuAkNE2ZXqltBVm5Jv6QweQKsX6bkcMc4IZok4a+hx8FM
   794  8IBpGf/I94pU6HzGXqCyc1d46drJgDY9mXa+6YDAJFl3xeXOOW2iGCfwXqhiCrKL
   795  MYvyMZzqF3QH5q4nb3ZnehYvraeMFXJXDn+Utqp8vd2r7ShfQJz01KtM4hgKdgSg
   796  jtW+shkVVN5ng/fPN85ovfAH2BHXFfHmQn4zKsYnLitpwYM/7S1HxlT61cdQ7Nnk
   797  3LZTYEgAoOmEmdheklT40WAYakksXGM5VrzG7x9S7s1Tm+Vb5LSThdHC8bxxwyTb
   798  KsDRDNJ84N9fPDO6qHnzaL2upQ43PycCAwEAAaOCAdkwggHVMIHHBgNVHREEgb8w
   799  gbyGFWh0dHA6Ly93d3cuaXplbnBlLmNvbYEPaW5mb0BpemVucGUuY29tpIGRMIGO
   800  MUcwRQYDVQQKDD5JWkVOUEUgUy5BLiAtIENJRiBBMDEzMzcyNjAtUk1lcmMuVml0
   801  b3JpYS1HYXN0ZWl6IFQxMDU1IEY2MiBTODFDMEEGA1UECQw6QXZkYSBkZWwgTWVk
   802  aXRlcnJhbmVvIEV0b3JiaWRlYSAxNCAtIDAxMDEwIFZpdG9yaWEtR2FzdGVpejAP
   803  BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUwKlK90cl
   804  h/+8taaJzoLSRqiJ66MwHwYDVR0jBBgwFoAUHRxlDqjyJXu0kc/ksbHmvVV0bAUw
   805  OgYDVR0gBDMwMTAvBgRVHSAAMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly93d3cuaXpl
   806  bnBlLmNvbS9jcHMwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8v
   807  b2NzcC5pemVucGUuY29tOjgwOTQwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2Ny
   808  bC5pemVucGUuY29tL2NnaS1iaW4vYXJsMjALBgkqhkiG9w0BAQsDggIBAMbjc3HM
   809  3DG9ubWPkzsF0QsktukpujbTTcGk4h20G7SPRy1DiiTxrRzdAMWGjZioOP3/fKCS
   810  M539qH0M+gsySNie+iKlbSZJUyE635T1tKw+G7bDUapjlH1xyv55NC5I6wCXGC6E
   811  3TEP5B/E7dZD0s9E4lS511ubVZivFgOzMYo1DO96diny/N/V1enaTCpRl1qH1OyL
   812  xUYTijV4ph2gL6exwuG7pxfRcVNHYlrRaXWfTz3F6NBKyULxrI3P/y6JAtN1GqT4
   813  VF/+vMygx22n0DufGepBwTQz6/rr1ulSZ+eMnuJiTXgh/BzQnkUsXTb8mHII25iR
   814  0oYF2qAsk6ecWbLiDpkHKIDHmML21MZE13MS8NSvTHoqJO4LyAmDe6SaeNHtrPlK
   815  b6mzE1BN2ug+ZaX8wLA5IMPFaf0jKhb/Cxu8INsxjt00brsErCc9ip1VNaH0M4bi
   816  1tGxfiew2436FaeyUxW7Pl6G5GgkNbuUc7QIoRy06DdU/U38BxW3uyJMY60zwHvS
   817  FlKAn0OvYp4niKhAJwaBVN3kowmJuOU5Rid+TUnfyxbJ9cttSgzaF3hP/N4zgMEM
   818  5tikXUskeckt8LUK96EH0QyssavAMECUEb/xrupyRdYWwjQGvNLq6T5+fViDGyOw
   819  k+lzD44wofy8paAy9uC9Owae0zMEzhcsyRm7
   820  -----END CERTIFICATE-----`
   821  
   822  const smimeRoot = `-----BEGIN CERTIFICATE-----
   823  MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4
   824  MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6
   825  ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD
   826  VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j
   827  b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq
   828  scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO
   829  xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H
   830  LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX
   831  uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD
   832  yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+
   833  JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q
   834  rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN
   835  BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L
   836  hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB
   837  QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+
   838  HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu
   839  Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg
   840  QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB
   841  BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
   842  MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
   843  AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA
   844  A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb
   845  laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56
   846  awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo
   847  JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw
   848  LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT
   849  VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk
   850  LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb
   851  UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/
   852  QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+
   853  naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls
   854  QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
   855  -----END CERTIFICATE-----`
   856  
   857  var nameConstraintsLeaf = `-----BEGIN CERTIFICATE-----
   858  MIIG+jCCBOKgAwIBAgIQWj9gbtPPkZs65N6TKyutRjANBgkqhkiG9w0BAQsFADCB
   859  yzELMAkGA1UEBhMCVVMxETAPBgNVBAgTCFZpcmdpbmlhMRMwEQYDVQQHEwpCbGFj
   860  a3NidXJnMSMwIQYDVQQLExpHbG9iYWwgUXVhbGlmaWVkIFNlcnZlciBDQTE8MDoG
   861  A1UEChMzVmlyZ2luaWEgUG9seXRlY2huaWMgSW5zdGl0dXRlIGFuZCBTdGF0ZSBV
   862  bml2ZXJzaXR5MTEwLwYDVQQDEyhWaXJnaW5pYSBUZWNoIEdsb2JhbCBRdWFsaWZp
   863  ZWQgU2VydmVyIENBMB4XDTE4MDQyNjE5NDU1M1oXDTE5MTIxMDAwMDAwMFowgZAx
   864  CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tz
   865  YnVyZzE8MDoGA1UEChMzVmlyZ2luaWEgUG9seXRlY2huaWMgSW5zdGl0dXRlIGFu
   866  ZCBTdGF0ZSBVbml2ZXJzaXR5MRswGQYDVQQDExJ1ZGN0ZXN0LmFkcy52dC5lZHUw
   867  ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCcoVBeV3AzdSGMzRWH0tuM
   868  VluEj+sq4r9PuLDBAdgjjHi4ED8npT2/fgOalswInXspRvFS+pkEwTrmeZ7HPzRJ
   869  HUE5YlX5Nc6WI8ZXPVg5E6GyoMy6gNlALwqsIvDCvqxBMc39oG6yOuGmQXdF6s0N
   870  BJMrXc4aPz60s4QMWNO2OHL0pmnZqE1TxYRBHUY/dk3cfsIepIDDuSxRsNE/P/MI
   871  pxm/uVOyiLEnPmOMsL430SZ7nC8PxUMqya9ok6Zaf7k54g7JJXDjE96VMCjMszIv
   872  Ud9qe1PbokTOxlG/4QW7Qm0dPbiJhTUuoBzVAxzlOOkSFdXqSYKjC9tFcbr8y+pT
   873  AgMBAAGjggIRMIICDTCBtgYIKwYBBQUHAQEEgakwgaYwXwYIKwYBBQUHMAKGU2h0
   874  dHA6Ly93d3cucGtpLnZ0LmVkdS9nbG9iYWxxdWFsaWZpZWRzZXJ2ZXIvY2FjZXJ0
   875  L2dsb2JhbHF1YWxpZmllZHNlcnZlcl9zaGEyNTYuY3J0MEMGCCsGAQUFBzABhjdo
   876  dHRwOi8vdnRjYS5wa2kudnQuZWR1OjgwODAvZWpiY2EvcHVibGljd2ViL3N0YXR1
   877  cy9vY3NwMB0GA1UdDgQWBBSzDLXee0wbgXpVQxvBQCophQDZbTAMBgNVHRMBAf8E
   878  AjAAMB8GA1UdIwQYMBaAFLxiYCfV4zVIF+lLq0Vq0Miod3GMMGoGA1UdIARjMGEw
   879  DgYMKwYBBAG0aAUCAgIBMA4GDCsGAQQBtGgFAgIBATA/BgwrBgEEAbRoBQICAwEw
   880  LzAtBggrBgEFBQcCARYhaHR0cDovL3d3dy5wa2kudnQuZWR1L2dsb2JhbC9jcHMv
   881  MEoGA1UdHwRDMEEwP6A9oDuGOWh0dHA6Ly93d3cucGtpLnZ0LmVkdS9nbG9iYWxx
   882  dWFsaWZpZWRzZXJ2ZXIvY3JsL2NhY3JsLmNybDAOBgNVHQ8BAf8EBAMCBeAwHQYD
   883  VR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMB0GA1UdEQQWMBSCEnVkY3Rlc3Qu
   884  YWRzLnZ0LmVkdTANBgkqhkiG9w0BAQsFAAOCAgEAD79kuyZbwQJCSBOVq9lA0lj4
   885  juHM7RMBfp2GuWvhk5F90OMKQCNdITva3oq4uQzt013TtwposYXq/d0Jobk6RHxj
   886  OJzRZVvEPsXLvKm8oLhz7/qgI8gcVeJFR9WgdNhjN1upn++EnABHUdDR77fgixuH
   887  FFwNC0WSZ6G0+WgYV7MKD4jYWh1DXEaJtQCN763IaWGxgvQaLUwS423xgwsx+8rw
   888  hCRYns5u8myTbUlEu2b+GYimiogtDFMT01A7y88vKl9g+3bx42dJHQNNmSzmYPfs
   889  IljtQbVwJIyNL/rwjoz7BTk8e9WY0qUK7ZYh+oGK8kla8yfPKtkvOJV29KdFKzTm
   890  42kNm6cH+U5gGwEEg+Xj66Q2yFH5J9kAoBazTepgQ/13wwTY0mU9PtKVBtMH5Y/u
   891  MoNVZz6p7vWWRrY5qSXIaW9qyF3bZnmPEHHYTplWsyAyh8blGlqPnpayDflPiQF/
   892  9y37kax5yhT0zPZW1ZwIZ5hDTO7pu5i83bYh3pzhvJNHtv74Nn/SX1dTZrWBi/HG
   893  OSWK3CLz8qAEBe72XGoBjBzuk9VQxg6k52qjxCyYf7CBSQpTZhsNMf0gzu+JNATc
   894  b+XaOqJT6uI/RfqAJVe16ZeXZIFZgQlzIwRS9vobq9fqTIpH/QxqgXROGqAlbBVp
   895  /ByH6FEe6+oH1UCklhg=
   896  -----END CERTIFICATE-----`
   897  
   898  var nameConstraintsIntermediate1 = `-----BEGIN CERTIFICATE-----
   899  MIIHVTCCBj2gAwIBAgINAecHzcaPEeFvu7X4TTANBgkqhkiG9w0BAQsFADBjMQsw
   900  CQYDVQQGEwJCRTEVMBMGA1UECxMMVHJ1c3RlZCBSb290MRkwFwYDVQQKExBHbG9i
   901  YWxTaWduIG52LXNhMSIwIAYDVQQDExlUcnVzdGVkIFJvb3QgQ0EgU0hBMjU2IEcy
   902  MB4XDTE3MTIwNjAwMDAwMFoXDTIyMTIwNjAwMDAwMFowgcsxCzAJBgNVBAYTAlVT
   903  MREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tzYnVyZzEjMCEGA1UE
   904  CxMaR2xvYmFsIFF1YWxpZmllZCBTZXJ2ZXIgQ0ExPDA6BgNVBAoTM1Zpcmdpbmlh
   905  IFBvbHl0ZWNobmljIEluc3RpdHV0ZSBhbmQgU3RhdGUgVW5pdmVyc2l0eTExMC8G
   906  A1UEAxMoVmlyZ2luaWEgVGVjaCBHbG9iYWwgUXVhbGlmaWVkIFNlcnZlciBDQTCC
   907  AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALgIZhEaptBWADBqdJ45ueFG
   908  zMXaGHnzNxoxR1fQIaaRQNdCg4cw3A4dWKMeEgYLtsp65ai3Xfw62Qaus0+KJ3Rh
   909  gV+rihqK81NUzkls78fJlADVDI4fCTlothsrE1CTOMiy97jKHai5mVTiWxmcxpmj
   910  v7fm5Nhc+uHgh2hIz6npryq495mD51ZrUTIaqAQN6Pw/VHfAmR524vgriTOjtp1t
   911  4lA9pXGWjF/vkhAKFFheOQSQ00rngo2wHgCqMla64UTN0oz70AsCYNZ3jDLx0kOP
   912  0YmMR3Ih91VA63kLqPXA0R6yxmmhhxLZ5bcyAy1SLjr1N302MIxLM/pSy6aquEnb
   913  ELhzqyp9yGgRyGJay96QH7c4RJY6gtcoPDbldDcHI9nXngdAL4DrZkJ9OkDkJLyq
   914  G66WZTF5q4EIs6yMdrywz0x7QP+OXPJrjYpbeFs6tGZCFnWPFfmHCRJF8/unofYr
   915  heq+9J7Jx3U55S/k57NXbAM1RAJOuMTlfn9Etf9Dpoac9poI4Liav6rBoUQk3N3J
   916  WqnVHNx/NdCyJ1/6UbKMJUZsStAVglsi6lVPo289HHOE4f7iwl3SyekizVOp01wU
   917  in3ycnbZB/rXmZbwapSxTTSBf0EIOr9i4EGfnnhCAVA9U5uLrI5OEB69IY8PNX00
   918  71s3Z2a2fio5c8m3JkdrAgMBAAGjggKdMIICmTAOBgNVHQ8BAf8EBAMCAQYwHQYD
   919  VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8CAQAw
   920  HQYDVR0OBBYEFLxiYCfV4zVIF+lLq0Vq0Miod3GMMB8GA1UdIwQYMBaAFMhjmwhp
   921  VMKYyNnN4zO3UF74yQGbMIGNBggrBgEFBQcBAQSBgDB+MDcGCCsGAQUFBzABhito
   922  dHRwOi8vb2NzcDIuZ2xvYmFsc2lnbi5jb20vdHJ1c3Ryb290c2hhMmcyMEMGCCsG
   923  AQUFBzAChjdodHRwOi8vc2VjdXJlLmdsb2JhbHNpZ24uY29tL2NhY2VydC90cnVz
   924  dHJvb3RzaGEyZzIuY3J0MIHyBgNVHR4EgeowgeeggbIwCIEGdnQuZWR1MAmCB2Jl
   925  di5uZXQwCoIIdmNvbS5lZHUwCIIGdnQuZWR1MAyCCnZ0Y2dpdC5jb20wd6R1MHMx
   926  CzAJBgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTETMBEGA1UEBxMKQmxhY2tz
   927  YnVyZzE8MDoGA1UEChMzVmlyZ2luaWEgUG9seXRlY2huaWMgSW5zdGl0dXRlIGFu
   928  ZCBTdGF0ZSBVbml2ZXJzaXR5oTAwCocIAAAAAAAAAAAwIocgAAAAAAAAAAAAAAAA
   929  AAAAAAAAAAAAAAAAAAAAAAAAAAAwQQYDVR0fBDowODA2oDSgMoYwaHR0cDovL2Ny
   930  bC5nbG9iYWxzaWduLmNvbS9ncy90cnVzdHJvb3RzaGEyZzIuY3JsMEwGA1UdIARF
   931  MEMwQQYJKwYBBAGgMgE8MDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2Jh
   932  bHNpZ24uY29tL3JlcG9zaXRvcnkvMA0GCSqGSIb3DQEBCwUAA4IBAQArHocpEKTv
   933  DW1Hw0USj60KN96aLJXTLm05s0LbjloeTePtDFtuisrbE85A0IhCwxdIl/VsQMZB
   934  7mQZBEmLzR+NK1/Luvs7C6WTmkqrE8H7D73dSOab5fMZIXS91V/aEtEQGpJMhwi1
   935  svd9TiiQrVkagrraeRWmTTz9BtUA3CeujuW2tShxF1ew4Q4prYw97EsE4HnKDJtu
   936  RtyTqKsuh/rRvKMmgUdEPZbVI23yzUKhi/mTbyml/35x/f6f5p7OYIKcQ/34sts8
   937  xoW9dfkWBQKAXCstXat3WJVilGXBFub6GoVZdnxTDipyMZhUT/vzXq2bPphjcdR5
   938  YGbmwyYmChfa
   939  -----END CERTIFICATE-----`
   940  
   941  var nameConstraintsIntermediate2 = `-----BEGIN CERTIFICATE-----
   942  MIIEXDCCA0SgAwIBAgILBAAAAAABNumCOV0wDQYJKoZIhvcNAQELBQAwTDEgMB4G
   943  A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
   944  Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIwNDI1MTEwMDAwWhcNMjcwNDI1
   945  MTEwMDAwWjBjMQswCQYDVQQGEwJCRTEVMBMGA1UECxMMVHJ1c3RlZCBSb290MRkw
   946  FwYDVQQKExBHbG9iYWxTaWduIG52LXNhMSIwIAYDVQQDExlUcnVzdGVkIFJvb3Qg
   947  Q0EgU0hBMjU2IEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz80+
   948  /Q2PAhLuYwe04YTLBLGKr1/JScHtDvAY5E94GjGxCbSR1/1VhL880UPJyN85tddO
   949  oxZPgtIyZixDvvK+CgpT5webyBBbqK/ap7aoByghAJ7X520XZMRwKA6cEWa6tjCL
   950  WH1zscxQxGzgtV50rn2ux2SapoCPxMpM4+tpEVwWJf3KP3NT+jd9GRaXWgNei5JK
   951  Quo9l+cZkSeuoWijvaer5hcLCufPywMMQd0r6XXIM/l7g9DjMaE24d+fa2bWxQXC
   952  8WT/PZ+D1KUEkdtn/ixADqsoiIibGn7M84EE9/NLjbzPrwROlBUJFz6cuw+II0rZ
   953  8OFFeZ/OkHHYZq2h9wIDAQABo4IBJjCCASIwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
   954  EwEB/wQFMAMBAf8wRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0
   955  dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMB0GA1UdDgQWBBTI
   956  Y5sIaVTCmMjZzeMzt1Be+MkBmzA2BgNVHR8ELzAtMCugKaAnhiVodHRwOi8vY3Js
   957  Lmdsb2JhbHNpZ24ubmV0L3Jvb3QtcjMuY3JsMD4GCCsGAQUFBwEBBDIwMDAuBggr
   958  BgEFBQcwAYYiaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL3Jvb3RyMzAfBgNV
   959  HSMEGDAWgBSP8Et/qC5FJK5NUPpjmove4t0bvDANBgkqhkiG9w0BAQsFAAOCAQEA
   960  XzbLwBjJiY6j3WEcxD3eVnsIY4pY3bl6660tgpxCuLVx4o1xyiVkS/BcQFD7GIoX
   961  FBRrf5HibO1uSEOw0QZoRwlsio1VPg1PRaccG5C1sB51l/TL1XH5zldZBCnRYrrF
   962  qCPorxi0xoRogj8kqkS2xyzYLElhx9X7jIzfZ8dC4mgOeoCtVvwM9xvmef3n6Vyb
   963  7/hl3w/zWwKxWyKJNaF7tScD5nvtLUzyBpr++aztiyJ1WliWcS6W+V2gKg9rxEC/
   964  rc2yJS70DvfkPiEnBJ2x2AHZV3yKTALUqurkV705JledqUT9I5frAwYNXZ8pNzde
   965  n+DIcSIo7yKy6MX9czbFWQ==
   966  -----END CERTIFICATE-----`
   967  
   968  var globalSignRoot = `-----BEGIN CERTIFICATE-----
   969  MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
   970  A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
   971  Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
   972  MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
   973  A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
   974  hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
   975  RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
   976  gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
   977  KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
   978  QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
   979  XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
   980  DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
   981  LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
   982  RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
   983  jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
   984  6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
   985  mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
   986  Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
   987  WD9f
   988  -----END CERTIFICATE-----`
   989  
   990  const digicertRoot = `-----BEGIN CERTIFICATE-----
   991  MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
   992  MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
   993  d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
   994  QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
   995  MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
   996  b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
   997  9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
   998  CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
   999  nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
  1000  43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
  1001  T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
  1002  gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
  1003  BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
  1004  TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
  1005  DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
  1006  hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
  1007  06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
  1008  PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
  1009  YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
  1010  CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
  1011  -----END CERTIFICATE-----`
  1012  
  1013  const trustAsiaSHA384Intermediate = `-----BEGIN CERTIFICATE-----
  1014  MIID9zCCAt+gAwIBAgIQC965p4OR4AKrGlsyW0XrDzANBgkqhkiG9w0BAQwFADBh
  1015  MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
  1016  d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
  1017  QTAeFw0xODA0MjcxMjQyNTlaFw0yODA0MjcxMjQyNTlaMFoxCzAJBgNVBAYTAkNO
  1018  MSUwIwYDVQQKExxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQwIgYDVQQD
  1019  ExtUcnVzdEFzaWEgRUNDIE9WIFRMUyBQcm8gQ0EwdjAQBgcqhkjOPQIBBgUrgQQA
  1020  IgNiAAQPIUn75M5BCQLKoPsSU2KTr3mDMh13usnAQ38XfKOzjXiyQ+W0inA7meYR
  1021  xS+XMQgvnbCigEsKj3ErPIzO68uC9V/KdqMaXWBJp85Ws9A4KL92NB4Okbn5dp6v
  1022  Qzy08PajggFeMIIBWjAdBgNVHQ4EFgQULdRyBx6HyIH/+LOvuexyH5p/3PwwHwYD
  1023  VR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDgYDVR0PAQH/BAQDAgGGMB0G
  1024  A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEA
  1025  MDcGCCsGAQUFBwEBBCswKTAnBggrBgEFBQcwAYYbaHR0cDovL29jc3AuZGlnaWNl
  1026  cnQtY24uY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwuZGlnaWNlcnQt
  1027  Y24uY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDBWBgNVHSAETzBNMDcGCWCG
  1028  SAGG/WwBATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20v
  1029  Q1BTMAgGBmeBDAECAjAIBgZngQwBAgMwDQYJKoZIhvcNAQEMBQADggEBACVRufYd
  1030  j81xUqngFCO+Pk8EYXie0pxHKsBZnOPygAyXKx+awUasKBAnHjmhoFPXaDGAP2oV
  1031  OeZTWgwnURVr6wUCuTkz2/8Tgl1egC7OrVcHSa0fIIhaVo9/zRA/hr31xMG7LFBk
  1032  GNd7jd06Up4f/UOGbcJsqJexc5QRcUeSwe1MiUDcTNiyCjZk74QCPdcfdFYM4xsa
  1033  SlUpboB5vyT7jFePZ2v95CKjcr0EhiQ0gwxpdgoipZdfYTiMFGxCLsk6v8pUv7Tq
  1034  PT/qadOGyC+PfLuZh1PtLp20mF06K+MzheCiv+w1NT5ofhmcObvukc68wvbvRFL6
  1035  rRzZxAYN36q1SX8=
  1036  -----END CERTIFICATE-----`
  1037  
  1038  const trustAsiaLeaf = `-----BEGIN CERTIFICATE-----
  1039  MIIEwTCCBEegAwIBAgIQBOjomZfHfhgz2bVYZVuf2DAKBggqhkjOPQQDAzBaMQsw
  1040  CQYDVQQGEwJDTjElMCMGA1UEChMcVHJ1c3RBc2lhIFRlY2hub2xvZ2llcywgSW5j
  1041  LjEkMCIGA1UEAxMbVHJ1c3RBc2lhIEVDQyBPViBUTFMgUHJvIENBMB4XDTE5MDUx
  1042  NzAwMDAwMFoXDTIwMDcyODEyMDAwMFowgY0xCzAJBgNVBAYTAkNOMRIwEAYDVQQI
  1043  DAnnpo/lu7rnnIExEjAQBgNVBAcMCeWOpumXqOW4gjEqMCgGA1UECgwh5Y6m6Zeo
  1044  5Y+B546W5Y+B56eR5oqA5pyJ6ZmQ5YWs5Y+4MRgwFgYDVQQLDA/nn6Xor4bkuqfm
  1045  nYPpg6gxEDAOBgNVBAMMByoudG0uY24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
  1046  AARx/MDQ0oGnCLagQIzjIz57iqFYFmz4/W6gaU6N+GHBkzyvQU8aX02QkdlTTNYL
  1047  TCoGFJxHB0XlZVSxrqoIPlNKo4ICuTCCArUwHwYDVR0jBBgwFoAULdRyBx6HyIH/
  1048  +LOvuexyH5p/3PwwHQYDVR0OBBYEFGTyf5adc5smW8NvDZyummJwZRLEMBkGA1Ud
  1049  EQQSMBCCByoudG0uY26CBXRtLmNuMA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAU
  1050  BggrBgEFBQcDAQYIKwYBBQUHAwIwRgYDVR0fBD8wPTA7oDmgN4Y1aHR0cDovL2Ny
  1051  bC5kaWdpY2VydC1jbi5jb20vVHJ1c3RBc2lhRUNDT1ZUTFNQcm9DQS5jcmwwTAYD
  1052  VR0gBEUwQzA3BglghkgBhv1sAQEwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cu
  1053  ZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBAgIwfgYIKwYBBQUHAQEEcjBwMCcGCCsG
  1054  AQUFBzABhhtodHRwOi8vb2NzcC5kaWdpY2VydC1jbi5jb20wRQYIKwYBBQUHMAKG
  1055  OWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LWNuLmNvbS9UcnVzdEFzaWFFQ0NPVlRM
  1056  U1Byb0NBLmNydDAMBgNVHRMBAf8EAjAAMIIBAwYKKwYBBAHWeQIEAgSB9ASB8QDv
  1057  AHUA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFqxGMTnwAABAMA
  1058  RjBEAiAz13zKEoyqd4e/96SK/fxfjl7uR+xhfoDZeyA1BvtfOwIgTY+8nJMGekv8
  1059  leIVdW6AGh7oqH31CIGTAbNJJWzaSFYAdgCHdb/nWXz4jEOZX73zbv9WjUdWNv9K
  1060  tWDBtOr/XqCDDwAAAWrEYxTCAAAEAwBHMEUCIQDlWm7+limbRiurcqUwXav3NSmx
  1061  x/aMnolLbh6+f+b1XAIgQfinHwLw6pDr4R9UkndUsX8QFF4GXS3/IwRR8HCp+pIw
  1062  CgYIKoZIzj0EAwMDaAAwZQIwHg8JmjRtcq+OgV0vVmdVBPqehi1sQJ9PZ+51CG+Z
  1063  0GOu+2HwS/fyLRViwSc/MZoVAjEA7NgbgpPN4OIsZn2XjMGxemtVxGFS6ZR+1364
  1064  EEeHB9vhZAEjQSePAfjR9aAGhXRa
  1065  -----END CERTIFICATE-----`
  1066  
  1067  const selfSigned = `-----BEGIN CERTIFICATE-----
  1068  MIIC/DCCAeSgAwIBAgIRAK0SWRVmi67xU3z0gkgY+PkwDQYJKoZIhvcNAQELBQAw
  1069  EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xNjA4MTkxNjMzNDdaFw0xNzA4MTkxNjMz
  1070  NDdaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
  1071  ggEKAoIBAQDWkm1kdCwxyKEt6OTmZitkmLGH8cQu9z7rUdrhW8lWNm4kh2SuaUWP
  1072  pscBjda5iqg51aoKuWJR2rw6ElDne+X5eit2FT8zJgAU8v39lMFjbaVZfS9TFOYF
  1073  w0Tk0Luo/PyKJpZnwhsP++iiGQiteJbndy8aLKmJ2MpLfpDGIgxEIyNb5dgoDi0D
  1074  WReDCpE6K9WDYqvKVGnQ2Jvqqra6Gfx0tFkuqJxQuqA8aUOlPHcCH4KBZdNEoXdY
  1075  YL3E4dCAh0YiDs80wNZx4cHqEM3L8gTEFqW2Tn1TSuPZO6gjJ9QPsuUZVjaMZuuO
  1076  NVxqLGujZkDzARhC3fBpptMuaAfi20+BAgMBAAGjTTBLMA4GA1UdDwEB/wQEAwIF
  1077  oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBYGA1UdEQQPMA2C
  1078  C2Zvby5leGFtcGxlMA0GCSqGSIb3DQEBCwUAA4IBAQBPvvfnDhsHWt+/cfwdAVim
  1079  4EDn+hYOMkTQwU0pouYIvY8QXYkZ8MBxpBtBMK4JhFU+ewSWoBAEH2dCCvx/BDxN
  1080  UGTSJHMbsvJHcFvdmsvvRxOqQ/cJz7behx0cfoeHMwcs0/vWv8ms5wHesb5Ek7L0
  1081  pl01FCBGTcncVqr6RK1r4fTpeCCfRIERD+YRJz8TtPH6ydesfLL8jIV40H8NiDfG
  1082  vRAvOtNiKtPzFeQVdbRPOskC4rcHyPeiDAMAMixeLi63+CFty4da3r5lRezeedCE
  1083  cw3ESZzThBwWqvPOtJdpXdm+r57pDW8qD+/0lY8wfImMNkQAyCUCLg/1Lxt/hrBj
  1084  -----END CERTIFICATE-----`
  1085  
  1086  const issuerSubjectMatchRoot = `-----BEGIN CERTIFICATE-----
  1087  MIICIDCCAYmgAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwIzEPMA0GA1UE
  1088  ChMGR29sYW5nMRAwDgYDVQQDEwdSb290IGNhMB4XDTE1MDEwMTAwMDAwMFoXDTI1
  1089  MDEwMTAwMDAwMFowIzEPMA0GA1UEChMGR29sYW5nMRAwDgYDVQQDEwdSb290IGNh
  1090  MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1
  1091  siSSOO4mYgLHlPE+oXdqwI/VImi2XeJM2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw
  1092  +QzGj+mz36NqhGxDWb6dstB2m8PX+plZw7jl81MDvUnWs8yiQ/6twgu5AbhWKZQD
  1093  JKcNKCEpqa6UW0r5nwIDAQABo10wWzAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYw
  1094  FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIE
  1095  EEA31wH7QC+4HH5UBCeMWQEwDQYJKoZIhvcNAQELBQADgYEAb4TfSeCZ1HFmHTKG
  1096  VsvqWmsOAGrRWm4fBiMH/8vRGnTkJEMLqiqgc3Ulgry/P6n4SIis7TqUOw3TiMhn
  1097  RGEz33Fsxa/tFoy/gvlJu+MqB1M2NyV33pGkdwl/b7KRWMQFieqO+uE7Ge/49pS3
  1098  eyfm5ITdK/WT9TzYhsU4AVZcn20=
  1099  -----END CERTIFICATE-----`
  1100  
  1101  const issuerSubjectMatchLeaf = `-----BEGIN CERTIFICATE-----
  1102  MIICODCCAaGgAwIBAgIJAOjwnT/iW+qmMA0GCSqGSIb3DQEBCwUAMCMxDzANBgNV
  1103  BAoTBkdvbGFuZzEQMA4GA1UEAxMHUm9vdCBDQTAeFw0xNTAxMDEwMDAwMDBaFw0y
  1104  NTAxMDEwMDAwMDBaMCAxDzANBgNVBAoTBkdvbGFuZzENMAsGA1UEAxMETGVhZjCB
  1105  nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA20Z9ky4SJwZIvAYoIat+xLaiXf4e
  1106  UkWIejZHpQgNkkJbwoHAvpd5mED7T20U/SsTi8KlLmfY1Ame1iI4t0oLdHMrwjTx
  1107  0ZPlltl0e/NYn2xhPMCwQdTZKyskI3dbHDu9dV3OIFTPoWOHHR4kxPMdGlCLqrYU
  1108  Q+2Xp3Vi9BTIUtcCAwEAAaN3MHUwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQG
  1109  CCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMBkGA1UdDgQSBBCfkRYf
  1110  Q0M+SabebbaA159gMBsGA1UdIwQUMBKAEEA31wH7QC+4HH5UBCeMWQEwDQYJKoZI
  1111  hvcNAQELBQADgYEAjYYF2on1HcUWFEG5NIcrXDiZ49laW3pb3gtcCEUJbxydMV8I
  1112  ynqjmdqDCyK+TwI1kU5dXDe/iSJYfTB20i/QoO53nnfA1hnr7KBjNWqAm4AagN5k
  1113  vEA4PCJprUYmoj3q9MKSSRYDlq5kIbl87mSRR4GqtAwJKxIasvOvULOxziQ=
  1114  -----END CERTIFICATE-----`
  1115  
  1116  const x509v1TestRoot = `-----BEGIN CERTIFICATE-----
  1117  MIICIDCCAYmgAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwIzEPMA0GA1UE
  1118  ChMGR29sYW5nMRAwDgYDVQQDEwdSb290IENBMB4XDTE1MDEwMTAwMDAwMFoXDTI1
  1119  MDEwMTAwMDAwMFowIzEPMA0GA1UEChMGR29sYW5nMRAwDgYDVQQDEwdSb290IENB
  1120  MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1
  1121  siSSOO4mYgLHlPE+oXdqwI/VImi2XeJM2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw
  1122  +QzGj+mz36NqhGxDWb6dstB2m8PX+plZw7jl81MDvUnWs8yiQ/6twgu5AbhWKZQD
  1123  JKcNKCEpqa6UW0r5nwIDAQABo10wWzAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYw
  1124  FAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIE
  1125  EEA31wH7QC+4HH5UBCeMWQEwDQYJKoZIhvcNAQELBQADgYEAcIwqeNUpQr9cOcYm
  1126  YjpGpYkQ6b248xijCK7zI+lOeWN89zfSXn1AvfsC9pSdTMeDklWktbF/Ad0IN8Md
  1127  h2NtN34ard0hEfHc8qW8mkXdsysVmq6cPvFYaHz+dBtkHuHDoy8YQnC0zdN/WyYB
  1128  /1JmacUUofl+HusHuLkDxmadogI=
  1129  -----END CERTIFICATE-----`
  1130  
  1131  const x509v1TestIntermediate = `-----BEGIN CERTIFICATE-----
  1132  MIIByjCCATMCCQCCdEMsT8ykqTANBgkqhkiG9w0BAQsFADAjMQ8wDQYDVQQKEwZH
  1133  b2xhbmcxEDAOBgNVBAMTB1Jvb3QgQ0EwHhcNMTUwMTAxMDAwMDAwWhcNMjUwMTAx
  1134  MDAwMDAwWjAwMQ8wDQYDVQQKEwZHb2xhbmcxHTAbBgNVBAMTFFguNTA5djEgaW50
  1135  ZXJtZWRpYXRlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDJ2QyniAOT+5YL
  1136  jeinEBJr3NsC/Q2QJ/VKmgvp+xRxuKTHJiVmxVijmp0vWg8AWfkmuE4p3hXQbbqM
  1137  k5yxrk1n60ONhim2L4VXriEvCE7X2OXhTmBls5Ufr7aqIgPMikwjScCXwz8E8qI8
  1138  UxyAhnjeJwMYBU8TuwBImSd4LBHoQQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAIab
  1139  DRG6FbF9kL9jb/TDHkbVBk+sl/Pxi4/XjuFyIALlARgAkeZcPmL5tNW1ImHkwsHR
  1140  zWE77kJDibzd141u21ZbLsKvEdUJXjla43bdyMmEqf5VGpC3D4sFt3QVH7lGeRur
  1141  x5Wlq1u3YDL/j6s1nU2dQ3ySB/oP7J+vQ9V4QeM+
  1142  -----END CERTIFICATE-----`
  1143  
  1144  const x509v1TestLeaf = `-----BEGIN CERTIFICATE-----
  1145  MIICMzCCAZygAwIBAgIJAPo99mqJJrpJMA0GCSqGSIb3DQEBCwUAMDAxDzANBgNV
  1146  BAoTBkdvbGFuZzEdMBsGA1UEAxMUWC41MDl2MSBpbnRlcm1lZGlhdGUwHhcNMTUw
  1147  MTAxMDAwMDAwWhcNMjUwMTAxMDAwMDAwWjArMQ8wDQYDVQQKEwZHb2xhbmcxGDAW
  1148  BgNVBAMTD2Zvby5leGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
  1149  gYEApUh60Z+a5/oKJxG//Dn8CihSo2CJHNIIO3zEJZ1EeNSMZCynaIR6D3IPZEIR
  1150  +RG2oGt+f5EEukAPYxwasp6VeZEezoQWJ+97nPCT6DpwLlWp3i2MF8piK2R9vxkG
  1151  Z5n0+HzYk1VM8epIrZFUXSMGTX8w1y041PX/yYLxbdEifdcCAwEAAaNaMFgwDgYD
  1152  VR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNV
  1153  HRMBAf8EAjAAMBkGA1UdDgQSBBBFozXe0SnzAmjy+1U6M/cvMA0GCSqGSIb3DQEB
  1154  CwUAA4GBADYzYUvaToO/ucBskPdqXV16AaakIhhSENswYVSl97/sODaxsjishKq9
  1155  5R7siu+JnIFotA7IbBe633p75xEnLN88X626N/XRFG9iScLzpj0o0PWXBUiB+fxL
  1156  /jt8qszOXCv2vYdUTPNuPqufXLWMoirpuXrr1liJDmedCcAHepY/
  1157  -----END CERTIFICATE-----`
  1158  
  1159  const ignoreCNWithSANRoot = `-----BEGIN CERTIFICATE-----
  1160  MIIDPzCCAiegAwIBAgIIJkzCwkNrPHMwDQYJKoZIhvcNAQELBQAwMDEQMA4GA1UE
  1161  ChMHVEVTVElORzEcMBoGA1UEAxMTKipUZXN0aW5nKiogUm9vdCBDQTAeFw0xNTAx
  1162  MDEwMDAwMDBaFw0yNTAxMDEwMDAwMDBaMDAxEDAOBgNVBAoTB1RFU1RJTkcxHDAa
  1163  BgNVBAMTEyoqVGVzdGluZyoqIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
  1164  DwAwggEKAoIBAQC4YAf5YqlXGcikvbMWtVrNICt+V/NNWljwfvSKdg4Inm7k6BwW
  1165  P6y4Y+n4qSYIWNU4iRkdpajufzctxQCO6ty13iw3qVktzcC5XBIiS6ymiRhhDgnY
  1166  VQqyakVGw9MxrPwdRZVlssUv3Hmy6tU+v5Ok31SLY5z3wKgYWvSyYs0b8bKNU8kf
  1167  2FmSHnBN16lxGdjhe3ji58F/zFMr0ds+HakrLIvVdFcQFAnQopM8FTHpoWNNzGU3
  1168  KaiO0jBbMFkd6uVjVnuRJ+xjuiqi/NWwiwQA+CEr9HKzGkxOF8nAsHamdmO1wW+w
  1169  OsCrC0qWQ/f5NTOVATTJe0vj88OMTvo3071VAgMBAAGjXTBbMA4GA1UdDwEB/wQE
  1170  AwICpDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUw
  1171  AwEB/zAZBgNVHQ4EEgQQQDfXAftAL7gcflQEJ4xZATANBgkqhkiG9w0BAQsFAAOC
  1172  AQEAGOn3XjxHyHbXLKrRmpwV447B7iNBXR5VlhwOgt1kWaHDL2+8f/9/h0HMkB6j
  1173  fC+/yyuYVqYuOeavqMGVrh33D2ODuTQcFlOx5lXukP46j3j+Lm0jjZ1qNX7vlP8I
  1174  VlUXERhbelkw8O4oikakwIY9GE8syuSgYf+VeBW/lvuAZQrdnPfabxe05Tre6RXy
  1175  nJHMB1q07YHpbwIkcV/lfCE9pig2nPXTLwYZz9cl46Ul5RCpPUi+IKURo3x8y0FU
  1176  aSLjI/Ya0zwUARMmyZ3RRGCyhIarPb20mKSaMf1/Nb23pS3k1QgmZhk5pAnXYsWu
  1177  BJ6bvwEAasFiLGP6Zbdmxb2hIA==
  1178  -----END CERTIFICATE-----`
  1179  
  1180  const ignoreCNWithSANLeaf = `-----BEGIN CERTIFICATE-----
  1181  MIIDaTCCAlGgAwIBAgIJAONakvRTxgJhMA0GCSqGSIb3DQEBCwUAMDAxEDAOBgNV
  1182  BAoTB1RFU1RJTkcxHDAaBgNVBAMTEyoqVGVzdGluZyoqIFJvb3QgQ0EwHhcNMTUw
  1183  MTAxMDAwMDAwWhcNMjUwMTAxMDAwMDAwWjAsMRAwDgYDVQQKEwdURVNUSU5HMRgw
  1184  FgYDVQQDEw9mb28uZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
  1185  ggEKAoIBAQDBqskp89V/JMIBBqcauKSOVLcMyIE/t0jgSWVrsI4sksBTabLsfMdS
  1186  ui2n+dHQ1dRBuw3o4g4fPrWwS3nMnV3pZUHEn2TPi5N1xkjTaxObXgKIY2GKmFP3
  1187  rJ9vYqHT6mT4K93kCHoRcmJWWySc7S3JAOhTcdB4G+tIdQJN63E+XRYQQfNrn5HZ
  1188  hxQoOzaguHFx+ZGSD4Ntk6BSZz5NfjqCYqYxe+iCpTpEEYhIpi8joSPSmkTMTxBW
  1189  S1W2gXbYNQ9KjNkGM6FnQsUJrSPMrWs4v3UB/U88N5LkZeF41SqD9ySFGwbGajFV
  1190  nyzj12+4K4D8BLhlOc0Eo/F/8GwOwvmxAgMBAAGjgYkwgYYwDgYDVR0PAQH/BAQD
  1191  AgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAA
  1192  MBkGA1UdDgQSBBCjeab27q+5pV43jBGANOJ1MBsGA1UdIwQUMBKAEEA31wH7QC+4
  1193  HH5UBCeMWQEwDwYDVR0RBAgwBocEfwAAATANBgkqhkiG9w0BAQsFAAOCAQEAGZfZ
  1194  ErTVxxpIg64s22mQpXSk/72THVQsfsKHzlXmztM0CJzH8ccoN67ZqKxJCfdiE/FI
  1195  Emb6BVV4cGPeIKpcxaM2dwX/Y+Y0JaxpQJvqLxs+EByRL0gPP3shgg86WWCjYLxv
  1196  AgOn862d/JXGDrC9vIlQ/DDQcyL5g0JV5UjG2G9TUigbnrXxBw7BoWK6wmoSaHnR
  1197  sZKEHSs3RUJvm7qqpA9Yfzm9jg+i9j32zh1xFacghAOmFRFXa9eCVeigZ/KK2mEY
  1198  j2kBQyvnyKsXHLAKUoUOpd6t/1PHrfXnGj+HmzZNloJ/BZ1kiWb4eLvMljoLGkZn
  1199  xZbqP3Krgjj4XNaXjg==
  1200  -----END CERTIFICATE-----`
  1201  
  1202  const excludedNamesLeaf = `-----BEGIN CERTIFICATE-----
  1203  MIID4DCCAsigAwIBAgIHDUSFtJknhzANBgkqhkiG9w0BAQsFADCBnjELMAkGA1UE
  1204  BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU
  1205  MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5
  1206  ICgzNzM0NTE1NTYyODA2Mzk3KTEhMB8GA1UEAwwYSW50ZXJtZWRpYXRlIENBIGZv
  1207  ciAzMzkyMB4XDTE3MDIwODIxMTUwNFoXDTE4MDIwODIwMjQ1OFowgZAxCzAJBgNV
  1208  BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlMb3MgR2F0b3Mx
  1209  FDASBgNVBAoMC05ldGZsaXggSW5jMS0wKwYDVQQLDCRQbGF0Zm9ybSBTZWN1cml0
  1210  eSAoMzczNDUxNTc0ODUwMjY5NikxEzARBgNVBAMMCjE3Mi4xNi4wLjEwggEiMA0G
  1211  CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCZ0oP1bMv6bOeqcKbzinnGpNOpenhA
  1212  zdFFsgea62znWsH3Wg4+1Md8uPCqlaQIsaJQKZHc50eKD3bg0Io7c6kxHkBQr1b8
  1213  Q7cGeK3CjdqG3NwS/aizzrLKOwL693hFwwy7JY7GGCvogbhyQRKn6iV0U9zMm7bu
  1214  /9pQVV/wx8u01u2uAlLttjyQ5LJkxo5t8cATFVqxdN5J9eY//VSDiTwXnlpQITBP
  1215  /Ow+zYuZ3kFlzH3CtCOhOEvNG3Ar1NvP3Icq35PlHV+Eki4otnKfixwByoiGpqCB
  1216  UEIY04VrZJjwBxk08y/3jY2B3VLYGgi+rryyCxIqkB7UpSNPMMWSG4UpAgMBAAGj
  1217  LzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0RBBYwFIIMYmVuZGVyLmxvY2FshwSsEAAB
  1218  MA0GCSqGSIb3DQEBCwUAA4IBAQCLW3JO8L7LKByjzj2RciPjCGH5XF87Wd20gYLq
  1219  sNKcFwCIeyZhnQy5aZ164a5G9AIk2HLvH6HevBFPhA9Ivmyv/wYEfnPd1VcFkpgP
  1220  hDt8MCFJ8eSjCyKdtZh1MPMLrLVymmJV+Rc9JUUYM9TIeERkpl0rskcO1YGewkYt
  1221  qKlWE+0S16+pzsWvKn831uylqwIb8ANBPsCX4aM4muFBHavSWAHgRO+P+yXVw8Q+
  1222  VQDnMHUe5PbZd1/+1KKVs1K/CkBCtoHNHp1d/JT+2zUQJphwja9CcgfFdVhSnHL4
  1223  oEEOFtqVMIuQfR2isi08qW/JGOHc4sFoLYB8hvdaxKWSE19A
  1224  -----END CERTIFICATE-----`
  1225  
  1226  const excludedNamesIntermediate = `-----BEGIN CERTIFICATE-----
  1227  MIIDzTCCArWgAwIBAgIHDUSFqYeczDANBgkqhkiG9w0BAQsFADCBmTELMAkGA1UE
  1228  BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU
  1229  MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5
  1230  ICgzNzM0NTE1NDc5MDY0NjAyKTEcMBoGA1UEAwwTTG9jYWwgUm9vdCBmb3IgMzM5
  1231  MjAeFw0xNzAyMDgyMTE1MDRaFw0xODAyMDgyMDI0NThaMIGeMQswCQYDVQQGEwJV
  1232  UzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJTG9zIEdhdG9zMRQwEgYD
  1233  VQQKDAtOZXRmbGl4IEluYzEtMCsGA1UECwwkUGxhdGZvcm0gU2VjdXJpdHkgKDM3
  1234  MzQ1MTU1NjI4MDYzOTcpMSEwHwYDVQQDDBhJbnRlcm1lZGlhdGUgQ0EgZm9yIDMz
  1235  OTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCOyEs6tJ/t9emQTvlx
  1236  3FS7uJSou5rKkuqVxZdIuYQ+B2ZviBYUnMRT9bXDB0nsVdKZdp0hdchdiwNXDG/I
  1237  CiWu48jkcv/BdynVyayOT+0pOJSYLaPYpzBx1Pb9M5651ct9GSbj6Tz0ChVonoIE
  1238  1AIZ0kkebucZRRFHd0xbAKVRKyUzPN6HJ7WfgyauUp7RmlC35wTmrmARrFohQLlL
  1239  7oICy+hIQePMy9x1LSFTbPxZ5AUUXVC3eUACU3vLClF/Xs8XGHebZpUXCdMQjOGS
  1240  nq1eFguFHR1poSB8uSmmLqm4vqUH9CDhEgiBAC8yekJ8//kZQ7lUEqZj3YxVbk+Y
  1241  E4H5AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
  1242  ADxrnmNX5gWChgX9K5fYwhFDj5ofxZXAKVQk+WjmkwMcmCx3dtWSm++Wdksj/ZlA
  1243  V1cLW3ohWv1/OAZuOlw7sLf98aJpX+UUmIYYQxDubq+4/q7VA7HzEf2k/i/oN1NI
  1244  JgtrhpPcZ/LMO6k7DYx0qlfYq8pTSfd6MI4LnWKgLc+JSPJJjmvspgio2ZFcnYr7
  1245  A264BwLo6v1Mos1o1JUvFFcp4GANlw0XFiWh7JXYRl8WmS5DoouUC+aNJ3lmyF6z
  1246  LbIjZCSfgZnk/LK1KU1j91FI2bc2ULYZvAC1PAg8/zvIgxn6YM2Q7ZsdEgWw0FpS
  1247  zMBX1/lk4wkFckeUIlkD55Y=
  1248  -----END CERTIFICATE-----`
  1249  
  1250  const excludedNamesRoot = `-----BEGIN CERTIFICATE-----
  1251  MIIEGTCCAwGgAwIBAgIHDUSFpInn/zANBgkqhkiG9w0BAQsFADCBozELMAkGA1UE
  1252  BhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBHYXRvczEU
  1253  MBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNlY3VyaXR5
  1254  ICgzNzMxNTA5NDM3NDYyNDg1KTEmMCQGA1UEAwwdTmFtZSBDb25zdHJhaW50cyBU
  1255  ZXN0IFJvb3QgQ0EwHhcNMTcwMjA4MjExNTA0WhcNMTgwMjA4MjAyNDU4WjCBmTEL
  1256  MAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCUxvcyBH
  1257  YXRvczEUMBIGA1UECgwLTmV0ZmxpeCBJbmMxLTArBgNVBAsMJFBsYXRmb3JtIFNl
  1258  Y3VyaXR5ICgzNzM0NTE1NDc5MDY0NjAyKTEcMBoGA1UEAwwTTG9jYWwgUm9vdCBm
  1259  b3IgMzM5MjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJymcnX29ekc
  1260  7+MLyr8QuAzoHWznmGdDd2sITwWRjM89/21cdlHCGKSpULUNdFp9HDLWvYECtxt+
  1261  8TuzKiQz7qAerzGUT1zI5McIjHy0e/i4xIkfiBiNeTCuB/N9QRbZlcfM80ErkaA4
  1262  gCAFK8qZAcWkHIl6e+KaQFMPLKk9kckgAnVDHEJe8oLNCogCJ15558b65g05p9eb
  1263  5Lg+E98hoPRTQaDwlz3CZPfTTA2EiEZInSi8qzodFCbTpJUVTbiVUH/JtVjlibbb
  1264  smdcx5PORK+8ZJkhLEh54AjaWOX4tB/7Tkk8stg2VBmrIARt/j4UVj7cTrIWU3bV
  1265  m8TwHJG+YgsCAwEAAaNaMFgwDwYDVR0TAQH/BAUwAwEB/zBFBgNVHR4EPjA8oBww
  1266  CocICgEAAP//AAAwDoIMYmVuZGVyLmxvY2FsoRwwCocICgEAAP//AAAwDoIMYmVu
  1267  ZGVyLmxvY2FsMA0GCSqGSIb3DQEBCwUAA4IBAQAMjbheffPxtSKSv9NySW+8qmHs
  1268  n7Mb5GGyCFu+cMZSoSaabstbml+zHEFJvWz6/1E95K4F8jKhAcu/CwDf4IZrSD2+
  1269  Hee0DolVSQhZpnHgPyj7ZATz48e3aJaQPUlhCEOh0wwF4Y0N4FV0t7R6woLylYRZ
  1270  yU1yRHUqUYpN0DWFpsPbBqgM6uUAVO2ayBFhPgWUaqkmSbZ/Nq7isGvknaTmcIwT
  1271  6mOAFN0qFb4RGzfGJW7x6z7KCULS7qVDp6fU3tRoScHFEgRubks6jzQ1W5ooSm4o
  1272  +NQCZDd5eFeU8PpNX7rgaYE4GPq+EEmLVCBYmdctr8QVdqJ//8Xu3+1phjDy
  1273  -----END CERTIFICATE-----`
  1274  
  1275  const invalidCNRoot = `-----BEGIN CERTIFICATE-----
  1276  MIIBFjCBvgIJAIsu4r+jb70UMAoGCCqGSM49BAMCMBQxEjAQBgNVBAsMCVRlc3Qg
  1277  cm9vdDAeFw0xODA3MTExODMyMzVaFw0yODA3MDgxODMyMzVaMBQxEjAQBgNVBAsM
  1278  CVRlc3Qgcm9vdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABF6oDgMg0LV6YhPj
  1279  QXaPXYCc2cIyCdqp0ROUksRz0pOLTc5iY2nraUheRUD1vRRneq7GeXOVNn7uXONg
  1280  oCGMjNwwCgYIKoZIzj0EAwIDRwAwRAIgDSiwgIn8g1lpruYH0QD1GYeoWVunfmrI
  1281  XzZZl0eW/ugCICgOfXeZ2GGy3wIC0352BaC3a8r5AAb2XSGNe+e9wNN6
  1282  -----END CERTIFICATE-----`
  1283  
  1284  const validCNWithoutSAN = `-----BEGIN CERTIFICATE-----
  1285  MIIBJzCBzwIUB7q8t9mrDAL+UB1OFaMN5BEWFKQwCgYIKoZIzj0EAwIwFDESMBAG
  1286  A1UECwwJVGVzdCByb290MB4XDTE4MDcxMTE4NDcyNFoXDTI4MDcwODE4NDcyNFow
  1287  GjEYMBYGA1UEAwwPZm9vLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D
  1288  AQcDQgAEp6Z8IjOnR38Iky1fYTUu2kVndvKXcxiwARJKGtW3b0E8uwVp9AZd/+sr
  1289  p4ULTPdFToFAeqnGHbu62bkms8pQkDAKBggqhkjOPQQDAgNHADBEAiBTbNe3WWFR
  1290  cqUYo0sNUuoV+tCTMDJUS+0PWIW4qBqCOwIgFHdLDn5PCk9kJpfc0O2qZx03hdq0
  1291  h7olHCpY9yMRiz0=
  1292  -----END CERTIFICATE-----`
  1293  
  1294  const rootWithoutSKID = `-----BEGIN CERTIFICATE-----
  1295  MIIBbzCCARSgAwIBAgIQeCkq3C8SOX/JM5PqYTl9cDAKBggqhkjOPQQDAjASMRAw
  1296  DgYDVQQKEwdBY21lIENvMB4XDTE5MDIwNDIyNTYzNFoXDTI5MDIwMTIyNTYzNFow
  1297  EjEQMA4GA1UEChMHQWNtZSBDbzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABISm
  1298  jGlTr4dLOWT+BCTm2PzWRjk1DpLcSAh+Al8eB1Nc2eBWxYIH9qPirfatvqBOA4c5
  1299  ZwycRpFoaw6O+EmXnVujTDBKMA4GA1UdDwEB/wQEAwICpDATBgNVHSUEDDAKBggr
  1300  BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MBIGA1UdEQQLMAmCB2V4YW1wbGUwCgYI
  1301  KoZIzj0EAwIDSQAwRgIhAMaBYWFCjTfn0MNyQ0QXvYT/iIFompkIqzw6wB7qjLrA
  1302  AiEA3sn65V7G4tsjZEOpN0Jykn9uiTjqniqn/S/qmv8gIec=
  1303  -----END CERTIFICATE-----`
  1304  
  1305  const leafWithAKID = `-----BEGIN CERTIFICATE-----
  1306  MIIBjTCCATSgAwIBAgIRAPCKYvADhKLPaWOtcTu2XYwwCgYIKoZIzj0EAwIwEjEQ
  1307  MA4GA1UEChMHQWNtZSBDbzAeFw0xOTAyMDQyMzA2NTJaFw0yOTAyMDEyMzA2NTJa
  1308  MBMxETAPBgNVBAoTCEFjbWUgTExDMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
  1309  Wk5N+/8X97YT6ClFNIE5/4yc2YwKn921l0wrIJEcT2u+Uydm7EqtCJNtZjYMAnBd
  1310  Acp/wynpTwC6tBTsxcM0s6NqMGgwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoG
  1311  CCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUwitfkXg0JglCjW9R
  1312  ssWvTAveakIwEgYDVR0RBAswCYIHZXhhbXBsZTAKBggqhkjOPQQDAgNHADBEAiBk
  1313  4LpWiWPOIl5PIhX9PDVkmjpre5oyoH/3aYwG8ABYuAIgCeSfbYueOOG2AdXuMqSU
  1314  ZZMqeJS7JldLx91sPUArY5A=
  1315  -----END CERTIFICATE-----`
  1316  
  1317  const rootMatchingSKIDMismatchingSubject = `-----BEGIN CERTIFICATE-----
  1318  MIIBQjCB6aADAgECAgEAMAoGCCqGSM49BAMCMBExDzANBgNVBAMTBlJvb3QgQTAe
  1319  Fw0wOTExMTAyMzAwMDBaFw0xOTExMDgyMzAwMDBaMBExDzANBgNVBAMTBlJvb3Qg
  1320  QTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABPK4p1uXq2aAeDtKDHIokg2rTcPM
  1321  2gq3N9Y96wiW6/7puBK1+INEW//cO9x6FpzkcsHw/TriAqy4sck/iDAvf9WjMjAw
  1322  MA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zAMBgNVHQ4EBQQDAQID
  1323  MAoGCCqGSM49BAMCA0gAMEUCIQDgtAp7iVHxMnKxZPaLQPC+Tv2r7+DJc88k2SKH
  1324  MPs/wQIgFjjNvBoQEl7vSHTcRGCCcFMdlN4l0Dqc9YwGa9fyrQs=
  1325  -----END CERTIFICATE-----`
  1326  
  1327  const rootMismatchingSKIDMatchingSubject = `-----BEGIN CERTIFICATE-----
  1328  MIIBNDCB26ADAgECAgEAMAoGCCqGSM49BAMCMBExDzANBgNVBAMTBlJvb3QgQjAe
  1329  Fw0wOTExMTAyMzAwMDBaFw0xOTExMDgyMzAwMDBaMBExDzANBgNVBAMTBlJvb3Qg
  1330  QjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABI1YRFcIlkWzm9BdEVrIsEQJ2dT6
  1331  qiW8/WV9GoIhmDtX9SEDHospc0Cgm+TeD2QYW2iMrS5mvNe4GSw0Jezg/bOjJDAi
  1332  MA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNI
  1333  ADBFAiEAukWOiuellx8bugRiwCS5XQ6IOJ1SZcjuZxj76WojwxkCIHqa71qNw8FM
  1334  DtA5yoL9M2pDFF6ovFWnaCe+KlzSwAW/
  1335  -----END CERTIFICATE-----`
  1336  
  1337  const leafMatchingAKIDMatchingIssuer = `-----BEGIN CERTIFICATE-----
  1338  MIIBNTCB26ADAgECAgEAMAoGCCqGSM49BAMCMBExDzANBgNVBAMTBlJvb3QgQjAe
  1339  Fw0wOTExMTAyMzAwMDBaFw0xOTExMDgyMzAwMDBaMA8xDTALBgNVBAMTBExlYWYw
  1340  WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASNWERXCJZFs5vQXRFayLBECdnU+qol
  1341  vP1lfRqCIZg7V/UhAx6LKXNAoJvk3g9kGFtojK0uZrzXuBksNCXs4P2zoyYwJDAO
  1342  BgNVHSMEBzAFgAMBAgMwEgYDVR0RBAswCYIHZXhhbXBsZTAKBggqhkjOPQQDAgNJ
  1343  ADBGAiEAnV9XV7a4h0nfJB8pWv+pBUXRlRFA2uZz3mXEpee8NYACIQCWa+wL70GL
  1344  ePBQCV1F9sE2q4ZrnsT9TZoNrSe/bMDjzA==
  1345  -----END CERTIFICATE-----`
  1346  
  1347  var unknownAuthorityErrorTests = []struct {
  1348  	name     string
  1349  	cert     string
  1350  	expected string
  1351  }{
  1352  	{"self-signed, cn", selfSignedWithCommonName, "x509: certificate signed by unknown authority (possibly because of \"empty\" while trying to verify candidate authority certificate \"test\")"},
  1353  	{"self-signed, no cn, org", selfSignedNoCommonNameWithOrgName, "x509: certificate signed by unknown authority (possibly because of \"empty\" while trying to verify candidate authority certificate \"ca\")"},
  1354  	{"self-signed, no cn, no org", selfSignedNoCommonNameNoOrgName, "x509: certificate signed by unknown authority (possibly because of \"empty\" while trying to verify candidate authority certificate \"serial:0\")"},
  1355  }
  1356  
  1357  func TestUnknownAuthorityError(t *testing.T) {
  1358  	for i, tt := range unknownAuthorityErrorTests {
  1359  		t.Run(tt.name, func(t *testing.T) {
  1360  			der, _ := pem.Decode([]byte(tt.cert))
  1361  			if der == nil {
  1362  				t.Fatalf("#%d: Unable to decode PEM block", i)
  1363  			}
  1364  			c, err := ParseCertificate(der.Bytes)
  1365  			if err != nil {
  1366  				t.Fatalf("#%d: Unable to parse certificate -> %v", i, err)
  1367  			}
  1368  			uae := &UnknownAuthorityError{
  1369  				Cert:     c,
  1370  				hintErr:  fmt.Errorf("empty"),
  1371  				hintCert: c,
  1372  			}
  1373  			actual := uae.Error()
  1374  			if actual != tt.expected {
  1375  				t.Errorf("#%d: UnknownAuthorityError.Error() response invalid actual: %s expected: %s", i, actual, tt.expected)
  1376  			}
  1377  		})
  1378  	}
  1379  }
  1380  
  1381  const selfSignedWithCommonName = `-----BEGIN CERTIFICATE-----
  1382  MIIDCjCCAfKgAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQKEwJjYTEL
  1383  MAkGA1UEAxMCY2EwHhcNMTYwODI4MTcwOTE4WhcNMjEwODI3MTcwOTE4WjAcMQsw
  1384  CQYDVQQKEwJjYTENMAsGA1UEAxMEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEP
  1385  ADCCAQoCggEBAOH55PfRsbvmcabfLLko1w/yuapY/hk13Cgmc3WE/Z1ZStxGiVxY
  1386  gQVH9n4W/TbUsrep/TmcC4MV7xEm5252ArcgaH6BeQ4QOTFj/6Jx0RT7U/ix+79x
  1387  8RRysf7OlzNpGIctwZEM7i/G+0ZfqX9ULxL/EW9tppSxMX1jlXZQarnU7BERL5cH
  1388  +G2jcbU9H28FXYishqpVYE9L7xrXMm61BAwvGKB0jcVW6JdhoAOSfQbbgp7JjIlq
  1389  czXqUsv1UdORO/horIoJptynTvuARjZzyWatya6as7wyOgEBllE6BjPK9zpn+lp3
  1390  tQ8dwKVqm/qBPhIrVqYG/Ec7pIv8mJfYabMCAwEAAaNZMFcwDgYDVR0PAQH/BAQD
  1391  AgOoMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAMBgNVHRMBAf8EAjAA
  1392  MAoGA1UdDgQDBAEAMAwGA1UdIwQFMAOAAQAwDQYJKoZIhvcNAQELBQADggEBAAAM
  1393  XMFphzq4S5FBcRdB2fRrmcoz+jEROBWvIH/1QUJeBEBz3ZqBaJYfBtQTvqCA5Rjw
  1394  dxyIwVd1W3q3aSulM0tO62UCU6L6YeeY/eq8FmpD7nMJo7kCrXUUAMjxbYvS3zkT
  1395  v/NErK6SgWnkQiPJBZNX1Q9+aSbLT/sbaCTdbWqcGNRuLGJkmqfIyoxRt0Hhpqsx
  1396  jP5cBaVl50t4qoCuVIE9cOucnxYXnI7X5HpXWvu8Pfxo4SwVjb1az8Fk5s8ZnxGe
  1397  fPB6Q3L/pKBe0SEe5GywpwtokPLB3lAygcuHbxp/1FlQ1NQZqq+vgXRIla26bNJf
  1398  IuYkJwt6w+LH/9HZgf8=
  1399  -----END CERTIFICATE-----`
  1400  const selfSignedNoCommonNameWithOrgName = `-----BEGIN CERTIFICATE-----
  1401  MIIC+zCCAeOgAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQKEwJjYTEL
  1402  MAkGA1UEAxMCY2EwHhcNMTYwODI4MTgxMzQ4WhcNMjEwODI3MTgxMzQ4WjANMQsw
  1403  CQYDVQQKEwJjYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL5EjrUa
  1404  7EtOMxWiIgTzp2FlQvncPsG329O3l3uNGnbigb8TmNMw2M8UhoDjd84pnU5RAfqd
  1405  8t5TJyw/ybnIKBN131Q2xX+gPQ0dFyMvcO+i1CUgCxmYZomKVA2MXO1RD1hLTYGS
  1406  gOVjc3no3MBwd8uVQp0NStqJ1QvLtNG4Uy+B28qe+ZFGGbjGqx8/CU4A8Szlpf7/
  1407  xAZR8w5qFUUlpA2LQYeHHJ5fQVXw7kyL1diNrKNi0G3qcY0IrBh++hT+hnEEXyXu
  1408  g8a0Ux18hoE8D6rAr34rCZl6AWfqW5wjwm+N5Ns2ugr9U4N8uCKJYMPHb2CtdubU
  1409  46IzVucpTfGLdaMCAwEAAaNZMFcwDgYDVR0PAQH/BAQDAgOoMB0GA1UdJQQWMBQG
  1410  CCsGAQUFBwMCBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMAoGA1UdDgQDBAEAMAwG
  1411  A1UdIwQFMAOAAQAwDQYJKoZIhvcNAQELBQADggEBAEn5SgVpJ3zjsdzPqK7Qd/sB
  1412  bYd1qtPHlrszjhbHBg35C6mDgKhcv4o6N+fuC+FojZb8lIxWzJtvT9pQbfy/V6u3
  1413  wOb816Hm71uiP89sioIOKCvSAstj/p9doKDOUaKOcZBTw0PS2m9eja8bnleZzBvK
  1414  rD8cNkHf74v98KvBhcwBlDifVzmkWzMG6TL1EkRXUyLKiWgoTUFSkCDV927oXXMR
  1415  DKnszq+AVw+K8hbeV2A7GqT7YfeqOAvSbatTDnDtKOPmlCnQui8A149VgZzXv7eU
  1416  29ssJSqjUPyp58dlV6ZuynxPho1QVZUOQgnJToXIQ3/5vIvJRXy52GJCs4/Gh/w=
  1417  -----END CERTIFICATE-----`
  1418  const selfSignedNoCommonNameNoOrgName = `-----BEGIN CERTIFICATE-----
  1419  MIIC7jCCAdagAwIBAgIBADANBgkqhkiG9w0BAQsFADAaMQswCQYDVQQKEwJjYTEL
  1420  MAkGA1UEAxMCY2EwHhcNMTYwODI4MTgxOTQ1WhcNMjEwODI3MTgxOTQ1WjAAMIIB
  1421  IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp3E+Jl6DpgzogHUW/i/AAcCM
  1422  fnNJLOamNVKFGmmxhb4XTHxRaWoTzrlsyzIMS0WzivvJeZVe6mWbvuP2kZanKgIz
  1423  35YXRTR9HbqkNTMuvnpUESzWxbGWE2jmt2+a/Jnz89FS4WIYRhF7nI2z8PvZOfrI
  1424  2gETTT2tEpoF2S4soaYfm0DBeT8K0/rogAaf+oeUS6V+v3miRcAooJgpNJGu9kqm
  1425  S0xKPn1RCFVjpiRd6YNS0xZirjYQIBMFBvoSoHjaOdgJptNRBprYPOxVJ/ItzGf0
  1426  kPmzPFCx2tKfxV9HLYBPgxi+fP3IIx8aIYuJn8yReWtYEMYU11hDPeAFN5Gm+wID
  1427  AQABo1kwVzAOBgNVHQ8BAf8EBAMCA6gwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsG
  1428  AQUFBwMBMAwGA1UdEwEB/wQCMAAwCgYDVR0OBAMEAQAwDAYDVR0jBAUwA4ABADAN
  1429  BgkqhkiG9w0BAQsFAAOCAQEATZVOFeiCpPM5QysToLv+8k7Rjoqt6L5IxMUJGEpq
  1430  4ENmldmwkhEKr9VnYEJY3njydnnTm97d9vOfnLj9nA9wMBODeOO3KL2uJR2oDnmM
  1431  9z1NSe2aQKnyBb++DM3ZdikpHn/xEpGV19pYKFQVn35x3lpPh2XijqRDO/erKemb
  1432  w67CoNRb81dy+4Q1lGpA8ORoLWh5fIq2t2eNGc4qB8vlTIKiESzAwu7u3sRfuWQi
  1433  4R+gnfLd37FWflMHwztFbVTuNtPOljCX0LN7KcuoXYlr05RhQrmoN7fQHsrZMNLs
  1434  8FVjHdKKu+uPstwd04Uy4BR/H2y1yerN9j/L6ZkMl98iiA==
  1435  -----END CERTIFICATE-----`
  1436  
  1437  const criticalExtRoot = `-----BEGIN CERTIFICATE-----
  1438  MIIBqzCCAVGgAwIBAgIJAJ+mI/85cXApMAoGCCqGSM49BAMCMB0xDDAKBgNVBAoT
  1439  A09yZzENMAsGA1UEAxMEUm9vdDAeFw0xNTAxMDEwMDAwMDBaFw0yNTAxMDEwMDAw
  1440  MDBaMB0xDDAKBgNVBAoTA09yZzENMAsGA1UEAxMEUm9vdDBZMBMGByqGSM49AgEG
  1441  CCqGSM49AwEHA0IABJGp9joiG2QSQA+1FczEDAsWo84rFiP3GTL+n+ugcS6TyNib
  1442  gzMsdbJgVi+a33y0SzLZxB+YvU3/4KTk8yKLC+2jejB4MA4GA1UdDwEB/wQEAwIC
  1443  BDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB
  1444  /zAZBgNVHQ4EEgQQQDfXAftAL7gcflQEJ4xZATAbBgNVHSMEFDASgBBAN9cB+0Av
  1445  uBx+VAQnjFkBMAoGCCqGSM49BAMCA0gAMEUCIFeSV00fABFceWR52K+CfIgOHotY
  1446  FizzGiLB47hGwjMuAiEA8e0um2Kr8FPQ4wmFKaTRKHMaZizCGl3m+RG5QsE1KWo=
  1447  -----END CERTIFICATE-----`
  1448  
  1449  const criticalExtIntermediate = `-----BEGIN CERTIFICATE-----
  1450  MIIBszCCAVmgAwIBAgIJAL2kcGZKpzVqMAoGCCqGSM49BAMCMB0xDDAKBgNVBAoT
  1451  A09yZzENMAsGA1UEAxMEUm9vdDAeFw0xNTAxMDEwMDAwMDBaFw0yNTAxMDEwMDAw
  1452  MDBaMCUxDDAKBgNVBAoTA09yZzEVMBMGA1UEAxMMSW50ZXJtZWRpYXRlMFkwEwYH
  1453  KoZIzj0CAQYIKoZIzj0DAQcDQgAESqVq92iPEq01cL4o99WiXDc5GZjpjNlzMS1n
  1454  rk8oHcVDp4tQRRQG3F4A6dF1rn/L923ha3b0fhDLlAvXZB+7EKN6MHgwDgYDVR0P
  1455  AQH/BAQDAgIEMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNVHRMB
  1456  Af8EBTADAQH/MBkGA1UdDgQSBBCMGmiotXbbXVd7H40UsgajMBsGA1UdIwQUMBKA
  1457  EEA31wH7QC+4HH5UBCeMWQEwCgYIKoZIzj0EAwIDSAAwRQIhAOhhNRb6KV7h3wbE
  1458  cdap8bojzvUcPD78fbsQPCNw1jPxAiBOeAJhlTwpKn9KHpeJphYSzydj9NqcS26Y
  1459  xXbdbm27KQ==
  1460  -----END CERTIFICATE-----`
  1461  
  1462  const criticalExtLeafWithExt = `-----BEGIN CERTIFICATE-----
  1463  MIIBxTCCAWugAwIBAgIJAJZAUtw5ccb1MAoGCCqGSM49BAMCMCUxDDAKBgNVBAoT
  1464  A09yZzEVMBMGA1UEAxMMSW50ZXJtZWRpYXRlMB4XDTE1MDEwMTAwMDAwMFoXDTI1
  1465  MDEwMTAwMDAwMFowJDEMMAoGA1UEChMDT3JnMRQwEgYDVQQDEwtleGFtcGxlLmNv
  1466  bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABF3ABa2+B6gUyg6ayCaRQWYY/+No
  1467  6PceLqEavZNUeVNuz7bS74Toy8I7R3bGMkMgbKpLSPlPTroAATvebTXoBaijgYQw
  1468  gYEwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD
  1469  AjAMBgNVHRMBAf8EAjAAMBkGA1UdDgQSBBBRNtBL2vq8nCV3qVp7ycxMMBsGA1Ud
  1470  IwQUMBKAEIwaaKi1dttdV3sfjRSyBqMwCgYDUQMEAQH/BAAwCgYIKoZIzj0EAwID
  1471  SAAwRQIgVjy8GBgZFiagexEuDLqtGjIRJQtBcf7lYgf6XFPH1h4CIQCT6nHhGo6E
  1472  I+crEm4P5q72AnA/Iy0m24l7OvLuXObAmg==
  1473  -----END CERTIFICATE-----`
  1474  
  1475  const criticalExtIntermediateWithExt = `-----BEGIN CERTIFICATE-----
  1476  MIIB2TCCAX6gAwIBAgIIQD3NrSZtcUUwCgYIKoZIzj0EAwIwHTEMMAoGA1UEChMD
  1477  T3JnMQ0wCwYDVQQDEwRSb290MB4XDTE1MDEwMTAwMDAwMFoXDTI1MDEwMTAwMDAw
  1478  MFowPTEMMAoGA1UEChMDT3JnMS0wKwYDVQQDEyRJbnRlcm1lZGlhdGUgd2l0aCBD
  1479  cml0aWNhbCBFeHRlbnNpb24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQtnmzH
  1480  mcRm10bdDBnJE7xQEJ25cLCL5okuEphRR0Zneo6+nQZikoh+UBbtt5GV3Dms7LeP
  1481  oF5HOplYDCd8wi/wo4GHMIGEMA4GA1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggr
  1482  BgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQKxdv
  1483  UuQZ6sO3XvBsxgNZ3zAbBgNVHSMEFDASgBBAN9cB+0AvuBx+VAQnjFkBMAoGA1ED
  1484  BAEB/wQAMAoGCCqGSM49BAMCA0kAMEYCIQCQzTPd6XKex+OAPsKT/1DsoMsg8vcG
  1485  c2qZ4Q0apT/kvgIhAKu2TnNQMIUdcO0BYQIl+Uhxc78dc9h4lO+YJB47pHGx
  1486  -----END CERTIFICATE-----`
  1487  
  1488  const criticalExtLeaf = `-----BEGIN CERTIFICATE-----
  1489  MIIBzzCCAXWgAwIBAgIJANoWFIlhCI9MMAoGCCqGSM49BAMCMD0xDDAKBgNVBAoT
  1490  A09yZzEtMCsGA1UEAxMkSW50ZXJtZWRpYXRlIHdpdGggQ3JpdGljYWwgRXh0ZW5z
  1491  aW9uMB4XDTE1MDEwMTAwMDAwMFoXDTI1MDEwMTAwMDAwMFowJDEMMAoGA1UEChMD
  1492  T3JnMRQwEgYDVQQDEwtleGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEH
  1493  A0IABG1Lfh8A0Ho2UvZN5H0+ONil9c8jwtC0y0xIZftyQE+Fwr9XwqG3rV2g4M1h
  1494  GnJa9lV9MPHg8+b85Hixm0ZSw7SjdzB1MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE
  1495  FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAZBgNVHQ4EEgQQ
  1496  UNhY4JhezH9gQYqvDMWrWDAbBgNVHSMEFDASgBArF29S5Bnqw7de8GzGA1nfMAoG
  1497  CCqGSM49BAMCA0gAMEUCIQClA3d4tdrDu9Eb5ZBpgyC+fU1xTZB0dKQHz6M5fPZA
  1498  2AIgN96lM+CPGicwhN24uQI6flOsO3H0TJ5lNzBYLtnQtlc=
  1499  -----END CERTIFICATE-----`
  1500  
  1501  func TestValidHostname(t *testing.T) {
  1502  	tests := []struct {
  1503  		host                     string
  1504  		validInput, validPattern bool
  1505  	}{
  1506  		{host: "example.com", validInput: true, validPattern: true},
  1507  		{host: "eXample123-.com", validInput: true, validPattern: true},
  1508  		{host: "-eXample123-.com"},
  1509  		{host: ""},
  1510  		{host: "."},
  1511  		{host: "example..com"},
  1512  		{host: ".example.com"},
  1513  		{host: "example.com.", validInput: true},
  1514  		{host: "*.example.com."},
  1515  		{host: "*.example.com", validPattern: true},
  1516  		{host: "*foo.example.com"},
  1517  		{host: "foo.*.example.com"},
  1518  		{host: "exa_mple.com", validInput: true, validPattern: true},
  1519  		{host: "foo,bar"},
  1520  		{host: "project-dev:us-central1:main"},
  1521  	}
  1522  	for _, tt := range tests {
  1523  		if got := validHostnamePattern(tt.host); got != tt.validPattern {
  1524  			t.Errorf("validHostnamePattern(%q) = %v, want %v", tt.host, got, tt.validPattern)
  1525  		}
  1526  		if got := validHostnameInput(tt.host); got != tt.validInput {
  1527  			t.Errorf("validHostnameInput(%q) = %v, want %v", tt.host, got, tt.validInput)
  1528  		}
  1529  	}
  1530  }
  1531  
  1532  func generateCert(cn string, isCA bool, issuer *Certificate, issuerKey crypto.PrivateKey) (*Certificate, crypto.PrivateKey, error) {
  1533  	priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  1534  	if err != nil {
  1535  		return nil, nil, err
  1536  	}
  1537  
  1538  	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
  1539  	serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit)
  1540  
  1541  	template := &Certificate{
  1542  		SerialNumber: serialNumber,
  1543  		Subject:      pkix.Name{CommonName: cn},
  1544  		NotBefore:    time.Now().Add(-1 * time.Hour),
  1545  		NotAfter:     time.Now().Add(24 * time.Hour),
  1546  
  1547  		KeyUsage:              KeyUsageKeyEncipherment | KeyUsageDigitalSignature | KeyUsageCertSign,
  1548  		ExtKeyUsage:           []ExtKeyUsage{ExtKeyUsageServerAuth},
  1549  		BasicConstraintsValid: true,
  1550  		IsCA:                  isCA,
  1551  	}
  1552  	if issuer == nil {
  1553  		issuer = template
  1554  		issuerKey = priv
  1555  	}
  1556  
  1557  	derBytes, err := CreateCertificate(rand.Reader, template, issuer, priv.Public(), issuerKey)
  1558  	if err != nil {
  1559  		return nil, nil, err
  1560  	}
  1561  	cert, err := ParseCertificate(derBytes)
  1562  	if err != nil {
  1563  		return nil, nil, err
  1564  	}
  1565  
  1566  	return cert, priv, nil
  1567  }
  1568  
  1569  func TestPathologicalChain(t *testing.T) {
  1570  	if testing.Short() {
  1571  		t.Skip("skipping generation of a long chain of certificates in short mode")
  1572  	}
  1573  
  1574  	// Build a chain where all intermediates share the same subject, to hit the
  1575  	// path building worst behavior.
  1576  	roots, intermediates := NewCertPool(), NewCertPool()
  1577  
  1578  	parent, parentKey, err := generateCert("Root CA", true, nil, nil)
  1579  	if err != nil {
  1580  		t.Fatal(err)
  1581  	}
  1582  	roots.AddCert(parent)
  1583  
  1584  	for i := 1; i < 100; i++ {
  1585  		parent, parentKey, err = generateCert("Intermediate CA", true, parent, parentKey)
  1586  		if err != nil {
  1587  			t.Fatal(err)
  1588  		}
  1589  		intermediates.AddCert(parent)
  1590  	}
  1591  
  1592  	leaf, _, err := generateCert("Leaf", false, parent, parentKey)
  1593  	if err != nil {
  1594  		t.Fatal(err)
  1595  	}
  1596  
  1597  	start := time.Now()
  1598  	_, err = leaf.Verify(VerifyOptions{
  1599  		Roots:         roots,
  1600  		Intermediates: intermediates,
  1601  	})
  1602  	t.Logf("verification took %v", time.Since(start))
  1603  
  1604  	if err == nil || !strings.Contains(err.Error(), "signature check attempts limit") {
  1605  		t.Errorf("expected verification to fail with a signature checks limit error; got %v", err)
  1606  	}
  1607  }
  1608  
  1609  func TestLongChain(t *testing.T) {
  1610  	if testing.Short() {
  1611  		t.Skip("skipping generation of a long chain of certificates in short mode")
  1612  	}
  1613  
  1614  	roots, intermediates := NewCertPool(), NewCertPool()
  1615  
  1616  	parent, parentKey, err := generateCert("Root CA", true, nil, nil)
  1617  	if err != nil {
  1618  		t.Fatal(err)
  1619  	}
  1620  	roots.AddCert(parent)
  1621  
  1622  	for i := 1; i < 15; i++ {
  1623  		name := fmt.Sprintf("Intermediate CA #%d", i)
  1624  		parent, parentKey, err = generateCert(name, true, parent, parentKey)
  1625  		if err != nil {
  1626  			t.Fatal(err)
  1627  		}
  1628  		intermediates.AddCert(parent)
  1629  	}
  1630  
  1631  	leaf, _, err := generateCert("Leaf", false, parent, parentKey)
  1632  	if err != nil {
  1633  		t.Fatal(err)
  1634  	}
  1635  
  1636  	start := time.Now()
  1637  	if _, err := leaf.Verify(VerifyOptions{
  1638  		Roots:         roots,
  1639  		Intermediates: intermediates,
  1640  	}); err != nil {
  1641  		t.Error(err)
  1642  	}
  1643  	t.Logf("verification took %v", time.Since(start))
  1644  }
  1645  
  1646  func TestSystemRootsError(t *testing.T) {
  1647  	if runtime.GOOS == "windows" || runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
  1648  		t.Skip("Windows and darwin do not use (or support) systemRoots")
  1649  	}
  1650  
  1651  	defer func(oldSystemRoots *CertPool) { systemRoots = oldSystemRoots }(systemRootsPool())
  1652  
  1653  	opts := VerifyOptions{
  1654  		Intermediates: NewCertPool(),
  1655  		DNSName:       "www.google.com",
  1656  		CurrentTime:   time.Unix(1677615892, 0),
  1657  	}
  1658  
  1659  	if ok := opts.Intermediates.AppendCertsFromPEM([]byte(gtsIntermediate)); !ok {
  1660  		t.Fatalf("failed to parse intermediate")
  1661  	}
  1662  
  1663  	leaf, err := certificateFromPEM(googleLeaf)
  1664  	if err != nil {
  1665  		t.Fatalf("failed to parse leaf: %v", err)
  1666  	}
  1667  
  1668  	systemRoots = nil
  1669  
  1670  	_, err = leaf.Verify(opts)
  1671  	if _, ok := err.(SystemRootsError); !ok {
  1672  		t.Errorf("error was not SystemRootsError: %v", err)
  1673  	}
  1674  }
  1675  
  1676  func TestSystemRootsErrorUnwrap(t *testing.T) {
  1677  	var err1 = errors.New("err1")
  1678  	err := SystemRootsError{Err: err1}
  1679  	if !errors.Is(err, err1) {
  1680  		t.Error("errors.Is failed, wanted success")
  1681  	}
  1682  }
  1683  
  1684  func macosMajorVersion(t *testing.T) (int, error) {
  1685  	cmd := testenv.Command(t, "sw_vers", "-productVersion")
  1686  	out, err := cmd.Output()
  1687  	if err != nil {
  1688  		if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
  1689  			return 0, fmt.Errorf("%v: %v\n%s", cmd, err, ee.Stderr)
  1690  		}
  1691  		return 0, fmt.Errorf("%v: %v", cmd, err)
  1692  	}
  1693  	before, _, ok := strings.Cut(string(out), ".")
  1694  	major, err := strconv.Atoi(before)
  1695  	if !ok || err != nil {
  1696  		return 0, fmt.Errorf("%v: unexpected output: %q", cmd, out)
  1697  	}
  1698  
  1699  	return major, nil
  1700  }
  1701  
  1702  func TestIssue51759(t *testing.T) {
  1703  	if runtime.GOOS != "darwin" {
  1704  		t.Skip("only affects darwin")
  1705  	}
  1706  
  1707  	testenv.MustHaveExecPath(t, "sw_vers")
  1708  	if vers, err := macosMajorVersion(t); err != nil {
  1709  		if builder := testenv.Builder(); builder != "" {
  1710  			t.Fatalf("unable to determine macOS version: %s", err)
  1711  		} else {
  1712  			t.Skip("unable to determine macOS version")
  1713  		}
  1714  	} else if vers < 11 {
  1715  		t.Skip("behavior only enforced in macOS 11 and after")
  1716  	}
  1717  
  1718  	// badCertData contains a cert that we parse as valid
  1719  	// but that macOS SecCertificateCreateWithData rejects.
  1720  	const badCertData = "0\x82\x01U0\x82\x01\a\xa0\x03\x02\x01\x02\x02\x01\x020\x05\x06\x03+ep0R1P0N\x06\x03U\x04\x03\x13Gderpkey8dc58100b2493614ee1692831a461f3f4dd3f9b3b088e244f887f81b4906ac260\x1e\x17\r220112235755Z\x17\r220313235755Z0R1P0N\x06\x03U\x04\x03\x13Gderpkey8dc58100b2493614ee1692831a461f3f4dd3f9b3b088e244f887f81b4906ac260*0\x05\x06\x03+ep\x03!\x00bA\xd8e\xadW\xcb\xefZ\x89\xb5\"\x1eR\x9d\xba\x0e:\x1042Q@\u007f\xbd\xfb{ks\x04\xd1£\x020\x000\x05\x06\x03+ep\x03A\x00[\xa7\x06y\x86(\x94\x97\x9eLwA\x00\x01x\xaa\xbc\xbd Ê]\n(΅!ف0\xf5\x9a%I\x19<\xffo\xf1\xeaaf@\xb1\xa7\xaf\xfd\xe9R\xc7\x0f\x8d&\xd5\xfc\x0f;Ϙ\x82\x84a\xbc\r"
  1721  	badCert, err := ParseCertificate([]byte(badCertData))
  1722  	if err != nil {
  1723  		t.Fatal(err)
  1724  	}
  1725  
  1726  	t.Run("leaf", func(t *testing.T) {
  1727  		opts := VerifyOptions{}
  1728  		expectedErr := "invalid leaf certificate"
  1729  		_, err = badCert.Verify(opts)
  1730  		if err == nil || err.Error() != expectedErr {
  1731  			t.Fatalf("unexpected error: want %q, got %q", expectedErr, err)
  1732  		}
  1733  	})
  1734  
  1735  	goodCert, err := certificateFromPEM(googleLeaf)
  1736  	if err != nil {
  1737  		t.Fatal(err)
  1738  	}
  1739  
  1740  	t.Run("intermediate", func(t *testing.T) {
  1741  		opts := VerifyOptions{
  1742  			Intermediates: NewCertPool(),
  1743  		}
  1744  		opts.Intermediates.AddCert(badCert)
  1745  		expectedErr := "SecCertificateCreateWithData: invalid certificate"
  1746  		_, err = goodCert.Verify(opts)
  1747  		if err == nil || err.Error() != expectedErr {
  1748  			t.Fatalf("unexpected error: want %q, got %q", expectedErr, err)
  1749  		}
  1750  	})
  1751  }
  1752  
  1753  type trustGraphEdge struct {
  1754  	Issuer         string
  1755  	Subject        string
  1756  	Type           int
  1757  	MutateTemplate func(*Certificate)
  1758  	Constraint     func([]*Certificate) error
  1759  }
  1760  
  1761  type rootDescription struct {
  1762  	Subject        string
  1763  	MutateTemplate func(*Certificate)
  1764  	Constraint     func([]*Certificate) error
  1765  }
  1766  
  1767  type trustGraphDescription struct {
  1768  	Roots []rootDescription
  1769  	Leaf  string
  1770  	Graph []trustGraphEdge
  1771  }
  1772  
  1773  func genCertEdge(t *testing.T, subject string, key crypto.Signer, mutateTmpl func(*Certificate), certType int, issuer *Certificate, signer crypto.Signer) *Certificate {
  1774  	t.Helper()
  1775  
  1776  	serial, err := rand.Int(rand.Reader, big.NewInt(100))
  1777  	if err != nil {
  1778  		t.Fatalf("failed to generate test serial: %s", err)
  1779  	}
  1780  	tmpl := &Certificate{
  1781  		SerialNumber: serial,
  1782  		Subject:      pkix.Name{CommonName: subject},
  1783  		NotBefore:    time.Now().Add(-time.Hour),
  1784  		NotAfter:     time.Now().Add(time.Hour),
  1785  	}
  1786  	if certType == rootCertificate || certType == intermediateCertificate {
  1787  		tmpl.IsCA, tmpl.BasicConstraintsValid = true, true
  1788  		tmpl.KeyUsage = KeyUsageCertSign
  1789  	} else if certType == leafCertificate {
  1790  		tmpl.DNSNames = []string{"localhost"}
  1791  	}
  1792  	if mutateTmpl != nil {
  1793  		mutateTmpl(tmpl)
  1794  	}
  1795  
  1796  	if certType == rootCertificate {
  1797  		issuer = tmpl
  1798  		signer = key
  1799  	}
  1800  
  1801  	d, err := CreateCertificate(rand.Reader, tmpl, issuer, key.Public(), signer)
  1802  	if err != nil {
  1803  		t.Fatalf("failed to generate test cert: %s", err)
  1804  	}
  1805  	c, err := ParseCertificate(d)
  1806  	if err != nil {
  1807  		t.Fatalf("failed to parse test cert: %s", err)
  1808  	}
  1809  	return c
  1810  }
  1811  
  1812  func buildTrustGraph(t *testing.T, d trustGraphDescription) (*CertPool, *CertPool, *Certificate) {
  1813  	t.Helper()
  1814  
  1815  	certs := map[string]*Certificate{}
  1816  	keys := map[string]crypto.Signer{}
  1817  	rootPool := NewCertPool()
  1818  	for _, r := range d.Roots {
  1819  		k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  1820  		if err != nil {
  1821  			t.Fatalf("failed to generate test key: %s", err)
  1822  		}
  1823  		root := genCertEdge(t, r.Subject, k, r.MutateTemplate, rootCertificate, nil, nil)
  1824  		if r.Constraint != nil {
  1825  			rootPool.AddCertWithConstraint(root, r.Constraint)
  1826  		} else {
  1827  			rootPool.AddCert(root)
  1828  		}
  1829  		certs[r.Subject] = root
  1830  		keys[r.Subject] = k
  1831  	}
  1832  
  1833  	intermediatePool := NewCertPool()
  1834  	var leaf *Certificate
  1835  	for _, e := range d.Graph {
  1836  		issuerCert, ok := certs[e.Issuer]
  1837  		if !ok {
  1838  			t.Fatalf("unknown issuer %s", e.Issuer)
  1839  		}
  1840  		issuerKey, ok := keys[e.Issuer]
  1841  		if !ok {
  1842  			t.Fatalf("unknown issuer %s", e.Issuer)
  1843  		}
  1844  
  1845  		k, ok := keys[e.Subject]
  1846  		if !ok {
  1847  			var err error
  1848  			k, err = ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  1849  			if err != nil {
  1850  				t.Fatalf("failed to generate test key: %s", err)
  1851  			}
  1852  			keys[e.Subject] = k
  1853  		}
  1854  		cert := genCertEdge(t, e.Subject, k, e.MutateTemplate, e.Type, issuerCert, issuerKey)
  1855  		certs[e.Subject] = cert
  1856  		if e.Subject == d.Leaf {
  1857  			leaf = cert
  1858  		} else {
  1859  			if e.Constraint != nil {
  1860  				intermediatePool.AddCertWithConstraint(cert, e.Constraint)
  1861  			} else {
  1862  				intermediatePool.AddCert(cert)
  1863  			}
  1864  		}
  1865  	}
  1866  
  1867  	return rootPool, intermediatePool, leaf
  1868  }
  1869  
  1870  func chainsToStrings(chains [][]*Certificate) []string {
  1871  	chainStrings := []string{}
  1872  	for _, chain := range chains {
  1873  		names := []string{}
  1874  		for _, c := range chain {
  1875  			names = append(names, c.Subject.String())
  1876  		}
  1877  		chainStrings = append(chainStrings, strings.Join(names, " -> "))
  1878  	}
  1879  	slices.Sort(chainStrings)
  1880  	return chainStrings
  1881  }
  1882  
  1883  func TestPathBuilding(t *testing.T) {
  1884  	tests := []struct {
  1885  		name           string
  1886  		graph          trustGraphDescription
  1887  		expectedChains []string
  1888  		expectedErr    string
  1889  	}{
  1890  		{
  1891  			// Build the following graph from RFC 4158, figure 7 (note that in this graph edges represent
  1892  			// certificates where the parent is the issuer and the child is the subject.) For the certificate
  1893  			// C->B, use an unsupported ExtKeyUsage (in this case ExtKeyUsageCodeSigning) which invalidates
  1894  			// the path Trust Anchor -> C -> B -> EE. The remaining valid paths should be:
  1895  			//   * Trust Anchor -> A -> B -> EE
  1896  			//   * Trust Anchor -> C -> A -> B -> EE
  1897  			//
  1898  			//     +---------+
  1899  			//     |  Trust  |
  1900  			//     | Anchor  |
  1901  			//     +---------+
  1902  			//      |       |
  1903  			//      v       v
  1904  			//   +---+    +---+
  1905  			//   | A |<-->| C |
  1906  			//   +---+    +---+
  1907  			//    |         |
  1908  			//    |  +---+  |
  1909  			//    +->| B |<-+
  1910  			//       +---+
  1911  			//         |
  1912  			//         v
  1913  			//       +----+
  1914  			//       | EE |
  1915  			//       +----+
  1916  			name: "bad EKU",
  1917  			graph: trustGraphDescription{
  1918  				Roots: []rootDescription{{Subject: "root"}},
  1919  				Leaf:  "leaf",
  1920  				Graph: []trustGraphEdge{
  1921  					{
  1922  						Issuer:  "root",
  1923  						Subject: "inter a",
  1924  						Type:    intermediateCertificate,
  1925  					},
  1926  					{
  1927  						Issuer:  "root",
  1928  						Subject: "inter c",
  1929  						Type:    intermediateCertificate,
  1930  					},
  1931  					{
  1932  						Issuer:  "inter c",
  1933  						Subject: "inter a",
  1934  						Type:    intermediateCertificate,
  1935  					},
  1936  					{
  1937  						Issuer:  "inter a",
  1938  						Subject: "inter c",
  1939  						Type:    intermediateCertificate,
  1940  					},
  1941  					{
  1942  						Issuer:  "inter c",
  1943  						Subject: "inter b",
  1944  						Type:    intermediateCertificate,
  1945  						MutateTemplate: func(t *Certificate) {
  1946  							t.ExtKeyUsage = []ExtKeyUsage{ExtKeyUsageCodeSigning}
  1947  						},
  1948  					},
  1949  					{
  1950  						Issuer:  "inter a",
  1951  						Subject: "inter b",
  1952  						Type:    intermediateCertificate,
  1953  					},
  1954  					{
  1955  						Issuer:  "inter b",
  1956  						Subject: "leaf",
  1957  						Type:    leafCertificate,
  1958  					},
  1959  				},
  1960  			},
  1961  			expectedChains: []string{
  1962  				"CN=leaf -> CN=inter b -> CN=inter a -> CN=inter c -> CN=root",
  1963  				"CN=leaf -> CN=inter b -> CN=inter a -> CN=root",
  1964  			},
  1965  		},
  1966  		{
  1967  			// Build the following graph from RFC 4158, figure 7 (note that in this graph edges represent
  1968  			// certificates where the parent is the issuer and the child is the subject.) For the certificate
  1969  			// C->B, use a unconstrained SAN which invalidates the path Trust Anchor -> C -> B -> EE. The
  1970  			// remaining valid paths should be:
  1971  			//   * Trust Anchor -> A -> B -> EE
  1972  			//   * Trust Anchor -> C -> A -> B -> EE
  1973  			//
  1974  			//     +---------+
  1975  			//     |  Trust  |
  1976  			//     | Anchor  |
  1977  			//     +---------+
  1978  			//      |       |
  1979  			//      v       v
  1980  			//   +---+    +---+
  1981  			//   | A |<-->| C |
  1982  			//   +---+    +---+
  1983  			//    |         |
  1984  			//    |  +---+  |
  1985  			//    +->| B |<-+
  1986  			//       +---+
  1987  			//         |
  1988  			//         v
  1989  			//       +----+
  1990  			//       | EE |
  1991  			//       +----+
  1992  			name: "bad EKU",
  1993  			graph: trustGraphDescription{
  1994  				Roots: []rootDescription{{Subject: "root"}},
  1995  				Leaf:  "leaf",
  1996  				Graph: []trustGraphEdge{
  1997  					{
  1998  						Issuer:  "root",
  1999  						Subject: "inter a",
  2000  						Type:    intermediateCertificate,
  2001  					},
  2002  					{
  2003  						Issuer:  "root",
  2004  						Subject: "inter c",
  2005  						Type:    intermediateCertificate,
  2006  					},
  2007  					{
  2008  						Issuer:  "inter c",
  2009  						Subject: "inter a",
  2010  						Type:    intermediateCertificate,
  2011  					},
  2012  					{
  2013  						Issuer:  "inter a",
  2014  						Subject: "inter c",
  2015  						Type:    intermediateCertificate,
  2016  					},
  2017  					{
  2018  						Issuer:  "inter c",
  2019  						Subject: "inter b",
  2020  						Type:    intermediateCertificate,
  2021  						MutateTemplate: func(t *Certificate) {
  2022  							t.PermittedDNSDomains = []string{"good"}
  2023  							t.DNSNames = []string{"bad"}
  2024  						},
  2025  					},
  2026  					{
  2027  						Issuer:  "inter a",
  2028  						Subject: "inter b",
  2029  						Type:    intermediateCertificate,
  2030  					},
  2031  					{
  2032  						Issuer:  "inter b",
  2033  						Subject: "leaf",
  2034  						Type:    leafCertificate,
  2035  					},
  2036  				},
  2037  			},
  2038  			expectedChains: []string{
  2039  				"CN=leaf -> CN=inter b -> CN=inter a -> CN=inter c -> CN=root",
  2040  				"CN=leaf -> CN=inter b -> CN=inter a -> CN=root",
  2041  			},
  2042  		},
  2043  		{
  2044  			// Build the following graph, we should find both paths:
  2045  			//   * Trust Anchor -> A -> C -> EE
  2046  			//   * Trust Anchor -> A -> B -> C -> EE
  2047  			//
  2048  			//	       +---------+
  2049  			//	       |  Trust  |
  2050  			//	       | Anchor  |
  2051  			//	       +---------+
  2052  			//	            |
  2053  			//	            v
  2054  			//	          +---+
  2055  			//	          | A |
  2056  			//	          +---+
  2057  			//	           | |
  2058  			//	           | +----+
  2059  			//	           |      v
  2060  			//	           |    +---+
  2061  			//	           |    | B |
  2062  			//	           |    +---+
  2063  			//	           |      |
  2064  			//	           |  +---v
  2065  			//	           v  v
  2066  			//            +---+
  2067  			//            | C |
  2068  			//            +---+
  2069  			//              |
  2070  			//              v
  2071  			//            +----+
  2072  			//            | EE |
  2073  			//            +----+
  2074  			name: "all paths",
  2075  			graph: trustGraphDescription{
  2076  				Roots: []rootDescription{{Subject: "root"}},
  2077  				Leaf:  "leaf",
  2078  				Graph: []trustGraphEdge{
  2079  					{
  2080  						Issuer:  "root",
  2081  						Subject: "inter a",
  2082  						Type:    intermediateCertificate,
  2083  					},
  2084  					{
  2085  						Issuer:  "inter a",
  2086  						Subject: "inter b",
  2087  						Type:    intermediateCertificate,
  2088  					},
  2089  					{
  2090  						Issuer:  "inter a",
  2091  						Subject: "inter c",
  2092  						Type:    intermediateCertificate,
  2093  					},
  2094  					{
  2095  						Issuer:  "inter b",
  2096  						Subject: "inter c",
  2097  						Type:    intermediateCertificate,
  2098  					},
  2099  					{
  2100  						Issuer:  "inter c",
  2101  						Subject: "leaf",
  2102  						Type:    leafCertificate,
  2103  					},
  2104  				},
  2105  			},
  2106  			expectedChains: []string{
  2107  				"CN=leaf -> CN=inter c -> CN=inter a -> CN=root",
  2108  				"CN=leaf -> CN=inter c -> CN=inter b -> CN=inter a -> CN=root",
  2109  			},
  2110  		},
  2111  		{
  2112  			// Build the following graph, which contains a cross-signature loop
  2113  			// (A and C cross sign each other). Paths that include the A -> C -> A
  2114  			// (and vice versa) loop should be ignored, resulting in the paths:
  2115  			//   * Trust Anchor -> A -> B -> EE
  2116  			//   * Trust Anchor -> C -> B -> EE
  2117  			//   * Trust Anchor -> A -> C -> B -> EE
  2118  			//   * Trust Anchor -> C -> A -> B -> EE
  2119  			//
  2120  			//     +---------+
  2121  			//     |  Trust  |
  2122  			//     | Anchor  |
  2123  			//     +---------+
  2124  			//      |       |
  2125  			//      v       v
  2126  			//   +---+    +---+
  2127  			//   | A |<-->| C |
  2128  			//   +---+    +---+
  2129  			//    |         |
  2130  			//    |  +---+  |
  2131  			//    +->| B |<-+
  2132  			//       +---+
  2133  			//         |
  2134  			//         v
  2135  			//       +----+
  2136  			//       | EE |
  2137  			//       +----+
  2138  			name: "ignore cross-sig loops",
  2139  			graph: trustGraphDescription{
  2140  				Roots: []rootDescription{{Subject: "root"}},
  2141  				Leaf:  "leaf",
  2142  				Graph: []trustGraphEdge{
  2143  					{
  2144  						Issuer:  "root",
  2145  						Subject: "inter a",
  2146  						Type:    intermediateCertificate,
  2147  					},
  2148  					{
  2149  						Issuer:  "root",
  2150  						Subject: "inter c",
  2151  						Type:    intermediateCertificate,
  2152  					},
  2153  					{
  2154  						Issuer:  "inter c",
  2155  						Subject: "inter a",
  2156  						Type:    intermediateCertificate,
  2157  					},
  2158  					{
  2159  						Issuer:  "inter a",
  2160  						Subject: "inter c",
  2161  						Type:    intermediateCertificate,
  2162  					},
  2163  					{
  2164  						Issuer:  "inter c",
  2165  						Subject: "inter b",
  2166  						Type:    intermediateCertificate,
  2167  					},
  2168  					{
  2169  						Issuer:  "inter a",
  2170  						Subject: "inter b",
  2171  						Type:    intermediateCertificate,
  2172  					},
  2173  					{
  2174  						Issuer:  "inter b",
  2175  						Subject: "leaf",
  2176  						Type:    leafCertificate,
  2177  					},
  2178  				},
  2179  			},
  2180  			expectedChains: []string{
  2181  				"CN=leaf -> CN=inter b -> CN=inter a -> CN=inter c -> CN=root",
  2182  				"CN=leaf -> CN=inter b -> CN=inter a -> CN=root",
  2183  				"CN=leaf -> CN=inter b -> CN=inter c -> CN=inter a -> CN=root",
  2184  				"CN=leaf -> CN=inter b -> CN=inter c -> CN=root",
  2185  			},
  2186  		},
  2187  		{
  2188  			// Build a simple two node graph, where the leaf is directly issued from
  2189  			// the root and both certificates have matching subject and public key, but
  2190  			// the leaf has SANs.
  2191  			name: "leaf with same subject, key, as parent but with SAN",
  2192  			graph: trustGraphDescription{
  2193  				Roots: []rootDescription{{Subject: "root"}},
  2194  				Leaf:  "root",
  2195  				Graph: []trustGraphEdge{
  2196  					{
  2197  						Issuer:  "root",
  2198  						Subject: "root",
  2199  						Type:    leafCertificate,
  2200  						MutateTemplate: func(c *Certificate) {
  2201  							c.DNSNames = []string{"localhost"}
  2202  						},
  2203  					},
  2204  				},
  2205  			},
  2206  			expectedChains: []string{
  2207  				"CN=root -> CN=root",
  2208  			},
  2209  		},
  2210  		{
  2211  			// Build a basic graph with two paths from leaf to root, but the path passing
  2212  			// through C should be ignored, because it has invalid EKU nesting.
  2213  			name: "ignore invalid EKU path",
  2214  			graph: trustGraphDescription{
  2215  				Roots: []rootDescription{{Subject: "root"}},
  2216  				Leaf:  "leaf",
  2217  				Graph: []trustGraphEdge{
  2218  					{
  2219  						Issuer:  "root",
  2220  						Subject: "inter a",
  2221  						Type:    intermediateCertificate,
  2222  					},
  2223  					{
  2224  						Issuer:  "root",
  2225  						Subject: "inter c",
  2226  						Type:    intermediateCertificate,
  2227  					},
  2228  					{
  2229  						Issuer:  "inter c",
  2230  						Subject: "inter b",
  2231  						Type:    intermediateCertificate,
  2232  						MutateTemplate: func(t *Certificate) {
  2233  							t.ExtKeyUsage = []ExtKeyUsage{ExtKeyUsageCodeSigning}
  2234  						},
  2235  					},
  2236  					{
  2237  						Issuer:  "inter a",
  2238  						Subject: "inter b",
  2239  						Type:    intermediateCertificate,
  2240  						MutateTemplate: func(t *Certificate) {
  2241  							t.ExtKeyUsage = []ExtKeyUsage{ExtKeyUsageServerAuth}
  2242  						},
  2243  					},
  2244  					{
  2245  						Issuer:  "inter b",
  2246  						Subject: "leaf",
  2247  						Type:    leafCertificate,
  2248  						MutateTemplate: func(t *Certificate) {
  2249  							t.ExtKeyUsage = []ExtKeyUsage{ExtKeyUsageServerAuth}
  2250  						},
  2251  					},
  2252  				},
  2253  			},
  2254  			expectedChains: []string{
  2255  				"CN=leaf -> CN=inter b -> CN=inter a -> CN=root",
  2256  			},
  2257  		},
  2258  		{
  2259  			// A name constraint on the root should apply to any names that appear
  2260  			// on the intermediate, meaning there is no valid chain.
  2261  			name: "constrained root, invalid intermediate",
  2262  			graph: trustGraphDescription{
  2263  				Roots: []rootDescription{
  2264  					{
  2265  						Subject: "root",
  2266  						MutateTemplate: func(t *Certificate) {
  2267  							t.PermittedDNSDomains = []string{"example.com"}
  2268  						},
  2269  					},
  2270  				},
  2271  				Leaf: "leaf",
  2272  				Graph: []trustGraphEdge{
  2273  					{
  2274  						Issuer:  "root",
  2275  						Subject: "inter",
  2276  						Type:    intermediateCertificate,
  2277  						MutateTemplate: func(t *Certificate) {
  2278  							t.DNSNames = []string{"beep.com"}
  2279  						},
  2280  					},
  2281  					{
  2282  						Issuer:  "inter",
  2283  						Subject: "leaf",
  2284  						Type:    leafCertificate,
  2285  						MutateTemplate: func(t *Certificate) {
  2286  							t.DNSNames = []string{"www.example.com"}
  2287  						},
  2288  					},
  2289  				},
  2290  			},
  2291  			expectedErr: "x509: a root or intermediate certificate is not authorized to sign for this name: DNS name \"beep.com\" is not permitted by any constraint",
  2292  		},
  2293  		{
  2294  			// A name constraint on the intermediate does not apply to the intermediate
  2295  			// itself, so this is a valid chain.
  2296  			name: "constrained intermediate, non-matching SAN",
  2297  			graph: trustGraphDescription{
  2298  				Roots: []rootDescription{{Subject: "root"}},
  2299  				Leaf:  "leaf",
  2300  				Graph: []trustGraphEdge{
  2301  					{
  2302  						Issuer:  "root",
  2303  						Subject: "inter",
  2304  						Type:    intermediateCertificate,
  2305  						MutateTemplate: func(t *Certificate) {
  2306  							t.DNSNames = []string{"beep.com"}
  2307  							t.PermittedDNSDomains = []string{"example.com"}
  2308  						},
  2309  					},
  2310  					{
  2311  						Issuer:  "inter",
  2312  						Subject: "leaf",
  2313  						Type:    leafCertificate,
  2314  						MutateTemplate: func(t *Certificate) {
  2315  							t.DNSNames = []string{"www.example.com"}
  2316  						},
  2317  					},
  2318  				},
  2319  			},
  2320  			expectedChains: []string{"CN=leaf -> CN=inter -> CN=root"},
  2321  		},
  2322  		{
  2323  			// A code constraint on the root, applying to one of two intermediates in the graph, should
  2324  			// result in only one valid chain.
  2325  			name: "code constrained root, two paths, one valid",
  2326  			graph: trustGraphDescription{
  2327  				Roots: []rootDescription{{Subject: "root", Constraint: func(chain []*Certificate) error {
  2328  					for _, c := range chain {
  2329  						if c.Subject.CommonName == "inter a" {
  2330  							return errors.New("bad")
  2331  						}
  2332  					}
  2333  					return nil
  2334  				}}},
  2335  				Leaf: "leaf",
  2336  				Graph: []trustGraphEdge{
  2337  					{
  2338  						Issuer:  "root",
  2339  						Subject: "inter a",
  2340  						Type:    intermediateCertificate,
  2341  					},
  2342  					{
  2343  						Issuer:  "root",
  2344  						Subject: "inter b",
  2345  						Type:    intermediateCertificate,
  2346  					},
  2347  					{
  2348  						Issuer:  "inter a",
  2349  						Subject: "inter c",
  2350  						Type:    intermediateCertificate,
  2351  					},
  2352  					{
  2353  						Issuer:  "inter b",
  2354  						Subject: "inter c",
  2355  						Type:    intermediateCertificate,
  2356  					},
  2357  					{
  2358  						Issuer:  "inter c",
  2359  						Subject: "leaf",
  2360  						Type:    leafCertificate,
  2361  					},
  2362  				},
  2363  			},
  2364  			expectedChains: []string{"CN=leaf -> CN=inter c -> CN=inter b -> CN=root"},
  2365  		},
  2366  		{
  2367  			// A code constraint on the root, applying to the only path, should result in an error.
  2368  			name: "code constrained root, one invalid path",
  2369  			graph: trustGraphDescription{
  2370  				Roots: []rootDescription{{Subject: "root", Constraint: func(chain []*Certificate) error {
  2371  					for _, c := range chain {
  2372  						if c.Subject.CommonName == "leaf" {
  2373  							return errors.New("bad")
  2374  						}
  2375  					}
  2376  					return nil
  2377  				}}},
  2378  				Leaf: "leaf",
  2379  				Graph: []trustGraphEdge{
  2380  					{
  2381  						Issuer:  "root",
  2382  						Subject: "inter",
  2383  						Type:    intermediateCertificate,
  2384  					},
  2385  					{
  2386  						Issuer:  "inter",
  2387  						Subject: "leaf",
  2388  						Type:    leafCertificate,
  2389  					},
  2390  				},
  2391  			},
  2392  			expectedErr: "x509: certificate signed by unknown authority (possibly because of \"bad\" while trying to verify candidate authority certificate \"root\")",
  2393  		},
  2394  	}
  2395  
  2396  	for _, tc := range tests {
  2397  		t.Run(tc.name, func(t *testing.T) {
  2398  			roots, intermediates, leaf := buildTrustGraph(t, tc.graph)
  2399  			chains, err := leaf.Verify(VerifyOptions{
  2400  				Roots:         roots,
  2401  				Intermediates: intermediates,
  2402  			})
  2403  			if err != nil && err.Error() != tc.expectedErr {
  2404  				t.Fatalf("unexpected error: got %q, want %q", err, tc.expectedErr)
  2405  			}
  2406  			if len(tc.expectedChains) == 0 {
  2407  				return
  2408  			}
  2409  			gotChains := chainsToStrings(chains)
  2410  			if !slices.Equal(gotChains, tc.expectedChains) {
  2411  				t.Errorf("unexpected chains returned:\ngot:\n\t%s\nwant:\n\t%s", strings.Join(gotChains, "\n\t"), strings.Join(tc.expectedChains, "\n\t"))
  2412  			}
  2413  		})
  2414  	}
  2415  }
  2416  
  2417  func TestEKUEnforcement(t *testing.T) {
  2418  	type ekuDescs struct {
  2419  		EKUs    []ExtKeyUsage
  2420  		Unknown []asn1.ObjectIdentifier
  2421  	}
  2422  	tests := []struct {
  2423  		name       string
  2424  		root       ekuDescs
  2425  		inters     []ekuDescs
  2426  		leaf       ekuDescs
  2427  		verifyEKUs []ExtKeyUsage
  2428  		err        string
  2429  	}{
  2430  		{
  2431  			name:       "valid, full chain",
  2432  			root:       ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}},
  2433  			inters:     []ekuDescs{ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}}},
  2434  			leaf:       ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}},
  2435  			verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth},
  2436  		},
  2437  		{
  2438  			name:       "valid, only leaf has EKU",
  2439  			root:       ekuDescs{},
  2440  			inters:     []ekuDescs{ekuDescs{}},
  2441  			leaf:       ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}},
  2442  			verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth},
  2443  		},
  2444  		{
  2445  			name:       "invalid, serverAuth not nested",
  2446  			root:       ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageClientAuth}},
  2447  			inters:     []ekuDescs{ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}}},
  2448  			leaf:       ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}},
  2449  			verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth},
  2450  			err:        "x509: certificate specifies an incompatible key usage",
  2451  		},
  2452  		{
  2453  			name:       "valid, two EKUs, one path",
  2454  			root:       ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}},
  2455  			inters:     []ekuDescs{ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}}},
  2456  			leaf:       ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}},
  2457  			verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth},
  2458  		},
  2459  		{
  2460  			name: "invalid, ladder",
  2461  			root: ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}},
  2462  			inters: []ekuDescs{
  2463  				ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}},
  2464  				ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageClientAuth}},
  2465  				ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth}},
  2466  				ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}},
  2467  			},
  2468  			leaf:       ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}},
  2469  			verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth},
  2470  			err:        "x509: certificate specifies an incompatible key usage",
  2471  		},
  2472  		{
  2473  			name:       "valid, intermediate has no EKU",
  2474  			root:       ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}},
  2475  			inters:     []ekuDescs{ekuDescs{}},
  2476  			leaf:       ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}},
  2477  			verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth},
  2478  		},
  2479  		{
  2480  			name:       "invalid, intermediate has no EKU and no nested path",
  2481  			root:       ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageClientAuth}},
  2482  			inters:     []ekuDescs{ekuDescs{}},
  2483  			leaf:       ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}},
  2484  			verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth, ExtKeyUsageClientAuth},
  2485  			err:        "x509: certificate specifies an incompatible key usage",
  2486  		},
  2487  		{
  2488  			name:       "invalid, intermediate has unknown EKU",
  2489  			root:       ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}},
  2490  			inters:     []ekuDescs{ekuDescs{Unknown: []asn1.ObjectIdentifier{{1, 2, 3}}}},
  2491  			leaf:       ekuDescs{EKUs: []ExtKeyUsage{ExtKeyUsageServerAuth}},
  2492  			verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth},
  2493  			err:        "x509: certificate specifies an incompatible key usage",
  2494  		},
  2495  	}
  2496  
  2497  	k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  2498  	if err != nil {
  2499  		t.Fatalf("failed to generate test key: %s", err)
  2500  	}
  2501  
  2502  	for _, tc := range tests {
  2503  		t.Run(tc.name, func(t *testing.T) {
  2504  			rootPool := NewCertPool()
  2505  			root := genCertEdge(t, "root", k, func(c *Certificate) {
  2506  				c.ExtKeyUsage = tc.root.EKUs
  2507  				c.UnknownExtKeyUsage = tc.root.Unknown
  2508  			}, rootCertificate, nil, k)
  2509  			rootPool.AddCert(root)
  2510  
  2511  			parent := root
  2512  			interPool := NewCertPool()
  2513  			for i, interEKUs := range tc.inters {
  2514  				inter := genCertEdge(t, fmt.Sprintf("inter %d", i), k, func(c *Certificate) {
  2515  					c.ExtKeyUsage = interEKUs.EKUs
  2516  					c.UnknownExtKeyUsage = interEKUs.Unknown
  2517  				}, intermediateCertificate, parent, k)
  2518  				interPool.AddCert(inter)
  2519  				parent = inter
  2520  			}
  2521  
  2522  			leaf := genCertEdge(t, "leaf", k, func(c *Certificate) {
  2523  				c.ExtKeyUsage = tc.leaf.EKUs
  2524  				c.UnknownExtKeyUsage = tc.leaf.Unknown
  2525  			}, intermediateCertificate, parent, k)
  2526  
  2527  			_, err := leaf.Verify(VerifyOptions{Roots: rootPool, Intermediates: interPool, KeyUsages: tc.verifyEKUs})
  2528  			if err == nil && tc.err != "" {
  2529  				t.Errorf("expected error")
  2530  			} else if err != nil && err.Error() != tc.err {
  2531  				t.Errorf("unexpected error: got %q, want %q", err.Error(), tc.err)
  2532  			}
  2533  		})
  2534  	}
  2535  }
  2536  
  2537  func TestVerifyEKURootAsLeaf(t *testing.T) {
  2538  	k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  2539  	if err != nil {
  2540  		t.Fatalf("failed to generate key: %s", err)
  2541  	}
  2542  
  2543  	for _, tc := range []struct {
  2544  		rootEKUs   []ExtKeyUsage
  2545  		verifyEKUs []ExtKeyUsage
  2546  		succeed    bool
  2547  	}{
  2548  		{
  2549  			verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth},
  2550  			succeed:    true,
  2551  		},
  2552  		{
  2553  			rootEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth},
  2554  			succeed:  true,
  2555  		},
  2556  		{
  2557  			rootEKUs:   []ExtKeyUsage{ExtKeyUsageServerAuth},
  2558  			verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth},
  2559  			succeed:    true,
  2560  		},
  2561  		{
  2562  			rootEKUs:   []ExtKeyUsage{ExtKeyUsageServerAuth},
  2563  			verifyEKUs: []ExtKeyUsage{ExtKeyUsageAny},
  2564  			succeed:    true,
  2565  		},
  2566  		{
  2567  			rootEKUs:   []ExtKeyUsage{ExtKeyUsageAny},
  2568  			verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth},
  2569  			succeed:    true,
  2570  		},
  2571  		{
  2572  			rootEKUs:   []ExtKeyUsage{ExtKeyUsageClientAuth},
  2573  			verifyEKUs: []ExtKeyUsage{ExtKeyUsageServerAuth},
  2574  			succeed:    false,
  2575  		},
  2576  	} {
  2577  		t.Run(fmt.Sprintf("root EKUs %#v, verify EKUs %#v", tc.rootEKUs, tc.verifyEKUs), func(t *testing.T) {
  2578  			tmpl := &Certificate{
  2579  				SerialNumber: big.NewInt(1),
  2580  				Subject:      pkix.Name{CommonName: "root"},
  2581  				NotBefore:    time.Now().Add(-time.Hour),
  2582  				NotAfter:     time.Now().Add(time.Hour),
  2583  				DNSNames:     []string{"localhost"},
  2584  				ExtKeyUsage:  tc.rootEKUs,
  2585  			}
  2586  			rootDER, err := CreateCertificate(rand.Reader, tmpl, tmpl, k.Public(), k)
  2587  			if err != nil {
  2588  				t.Fatalf("failed to create certificate: %s", err)
  2589  			}
  2590  			root, err := ParseCertificate(rootDER)
  2591  			if err != nil {
  2592  				t.Fatalf("failed to parse certificate: %s", err)
  2593  			}
  2594  			roots := NewCertPool()
  2595  			roots.AddCert(root)
  2596  
  2597  			_, err = root.Verify(VerifyOptions{Roots: roots, KeyUsages: tc.verifyEKUs})
  2598  			if err == nil && !tc.succeed {
  2599  				t.Error("verification succeed")
  2600  			} else if err != nil && tc.succeed {
  2601  				t.Errorf("verification failed: %q", err)
  2602  			}
  2603  		})
  2604  	}
  2605  
  2606  }
  2607  
  2608  func TestVerifyNilPubKey(t *testing.T) {
  2609  	c := &Certificate{
  2610  		RawIssuer:      []byte{1, 2, 3},
  2611  		AuthorityKeyId: []byte{1, 2, 3},
  2612  	}
  2613  	opts := &VerifyOptions{}
  2614  	opts.Roots = NewCertPool()
  2615  	r := &Certificate{
  2616  		RawSubject:   []byte{1, 2, 3},
  2617  		SubjectKeyId: []byte{1, 2, 3},
  2618  	}
  2619  	opts.Roots.AddCert(r)
  2620  
  2621  	_, err := c.buildChains([]*Certificate{r}, nil, opts)
  2622  	if _, ok := err.(UnknownAuthorityError); !ok {
  2623  		t.Fatalf("buildChains returned unexpected error, got: %v, want %v", err, UnknownAuthorityError{})
  2624  	}
  2625  }
  2626  
  2627  func TestVerifyBareWildcard(t *testing.T) {
  2628  	k, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  2629  	if err != nil {
  2630  		t.Fatalf("failed to generate key: %s", err)
  2631  	}
  2632  	tmpl := &Certificate{
  2633  		SerialNumber: big.NewInt(1),
  2634  		Subject:      pkix.Name{CommonName: "test"},
  2635  		NotBefore:    time.Now().Add(-time.Hour),
  2636  		NotAfter:     time.Now().Add(time.Hour),
  2637  		DNSNames:     []string{"*"},
  2638  	}
  2639  	cDER, err := CreateCertificate(rand.Reader, tmpl, tmpl, k.Public(), k)
  2640  	if err != nil {
  2641  		t.Fatalf("failed to create certificate: %s", err)
  2642  	}
  2643  	c, err := ParseCertificate(cDER)
  2644  	if err != nil {
  2645  		t.Fatalf("failed to parse certificate: %s", err)
  2646  	}
  2647  
  2648  	if err := c.VerifyHostname("label"); err == nil {
  2649  		t.Fatalf("VerifyHostname unexpected success with bare wildcard SAN")
  2650  	}
  2651  }
  2652  
  2653  func TestPoliciesValid(t *testing.T) {
  2654  	// These test cases, the comments, and the certificates they rely on, are
  2655  	// stolen from BoringSSL [0]. We skip the tests which involve certificate
  2656  	// parsing as part of the verification process. Those tests are in
  2657  	// TestParsePolicies.
  2658  	//
  2659  	// [0] https://boringssl.googlesource.com/boringssl/+/264f4f7a958af6c4ccb04662e302a99dfa7c5b85/crypto/x509/x509_test.cc#5913
  2660  
  2661  	testOID1 := mustNewOIDFromInts([]uint64{1, 2, 840, 113554, 4, 1, 72585, 2, 1})
  2662  	testOID2 := mustNewOIDFromInts([]uint64{1, 2, 840, 113554, 4, 1, 72585, 2, 2})
  2663  	testOID3 := mustNewOIDFromInts([]uint64{1, 2, 840, 113554, 4, 1, 72585, 2, 3})
  2664  	testOID4 := mustNewOIDFromInts([]uint64{1, 2, 840, 113554, 4, 1, 72585, 2, 4})
  2665  	testOID5 := mustNewOIDFromInts([]uint64{1, 2, 840, 113554, 4, 1, 72585, 2, 5})
  2666  
  2667  	loadTestCert := func(t *testing.T, path string) *Certificate {
  2668  		b, err := os.ReadFile(path)
  2669  		if err != nil {
  2670  			t.Fatal(err)
  2671  		}
  2672  		p, _ := pem.Decode(b)
  2673  		c, err := ParseCertificate(p.Bytes)
  2674  		if err != nil {
  2675  			t.Fatal(err)
  2676  		}
  2677  		return c
  2678  	}
  2679  
  2680  	root := loadTestCert(t, "testdata/policy_root.pem")
  2681  	root_cross_inhibit_mapping := loadTestCert(t, "testdata/policy_root_cross_inhibit_mapping.pem")
  2682  	root2 := loadTestCert(t, "testdata/policy_root2.pem")
  2683  	intermediate := loadTestCert(t, "testdata/policy_intermediate.pem")
  2684  	intermediate_any := loadTestCert(t, "testdata/policy_intermediate_any.pem")
  2685  	intermediate_mapped := loadTestCert(t, "testdata/policy_intermediate_mapped.pem")
  2686  	intermediate_mapped_any := loadTestCert(t, "testdata/policy_intermediate_mapped_any.pem")
  2687  	intermediate_mapped_oid3 := loadTestCert(t, "testdata/policy_intermediate_mapped_oid3.pem")
  2688  	intermediate_require := loadTestCert(t, "testdata/policy_intermediate_require.pem")
  2689  	intermediate_require1 := loadTestCert(t, "testdata/policy_intermediate_require1.pem")
  2690  	intermediate_require2 := loadTestCert(t, "testdata/policy_intermediate_require2.pem")
  2691  	intermediate_require_no_policies := loadTestCert(t, "testdata/policy_intermediate_require_no_policies.pem")
  2692  	leaf := loadTestCert(t, "testdata/policy_leaf.pem")
  2693  	leaf_any := loadTestCert(t, "testdata/policy_leaf_any.pem")
  2694  	leaf_none := loadTestCert(t, "testdata/policy_leaf_none.pem")
  2695  	leaf_oid1 := loadTestCert(t, "testdata/policy_leaf_oid1.pem")
  2696  	leaf_oid2 := loadTestCert(t, "testdata/policy_leaf_oid2.pem")
  2697  	leaf_oid3 := loadTestCert(t, "testdata/policy_leaf_oid3.pem")
  2698  	leaf_oid4 := loadTestCert(t, "testdata/policy_leaf_oid4.pem")
  2699  	leaf_oid5 := loadTestCert(t, "testdata/policy_leaf_oid5.pem")
  2700  	leaf_require := loadTestCert(t, "testdata/policy_leaf_require.pem")
  2701  	leaf_require1 := loadTestCert(t, "testdata/policy_leaf_require1.pem")
  2702  
  2703  	type testCase struct {
  2704  		chain                 []*Certificate
  2705  		policies              []OID
  2706  		requireExplicitPolicy bool
  2707  		inhibitPolicyMapping  bool
  2708  		inhibitAnyPolicy      bool
  2709  		valid                 bool
  2710  	}
  2711  
  2712  	tests := []testCase{
  2713  		// The chain is good for |oid1| and |oid2|, but not |oid3|.
  2714  		{
  2715  			chain:                 []*Certificate{leaf, intermediate, root},
  2716  			requireExplicitPolicy: true,
  2717  			valid:                 true,
  2718  		},
  2719  		{
  2720  			chain:                 []*Certificate{leaf, intermediate, root},
  2721  			policies:              []OID{testOID1},
  2722  			requireExplicitPolicy: true,
  2723  			valid:                 true,
  2724  		},
  2725  		{
  2726  			chain:                 []*Certificate{leaf, intermediate, root},
  2727  			policies:              []OID{testOID2},
  2728  			requireExplicitPolicy: true,
  2729  			valid:                 true,
  2730  		},
  2731  		{
  2732  			chain:                 []*Certificate{leaf, intermediate, root},
  2733  			policies:              []OID{testOID3},
  2734  			requireExplicitPolicy: true,
  2735  			valid:                 false,
  2736  		},
  2737  		{
  2738  			chain:                 []*Certificate{leaf, intermediate, root},
  2739  			policies:              []OID{testOID1, testOID2},
  2740  			requireExplicitPolicy: true,
  2741  			valid:                 true,
  2742  		},
  2743  		{
  2744  			chain:                 []*Certificate{leaf, intermediate, root},
  2745  			policies:              []OID{testOID1, testOID3},
  2746  			requireExplicitPolicy: true,
  2747  			valid:                 true,
  2748  		},
  2749  		// Without |X509_V_FLAG_EXPLICIT_POLICY|, the policy tree is built and
  2750  		// intersected with user-specified policies, but it is not required to result
  2751  		// in any valid policies.
  2752  		{
  2753  			chain:    []*Certificate{leaf, intermediate, root},
  2754  			policies: []OID{testOID1},
  2755  			valid:    true,
  2756  		},
  2757  		{
  2758  			chain:    []*Certificate{leaf, intermediate, root},
  2759  			policies: []OID{testOID3},
  2760  			valid:    true,
  2761  		},
  2762  		// However, a CA with policy constraints can require an explicit policy.
  2763  		{
  2764  			chain:    []*Certificate{leaf, intermediate_require, root},
  2765  			policies: []OID{testOID1},
  2766  			valid:    true,
  2767  		},
  2768  		{
  2769  			chain:    []*Certificate{leaf, intermediate_require, root},
  2770  			policies: []OID{testOID3},
  2771  			valid:    false,
  2772  		},
  2773  		// requireExplicitPolicy applies even if the application does not configure a
  2774  		// user-initial-policy-set. If the validation results in no policies, the
  2775  		// chain is invalid.
  2776  		{
  2777  			chain:                 []*Certificate{leaf_none, intermediate_require, root},
  2778  			requireExplicitPolicy: true,
  2779  			valid:                 false,
  2780  		},
  2781  		// A leaf can also set requireExplicitPolicy.
  2782  		{
  2783  			chain: []*Certificate{leaf_require, intermediate, root},
  2784  			valid: true,
  2785  		},
  2786  		{
  2787  			chain:    []*Certificate{leaf_require, intermediate, root},
  2788  			policies: []OID{testOID1},
  2789  			valid:    true,
  2790  		},
  2791  		{
  2792  			chain:    []*Certificate{leaf_require, intermediate, root},
  2793  			policies: []OID{testOID3},
  2794  			valid:    false,
  2795  		},
  2796  		// requireExplicitPolicy is a count of certificates to skip. If the value is
  2797  		// not zero by the end of the chain, it doesn't count.
  2798  		{
  2799  			chain:    []*Certificate{leaf, intermediate_require1, root},
  2800  			policies: []OID{testOID3},
  2801  			valid:    false,
  2802  		},
  2803  		{
  2804  			chain:    []*Certificate{leaf, intermediate_require2, root},
  2805  			policies: []OID{testOID3},
  2806  			valid:    true,
  2807  		},
  2808  		{
  2809  			chain:    []*Certificate{leaf_require1, intermediate, root},
  2810  			policies: []OID{testOID3},
  2811  			valid:    true,
  2812  		},
  2813  		// If multiple certificates specify the constraint, the more constrained value
  2814  		// wins.
  2815  		{
  2816  			chain:    []*Certificate{leaf_require1, intermediate_require1, root},
  2817  			policies: []OID{testOID3},
  2818  			valid:    false,
  2819  		},
  2820  		{
  2821  			chain:    []*Certificate{leaf_require, intermediate_require2, root},
  2822  			policies: []OID{testOID3},
  2823  			valid:    false,
  2824  		},
  2825  		// An intermediate that requires an explicit policy, but then specifies no
  2826  		// policies should fail verification as a result.
  2827  		{
  2828  			chain:    []*Certificate{leaf, intermediate_require_no_policies, root},
  2829  			policies: []OID{testOID1},
  2830  			valid:    false,
  2831  		},
  2832  		// A constrained intermediate's policy extension has a duplicate policy, which
  2833  		// is invalid.
  2834  		// {
  2835  		// 	chain:    []*Certificate{leaf, intermediate_require_duplicate, root},
  2836  		// 	policies: []OID{testOID1},
  2837  		// 	valid:    false,
  2838  		// },
  2839  		// The leaf asserts anyPolicy, but the intermediate does not. The resulting
  2840  		// valid policies are the intersection.
  2841  		{
  2842  			chain:                 []*Certificate{leaf_any, intermediate, root},
  2843  			policies:              []OID{testOID1},
  2844  			requireExplicitPolicy: true,
  2845  			valid:                 true,
  2846  		},
  2847  		{
  2848  			chain:                 []*Certificate{leaf_any, intermediate, root},
  2849  			policies:              []OID{testOID3},
  2850  			requireExplicitPolicy: true,
  2851  			valid:                 false,
  2852  		},
  2853  		// The intermediate asserts anyPolicy, but the leaf does not. The resulting
  2854  		// valid policies are the intersection.
  2855  		{
  2856  			chain:                 []*Certificate{leaf, intermediate_any, root},
  2857  			policies:              []OID{testOID1},
  2858  			requireExplicitPolicy: true,
  2859  			valid:                 true,
  2860  		},
  2861  		{
  2862  			chain:                 []*Certificate{leaf, intermediate_any, root},
  2863  			policies:              []OID{testOID3},
  2864  			requireExplicitPolicy: true,
  2865  			valid:                 false,
  2866  		},
  2867  		// Both assert anyPolicy. All policies are valid.
  2868  		{
  2869  			chain:                 []*Certificate{leaf_any, intermediate_any, root},
  2870  			policies:              []OID{testOID1},
  2871  			requireExplicitPolicy: true,
  2872  			valid:                 true,
  2873  		},
  2874  		{
  2875  			chain:                 []*Certificate{leaf_any, intermediate_any, root},
  2876  			policies:              []OID{testOID3},
  2877  			requireExplicitPolicy: true,
  2878  			valid:                 true,
  2879  		},
  2880  		// With just a trust anchor, policy checking silently succeeds.
  2881  		{
  2882  			chain:                 []*Certificate{root},
  2883  			policies:              []OID{testOID1},
  2884  			requireExplicitPolicy: true,
  2885  			valid:                 true,
  2886  		},
  2887  		// Although |intermediate_mapped_oid3| contains many mappings, it only accepts
  2888  		// OID3. Nodes should not be created for the other mappings.
  2889  		{
  2890  			chain:                 []*Certificate{leaf_oid1, intermediate_mapped_oid3, root},
  2891  			policies:              []OID{testOID3},
  2892  			requireExplicitPolicy: true,
  2893  			valid:                 true,
  2894  		},
  2895  		{
  2896  			chain:                 []*Certificate{leaf_oid4, intermediate_mapped_oid3, root},
  2897  			policies:              []OID{testOID4},
  2898  			requireExplicitPolicy: true,
  2899  			valid:                 false,
  2900  		},
  2901  		// Policy mapping can be inhibited, either by the caller or a certificate in
  2902  		// the chain, in which case mapped policies are unassertable (apart from some
  2903  		// anyPolicy edge cases).
  2904  		{
  2905  			chain:                 []*Certificate{leaf_oid1, intermediate_mapped_oid3, root},
  2906  			policies:              []OID{testOID3},
  2907  			requireExplicitPolicy: true,
  2908  			inhibitPolicyMapping:  true,
  2909  			valid:                 false,
  2910  		},
  2911  		{
  2912  			chain:                 []*Certificate{leaf_oid1, intermediate_mapped_oid3, root_cross_inhibit_mapping, root2},
  2913  			policies:              []OID{testOID3},
  2914  			requireExplicitPolicy: true,
  2915  			valid:                 false,
  2916  		},
  2917  	}
  2918  
  2919  	for _, useAny := range []bool{false, true} {
  2920  		var intermediate *Certificate
  2921  		if useAny {
  2922  			intermediate = intermediate_mapped_any
  2923  		} else {
  2924  			intermediate = intermediate_mapped
  2925  		}
  2926  		extraTests := []testCase{
  2927  			// OID3 is mapped to {OID1, OID2}, which means OID1 and OID2 (or both) are
  2928  			// acceptable for OID3.
  2929  			{
  2930  				chain:                 []*Certificate{leaf, intermediate, root},
  2931  				policies:              []OID{testOID3},
  2932  				requireExplicitPolicy: true,
  2933  				valid:                 true,
  2934  			},
  2935  			{
  2936  				chain:                 []*Certificate{leaf_oid1, intermediate, root},
  2937  				policies:              []OID{testOID3},
  2938  				requireExplicitPolicy: true,
  2939  				valid:                 true,
  2940  			},
  2941  			{
  2942  				chain:                 []*Certificate{leaf_oid2, intermediate, root},
  2943  				policies:              []OID{testOID3},
  2944  				requireExplicitPolicy: true,
  2945  				valid:                 true,
  2946  			},
  2947  			// If the intermediate's policies were anyPolicy, OID3 at the leaf, despite
  2948  			// being mapped, is still acceptable as OID3 at the root. Despite the OID3
  2949  			// having expected_policy_set = {OID1, OID2}, it can match the anyPolicy
  2950  			// node instead.
  2951  			//
  2952  			// If the intermediate's policies listed OIDs explicitly, OID3 at the leaf
  2953  			// is not acceptable as OID3 at the root. OID3 has expected_polciy_set =
  2954  			// {OID1, OID2} and no other node allows OID3.
  2955  			{
  2956  				chain:                 []*Certificate{leaf_oid3, intermediate, root},
  2957  				policies:              []OID{testOID3},
  2958  				requireExplicitPolicy: true,
  2959  				valid:                 useAny,
  2960  			},
  2961  			// If the intermediate's policies were anyPolicy, OID1 at the leaf is no
  2962  			// longer acceptable as OID1 at the root because policies only match
  2963  			// anyPolicy when they match no other policy.
  2964  			//
  2965  			// If the intermediate's policies listed OIDs explicitly, OID1 at the leaf
  2966  			// is acceptable as OID1 at the root because it will match both OID1 and
  2967  			// OID3 (mapped) policies.
  2968  			{
  2969  				chain:                 []*Certificate{leaf_oid1, intermediate, root},
  2970  				policies:              []OID{testOID1},
  2971  				requireExplicitPolicy: true,
  2972  				valid:                 !useAny,
  2973  			},
  2974  			// All pairs of OID4 and OID5 are mapped together, so either can stand for
  2975  			// the other.
  2976  			{
  2977  				chain:                 []*Certificate{leaf_oid4, intermediate, root},
  2978  				policies:              []OID{testOID4},
  2979  				requireExplicitPolicy: true,
  2980  				valid:                 true,
  2981  			},
  2982  			{
  2983  				chain:                 []*Certificate{leaf_oid4, intermediate, root},
  2984  				policies:              []OID{testOID5},
  2985  				requireExplicitPolicy: true,
  2986  				valid:                 true,
  2987  			},
  2988  			{
  2989  				chain:                 []*Certificate{leaf_oid5, intermediate, root},
  2990  				policies:              []OID{testOID4},
  2991  				requireExplicitPolicy: true,
  2992  				valid:                 true,
  2993  			},
  2994  			{
  2995  				chain:                 []*Certificate{leaf_oid5, intermediate, root},
  2996  				policies:              []OID{testOID5},
  2997  				requireExplicitPolicy: true,
  2998  				valid:                 true,
  2999  			},
  3000  			{
  3001  				chain:                 []*Certificate{leaf_oid4, intermediate, root},
  3002  				policies:              []OID{testOID4, testOID5},
  3003  				requireExplicitPolicy: true,
  3004  				valid:                 true,
  3005  			},
  3006  		}
  3007  		tests = append(tests, extraTests...)
  3008  	}
  3009  
  3010  	for i, tc := range tests {
  3011  		t.Run(fmt.Sprint(i), func(t *testing.T) {
  3012  			valid := policiesValid(tc.chain, VerifyOptions{
  3013  				CertificatePolicies:   tc.policies,
  3014  				requireExplicitPolicy: tc.requireExplicitPolicy,
  3015  				inhibitPolicyMapping:  tc.inhibitPolicyMapping,
  3016  				inhibitAnyPolicy:      tc.inhibitAnyPolicy,
  3017  			})
  3018  			if valid != tc.valid {
  3019  				t.Errorf("policiesValid: got %t, want %t", valid, tc.valid)
  3020  			}
  3021  		})
  3022  	}
  3023  }
  3024  
  3025  func TestInvalidPolicyWithAnyKeyUsage(t *testing.T) {
  3026  	loadTestCert := func(t *testing.T, path string) *Certificate {
  3027  		b, err := os.ReadFile(path)
  3028  		if err != nil {
  3029  			t.Fatal(err)
  3030  		}
  3031  		p, _ := pem.Decode(b)
  3032  		c, err := ParseCertificate(p.Bytes)
  3033  		if err != nil {
  3034  			t.Fatal(err)
  3035  		}
  3036  		return c
  3037  	}
  3038  
  3039  	testOID3 := mustNewOIDFromInts([]uint64{1, 2, 840, 113554, 4, 1, 72585, 2, 3})
  3040  	root, intermediate, leaf := loadTestCert(t, "testdata/policy_root.pem"), loadTestCert(t, "testdata/policy_intermediate_require.pem"), loadTestCert(t, "testdata/policy_leaf.pem")
  3041  
  3042  	expectedErr := "x509: no valid chains built: 1 candidate chains with invalid policies"
  3043  
  3044  	roots, intermediates := NewCertPool(), NewCertPool()
  3045  	roots.AddCert(root)
  3046  	intermediates.AddCert(intermediate)
  3047  
  3048  	_, err := leaf.Verify(VerifyOptions{
  3049  		Roots:               roots,
  3050  		Intermediates:       intermediates,
  3051  		KeyUsages:           []ExtKeyUsage{ExtKeyUsageAny},
  3052  		CertificatePolicies: []OID{testOID3},
  3053  	})
  3054  	if err == nil {
  3055  		t.Fatal("unexpected success, invalid policy shouldn't be bypassed by passing VerifyOptions.KeyUsages with ExtKeyUsageAny")
  3056  	} else if err.Error() != expectedErr {
  3057  		t.Fatalf("unexpected error, got %q, want %q", err, expectedErr)
  3058  	}
  3059  }
  3060  
  3061  func TestCertificateChainSignedByECDSA(t *testing.T) {
  3062  	caKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  3063  	if err != nil {
  3064  		t.Fatal(err)
  3065  	}
  3066  	root := &Certificate{
  3067  		SerialNumber:          big.NewInt(1),
  3068  		Subject:               pkix.Name{CommonName: "X"},
  3069  		NotBefore:             time.Now().Add(-time.Hour),
  3070  		NotAfter:              time.Now().Add(365 * 24 * time.Hour),
  3071  		IsCA:                  true,
  3072  		KeyUsage:              KeyUsageCertSign | KeyUsageCRLSign,
  3073  		BasicConstraintsValid: true,
  3074  	}
  3075  	caDER, err := CreateCertificate(rand.Reader, root, root, &caKey.PublicKey, caKey)
  3076  	if err != nil {
  3077  		t.Fatal(err)
  3078  	}
  3079  	root, err = ParseCertificate(caDER)
  3080  	if err != nil {
  3081  		t.Fatal(err)
  3082  	}
  3083  
  3084  	leafKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
  3085  	leaf := &Certificate{
  3086  		SerialNumber:          big.NewInt(42),
  3087  		Subject:               pkix.Name{CommonName: "leaf"},
  3088  		NotBefore:             time.Now().Add(-10 * time.Minute),
  3089  		NotAfter:              time.Now().Add(24 * time.Hour),
  3090  		KeyUsage:              KeyUsageDigitalSignature,
  3091  		ExtKeyUsage:           []ExtKeyUsage{ExtKeyUsageServerAuth},
  3092  		BasicConstraintsValid: true,
  3093  	}
  3094  	leafDER, err := CreateCertificate(rand.Reader, leaf, root, &leafKey.PublicKey, caKey)
  3095  	if err != nil {
  3096  		t.Fatal(err)
  3097  	}
  3098  	leaf, err = ParseCertificate(leafDER)
  3099  	if err != nil {
  3100  		t.Fatal(err)
  3101  	}
  3102  
  3103  	inter, err := ParseCertificate(dsaSelfSignedCNX(t))
  3104  	if err != nil {
  3105  		t.Fatal(err)
  3106  	}
  3107  
  3108  	inters := NewCertPool()
  3109  	inters.AddCert(root)
  3110  	inters.AddCert(inter)
  3111  
  3112  	wantErr := "certificate signed by unknown authority"
  3113  	_, err = leaf.Verify(VerifyOptions{Intermediates: inters, Roots: NewCertPool()})
  3114  	if !strings.Contains(err.Error(), wantErr) {
  3115  		t.Errorf("got %v, want %q", err, wantErr)
  3116  	}
  3117  }
  3118  
  3119  // dsaSelfSignedCNX produces DER-encoded
  3120  // certificate with the properties:
  3121  //
  3122  //	Subject=Issuer=CN=X
  3123  //	DSA SPKI
  3124  //	Matching inner/outer signature OIDs
  3125  //	Dummy ECDSA signature
  3126  func dsaSelfSignedCNX(t *testing.T) []byte {
  3127  	t.Helper()
  3128  	var params dsa.Parameters
  3129  	if err := dsa.GenerateParameters(&params, rand.Reader, dsa.L1024N160); err != nil {
  3130  		t.Fatal(err)
  3131  	}
  3132  
  3133  	var dsaPriv dsa.PrivateKey
  3134  	dsaPriv.Parameters = params
  3135  	if err := dsa.GenerateKey(&dsaPriv, rand.Reader); err != nil {
  3136  		t.Fatal(err)
  3137  	}
  3138  	dsaPub := &dsaPriv.PublicKey
  3139  
  3140  	type dsaParams struct{ P, Q, G *big.Int }
  3141  	paramDER, err := asn1.Marshal(dsaParams{dsaPub.P, dsaPub.Q, dsaPub.G})
  3142  	if err != nil {
  3143  		t.Fatal(err)
  3144  	}
  3145  	yDER, err := asn1.Marshal(dsaPub.Y)
  3146  	if err != nil {
  3147  		t.Fatal(err)
  3148  	}
  3149  
  3150  	spki := publicKeyInfo{
  3151  		Algorithm: pkix.AlgorithmIdentifier{
  3152  			Algorithm:  oidPublicKeyDSA,
  3153  			Parameters: asn1.RawValue{FullBytes: paramDER},
  3154  		},
  3155  		PublicKey: asn1.BitString{Bytes: yDER, BitLength: 8 * len(yDER)},
  3156  	}
  3157  
  3158  	rdn := pkix.Name{CommonName: "X"}.ToRDNSequence()
  3159  	b, err := asn1.Marshal(rdn)
  3160  	if err != nil {
  3161  		t.Fatal(err)
  3162  	}
  3163  	rawName := asn1.RawValue{FullBytes: b}
  3164  
  3165  	algoIdent := pkix.AlgorithmIdentifier{Algorithm: oidSignatureDSAWithSHA256}
  3166  	tbs := tbsCertificate{
  3167  		Version:            0,
  3168  		SerialNumber:       big.NewInt(1002),
  3169  		SignatureAlgorithm: algoIdent,
  3170  		Issuer:             rawName,
  3171  		Validity:           validity{NotBefore: time.Now().Add(-time.Hour), NotAfter: time.Now().Add(24 * time.Hour)},
  3172  		Subject:            rawName,
  3173  		PublicKey:          spki,
  3174  	}
  3175  	c := certificate{
  3176  		TBSCertificate:     tbs,
  3177  		SignatureAlgorithm: algoIdent,
  3178  		SignatureValue:     asn1.BitString{Bytes: []byte{0}, BitLength: 8},
  3179  	}
  3180  	dsaDER, err := asn1.Marshal(c)
  3181  	if err != nil {
  3182  		t.Fatal(err)
  3183  	}
  3184  	return dsaDER
  3185  }
  3186  

View as plain text