mpeylo / cmpossl

An OpenSSL-based implementation of the Certificate Management Protocol (CMP), defined in IETF RFCs 4210, 4211, and 6712. It is being extended according to the emerging RFCs 'CMP Updates' (CMPv3), 'CMP Algorithms', and 'Lightweight CMP Profile'.
https://github.com/mpeylo/cmpossl/wiki
Other
35 stars 13 forks source link

response to p10cr is rejected (key mismatch) #183

Closed gingerbeard-man closed 5 years ago

gingerbeard-man commented 5 years ago

Hi, We have used cmpossl to implement a frontend / proxy for our bespoke CA system. Clients send CR messages which are converted and passed to the CA and its responses are packaged into CP for the clients.

One client would also like to send us occasional PKCS#10 request files, bypassing the established CMP connection. These requests should then be processed by the CA in the same way as the automated CMP traffic. The idea is to use the openssl cmp client to manually inject these requests into our CMP proxy.

I have added support for the P10CR command in the proxy and written a simple script which calls openssl cmp with -cmd p10cr and -csr. Unfortunately the new certificate in the CP response is rejected because its public key does not match our private key. Obviously we do not have access to the private key with which the CSR was created. I assume this will apply to most use cases for P10CR, otherwise a regular CR message could be created instead.

$ openssl cmp -cmd p10cr -config '' -disableconfirm -popo -1 \
> -server 127.0.0.1:10080 -path /cmp/testing -trusted certs/ca_ec.pem \
> -cert certs/request_ec.pem -key keys/request_ec.pem \
> -csr my_csr.pem -certout my_cert.pem
CMP INFO: sending p10cr
CMP INFO: got response
140031227574016:error:0B080074:x509 certificate routines:X509_check_private_key:key values mismatch:crypto/x509/x509_cmp.c:294:
140031227574016:error:360A3065:CMP routines:OSSL_CMP_exec_P10CR_ses:certificate not accepted:crypto/cmp/cmp_ses.c:632:rejecting newly enrolled cert; public key in new certificate does not match our private key

(Note that neither confirmation messages nor proof-of-possession are used in this environment, only signature-based overall message protection.)

Is there some option to disable this key check using the command line or config file? Is our basic idea flawed in any way? The cert and key used for message protection are our own and in no way related to the PKCS#10 CSR which effectively comes from outside our organization.

We are working with cmpossl master as of January 2019, patched into openssl-1.1.1a.

DDvO commented 5 years ago

Thanks for your report. Sorry for the delay answering; I overlooked it at first.

You are right, for P10CR the consistency check of the new certificate with any private key does not make sense. When I implemented this check I did not have in mind that it must not be done for p10cr. I cannot actually test this type of request because I do not have a server that can make use of it, therefore this bug went unnoticed for long time. I've just done a respective fix; please try it out and let me know.

BTW, for p10cr there is no need to use the -popo option since this is ignored anyway. I've now made clear that the POPO option is relevant (only) for IR, CR, and KUR.

gingerbeard-man commented 5 years ago

Thanks, David. I can confirm that your fix works for us.

$ openssl cmp -cmd p10cr -config '' -disableconfirm \
> -server 127.0.0.1:10080 -path /cmp/testing -trusted certs/ca_ec.pem \
> -cert certs/request_ec.pem -key keys/request_ec.pem \
> -csr my_csr.pem -certout my_cert.pem
CMP INFO: sending p10cr
CMP INFO: got response
CMP INFO: received 1 enrolled certificate, saving to file 'my_cert.pem'

Agree on the -popo. It was a copy-paste leftover from running a normal cr command.

Another thing, not related other than by proximity in the code: The -extracertsout option only works for IP/CP/KUP responses although any PKIMessage could have extraCerts. The option simply writes to disk what is in the CTX. Is there a reason why CMP_CTX_set1_extraCertsIn() is only called in cert_response() and not for all received messages? E.g. if I send an RR and want to see what extraCerts the server has put in his RP then I have to use Wireshark or save the whole response with -rspout.

mpeylo commented 5 years ago

No special intention that -extracertsout is only implemented for IP/CP/KUP. The reason that it's not there is so far, is just that it wasn't explicitly needed.

Main purpose of the functionality is for EE or RA to be able to extract the full certificate chain of the issued certificate, as issuing CA certificate etc are (possibly) included in extraCerts. For RP, the content of extraCerts is only meaningfully used to validate the message protection, so besides debugging, there seems to be little reason to write out the certificates.

Would probably not be difficult to have that implemented, might make sense to raise a feature request if that is needed (but of course no guarantee that/when that feature would appear as it seems to be somewhat optional).

DDvO commented 5 years ago

Since our documentation does not say that the storage of received extracerts is restricted to cp/ip/kup and indeed the extraCerts are a generic component of all CMP messages I consider the issue @gingerbeard-man brought up actually a bug and not a missing feature. As @mpeylo suspected a fix is pretty straightforward to implement; I've just done it.