github.com/hashicorp/vault/sdk@v0.11.0/helper/certutil/certutil_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package certutil
     5  
     6  import (
     7  	"bytes"
     8  	"crypto"
     9  	"crypto/ecdsa"
    10  	"crypto/ed25519"
    11  	"crypto/elliptic"
    12  	"crypto/rand"
    13  	"crypto/rsa"
    14  	"crypto/x509"
    15  	"crypto/x509/pkix"
    16  	"encoding/asn1"
    17  	"encoding/json"
    18  	"encoding/pem"
    19  	"fmt"
    20  	"math/big"
    21  	mathrand "math/rand"
    22  	"reflect"
    23  	"strings"
    24  	"sync"
    25  	"testing"
    26  	"time"
    27  
    28  	"github.com/fatih/structs"
    29  )
    30  
    31  // Tests converting back and forth between a CertBundle and a ParsedCertBundle.
    32  //
    33  // Also tests the GetSubjKeyID, GetHexFormatted, ParseHexFormatted and
    34  // ParsedCertBundle.getSigner functions.
    35  func TestCertBundleConversion(t *testing.T) {
    36  	cbuts := []*CertBundle{
    37  		refreshRSACertBundle(),
    38  		refreshRSACertBundleWithChain(),
    39  		refreshRSA8CertBundle(),
    40  		refreshRSA8CertBundleWithChain(),
    41  		refreshECCertBundle(),
    42  		refreshECCertBundleWithChain(),
    43  		refreshEC8CertBundle(),
    44  		refreshEC8CertBundleWithChain(),
    45  		refreshEd255198CertBundle(),
    46  		refreshEd255198CertBundleWithChain(),
    47  	}
    48  
    49  	for i, cbut := range cbuts {
    50  		pcbut, err := cbut.ToParsedCertBundle()
    51  		if err != nil {
    52  			t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i)
    53  			t.Errorf("Error converting to parsed cert bundle: %s", err)
    54  			continue
    55  		}
    56  
    57  		err = compareCertBundleToParsedCertBundle(cbut, pcbut)
    58  		if err != nil {
    59  			t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i)
    60  			t.Errorf(err.Error())
    61  		}
    62  
    63  		cbut, err := pcbut.ToCertBundle()
    64  		if err != nil {
    65  			t.Fatalf("Error converting to cert bundle: %s", err)
    66  		}
    67  
    68  		err = compareCertBundleToParsedCertBundle(cbut, pcbut)
    69  		if err != nil {
    70  			t.Fatalf(err.Error())
    71  		}
    72  	}
    73  }
    74  
    75  func BenchmarkCertBundleParsing(b *testing.B) {
    76  	for i := 0; i < b.N; i++ {
    77  		cbuts := []*CertBundle{
    78  			refreshRSACertBundle(),
    79  			refreshRSACertBundleWithChain(),
    80  			refreshRSA8CertBundle(),
    81  			refreshRSA8CertBundleWithChain(),
    82  			refreshECCertBundle(),
    83  			refreshECCertBundleWithChain(),
    84  			refreshEC8CertBundle(),
    85  			refreshEC8CertBundleWithChain(),
    86  			refreshEd255198CertBundle(),
    87  			refreshEd255198CertBundleWithChain(),
    88  		}
    89  
    90  		for i, cbut := range cbuts {
    91  			pcbut, err := cbut.ToParsedCertBundle()
    92  			if err != nil {
    93  				b.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i)
    94  				b.Errorf("Error converting to parsed cert bundle: %s", err)
    95  				continue
    96  			}
    97  
    98  			cbut, err = pcbut.ToCertBundle()
    99  			if err != nil {
   100  				b.Fatalf("Error converting to cert bundle: %s", err)
   101  			}
   102  		}
   103  	}
   104  }
   105  
   106  func TestCertBundleParsing(t *testing.T) {
   107  	cbuts := []*CertBundle{
   108  		refreshRSACertBundle(),
   109  		refreshRSACertBundleWithChain(),
   110  		refreshRSA8CertBundle(),
   111  		refreshRSA8CertBundleWithChain(),
   112  		refreshECCertBundle(),
   113  		refreshECCertBundleWithChain(),
   114  		refreshEC8CertBundle(),
   115  		refreshEC8CertBundleWithChain(),
   116  		refreshEd255198CertBundle(),
   117  		refreshEd255198CertBundleWithChain(),
   118  	}
   119  
   120  	for i, cbut := range cbuts {
   121  		jsonString, err := json.Marshal(cbut)
   122  		if err != nil {
   123  			t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i)
   124  			t.Fatalf("Error marshaling testing certbundle to JSON: %s", err)
   125  		}
   126  		pcbut, err := ParsePKIJSON(jsonString)
   127  		if err != nil {
   128  			t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i)
   129  			t.Fatalf("Error during JSON bundle handling: %s", err)
   130  		}
   131  		err = compareCertBundleToParsedCertBundle(cbut, pcbut)
   132  		if err != nil {
   133  			t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i)
   134  			t.Fatalf(err.Error())
   135  		}
   136  
   137  		dataMap := structs.New(cbut).Map()
   138  		pcbut, err = ParsePKIMap(dataMap)
   139  		if err != nil {
   140  			t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i)
   141  			t.Fatalf("Error during JSON bundle handling: %s", err)
   142  		}
   143  		err = compareCertBundleToParsedCertBundle(cbut, pcbut)
   144  		if err != nil {
   145  			t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i)
   146  			t.Fatalf(err.Error())
   147  		}
   148  
   149  		pcbut, err = ParsePEMBundle(cbut.ToPEMBundle())
   150  		if err != nil {
   151  			t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i)
   152  			t.Fatalf("Error during JSON bundle handling: %s", err)
   153  		}
   154  		err = compareCertBundleToParsedCertBundle(cbut, pcbut)
   155  		if err != nil {
   156  			t.Logf("Error occurred with bundle %d in test array (index %d).\n", i+1, i)
   157  			t.Fatalf(err.Error())
   158  		}
   159  	}
   160  }
   161  
   162  func compareCertBundleToParsedCertBundle(cbut *CertBundle, pcbut *ParsedCertBundle) error {
   163  	if cbut == nil {
   164  		return fmt.Errorf("got nil bundle")
   165  	}
   166  	if pcbut == nil {
   167  		return fmt.Errorf("got nil parsed bundle")
   168  	}
   169  
   170  	switch {
   171  	case pcbut.Certificate == nil:
   172  		return fmt.Errorf("parsed bundle has nil certificate")
   173  	case pcbut.PrivateKey == nil:
   174  		return fmt.Errorf("parsed bundle has nil private key")
   175  	}
   176  
   177  	switch cbut.PrivateKey {
   178  	case privRSAKeyPem:
   179  		if pcbut.PrivateKeyType != RSAPrivateKey {
   180  			return fmt.Errorf("parsed bundle has wrong private key type: %v, should be 'rsa' (%v)", pcbut.PrivateKeyType, RSAPrivateKey)
   181  		}
   182  	case privRSA8KeyPem:
   183  		if pcbut.PrivateKeyType != RSAPrivateKey {
   184  			return fmt.Errorf("parsed bundle has wrong pkcs8 private key type: %v, should be 'rsa' (%v)", pcbut.PrivateKeyType, RSAPrivateKey)
   185  		}
   186  	case privECKeyPem:
   187  		if pcbut.PrivateKeyType != ECPrivateKey {
   188  			return fmt.Errorf("parsed bundle has wrong private key type: %v, should be 'ec' (%v)", pcbut.PrivateKeyType, ECPrivateKey)
   189  		}
   190  	case privEC8KeyPem:
   191  		if pcbut.PrivateKeyType != ECPrivateKey {
   192  			return fmt.Errorf("parsed bundle has wrong pkcs8 private key type: %v, should be 'ec' (%v)", pcbut.PrivateKeyType, ECPrivateKey)
   193  		}
   194  	case privEd255198KeyPem:
   195  		if pcbut.PrivateKeyType != Ed25519PrivateKey {
   196  			return fmt.Errorf("parsed bundle has wrong pkcs8 private key type: %v, should be 'ed25519' (%v)", pcbut.PrivateKeyType, ECPrivateKey)
   197  		}
   198  	default:
   199  		return fmt.Errorf("parsed bundle has unknown private key type")
   200  	}
   201  
   202  	subjKeyID, err := GetSubjKeyID(pcbut.PrivateKey)
   203  	if err != nil {
   204  		return fmt.Errorf("error when getting subject key id: %s", err)
   205  	}
   206  	if bytes.Compare(subjKeyID, pcbut.Certificate.SubjectKeyId) != 0 {
   207  		return fmt.Errorf("parsed bundle private key does not match subject key id\nGot\n%#v\nExpected\n%#v\nCert\n%#v", subjKeyID, pcbut.Certificate.SubjectKeyId, *pcbut.Certificate)
   208  	}
   209  
   210  	switch {
   211  	case len(pcbut.CAChain) > 0 && len(cbut.CAChain) == 0:
   212  		return fmt.Errorf("parsed bundle ca chain has certs when cert bundle does not")
   213  	case len(pcbut.CAChain) == 0 && len(cbut.CAChain) > 0:
   214  		return fmt.Errorf("cert bundle ca chain has certs when parsed cert bundle does not")
   215  	}
   216  
   217  	cb, err := pcbut.ToCertBundle()
   218  	if err != nil {
   219  		return fmt.Errorf("thrown error during parsed bundle conversion: %s\n\nInput was: %#v", err, *pcbut)
   220  	}
   221  
   222  	switch {
   223  	case len(cb.Certificate) == 0:
   224  		return fmt.Errorf("bundle has nil certificate")
   225  	case len(cb.PrivateKey) == 0:
   226  		return fmt.Errorf("bundle has nil private key")
   227  	case len(cb.CAChain[0]) == 0:
   228  		return fmt.Errorf("bundle has nil issuing CA")
   229  	}
   230  
   231  	switch pcbut.PrivateKeyType {
   232  	case RSAPrivateKey:
   233  		if cb.PrivateKey != privRSAKeyPem && cb.PrivateKey != privRSA8KeyPem {
   234  			return fmt.Errorf("bundle private key does not match")
   235  		}
   236  	case ECPrivateKey:
   237  		if cb.PrivateKey != privECKeyPem && cb.PrivateKey != privEC8KeyPem {
   238  			return fmt.Errorf("bundle private key does not match")
   239  		}
   240  	case Ed25519PrivateKey:
   241  		if cb.PrivateKey != privEd255198KeyPem {
   242  			return fmt.Errorf("bundle private key does not match")
   243  		}
   244  	default:
   245  		return fmt.Errorf("certBundle has unknown private key type")
   246  	}
   247  
   248  	if cb.SerialNumber != GetHexFormatted(pcbut.Certificate.SerialNumber.Bytes(), ":") {
   249  		return fmt.Errorf("bundle serial number does not match")
   250  	}
   251  
   252  	if !bytes.Equal(pcbut.Certificate.SerialNumber.Bytes(), ParseHexFormatted(cb.SerialNumber, ":")) {
   253  		return fmt.Errorf("failed re-parsing hex formatted number %s", cb.SerialNumber)
   254  	}
   255  
   256  	switch {
   257  	case len(pcbut.CAChain) > 0 && len(cb.CAChain) == 0:
   258  		return fmt.Errorf("parsed bundle ca chain has certs when cert bundle does not")
   259  	case len(pcbut.CAChain) == 0 && len(cb.CAChain) > 0:
   260  		return fmt.Errorf("cert bundle ca chain has certs when parsed cert bundle does not")
   261  	case !reflect.DeepEqual(cbut.CAChain, cb.CAChain):
   262  		return fmt.Errorf("cert bundle ca chain does not match: %#v\n\n%#v", cbut.CAChain, cb.CAChain)
   263  	}
   264  
   265  	return nil
   266  }
   267  
   268  func TestCSRBundleConversion(t *testing.T) {
   269  	csrbuts := []*CSRBundle{
   270  		refreshRSACSRBundle(),
   271  		refreshECCSRBundle(),
   272  		refreshEd25519CSRBundle(),
   273  	}
   274  
   275  	for _, csrbut := range csrbuts {
   276  		pcsrbut, err := csrbut.ToParsedCSRBundle()
   277  		if err != nil {
   278  			t.Fatalf("Error converting to parsed CSR bundle: %v", err)
   279  		}
   280  
   281  		err = compareCSRBundleToParsedCSRBundle(csrbut, pcsrbut)
   282  		if err != nil {
   283  			t.Fatalf(err.Error())
   284  		}
   285  
   286  		csrbut, err = pcsrbut.ToCSRBundle()
   287  		if err != nil {
   288  			t.Fatalf("Error converting to CSR bundle: %v", err)
   289  		}
   290  
   291  		err = compareCSRBundleToParsedCSRBundle(csrbut, pcsrbut)
   292  		if err != nil {
   293  			t.Fatalf(err.Error())
   294  		}
   295  	}
   296  }
   297  
   298  func compareCSRBundleToParsedCSRBundle(csrbut *CSRBundle, pcsrbut *ParsedCSRBundle) error {
   299  	if csrbut == nil {
   300  		return fmt.Errorf("got nil bundle")
   301  	}
   302  	if pcsrbut == nil {
   303  		return fmt.Errorf("got nil parsed bundle")
   304  	}
   305  
   306  	switch {
   307  	case pcsrbut.CSR == nil:
   308  		return fmt.Errorf("parsed bundle has nil csr")
   309  	case pcsrbut.PrivateKey == nil:
   310  		return fmt.Errorf("parsed bundle has nil private key")
   311  	}
   312  
   313  	switch csrbut.PrivateKey {
   314  	case privRSAKeyPem:
   315  		if pcsrbut.PrivateKeyType != RSAPrivateKey {
   316  			return fmt.Errorf("parsed bundle has wrong private key type")
   317  		}
   318  	case privECKeyPem:
   319  		if pcsrbut.PrivateKeyType != ECPrivateKey {
   320  			return fmt.Errorf("parsed bundle has wrong private key type")
   321  		}
   322  	case privEd255198KeyPem:
   323  		if pcsrbut.PrivateKeyType != Ed25519PrivateKey {
   324  			return fmt.Errorf("parsed bundle has wrong private key type")
   325  		}
   326  	default:
   327  		return fmt.Errorf("parsed bundle has unknown private key type")
   328  	}
   329  
   330  	csrb, err := pcsrbut.ToCSRBundle()
   331  	if err != nil {
   332  		return fmt.Errorf("Thrown error during parsed bundle conversion: %s\n\nInput was: %#v", err, *pcsrbut)
   333  	}
   334  
   335  	switch {
   336  	case len(csrb.CSR) == 0:
   337  		return fmt.Errorf("bundle has nil certificate")
   338  	case len(csrb.PrivateKey) == 0:
   339  		return fmt.Errorf("bundle has nil private key")
   340  	}
   341  
   342  	switch csrb.PrivateKeyType {
   343  	case "rsa":
   344  		if pcsrbut.PrivateKeyType != RSAPrivateKey {
   345  			return fmt.Errorf("bundle has wrong private key type")
   346  		}
   347  		if csrb.PrivateKey != privRSAKeyPem {
   348  			return fmt.Errorf("bundle rsa private key does not match\nGot\n%#v\nExpected\n%#v", csrb.PrivateKey, privRSAKeyPem)
   349  		}
   350  	case "ec":
   351  		if pcsrbut.PrivateKeyType != ECPrivateKey {
   352  			return fmt.Errorf("bundle has wrong private key type")
   353  		}
   354  		if csrb.PrivateKey != privECKeyPem {
   355  			return fmt.Errorf("bundle ec private key does not match")
   356  		}
   357  	case "ed25519":
   358  		if pcsrbut.PrivateKeyType != Ed25519PrivateKey {
   359  			return fmt.Errorf("bundle has wrong private key type")
   360  		}
   361  		if csrb.PrivateKey != privEd255198KeyPem {
   362  			return fmt.Errorf("bundle ed25519 private key does not match")
   363  		}
   364  	default:
   365  		return fmt.Errorf("bundle has unknown private key type")
   366  	}
   367  
   368  	return nil
   369  }
   370  
   371  func TestTLSConfig(t *testing.T) {
   372  	cbut := refreshRSACertBundle()
   373  
   374  	pcbut, err := cbut.ToParsedCertBundle()
   375  	if err != nil {
   376  		t.Fatalf("Error getting parsed cert bundle: %s", err)
   377  	}
   378  
   379  	usages := []TLSUsage{
   380  		TLSUnknown,
   381  		TLSClient,
   382  		TLSServer,
   383  		TLSClient | TLSServer,
   384  	}
   385  
   386  	for _, usage := range usages {
   387  		tlsConfig, err := pcbut.GetTLSConfig(usage)
   388  		if err != nil {
   389  			t.Fatalf("Error getting tls config: %s", err)
   390  		}
   391  		if tlsConfig == nil {
   392  			t.Fatalf("Got nil tls.Config")
   393  		}
   394  
   395  		if len(tlsConfig.Certificates) != 1 {
   396  			t.Fatalf("Unexpected length in config.Certificates")
   397  		}
   398  
   399  		// Length should be 2, since we passed in a CA
   400  		if len(tlsConfig.Certificates[0].Certificate) != 2 {
   401  			t.Fatalf("Did not find both certificates in config.Certificates.Certificate")
   402  		}
   403  
   404  		if tlsConfig.Certificates[0].Leaf != pcbut.Certificate {
   405  			t.Fatalf("Leaf certificate does not match parsed bundle's certificate")
   406  		}
   407  
   408  		if tlsConfig.Certificates[0].PrivateKey != pcbut.PrivateKey {
   409  			t.Fatalf("Config's private key does not match parsed bundle's private key")
   410  		}
   411  
   412  		switch usage {
   413  		case TLSServer | TLSClient:
   414  			if len(tlsConfig.ClientCAs.Subjects()) != 1 || bytes.Compare(tlsConfig.ClientCAs.Subjects()[0], pcbut.CAChain[0].Certificate.RawSubject) != 0 {
   415  				t.Fatalf("CA certificate not in client cert pool as expected")
   416  			}
   417  			if len(tlsConfig.RootCAs.Subjects()) != 1 || bytes.Compare(tlsConfig.RootCAs.Subjects()[0], pcbut.CAChain[0].Certificate.RawSubject) != 0 {
   418  				t.Fatalf("CA certificate not in root cert pool as expected")
   419  			}
   420  		case TLSServer:
   421  			if len(tlsConfig.ClientCAs.Subjects()) != 1 || bytes.Compare(tlsConfig.ClientCAs.Subjects()[0], pcbut.CAChain[0].Certificate.RawSubject) != 0 {
   422  				t.Fatalf("CA certificate not in client cert pool as expected")
   423  			}
   424  			if tlsConfig.RootCAs != nil {
   425  				t.Fatalf("Found root pools in config object when not expected")
   426  			}
   427  		case TLSClient:
   428  			if len(tlsConfig.RootCAs.Subjects()) != 1 || bytes.Compare(tlsConfig.RootCAs.Subjects()[0], pcbut.CAChain[0].Certificate.RawSubject) != 0 {
   429  				t.Fatalf("CA certificate not in root cert pool as expected")
   430  			}
   431  			if tlsConfig.ClientCAs != nil {
   432  				t.Fatalf("Found root pools in config object when not expected")
   433  			}
   434  		default:
   435  			if tlsConfig.RootCAs != nil || tlsConfig.ClientCAs != nil {
   436  				t.Fatalf("Found root pools in config object when not expected")
   437  			}
   438  		}
   439  	}
   440  }
   441  
   442  func TestNewCertPool(t *testing.T) {
   443  	caExample := `-----BEGIN CERTIFICATE-----
   444  MIIC5zCCAc+gAwIBAgIBATANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwptaW5p
   445  a3ViZUNBMB4XDTE5MTIxMDIzMDUxOVoXDTI5MTIwODIzMDUxOVowFTETMBEGA1UE
   446  AxMKbWluaWt1YmVDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANFi
   447  /RIdMHd865X6JygTb9riX01DA3QnR+RoXDXNnj8D3LziLG2n8ItXMJvWbU3sxxyy
   448  nX9HxJ0SIeexj1cYzdQBtJDjO1/PeuKc4CZ7zCukCAtHz8mC7BDPOU7F7pggpcQ0
   449  /t/pa2m22hmCu8aDF9WlUYHtJpYATnI/A5vz/VFLR9daxmkl59Qo3oHITj7vAzSx
   450  /75r9cibpQyJ+FhiHOZHQWYY2JYw2g4v5hm5hg5SFM9yFcZ75ISI9ebyFFIl9iBY
   451  zAk9jqv1mXvLr0Q39AVwMTamvGuap1oocjM9NIhQvaFL/DNqF1ouDQjCf5u2imLc
   452  TraO1/2KO8fqwOZCOrMCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgKkMB0GA1UdJQQW
   453  MBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
   454  DQEBCwUAA4IBAQBtVZCwCPqUUUpIClAlE9nc2fo2bTs9gsjXRmqdQ5oaSomSLE93
   455  aJWYFuAhxPXtlApbLYZfW2m1sM3mTVQN60y0uE4e1jdSN1ErYQ9slJdYDAMaEmOh
   456  iSexj+Nd1scUiMHV9lf3ps5J8sYeCpwZX3sPmw7lqZojTS12pANBDcigsaj5RRyN
   457  9GyP3WkSQUsTpWlDb9Fd+KNdkCVw7nClIpBPA2KW4BQKw/rNSvOFD61mbzc89lo0
   458  Q9IFGQFFF8jO18lbyWqnRBGXcS4/G7jQ3S7C121d14YLUeAYOM7pJykI1g4CLx9y
   459  vitin0L6nprauWkKO38XgM4T75qKZpqtiOcT
   460  -----END CERTIFICATE-----
   461  `
   462  	if _, err := NewCertPool(bytes.NewReader([]byte(caExample))); err != nil {
   463  		t.Fatal(err)
   464  	}
   465  }
   466  
   467  func TestGetPublicKeySize(t *testing.T) {
   468  	rsa, err := rsa.GenerateKey(rand.Reader, 3072)
   469  	if err != nil {
   470  		t.Fatal(err)
   471  	}
   472  	if GetPublicKeySize(&rsa.PublicKey) != 3072 {
   473  		t.Fatal("unexpected rsa key size")
   474  	}
   475  	ecdsa, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
   476  	if err != nil {
   477  		t.Fatal(err)
   478  	}
   479  	if GetPublicKeySize(&ecdsa.PublicKey) != 384 {
   480  		t.Fatal("unexpected ecdsa key size")
   481  	}
   482  	ed25519, _, err := ed25519.GenerateKey(rand.Reader)
   483  	if err != nil {
   484  		t.Fatal(err)
   485  	}
   486  	if GetPublicKeySize(ed25519) != 256 {
   487  		t.Fatal("unexpected ed25519 key size")
   488  	}
   489  	// Skipping DSA as too slow
   490  }
   491  
   492  func refreshRSA8CertBundle() *CertBundle {
   493  	initTest.Do(setCerts)
   494  	return &CertBundle{
   495  		Certificate: certRSAPem,
   496  		PrivateKey:  privRSA8KeyPem,
   497  		CAChain:     []string{issuingCaChainPem[0]},
   498  	}
   499  }
   500  
   501  func refreshRSA8CertBundleWithChain() *CertBundle {
   502  	initTest.Do(setCerts)
   503  	ret := refreshRSA8CertBundle()
   504  	ret.CAChain = issuingCaChainPem
   505  	return ret
   506  }
   507  
   508  func refreshRSACertBundle() *CertBundle {
   509  	initTest.Do(setCerts)
   510  	return &CertBundle{
   511  		Certificate: certRSAPem,
   512  		CAChain:     []string{issuingCaChainPem[0]},
   513  		PrivateKey:  privRSAKeyPem,
   514  	}
   515  }
   516  
   517  func refreshRSACertBundleWithChain() *CertBundle {
   518  	initTest.Do(setCerts)
   519  	ret := refreshRSACertBundle()
   520  	ret.CAChain = issuingCaChainPem
   521  	return ret
   522  }
   523  
   524  func refreshECCertBundle() *CertBundle {
   525  	initTest.Do(setCerts)
   526  	return &CertBundle{
   527  		Certificate: certECPem,
   528  		CAChain:     []string{issuingCaChainPem[0]},
   529  		PrivateKey:  privECKeyPem,
   530  	}
   531  }
   532  
   533  func refreshECCertBundleWithChain() *CertBundle {
   534  	initTest.Do(setCerts)
   535  	ret := refreshECCertBundle()
   536  	ret.CAChain = issuingCaChainPem
   537  	return ret
   538  }
   539  
   540  func refreshEd255198CertBundle() *CertBundle {
   541  	initTest.Do(setCerts)
   542  	return &CertBundle{
   543  		Certificate: certEd25519Pem,
   544  		PrivateKey:  privEd255198KeyPem,
   545  		CAChain:     []string{issuingCaChainPem[0]},
   546  	}
   547  }
   548  
   549  func refreshEd255198CertBundleWithChain() *CertBundle {
   550  	initTest.Do(setCerts)
   551  	ret := refreshEd255198CertBundle()
   552  	ret.CAChain = issuingCaChainPem
   553  	return ret
   554  }
   555  
   556  func refreshEd25519CSRBundle() *CSRBundle {
   557  	initTest.Do(setCerts)
   558  	return &CSRBundle{
   559  		CSR:        csrEd25519Pem,
   560  		PrivateKey: privEd255198KeyPem,
   561  	}
   562  }
   563  
   564  func refreshRSACSRBundle() *CSRBundle {
   565  	initTest.Do(setCerts)
   566  	return &CSRBundle{
   567  		CSR:        csrRSAPem,
   568  		PrivateKey: privRSAKeyPem,
   569  	}
   570  }
   571  
   572  func refreshECCSRBundle() *CSRBundle {
   573  	initTest.Do(setCerts)
   574  	return &CSRBundle{
   575  		CSR:        csrECPem,
   576  		PrivateKey: privECKeyPem,
   577  	}
   578  }
   579  
   580  func refreshEC8CertBundle() *CertBundle {
   581  	initTest.Do(setCerts)
   582  	return &CertBundle{
   583  		Certificate: certECPem,
   584  		PrivateKey:  privEC8KeyPem,
   585  		CAChain:     []string{issuingCaChainPem[0]},
   586  	}
   587  }
   588  
   589  func refreshEC8CertBundleWithChain() *CertBundle {
   590  	initTest.Do(setCerts)
   591  	ret := refreshEC8CertBundle()
   592  	ret.CAChain = issuingCaChainPem
   593  	return ret
   594  }
   595  
   596  func setCerts() {
   597  	caKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   598  	if err != nil {
   599  		panic(err)
   600  	}
   601  	subjKeyID, err := GetSubjKeyID(caKey)
   602  	if err != nil {
   603  		panic(err)
   604  	}
   605  	caCertTemplate := &x509.Certificate{
   606  		Subject: pkix.Name{
   607  			CommonName: "root.localhost",
   608  		},
   609  		SubjectKeyId:          subjKeyID,
   610  		DNSNames:              []string{"root.localhost"},
   611  		KeyUsage:              x509.KeyUsage(x509.KeyUsageCertSign | x509.KeyUsageCRLSign),
   612  		SerialNumber:          big.NewInt(mathrand.Int63()),
   613  		NotBefore:             time.Now().Add(-30 * time.Second),
   614  		NotAfter:              time.Now().Add(262980 * time.Hour),
   615  		BasicConstraintsValid: true,
   616  		IsCA:                  true,
   617  	}
   618  	caBytes, err := x509.CreateCertificate(rand.Reader, caCertTemplate, caCertTemplate, caKey.Public(), caKey)
   619  	if err != nil {
   620  		panic(err)
   621  	}
   622  	caCert, err := x509.ParseCertificate(caBytes)
   623  	if err != nil {
   624  		panic(err)
   625  	}
   626  	caCertPEMBlock := &pem.Block{
   627  		Type:  "CERTIFICATE",
   628  		Bytes: caBytes,
   629  	}
   630  	caCertPEM := strings.TrimSpace(string(pem.EncodeToMemory(caCertPEMBlock)))
   631  
   632  	intKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   633  	if err != nil {
   634  		panic(err)
   635  	}
   636  	subjKeyID, err = GetSubjKeyID(intKey)
   637  	if err != nil {
   638  		panic(err)
   639  	}
   640  	intCertTemplate := &x509.Certificate{
   641  		Subject: pkix.Name{
   642  			CommonName: "int.localhost",
   643  		},
   644  		SubjectKeyId:          subjKeyID,
   645  		DNSNames:              []string{"int.localhost"},
   646  		KeyUsage:              x509.KeyUsage(x509.KeyUsageCertSign | x509.KeyUsageCRLSign),
   647  		SerialNumber:          big.NewInt(mathrand.Int63()),
   648  		NotBefore:             time.Now().Add(-30 * time.Second),
   649  		NotAfter:              time.Now().Add(262980 * time.Hour),
   650  		BasicConstraintsValid: true,
   651  		IsCA:                  true,
   652  	}
   653  	intBytes, err := x509.CreateCertificate(rand.Reader, intCertTemplate, caCert, intKey.Public(), caKey)
   654  	if err != nil {
   655  		panic(err)
   656  	}
   657  	intCert, err := x509.ParseCertificate(intBytes)
   658  	if err != nil {
   659  		panic(err)
   660  	}
   661  	intCertPEMBlock := &pem.Block{
   662  		Type:  "CERTIFICATE",
   663  		Bytes: intBytes,
   664  	}
   665  	intCertPEM := strings.TrimSpace(string(pem.EncodeToMemory(intCertPEMBlock)))
   666  
   667  	// EC generation
   668  	{
   669  		key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   670  		if err != nil {
   671  			panic(err)
   672  		}
   673  		subjKeyID, err := GetSubjKeyID(key)
   674  		if err != nil {
   675  			panic(err)
   676  		}
   677  		certTemplate := &x509.Certificate{
   678  			Subject: pkix.Name{
   679  				CommonName: "localhost",
   680  			},
   681  			SubjectKeyId: subjKeyID,
   682  			DNSNames:     []string{"localhost"},
   683  			ExtKeyUsage: []x509.ExtKeyUsage{
   684  				x509.ExtKeyUsageServerAuth,
   685  				x509.ExtKeyUsageClientAuth,
   686  			},
   687  			KeyUsage:     x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement,
   688  			SerialNumber: big.NewInt(mathrand.Int63()),
   689  			NotBefore:    time.Now().Add(-30 * time.Second),
   690  			NotAfter:     time.Now().Add(262980 * time.Hour),
   691  		}
   692  		csrTemplate := &x509.CertificateRequest{
   693  			Subject: pkix.Name{
   694  				CommonName: "localhost",
   695  			},
   696  			DNSNames: []string{"localhost"},
   697  		}
   698  		csrBytes, err := x509.CreateCertificateRequest(rand.Reader, csrTemplate, key)
   699  		if err != nil {
   700  			panic(err)
   701  		}
   702  		csrPEMBlock := &pem.Block{
   703  			Type:  "CERTIFICATE REQUEST",
   704  			Bytes: csrBytes,
   705  		}
   706  		csrECPem = strings.TrimSpace(string(pem.EncodeToMemory(csrPEMBlock)))
   707  		certBytes, err := x509.CreateCertificate(rand.Reader, certTemplate, intCert, key.Public(), intKey)
   708  		if err != nil {
   709  			panic(err)
   710  		}
   711  		certPEMBlock := &pem.Block{
   712  			Type:  "CERTIFICATE",
   713  			Bytes: certBytes,
   714  		}
   715  		certECPem = strings.TrimSpace(string(pem.EncodeToMemory(certPEMBlock)))
   716  		marshaledKey, err := x509.MarshalECPrivateKey(key)
   717  		if err != nil {
   718  			panic(err)
   719  		}
   720  		keyPEMBlock := &pem.Block{
   721  			Type:  "EC PRIVATE KEY",
   722  			Bytes: marshaledKey,
   723  		}
   724  		privECKeyPem = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock)))
   725  		marshaledKey, err = x509.MarshalPKCS8PrivateKey(key)
   726  		if err != nil {
   727  			panic(err)
   728  		}
   729  		keyPEMBlock = &pem.Block{
   730  			Type:  "PRIVATE KEY",
   731  			Bytes: marshaledKey,
   732  		}
   733  		privEC8KeyPem = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock)))
   734  	}
   735  
   736  	// RSA generation
   737  	{
   738  		key, err := rsa.GenerateKey(rand.Reader, 2048)
   739  		if err != nil {
   740  			panic(err)
   741  		}
   742  		subjKeyID, err := GetSubjKeyID(key)
   743  		if err != nil {
   744  			panic(err)
   745  		}
   746  		certTemplate := &x509.Certificate{
   747  			Subject: pkix.Name{
   748  				CommonName: "localhost",
   749  			},
   750  			SubjectKeyId: subjKeyID,
   751  			DNSNames:     []string{"localhost"},
   752  			ExtKeyUsage: []x509.ExtKeyUsage{
   753  				x509.ExtKeyUsageServerAuth,
   754  				x509.ExtKeyUsageClientAuth,
   755  			},
   756  			KeyUsage:     x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement,
   757  			SerialNumber: big.NewInt(mathrand.Int63()),
   758  			NotBefore:    time.Now().Add(-30 * time.Second),
   759  			NotAfter:     time.Now().Add(262980 * time.Hour),
   760  		}
   761  		csrTemplate := &x509.CertificateRequest{
   762  			Subject: pkix.Name{
   763  				CommonName: "localhost",
   764  			},
   765  			DNSNames: []string{"localhost"},
   766  		}
   767  		csrBytes, err := x509.CreateCertificateRequest(rand.Reader, csrTemplate, key)
   768  		if err != nil {
   769  			panic(err)
   770  		}
   771  		csrPEMBlock := &pem.Block{
   772  			Type:  "CERTIFICATE REQUEST",
   773  			Bytes: csrBytes,
   774  		}
   775  		csrRSAPem = strings.TrimSpace(string(pem.EncodeToMemory(csrPEMBlock)))
   776  		certBytes, err := x509.CreateCertificate(rand.Reader, certTemplate, intCert, key.Public(), intKey)
   777  		if err != nil {
   778  			panic(err)
   779  		}
   780  		certPEMBlock := &pem.Block{
   781  			Type:  "CERTIFICATE",
   782  			Bytes: certBytes,
   783  		}
   784  		certRSAPem = strings.TrimSpace(string(pem.EncodeToMemory(certPEMBlock)))
   785  		marshaledKey := x509.MarshalPKCS1PrivateKey(key)
   786  		keyPEMBlock := &pem.Block{
   787  			Type:  "RSA PRIVATE KEY",
   788  			Bytes: marshaledKey,
   789  		}
   790  		privRSAKeyPem = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock)))
   791  		marshaledKey, err = x509.MarshalPKCS8PrivateKey(key)
   792  		if err != nil {
   793  			panic(err)
   794  		}
   795  		keyPEMBlock = &pem.Block{
   796  			Type:  "PRIVATE KEY",
   797  			Bytes: marshaledKey,
   798  		}
   799  		privRSA8KeyPem = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock)))
   800  	}
   801  
   802  	// Ed25519 generation
   803  	{
   804  		pubkey, privkey, err := ed25519.GenerateKey(rand.Reader)
   805  		if err != nil {
   806  			panic(err)
   807  		}
   808  		subjKeyID, err := GetSubjKeyID(privkey)
   809  		if err != nil {
   810  			panic(err)
   811  		}
   812  		certTemplate := &x509.Certificate{
   813  			Subject: pkix.Name{
   814  				CommonName: "localhost",
   815  			},
   816  			SubjectKeyId: subjKeyID,
   817  			DNSNames:     []string{"localhost"},
   818  			ExtKeyUsage: []x509.ExtKeyUsage{
   819  				x509.ExtKeyUsageServerAuth,
   820  				x509.ExtKeyUsageClientAuth,
   821  			},
   822  			KeyUsage:     x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement,
   823  			SerialNumber: big.NewInt(mathrand.Int63()),
   824  			NotBefore:    time.Now().Add(-30 * time.Second),
   825  			NotAfter:     time.Now().Add(262980 * time.Hour),
   826  		}
   827  		csrTemplate := &x509.CertificateRequest{
   828  			Subject: pkix.Name{
   829  				CommonName: "localhost",
   830  			},
   831  			DNSNames: []string{"localhost"},
   832  		}
   833  		csrBytes, err := x509.CreateCertificateRequest(rand.Reader, csrTemplate, privkey)
   834  		if err != nil {
   835  			panic(err)
   836  		}
   837  		csrPEMBlock := &pem.Block{
   838  			Type:  "CERTIFICATE REQUEST",
   839  			Bytes: csrBytes,
   840  		}
   841  		csrEd25519Pem = strings.TrimSpace(string(pem.EncodeToMemory(csrPEMBlock)))
   842  		certBytes, err := x509.CreateCertificate(rand.Reader, certTemplate, intCert, pubkey, intKey)
   843  		if err != nil {
   844  			panic(err)
   845  		}
   846  		certPEMBlock := &pem.Block{
   847  			Type:  "CERTIFICATE",
   848  			Bytes: certBytes,
   849  		}
   850  		certEd25519Pem = strings.TrimSpace(string(pem.EncodeToMemory(certPEMBlock)))
   851  		marshaledKey, err := x509.MarshalPKCS8PrivateKey(privkey)
   852  		if err != nil {
   853  			panic(err)
   854  		}
   855  		keyPEMBlock := &pem.Block{
   856  			Type:  "PRIVATE KEY",
   857  			Bytes: marshaledKey,
   858  		}
   859  		privEd255198KeyPem = strings.TrimSpace(string(pem.EncodeToMemory(keyPEMBlock)))
   860  	}
   861  
   862  	issuingCaChainPem = []string{intCertPEM, caCertPEM}
   863  }
   864  
   865  func TestComparePublicKeysAndType(t *testing.T) {
   866  	rsa1 := genRsaKey(t).Public()
   867  	rsa2 := genRsaKey(t).Public()
   868  	eddsa1 := genEdDSA(t).Public()
   869  	eddsa2 := genEdDSA(t).Public()
   870  	ed25519_1, _ := genEd25519Key(t)
   871  	ed25519_2, _ := genEd25519Key(t)
   872  
   873  	type args struct {
   874  		key1Iface crypto.PublicKey
   875  		key2Iface crypto.PublicKey
   876  	}
   877  	tests := []struct {
   878  		name    string
   879  		args    args
   880  		want    bool
   881  		wantErr bool
   882  	}{
   883  		{name: "RSA_Equal", args: args{key1Iface: rsa1, key2Iface: rsa1}, want: true, wantErr: false},
   884  		{name: "RSA_NotEqual", args: args{key1Iface: rsa1, key2Iface: rsa2}, want: false, wantErr: false},
   885  		{name: "EDDSA_Equal", args: args{key1Iface: eddsa1, key2Iface: eddsa1}, want: true, wantErr: false},
   886  		{name: "EDDSA_NotEqual", args: args{key1Iface: eddsa1, key2Iface: eddsa2}, want: false, wantErr: false},
   887  		{name: "ED25519_Equal", args: args{key1Iface: ed25519_1, key2Iface: ed25519_1}, want: true, wantErr: false},
   888  		{name: "ED25519_NotEqual", args: args{key1Iface: ed25519_1, key2Iface: ed25519_2}, want: false, wantErr: false},
   889  		{name: "Mismatched_RSA", args: args{key1Iface: rsa1, key2Iface: ed25519_2}, want: false, wantErr: false},
   890  		{name: "Mismatched_EDDSA", args: args{key1Iface: ed25519_1, key2Iface: rsa1}, want: false, wantErr: false},
   891  		{name: "Mismatched_ED25519", args: args{key1Iface: ed25519_1, key2Iface: rsa1}, want: false, wantErr: false},
   892  	}
   893  	for _, tt := range tests {
   894  		t.Run(tt.name, func(t *testing.T) {
   895  			got, err := ComparePublicKeysAndType(tt.args.key1Iface, tt.args.key2Iface)
   896  			if (err != nil) != tt.wantErr {
   897  				t.Errorf("ComparePublicKeysAndType() error = %v, wantErr %v", err, tt.wantErr)
   898  				return
   899  			}
   900  			if got != tt.want {
   901  				t.Errorf("ComparePublicKeysAndType() got = %v, want %v", got, tt.want)
   902  			}
   903  		})
   904  	}
   905  }
   906  
   907  func TestNotAfterValues(t *testing.T) {
   908  	if ErrNotAfterBehavior != 0 {
   909  		t.Fatalf("Expected ErrNotAfterBehavior=%v to have value 0", ErrNotAfterBehavior)
   910  	}
   911  
   912  	if TruncateNotAfterBehavior != 1 {
   913  		t.Fatalf("Expected TruncateNotAfterBehavior=%v to have value 1", TruncateNotAfterBehavior)
   914  	}
   915  
   916  	if PermitNotAfterBehavior != 2 {
   917  		t.Fatalf("Expected PermitNotAfterBehavior=%v to have value 2", PermitNotAfterBehavior)
   918  	}
   919  }
   920  
   921  func TestSignatureAlgorithmRoundTripping(t *testing.T) {
   922  	for leftName, value := range SignatureAlgorithmNames {
   923  		if leftName == "pureed25519" && value == x509.PureEd25519 {
   924  			continue
   925  		}
   926  
   927  		rightName, present := InvSignatureAlgorithmNames[value]
   928  		if !present {
   929  			t.Fatalf("%v=%v is present in SignatureAlgorithmNames but not in InvSignatureAlgorithmNames", leftName, value)
   930  		}
   931  
   932  		if strings.ToLower(rightName) != leftName {
   933  			t.Fatalf("%v=%v is present in SignatureAlgorithmNames but inverse for %v has different name: %v", leftName, value, value, rightName)
   934  		}
   935  	}
   936  
   937  	for leftValue, name := range InvSignatureAlgorithmNames {
   938  		rightValue, present := SignatureAlgorithmNames[strings.ToLower(name)]
   939  		if !present {
   940  			t.Fatalf("%v=%v is present in InvSignatureAlgorithmNames but not in SignatureAlgorithmNames", leftValue, name)
   941  		}
   942  
   943  		if rightValue != leftValue {
   944  			t.Fatalf("%v=%v is present in InvSignatureAlgorithmNames but forwards for %v has different value: %v", leftValue, name, name, rightValue)
   945  		}
   946  	}
   947  }
   948  
   949  // TestParseBasicConstraintExtension Verify extension generation and parsing of x509 basic constraint extensions
   950  // works as expected.
   951  func TestBasicConstraintExtension(t *testing.T) {
   952  	t.Parallel()
   953  
   954  	tests := []struct {
   955  		name       string
   956  		isCA       bool
   957  		maxPathLen int
   958  	}{
   959  		{"empty-seq", false, -1},
   960  		{"just-ca-true", true, -1},
   961  		{"just-ca-with-maxpathlen", true, 2},
   962  	}
   963  	for _, tt := range tests {
   964  		t.Run(tt.name, func(t *testing.T) {
   965  			ext, err := CreateBasicConstraintExtension(tt.isCA, tt.maxPathLen)
   966  			if err != nil {
   967  				t.Fatalf("failed generating basic extension: %v", err)
   968  			}
   969  
   970  			gotIsCa, gotMaxPathLen, err := ParseBasicConstraintExtension(ext)
   971  			if err != nil {
   972  				t.Fatalf("failed parsing basic extension: %v", err)
   973  			}
   974  
   975  			if tt.isCA != gotIsCa {
   976  				t.Fatalf("expected isCa (%v) got isCa (%v)", tt.isCA, gotIsCa)
   977  			}
   978  
   979  			if tt.maxPathLen != gotMaxPathLen {
   980  				t.Fatalf("expected maxPathLen (%v) got maxPathLen (%v)", tt.maxPathLen, gotMaxPathLen)
   981  			}
   982  		})
   983  	}
   984  
   985  	t.Run("bad-extension-oid", func(t *testing.T) {
   986  		// Test invalid type errors out
   987  		_, _, err := ParseBasicConstraintExtension(pkix.Extension{})
   988  		if err == nil {
   989  			t.Fatalf("should have failed parsing non-basic constraint extension")
   990  		}
   991  	})
   992  
   993  	t.Run("garbage-value", func(t *testing.T) {
   994  		extraBytes, err := asn1.Marshal("a string")
   995  		if err != nil {
   996  			t.Fatalf("failed encoding the struct: %v", err)
   997  		}
   998  		ext := pkix.Extension{
   999  			Id:    ExtensionBasicConstraintsOID,
  1000  			Value: extraBytes,
  1001  		}
  1002  		_, _, err = ParseBasicConstraintExtension(ext)
  1003  		if err == nil {
  1004  			t.Fatalf("should have failed parsing basic constraint with extra information")
  1005  		}
  1006  	})
  1007  }
  1008  
  1009  func genRsaKey(t *testing.T) *rsa.PrivateKey {
  1010  	key, err := rsa.GenerateKey(rand.Reader, 2048)
  1011  	if err != nil {
  1012  		t.Fatal(err)
  1013  	}
  1014  	return key
  1015  }
  1016  
  1017  func genEdDSA(t *testing.T) *ecdsa.PrivateKey {
  1018  	key, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
  1019  	if err != nil {
  1020  		t.Fatal(err)
  1021  	}
  1022  	return key
  1023  }
  1024  
  1025  func genEd25519Key(t *testing.T) (ed25519.PublicKey, ed25519.PrivateKey) {
  1026  	key, priv, err := ed25519.GenerateKey(rand.Reader)
  1027  	if err != nil {
  1028  		t.Fatal(err)
  1029  	}
  1030  	return key, priv
  1031  }
  1032  
  1033  var (
  1034  	initTest           sync.Once
  1035  	privRSA8KeyPem     string
  1036  	privRSAKeyPem      string
  1037  	csrRSAPem          string
  1038  	certRSAPem         string
  1039  	privEd255198KeyPem string
  1040  	csrEd25519Pem      string
  1041  	certEd25519Pem     string
  1042  	privECKeyPem       string
  1043  	csrECPem           string
  1044  	privEC8KeyPem      string
  1045  	certECPem          string
  1046  	issuingCaChainPem  []string
  1047  )