...

Source file src/github.com/letsencrypt/boulder/issuance/issuance_test.go

Documentation: github.com/letsencrypt/boulder/issuance

     1  package issuance
     2  
     3  import (
     4  	"crypto"
     5  	"crypto/dsa"
     6  	"crypto/ecdsa"
     7  	"crypto/ed25519"
     8  	"crypto/elliptic"
     9  	"crypto/rand"
    10  	"crypto/rsa"
    11  	"crypto/x509"
    12  	"crypto/x509/pkix"
    13  	"encoding/asn1"
    14  	"encoding/base64"
    15  	"fmt"
    16  	"math/big"
    17  	"os"
    18  	"strings"
    19  	"testing"
    20  	"time"
    21  
    22  	ct "github.com/google/certificate-transparency-go"
    23  	"github.com/jmhodges/clock"
    24  
    25  	"github.com/letsencrypt/boulder/cmd"
    26  	"github.com/letsencrypt/boulder/config"
    27  	"github.com/letsencrypt/boulder/core"
    28  	"github.com/letsencrypt/boulder/ctpolicy/loglist"
    29  	"github.com/letsencrypt/boulder/linter"
    30  	"github.com/letsencrypt/boulder/test"
    31  )
    32  
    33  func defaultProfileConfig() ProfileConfig {
    34  	return ProfileConfig{
    35  		AllowCommonName:     true,
    36  		AllowCTPoison:       true,
    37  		AllowSCTList:        true,
    38  		AllowMustStaple:     true,
    39  		MaxValidityPeriod:   config.Duration{Duration: time.Hour},
    40  		MaxValidityBackdate: config.Duration{Duration: time.Hour},
    41  	}
    42  }
    43  
    44  func defaultIssuerConfig() IssuerConfig {
    45  	return IssuerConfig{
    46  		UseForECDSALeaves: true,
    47  		UseForRSALeaves:   true,
    48  		IssuerURL:         "http://issuer-url",
    49  		OCSPURL:           "http://ocsp-url",
    50  	}
    51  }
    52  
    53  func defaultProfile() *Profile {
    54  	p, _ := NewProfile(defaultProfileConfig(), defaultIssuerConfig())
    55  	return p
    56  }
    57  
    58  var issuerCert *Certificate
    59  var issuerSigner *ecdsa.PrivateKey
    60  
    61  func TestMain(m *testing.M) {
    62  	tk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    63  	cmd.FailOnError(err, "failed to generate test key")
    64  	issuerSigner = tk
    65  	template := &x509.Certificate{
    66  		SerialNumber:          big.NewInt(123),
    67  		BasicConstraintsValid: true,
    68  		IsCA:                  true,
    69  		Subject: pkix.Name{
    70  			CommonName: "big ca",
    71  		},
    72  		KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature,
    73  	}
    74  	issuer, err := x509.CreateCertificate(rand.Reader, template, template, tk.Public(), tk)
    75  	cmd.FailOnError(err, "failed to generate test issuer")
    76  	cert, err := x509.ParseCertificate(issuer)
    77  	cmd.FailOnError(err, "failed to parse test issuer")
    78  	issuerCert = &Certificate{Certificate: cert}
    79  	os.Exit(m.Run())
    80  }
    81  
    82  func TestNewProfileNoIssuerURL(t *testing.T) {
    83  	_, err := NewProfile(ProfileConfig{}, IssuerConfig{})
    84  	test.AssertError(t, err, "NewProfile didn't fail with no issuer URL")
    85  	test.AssertEquals(t, err.Error(), "Issuer URL is required")
    86  }
    87  
    88  func TestNewProfileNoOCSPURL(t *testing.T) {
    89  	_, err := NewProfile(ProfileConfig{}, IssuerConfig{IssuerURL: "issuer-url"})
    90  	test.AssertError(t, err, "NewProfile didn't fail with no OCSP URL")
    91  	test.AssertEquals(t, err.Error(), "OCSP URL is required")
    92  }
    93  
    94  func TestRequestValid(t *testing.T) {
    95  	fc := clock.NewFake()
    96  	fc.Add(time.Hour * 24)
    97  	tests := []struct {
    98  		name          string
    99  		profile       *Profile
   100  		request       *IssuanceRequest
   101  		expectedError string
   102  	}{
   103  		{
   104  			name:          "unsupported key type",
   105  			profile:       &Profile{},
   106  			request:       &IssuanceRequest{PublicKey: &dsa.PublicKey{}},
   107  			expectedError: "unsupported public key type",
   108  		},
   109  		{
   110  			name:          "cannot sign rsa",
   111  			profile:       &Profile{},
   112  			request:       &IssuanceRequest{PublicKey: &rsa.PublicKey{}},
   113  			expectedError: "cannot sign RSA public keys",
   114  		},
   115  		{
   116  			name:          "cannot sign ecdsa",
   117  			profile:       &Profile{},
   118  			request:       &IssuanceRequest{PublicKey: &ecdsa.PublicKey{}},
   119  			expectedError: "cannot sign ECDSA public keys",
   120  		},
   121  		{
   122  			name: "must staple not allowed",
   123  			profile: &Profile{
   124  				useForECDSALeaves: true,
   125  			},
   126  			request: &IssuanceRequest{
   127  				PublicKey:         &ecdsa.PublicKey{},
   128  				IncludeMustStaple: true,
   129  			},
   130  			expectedError: "must-staple extension cannot be included",
   131  		},
   132  		{
   133  			name: "ct poison not allowed",
   134  			profile: &Profile{
   135  				useForECDSALeaves: true,
   136  			},
   137  			request: &IssuanceRequest{
   138  				PublicKey:       &ecdsa.PublicKey{},
   139  				IncludeCTPoison: true,
   140  			},
   141  			expectedError: "ct poison extension cannot be included",
   142  		},
   143  		{
   144  			name: "sct list not allowed",
   145  			profile: &Profile{
   146  				useForECDSALeaves: true,
   147  			},
   148  			request: &IssuanceRequest{
   149  				PublicKey: &ecdsa.PublicKey{},
   150  				sctList:   []ct.SignedCertificateTimestamp{},
   151  			},
   152  			expectedError: "sct list extension cannot be included",
   153  		},
   154  		{
   155  			name: "sct list and ct poison not allowed",
   156  			profile: &Profile{
   157  				useForECDSALeaves: true,
   158  				allowCTPoison:     true,
   159  				allowSCTList:      true,
   160  			},
   161  			request: &IssuanceRequest{
   162  				PublicKey:       &ecdsa.PublicKey{},
   163  				IncludeCTPoison: true,
   164  				sctList:         []ct.SignedCertificateTimestamp{},
   165  			},
   166  			expectedError: "cannot include both ct poison and sct list extensions",
   167  		},
   168  		{
   169  			name: "common name not allowed",
   170  			profile: &Profile{
   171  				useForECDSALeaves: true,
   172  			},
   173  			request: &IssuanceRequest{
   174  				PublicKey:  &ecdsa.PublicKey{},
   175  				CommonName: "cn",
   176  			},
   177  			expectedError: "common name cannot be included",
   178  		},
   179  		{
   180  			name: "negative validity",
   181  			profile: &Profile{
   182  				useForECDSALeaves: true,
   183  			},
   184  			request: &IssuanceRequest{
   185  				PublicKey: &ecdsa.PublicKey{},
   186  				NotBefore: fc.Now().Add(time.Hour),
   187  				NotAfter:  fc.Now(),
   188  			},
   189  			expectedError: "NotAfter must be after NotBefore",
   190  		},
   191  		{
   192  			name: "validity larger than max",
   193  			profile: &Profile{
   194  				useForECDSALeaves: true,
   195  				maxValidity:       time.Minute,
   196  			},
   197  			request: &IssuanceRequest{
   198  				PublicKey: &ecdsa.PublicKey{},
   199  				NotBefore: fc.Now(),
   200  				NotAfter:  fc.Now().Add(time.Hour - time.Second),
   201  			},
   202  			expectedError: "validity period is more than the maximum allowed period (1h0m0s>1m0s)",
   203  		},
   204  		{
   205  			name: "validity larger than max due to inclusivity",
   206  			profile: &Profile{
   207  				useForECDSALeaves: true,
   208  				maxValidity:       time.Hour,
   209  			},
   210  			request: &IssuanceRequest{
   211  				PublicKey: &ecdsa.PublicKey{},
   212  				NotBefore: fc.Now(),
   213  				NotAfter:  fc.Now().Add(time.Hour),
   214  			},
   215  			expectedError: "validity period is more than the maximum allowed period (1h0m1s>1h0m0s)",
   216  		},
   217  		{
   218  			name: "validity backdated more than max",
   219  			profile: &Profile{
   220  				useForECDSALeaves: true,
   221  				maxValidity:       time.Hour * 2,
   222  				maxBackdate:       time.Hour,
   223  			},
   224  			request: &IssuanceRequest{
   225  				PublicKey: &ecdsa.PublicKey{},
   226  				NotBefore: fc.Now().Add(-time.Hour * 2),
   227  				NotAfter:  fc.Now().Add(-time.Hour),
   228  			},
   229  			expectedError: "NotBefore is backdated more than the maximum allowed period (2h0m0s>1h0m0s)",
   230  		},
   231  		{
   232  			name: "validity is forward dated",
   233  			profile: &Profile{
   234  				useForECDSALeaves: true,
   235  				maxValidity:       time.Hour * 2,
   236  				maxBackdate:       time.Hour,
   237  			},
   238  			request: &IssuanceRequest{
   239  				PublicKey: &ecdsa.PublicKey{},
   240  				NotBefore: fc.Now().Add(time.Hour),
   241  				NotAfter:  fc.Now().Add(time.Hour * 2),
   242  			},
   243  			expectedError: "NotBefore is in the future",
   244  		},
   245  		{
   246  			name: "serial too short",
   247  			profile: &Profile{
   248  				useForECDSALeaves: true,
   249  				maxValidity:       time.Hour * 2,
   250  			},
   251  			request: &IssuanceRequest{
   252  				PublicKey: &ecdsa.PublicKey{},
   253  				NotBefore: fc.Now(),
   254  				NotAfter:  fc.Now().Add(time.Hour),
   255  				Serial:    []byte{0, 1, 2, 3, 4, 5, 6, 7},
   256  			},
   257  			expectedError: "serial must be between 9 and 19 bytes",
   258  		},
   259  		{
   260  			name: "serial too long",
   261  			profile: &Profile{
   262  				useForECDSALeaves: true,
   263  				maxValidity:       time.Hour * 2,
   264  			},
   265  			request: &IssuanceRequest{
   266  				PublicKey: &ecdsa.PublicKey{},
   267  				NotBefore: fc.Now(),
   268  				NotAfter:  fc.Now().Add(time.Hour),
   269  				Serial:    []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
   270  			},
   271  			expectedError: "serial must be between 9 and 19 bytes",
   272  		},
   273  		{
   274  			name: "good",
   275  			profile: &Profile{
   276  				useForECDSALeaves: true,
   277  				maxValidity:       time.Hour * 2,
   278  			},
   279  			request: &IssuanceRequest{
   280  				PublicKey: &ecdsa.PublicKey{},
   281  				NotBefore: fc.Now(),
   282  				NotAfter:  fc.Now().Add(time.Hour),
   283  				Serial:    []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
   284  			},
   285  		},
   286  	}
   287  	for _, tc := range tests {
   288  		t.Run(tc.name, func(t *testing.T) {
   289  			err := tc.profile.requestValid(fc, tc.request)
   290  			if err != nil {
   291  				if tc.expectedError == "" {
   292  					t.Errorf("failed with unexpected error: %s", err)
   293  				} else if tc.expectedError != err.Error() {
   294  					t.Errorf("failed with unexpected error, wanted: %q, got: %q", tc.expectedError, err.Error())
   295  				}
   296  				return
   297  			} else if tc.expectedError != "" {
   298  				t.Errorf("didn't fail, expected %q", tc.expectedError)
   299  			}
   300  		})
   301  	}
   302  }
   303  
   304  func TestGenerateTemplate(t *testing.T) {
   305  	tests := []struct {
   306  		name             string
   307  		profile          *Profile
   308  		expectedTemplate *x509.Certificate
   309  	}{
   310  		{
   311  			name: "crl url",
   312  			profile: &Profile{
   313  				crlURL: "crl-url",
   314  				sigAlg: x509.SHA256WithRSA,
   315  			},
   316  			expectedTemplate: &x509.Certificate{
   317  				BasicConstraintsValid: true,
   318  				SignatureAlgorithm:    x509.SHA256WithRSA,
   319  				ExtKeyUsage:           defaultEKU,
   320  				IssuingCertificateURL: []string{""},
   321  				OCSPServer:            []string{""},
   322  				CRLDistributionPoints: []string{"crl-url"},
   323  				PolicyIdentifiers:     []asn1.ObjectIdentifier{{2, 23, 140, 1, 2, 1}},
   324  			},
   325  		},
   326  	}
   327  
   328  	for _, tc := range tests {
   329  		t.Run(tc.name, func(t *testing.T) {
   330  			template := tc.profile.generateTemplate()
   331  			test.AssertDeepEquals(t, *template, *tc.expectedTemplate)
   332  		})
   333  	}
   334  }
   335  
   336  func TestNewIssuer(t *testing.T) {
   337  	_, err := NewIssuer(
   338  		issuerCert,
   339  		issuerSigner,
   340  		defaultProfile(),
   341  		&linter.Linter{},
   342  		clock.NewFake(),
   343  	)
   344  	test.AssertNotError(t, err, "NewIssuer failed")
   345  }
   346  
   347  func TestNewIssuerUnsupportedKeyType(t *testing.T) {
   348  	_, err := NewIssuer(
   349  		&Certificate{
   350  			Certificate: &x509.Certificate{
   351  				PublicKey: &ed25519.PublicKey{},
   352  			},
   353  		},
   354  		&ed25519.PrivateKey{},
   355  		defaultProfile(),
   356  		&linter.Linter{},
   357  		clock.NewFake(),
   358  	)
   359  	test.AssertError(t, err, "NewIssuer didn't fail")
   360  	test.AssertEquals(t, err.Error(), "unsupported issuer key type")
   361  }
   362  
   363  func TestNewIssuerNoCertSign(t *testing.T) {
   364  	_, err := NewIssuer(
   365  		&Certificate{
   366  			Certificate: &x509.Certificate{
   367  				PublicKey: &ecdsa.PublicKey{
   368  					Curve: elliptic.P256(),
   369  				},
   370  				KeyUsage: 0,
   371  			},
   372  		},
   373  		issuerSigner,
   374  		defaultProfile(),
   375  		&linter.Linter{},
   376  		clock.NewFake(),
   377  	)
   378  	test.AssertError(t, err, "NewIssuer didn't fail")
   379  	test.AssertEquals(t, err.Error(), "end-entity signing cert does not have keyUsage certSign")
   380  }
   381  
   382  func TestNewIssuerNoDigitalSignature(t *testing.T) {
   383  	_, err := NewIssuer(
   384  		&Certificate{
   385  			Certificate: &x509.Certificate{
   386  				PublicKey: &ecdsa.PublicKey{
   387  					Curve: elliptic.P256(),
   388  				},
   389  				KeyUsage: x509.KeyUsageCertSign,
   390  			},
   391  		},
   392  		issuerSigner,
   393  		defaultProfile(),
   394  		&linter.Linter{},
   395  		clock.NewFake(),
   396  	)
   397  	test.AssertError(t, err, "NewIssuer didn't fail")
   398  	test.AssertEquals(t, err.Error(), "end-entity ocsp signing cert does not have keyUsage digitalSignature")
   399  }
   400  
   401  func TestNewIssuerOCSPOnly(t *testing.T) {
   402  	p := defaultProfile()
   403  	p.useForRSALeaves = false
   404  	p.useForECDSALeaves = false
   405  	_, err := NewIssuer(
   406  		&Certificate{
   407  			Certificate: &x509.Certificate{
   408  				PublicKey: &ecdsa.PublicKey{
   409  					Curve: elliptic.P256(),
   410  				},
   411  				KeyUsage: x509.KeyUsageDigitalSignature,
   412  			},
   413  		},
   414  		issuerSigner,
   415  		p,
   416  		&linter.Linter{},
   417  		clock.NewFake(),
   418  	)
   419  	test.AssertNotError(t, err, "NewIssuer failed")
   420  }
   421  
   422  func TestIssue(t *testing.T) {
   423  	for _, tc := range []struct {
   424  		name         string
   425  		generateFunc func() (crypto.Signer, error)
   426  		ku           x509.KeyUsage
   427  	}{
   428  		{
   429  			name: "RSA",
   430  			generateFunc: func() (crypto.Signer, error) {
   431  				return rsa.GenerateKey(rand.Reader, 2048)
   432  			},
   433  			ku: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment,
   434  		},
   435  		{
   436  			name: "ECDSA",
   437  			generateFunc: func() (crypto.Signer, error) {
   438  				return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   439  			},
   440  			ku: x509.KeyUsageDigitalSignature,
   441  		},
   442  	} {
   443  		t.Run(tc.name, func(t *testing.T) {
   444  			fc := clock.NewFake()
   445  			fc.Set(time.Now())
   446  			linter, err := linter.New(
   447  				issuerCert.Certificate,
   448  				issuerSigner,
   449  				[]string{
   450  					"w_ct_sct_policy_count_unsatisfied",
   451  					"e_scts_from_same_operator",
   452  					"n_subject_common_name_included",
   453  				},
   454  			)
   455  			test.AssertNotError(t, err, "failed to create linter")
   456  			signer, err := NewIssuer(issuerCert, issuerSigner, defaultProfile(), linter, fc)
   457  			test.AssertNotError(t, err, "NewIssuer failed")
   458  			pk, err := tc.generateFunc()
   459  			test.AssertNotError(t, err, "failed to generate test key")
   460  			lintCertBytes, issuanceToken, err := signer.Prepare(&IssuanceRequest{
   461  				PublicKey:       pk.Public(),
   462  				Serial:          []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
   463  				CommonName:      "example.com",
   464  				DNSNames:        []string{"example.com"},
   465  				NotBefore:       fc.Now(),
   466  				NotAfter:        fc.Now().Add(time.Hour - time.Second),
   467  				IncludeCTPoison: true,
   468  			})
   469  			test.AssertNotError(t, err, "Prepare failed")
   470  			_, err = x509.ParseCertificate(lintCertBytes)
   471  			test.AssertNotError(t, err, "failed to parse certificate")
   472  			certBytes, err := signer.Issue(issuanceToken)
   473  			test.AssertNotError(t, err, "Issue failed")
   474  			cert, err := x509.ParseCertificate(certBytes)
   475  			test.AssertNotError(t, err, "failed to parse certificate")
   476  			err = cert.CheckSignatureFrom(issuerCert.Certificate)
   477  			test.AssertNotError(t, err, "signature validation failed")
   478  			test.AssertDeepEquals(t, cert.DNSNames, []string{"example.com"})
   479  			test.AssertEquals(t, cert.Subject.CommonName, "example.com")
   480  			test.AssertByteEquals(t, cert.SerialNumber.Bytes(), []byte{1, 2, 3, 4, 5, 6, 7, 8, 9})
   481  			test.AssertDeepEquals(t, cert.PublicKey, pk.Public())
   482  			test.AssertEquals(t, len(cert.Extensions), 9) // Constraints, KU, EKU, SKID, AKID, AIA, SAN, Policies, Poison
   483  			test.AssertEquals(t, cert.KeyUsage, tc.ku)
   484  		})
   485  	}
   486  }
   487  
   488  func TestIssueRSA(t *testing.T) {
   489  	fc := clock.NewFake()
   490  	fc.Set(time.Now())
   491  	linter, err := linter.New(
   492  		issuerCert.Certificate,
   493  		issuerSigner,
   494  		[]string{
   495  			"w_ct_sct_policy_count_unsatisfied",
   496  			"e_scts_from_same_operator",
   497  		},
   498  	)
   499  	test.AssertNotError(t, err, "failed to create linter")
   500  	signer, err := NewIssuer(issuerCert, issuerSigner, defaultProfile(), linter, fc)
   501  	test.AssertNotError(t, err, "NewIssuer failed")
   502  	pk, err := rsa.GenerateKey(rand.Reader, 2048)
   503  	test.AssertNotError(t, err, "failed to generate test key")
   504  	_, issuanceToken, err := signer.Prepare(&IssuanceRequest{
   505  		PublicKey:       pk.Public(),
   506  		Serial:          []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
   507  		DNSNames:        []string{"example.com"},
   508  		NotBefore:       fc.Now(),
   509  		NotAfter:        fc.Now().Add(time.Hour - time.Second),
   510  		IncludeCTPoison: true,
   511  	})
   512  	test.AssertNotError(t, err, "failed to prepare lint certificate")
   513  	certBytes, err := signer.Issue(issuanceToken)
   514  	test.AssertNotError(t, err, "failed to parse certificate")
   515  	cert, err := x509.ParseCertificate(certBytes)
   516  	test.AssertNotError(t, err, "failed to parse certificate")
   517  	err = cert.CheckSignatureFrom(issuerCert.Certificate)
   518  	test.AssertNotError(t, err, "signature validation failed")
   519  	test.AssertByteEquals(t, cert.SerialNumber.Bytes(), []byte{1, 2, 3, 4, 5, 6, 7, 8, 9})
   520  	test.AssertDeepEquals(t, cert.PublicKey, pk.Public())
   521  	test.AssertEquals(t, len(cert.Extensions), 9) // Constraints, KU, EKU, SKID, AKID, AIA, SAN, Policies, Poison
   522  	test.AssertEquals(t, cert.KeyUsage, x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment)
   523  }
   524  
   525  func TestIssueCommonName(t *testing.T) {
   526  	fc := clock.NewFake()
   527  	fc.Set(time.Now())
   528  	linter, err := linter.New(
   529  		issuerCert.Certificate,
   530  		issuerSigner,
   531  		[]string{
   532  			"w_ct_sct_policy_count_unsatisfied",
   533  			"e_scts_from_same_operator",
   534  			"n_subject_common_name_included",
   535  		},
   536  	)
   537  	test.AssertNotError(t, err, "failed to create linter")
   538  	signer, err := NewIssuer(issuerCert, issuerSigner, defaultProfile(), linter, fc)
   539  	test.AssertNotError(t, err, "NewIssuer failed")
   540  	pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   541  	test.AssertNotError(t, err, "failed to generate test key")
   542  	ir := &IssuanceRequest{
   543  		PublicKey:       pk.Public(),
   544  		Serial:          []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
   545  		CommonName:      "example.com",
   546  		DNSNames:        []string{"example.com", "www.example.com"},
   547  		NotBefore:       fc.Now(),
   548  		NotAfter:        fc.Now().Add(time.Hour - time.Second),
   549  		IncludeCTPoison: true,
   550  	}
   551  
   552  	_, issuanceToken, err := signer.Prepare(ir)
   553  	test.AssertNotError(t, err, "Prepare failed")
   554  	certBytes, err := signer.Issue(issuanceToken)
   555  	test.AssertNotError(t, err, "Issue failed")
   556  	cert, err := x509.ParseCertificate(certBytes)
   557  	test.AssertNotError(t, err, "failed to parse certificate")
   558  	test.AssertEquals(t, cert.Subject.CommonName, "example.com")
   559  
   560  	signer.Profile.allowCommonName = false
   561  	_, _, err = signer.Prepare(ir)
   562  	test.AssertError(t, err, "Prepare should have failed")
   563  
   564  	ir.CommonName = ""
   565  	_, issuanceToken, err = signer.Prepare(ir)
   566  	test.AssertNotError(t, err, "Prepare failed")
   567  	certBytes, err = signer.Issue(issuanceToken)
   568  	test.AssertNotError(t, err, "Issue failed")
   569  	cert, err = x509.ParseCertificate(certBytes)
   570  	test.AssertNotError(t, err, "failed to parse certificate")
   571  	test.AssertEquals(t, cert.Subject.CommonName, "")
   572  	test.AssertDeepEquals(t, cert.DNSNames, []string{"example.com", "www.example.com"})
   573  }
   574  
   575  func TestIssueCTPoison(t *testing.T) {
   576  	fc := clock.NewFake()
   577  	fc.Set(time.Now())
   578  	linter, err := linter.New(
   579  		issuerCert.Certificate,
   580  		issuerSigner,
   581  		[]string{
   582  			"w_ct_sct_policy_count_unsatisfied",
   583  			"e_scts_from_same_operator",
   584  		},
   585  	)
   586  	test.AssertNotError(t, err, "failed to create linter")
   587  	signer, err := NewIssuer(issuerCert, issuerSigner, defaultProfile(), linter, fc)
   588  	test.AssertNotError(t, err, "NewIssuer failed")
   589  	pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   590  	test.AssertNotError(t, err, "failed to generate test key")
   591  	_, issuanceToken, err := signer.Prepare(&IssuanceRequest{
   592  		PublicKey:       pk.Public(),
   593  		Serial:          []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
   594  		DNSNames:        []string{"example.com"},
   595  		IncludeCTPoison: true,
   596  		NotBefore:       fc.Now(),
   597  		NotAfter:        fc.Now().Add(time.Hour - time.Second),
   598  	})
   599  	test.AssertNotError(t, err, "Prepare failed")
   600  	certBytes, err := signer.Issue(issuanceToken)
   601  	test.AssertNotError(t, err, "Issue failed")
   602  	cert, err := x509.ParseCertificate(certBytes)
   603  	test.AssertNotError(t, err, "failed to parse certificate")
   604  	err = cert.CheckSignatureFrom(issuerCert.Certificate)
   605  	test.AssertNotError(t, err, "signature validation failed")
   606  	test.AssertByteEquals(t, cert.SerialNumber.Bytes(), []byte{1, 2, 3, 4, 5, 6, 7, 8, 9})
   607  	test.AssertDeepEquals(t, cert.PublicKey, pk.Public())
   608  	test.AssertEquals(t, len(cert.Extensions), 9) // Constraints, KU, EKU, SKID, AKID, AIA, SAN, Policies, CT Poison
   609  	test.AssertDeepEquals(t, cert.Extensions[8], ctPoisonExt)
   610  }
   611  
   612  func mustDecodeB64(b string) []byte {
   613  	out, err := base64.StdEncoding.DecodeString(b)
   614  	if err != nil {
   615  		panic(err)
   616  	}
   617  	return out
   618  }
   619  
   620  func TestIssueSCTList(t *testing.T) {
   621  	fc := clock.NewFake()
   622  	fc.Set(time.Now())
   623  	err := loglist.InitLintList("../test/ct-test-srv/log_list.json")
   624  	test.AssertNotError(t, err, "failed to load log list")
   625  	linter, err := linter.New(
   626  		issuerCert.Certificate,
   627  		issuerSigner,
   628  		[]string{},
   629  	)
   630  	test.AssertNotError(t, err, "failed to create linter")
   631  	signer, err := NewIssuer(issuerCert, issuerSigner, defaultProfile(), linter, fc)
   632  	test.AssertNotError(t, err, "NewIssuer failed")
   633  	pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   634  	test.AssertNotError(t, err, "failed to generate test key")
   635  	_, issuanceToken, err := signer.Prepare(&IssuanceRequest{
   636  		PublicKey:       pk.Public(),
   637  		Serial:          []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
   638  		DNSNames:        []string{"example.com"},
   639  		NotBefore:       fc.Now(),
   640  		NotAfter:        fc.Now().Add(time.Hour - time.Second),
   641  		IncludeCTPoison: true,
   642  	})
   643  	test.AssertNotError(t, err, "Prepare failed")
   644  	precertBytes, err := signer.Issue(issuanceToken)
   645  	test.AssertNotError(t, err, "Issue failed")
   646  	precert, err := x509.ParseCertificate(precertBytes)
   647  	test.AssertNotError(t, err, "failed to parse certificate")
   648  
   649  	sctList := []ct.SignedCertificateTimestamp{
   650  		{
   651  			SCTVersion: ct.V1,
   652  			LogID:      ct.LogID{KeyID: *(*[32]byte)(mustDecodeB64("OJiMlNA1mMOTLd/pI7q68npCDrlsQeFaqAwasPwEvQM="))},
   653  		},
   654  		{
   655  			SCTVersion: ct.V1,
   656  			LogID:      ct.LogID{KeyID: *(*[32]byte)(mustDecodeB64("UtToynGEyMkkXDMQei8Ll54oMwWHI0IieDEKs12/Td4="))},
   657  		},
   658  	}
   659  
   660  	request2, err := RequestFromPrecert(precert, sctList)
   661  	test.AssertNotError(t, err, "generating request from precert")
   662  
   663  	_, issuanceToken2, err := signer.Prepare(request2)
   664  	test.AssertNotError(t, err, "preparing final cert issuance")
   665  
   666  	finalCertBytes, err := signer.Issue(issuanceToken2)
   667  	test.AssertNotError(t, err, "Issue failed")
   668  
   669  	finalCert, err := x509.ParseCertificate(finalCertBytes)
   670  	test.AssertNotError(t, err, "failed to parse certificate")
   671  
   672  	err = finalCert.CheckSignatureFrom(issuerCert.Certificate)
   673  	test.AssertNotError(t, err, "signature validation failed")
   674  	test.AssertByteEquals(t, finalCert.SerialNumber.Bytes(), []byte{1, 2, 3, 4, 5, 6, 7, 8, 9})
   675  	test.AssertDeepEquals(t, finalCert.PublicKey, pk.Public())
   676  	test.AssertEquals(t, len(finalCert.Extensions), 9) // Constraints, KU, EKU, SKID, AKID, AIA, SAN, Policies, SCT list
   677  	test.AssertDeepEquals(t, finalCert.Extensions[8], pkix.Extension{
   678  		Id: sctListOID,
   679  		Value: []byte{
   680  			4, 100, 0, 98, 0, 47, 0, 56, 152, 140, 148, 208, 53, 152, 195, 147, 45,
   681  			223, 233, 35, 186, 186, 242, 122, 66, 14, 185, 108, 65, 225, 90, 168, 12,
   682  			26, 176, 252, 4, 189, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47,
   683  			0, 82, 212, 232, 202, 113, 132, 200, 201, 36, 92, 51, 16, 122, 47, 11,
   684  			151, 158, 40, 51, 5, 135, 35, 66, 34, 120, 49, 10, 179, 93, 191, 77, 222,
   685  			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
   686  		},
   687  	})
   688  }
   689  
   690  func TestIssueMustStaple(t *testing.T) {
   691  	fc := clock.NewFake()
   692  	fc.Set(time.Now())
   693  	linter, err := linter.New(
   694  		issuerCert.Certificate,
   695  		issuerSigner,
   696  		[]string{
   697  			"w_ct_sct_policy_count_unsatisfied",
   698  			"e_scts_from_same_operator",
   699  		},
   700  	)
   701  	test.AssertNotError(t, err, "failed to create linter")
   702  	signer, err := NewIssuer(issuerCert, issuerSigner, defaultProfile(), linter, fc)
   703  	test.AssertNotError(t, err, "NewIssuer failed")
   704  	pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   705  	test.AssertNotError(t, err, "failed to generate test key")
   706  	_, issuanceToken, err := signer.Prepare(&IssuanceRequest{
   707  		PublicKey:         pk.Public(),
   708  		Serial:            []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
   709  		DNSNames:          []string{"example.com"},
   710  		IncludeMustStaple: true,
   711  		NotBefore:         fc.Now(),
   712  		NotAfter:          fc.Now().Add(time.Hour - time.Second),
   713  		IncludeCTPoison:   true,
   714  	})
   715  	test.AssertNotError(t, err, "Prepare failed")
   716  	certBytes, err := signer.Issue(issuanceToken)
   717  	test.AssertNotError(t, err, "Issue failed")
   718  	cert, err := x509.ParseCertificate(certBytes)
   719  	test.AssertNotError(t, err, "failed to parse certificate")
   720  	err = cert.CheckSignatureFrom(issuerCert.Certificate)
   721  	test.AssertNotError(t, err, "signature validation failed")
   722  	test.AssertByteEquals(t, cert.SerialNumber.Bytes(), []byte{1, 2, 3, 4, 5, 6, 7, 8, 9})
   723  	test.AssertDeepEquals(t, cert.PublicKey, pk.Public())
   724  	test.AssertEquals(t, len(cert.Extensions), 10) // Constraints, KU, EKU, SKID, AKID, AIA, SAN, Policies, Must-Staple, Poison
   725  	test.AssertDeepEquals(t, cert.Extensions[9], mustStapleExt)
   726  }
   727  
   728  func TestIssueBadLint(t *testing.T) {
   729  	fc := clock.NewFake()
   730  	fc.Set(time.Now())
   731  	lint, err := linter.New(issuerCert.Certificate, issuerSigner, []string{})
   732  	test.AssertNotError(t, err, "failed to create linter")
   733  	signer, err := NewIssuer(issuerCert, issuerSigner, defaultProfile(), lint, fc)
   734  	test.AssertNotError(t, err, "NewIssuer failed")
   735  	pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   736  	test.AssertNotError(t, err, "failed to generate test key")
   737  	_, _, err = signer.Prepare(&IssuanceRequest{
   738  		PublicKey:       pk.Public(),
   739  		Serial:          []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
   740  		DNSNames:        []string{"example-com"},
   741  		NotBefore:       fc.Now(),
   742  		NotAfter:        fc.Now().Add(time.Hour - time.Second),
   743  		IncludeCTPoison: true,
   744  	})
   745  	test.AssertError(t, err, "Prepare didn't fail")
   746  	test.AssertErrorIs(t, err, linter.ErrLinting)
   747  	test.AssertContains(t, err.Error(), "tbsCertificate linting failed: failed lint(s)")
   748  }
   749  
   750  func TestLoadChain_Valid(t *testing.T) {
   751  	chain, err := LoadChain([]string{
   752  		"../test/test-ca-cross.pem",
   753  		"../test/test-root2.pem",
   754  	})
   755  	test.AssertNotError(t, err, "Should load valid chain")
   756  
   757  	expectedIssuer, err := core.LoadCert("../test/test-ca-cross.pem")
   758  	test.AssertNotError(t, err, "Failed to load test issuer")
   759  
   760  	chainIssuer := chain[0]
   761  	test.AssertNotNil(t, chainIssuer, "Failed to decode chain PEM")
   762  
   763  	test.AssertByteEquals(t, chainIssuer.Raw, expectedIssuer.Raw)
   764  }
   765  
   766  func TestLoadChain_TooShort(t *testing.T) {
   767  	_, err := LoadChain([]string{"/path/to/one/cert.pem"})
   768  	test.AssertError(t, err, "Should reject too-short chain")
   769  }
   770  
   771  func TestLoadChain_Unloadable(t *testing.T) {
   772  	_, err := LoadChain([]string{
   773  		"does-not-exist.pem",
   774  		"../test/test-root2.pem",
   775  	})
   776  	test.AssertError(t, err, "Should reject unloadable chain")
   777  
   778  	_, err = LoadChain([]string{
   779  		"../test/test-ca-cross.pem",
   780  		"does-not-exist.pem",
   781  	})
   782  	test.AssertError(t, err, "Should reject unloadable chain")
   783  
   784  	invalidPEMFile, _ := os.CreateTemp("", "invalid.pem")
   785  	err = os.WriteFile(invalidPEMFile.Name(), []byte(""), 0640)
   786  	test.AssertNotError(t, err, "Error writing invalid PEM tmp file")
   787  	_, err = LoadChain([]string{
   788  		invalidPEMFile.Name(),
   789  		"../test/test-root2.pem",
   790  	})
   791  	test.AssertError(t, err, "Should reject unloadable chain")
   792  }
   793  
   794  func TestLoadChain_InvalidSig(t *testing.T) {
   795  	_, err := LoadChain([]string{
   796  		"../test/test-root2.pem",
   797  		"../test/test-ca-cross.pem",
   798  	})
   799  	test.AssertError(t, err, "Should reject invalid signature")
   800  	test.Assert(t, strings.Contains(err.Error(), "test-ca-cross.pem"),
   801  		fmt.Sprintf("Expected error to mention filename, got: %s", err))
   802  	test.Assert(t, strings.Contains(err.Error(), "signature from \"CN=happy hacker fake CA\""),
   803  		fmt.Sprintf("Expected error to mention subject, got: %s", err))
   804  }
   805  
   806  func TestIssuanceToken(t *testing.T) {
   807  	fc := clock.NewFake()
   808  	linter, err := linter.New(issuerCert.Certificate, issuerSigner, []string{})
   809  	test.AssertNotError(t, err, "failed to create linter")
   810  	signer, err := NewIssuer(issuerCert, issuerSigner, defaultProfile(), linter, fc)
   811  	test.AssertNotError(t, err, "NewIssuer failed")
   812  
   813  	_, err = signer.Issue(&issuanceToken{})
   814  	test.AssertError(t, err, "expected issuance with a zero token to fail")
   815  
   816  	_, err = signer.Issue(nil)
   817  	test.AssertError(t, err, "expected issuance with a nil token to fail")
   818  
   819  	pk, err := rsa.GenerateKey(rand.Reader, 2048)
   820  	test.AssertNotError(t, err, "failed to generate test key")
   821  	_, issuanceToken, err := signer.Prepare(&IssuanceRequest{
   822  		PublicKey:       pk.Public(),
   823  		Serial:          []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
   824  		DNSNames:        []string{"example.com"},
   825  		NotBefore:       fc.Now(),
   826  		NotAfter:        fc.Now().Add(time.Hour - time.Second),
   827  		IncludeCTPoison: true,
   828  	})
   829  	test.AssertNotError(t, err, "expected Prepare to succeed")
   830  	_, err = signer.Issue(issuanceToken)
   831  	test.AssertNotError(t, err, "expected first issuance to succeed")
   832  
   833  	_, err = signer.Issue(issuanceToken)
   834  	test.AssertError(t, err, "expected second issuance with the same issuance token to fail")
   835  	test.AssertContains(t, err.Error(), "issuance token already redeemed")
   836  
   837  	_, issuanceToken, err = signer.Prepare(&IssuanceRequest{
   838  		PublicKey:       pk.Public(),
   839  		Serial:          []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
   840  		DNSNames:        []string{"example.com"},
   841  		NotBefore:       fc.Now(),
   842  		NotAfter:        fc.Now().Add(time.Hour - time.Second),
   843  		IncludeCTPoison: true,
   844  	})
   845  	test.AssertNotError(t, err, "expected Prepare to succeed")
   846  
   847  	signer2, err := NewIssuer(issuerCert, issuerSigner, defaultProfile(), linter, fc)
   848  	test.AssertNotError(t, err, "NewIssuer failed")
   849  
   850  	_, err = signer2.Issue(issuanceToken)
   851  	test.AssertError(t, err, "expected redeeming an issuance token with the wrong issuer to fail")
   852  	test.AssertContains(t, err.Error(), "wrong issuer")
   853  }
   854  
   855  func TestInvalidProfile(t *testing.T) {
   856  	fc := clock.NewFake()
   857  	fc.Set(time.Now())
   858  	err := loglist.InitLintList("../test/ct-test-srv/log_list.json")
   859  	test.AssertNotError(t, err, "failed to load log list")
   860  	linter, err := linter.New(
   861  		issuerCert.Certificate,
   862  		issuerSigner,
   863  		[]string{},
   864  	)
   865  	test.AssertNotError(t, err, "failed to create linter")
   866  	signer, err := NewIssuer(issuerCert, issuerSigner, defaultProfile(), linter, fc)
   867  	test.AssertNotError(t, err, "NewIssuer failed")
   868  	pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   869  	test.AssertNotError(t, err, "failed to generate test key")
   870  	_, _, err = signer.Prepare(&IssuanceRequest{
   871  		PublicKey:       pk.Public(),
   872  		Serial:          []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
   873  		DNSNames:        []string{"example.com"},
   874  		NotBefore:       fc.Now(),
   875  		NotAfter:        fc.Now().Add(time.Hour - time.Second),
   876  		IncludeCTPoison: true,
   877  		precertDER:      []byte{6, 6, 6},
   878  	})
   879  	test.AssertError(t, err, "Invalid IssuanceRequest")
   880  
   881  	_, _, err = signer.Prepare(&IssuanceRequest{
   882  		PublicKey: pk.Public(),
   883  		Serial:    []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
   884  		DNSNames:  []string{"example.com"},
   885  		NotBefore: fc.Now(),
   886  		NotAfter:  fc.Now().Add(time.Hour - time.Second),
   887  		sctList: []ct.SignedCertificateTimestamp{
   888  			{
   889  				SCTVersion: ct.V1,
   890  				LogID:      ct.LogID{KeyID: *(*[32]byte)(mustDecodeB64("OJiMlNA1mMOTLd/pI7q68npCDrlsQeFaqAwasPwEvQM="))},
   891  			},
   892  		},
   893  		precertDER: []byte{},
   894  	})
   895  	test.AssertError(t, err, "Invalid IssuanceRequest")
   896  }
   897  
   898  // Generate a precert from one profile and a final cert from another, and verify
   899  // that the final cert errors out when linted because the lint cert doesn't
   900  // corresponding with the precert.
   901  func TestMismatchedProfiles(t *testing.T) {
   902  	fc := clock.NewFake()
   903  	fc.Set(time.Now())
   904  	err := loglist.InitLintList("../test/ct-test-srv/log_list.json")
   905  	test.AssertNotError(t, err, "failed to load log list")
   906  	linter, err := linter.New(
   907  		issuerCert.Certificate,
   908  		issuerSigner,
   909  		[]string{"n_subject_common_name_included"},
   910  	)
   911  	test.AssertNotError(t, err, "failed to create linter")
   912  
   913  	issuer1, err := NewIssuer(issuerCert, issuerSigner, defaultProfile(), linter, fc)
   914  	test.AssertNotError(t, err, "NewIssuer failed")
   915  	pk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
   916  	test.AssertNotError(t, err, "failed to generate test key")
   917  	_, issuanceToken, err := issuer1.Prepare(&IssuanceRequest{
   918  		PublicKey:       pk.Public(),
   919  		Serial:          []byte{1, 2, 3, 4, 5, 6, 7, 8, 9},
   920  		CommonName:      "example.com",
   921  		DNSNames:        []string{"example.com"},
   922  		NotBefore:       fc.Now(),
   923  		NotAfter:        fc.Now().Add(time.Hour - time.Second),
   924  		IncludeCTPoison: true,
   925  	})
   926  	test.AssertNotError(t, err, "making IssuanceRequest")
   927  
   928  	precertDER, err := issuer1.Issue(issuanceToken)
   929  	test.AssertNotError(t, err, "signing precert")
   930  
   931  	// Create a new profile that differs slightly (no common name)
   932  	profileConfig := defaultProfileConfig()
   933  	profileConfig.AllowCommonName = false
   934  	p, err := NewProfile(profileConfig, defaultIssuerConfig())
   935  	test.AssertNotError(t, err, "NewProfile failed")
   936  	issuer2, err := NewIssuer(issuerCert, issuerSigner, p, linter, fc)
   937  	test.AssertNotError(t, err, "NewIssuer failed")
   938  
   939  	sctList := []ct.SignedCertificateTimestamp{
   940  		{
   941  			SCTVersion: ct.V1,
   942  			LogID:      ct.LogID{KeyID: *(*[32]byte)(mustDecodeB64("OJiMlNA1mMOTLd/pI7q68npCDrlsQeFaqAwasPwEvQM="))},
   943  		},
   944  		{
   945  			SCTVersion: ct.V1,
   946  			LogID:      ct.LogID{KeyID: *(*[32]byte)(mustDecodeB64("UtToynGEyMkkXDMQei8Ll54oMwWHI0IieDEKs12/Td4="))},
   947  		},
   948  	}
   949  
   950  	precert, err := x509.ParseCertificate(precertDER)
   951  	test.AssertNotError(t, err, "parsing precert")
   952  
   953  	request2, err := RequestFromPrecert(precert, sctList)
   954  	test.AssertNotError(t, err, "RequestFromPrecert")
   955  	request2.CommonName = ""
   956  
   957  	_, _, err = issuer2.Prepare(request2)
   958  	test.AssertError(t, err, "preparing final cert issuance")
   959  	test.AssertContains(t, err.Error(), "precert does not correspond to linted final cert")
   960  }
   961  

View as plain text