Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Profiles: allow for omission of KU, EKU, and SKID #7622

Merged
merged 4 commits into from
Jul 31, 2024
Merged

Conversation

aarongable
Copy link
Contributor

@aarongable aarongable commented Jul 20, 2024

Add three new keys to the CA's ProfileConfig:

  • OmitKeyEncipherment causes the keyEncipherment Key Usage to be omitted from certificates with RSA public keys. We currently include it for backwards compatibility with TLS 1.1 servers that don't support modern cipher suites, but this KU is completely useless as of TLS 1.3.
  • OmitClientAuth causes the tlsClientAuthentication Extended Key Usage to be omitted from all certificates. We currently include it to support any subscribers who may be relying on it, but Root Programs are moving towards single-purpose hierarchies and its inclusion is being discouraged.
  • OmitSKID causes the Subject Key Identifier extension to be omitted from all certificates. We currently include this extension because it is recommended by RFC 5280, but it serves little to no practical purpose and consumes a large number of bytes, so it is now NOT RECOMMENDED by the Baseline Requirements.

Make substantive changes to issuer.requestValid and issuer.Prepare to implement the desired behavior for each of these options. Make a very slight change to ra.matchesCSR to generally allow for serverAuth-only EKUs. Improve the unit tests of both the //ca and //issuance packages to cover the new behavior.

Part of #7610
No config changes at this time; they will be made as part of #7309

Base automatically changed from profile-determines-expiry to main July 25, 2024 20:47
@aarongable aarongable marked this pull request as ready for review July 26, 2024 00:14
@aarongable aarongable requested a review from a team as a code owner July 26, 2024 00:14
@aarongable aarongable requested a review from jsha July 26, 2024 00:14
@aarongable
Copy link
Contributor Author

aarongable commented Jul 26, 2024

I have used a locally-modified version of the eggsampler/acme client (capable of specifying a profile name in newOrder requests) to implement an integration test covering this new behavior:

// TestIssuanceProfiles verifies that profile selection works, and results in
// measurable differences between certificates issued under different profiles.
// It does not test the omission of the keyEncipherment KU, because all of our
// integration test framework assumes ECDSA pubkeys for the sake of speed,
// and ECDSA certs don't get the keyEncipherment KU in either profile.
func TestIssuanceProfiles(t *testing.T) {
	t.Parallel()

	// Create an account.
	client, err := makeClient("mailto:example@letsencrypt.org")
	test.AssertNotError(t, err, "creating acme client")

	profiles := client.Directory().Meta.Profiles
	if len(profiles) < 2 {
		t.Fatal("ACME server not advertising multiple profiles")
	}

	// Create a private key.
	key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	test.AssertNotError(t, err, "creating random cert key")

	// Create a set of identifiers to request.
	names := []string{random_domain()}

	// Get one cert for each profile that we know the test server advertises.
	res, err := authAndIssue(client, key, names, true, "legacy")
	test.AssertNotError(t, err, "failed to issue under legacy profile")
	test.AssertEquals(t, res.Order.Profile, "legacy")
	legacy := res.certs[0]

	res, err = authAndIssue(client, key, names, true, "modern")
	test.AssertNotError(t, err, "failed to issue under modern profile")
	test.AssertEquals(t, res.Order.Profile, "modern")
	modern := res.certs[0]

	// Check that each profile worked as expected.
	test.AssertEquals(t, legacy.Subject.CommonName, names[0])
	test.AssertEquals(t, modern.Subject.CommonName, "")

	test.AssertDeepEquals(t, legacy.ExtKeyUsage, []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth})
	test.AssertDeepEquals(t, modern.ExtKeyUsage, []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth})

	test.AssertEquals(t, len(legacy.SubjectKeyId), 20)
	test.AssertEquals(t, len(modern.SubjectKeyId), 0)
}

This test passes with one additional modification: configuring the CA to also ignore the w_ext_subject_key_identifier_missing_sub_cert lint. This leads me to believe that we probably want our ignored lints to be configured on a per-profile basis, so I will begin on that work soon.

edit: I have now made per-profile lints.

@letsencrypt letsencrypt deleted a comment from github-actions bot Jul 26, 2024
@letsencrypt letsencrypt deleted a comment from github-actions bot Jul 26, 2024
Copy link
Contributor

@aarongable, this PR appears to contain configuration and/or SQL schema changes. Please ensure that a corresponding deployment ticket has been filed with the new values.

Copy link
Contributor

@jsha jsha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some small changes, otherwise good!

ca/ca.go Outdated Show resolved Hide resolved
ra/ra.go Outdated Show resolved Hide resolved
@aarongable aarongable merged commit c6c7617 into main Jul 31, 2024
14 checks passed
@aarongable aarongable deleted the profile-modernity branch July 31, 2024 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants