-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
crypto: clear error stack in ECDH::BufferToPoint #13275
Conversation
test/parallel/test-crypto-dh.js
Outdated
'pQhByd5eyj3lgZ7m7jbchtdgyOF8Io/1ng==\n' + | ||
'-----END EC PRIVATE KEY-----'; | ||
assert.ok(crypto.createSign('SHA256').sign(ecPrivateKey), | ||
'signing should not throw'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe better to use this instead?:
assert.doesNotThrow(() => {
crypto.createSign('SHA256').sign(ecPrivateKey);
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, will update
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Although I guess that doesn't check that you get a truthy return value. Could be added as an assertion to the function if it's important.)
/cc @nodejs/crypto |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
src/node_crypto.cc
Outdated
@@ -5109,6 +5109,8 @@ EC_POINT* ECDH::BufferToPoint(char* data, size_t len) { | |||
return nullptr; | |||
} | |||
|
|||
MarkPopErrorOnReturn mark_pop_error_on_return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not wrong but I'd put this in ECDH::ComputeSecret()
and ECDH::SetPublicKey()
, the binding functions that call ECDH::BufferToPoint()
.
Maybe we should simply make it a rule that binding functions must restore the error stack.
test/parallel/test-crypto-dh.js
Outdated
curve.generateKeys(); | ||
try { | ||
curve.computeSecret(invalidKey); | ||
assert(false, 'key generation should have failed'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This throws an exception so you still end up in the catch block. The pattern tests usually use is this:
let gotError = false;
try {
// ...
} catch (e) {
gotError = true;
// ...
}
assert(gotError);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with assert.throws()
in this case is that the test case is actually in the catch
block. The pattern @bnoordhuis lays out will work as will the way it is currently done in this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But the test case doesn't have to be in the catch block, or am I just missing something?
assert.throws(() => curve.computeSecret(invalidKey));
const ecPrivateKey = ...;
assert.doesNotThrow(() => crypto.createSign('SHA256').sign(ecPrivateKey));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this last one, thanks for the suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sam-github Ah, yes, you are right.
Functions that call `ECDH::BufferToPoint` were not clearing the error stack on failure, so an invalid key could leave leftover error state and cause subsequent (unrelated) signing operations to fail.
Thanks all, rebased to latest master and updated based on @bnoordhuis @sam-github feedback. |
Will it be possible to uplift this patch to node 4 and 6? |
As a bug fix, it will land on 6.x after being released in 7.x for a while (usually a couple weeks, just to make sure there are no unexpected side effects). 4.x at this point requires an explicit request, we don't release unless we have to. It looks like not clearing the error stack can have wide-reaching consequences, but we prefer to not re-release 4.x unless necessary. @vladikoff @rfk Do you have a need for this on 4.x? Some description of impact will make it much easier to make the case for it in 4.x /cc @nodejs/lts |
This bug affects our app because we happen to do both RSA signing and ECDH with user-submitted keys, so we recently deployed a workaround to production to guard against this being used as a DoS vector (i.e. deliberately submitting invalid ECDH keys to DoS the RSA signing functionality): I think this workaround means we can live without it on 4.x if we have to, although I'm not 100% confident, and I can't comment on how likely other apps are to be affected in a similar way. Having the fix on 4.x would obviously be preferable to this workaround from our point of view, but I understand that's not a trivial ask :-) |
I think that's bad enough it is worth proposing for 4.x LTS |
@sam-github I agree. |
I agree that this is worth backporting to 4.x |
+1 to backporting to v4.x. The next question is how urgently it should happen I guess. |
Is this the first thing that might conceivably be targettable at 4.x? Maybe the thing to do is open an issue in nodejs/LTS to update 4.x, and link any candidates. I haven't heard of any others, but I'm not the best source of news on that front. |
there is a single commit sitting on v4.x-staging and one or two other random small ones that would be good to include. For the most part I believe we have been on top of backporting anything that would be good to have in a maintenance release... we could theoretically re audit against v6.x to double check edit: worth mentioning there was a v4.x release last month... but if this warrants a new release it makes sense |
Landed in f666533 |
Functions that call `ECDH::BufferToPoint` were not clearing the error stack on failure, so an invalid key could leave leftover error state and cause subsequent (unrelated) signing operations to fail. PR-URL: #13275 Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Sam Roberts <[email protected]> Reviewed-By: James M Snell <[email protected]>
It doesn't cherry-pick clean to 4.x or to 6.x, @rfk would you have the time to backport to 6.x? The process is to open a PR targeting v6.x-staging, title would be |
@nodejs/lts 4.8.3 was May 2nd, maybe we could do a 4.8.4 on July 2nd (aprox), to give time for any more patches to come in? 2 months seems a reasonable maintenance cadence. |
Backporting guide is here: https://github.com/nodejs/node/blob/master/doc/guides/backporting-to-release-lines.md |
Sure, I'll try to take a look later today. |
@rfk Thank you. |
Functions that call `ECDH::BufferToPoint` were not clearing the error stack on failure, so an invalid key could leave leftover error state and cause subsequent (unrelated) signing operations to fail. PR-URL: #13275 Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Sam Roberts <[email protected]> Reviewed-By: James M Snell <[email protected]>
Functions that call `ECDH::BufferToPoint` were not clearing the error stack on failure, so an invalid key could leave leftover error state and cause subsequent (unrelated) signing operations to fail. PR-URL: nodejs#13275 Backport-PR-URL: nodejs#13397 Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Sam Roberts <[email protected]> Reviewed-By: James M Snell <[email protected]>
Functions that call `ECDH::BufferToPoint` were not clearing the error stack on failure, so an invalid key could leave leftover error state and cause subsequent (unrelated) signing operations to fail. PR-URL: #13275 Backport-PR-URL: #13397 Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Sam Roberts <[email protected]> Reviewed-By: James M Snell <[email protected]>
Functions that call `ECDH::BufferToPoint` were not clearing the error stack on failure, so an invalid key could leave leftover error state and cause subsequent (unrelated) signing operations to fail. PR-URL: #13275 Backport-PR-URL: #13399 Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Sam Roberts <[email protected]> Reviewed-By: James M Snell <[email protected]>
Functions that call `ECDH::BufferToPoint` were not clearing the error stack on failure, so an invalid key could leave leftover error state and cause subsequent (unrelated) signing operations to fail. PR-URL: #13275 Backport-PR-URL: #13397 Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Sam Roberts <[email protected]> Reviewed-By: James M Snell <[email protected]>
Functions that call `ECDH::BufferToPoint` were not clearing the error stack on failure, so an invalid key could leave leftover error state and cause subsequent (unrelated) signing operations to fail. PR-URL: #13275 Backport-PR-URL: #13399 Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Sam Roberts <[email protected]> Reviewed-By: James M Snell <[email protected]>
Functions that call `ECDH::BufferToPoint` were not clearing the error stack on failure, so an invalid key could leave leftover error state and cause subsequent (unrelated) signing operations to fail. PR-URL: #13275 Backport-PR-URL: #13399 Reviewed-By: Fedor Indutny <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Sam Roberts <[email protected]> Reviewed-By: James M Snell <[email protected]>
The
ECDH::BufferToPoint
function was not clearing the error stack on failure, and the leftover error state could cause subsequent (unrelated) signing operations to fail. This updates the function to use existing error-clearing helpers and seems to resolve the problem for me.Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)