-
Notifications
You must be signed in to change notification settings - Fork 835
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
[Bug]: Invalid CSR generated by ESP32s3 #6205
Comments
@anhu will you review this or assign to another engineer? Jim is traveling next week. |
Hi @PaulMartinsen , Thank you very much for all the details. I have read your report very carefully and reproduced what you have seen on windows on my linux machine. Her are my steps (for the benefit of future readers):
Interestingly, when I use openssl to generate a CSR with the same private key, the same thing happens:
This would make me agree with you that there is a problem with the private key. However, I find it strange that the problem would manifest itself in the usage of the public key that is based on the private key and not usage of the private key itself. I will first do my best to better understand what kind of problem OpenSSL is encountering and report my findings here. However, please note that I do not have the ESP hardware. As such, once I report my findings, I will need to assign to another developer who has the relevant hardware. Warm regards, Anthony |
It would appear that OpenSSL is expecting this format of padding:
I think this is called PKCS1 padding. Instead of getting the initial 0, it is finding a value of decimal 135. So, it would appear the padding is being done incorrectly. I will need to dig into this a big deeper. @PaulMartinsen , I'm unfamiliar with the ESP hardware acceleration code and hardware. I will need to lookup whether it is the code or the hardware that is responsible for the padding. Please stay tuned while I do the research. If you can provide insights, I'd really appreciate it. Warm regards, Anthony |
Hi @anhu , thanks very much for your analysis. A great idea to use the private key to sign a CSR locally. My understanding is the ESP hardware accelerates low level operations (e.g., Z = X * Y (mod M) ; Z = X^Y mod M), SHA and AES operations. I don't know enough about how the private key's are generated to know where the padding is being done though. I do have TLSv1.3 connections working on the ESP32s3 using the hardware acceleration and @gojimmypi has fixed some issues in SHA (that's the branch I mentioned above). Is there a function in the library to load a PEM private key? I could upload a private key onto the device then do the CSR on that to confirm the private key is the issue if that were useful. I couldn't find a library function for that though. Another possibility would be to use the Wolf library to make a CSR using the bad private key. Would we expect the problem to be detected by Have a great day |
Hi @PaulMartinsen , |
Thanks @anhu . I modified the code sample from above to load the private key I'd previously made with OpenSSL and loaded onto the ESP32s3 instead of calling
So that doesn't have the self-signature miss-match I see when using
|
Hi @PaulMartinsen , Wow. Thank you so much for your prompt reaction time and hard work!! It seems quite clear to me now that when the private key is generated, it has the public components in it. Then, when the CSR is generated, the public components are just being copied into the CSR. Once the public key is then actually used to verify the CSR, the padding problem is discovered. As you said in your original post, this only happens when ESP32s3 acceleration is enabled. Please forgive my ignorance, but can you please let me know which flag/macro turns on ESP32s3 acceleration? Warm regards, Anthony |
Is this an urgent issue for you? Is temporarily disabling hardware acceleration a viable temporary solution? Warm regards, Anthony |
For the benefit of future readers: I have looked in the code where Warm regards, Anthony |
Hi @PaulMartinsen , The next sensible step would be to turn off hardware acceleration and see the differences in the csr that are generated. Can you try that? I do not have the correct hardware so I can't try that. Note that @gojimmypi will be helping here to setup an environment to reproduce what you are seeing. However, due to other activities he will have limited time to work on this. I'm assigning this to him, but will continue to monitor and help out on this issue. |
Oh, the unaccelerated version is in the zip file. Let me look into that. |
Hi @anhu This isn't a blocking problem for me at the moment as I can load externally generated keys onto the device. But I'm keenly interestedin, and happy to help with, its resolution :). I add the following pre-processor symbols to
BTW, I just tried I'm not quite sure what you mean by comparing the CSR with and without hardware acceleration. I'm generating a separate private key each time. Since you saw the same problem with OpenSSL, I'm not sure if reusing the hardware acceleration generated private key in a non-hardware accelerated CSR will tell us anything new? Did I missunderstand? Thanks for your help with this. Much appreciated. BTW, I'm in New Zealand. We are about 12 hours behind GMT, so sometimes there might be delays in my responses :) |
I'm not so worried about the delays in responses, but thanks for letting me know. I just like to keep my notes here in case I need to move onto something else and another developer needs some context. |
Hi @PaulMartinsen ,
So I wanted to confirm that the format of the padding was conforming to this:
And it is!! I saw a 0, about 200 FF bytes, and a 0 and then some other bytes after that. I need to talk to my colleagues. Please stay tuned. Warm regards, Anthony |
Sorry, I've made a rookie mistake. I thought this was a problem with padding, but actually this indicates that there are problems somewhere else in the cryptographic procedure. Basically, the verify operation is failing. To get a better idea of the root cause we would need to override the RNG with a fake RNG that gives deterministic data (ie a buffer of incremented byte values) and see what the difference is between hardware acceleration and no hardware acceleration. Warm regards, Anthony |
Heh. @anhu , i don't think that's a mistake; could be anything! To me, the real mystery is why the bad private key doesn't raise an error earlier. I'm using the hardware random number generator. With the following
I removed the I'm not sure what you had in mind by a deterministic data, but I put the custom settings back and modified the random number generator as shown below. I tried to create a new private key and CSR, but after more than 5 minutes it wasn't done (normally takes about 30 seconds). To me it looked like the code was trying to find a prime number so maybe my crude sequential RNG isn't up to the job?
|
FWIW, I generated a 512 bit key and CSR on the ESP32s3 (previous keys have been 2048 bits). But I still see the signature miss-match error. |
For those following along, I looked at the docs and the csr example and created a VisualGDB example & README for a sample ESP32 app that creates a RSA Key cert:
I manually copied the console output and saved to a file, for example
Adjusting the default user_settings.h both enabling and disabling this section for either no hardware or use hardware acceleration:
In each case, with a hardware-generated cert or not, both files could be successfully signed. So it appears this is not a hardware acceleration issue, rather a possible incompatible settings. Thanks @PaulMartinsen for the tips on using OpenSSL: Create request:SRC=gojimmypi_private_rsa_generated_key_hw.txt
CSR_OUT=$SRC-CertificateRequest.csr
DEVICE_ID=4243
openssl req -new -key ./input/$SRC \
-nodes \
-out ./output/$CSR_OUT \
-subj "/C=NZ/ST=Waikato/L=Hamilton/O=Blue Leaf Software Ltd/CN=Lumos-%DeviceId%/serialNumber=$DEVICE_ID" \
-addext "subjectAltName = URI:dev:ops:59430-Lumos-$DEVICE_ID" \
-addext "extendedKeyUsage = serverAuth, clientAuth" Sign the request:
SettingsA side note: I'm not sure about the impact of having a relative include path to a separate header file from the wolfSSL In the coming days I'll wrap up this example and save it over on the wolfssl-examples/ESP32. I'll also add some code to make a cert request from the ESP32. I'll take a closer look at the original settings to see if there was some sort of conflict that could be detected and flagged with a warning. |
That's a useful test case @gojimmypi . A couple of suggestions:
It looks like key size plays a role in this problem. Consider two processes:
OpenSSL here refers to
Unfortunately, relative paths are a necessary side effect of multiple targets, build systems and finite resources for me. But I agree, simpler is better! |
Follow up observation for Process 2 with 1024 bit keys. OpenSSL reports the subject in the signed CSR as: I noticed |
@PaulMartinsen I've been able to duplicate your issue on the ESP32-S3, even with fresh code and what I believe to be a good Shown below is a table of RSA key bit length sizes, along with whether the keys were generated with HW or SW. This latest version of code is using wolfSSL to create and sign the generated CSR. The links in this table are to
The
Note the naming convention is The code has a
Now to figure out why only HW 512 and 2048 bit lengths have OpenSSL complain about signature mismatches, with otherwise no errors or indications of any sort of problems. |
I have an interim solution in place for this on my ED25519_SHA2_fix branch. The current wolfSSL master branch will need to completely turn off one of the hardware encryption features: I've confirmed this is problematic on Xtensa architectures: ESP32 and ESP32-S3 with wolfSSL hardware encryption turned on.. As it turns out, the cause of the certificate signature failure is in the wolfcrypt/tfc.c for certain RSA bit lengths when Espressif Hardware Acceleration is turned on. There are 2 different problems. The first is when doing RSA 512 bit: the fp_exptmod( ) returns an incorrect result when calling the HW The other one is for RSA 1024 bit: the mp_mulmod( ) returns a incorrect result. Note this one is related to the Curiously, the wolfssl_test passes all of the tests. Clearly there's a missing test that I'll need to add. As this is not a SHA test, I've not yet decided if I create a new issue, or just rename #5989. For now, I've added compile-time macro gating that detects and falls back to software calculations for both of the problematic Espressif HW calcs. This requires that the RSA bit length be defined in the
Currently if this is not defined, and the TFM As a side note: For experimenting with various settings that get assigned with
but these are apparently enabled by default:
Note that I've also added As noted above, this is tested with the the cert_peek.sh script that has since been updated to also accept a 3rd parameter for target chip set. (ESP32 or ESP32-C3 or ESP32-S3) To test with existing files, there are 6 new files with a I'll need more time to dig into |
Great work @gojimmypi !! |
Hi @PaulMartinsen a brief update: I'm still working on a better solution than just disabling the known problematic key lengths as noted in #6286. I believe I have found the root cause. As the problem is not reproducible, even on a fixed binary when running the same code after fresh reboot, more testing is in order before I can confirm. |
Thanks for persisting with this @gojimmypi . I've been using 1024-bit keys for now, which are okay for testing, but this is going to be another important bug-fix for the library! Appreciate your hard work on this. |
Hi @PaulMartinsen - thank you! Indeed I've learned a lot during this exercise! At this point, I believe I have found the root cause of this issue. I have an initial fix with on my ED25519_SHA2_fix branch. The problem seems to be a simple sign issue as noted in #6359, specifically related to the I need to clean up my code and perform more testing, but I wanted you to have this information as soon as possible. It's curious that this problem does not manifest itself in other key sizes, such as the 1024-bit keys that you are using. I do need to revisit the operand pointer issue originally noted in #6359 and convince myself there's no problem there. |
In addition to the sign issue in esp_mp_mul described above and shown here: It appears there's another problem in esp_mp_exptmod where although the answer seems the same, the When this condition is encountered, the CSR signing process fails. |
That's very interesting @gojimmypi . Mind boggling that the 1024-bit keys seem to work okay (I've made a few 1024-bit ones since we first found this issue, still with no problems). So I guess wrong math can give the right answer sometimes! Thanks again for your persistence with this, rather thorny, problem. Much appreciated! |
Hi @PaulMartinsen just an update on this topic: I've certainly not forgotten this issue even though there's be no recent update here. In fact, it continues to have my undivided attention. I've found a variety of peripheral issues and improvements that I'm working on. (e.g. see ESP32 Errata) The end result should be quite nice. I'm also adding an entire testing infrastructure that will greatly ease the development and validation of the new ESP32-C3/C6 RISC-V Architecture, as soon as I can wrap up the ESP32/S3 Xtensa. This new feature has certainly be quite helpful to confirm proper operation using the wolfcrypt tests. Thanks very much for your patience. Cheers |
Fantastic to see this one resolved. Thanks to all and particularly @gojimmypi for all your hard work on it. Much appreciated! |
Contact Details
No response
Version
Jim/ED25519_SHA2_fix
Description
Library creates an invalid certificate signing request on the ESP32s3 when hardware acceleration is enabled. A valid signing request is generated with hardware acceleration disabled, or the code running on a Windows target. Previously I've seen the same problem on the ESP32 and even with hardware acceleration disabled. Have tested on a recent master branch and also ED25519_SHA2_fix. I used @gojimmypi 's branch as he has a lot of fixes for the Espressif implementation of the library.
Output from the signing command when supplied with a good CSR (ESP32s3 without h/w acceleration):
Output from the signing command when supplied with a bad CSR (ESP32s3 with h/w acceleration):
If I take the private key that's generated on the device I can create a CSR as below (in Windows), but that produces the same error message as above when I try to sign the CSR as above suggesting the problem might be with the private key.
openssl req -new -key "Input\BLS-001 - ESP32s3 - HW acceleration - New private key - Jim ED25519_SHA2_fix.pem" -nodes -out Output\BLS-001-req.csr
Code used to generate a private key and signing request on the device:
Also attached, WolfSSL user_settings.zip files, Keys and certificate signing requests.zip
Reproduction steps
No response
Relevant log output
No response
The text was updated successfully, but these errors were encountered: