Exemple #1
0
func TestAddPoliciesWithQualifiers(t *testing.T) {
	var cert x509.Certificate
	addPolicies(&cert, []config.CertificatePolicy{
		{
			ID: config.OID([]int{1, 2, 3, 4}),
			Qualifiers: []config.CertificatePolicyQualifier{
				{
					Type:  "id-qt-cps",
					Value: "http://example.com/cps",
				},
				{
					Type:  "id-qt-unotice",
					Value: "Do What Thou Wilt",
				},
			},
		},
	})

	if len(cert.ExtraExtensions) != 1 {
		t.Fatal("No extension added")
	}
	ext := cert.ExtraExtensions[0]
	if !reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 32}) {
		t.Fatal(fmt.Sprintf("Wrong OID for policy qualifier %v", ext.Id))
	}
	if ext.Critical {
		t.Fatal("Policy qualifier marked critical")
	}
	expectedBytes, _ := hex.DecodeString("304e304c06032a03043045302206082b060105050702011616687474703a2f2f6578616d706c652e636f6d2f637073301f06082b0601050507020230130c11446f20576861742054686f752057696c74")
	if !bytes.Equal(ext.Value, expectedBytes) {
		t.Fatal(fmt.Sprintf("Value didn't match expected bytes: %s vs %s",
			hex.EncodeToString(ext.Value), hex.EncodeToString(expectedBytes)))
	}
}
Exemple #2
0
func TestAddPolicies(t *testing.T) {
	var cert x509.Certificate
	addPolicies(&cert, []config.CertificatePolicy{
		{
			ID: config.OID([]int{1, 2, 3, 4}),
		},
	})

	if len(cert.ExtraExtensions) != 1 {
		t.Fatal("No extension added")
	}
	ext := cert.ExtraExtensions[0]
	if !reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 32}) {
		t.Fatal(fmt.Sprintf("Wrong OID for policy qualifier %v", ext.Id))
	}
	if ext.Critical {
		t.Fatal("Policy qualifier marked critical")
	}
	expectedBytes, _ := hex.DecodeString("3007300506032a0304")
	if !bytes.Equal(ext.Value, expectedBytes) {
		t.Fatal(fmt.Sprintf("Value didn't match expected bytes: got %s, expected %s",
			hex.EncodeToString(ext.Value), hex.EncodeToString(expectedBytes)))
	}
}
Exemple #3
0
func TestExtensionSign(t *testing.T) {
	csrPEM, err := ioutil.ReadFile(testCSR)
	if err != nil {
		t.Fatalf("%v", err)
	}

	s := newCustomSigner(t, testECDSACaFile, testECDSACaKeyFile)

	// By default, no extensions should be allowed
	request := signer.SignRequest{
		Request: string(csrPEM),
		Extensions: []signer.Extension{
			signer.Extension{ID: config.OID(asn1.ObjectIdentifier{1, 2, 3, 4})},
		},
	}

	_, err = s.Sign(request)
	if err == nil {
		t.Fatalf("expected a policy error")
	}

	// Whitelist a specific extension.  The extension with OID 1.2.3.4 should be
	// allowed through, but the one with OID 1.2.3.5 should not.
	s.policy = &config.Signing{
		Default: &config.SigningProfile{
			Usage:              []string{"cert sign", "crl sign"},
			ExpiryString:       "1h",
			Expiry:             1 * time.Hour,
			CA:                 true,
			ExtensionWhitelist: map[string]bool{"1.2.3.4": true},
		},
	}

	// Test that a forbidden extension triggers a sign error
	request = signer.SignRequest{
		Request: string(csrPEM),
		Extensions: []signer.Extension{
			signer.Extension{ID: config.OID(asn1.ObjectIdentifier{1, 2, 3, 5})},
		},
	}

	_, err = s.Sign(request)
	if err == nil {
		t.Fatalf("expected a policy error")
	}

	extValue := []byte{0x05, 0x00}
	extValueHex := hex.EncodeToString(extValue)

	// Test that an allowed extension makes it through
	request = signer.SignRequest{
		Request: string(csrPEM),
		Extensions: []signer.Extension{
			signer.Extension{
				ID:       config.OID(asn1.ObjectIdentifier{1, 2, 3, 4}),
				Critical: false,
				Value:    extValueHex,
			},
		},
	}

	certPEM, err := s.Sign(request)
	if err != nil {
		t.Fatalf("%v", err)
	}

	cert, err := helpers.ParseCertificatePEM(certPEM)
	if err != nil {
		t.Fatalf("%v", err)
	}

	foundAllowed := false
	for _, ext := range cert.Extensions {
		if ext.Id.String() == "1.2.3.4" {
			foundAllowed = true

			if ext.Critical {
				t.Fatalf("Extensions should not be marked critical")
			}

			if !bytes.Equal(extValue, ext.Value) {
				t.Fatalf("Extension has wrong value: %s != %s", hex.EncodeToString(ext.Value), extValueHex)
			}
		}
	}
	if !foundAllowed {
		t.Fatalf("Custom extension not included in the certificate")
	}
}
)

// OID and fixed value for the "must staple" variant of the TLS Feature
// extension:
//
//  Features ::= SEQUENCE OF INTEGER                  [RFC7633]
//  enum { ... status_request(5) ...} ExtensionType;  [RFC6066]
//
// DER Encoding:
//  30 03 - SEQUENCE (3 octets)
//  |-- 02 01 - INTEGER (1 octet)
//  |   |-- 05 - 5
var (
	mustStapleFeatureValue = []byte{0x30, 0x03, 0x02, 0x01, 0x05}
	mustStapleExtension    = signer.Extension{
		ID:       cfsslConfig.OID(oidTLSFeature),
		Critical: false,
		Value:    hex.EncodeToString(mustStapleFeatureValue),
	}
)

// Metrics for CA statistics
const (
	// Increments when CA observes an HSM or signing error
	metricSigningError = "CA.SigningError"
	metricHSMError     = metricSigningError + ".HSMError"

	// Increments when CA handles a CSR requesting a "basic" extension:
	// authorityInfoAccess, authorityKeyIdentifier, extKeyUsage, keyUsage,
	// basicConstraints, certificatePolicies, crlDistributionPoints,
	// subjectAlternativeName, subjectKeyIdentifier,
func setup(t *testing.T) *testCtx {
	fc := clock.NewFake()
	fc.Add(1 * time.Hour)

	pa, err := policy.New(nil)
	test.AssertNotError(t, err, "Couldn't create PA")
	err = pa.SetHostnamePolicyFile("../test/hostname-policy.json")
	test.AssertNotError(t, err, "Couldn't set hostname policy")

	// Create a CA
	caConfig := cmd.CAConfig{
		RSAProfile:   rsaProfileName,
		ECDSAProfile: ecdsaProfileName,
		SerialPrefix: 17,
		Expiry:       "8760h",
		LifespanOCSP: cmd.ConfigDuration{Duration: 45 * time.Minute},
		MaxNames:     2,
		DoNotForceCN: true,
		CFSSL: cfsslConfig.Config{
			Signing: &cfsslConfig.Signing{
				Profiles: map[string]*cfsslConfig.SigningProfile{
					rsaProfileName: {
						Usage:     []string{"digital signature", "key encipherment", "server auth"},
						CA:        false,
						IssuerURL: []string{"http://not-example.com/issuer-url"},
						OCSP:      "http://not-example.com/ocsp",
						CRL:       "http://not-example.com/crl",

						Policies: []cfsslConfig.CertificatePolicy{
							{
								ID: cfsslConfig.OID(asn1.ObjectIdentifier{2, 23, 140, 1, 2, 1}),
							},
						},
						ExpiryString: "8760h",
						Backdate:     time.Hour,
						CSRWhitelist: &cfsslConfig.CSRWhitelist{
							PublicKeyAlgorithm: true,
							PublicKey:          true,
							SignatureAlgorithm: true,
						},
						ClientProvidesSerialNumbers: true,
						AllowedExtensions: []cfsslConfig.OID{
							cfsslConfig.OID(oidTLSFeature),
						},
					},
					ecdsaProfileName: {
						Usage:     []string{"digital signature", "server auth"},
						CA:        false,
						IssuerURL: []string{"http://not-example.com/issuer-url"},
						OCSP:      "http://not-example.com/ocsp",
						CRL:       "http://not-example.com/crl",

						Policies: []cfsslConfig.CertificatePolicy{
							{
								ID: cfsslConfig.OID(asn1.ObjectIdentifier{2, 23, 140, 1, 2, 1}),
							},
						},
						ExpiryString: "8760h",
						Backdate:     time.Hour,
						CSRWhitelist: &cfsslConfig.CSRWhitelist{
							PublicKeyAlgorithm: true,
							PublicKey:          true,
							SignatureAlgorithm: true,
						},
						ClientProvidesSerialNumbers: true,
					},
				},
				Default: &cfsslConfig.SigningProfile{
					ExpiryString: "8760h",
				},
			},
		},
	}

	stats := mocks.NewStatter()

	issuers := []Issuer{{caKey, caCert}}

	keyPolicy := core.KeyPolicy{
		AllowRSA:           true,
		AllowECDSANISTP256: true,
		AllowECDSANISTP384: true,
	}

	return &testCtx{
		caConfig,
		pa,
		issuers,
		keyPolicy,
		fc,
		stats,
	}
}