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.generatePrime results in an abort in FIPS mode #56377

Open
zyscoder opened this issue Dec 27, 2024 · 6 comments
Open

crypto.generatePrime results in an abort in FIPS mode #56377

zyscoder opened this issue Dec 27, 2024 · 6 comments
Labels
confirmed-bug Issues with confirmed bugs. crypto Issues and PRs related to the crypto subsystem.

Comments

@zyscoder
Copy link

Version

v22.11.0

Platform

Linux u24vm 6.8.0-50-generic #51-Ubuntu SMP PREEMPT_DYNAMIC Sat Nov  9 17:58:29 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

Subsystem

crypto

What steps will reproduce the bug?

Setup a node instance,

» node

and run the following javascript code.

_crypto = require('crypto');
_crypto.setFips(true);
_crypto.generatePrime(64,()=>{});

Then the node instance occurs an abort.

How often does it reproduce? Is there a required condition?

This abort can always be triggered following the steps above.

What is the expected behavior? Why is that the expected behavior?

If any error occurs, an exception or similar error-reporting stuff should be thrown, caught, and handled correctly. There is no reason to abort the whole node process.

What do you see instead?

» node                                                                                                       
Welcome to Node.js v22.11.0.
Type ".help" for more information.
> _crypto = require('crypto');
{
  checkPrime: [Function: checkPrime],
  checkPrimeSync: [Function: checkPrimeSync],
  createCipheriv: [Function: createCipheriv],
  createDecipheriv: [Function: createDecipheriv],
  createDiffieHellman: [Function: createDiffieHellman],
  createDiffieHellmanGroup: [Function: createDiffieHellmanGroup],
  createECDH: [Function: createECDH],
  createHash: [Function: createHash],
  createHmac: [Function: createHmac],
  createPrivateKey: [Function: createPrivateKey],
  createPublicKey: [Function: createPublicKey],
  createSecretKey: [Function: createSecretKey],
  createSign: [Function: createSign],
  createVerify: [Function: createVerify],
  diffieHellman: [Function: diffieHellman],
  generatePrime: [Function: generatePrime],
  generatePrimeSync: [Function: generatePrimeSync],
  getCiphers: [Function (anonymous)],
  getCipherInfo: [Function: getCipherInfo],
  getCurves: [Function (anonymous)],
  getDiffieHellman: [Function: createDiffieHellmanGroup],
  getHashes: [Function (anonymous)],
  hkdf: [Function: hkdf],
  hkdfSync: [Function: hkdfSync],
  pbkdf2: [Function: pbkdf2],
  pbkdf2Sync: [Function: pbkdf2Sync],
  generateKeyPair: [Function: generateKeyPair],
  generateKeyPairSync: [Function: generateKeyPairSync],
  generateKey: [Function: generateKey],
  generateKeySync: [Function: generateKeySync],
  privateDecrypt: [Function (anonymous)],
  privateEncrypt: [Function (anonymous)],
  publicDecrypt: [Function (anonymous)],
  publicEncrypt: [Function (anonymous)],
  randomBytes: [Function: randomBytes],
  randomFill: [Function: randomFill],
  randomFillSync: [Function: randomFillSync],
  randomInt: [Function: randomInt],
  randomUUID: [Function: randomUUID],
  scrypt: [Function: scrypt],
  scryptSync: [Function: scryptSync],
  sign: [Function: signOneShot],
  setEngine: [Function: setEngine],
  timingSafeEqual: [Function (anonymous)],
  getFips: [Function: getFips],
  setFips: [Function: setFips],
  verify: [Function: verifyOneShot],
  hash: [Function: hash],
  Certificate: [Function: Certificate] {
    exportChallenge: [Function: exportChallenge],
    exportPublicKey: [Function: exportPublicKey],
    verifySpkac: [Function: verifySpkac]
  },
  Cipher: undefined,
  Cipheriv: [Function: Cipheriv],
  Decipher: undefined,
  Decipheriv: [Function: Decipheriv],
  DiffieHellman: [Function: DiffieHellman],
  DiffieHellmanGroup: [Function: DiffieHellmanGroup],
  ECDH: [Function: ECDH] { convertKey: [Function: convertKey] },
  Hash: [Function: deprecated],
  Hmac: [Function: deprecated],
  KeyObject: [class KeyObject],
  Sign: [Function: Sign],
  Verify: [Function: Verify],
  X509Certificate: [class X509Certificate],
  secureHeapUsed: [Function: secureHeapUsed],
  constants: [Object: null prototype] {
    OPENSSL_VERSION_NUMBER: 805306608,
    SSL_OP_ALL: 2147485776,
    SSL_OP_ALLOW_NO_DHE_KEX: 1024,
    SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: 262144,
    SSL_OP_CIPHER_SERVER_PREFERENCE: 4194304,
    SSL_OP_CISCO_ANYCONNECT: 32768,
    SSL_OP_COOKIE_EXCHANGE: 8192,
    SSL_OP_CRYPTOPRO_TLSEXT_BUG: 2147483648,
    SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: 2048,
    SSL_OP_LEGACY_SERVER_CONNECT: 4,
    SSL_OP_NO_COMPRESSION: 131072,
    SSL_OP_NO_ENCRYPT_THEN_MAC: 524288,
    SSL_OP_NO_QUERY_MTU: 4096,
    SSL_OP_NO_RENEGOTIATION: 1073741824,
    SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: 65536,
    SSL_OP_NO_SSLv2: 0,
    SSL_OP_NO_SSLv3: 33554432,
    SSL_OP_NO_TICKET: 16384,
    SSL_OP_NO_TLSv1: 67108864,
    SSL_OP_NO_TLSv1_1: 268435456,
    SSL_OP_NO_TLSv1_2: 134217728,
    SSL_OP_NO_TLSv1_3: 536870912,
    SSL_OP_PRIORITIZE_CHACHA: 2097152,
    SSL_OP_TLS_ROLLBACK_BUG: 8388608,
    ENGINE_METHOD_RSA: 1,
    ENGINE_METHOD_DSA: 2,
    ENGINE_METHOD_DH: 4,
    ENGINE_METHOD_RAND: 8,
    ENGINE_METHOD_EC: 2048,
    ENGINE_METHOD_CIPHERS: 64,
    ENGINE_METHOD_DIGESTS: 128,
    ENGINE_METHOD_PKEY_METHS: 512,
    ENGINE_METHOD_PKEY_ASN1_METHS: 1024,
    ENGINE_METHOD_ALL: 65535,
    ENGINE_METHOD_NONE: 0,
    DH_CHECK_P_NOT_SAFE_PRIME: 2,
    DH_CHECK_P_NOT_PRIME: 1,
    DH_UNABLE_TO_CHECK_GENERATOR: 4,
    DH_NOT_SUITABLE_GENERATOR: 8,
    RSA_PKCS1_PADDING: 1,
    RSA_NO_PADDING: 3,
    RSA_PKCS1_OAEP_PADDING: 4,
    RSA_X931_PADDING: 5,
    RSA_PKCS1_PSS_PADDING: 6,
    RSA_PSS_SALTLEN_DIGEST: -1,
    RSA_PSS_SALTLEN_MAX_SIGN: -2,
    RSA_PSS_SALTLEN_AUTO: -2,
    defaultCoreCipherList: 'TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA256:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA',
    TLS1_VERSION: 769,
    TLS1_1_VERSION: 770,
    TLS1_2_VERSION: 771,
    TLS1_3_VERSION: 772,
    POINT_CONVERSION_COMPRESSED: 2,
    POINT_CONVERSION_UNCOMPRESSED: 4,
    POINT_CONVERSION_HYBRID: 6,
    defaultCipherList: [Getter/Setter]
  },
  webcrypto: [Getter],
  subtle: [Getter],
  getRandomValues: [Getter]
}
> _crypto.setFips(true);
undefined
> _crypto.generatePrime(64,()=>{});

  #  node[337926]: static bool node::crypto::RandomPrimeTraits::DeriveBits(node::Environment*, const node::crypto::RandomPrimeConfig&, node::crypto::ByteSource*) at ../src/crypto/crypto_random.cc:151
  #  Assertion failed: ncrypto::CSPRNG(nullptr, 0)

----- Native stack trace -----

undefined
>  1: 0xf76527 node::Assert(node::AssertionInfo const&) [node]
 2: 0x115c1ba non-virtual thunk to node::crypto::DeriveBitsJob<node::crypto::RandomPrimeTraits>::DoThreadPoolWork() [node]
 3: 0xf32bc1 node::ThreadPoolWork::ScheduleWork()::{lambda(uv_work_s*)#1}::_FUN(uv_work_s*) [node]
 4: 0x1d27b80  [node]
 5: 0x78901ba9ca94  [/lib/x86_64-linux-gnu/libc.so.6]
 6: 0x78901bb29c3c  [/lib/x86_64-linux-gnu/libc.so.6]
[1]    337926 IOT instruction (core dumped)  node

Additional information

No response

@lpinca lpinca added the crypto Issues and PRs related to the crypto subsystem. label Dec 27, 2024
@himself65
Copy link
Member

const crypto = require('node:crypto');

crypto.setFips(true);
crypto.generatePrime(64,()=>{});
➜  node git:(main) ✗ out/Debug/node ./main.js

  #  out/Debug/node[75750]: static bool node::crypto::RandomPrimeTraits::DeriveBits(Environment *, const RandomPrimeConfig &, ByteSource *) at ../src/crypto/crypto_random.cc:151
  #  Assertion failed: ncrypto::CSPRNG(nullptr, 0)

----- Native stack trace -----

 1: 0x100590390 node::DumpNativeBacktrace(__sFILE*) [/Users/himself65/Code/node/out/Debug/node]
 2: 0x1006fce3c node::Assert(node::AssertionInfo const&) [/Users/himself65/Code/node/out/Debug/node]
 3: 0x100a24900 node::crypto::RandomPrimeTraits::DeriveBits(node::Environment*, node::crypto::RandomPrimeConfig const&, node::crypto::ByteSource*) [/Users/himself65/Code/node/out/Debug/node]
 4: 0x100a27934 node::crypto::DeriveBitsJob<node::crypto::RandomPrimeTraits>::DoThreadPoolWork() [/Users/himself65/Code/node/out/Debug/node]
 5: 0x100671608 node::ThreadPoolWork::ScheduleWork()::'lambda'(uv_work_s*)::operator()(uv_work_s*) const [/Users/himself65/Code/node/out/Debug/node]
 6: 0x10067151c node::ThreadPoolWork::ScheduleWork()::'lambda'(uv_work_s*)::__invoke(uv_work_s*) [/Users/himself65/Code/node/out/Debug/node]
 7: 0x1023c47c0 uv__queue_work [/Users/himself65/Code/node/out/Debug/node]
 8: 0x1023c510c worker [/Users/himself65/Code/node/out/Debug/node]
 9: 0x19e1042e4 _pthread_start [/usr/lib/system/libsystem_pthread.dylib]
10: 0x19e0ff0fc thread_start [/usr/lib/system/libsystem_pthread.dylib]
[1]    75750 abort      out/Debug/node ./main.j

@jasnell jasnell added the confirmed-bug Issues with confirmed bugs. label Jan 6, 2025
@himself65
Copy link
Member

might related to #46200

@himself65
Copy link
Member

I saw one possible bug here, my mac doesn't support FIPS

out/Debug/node --force-fips ./main.js
out/Debug/node: OpenSSL error when trying to enable FIPS:
40429E0702000000:error:12800067:DSO support routines:dlfcn_load:could not load the shared library:../deps/openssl/openssl/crypto/dso/dso_dlfcn.c:118:filename(/Users/himself65/Code/node/out/$(BUILDTYPE)/obj.target/deps/openssl/lib/openssl-modules/fips.dylib): dlopen(/Users/himself65/Code/node/out/$(BUILDTYPE)/obj.target/deps/openssl/lib/openssl-modules/fips.dylib, 0x0002): tried: '/Users/himself65/Code/node/out/$(BUILDTYPE)/obj.target/deps/openssl/lib/openssl-modules/fips.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/himself65/Code/node/out/$(BUILDTYPE)/obj.target/deps/openssl/lib/openssl-modules/fips.dylib' (no such file), '/Users/himself65/Code/node/out/$(BUILDTYPE)/obj.target/deps/openssl/lib/openssl-modules/fips.dylib' (no such file)

@himself65
Copy link
Member

with nvm version

➜  node git:(main) ✗ node --force-fips ./main.js
node: OpenSSL error when trying to enable FIPS:
40429E0702000000:error:12800067:DSO support routines:dlfcn_load:could not load the shared library:../deps/openssl/openssl/crypto/dso/dso_dlfcn.c:118:filename(/Users/iojs/build/ws/out/$(BUILDTYPE)/obj.target/deps/openssl/lib/openssl-modules/fips.dylib): dlopen(/Users/iojs/build/ws/out/$(BUILDTYPE)/obj.target/deps/openssl/lib/openssl-modules/fips.dylib, 0x0002): tried: '/Users/iojs/build/ws/out/$(BUILDTYPE)/obj.target/deps/openssl/lib/openssl-modules/fips.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Users/iojs/build/ws/out/$(BUILDTYPE)/obj.target/deps/openssl/lib/openssl-modules/fips.dylib' (no such file), '/Users/iojs/build/ws/out/$(BUILDTYPE)/obj.target/deps/openssl/lib/openssl-modules/fips.dylib' (no such file)

P.S. why it's iojs? looks like this is static file path?

@himself65 himself65 changed the title crypto.generatePrime results in an abort crypto.generatePrime results in an abort in FIPS mode Jan 6, 2025
@jasnell
Copy link
Member

jasnell commented Jan 6, 2025

I was able to reproduce the issue on ubuntu so it's not related to that I do not think. This is specific to something with the random number generation in fips mode. Will be investigating

@richardlau
Copy link
Member

richardlau commented Jan 6, 2025

CSPRNG() can fail if OpenSSL cannot find an appropriate algorithm to use.

#if OPENSSL_VERSION_MAJOR >= 3
const auto code = ERR_peek_last_error();
// A misconfigured OpenSSL 3 installation may report 1 from RAND_poll()
// and RAND_status() but fail in RAND_bytes() if it cannot look up
// a matching algorithm for the CSPRNG.
if (ERR_GET_LIB(code) == ERR_LIB_RAND) {
const auto reason = ERR_GET_REASON(code);
if (reason == RAND_R_ERROR_INSTANTIATING_DRBG ||
reason == RAND_R_UNABLE_TO_FETCH_DRBG ||
reason == RAND_R_UNABLE_TO_CREATE_DRBG) {
return false;
}
}
#endif

Specifically with crypto.setFips(true); Node.js instructs OpenSSL to only use algorithms which have the fips=yes property set. If you do not have a properly configured FIPS set up then there will be no matching algorithms, causing CSNPRG() to fail which then trips this CHECK():

// Make sure the CSPRNG is properly seeded.
CHECK(ncrypto::CSPRNG(nullptr, 0));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug Issues with confirmed bugs. crypto Issues and PRs related to the crypto subsystem.
Projects
None yet
Development

No branches or pull requests

5 participants