-
-
Notifications
You must be signed in to change notification settings - Fork 9.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OpenSSL 3.0.8: ed25519 a decode from and then encode to a pem file corrupts the key if fips+base provider is used #20758
Comments
Hmm... this certainly does not look right. Can you please paste the contents of the openssl_fips.cnf file? |
Sure! the
And the
|
What happens if you remove the default_properties setting? Actually the ED25519 algorithm is not FIPS approved so it is not supported with fips=yes property. That still does not mean the failure mode should be to output a bogus public key. Instead the functions should fail to import/export ED25519 keys completely. |
Sure. I tested it with the config file removing the default_properties setting. And the result is same with the case of the
|
I reported this issue with the ed25519 on the FIPS mode. And a similar issue outputting the bogus public key also happens with the x25519 pem file on the FIPS mode too. |
…em file wrong? openssl#20758 Public key happens only for Fips
…em file wrong? openssl#20758 Changed logic for fips
Not according to our 3.0 code: openssl/providers/fips/fipsprov.c Line 394 in 87abde5
openssl/providers/fips/fipsprov.c Lines 439 to 440 in 87abde5
(the same goes in 3.1, btw)
It shouldn't fail completely in 3.0. But, I do wonder why a bogus key is being output... |
UPDATE: NEVER MIND THIS, that's of course the first DER decode attempt.
|
The 3.0 security policy forbids EdDSA operations. Refer to table 8 on page 24. |
Yeah, but as was previously said, our code says something different, and returns a bogus key. The issue is very likely not so much about the abuse of the FIPS module as it's a problem with what data gets passed over an export/import dance when the decoder and the keymgmt are in different providers. I'm starting to have it my mind to put together an experiment where the decoders and encoders are removed from the default provider, i.e. only exist in the base provider, just to see what falls apart. |
How is the progress of this issue? |
I tested this issue with the OpenSSL latest master branch
Install OpenSSL masterI installed the OpenSSL like this from the GitHub source.
I added the FIPS config file as usual.
Run the reproducing programI compiled the reproducing program like this. Interestingly the behavior is different from the OpenSSL 3.0.8.
I ran the program on the FIPS case like this. It failed with segmentation fault.
I also ran the program in the non-FIPS case. It succeeded as expected
DebugI debugged the FIPS case with the GDB like this. It seems that the value of the
|
I executed
And the result shows 9fa5532 is the commit. And here is the result of the
|
ed25519 is not FIPS approved. Your default properties is mandated only FIPS approved algorithms are used. Consequently, ed25519 is not being fetched. There is no fix for this that remains FIPS compliant. The reason ed25519 is in the FIPS provider is historic and based on NIST changing their mind about permitting it as a vendor affirmed algorithm. For the original 3.0 validation, we were allowed to include it. Late last year, NIST had a change of mind and mandated that it not be included so we had to adapt. The non-compliance is covered in the security policy which is required reading since it imposes other restrictions on the building and use of the FIPS provider. |
@paulidale thank you for explaining the context. So, for example using my reproducer ed25519.c calling Do you think the behavior of the
Could you share the link of the security policy document? I would like to know why the commits to make the ed25519 unapproved is backported to the |
The downloads page has links to the security policy documents. OpenSSL 3.0 has banned EdDSA by policy, so a technical fix isn't required. This is why you must read the security policy and check for updates because the policy does change over time. |
As for the segmentation fault, are you certain that everything passed in was correct? |
The ossl_pkey_read_generic() should check whether the pkey is non-NULL in between those tries and return early if you already loaded the key. However that is not the problem. What does the call EVP_PKEY_has(pkey, EVP_PKEY_PUBLIC_KEY) return on the returned pkey? |
@paulidale thanks for the link! I found the "security policy" links there. @paulidale and @t8m thanks for the help. As you said, my reproducing program was wrong. And even when the I refactored the program with more strict error handling, and created the ed25519_2.c. And the
Sure. I will try it. But where is the |
As a reference, here is the result in the FIPS case on the master branch.
|
In both security policy documents "openssl-3.0.0-security-policy-2023-01-26.pdf" "openssl-3.0.8-security-policy-2023-05-05.pdf" - "Cryptographic Algorithms", there is the following part. Does it mean the "OpenSSL 3.0 has banned EdDSA by policy", right?
So, maybe a C program using OpenSSL APIs needs to handle this case as an error case. How can I implement it, considering the OpenSSL 3.1, 3.0, 1.1, 1.0 cases? A hint is helpful. |
Oops, sorry, this isn't a public function yet. |
I do not see a need to special case anything. You just do proper error handling and if the decode fails it means the key is not supported. However originally this issue was about some problem with importing/exporting the keys to the FIPS module if the |
@t8m Note my report and my test with The problem is the OpenSSL 3.0 (3.0.8) FIPS case. Because in the case, the decode still succeeds, returning a wrong text. So, I thought our program using OpenSSL APIs needs to handle the case as an error.
The original issue was for OpenSSL 3.0.8 (3.0). Now when testing with OpenSSL 3.0.9, I can reproduce the issue of the original report.
|
Yes, just as I mentioned earlier.
This is where it gets messy. 1.1 and 1.0 don't know about FIPS, so no problem for them. In 3.1 they are correctly flagged in the FIPS provider, so again no problem so long as you do error checking. 3.0 is the problematic case. If you are using the 3.0 FIPS provider, it is your responsibility to enforce that no EdDSA keys are used. This can be done by loading the key regardless and using |
@paulidale All right. I just wanted to confirm just in case. And thanks for explaining the suggested implementation. It's helpful.
I still have a question for your comment above. This means that we shouldn't fix for this issue in OpenSSL 3.0 (
|
That patch would fix the problem but with the side effect of not being FIPS compliant. Any change to the source code, no matter how slight, means not FIPS anymore. Currently you must use the released 3.0.0 or 3.0.8 code unmodified. The technical committee discussed this at length and decided that the paperwork change banning these algorithms was good enough and that a patch to also "fix" the code wasn't required. This approach is fine under the FIPS 140-2 standard that we validated even though it places extra burden on the users of the validation. |
We are really mixing up two issues here which should not be mixed up. One is the problem of whether ED25519 and ED448 are allowed under FIPS or not - simply currently not and an application which wants to be FIPS compliant must not use them. However I do not think this should be solved in Ruby bindings. This is (at least in case of FIPS 140-2 -> 3.0.x FIPS modules) purely application dependent decision and Ruby bindings should NOT try to block it on its own. However this still does not resolve the problem of the wrong handling of ED25519 keys on import/export in case the support is enabled in the FIPS module - we absolutely need to investigate the cause and fix it. |
@paulidale Sure. Thanks for explaining the situation.
@t8m I understood that we shouldn't mix the 2 issues. Thanks for mentioning it. I opened another issue ticket #21493 with a x25519 pem file. Maybe the cause is the same with this issue with an ed25519 pem file in OpenSSL 3.0. However, we can reproduce the issue with x25519 in OpenSSL master branch. I thought that it's more convenient to debug and fix the issue. My concern about not to fix this issue with ed25519 and ed448 in OpenSSL 3.0 on OpenSSL Ruby binding side is that we may see the repeated false positive issue tickets to be opened by someone if we don't fix it. |
Can you please elaborate what would be reported against Ruby bindings? Because I do not understand what you would like to fix in the bindings. |
@t8m Sure. One of the issues reported by me is a mismatch between the original pem file and encoded and decoded text in ed25519 and x25519 in OpenSSL 3.0. ruby/openssl#603 (comment) is the report. As you know, I already opened the issue tickets in this repository. And there are other unit test failures (ruby/openssl#603 (comment)) in the OpenSSL Ruby binding's CI. I am trying to pass all the unit tests in OpenSSL 3.1 and 3.0 FIPS CI cases. I think a reason that I wanted to implement the error handling for the ed25519 and ed448 is that I still don't notice about how much the demerit of implementing the error handling is. However, rethinking again, I changed my mind I will not implement the error handling of the ed25519 and ed448 case in OpenSSL 3.0 in the OpenSSL Ruby binding by following your suggestion. I can just note the situation (the ed25519 and ed448 crypto is only banned in the security policy document, but still allowed in the code) as a comment in the code of the unit tests of OpenSSL Ruby binding. |
This issue is plain bug in OpenSSL and should be fixed by #21519 |
Thank you for the PR! Let me test the fixes with the OpenSSL on the head of the openssl-3.0 branch. |
I think we can close this issue ticket now as the commits on the PR #21519 (comment) were merged to the |
Yep, closing. |
At an unit test in the OpenSSL Ruby binding (https://github.com/ruby/openssl), I see an FIPS mode specific issue related to
ed25519
encryption. In my understanding, the program reads aned25519
public key PEM file and convert it to something, then convert it to the PEM file again. The result of the final PEM file should be the same with the original PEM file. But the content is different with the OpenSSL 3.0.8 FIPS mode.Fortunately I was able to prepare a reproducing program with only C language without Ruby. You can see it below.
The Ruby program
First, just let me share how the issue look like in the OpenSSL Ruby binding. I am testing it on the branch on my forked repository of the
ruby/openssl
, https://github.com/junaruga/openssl/tree/wip/fips-ed25519-report here.In the following case with the ed25519 public key,
Non-FIPS mode
We expect that the following command returns the original
ed25519_pub.pem
's content. And it works with the OpenSSL 3.0.8 non-FIPS mode.FIPS mode
A reproducing program with C
Here is the program, https://github.com/junaruga/report-openssl-fips-ed25519.
Non-FIPS mode
The printed text on the last lines after
[DEBUG] ossl_membio2str buf->data:
are the same with theed25519_pub.pem
.FIPS mode
The printed text is different from with the
ed25519_pub.pem
. Is this an expected behavior?The text was updated successfully, but these errors were encountered: