lamps-wg / cmp-updates

RFC4210bis and RFC6712bis
Other
2 stars 5 forks source link

Identifying private key when using EnvelopedData for indirect POPO #62

Closed rajeev-0 closed 3 weeks ago

rajeev-0 commented 1 month ago

When using EnvelopedData with encrypted certificate (section 5.2.2) for indirect POPO (section 5.2.8.3.2), RecipientIdentifier in KeyTransRecipientInfo (RFC 5652, section 6.2.1 ) and KEMRecipientInfo (draft-ietf-lamps-cms-kemri-08, section 3) can not be used by client to identify the corresponding private key for obtaining content-encryption key (CEK). So an alternative should be provided for matching the cert response (containing EnvelopedData with encrypted certificate) to corresponding private key.

One suggestion would be to add a note in section 5.2.2 stating: When using certificate in encrypted form for indirect POP, client should use transactionID and certReqId to identify the corresponding private key for decrypting the content-encryption key.

HBrock commented 1 month ago

Indirect POP is specifically relevant for KEM keys. I posted a question on this topic to the LAMPS email list. In any case if Indirect POP is used, also with key agreement, the certificate is delivered in encrypted form and the recipient has no knowledge of issuerAndSerialNumber or subjectKeyIdentifier before decrypting it. Therefore, the note is specific to Indirect POP and we should consider adding it to Section 5.2.8.3.2.

HBrock commented 1 month ago

An additional paragraphe to Section 5.2.8.3.2 could be: "Note that in some cases CMS enveloped data uses issuerAndSerialNumber or subjectKeyIdentifier to specify the recipient's certificate, and thereby the recipient's public key, that was used to generate the key-encryption key. In the indirect method, the specified recipient's certificate is delivered in encrypted form and therefore the recipient cannot use issuerAndSerialNumber or subjectKeyIdentifier to identify the private key for decrypting the key-encryption key. Alternatively the recipient should use transactionID and certReqId."

rajeev-0 commented 1 month ago

I agree, it should be added to Section 5.3.8.3.2.

HBrock commented 1 month ago

Russ proposed to use a key identifyer, see https://mailarchive.ietf.org/arch/msg/spasm/0xuq496AV-pkyiAF2kqvOTi0-uI/

HBrock commented 1 month ago

Russ proposes to specify method 4) from RFC 7093 Section 2 (https://datatracker.ietf.org/doc/html/rfc7093#section-2) to use with SHA-256 for the CMS recipient identifier in RecipienInfo.

An additional paragraphe to Section 5.2.8.3.2 could be: "Note that when using CMS EnvelopedData to deliver the newly issued certificate in encrypted form, the sender requires to let the recipient know which key was used to protect the certificate. All RecipientInfo types, except PasswordRecipientInfo, offer two choices to specify the recipient's certificate, and thereby the recipient's public key, that was used to protect the content-encryption key. As long as the newly issued certificate was not decrypted, the recipient cannot use any content of that certificate to identify this key. Therefore, the sender and recipient MUST use a SHA-256 hash of the DER encoding of a SubjectPublicKeyInfo value in the SubjectKeyIdentifier choice of RecipientIdentifier, which uses method 4 from RFC 7093 Section 2, to identify the key that was used by the sender to protect the content-encryption key."

@DDvO What do you think?

DDvO commented 1 month ago

I suggest the following wording for enhanced explanation and preciseness:

"As always when using CMS EnvelopedData to deliver encrypted content, the sender needs to let the recipient know which asymmetric key was used for the encryption. Usually this is done by identifying a certificate of the recipient using the issuer and serial number fields or the subject key identifier field contained in the certificate. Yet in the case of encrypting the newly issued certificate with the public key contained in that certificate, the recipient cannot use any of these fields because it does not yet have access to them before decrypting the certificate. To solve this problem, an identifier needs to be chosen that can be computed by both the sender and the recipient without knowing the newly issued certificate. Method 4 from RFC 7093 Section 2 with SHA-256 SHALL be applied. That is, the RecipientIdentifier MUST contain the subjectKeyIdentifier choice, with its value being the SHA-256 hash for the DER encoding of the SubjectPublicKeyInfo contained in the certificate signing request."

HBrock commented 1 month ago

Thank you David, I took some of you proposaly. "Note that when delivering the newly issued certificate in encrypted form, the sender requires to let the recipient know which (private) key to use when decrypting the certificate. For asymmetric keys, CMS EnvelopedData is identifying a certificate of the recipient using the issuer and serial number fields or the subject key identifier field contained in the certificate to identify this key pair. As the recipient receives the newly issued certificate in encrypted form, the recipient cannot use any content of that certificate for identifying the private key to utilize for decryption. Therefore, the sender and recipient MUST use a SHA-256 hash of the DER encoding of the SubjectPublicKeyInfo contained in the certificate signing request to fill in the SubjectKeyIdentifier choice of RecipientIdentifier. This utilizes SHA-256 with method 4 from RFC 7093 Section 2."

HBrock commented 1 month ago

What is the best way to identify the newly generated key pair to use for decrypting the EnvelopedData containing the new certificate using

The first procedure only affects the recipient and not the sender of the message.

johngray-dev commented 1 month ago

I like the second option, as it makes no assumptions on how an implementation may need to use the transactionID or certReqId.

I combined the text you and Daivd suggest above Hendrik:

When delivering the newly issued certificate in encrypted form, the sender needs to let the recipient know which asymmetric private key to use when decrypting the certificate. Normally the recipients private key is identified by using the issuer and serial number or subject key identifier fields contained in its associated public certificate, but this is not possible when the certificate itself is received in encrypted form. Therefore, the sender and recipient MUST use a SHA-256 hash of the DER encoding of the SubjectPublicKeyInfo contained in the certificate signing request to fill in the SubjectKeyIdentifier choice of RecipientIdentifier. This utilizes SHA-256 with method 4 from RFC 7093 Section 2.

DDvO commented 1 month ago

To me, the first option appears best for two reasons.

HBrock commented 1 month ago

Thank you for your proposals. I see @russhousley, @rajeev-0, and @johngray-dev in favor of the second option and @DDvO in favor of the first option. @primetomas, @dghgit, and @ralienpp, is there anything you want to add? Does anyone wants to comment on @DDvO arguments?

It would be great to conclude on this topic before the submission-cutoff for next IETF.

dghgit commented 1 month ago

I'd also go with the second.

It's true the receiver could try winging it, but it's always good to have a sanity check.

HBrock commented 1 month ago

I missed the feedback from @primetomas on email. I copied the text in this comment below. But I do not see a clear preference for one or the other option.

"I did see that question. As you noted, any method that the client and server can generate independently without the client needing to receive the full response would work. Transaction and reqID are well known in CMP, and mandatory, so should be easy to use Rec keyid may be useful for carrier pidgeon transport, if the client looses state?

For implementation i think it's helpful to specify a mandatory option to avoid making it more complex than it is for clients and servers, having to implement lots of checks for different possibilities.

Regards, Tomas"

HBrock commented 1 month ago

I am definitely planning for a clear specification and normative text her to prevent the implementations check for different options. Currently I do see a clear preference for option 2 using the SHA-256 hash of the DER-encoded SubjectPublicKey structure as recipient key identifier. I also like the text proposed by @johngray-dev.

Does anyone still want to respond to @DDvO points in order to convince him?

DDvO commented 1 month ago

Transaction and reqID are well known in CMP, and mandatory, so should be easy to use

Yes, they are.

Rec keyid may be useful for carrier pidgeon transport, if the client looses state?

If the client ever loses its transaction state, it would be lost anyway. (And BTW this does not happen practice - I can say this with nearly 10 years of experience with various CMP clients.)

So the first option is most painless and pretty much a no-brainer for both clients and server. Update: I meanwhile had a look at the OpenSSL CMS documentation and implementation and found that for all key management techniques supported so far (which does not yet include KEM), it is assumed that the private key to use for decryption is pre-determined (by the application layer calling CMS, which in our case is CMP).

It's true the receiver could try winging it, but it's always good to have a sanity check.

I do not see the need for an extra sanity check (using a key identifier or the like). The client knows for sure which key(s) it used in the request.

HBrock commented 1 month ago

@DDvO I see you point. Thank you for explaining it further.

@russhousley @rajeev-0 @johngray-dev @DDvO @primetomas @dghgit @ralienpp @ounsworth @carl-wallace How do we get to a conclusion now?

@russhousley Is there a procedure to reach consensus?

DDvO commented 1 month ago

The origin of this issue is that all respective texts so far (more or less) assume that the recipient/receiver already has (direct access to) a certificate that is used to (indirectly) refer to the key to use for decryption:

recipient's certificate with an algorithm identifier and a public key that supports key encapsulation mechanism and where any given key usage extension allows keyEncipherment: The content-encryption key will be protected using the key management technique for KEM keys, as specified in [I-D.ietf-lamps-cms-kemri].

rid specifies the recipient's certificate or key that was used by the originator with the KEM Encapsulate() function. The RecipientIdentifier provides two alternatives for specifying the recipient's certificate [RFC5280], and thereby the recipient's public key. The recipient's certificate MUST contain a KEM public key. Therefore, a recipient X.509 version 3 certificate that contains a key usage extension MUST assert the keyEncipherment bit. The issuerAndSerialNumber alternative identifies the recipient's certificate by the issuer's distinguished name and the certificate serial number; the subjectKeyIdentifier alternative identifies the recipient's certificate by a key identifier. When an X.509 certificate is referenced, the key identifier matches the X.509 subjectKeyIdentifier extension value. When other certificate formats are referenced, the documents that specify the certificate format and their use with the CMS must include details on matching the key identifier to the appropriate certificate field. For recipient processing, implementations MUST support both of these alternatives for specifying the recipient's certificate. For originator processing, implementations MUST support at least one of these alternatives.

rid specifies the recipient's certificate or key that was used by the sender to protect the content-encryption key. The content- encryption key is encrypted with the recipient's public key. The RecipientIdentifier provides two alternatives for specifying the recipient's certificate, and thereby the recipient's public key. The recipient's certificate must contain a key transport public key. Therefore, a recipient X.509 version 3 certificate that contains a key usage extension MUST assert the keyEncipherment bit. The issuerAndSerialNumber alternative identifies the recipient's certificate by the issuer's distinguished name and the certificate serial number; the subjectKeyIdentifier identifies the recipient's certificate by a key identifier. When an X.509 certificate is referenced, the key identifier matches the X.509 subjectKeyIdentifier extension value. When other certificate formats are referenced, the documents that specify the certificate format and their use with the CMS must include details on matching the key identifier to the appropriate certificate field. For recipient processing, implementations MUST support both of these alternatives for specifying the recipient's certificate. For sender processing, implementations MUST support at least one of these alternatives.

It would be good if these were extended to explicitly describe or reference a proper handling of the case where the sender directly references a public key (rather than a certificate), providing a default method for computing the SubjectKeyIdentifier. BTW, when using the subjectKeyIdentifier choice, my preference would be to use from RFC 7093 Section 2 not method 4, but method 1 because it is simpler (does not use an extra level of DER encoding) and already implies the use of SHA256. Anyway, note that for the specific use case of identifying a public key for CMS encryption, the old method using 160-bit SHA-1 as described in RFC 5280 would still work perfectly fine as well.

If this is done in KEMRI section 3, I'd be fine with using the second option here because then for both sides a default way of directly referencing a key via a SubjectKeyIdentfier is defined already at CMS level, and doing the key selection at application level (using CMP transaction details) is then clearly not needed. Then it will be sufficient to require (and explain why, as already suggested) that for the special use case of sending an encrypted cert, the subjectKeyIdentifier choice of the RecipientIdentifier MUST be used, applying the default method of computing the key identifier value.

DDvO commented 1 month ago

On further thoughts, I've extended the text and revised the final part of my most recent comment.

DDvO commented 1 month ago

Is anyone aware of a CMS implementation that already provides the possibility for a sender application to specify the RecipientIdentifier in a way independent of a recipient certificate?

OpenSSL does not. So when adding KEM support, going for option 2, this would be required to add to the implementation.

DDvO commented 1 month ago

Is anyone aware of a CMS implementation that does not provide a way for the receiver application to pre-select the private key to use for decryption?

For the key management mechanisms so far supported by OpenSSL, this is the only way to do it.

And does anyone know of a CMS implementation that enables the receiver to hand in a key identifier for an asymmetric key that is independent of a cert?

OpenSSL does not.

One can in addition provide a related certificate, which is then used for a sanity check matching the cert with the RecipientIdentifier(s), but so far no sanity check is implemented that works without a certificate - the existing implementation does the same thing that the hitherto CMS spec(s) assume: they take the SubjectKeyIdentifier from any cert provided by the application.

carl-wallace commented 1 month ago

I've written code that allows for searching a key store for a match against a recipient identifier and code that allows pre-selection. I have not written code that allows for creation of a recipient identifier independent of a certificate, but that's not the case here. The server has the cert.

Why is a SKID calculated per a standard mechanism a problem? The server will have the certificate, the client will not, but will have the public key and can calculate the SKID. As has been noted many times in this thread, in the common case there is only one key that makes sense for the client to use and a SKID calculated on the key can provide a sanity check for folks that want it. Folks who don't want it, can wing it. I am missing what the issue is.

russhousley commented 1 month ago

@Hendrik: Consensus will not be determined in a GitHub issue discussion. You have two ways forward. You either describe the alternatives in a message to the mail list or you pick one and put it in the document. The first one allows for a very narrow discussion. The second one has the possibility of discussing this issue and others at the same time.

DDvO commented 1 month ago

I've written code that allows for searching a key store for a match against a recipient identifier and code that allows pre-selection. I have not written code that allows for creation of a recipient identifier independent of a certificate, but that's not the case here. The server has the cert.

Sure the sender/server has the cert, but the client/recipient does not (yet) know it before decrypting it, for which it needs to determine which key to use in advance. So any key identification based on the cert contents does not work (yet).

In my opinion it is sufficient and clearly more straightforward to use the first option suggested to determine the right key to use at application level, independent of the CMS level. This effectively ignores the identifier inserted by the sender.

Why is a SKID calculated per a standard mechanism a problem? The server will have the certificate, the client will not, but will have the public key and can calculate the SKID. As has been noted many times in this thread, in the common case there is only one key that makes sense for the client to use and a SKID calculated on the key can provide a sanity check for folks that want it. Folks who don't want it, can wing it. I am missing what the issue is.

As there is no such thing as the SKID of a given public key (there are just more or less common ways of computing some useful SKID) and the method is not made explicit, the receiver would not know which method to use for computing it.

The suggested second option would provide a unique way for computing a specific SKID. Yet this makes things more complicated for implementations with no real gain (just a pretty redundant sanity checking).

carl-wallace commented 1 month ago

Sure the sender/server has the cert, but the client/recipient does not (yet) know it before decrypting it

If the SKID value can be calculated from the public key via a mechanism that assures both the client and the server arrive at the same value, how does it matter that the client does not have the cert? The client obviously has the public key value because it generated the public key value.

the receiver would not know which method to use for computing it

The point is that the authors of this spec write down how to compute it. There are not "more or less common ways", you pick one and write it down.

I think you are saying is that if you assume that SKIDs can be any old value that the server elects and the client cannot know the value and thus cannot avail itself of this sanity check. This is true. So don't do that. Either codify a way to calculate the SKID when using this new spec or elect to not have a sanity check.

If you are electing to allow the server a free hand in choosing SKID values (or to use issuer/serial recipient key identifier) then you are either sacrificing the sanity check or you are adding a new recipient identifier choice (based on transaction ID or something else). I think you are electing to not have a sanity check. That may be OK, write it down. To my eye, the simplest path is to not allow the server a free hand in choosing SKID values.

DDvO commented 1 month ago

Sure the sender/server has the cert, but the client/recipient does not (yet) know it before decrypting it

If the SKID value can be calculated from the public key via a mechanism that assures both the client and the server arrive at the same value, how does it matter that the client does not have the cert? The client obviously has the public key value because it generated the public key value.

Sure this works, and is what has been suggested as the 2nd option.

the receiver would not know which method to use for computing it

The point is that the authors of this spec write down how to compute it. There are not "more or less common ways", you pick one and write it down.

Yes, but as I've been conveying to those favouring this approach, this comes at extra cost: It needs to be specified that a certain method has to be used, this needs to be implemented on both sender and receiver side (and there is also a minor computational penalty computing the DER encoding and hash value).

I think you are saying is that if you assume that SKIDs can be any old value that the server elects and the client cannot know the value and thus cannot avail itself of this sanity check. This is true. So don't do that. Either codify a way to calculate the SKID when using this new spec or elect to not have a sanity check.

Basically yes (though in theory even when not going for the 2nd suggested option, after the receiver decrypted the cert, it could do the sanity check in retrospect, yet in this case the CMS level has already been left, which would make it more hard to do at that point, and IMO the benefit of the sanity check is negligible).

If you are electing to allow the server a free hand in choosing SKID values (or to use issuer/serial recipient key identifier) then you are either sacrificing the sanity check or you are adding a new recipient identifier choice (based on transaction ID or something else). I think you are electing to not have a sanity check. That may be OK, write it down. To my eye, the simplest path is to not allow the server a free hand in choosing SKID values.

Yes, this is my preference and also my advice from implementer's perspective: let the server do whatever it is accustomed to do providing any (direct or indirect) key identifier, and the receiver simply ignores it. This is sufficient and does not require extra specification effort, and - more importantly - no extra implementation effort.

DDvO commented 1 month ago

In fact, the choice to make is not whether to use

but whether to use only the first item or in addition also the second item. This is because, in practice, the CMP client will always have to tell the CMS library/layer which private key (it expects the CMS layer) to use for decrypting the CMS encrypted cert.

The only thing the CMS lib may do in case the section item is implemented is to (sanity-)check in addition that the received RecipientIdentifier agrees with that.

Yet even if this check is performed, such that it gets confirmed that sender and receiver agree on the key to use for decryption, this is not sufficient to guarantee that the decryption works fine (because many other things may have gone wrong). So anyway the decrypted cert will need to be sanity-checked, at the latest at application level. And when this succeeds, among others the correct choice of the decryption key is indirectly confirmed. This is why I see (little to) no real value in spending the effort to come up with a RecipientIdentifier that the receiver can use to sanity-check in advance the agreement on the decryption key.

Also note that the CMS encryption is part of a CMP message, the origin of which will already have been verified by the receiver before it involves the CMS lib. So at this point it is already clear that the encrypting party is authorised to send CMP messages with responses that ask for indirect POP by cert decryption, and thus we do not need to defend at CMS level against nifty decryption oracle attacks or the like.

HBrock commented 3 weeks ago

This issue was solved with V12