CMP extension to OpenSSL, incremental PR chunk 1: CRMF API#7328
CMP extension to OpenSSL, incremental PR chunk 1: CRMF API#7328DDvO wants to merge 5 commits intoopenssl:masterfrom
Conversation
|
The next chunk is going to be the CRMF implementation, after we have received reviewers' feedback on the CRMF API and dealt with it. |
|
In case one wonders: the CI build failures automatically reported below are just due to |
mattcaswell
left a comment
There was a problem hiding this comment.
Some initial thoughts only. I've only reviewed the header file so far.
include/openssl/crmf.h
Outdated
| int OSSL_CRMF_MSG_set1_regCtrl_authenticator(OSSL_CRMF_MSG *msg, | ||
| ASN1_UTF8STRING *auth); | ||
| int OSSL_CRMF_MSG_set1_regCtrl_pkiPublicationInfo(OSSL_CRMF_MSG *msg, | ||
| OSSL_CRMF_PKIPUBLICATIONINFO *pi); |
There was a problem hiding this comment.
So I can use the OSSL_CRMF_PKIPUBLICATIONINFO object here. I see the DECLARE_ASN1_FUNCTIONS macro above, which is going to give me *_new, *_free functions etc. But how do I populate this with any data? There seem to be no way of setting any values within this structure. The same comment applies to a number of the other objects in this header file, e.g. OSSL_CRMF_PKIARCHIVEOPTIONS, OSSL_CRMF_ENCRYPTEDVALUE.
There was a problem hiding this comment.
Good point, I will see that those get created - although there might not be any CA-side implementation that could digest those.
include/openssl/crmf.h
Outdated
|
|
||
| /* crmf_lib.c */ | ||
| int OSSL_CRMF_MSG_set1_regCtrl_regToken(OSSL_CRMF_MSG *msg, | ||
| ASN1_UTF8STRING *tok); |
There was a problem hiding this comment.
There is only a setter for this and other fields. Should there be getters as well?
There was a problem hiding this comment.
In general yes, yet this implementation focuses on the CMP (and thus CRMF) client side.
The client typically just sets these fields in its requests and does not need to read them out again.
include/openssl/crmf.h
Outdated
| @@ -0,0 +1,121 @@ | |||
| /* | |||
| * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. | |||
There was a problem hiding this comment.
This is a new file. Is the claim of copyright back to 1995 justified? Similarly for the Nokia and Siemens copyright claims below.
There was a problem hiding this comment.
OpenSSL copyright might be a tricky question: the CMP/CRMF code builds up and loans a lot from existing OpenSSL code, which generally states copyright going back to 1995. It might be of course OK to adjust that to the earliest version of the file, which will usually be 2007?
The dates for the Nokia and Siemens copyright claims are verified; development was started in 2007.
There was a problem hiding this comment.
I'm fine with whatever the earliest date is.
include/openssl/crmf.h
Outdated
| int OSSL_CRMF_MSG_set1_regInfo_certReq(OSSL_CRMF_MSG *msg, | ||
| OSSL_CRMF_CERTREQUEST *cr); | ||
|
|
||
| int OSSL_CRMF_MSG_set_version2(OSSL_CRMF_MSG *crm); |
There was a problem hiding this comment.
Why do we need this? RFC 4211 suggests this value SHOULD be omitted.
There was a problem hiding this comment.
Maybe if someone wants to see how a server reacts if that is set? SHOULD is not a SHALL?
If it's OpenSSL policy that such options are not there, then it will vanish. But then there might be a question how to set the optional version field? ;-)
There was a problem hiding this comment.
Well it's not a policy exactly. But if we're not supposed to set it according to the RFC, and it doesn't give us any benefit in setting it, then I don't really see any point in providing an API to allow people to set it.
include/openssl/crmf.h
Outdated
|
|
||
| /* crmf_pbm.c */ | ||
| OSSL_CRMF_PBMPARAMETER *OSSL_CRMF_pbmp_new(size_t slen, int owfnid, | ||
| long itercnt, int macnid); |
There was a problem hiding this comment.
Why long? We generally don't use long in new APIs any more. It's not particularly helpful because it may not be any bigger than int. Either use int (which we require to be at least 4 bytes in size on all our platforms), or use a int64_t if you require a larger type. Same comment applies to other uses of long in this header.
There was a problem hiding this comment.
Thank you for pointing that out.
Probably historic reasons: I think when that was written, ASN1_INTEGER_set() and ASN1_INTEGER_get() were the only available options. I replace them with their int64_t counterparts. The changes will appear soon, have already sent them for quality review before merging.
mattcaswell
left a comment
There was a problem hiding this comment.
I've now reviewed the rest of this PR. A few more comments below.
|
|
||
| =head1 COPYRIGHT | ||
|
|
||
| Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved. |
There was a problem hiding this comment.
Just querying this copyright date again since this is a new file.
There was a problem hiding this comment.
I'm still somewhat unsure what dates to put for OpenSSL Project Authors copyright. Basically everything is fine for me.
Options are likely:
- first version of the file (we can find out from Sourceforge / Github)
- first version / copyright of content somehow used or significantly in the file (that might be 2007 or 1995)
- official / successful submission to the project (that might be 2018 or realistically 2019)
For Nokia (c) in source files, it will usually start 2007 (2015 for Siemens) as that was when content was created which eventually ended up / directly influenced in most files.
There was a problem hiding this comment.
I'm also fine with any of these options.
My suggestion would be to simply put in all files:
Copyright 2007-2018 The OpenSSL Project Authors. All Rights Reserved.
|
|
||
| OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert() decrypts the certificate in the given | ||
| encryptedValue B<ecert>, using the private key B<pkey>. | ||
| This is needed for the indirect PoP method as in RFC 4210 section 5.2.8.2. |
There was a problem hiding this comment.
Although it is implied from the get0/get1 name, not everyone is familiar with that particular OpenSSL idiom so we should explicitly state the memory management semantics for each getter/setter. (Comment applies here and in all the other pod files)
There was a problem hiding this comment.
I've taken care of this (for all CRMF doc files), also regarding set0 vs. set1.
|
|
||
| =head1 DESCRIPTION | ||
|
|
||
| OSSL_CRMF_MSG_set1_regInfo_utf8Pairs() adds the cutf8Pairs regInfo to the given |
There was a problem hiding this comment.
cutf8Pairs? Typo? RFC4211 says that this can appear multiple times in the regInfo. Is this possible with this API?
There was a problem hiding this comment.
Typo, good catch.
Yes, the code allows to set multiple instances of the utf8Pairs control to be set by calling that function multiple times. I realized that this is also possible for certReq, where the RFC states that there can only be one (which makes sense due to its nature- while using non-normative language).
I would describe this in a NOTES section to the man page. I believe that this is sufficient, and it does not require explicit enforcement by the API, as as nobody will ever be able to use this functions without closely investigating in the RFC what they are for in the first place.
=head1 NOTES
Calling the functions multiple times adds multiple instances of the control in
question to the regInfo structure of the given B<msg>. However RFC RFC 4211
only expects multiple instances of utf8Pairs in one regInfo structure, but not
for certReq.
Does this make sense?
doc/man3/OSSL_CRMF_pbmp_new.pod
Outdated
| structure with new a random salt of given length B<saltlen>, OWF (one-way | ||
| function) NID B<owfnid>, iteration count B<itercnt>, and MAC NID B<macnid>. | ||
|
|
||
| The iteration count is enforced to be at least 100, as stipulated by RFC 4211. |
There was a problem hiding this comment.
Drop this sentence. You already said it above.
doc/man3/OSSL_CRMF_pbmp_new.pod
Outdated
| =head1 NOTES | ||
|
|
||
| The OWF (one-way function) and for the MAC (message authentication code) may be | ||
| any with an NID defined in B<openssl/objects.h>, |
doc/man3/OSSL_CRMF_pbmp_new.pod
Outdated
| unsiged char *msg = "Hello"; | ||
| unsiged char *sec = "SeCrEt"; | ||
| unsiged char *mac = NULL; | ||
| unsiged int maclen; |
|
We have meanwhile reacted to all of Matt's review comments and provided an update with our respective fixes. |
mattcaswell
left a comment
There was a problem hiding this comment.
Looks ok to me. Needs a second review from @openssl/committers.
I'm not sure how best to handle this. Until we have the implementation half of this, it probably shouldn't really be merged. On the other hand that will complicate the review of the implementation PR because it will have to include all the commits from this PR.
|
Pleased to hear. |
Yes - lets do that. |
|
Oops, I had overlooked your swift response. |
|
Still looking for a second reviewer for this. Ping @openssl/committers |
There was a problem hiding this comment.
Aehm, sorry, but "popo" is the german word for butt.
Could we please have another name?
There was a problem hiding this comment.
:-) That's funny!
Actually though it is consistently called popo in the RFC!!
There was a problem hiding this comment.
Actually though it is consistently called popo in the RFC!!
Actually they don't use it consistently: I counted only 23 POPOs vs 71-23 = 48 POPs.
curl https://www.ietf.org/rfc/rfc4210.txt | tr ' ' '\n' | grep POP | wc -l
71
curl https://www.ietf.org/rfc/rfc4210.txt | tr ' ' '\n' | grep POPO | wc -l
23
So why not use POP instead of POPO?
There was a problem hiding this comment.
I think the waned to have a prove that the joke is really funny...
There was a problem hiding this comment.
Both Martin and me are native German speakers.
We're aware of this accidental pun and got used to it :)
There was a problem hiding this comment.
yeah, as far as the ASN.1 terms are used, its probably okay.
Honestly I had to laugh and could not stop for a while :) when I read the create_popo thing...
There was a problem hiding this comment.
yeah, as far as the ASN.1 terms are used, its probably okay.
Honestly I had to laugh and could not stop for a while :) when I read the create_popo thing...
There was a problem hiding this comment.
Oops; will be fixed (as well as RAVerfied -> RAVerified).
Also includes CRMF (RFC 4211) and HTTP transfer (RFC 6712) CMP and CRMF API is added to libcrypto, and the "cmp" app to the openssl CLI. Adds extensive man pages and tests. Integration into build scripts. Incremental pull request based on OpenSSL commit 1362190 of 2018-09-26 1st chunk: CRMF API (include/openssl/crmf.h) and its documentation (reviewed)
|
I've meanwhile provided the code portion of the CRMF implementation as the second commit. |
Personally I would remove that commit until such time as @bernd-edlinger has finished reviewing what is currently there. And then I would create it as a different PR with both the commits from here and the implementation commits so that we have a clear separation of the review history and we know exactly what is in scope for review at any one time. |
|
All right, I will retract the second commit soon. |
|
Also AppVeyor was fine with the code :-) |
|
|
||
| =head1 RETURN VALUES | ||
|
|
||
| All functions returns 1 on success, 0 on error. |
| to B<si>. Consumes the B<spi> pointer. | ||
|
|
||
| OSSL_CRMF_MSG_set0_SinglePubInfo() sets given B<method> and PubLoction B<nm> to | ||
| B<spi>. PubLocation is optional, and therfore B<nm> may be NULL. Consumes the |
include/openssl/crmf.h
Outdated
| int OSSL_CRMF_MSG_set_validity(OSSL_CRMF_MSG *crm, time_t from, time_t to); | ||
| int OSSL_CRMF_MSG_set_certReqId(OSSL_CRMF_MSG *crm, int rid); | ||
| int OSSL_CRMF_MSG_get_certReqId(OSSL_CRMF_MSG *crm); | ||
| int OSSL_CRMF_ASN1_get_int(int *pr, const ASN1_INTEGER *a); |
There was a problem hiding this comment.
What does this function?
There was a problem hiding this comment.
Ah, this is a new function I forgot to document so far. It's basically like ASN1_INTEGER_get_int64(), actually calling it, but with range checks according its result type int. It is used both in the CRMF and CMP sub-libraries. I'll add the doc.
BTW, this rather general function could also be moved (with adapted name) to crypto/asn1/a_int.c. I'll add a TODO.
| # define OSSL_CRMF_POPOPRIVKEY_AGREEMAC 3 | ||
| # define OSSL_CRMF_POPOPRIVKEY_ENCRYPTEDKEY 4 | ||
|
|
||
| # define OSSL_CRMF_SUBSEQUENTMESSAGE_ENCRCERT 0 |
There was a problem hiding this comment.
funny, the methods are called like encCert, rfc4210 "CertOrEncCert", rfc 4211 has "encrCert"
|
@bernd-edlinger, thank you for your review of the CRMF API and doc. |
|
Nice that we meanwhile have both approvals :) I've just provided the second chunk of our incremental PR in #7646. |
|
I've just applied the "hold" label on this, so that no one attempts to merge it until chunk 2 is also ready. |
|
Now that #7646 is approved, I pushed this one. |
Also includes CRMF (RFC 4211) and HTTP transfer (RFC 6712) CMP and CRMF API is added to libcrypto, and the "cmp" app to the openssl CLI. Adds extensive man pages and tests. Integration into build scripts. Incremental pull request based on OpenSSL commit 1362190 of 2018-09-26 1st chunk: CRMF API (include/openssl/crmf.h) and its documentation (reviewed) Reviewed-by: Bernd Edlinger <[email protected]> Reviewed-by: Matt Caswell <[email protected]> (Merged from #7328)
Certificate Management Protocol (CMP, RFC 4210) extension to OpenSSL.
Also includes CRMF (RFC 4211) and HTTP transfer (RFC 6712).
CMP and CRMF functionality added to
libcrypto, and thecmpapp to theopensslCLI.Adds extensive man pages and tests. Integration into build scripts.
Incremental pull request as suggested by @mattcaswell: #6811 (comment) and recently agreed by email.
Initial chunk consists of the CRMF API
as declared in the header file
include/openssl/crmf.hand its documentation in
doc/man3/OSSL_CRMF_*.podChecklist