Decentralize legacy_ctrl_str_to_param()#10947
Decentralize legacy_ctrl_str_to_param()#10947levitte wants to merge 5 commits intoopenssl:masterfrom
Conversation
|
It was always the intention that string controls would be directly, simply and fairly uniformly translated to OSSL_PARAM. Let's remember that libcrypto is becoming a framework, and can therefore not assume too much knowledge of what the provided implementations want. |
|
travis failures need addressing |
b9358ff to
75306fd
Compare
|
I had to fix a couple of things, so a re-approval is needed, regardless of if @romen's concern is already answered or not. |
2bfce3c to
03cbc8c
Compare
|
Ping? |
|
@vt-alt, could you please remind the test case? |
|
@beldmit |
|
Sure! Many thanks! |
|
Hmmm, that test fails... but does that have anything to do with this PR? |
|
On my local build I get |
My misunderstanding, sorry. |
Thanks. I'll investigate |
|
I'll comment on it there |
|
Rebase needed |
This function did a bit too much in terms of central control, actually more so than the legacy counterpart, where all the string processing is done in the diverse *_pmeth.c. Furthermore, there was no room whatsoever for control keys that libcrypto isn't centrally aware of. This function is changed to simply translating keys and values to OSSL_PARAM form and then sent on their merry way to the provider implementations through EVP_PKEY_CTX_set_params(). It translates selected well known legacy names to their core name counterpart, and that's as far as centralized control should extend.
It turns out this was never necessary, as the implementation should always check the default digest size anyway.
Because the libcrypto code has relinquished control of exact words to express padding mode choices, we re-implement them in the appropriate provider implementation. For the sake of legacy controls, we maintain support for the numeric form of the padding mode, but leave that support otherwise undeclared.
Refactor the DSA SIGNATURE digest setup to be uniform, and to happen in two places: 1. when given through the digestsign and digestverify inits 2. when given through the set_ctx_params function. When setting up the digest, we also check that the digest is one of the officially accepted for DSA.
A check was present as to what operation is performed with this context. It may have been useful at some point, but isn't any more.
de720c5 to
0f9b2cb
Compare
|
That was a trivial conflict, easily resolved. This PR isn't changed by it, so I'll take that reconfirmation and merge. |
|
Just to be safe, I'll wait a bit for the CIs, though |
This function did a bit too much in terms of central control, actually more so than the legacy counterpart, where all the string processing is done in the diverse *_pmeth.c. Furthermore, there was no room whatsoever for control keys that libcrypto isn't centrally aware of. This function is changed to simply translating keys and values to OSSL_PARAM form and then sent on their merry way to the provider implementations through EVP_PKEY_CTX_set_params(). It translates selected well known legacy names to their core name counterpart, and that's as far as centralized control should extend. Reviewed-by: Shane Lontis <[email protected]> (Merged from #10947)
It turns out this was never necessary, as the implementation should always check the default digest size anyway. Reviewed-by: Shane Lontis <[email protected]> (Merged from #10947)
Because the libcrypto code has relinquished control of exact words to express padding mode choices, we re-implement them in the appropriate provider implementation. For the sake of legacy controls, we maintain support for the numeric form of the padding mode, but leave that support otherwise undeclared. Reviewed-by: Shane Lontis <[email protected]> (Merged from #10947)
Refactor the DSA SIGNATURE digest setup to be uniform, and to happen in two places: 1. when given through the digestsign and digestverify inits 2. when given through the set_ctx_params function. When setting up the digest, we also check that the digest is one of the officially accepted for DSA. Reviewed-by: Shane Lontis <[email protected]> (Merged from #10947)
A check was present as to what operation is performed with this context. It may have been useful at some point, but isn't any more. Reviewed-by: Shane Lontis <[email protected]> (Merged from #10947)
|
Merged 972fa31 Decentralize legacy_ctrl_str_to_param() |
|
I know my issue comes late, but I couldn't find cycles to spare until now. I see now another problem with this: by going directly to the provider interface with Yes, the code inside libcrypto looks nicer and saner this way, but this way we lose the ability to return specific return values for different error conditions or we force every external provider to implement whatever workarounds we devise inside the providers we distribute to retain the legacy behavior. Examples from #10631
|
|
@levitte could you have a look at this? |
Er, yes? So let's see if I can clarify something that seems to be a point of confusion, and I'm going to do see by using the term "backend", as a broad term for "implementations under the hood". In pre-3.0 terms, any EVP_CIPHER, EVP_MD, EVP_PKEY_METHOD, EVP_PKEY_ASN1_METHOD implements a backend, whether it happens to be built in (our ameth and pmeth files) or coming from en engine, or coming from a provider in the case of EVP_CIPHER and EVP_MD. The EVP API per se doesn't really know, and shouldn't really know what the backends are up to, and this is very visible when you look at how the pre-3.0 openssl/crypto/evp/pmeth_lib.c Lines 407 to 418 in ff6d0a6 So what had happened previous to this PR was that code that belonged in the backends was moved to central EVP functions when it should have moved from the old backend (whatever ameth or pmeth file) to the new backends (providers). That was wrong, on principle.
Do we? Would you claim that any ENGINE implementor that wanted to implement their version of, say, RSA, was forced to implement the exact behaviour the our backends (crypto/rsa/rsa_ameth.c or crypto/rsa/rsa_pmeth.c)? To what extent? 'cause believe you me, that wasn't necessarily the case... The very simple truth is central EVP code such as All this being said, you're quite right that there are things that aren't the same between the old (ameth and pmeth code) and the new (providers) backends, and that can be summed up in three parts:
Now... to your analysis of return codes:
I don't understand why
Er.... If the backend code to handle an
Now, here you do have a point, and that gets back to what I said in 3. above, that
If you look at other code that we have moved from diverse built in methods to our providers, we haven't concerned ourselves with preserving exact error codes. They are all over the place regardless.
This is again about -2, right? I hope I have answered that clearly enough.
Er... how is this a concern specifically for control values (legacy) or parameters (provider) being passed to the backend via |
It's not that I don't like the idea of doing it like this, it's just that I am afraid we are breaking backward compatibility: before
This is not the whole picture though, as the code I linked before (also from 1.1.1) shows
ENGINEs imposed their own restraints on external implementers, and returning the same return values and error codes for at least a subset of these controls was indeed one of the restraints, but you are definitely more knowledgeable than me about ENGINEs so I probably am missing your point. Here what I see as a problem is that if to behave like legacy a specific
This is fine, as long the complexity of being backward compatible with legacy It is fine to resolve that being backward compatible with return values or error codes is just nit picking and deliberate that we will break our promise in this niche aspect, but it should still be discussed (and probably OMC voted).
Agreed!
Agreed!
Agreed!
Let's dive into the handling of "ecdh_cofactor_mode" from the point of view of a 1.1.1 application calling Lines 385 to 389 in 894da2f Lines 1387 to 1390 in 894da2f openssl/crypto/evp/pmeth_lib.c Lines 366 to 399 in 894da2f (shows 3 different conditions under which Lines 247 to 278 in 894da2f (return So openssl/crypto/evp/pmeth_lib.c Lines 387 to 390 in 894da2f should answer to the "why
Agreed that if this happens there are probably bigger problems: before 3.0 we used to handle these cases in
I agree this should be manageable without too much fuss!
I noticed this, as well as the fact that in the DH provider implementation we have TODOs to raise errors.
Yes, the
This was just meant to be an example of a case where it was and is reasonable that applications checked for that |
It does not. There's a huge structural difference that you've ignored. In legacy code What I would expect, the day that legacy code goes away, is that this: openssl/crypto/evp/pmeth_lib.c Lines 860 to 867 in 87d3bb8 gets replace with this: ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_OPERATION);
return -1;(or quite frankly, I hope that everything called but since we currently have a mixture of providers and legacy backends, we simply let legacy take care of whatever there's no provider code.
I actually think that returning -2 in such cases is wrong. 0 should be returned, as it is an error. The manual for
"the operation", here, refers to the cmd, i.e. things like |
|
As for the diverse |
|
Regarding the first half of #10947 (comment) I am not ignoring the fact that the architectural reorganization makes the check likely superfluous, I am just concerned that by skipping it (because it is superfluous and hopefully triggered before calling any ctrl function) we might be altering the return value and error codes raised in these corner cases. I am likely to be overthinking this, and probably you are completely right in assuming that these checks even if present would never trigger the special return value and raised error, but without extensive testing we have no way of guaranteeing this is the case!
I tend to agree with you, and can't wait for the moment we will drop the ctrl functions, but even if it is an error, it is an ossified behavior from at least 1.0.2, that should require a discussion before being changed! |
If we really want to keep (wrongly) returning -2 for incorrect parameter values, then I can only see one answer, that the providers will have to return -2 in those cases. Trying to do some magic in the EVP code will only create a total mess, of which we already saw the effect before this PR. |
If we (or OMC) doesn't vote to approve breaking legacy compatibility we should figure out where all that ugliness would need to go. I would argue that, with libcrypto becoming essentially a framework, any temporary workaround to maintain our promise of backward compatibility must be handled inside the framework code, no matter how ugly, and can't really be forced on external providers! Maybe some other reviewer may chime in: does this really constitute breaking behavior? Do we need an OMC vote to get rid of the ugliness? I will look at #11046 as soon as possible! |
This function did a bit too much in terms of central control, actually
more so than the legacy counterpart, where all the string processing
is done in the diverse *_pmeth.c. Furthermore, there was no room
whatsoever for control keys that libcrypto isn't centrally aware of.
This function is changed to simply translating keys and values to
OSSL_PARAM form and then sent on their merry way to the provider
implementations through EVP_PKEY_CTX_set_params(). It translates
selected well known legacy names to their core name counterpart, and
that's as far as centralized control should extend.
There were consequences, of course. For RSA, The padding mode could
be given in form of words, and that got moved to the RSA ASYM_CIPHER
implementation. For DSA, it turned out that the SIGNATURE implementation
didn't like to get a "digest" param without the "digest-size" param...