EVP: Fix EVP_Digest{Sign,Verify}Init() to handle no default digest #11576
Conversation
|
This turned out to be a logical exercise as well. Basically, the previous logic in So essentially, we're turning the provider implementation logic around to be legacy compatible, i.e. the provider implementation must provide a default or mandatory digest name if there is such a thing, and the empty string gets the special meaning that no digest must be used with this algorithm. |
|
I not at all sure about the return_size kludge. |
| params[0] = | ||
| OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST, | ||
| mddefault, sizeof(mddefault)); | ||
| params[0].return_size = sizeof(mddefault) + 1; |
paulidale
Apr 20, 2020
Contributor
Setting the return size here will have no effect. The return size is set by the recipient.
This isn't a great solution to the did the other end set this question that we've thus far not been able to answered.
Setting the return size here will have no effect. The return size is set by the recipient.
This isn't a great solution to the did the other end set this question that we've thus far not been able to answered.
levitte
Apr 20, 2020
Author
Member
Setting the return size here will have no effect. The return size is set by the recipient.
... if the recipient supports this parameter, and in that case, it will be set to something other than this initial value.
Setting the return size here will have no effect. The return size is set by the recipient.
... if the recipient supports this parameter, and in that case, it will be set to something other than this initial value.
paulidale
Apr 20, 2020
Contributor
I noted this, I don't like this way of detecting a parameter being set.
It's error prone -- the return size is set but the buffer not if the return size is larger than the data length. So a legitimate return of size sizeof(mddefault) + 1 could be a problem -- it isn't here because of another check but I think it is a bad precedent to set.
I'd consider using (size_t)-1 would be better. Best would be for the helper functions to support what is required. The construct calls clearing whatever sentinel is used, the set calls flag it and an additional function to check.
I noted this, I don't like this way of detecting a parameter being set.
It's error prone -- the return size is set but the buffer not if the return size is larger than the data length. So a legitimate return of size sizeof(mddefault) + 1 could be a problem -- it isn't here because of another check but I think it is a bad precedent to set.
I'd consider using (size_t)-1 would be better. Best would be for the helper functions to support what is required. The construct calls clearing whatever sentinel is used, the set calls flag it and an additional function to check.
levitte
Apr 20, 2020
Author
Member
So a legitimate return of size sizeof(mddefault) + 1 could be a problem
If p.data_size is sizeof(mddefault), I don't see how that would be a legitimate return size... that would mean that the receiving end has overwritten the buffer.
I'd consider using (size_t)-1 would be better.
I've considered that, but couldn't shake the feeling that there may be platforms where that's a perfectly legitimate size that doesn't necessarily eat all available memory (i.e. where size_t is smaller in size than void *). It's unlikely that we'll hit that kind of size, at least for now, but...
Best would be for the helper functions to support what is required. The construct calls clearing whatever sentinel is used, the set calls flag it and an additional function to check.
I have nothing against that idea.
So a legitimate return of size
sizeof(mddefault) + 1could be a problem
If p.data_size is sizeof(mddefault), I don't see how that would be a legitimate return size... that would mean that the receiving end has overwritten the buffer.
I'd consider using
(size_t)-1would be better.
I've considered that, but couldn't shake the feeling that there may be platforms where that's a perfectly legitimate size that doesn't necessarily eat all available memory (i.e. where size_t is smaller in size than void *). It's unlikely that we'll hit that kind of size, at least for now, but...
Best would be for the helper functions to support what is required. The construct calls clearing whatever sentinel is used, the set calls flag it and an additional function to check.
I have nothing against that idea.
paulidale
Apr 20, 2020
Contributor
If p.data_size is sizeof(mddefault), I don't see how that would be a legitimate return size...
If the return size is larger than the buffer size, the return size is set but no data is returned. The function also returns 0, so it's not an issue here.
I'll try make a stab at an API tomorrow. No promises.
If p.data_size is sizeof(mddefault), I don't see how that would be a legitimate return size...
If the return size is larger than the buffer size, the return size is set but no data is returned. The function also returns 0, so it's not an issue here.
I'll try make a stab at an API tomorrow. No promises.
levitte
Apr 20, 2020
Author
Member
Don't make this a blocker for the upcoming alpha.
Don't make this a blocker for the upcoming alpha.
kaduk
Apr 20, 2020
Contributor
Interestingly, a compliant C99 implementation is allowed to set SIZE_MAX as small as 65535.
Interestingly, a compliant C99 implementation is allowed to set SIZE_MAX as small as 65535.
paulidale
Apr 20, 2020
Contributor
I've used processors where even that would be way too large :)
I've used processors where even that would be way too large :)
levitte
Apr 21, 2020
Author
Member
I've come to terms with the (size_t)-1 value. It will probably be eons before we see a legitimate size get even close...
I've come to terms with the (size_t)-1 value. It will probably be eons before we see a legitimate size get even close...
| OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, | ||
| mdmandatory, | ||
| sizeof(mdmandatory)); | ||
| params[1].return_size = sizeof(mdmandatory) + 1; |
paulidale
Apr 20, 2020
Contributor
Likewise.
Likewise.
doc/man3/EVP_PKEY_get_default_digest_nid.pod
Outdated
Show resolved
Hide resolved
|
Do we need a test for this? |
That should be a generalized test. Not in this PR |
|
The Travis breakage is relevant. |
|
There seems to be some missing text in the commit message for "EVP: Fix EVP_Digest{Sign,Verify}Init() to handle no default digest" (and the pull request description), that cuts off after:
|
It turns out that the provider implementation of EC keys came with no default digest... |
Reworded |
|
The remaining Travis failures are not relevant here (one is fixed in #11573) |
evp_keymgmt_util_get_deflt_digest_name() is a refactor of the provider side key part of EVP_PKEY_get_default_digest_name(), that takes EVP_KEYMGMT and provider keydata pointers instead of an EVP_PKEY pointer. We also ensure that it uses SN_undef as the default name if the provider implementation gave us an empty string, since this is what EVP_PKEY_get_default_digest_name() responds when getting the digest name via a EVP_PKEY_ASN1_METHOD ctrl call that returns NID_undef.
EVP_DigestSignInit() and EVP_DigestVerifyInit() would detect if there is no default digest when using legacy (EVP_PKEY_ASN1_METHOD) implementations. However, it doesn't do that when provider side keys are used. Furthermore, because EVP_PKEY_get_default_digest_name() was used in the portion of the code that uses the provider implementation, the EVP_PKEY_ASN1_METHOD would be used if the key has one attached. This is now changed to use evp_keymgmt_util_get_deflt_digest_name() instead. Finally, we make sure to detect if the provider implementation supports the digest name parameters (default or mandatory), and returns with error if not. This is what the legacy portion of the code does. Fixes #11571
This adds handling of the parameter "mandatory-digest" and responds with an empty string, meaning that no digest may be used.
|
Rebased. The #11592 fix should result in a clean Travis run |
|
If this is slated for the alpha release, the param modification detection can be switched over after it. |
|
@paulidale, if you could remember the "approval: done" label, that would be quit helpful. |
|
Oops, sorry. |
|
24 hours has passed since 'approval: done' was set, but as this PR has been updated in that time the label 'approval: ready to merge' is not being automatically set. Please review the updates and set the label manually. |
evp_keymgmt_util_get_deflt_digest_name() is a refactor of the provider side key part of EVP_PKEY_get_default_digest_name(), that takes EVP_KEYMGMT and provider keydata pointers instead of an EVP_PKEY pointer. We also ensure that it uses SN_undef as the default name if the provider implementation gave us an empty string, since this is what EVP_PKEY_get_default_digest_name() responds when getting the digest name via a EVP_PKEY_ASN1_METHOD ctrl call that returns NID_undef. Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from #11576)
EVP_DigestSignInit() and EVP_DigestVerifyInit() would detect if there is no default digest when using legacy (EVP_PKEY_ASN1_METHOD) implementations. However, it doesn't do that when provider side keys are used. Furthermore, because EVP_PKEY_get_default_digest_name() was used in the portion of the code that uses the provider implementation, the EVP_PKEY_ASN1_METHOD would be used if the key has one attached. This is now changed to use evp_keymgmt_util_get_deflt_digest_name() instead. Finally, we make sure to detect if the provider implementation supports the digest name parameters (default or mandatory), and returns with error if not. This is what the legacy portion of the code does. Fixes #11571 Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from #11576)
This adds handling of the parameter "mandatory-digest" and responds with an empty string, meaning that no digest may be used. Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from #11576)
Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from #11576)
|
Pushed! |
EVP_DigestSignInit() and EVP_DigestVerifyInit() would detect if there
is no default digest when using legacy (EVP_PKEY_ASN1_METHOD)
implementations. However, it doesn't do that when provider side keys
are used.
Furthermore, because EVP_PKEY_get_default_digest_name() was used in
the portion of the code that uses the provider implementation, the
EVP_PKEY_ASN1_METHOD would be used if the key has one attached. This
is now changed to use evp_keymgmt_util_get_deflt_digest_name()
instead.
Finally, we make sure to detect if the provider implementation
supports the digest name parameters (default or mandatory), and
returns with error if not. This is what the legacy portion of the
Fixes #11571