Improve the usability of the ca app using EdDSA#6901
Improve the usability of the ca app using EdDSA#6901mattcaswell wants to merge 3 commits intoopenssl:masterfrom
Conversation
Previously you had to supply "null" as the digest to use EdDSA. This changes things so that any digest is ignored.
| * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is | ||
| * mandatory for this algorithm. | ||
| */ | ||
| if (def_ret == 2 && def_nid == NID_undef) { |
There was a problem hiding this comment.
dislike magic numbers, but okay if this is out of scope for this PR.
There was a problem hiding this comment.
So do I, but I thought it was moving the scope too far to tackle that in this PR.
There was a problem hiding this comment.
On an additional note: we say that if it returns 2 the digest is mandatory for this algorithm, but we act in that direction only if the return is 2 and the required digest is NID_undef.
What if the required default was something else, e.g. SM3 for SM2 or an engine-provided PKEY method with such requirements? Shouldn't it be honored?
There was a problem hiding this comment.
@romen, perhaps it should - but again I think that starts moving the scope of this PR too far away from the original problem.
There was a problem hiding this comment.
@mattcaswell I understand that.
My issue is that I'm just not convinced that, in this case, usability can trample on backwards behavioral compatibility.
Is it really necessary that Ed25519/448 should ignore explicit configuration lines/cmdline args?
I ask because to introduce this we are adding a very specific (only for (EVP_PKEY_get_default_digest_nid() == 2) && (returned_nid == NID_undef)) behavior in the apps, which does not match exactly the documented behavior of the function (returns 2 if the digest is mandatory for this algorithm).
There was a problem hiding this comment.
Is that a break in backwards compat? There are lots of things that the apps can now do in 1.1.1 that they couldn't do before. Try pointing a 1.1.0 s_client at a TLSv1.3 only server....it will fail. Do the same in 1.1.1 and it will work!
There was a problem hiding this comment.
More concerning for backwards compat would be if there are things in 1.1.0 that used to work, but now don't in 1.1.1.
There was a problem hiding this comment.
@romen Because if you run the same commands with 1.1.0 apps (with access to Ed25519 through an engine) and 1.1.1 apps, using the same configuration file for the pki settings, the former fails while the second succeeds.
The whole point of the PR is to succeed where we previously failed. The failure is spurious, the public key algorithm does not use a digest for signing, so we should succeed regardless of any specified digest. Requiring the user to explicitly specify a null digest is a bad UI and breaks existing configuration files and command-line scripts.
If a particular public key algorithm works exclusively with a particular digest or no digest, then we should always use that (or no) digest, and ignore options that provide a digest to use for those key types that could use one of many.
@mattcaswell I think it is time to go ahead and push this PR, I've not seen any substantive objections that prevent moving forward. If someone wants to fine-tune with a follow-on PR we can evaluate that separately.
There was a problem hiding this comment.
If a particular public key algorithm works exclusively with a particular digest or no digest, then we should always use that (or no) digest, and ignore options that provide a digest to use for those key types that could use one of many.
@vdukhovni but we don't do this with this changes, only for the "no digest", that's why I am talking about "special case" and not conforming to the documented behavior: if the function returns 2 but it's not asking for the null digest then we still fail!
@mattcaswell I don't mean to stop the PR, I raised my objections and discussion points, which were evaluated, so I am satisfied anyway!
There was a problem hiding this comment.
I am aware that this PR does not address the case of a single non-null mandatory digest. We can address that issue when we come to it. This PR is strictly an improvement, that addresses the immediate issue. We can generalize later, but feel free to propose a follow-on PR if you have something ready to go.
|
I guess this is perfectly fine for now. I only want to raise the issue of thinking about a future when instead of only PureEdDSA OpenSSL might support also HashEdDSA: would this change have an unintended impact on configuration patterns or command line arguments that might be difficult to break in future versions? I honestly don't know the answer, nor if such issues would concern the guarantees in minor or major releases. |
I did consider this, but I don't think it is an issue. The way it has been implemented the ca app asks the EVP_PKEY object what its default hash is. Only if the default hash is undefined is it allowed to not have a hash specified. If we later implement hash EdDSA then the EVP_PKEY will return with a sensible, defined, hash. |
|
Thanks for clarifying it @mattcaswell! |
|
It seems to me that req.c be fixed the similar way to ca.c. |
|
I'm not sure that code should ignore configuration settings. Correction for #6201 , i.e. null digest is fine with me. |
The current solution is causing some significant usability problems, so it doesn't seem to be viable: |
This follows on from the previous commit, and makes the same change to ignore the digest if we are using EdDSA.
|
I added a new commit to make an equivalent change in the req app. Interestingly, while updating the documentation for that I discovered that we already ignore the digest configuration setting in req in some situations so this approach seems consistent with that. |
|
@richsalz please reconfirm |
|
reconfirm. good catch, @petrovr ! |
|
I think the catch was @beldmit...! |
|
mattcaswell wrote:
I think the catch was @beldmit...!
Perhaps @beldmit is reporter.
My point is that program code can not ignore invalid values:
1) null is valid value,
2) missing digest could mean use default , i.e. null
3) other values, for instance sha1, should break processing .
Regards,
Roumen Petrov
|
I disagree. It is perfectly reasonable to want to set a default digest of (say) sha256 for most stuff, but not use it when doing EdDSA. |
|
mattcaswell wrote:
> My point is that program code can not ignore invalid values:
> 1) null is valid value,
> 2) missing digest could mean use default , i.e. null
> 3) other values, for instance sha1, should break processing
I disagree. It is perfectly reasonable to want to set a default digest of (say) sha256 for most stuff, but not use it when doing EdDSA.
Digest depends from algorithm.
I would like to have more consistent behaviour. For instance if I set
md5 for dsa processing is blocked by error ..."dsa
routines:pkey_dsa_ctrl:invalid digest type:crypto/dsa/dsa_pmeth.c:142:"
This is reason to ask for consistency with existing functionality.
Roumen
|
|
I have the required approval for this, and I still think this is the correct approach, but given @petrovr's objection I invite any other comment from @openssl/committers. |
|
I don't see the parameter as forcing a digest value conceptually. I think defining default_digest to mean the digest for algorithms that allow a settable digest is a reasonable approach (and the documentation should be updated to make that clear that this is the definition of the configuration parameter - not that some algorithms ignore it - that it only applies to algorithms that allow settable values). That way it is clearer what is going on here and looks less like a workaround. Basically more clarity in the docs wording - but I agree with @mattcaswell in terms of the approach. |
vdukhovni
left a comment
There was a problem hiding this comment.
One could take the view that each "ca" instance is associated with a particular key, and should use a dedicated openssl.cnf for that instance, with an appropriate default_md. But, sadly, this is not what users do, and having the software fail by default is simply not a good UI. So I'm in favour of this approach. An explicit -md _mumble_ will still fail when _mumble_ is not compatible with the key. That's good enough.
crypto/ec/ecx_meth.c
Outdated
|
|
||
| ecx_free, | ||
| ecx_ctrl, | ||
| ecx_xctrl, |
crypto/ec/ecx_meth.c
Outdated
|
|
||
| ecx_free, | ||
| 0, | ||
| ecx_edctrl, |
There was a problem hiding this comment.
Please use ecd_crtl for consistency with other ed... specific functions
|
It is about how to change existing code : Also think about "default" to be set unconditionally in above code snippet. |
That would require a user wishing to use EdDSA, along with other algorithms to only use the "default" setting. Setting it to (say) sha256 would rule out the use of EdDSA - which I think is incorrect. |
|
Fix up commit pushed renaming the
Just to be clear an explicit @vdukhovni please can you reconfirm after the ctrl function name change commit? |
|
I don't like to stop progress on this issue, i.e. approvals. For protocol I did tests with following code snipped from apps/ca.cThis was my idea. Let me know if someone found above generic approach useful. Is so I open an enhancement request. |
romen
left a comment
There was a problem hiding this comment.
I would also note that this change will introduce a substantial behavior change from previous versions: e.g. if an engine provided ed25519 to version 1.1.0, using the same command for the ca app with the same cmdline arguments and the same configuration file will not yield the same results.
Specifically on 1.1.0 one must either provide -md null or -md default as an argument or alter the configuration file.
Breaking the assumption that the ca app will act based on the arguments/configuration might be something that should be done in a major release rather than in a minor one.
I understand that this is done for usability, but at the least I think that an entry in CHANGES and NEWS about changing the behavior of the ca app is required, as in this case it is disruptive of compatibility with 1.1.0 for 3rd party engines.
| * EVP_PKEY_get_default_digest_nid() returns 2 if the digest is | ||
| * mandatory for this algorithm. | ||
| */ | ||
| if (def_ret == 2 && def_nid == NID_undef) { |
There was a problem hiding this comment.
On an additional note: we say that if it returns 2 the digest is mandatory for this algorithm, but we act in that direction only if the return is 2 and the required digest is NID_undef.
What if the required default was something else, e.g. SM3 for SM2 or an engine-provided PKEY method with such requirements? Shouldn't it be honored?
| * for this algorithm. | ||
| */ | ||
| if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) == 2 | ||
| && def_nid == NID_undef) { |
There was a problem hiding this comment.
Also on req we honor the return value 2 only for NID_undef
There was a problem hiding this comment.
As above I think this is a valid point, but I don't want to tackle that in this PR.
| This option specifies the digest algorithm to use. Any digest supported by the | ||
| OpenSSL B<dgst> command can be used. This option can be overridden on the | ||
| command line. Certain signing algorithms (i.e. Ed25519 and Ed448) will ignore | ||
| any digest that has been set. |
There was a problem hiding this comment.
This is a behavior change, should it warrant an HISTORY entry?
There was a problem hiding this comment.
Is it really a behaviour change? There aren't any algorithms in 1.1.0 where this clause applies. You gave the example somewhere else of someone providing an engine to do ed25519 in 1.1.0. I'm not convinced that is actually possible. In 1.1.0 we assume that all signing algorithms require a digest...and stuff will probably break if you try to supply one via an engine where that isn't true.
There was a problem hiding this comment.
I commented on the behavior change explicitly because I noticed that it started breaking stuff for an engine I am working on (libsuola) which does exactly this, and I noticed that after this change 1.1.1 apps have the option of ignoring explicitly set configuration entries or cmdline args, while 1.1.0 apps don't.
I just wanted to make sure that all the implications of this change are discussed before committing to them! ;)
There was a problem hiding this comment.
I noticed that it started breaking stuff for an engine I am working on
Interesting. Can you be more explicit about in what way it broke?
| message digest NID for the public key signature operations associated with key | ||
| B<pkey>. | ||
| B<pkey>. Note that some signature algorithms (i.e. Ed25519 and Ed448) do not use | ||
| a digest during signing. In this case B<pnid> will be set to NID_undef. |
There was a problem hiding this comment.
If I am not mistaken, up to 1.1.0 returning NID_undef as the default md would cause errors in the OpenSSL apps.
If that's the case, and this change is ok for a minor release, an HISTORY entry detailing the change might be required.
There was a problem hiding this comment.
On further investigation, I am mistaken on this, so nevermind this comment.
|
BTW, why not to specify a separate NID, not NID_undef for md_null? It can save us from separate processing NID_undef as dgst_nid here and may be in some other places of code. |
One could perhaps argue that the "Intrinsic" TLS HashAlgorithm defined by RFC 8422 (section 5.1.3) would argue for having such a dedicated new NID, but if we do add such a thing, we'd need to assign it some semantics for all the other places it could be used, and it's unclear that we really want to do that. |
Previously you had to supply "null" as the digest to use EdDSA. This changes things so that any digest is ignored. Reviewed-by: Viktor Dukhovni <[email protected]> (Merged from #6901)
This follows on from the previous commit, and makes the same change to ignore the digest if we are using EdDSA. Reviewed-by: Viktor Dukhovni <[email protected]> (Merged from #6901)
|
For reasons I don't entirely understand (or agree with), this PR seems to have been more controversial than I expected. However I still believe this is the correct approach, and it has all the relevant approvals and support from an OMC member, with no "-1" from any committer, so I have pushed. If people want to they can follow up with further PRs as appropriate. |
Previously you had to supply "null" as the digest to use EdDSA. This changes
things so that any digest is ignored.