Okay, I'm going to come in swinging (sorry!) by saying that I don't think something like what is proposed here should be standardized. I think the overall idea is a good one, and very well motivated and obviously well intentioned, but there are a few things that make this specific idea not the right direction to go. I'll talk a little bit about why that is, and then suggest the direction we should be going in instead.
Let's Encrypt intends to do this in the very near future.
I think that this line gets at the core of why this proposal is not the right direction. This is confusing two very different concepts: what chains are available, and what profiles are available. The profile affects the actual contents of your end-entity cert: being signed by an ECDSA intermediate means you have a different signature algorithm. The chain just affects the certs above your end-entity, such as whether you present X2-signed-by-X1 or X2-self-signed.
And much of the follow-on conversation here has the same issue, unfortunately. The difference between X1 and X2 is generally just a matter of chains, yes, but the difference between E1 and R3 is not, and should not be confused with merely chain selection.
How would one define a "Type"? Is it always going to be just RSA and ECDSA? What about when Ed25519 finally gets allowed? What if people want other things (like KEM certificates)? What if people want EV certificates (not from LE, but from some other ACME server) -- does that count as a Type? Even if that CA only issues EV from a subset of their intermediates?
If this field is super strictly limited, then it becomes difficult to extend. If it is wide-open, it becomes non-machine-readable.
This list is really the core of the issue here: there are many different criteria that a client might want to know about ahead of time and select. Too many. A smart CA doesn't actually want to let clients select any combination of these attributes, because some combinations are useless, or worse, disallowed. Today, the mechanism for selecting things like this is the CSR (that's how we determine that the client wants OCSP must-staple), but CSRs are bad for this because CAs consistently make mistakes regarding copying values directly from the CSR to the final cert. And we don't really want to balloon the newOrder request with a dozen different fields, which will obviously be a mis-prediction of which fields are actually useful (observe: the notBefore and notAfter fields in the newOrder request today, which we ignore).
So, what should we do instead?
I already have a private draft of what follows, which I intend to share with the IETF ACME WG in the near future. I've been talking through this plan with other folks here and at other ACME CAs for a while now and we think this is the best -- simple, obvious, flexible, minimal -- path forward.
Profile Selection. The Directory's Meta object gets a new sub-field listing the available profiles. Each profile has a name and either a short text description or a URL pointing at a documentation page (we're not sure which is better yet).
HTTP/1.1 200 OK
Content-Type: application/json
{
"newNonce": "https://example.com/acme/new-nonce",
"newAccount": "https://example.com/acme/new-account",
"newOrder": "https://example.com/acme/new-order",
"newAuthz": "https://example.com/acme/new-authz",
"revokeCert": "https://example.com/acme/revoke-cert",
"keyChange": "https://example.com/acme/key-change",
"meta": {
"termsOfService": "https://example.com/acme/terms/2017-5-30",
"website": "https://www.example.com/",
"caaIdentities": ["example.com"],
"externalAccountRequired": false,
"profiles": {
"default": "The profile that Let's Encrypt has been using for the last 6+ years.",
"short": "The same as 'default', but with a validity period of 10 days.",
"minimal": "A stripped-down profile with a short lifetime, no OCSP, no keyEncipherment KU, no clientAuth EKU, etc."
}
}
}
The client exposes these options and their descriptions to its operator, who selects one (e.g. by putting the profile name in a config file). The client then includes that profile name in a new field of the newOrder request.
POST /acme/new-order HTTP/1.1
Host: example.com
Content-Type: application/jose+json
{
"protected": base64url({
"alg": "ES256",
"kid": "https://example.com/acme/acct/evOfKhNU60wg",
"nonce": "5XJ1L3lEkMG7tR6pA00clA",
"url": "https://example.com/acme/new-order"
}),
"payload": base64url({
"identifiers": [
{ "type": "dns", "value": "www.example.org" },
{ "type": "dns", "value": "example.org" }
],
"profile": "minimal"
}),
"signature": "H6ZXtGjTZyUnPeKn...wEA4TklBdh3e454g"
}
That's basically it. There are obviously details (which profile is used if none is indicated?) but this mechanism gets both CAs and clients 90+% of what they need to more formally advertise, negotiate, and configure different issuance options.