Skip to content
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: avoid unitializing ECDH objects on error #34302

Closed

Conversation

tniessen
Copy link
Member

The previous code changed the private key of the ECDH object, but removed the public key if deriving it from the private key failed. Instead, if deriving the public key fails, neither the private nor the public key stored in the ECDH object should be updated.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • commit message follows commit guidelines

@tniessen tniessen added crypto Issues and PRs related to the crypto subsystem. openssl Issues and PRs related to the OpenSSL dependency. labels Jul 10, 2020
@nodejs-github-bot nodejs-github-bot added the c++ Issues and PRs that require attention from people who are familiar with C++. label Jul 10, 2020
@nodejs-github-bot
Copy link
Collaborator

@tniessen tniessen added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Jul 17, 2020
@nodejs-github-bot
Copy link
Collaborator

@addaleax
Copy link
Member

I’m guessing this test failure is not unrelated? https://ci.nodejs.org/job/node-test-commit-linux-containered/21411/nodes=ubi81_sharedlibs_openssl111fips_x64/testReport/junit/(root)/test/parallel_test_crypto_dh/

internal/crypto/diffiehellman.js:178
  this[kHandle].setPublicKey(toBuf(key, encoding));
                ^

Error: Failed to convert Buffer to EC_POINT
    at ECDH.setPublicKey (internal/crypto/diffiehellman.js:178:17)
    at Object.<anonymous> (/home/iojs/build/workspace/node-test-commit-linux-containered/test/parallel/test-crypto-dh.js:316:9)
    at Module._compile (internal/modules/cjs/loader.js:1250:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1271:10)
    at Module.load (internal/modules/cjs/loader.js:1099:32)
    at Function.Module._load (internal/modules/cjs/loader.js:964:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
    at internal/main/run_main_module.js:17:47

@addaleax addaleax removed the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Jul 21, 2020
@tniessen
Copy link
Member Author

tniessen commented Aug 14, 2020

I ran the test about 100,000 times locally without errors, so the error seems to be platform-specific.


CI stress test: https://ci.nodejs.org/job/node-stress-single-test/167/

  1. It seems to never fail on rhel7-s390x.

  2. It always fails on alpine-last-latest-x64, alpine-latest-x64 with a crash:

Crash
10:56:17 not ok 1 parallel/test-crypto-dh
10:56:17   ---
10:56:17   duration_ms: 1.313
10:56:17   severity: crashed
10:56:17   exitcode: -11
10:56:17   stack: |-
10:56:17   ...
  1. It seems to be flaky on win10-vs2019, producing either one of these errors:
Failed to convert Buffer to EC_POINT
11:15:26 not ok 1 parallel/test-crypto-dh
11:15:26   ---
11:15:26   duration_ms: 2.214
11:15:26   severity: fail
11:15:26   exitcode: 1
11:15:26   stack: |-
11:15:26     internal/crypto/diffiehellman.js:178
11:15:26       this[kHandle].setPublicKey(toBuf(key, encoding));
11:15:26                     ^
11:15:26     
11:15:26     Error: Failed to convert Buffer to EC_POINT
11:15:26         at ECDH.setPublicKey (internal/crypto/diffiehellman.js:178:17)
11:15:26         at Object.<anonymous> (C:\workspace\node-stress-single-test\nodes\win10-vs2019\test\parallel\test-crypto-dh.js:316:9)
11:15:26         at Module._compile (internal/modules/cjs/loader.js:1252:30)
11:15:26         at Object.Module._extensions..js (internal/modules/cjs/loader.js:1273:10)
11:15:26         at Module.load (internal/modules/cjs/loader.js:1101:32)
11:15:26         at Function.Module._load (internal/modules/cjs/loader.js:966:14)
11:15:26         at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
11:15:26         at internal/main/run_main_module.js:17:47
11:15:26   ...
ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY
11:43:04 not ok 1 parallel/test-crypto-dh
11:43:04   ---
11:43:04   duration_ms: 2.113
11:43:04   severity: fail
11:43:04   exitcode: 1
11:43:04   stack: |-
11:43:04     internal/crypto/diffiehellman.js:127
11:43:04         throw new ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY();
11:43:04         ^
11:43:04     
11:43:04     Error [ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY]: Public key is not valid for specified curve
11:43:04         at new NodeError (internal/errors.js:253:15)
11:43:04         at ECDH.dhComputeSecret [as computeSecret] (internal/crypto/diffiehellman.js:127:11)
11:43:04         at Object.<anonymous> (C:\workspace\node-stress-single-test\nodes\win10-vs2019\test\parallel\test-crypto-dh.js:360:28)
11:43:04         at Module._compile (internal/modules/cjs/loader.js:1252:30)
11:43:04         at Object.Module._extensions..js (internal/modules/cjs/loader.js:1273:10)
11:43:04         at Module.load (internal/modules/cjs/loader.js:1101:32)
11:43:04         at Function.Module._load (internal/modules/cjs/loader.js:966:14)
11:43:04         at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
11:43:04         at internal/main/run_main_module.js:17:47 {
11:43:04       code: 'ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY'
11:43:04     }
11:43:04   ...

New stress test with a few more platforms: https://ci.nodejs.org/job/node-stress-single-test/168/

  1. The test always succeeds on rhel7-s390x, debian9-64, and ubuntu1804-64.
  2. The test always crashes on alpine-last-latest-x64, alpine-latest-x64.
    • crashed (-11)
  3. The test is flaky on win10-vs2019 with only 20 executions succeeding, and 980 failing.
    • crashed (-1073741819)
    • ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY
    • Failed to convert Buffer to EC_POINT
  4. The test is flaky on osx1015 with 979 succeeding, and 21 failing.
    • crashed (-11)
    • ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY

Seems like a memory-related bug. Can reproduce in valgrind on Ubuntu.

The previous code changed the private key of the ECDH object, but
removed the public key if deriving it from the private key failed.
Instead, if deriving the public key fails, neither the private nor
the public key stored in the ECDH object should be updated.
@tniessen tniessen force-pushed the crypto-ec-dont-create-invalid-state branch from 46040f1 to a8c7d72 Compare August 14, 2020 14:16
@tniessen tniessen added the request-ci Add this label to start a Jenkins CI on a PR. label Aug 14, 2020
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Aug 14, 2020
@nodejs-github-bot
Copy link
Collaborator

@tniessen tniessen added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Aug 14, 2020
@tniessen
Copy link
Member Author

Landed in 4a9e312, thanks for reviewing.

@tniessen tniessen closed this Aug 14, 2020
@tniessen tniessen removed the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Aug 14, 2020
tniessen added a commit that referenced this pull request Aug 14, 2020
The previous code changed the private key of the ECDH object, but
removed the public key if deriving it from the private key failed.
Instead, if deriving the public key fails, neither the private nor
the public key stored in the ECDH object should be updated.

PR-URL: #34302
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
MylesBorins pushed a commit that referenced this pull request Aug 17, 2020
The previous code changed the private key of the ECDH object, but
removed the public key if deriving it from the private key failed.
Instead, if deriving the public key fails, neither the private nor
the public key stored in the ECDH object should be updated.

PR-URL: #34302
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
@danielleadams danielleadams mentioned this pull request Aug 20, 2020
BethGriggs pushed a commit that referenced this pull request Aug 20, 2020
The previous code changed the private key of the ECDH object, but
removed the public key if deriving it from the private key failed.
Instead, if deriving the public key fails, neither the private nor
the public key stored in the ECDH object should be updated.

PR-URL: #34302
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
addaleax pushed a commit that referenced this pull request Sep 22, 2020
The previous code changed the private key of the ECDH object, but
removed the public key if deriving it from the private key failed.
Instead, if deriving the public key fails, neither the private nor
the public key stored in the ECDH object should be updated.

PR-URL: #34302
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
addaleax pushed a commit that referenced this pull request Sep 22, 2020
The previous code changed the private key of the ECDH object, but
removed the public key if deriving it from the private key failed.
Instead, if deriving the public key fails, neither the private nor
the public key stored in the ECDH object should be updated.

PR-URL: #34302
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
@codebytere codebytere mentioned this pull request Sep 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. crypto Issues and PRs related to the crypto subsystem. openssl Issues and PRs related to the OpenSSL dependency.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants