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

View as plain text