Repository navigation
crypto: fix race breaking RSA-PSS key decoding - #66935
Closed
christianaurichzm wants to merge 1 commit into
Closed
christianaurichzm wants to merge 1 commit into
christianaurichzm wants to merge 1 commit into
Conversation
Since 43d3fe9, startup no longer fetches anything from OpenSSL, so the first fetch can happen on a thread pool crypto job, on the root certificate loader that `require('tls')` starts, or in a Worker. OpenSSL 3 copies its legacy algorithm names into the name map on that first fetch, and other threads can look names up before the copy is done. An RSA-PSS key decoded on the main thread meanwhile resolves its OID name, `rsassaPss`, to nothing, and OpenSSL 3.5 caches the resulting empty decoder set. From then on every RSA-PSS public key decode in the process fails with `ERR_OSSL_EVP_DECODE_ERROR`. Do one fetch on the calling thread before a crypto job runs, before the certificate loading threads start, and before a Worker thread starts. Signed-off-by: Christian Aurich Zanettini Martins <christian.aurichzm@gmail.com>
Collaborator
|
Review requested:
|
Contributor
Author
Member
|
@christianaurichzm see #66903, i think this isn't needed when we revert the PRs that triggered this. |
Contributor
Author
|
Thanks, I hadn't seen #66903. I tried main with the revert and all three cases here pass (0 of 3000), so I'm closing this one. The revert doesn't add a test for this though. Want me to send |
Member
|
That would be nice, i also have a repro script in that PR's comment, see if you can combine yours with mine (if that makes sense), up to you. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #66935 +/- ##
==========================================
- Coverage 90.59% 90.58% -0.02%
==========================================
Files 797 797
Lines 278475 278482 +7
Branches 53533 53539 +6
==========================================
- Hits 252293 252255 -38
- Misses 16532 16560 +28
- Partials 9650 9667 +17
🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An RSA-PSS public key can fail to decode when the first OpenSSL fetch of the process happens on a thread that Node.js started, and from then on every RSA-PSS decode in the process fails:
The same happens with
require('tls'), which loads the root certificates on another thread, and with a Worker that hashes something as it starts. It is also the intermittentparallel/test-crypto-x509failure on GitHub Actions since 697ecce addedrequire('tls')to that test (1, 2, 3). [2] ran onv26.x-staging.On the first fetch, OpenSSL 3 copies its legacy algorithm names into the name map (
ossl_namemap_stored()). The empty check and the copy are not under one lock, so another thread can look names up while the copy is still running. The SPKI decoder looks the key type up by the long name of its OID (x_pubkey.c), which for RSA-PSS isrsassaPss, and the 3.5 default provider doesn't register that name. In that window it resolves to nothing, and the empty decoder set gets cached. Until #65796 the CSPRNG check at startup did the first fetch before any other thread existed, and v22.23.1 doesn't fail.This adds
EnsureOpenSSLNameMap(), which does one fetch on the calling thread, once per process. It runs before a crypto job is scheduled, before the certificate loading threads start and before a Worker thread starts. Startup still does no fetch. The firstpbkdf2(),require('tls')ornew Worker()gets 0.3 to 0.5 ms slower, once.Over 3000 runs, 16 at a time, failures go from 832 to 0 with
pbkdf2(), from 44 to 0 withrequire('tls')and from 264 to 0 with a Worker.test/parallel/test-crypto-off-thread-first-use.jsfails onmainand passes with this change, andparallel,sequentialandcctestpass locally. Threads that a native addon starts itself are still not covered.Refs: #65796