Source file src/crypto/x509/verify_test.go

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

View as plain text