diff --git a/deps/ncrypto/ncrypto.cc b/deps/ncrypto/ncrypto.cc index 07049405de6239..b7a0c96ee2ea60 100644 --- a/deps/ncrypto/ncrypto.cc +++ b/deps/ncrypto/ncrypto.cc @@ -147,7 +147,12 @@ DataPointer DataPointer::SecureAlloc(size_t len) { #ifndef OPENSSL_IS_BORINGSSL auto ptr = OPENSSL_secure_zalloc(len); if (ptr == nullptr) return {}; - return DataPointer(ptr, len, true); + // OPENSSL_secure_zalloc transparently falls back to a regular allocation + // when the secure heap is not initialized or is exhausted. Reflect the + // actual provenance of the pointer so that reset() routes to the correct + // free function (OPENSSL_secure_clear_free vs. OPENSSL_clear_free) and + // callers of isSecure() get a truthful answer. + return DataPointer(ptr, len, CRYPTO_secure_allocated(ptr) == 1); #else // BoringSSL does not implement the OPENSSL_secure_zalloc API. auto ptr = OPENSSL_malloc(len); @@ -3103,9 +3108,13 @@ const Cipher Cipher::AES_256_GCM = Cipher::FromNid(NID_aes_256_gcm); const Cipher Cipher::AES_128_KW = Cipher::FromNid(NID_id_aes128_wrap); const Cipher Cipher::AES_192_KW = Cipher::FromNid(NID_id_aes192_wrap); const Cipher Cipher::AES_256_KW = Cipher::FromNid(NID_id_aes256_wrap); + +#ifndef OPENSSL_IS_BORINGSSL const Cipher Cipher::AES_128_OCB = Cipher::FromNid(NID_aes_128_ocb); const Cipher Cipher::AES_192_OCB = Cipher::FromNid(NID_aes_192_ocb); const Cipher Cipher::AES_256_OCB = Cipher::FromNid(NID_aes_256_ocb); +#endif + const Cipher Cipher::CHACHA20_POLY1305 = Cipher::FromNid(NID_chacha20_poly1305); bool Cipher::isGcmMode() const { diff --git a/deps/ncrypto/ncrypto.h b/deps/ncrypto/ncrypto.h index 4f86702da88267..1f116169f57a27 100644 --- a/deps/ncrypto/ncrypto.h +++ b/deps/ncrypto/ncrypto.h @@ -309,9 +309,12 @@ class Cipher final { #else static constexpr size_t MAX_AUTH_TAG_LENGTH = 16; #endif - static_assert(EVP_GCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH && - EVP_CCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH && - EVP_CHACHAPOLY_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH); + static_assert(EVP_GCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH +#ifndef OPENSSL_IS_BORINGSSL + && EVP_CCM_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH && + EVP_CHACHAPOLY_TLS_TAG_LEN <= MAX_AUTH_TAG_LENGTH +#endif + ); // NOLINT(whitespace/parens) Cipher() = default; Cipher(const EVP_CIPHER* cipher) : cipher_(cipher) {} diff --git a/src/crypto/crypto_cipher.cc b/src/crypto/crypto_cipher.cc index 638dda0ad10593..2e9acf86099ee8 100644 --- a/src/crypto/crypto_cipher.cc +++ b/src/crypto/crypto_cipher.cc @@ -447,8 +447,10 @@ bool CipherBase::InitAuthenticated(const char* cipher_type, // Other modes (CCM, OCB) require an explicit tag length. if (ctx_.isGcmMode()) { auth_tag_len = EVP_GCM_TLS_TAG_LEN; +#ifdef EVP_CHACHAPOLY_TLS_TAG_LEN } else if (ctx_.isChaCha20Poly1305()) { auth_tag_len = EVP_CHACHAPOLY_TLS_TAG_LEN; +#endif } else { THROW_ERR_CRYPTO_INVALID_AUTH_TAG( env(), "authTagLength required for %s", cipher_type); diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc index 257b00944f3af7..c66d1c509e03f3 100644 --- a/src/crypto/crypto_context.cc +++ b/src/crypto/crypto_context.cc @@ -1928,8 +1928,13 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo& args) { // true to this function instead of the original string. Any other string // value will be interpreted as custom DH parameters below. if (args[0]->IsTrue()) { +#ifdef SSL_CTX_set_dh_auto CHECK(SSL_CTX_set_dh_auto(sc->ctx_.get(), true)); return; +#else + return THROW_ERR_CRYPTO_UNSUPPORTED_OPERATION( + env, "Automatic DH parameter selection is not supported"); +#endif } DHPointer dh; diff --git a/src/crypto/crypto_dh.cc b/src/crypto/crypto_dh.cc index 36e38e99f06fe0..fa8f36fa33c08f 100644 --- a/src/crypto/crypto_dh.cc +++ b/src/crypto/crypto_dh.cc @@ -309,15 +309,17 @@ void ComputeSecret(const FunctionCallbackInfo& args) { BignumPointer key(key_buf.data(), key_buf.size()); switch (dh.checkPublicKey(key)) { - case DHPointer::CheckPublicKeyResult::INVALID: - // Fall-through case DHPointer::CheckPublicKeyResult::CHECK_FAILED: return THROW_ERR_CRYPTO_INVALID_KEYTYPE(env, "Unspecified validation error"); +#ifndef OPENSSL_IS_BORINGSSL case DHPointer::CheckPublicKeyResult::TOO_SMALL: return THROW_ERR_CRYPTO_INVALID_KEYLEN(env, "Supplied key is too small"); case DHPointer::CheckPublicKeyResult::TOO_LARGE: return THROW_ERR_CRYPTO_INVALID_KEYLEN(env, "Supplied key is too large"); +#endif + case DHPointer::CheckPublicKeyResult::INVALID: + return THROW_ERR_CRYPTO_INVALID_KEYTYPE(env, "Supplied key is invalid"); case DHPointer::CheckPublicKeyResult::NONE: break; } diff --git a/src/crypto/crypto_rsa.cc b/src/crypto/crypto_rsa.cc index e39a7fe72de651..38122d14efe2e6 100644 --- a/src/crypto/crypto_rsa.cc +++ b/src/crypto/crypto_rsa.cc @@ -135,6 +135,18 @@ Maybe RsaKeyGenTraits::AdditionalConfig( params->params.modulus_bits = args[*offset + 1].As()->Value(); params->params.exponent = args[*offset + 2].As()->Value(); +#ifdef OPENSSL_IS_BORINGSSL + // BoringSSL hangs indefinitely generating an RSA key with e=1, and for + // other invalid exponents (e=0, even values) reports the misleading error + // RSA_R_TOO_MANY_ITERATIONS only after running the full keygen loop. Reject + // those up-front with a clear error. The constraint here (odd integer >= 3) + // matches BoringSSL's own rsa_check_public_key validation. + if (params->params.exponent < 3 || (params->params.exponent & 1) == 0) { + THROW_ERR_OUT_OF_RANGE(env, "publicExponent is invalid"); + return Nothing(); + } +#endif + *offset += 3; if (params->params.variant == kKeyVariantRSA_PSS) { diff --git a/src/crypto/crypto_util.cc b/src/crypto/crypto_util.cc index 4b921f1cf308f8..0e743135e8de15 100644 --- a/src/crypto/crypto_util.cc +++ b/src/crypto/crypto_util.cc @@ -553,44 +553,51 @@ Maybe Decorate(Environment* env, c = ToUpper(c); } -#define OSSL_ERROR_CODES_MAP(V) \ - V(SYS) \ - V(BN) \ - V(RSA) \ - V(DH) \ - V(EVP) \ - V(BUF) \ - V(OBJ) \ - V(PEM) \ - V(DSA) \ - V(X509) \ - V(ASN1) \ - V(CONF) \ - V(CRYPTO) \ - V(EC) \ - V(SSL) \ - V(BIO) \ - V(PKCS7) \ - V(X509V3) \ - V(PKCS12) \ - V(RAND) \ - V(DSO) \ - V(ENGINE) \ - V(OCSP) \ - V(UI) \ - V(COMP) \ - V(ECDSA) \ - V(ECDH) \ - V(OSSL_STORE) \ - V(FIPS) \ - V(CMS) \ - V(TS) \ - V(HMAC) \ - V(CT) \ - V(ASYNC) \ - V(KDF) \ - V(SM2) \ - V(USER) \ +#ifdef OPENSSL_IS_BORINGSSL +#define OSSL_ERROR_CODES_MAP_OPENSSL_ONLY(V) +#else +#define OSSL_ERROR_CODES_MAP_OPENSSL_ONLY(V) \ + V(PKCS12) \ + V(DSO) \ + V(OSSL_STORE) \ + V(FIPS) \ + V(TS) \ + V(CT) \ + V(ASYNC) \ + V(KDF) \ + V(SM2) +#endif + +#define OSSL_ERROR_CODES_MAP(V) \ + V(SYS) \ + V(BN) \ + V(RSA) \ + V(DH) \ + V(EVP) \ + V(BUF) \ + V(OBJ) \ + V(PEM) \ + V(DSA) \ + V(X509) \ + V(ASN1) \ + V(CONF) \ + V(CRYPTO) \ + V(EC) \ + V(SSL) \ + V(BIO) \ + V(PKCS7) \ + V(X509V3) \ + V(RAND) \ + V(ENGINE) \ + V(OCSP) \ + V(UI) \ + V(COMP) \ + V(ECDSA) \ + V(ECDH) \ + V(CMS) \ + V(HMAC) \ + V(USER) \ + OSSL_ERROR_CODES_MAP_OPENSSL_ONLY(V) #define V(name) case ERR_LIB_##name: lib = #name "_"; break; const char* lib = ""; @@ -600,6 +607,7 @@ Maybe Decorate(Environment* env, } #undef V #undef OSSL_ERROR_CODES_MAP +#undef OSSL_ERROR_CODES_MAP_OPENSSL_ONLY // Don't generate codes like "ERR_OSSL_SSL_". if (lib && strcmp(lib, "SSL_") == 0) prefix = ""; @@ -728,7 +736,6 @@ void SecureBuffer(const FunctionCallbackInfo& args) { uint32_t len = args[0].As()->Value(); auto data = DataPointer::SecureAlloc(len); - CHECK(data.isSecure()); if (!data) { return THROW_ERR_OPERATION_FAILED(env, "Allocation failed"); } diff --git a/test/parallel/test-crypto-async-sign-verify.js b/test/parallel/test-crypto-async-sign-verify.js index b5d356ea520d20..bee83eaf8de022 100644 --- a/test/parallel/test-crypto-async-sign-verify.js +++ b/test/parallel/test-crypto-async-sign-verify.js @@ -102,17 +102,19 @@ if (!process.features.openssl_is_boringssl) { // ECDSA w/ ieee-p1363 signature encoding test('ec_secp256k1_public.pem', 'ec_secp256k1_private.pem', 'sha384', false, { dsaEncoding: 'ieee-p1363' }); -} -// DSA w/ der signature encoding -test('dsa_public.pem', 'dsa_private.pem', 'sha256', - false); -test('dsa_public.pem', 'dsa_private.pem', 'sha256', - false, { dsaEncoding: 'der' }); + // DSA w/ der signature encoding + test('dsa_public.pem', 'dsa_private.pem', 'sha256', + false); + test('dsa_public.pem', 'dsa_private.pem', 'sha256', + false, { dsaEncoding: 'der' }); -// DSA w/ ieee-p1363 signature encoding -test('dsa_public.pem', 'dsa_private.pem', 'sha256', false, - { dsaEncoding: 'ieee-p1363' }); + // DSA w/ ieee-p1363 signature encoding + test('dsa_public.pem', 'dsa_private.pem', 'sha256', false, + { dsaEncoding: 'ieee-p1363' }); +} else { + common.printSkipMessage('Skipping unsupported ed448/secp256k1/dsa test cases'); +} // Test Parallel Execution w/ KeyObject is threadsafe in openssl3 { diff --git a/test/parallel/test-crypto-authenticated.js b/test/parallel/test-crypto-authenticated.js index 9778ea548e81d7..2a4e2a1520a353 100644 --- a/test/parallel/test-crypto-authenticated.js +++ b/test/parallel/test-crypto-authenticated.js @@ -626,22 +626,25 @@ for (const test of TEST_CASES) { { // CCM cipher without data should not crash, see https://github.com/nodejs/node/issues/38035. - const algo = 'aes-128-ccm'; - const key = Buffer.alloc(16); - const iv = Buffer.alloc(12); - const opts = { authTagLength: 10 }; + if (!ciphers.includes('aes-128-ccm')) { + common.printSkipMessage(`unsupported aes-128-ccm test`); + } else { + const key = Buffer.alloc(16); + const iv = Buffer.alloc(12); + const opts = { authTagLength: 10 }; - const cipher = crypto.createCipheriv(algo, key, iv, opts); - assert.throws(() => { - cipher.final(); - }, hasOpenSSL3 ? { - code: 'ERR_OSSL_TAG_NOT_SET' - } : { - message: /Unsupported state/ - }); + const cipher = crypto.createCipheriv('aes-128-ccm', key, iv, opts); + assert.throws(() => { + cipher.final(); + }, hasOpenSSL3 ? { + code: 'ERR_OSSL_TAG_NOT_SET' + } : { + message: /Unsupported state/ + }); + } } -{ +if (!process.features.openssl_is_boringssl) { const key = Buffer.alloc(32); const iv = Buffer.alloc(12); @@ -653,11 +656,13 @@ for (const test of TEST_CASES) { message: errMessages.authTagLength }); } +} else { + common.printSkipMessage('Skipping unsupported chacha20-poly1305 test'); } // ChaCha20-Poly1305 should respect the authTagLength option and should not // require the authentication tag before calls to update() during decryption. -{ +if (!process.features.openssl_is_boringssl) { const key = Buffer.alloc(32); const iv = Buffer.alloc(12); @@ -697,6 +702,8 @@ for (const test of TEST_CASES) { } } } +} else { + common.printSkipMessage('Skipping unsupported chacha20-poly1305 test'); } // ChaCha20-Poly1305 should default to an authTagLength of 16. When encrypting, @@ -706,7 +713,7 @@ for (const test of TEST_CASES) { // shorter tags as long as their length was valid according to NIST SP 800-38D. // For ChaCha20-Poly1305, we intentionally deviate from that because there are // no recommended or approved authentication tag lengths below 16 bytes. -{ +if (!process.features.openssl_is_boringssl) { const rfcTestCases = TEST_CASES.filter(({ algo, tampered }) => { return algo === 'chacha20-poly1305' && tampered === false; }); @@ -740,10 +747,12 @@ for (const test of TEST_CASES) { assert.strictEqual(plaintext.toString('hex'), testCase.plain); } +} else { + common.printSkipMessage('Skipping unsupported chacha20-poly1305 test'); } // https://github.com/nodejs/node/issues/45874 -{ +if (!process.features.openssl_is_boringssl) { const rfcTestCases = TEST_CASES.filter(({ algo, tampered }) => { return algo === 'chacha20-poly1305' && tampered === false; }); @@ -771,10 +780,12 @@ for (const test of TEST_CASES) { assert.throws(() => { decipher.final(); }, /Unsupported state or unable to authenticate data/); +} else { + common.printSkipMessage('Skipping unsupported chacha20-poly1305 test'); } // Refs: https://github.com/nodejs/node/issues/62342 -{ +if (ciphers.includes('aes-128-ccm')) { const key = crypto.randomBytes(16); const nonce = crypto.randomBytes(13); @@ -794,4 +805,6 @@ for (const test of TEST_CASES) { decipher.setAAD(Buffer.alloc(0), { plaintextLength: 0 }); decipher.update(new DataView(new ArrayBuffer(0))); decipher.final(); +} else { + common.printSkipMessage('Skipping unsupported aes-128-ccm test'); } diff --git a/test/parallel/test-crypto-cipheriv-decipheriv.js b/test/parallel/test-crypto-cipheriv-decipheriv.js index 3f0ea5b31ba189..095458e7d0b425 100644 --- a/test/parallel/test-crypto-cipheriv-decipheriv.js +++ b/test/parallel/test-crypto-cipheriv-decipheriv.js @@ -62,6 +62,10 @@ function testCipher2(key, iv) { function testCipher3(key, iv) { + if (!crypto.getCiphers().includes('id-aes128-wrap')) { + common.printSkipMessage(`unsupported id-aes128-wrap test`); + return; + } // Test encryption and decryption with explicit key and iv. // AES Key Wrap test vector comes from RFC3394 const plaintext = Buffer.from('00112233445566778899AABBCCDDEEFF', 'hex'); diff --git a/test/parallel/test-crypto-default-shake-lengths-oneshot.js b/test/parallel/test-crypto-default-shake-lengths-oneshot.js index 90b4c3de21a317..4aff888c104eb2 100644 --- a/test/parallel/test-crypto-default-shake-lengths-oneshot.js +++ b/test/parallel/test-crypto-default-shake-lengths-oneshot.js @@ -4,6 +4,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.features.openssl_is_boringssl) + common.skip('not supported by BoringSSL'); + const { hash } = require('crypto'); common.expectWarning({ diff --git a/test/parallel/test-crypto-dh-curves.js b/test/parallel/test-crypto-dh-curves.js index 81a469c226c261..ddd5ea9377e63f 100644 --- a/test/parallel/test-crypto-dh-curves.js +++ b/test/parallel/test-crypto-dh-curves.js @@ -16,7 +16,9 @@ const p = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' + crypto.createDiffieHellman(p, 'hex'); // Confirm DH_check() results are exposed for optional examination. -const bad_dh = crypto.createDiffieHellman('02', 'hex'); +const bad_dh = process.features.openssl_is_boringssl ? + crypto.createDiffieHellman('abcd', 'hex', 0) : + crypto.createDiffieHellman('02', 'hex'); assert.notStrictEqual(bad_dh.verifyError, 0); const availableCurves = new Set(crypto.getCurves()); diff --git a/test/parallel/test-crypto-dh-group-setters.js b/test/parallel/test-crypto-dh-group-setters.js index 7c774111952ead..37d0a44d0e1e10 100644 --- a/test/parallel/test-crypto-dh-group-setters.js +++ b/test/parallel/test-crypto-dh-group-setters.js @@ -6,6 +6,10 @@ if (!common.hasCrypto) const assert = require('assert'); const crypto = require('crypto'); +if (process.features.openssl_is_boringssl) { + common.skip('Skipping unsupported Diffie-Hellman tests'); +} + // Unlike DiffieHellman, DiffieHellmanGroup does not have any setters. const dhg = crypto.getDiffieHellman('modp1'); assert.strictEqual(dhg.constructor, crypto.DiffieHellmanGroup); diff --git a/test/parallel/test-crypto-dh-modp2-views.js b/test/parallel/test-crypto-dh-modp2-views.js index 8d01731af79394..a28e615b7f35c7 100644 --- a/test/parallel/test-crypto-dh-modp2-views.js +++ b/test/parallel/test-crypto-dh-modp2-views.js @@ -7,6 +7,10 @@ const assert = require('assert'); const crypto = require('crypto'); const { modp2buf } = require('../common/crypto'); +if (process.features.openssl_is_boringssl) { + common.skip('Skipping unsupported Diffie-Hellman tests'); +} + const modp2 = crypto.createDiffieHellmanGroup('modp2'); const views = common.getArrayBufferViews(modp2buf); diff --git a/test/parallel/test-crypto-dh-modp2.js b/test/parallel/test-crypto-dh-modp2.js index 19767d26f4e5fb..eb262f235ff30b 100644 --- a/test/parallel/test-crypto-dh-modp2.js +++ b/test/parallel/test-crypto-dh-modp2.js @@ -6,6 +6,11 @@ if (!common.hasCrypto) const assert = require('assert'); const crypto = require('crypto'); const { modp2buf } = require('../common/crypto'); + +if (process.features.openssl_is_boringssl) { + common.skip('Skipping unsupported Diffie-Hellman tests'); +} + const modp2 = crypto.createDiffieHellmanGroup('modp2'); { diff --git a/test/parallel/test-crypto-dh.js b/test/parallel/test-crypto-dh.js index 3c00a5fc73bb9f..8a3dee5b0756d1 100644 --- a/test/parallel/test-crypto-dh.js +++ b/test/parallel/test-crypto-dh.js @@ -8,7 +8,6 @@ const assert = require('assert'); const crypto = require('crypto'); const { hasOpenSSL3, - hasOpenSSL, } = require('../common/crypto'); { @@ -90,13 +89,10 @@ const { } { - // Error message was changed in OpenSSL 3.0.x from 3.0.12, and 3.1.x from 3.1.4. - const hasOpenSSL3WithNewErrorMessage = (hasOpenSSL(3, 0, 12) && !hasOpenSSL(3, 1, 0)) || - (hasOpenSSL(3, 1, 4)); assert.throws(() => { dh3.computeSecret(''); - }, { message: hasOpenSSL3 && !hasOpenSSL3WithNewErrorMessage ? - 'Unspecified validation error' : + }, { message: process.features.openssl_is_boringssl ? + 'Supplied key is invalid' : 'Supplied key is too small' }); } } @@ -104,10 +100,24 @@ const { // Through a fluke of history, g=0 defaults to DH_GENERATOR (2). { const g = 0; - crypto.createDiffieHellman('abcdef', g); + if (process.features.openssl_is_boringssl) { + assert.throws(() => crypto.createDiffieHellman('abcdef', g), { + code: 'ERR_CRYPTO_OPERATION_FAILED', + name: 'Error' + }); + } else { + crypto.createDiffieHellman('abcdef', g); + } crypto.createDiffieHellman('abcdef', 'hex', g); } { - crypto.createDiffieHellman('abcdef', Buffer.from([2])); // OK + if (process.features.openssl_is_boringssl) { + assert.throws(() => crypto.createDiffieHellman('abcdef', Buffer.from([2])), { + code: 'ERR_CRYPTO_OPERATION_FAILED', + name: 'Error' + }); + } else { + crypto.createDiffieHellman('abcdef', Buffer.from([2])); // OK + } } diff --git a/test/parallel/test-crypto-ecdh-setpublickey-deprecation.js b/test/parallel/test-crypto-ecdh-setpublickey-deprecation.js index 81ee561c4efef7..317c219f501aaf 100644 --- a/test/parallel/test-crypto-ecdh-setpublickey-deprecation.js +++ b/test/parallel/test-crypto-ecdh-setpublickey-deprecation.js @@ -13,7 +13,7 @@ common.expectWarning( 'DeprecationWarning', 'ecdh.setPublicKey() is deprecated.', 'DEP0031'); -const ec = crypto.createECDH('secp256k1'); +const ec = crypto.createECDH('prime256v1'); try { // This will throw but we don't care about the error, // we just want to verify that the deprecation warning diff --git a/test/parallel/test-crypto-fips.js b/test/parallel/test-crypto-fips.js index a5e25b8fd1073a..04a95fa5fd37c9 100644 --- a/test/parallel/test-crypto-fips.js +++ b/test/parallel/test-crypto-fips.js @@ -4,6 +4,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.features.openssl_is_boringssl) + common.skip('BoringSSL does not support FIPS'); + const assert = require('assert'); const spawnSync = require('child_process').spawnSync; const path = require('path'); diff --git a/test/parallel/test-crypto-getcipherinfo.js b/test/parallel/test-crypto-getcipherinfo.js index b0902908b5c454..d55985aa3c7f6b 100644 --- a/test/parallel/test-crypto-getcipherinfo.js +++ b/test/parallel/test-crypto-getcipherinfo.js @@ -18,6 +18,12 @@ assert.strictEqual(getCipherInfo('cipher that does not exist'), undefined); for (const cipher of ciphers) { const info = getCipherInfo(cipher); + if (process.features.openssl_is_boringssl && !info) { + // BoringSSL reports some legacy ciphers in getCiphers() but returns no + // info for them (e.g. des-ede3, des-ede3-ecb, rc2-40-cbc). + common.printSkipMessage(`Skipping unsupported ${cipher} test case`); + continue; + } assert(info); const info2 = getCipherInfo(info.nid); assert.deepStrictEqual(info, info2); @@ -65,10 +71,14 @@ assert(!getCipherInfo('aes-128-ccm', { ivLength: 14 })); if (!process.features.openssl_is_boringssl) { for (let n = 7; n <= 13; n++) assert(getCipherInfo('aes-128-ccm', { ivLength: n })); +} else { + common.printSkipMessage('Skipping unsupported aes-128-ccm test cases'); } assert(!getCipherInfo('aes-128-ocb', { ivLength: 16 })); if (!process.features.openssl_is_boringssl) { for (let n = 1; n < 16; n++) assert(getCipherInfo('aes-128-ocb', { ivLength: n })); +} else { + common.printSkipMessage('Skipping unsupported aes-128-ocb test cases'); } diff --git a/test/parallel/test-crypto-hash-stream-pipe.js b/test/parallel/test-crypto-hash-stream-pipe.js index d22281abbd5c3c..ac851646a91889 100644 --- a/test/parallel/test-crypto-hash-stream-pipe.js +++ b/test/parallel/test-crypto-hash-stream-pipe.js @@ -30,11 +30,18 @@ const crypto = require('crypto'); const stream = require('stream'); const s = new stream.PassThrough(); -const h = crypto.createHash('sha3-512'); -const expect = '36a38a2a35e698974d4e5791a3f05b05' + - '198235381e864f91a0e8cd6a26b677ec' + - 'dcde8e2b069bd7355fabd68abd6fc801' + - '19659f25e92f8efc961ee3a7c815c758'; +const h = process.features.openssl_is_boringssl ? + crypto.createHash('sha512') : + crypto.createHash('sha3-512'); +const expect = process.features.openssl_is_boringssl ? + 'fba055c6fd0c5b6645407749ed7a8b41' + + 'b8f629f2163c3ca3701d864adabda1f8' + + '93c37bf82b22fdd151ba8e357f611da4' + + '88a74b6a5525dd9b69554c6ce5138ad7' : + '36a38a2a35e698974d4e5791a3f05b05' + + '198235381e864f91a0e8cd6a26b677ec' + + 'dcde8e2b069bd7355fabd68abd6fc801' + + '19659f25e92f8efc961ee3a7c815c758'; s.pipe(h).on('data', common.mustCall(function(c) { assert.strictEqual(c, expect); diff --git a/test/parallel/test-crypto-hash.js b/test/parallel/test-crypto-hash.js index 5f18ad2d1ec137..79c20ea75983d5 100644 --- a/test/parallel/test-crypto-hash.js +++ b/test/parallel/test-crypto-hash.js @@ -8,8 +8,10 @@ common.expectWarning({ DeprecationWarning: [ ['crypto.Hash constructor is deprecated.', 'DEP0179'], - ['Creating SHAKE128/256 digests without an explicit options.outputLength is deprecated.', - 'DEP0198'], + ...(process.features.openssl_is_boringssl ? [] : [[ + 'Creating SHAKE128/256 digests without an explicit options.outputLength is deprecated.', + 'DEP0198', + ]]), ] }); @@ -269,6 +271,8 @@ if (!process.features.openssl_is_boringssl) { assert.throws(() => crypto.createHash('sha256', { outputLength }), { code: 'ERR_OUT_OF_RANGE' }); } +} else { + common.printSkipMessage('Skipping unsupported XOF hash test cases'); } { diff --git a/test/parallel/test-crypto-key-objects-raw.js b/test/parallel/test-crypto-key-objects-raw.js index f301cc1942fd9a..896798ddc640f4 100644 --- a/test/parallel/test-crypto-key-objects-raw.js +++ b/test/parallel/test-crypto-key-objects-raw.js @@ -34,10 +34,15 @@ const { hasOpenSSL } = require('../common/crypto'); // Key types that don't support raw-* formats { - for (const [type, pub, priv] of [ + const unsupportedKeyTypes = [ ['rsa', 'rsa_public_2048.pem', 'rsa_private_2048.pem'], - ['dsa', 'dsa_public.pem', 'dsa_private.pem'], - ]) { + ]; + if (!process.features.openssl_is_boringssl) { + unsupportedKeyTypes.push(['dsa', 'dsa_public.pem', 'dsa_private.pem']); + } else { + common.printSkipMessage('Skipping unsupported dsa test case'); + } + for (const [type, pub, priv] of unsupportedKeyTypes) { const pubKeyObj = crypto.createPublicKey( fixtures.readKey(pub, 'ascii')); const privKeyObj = crypto.createPrivateKey( @@ -58,7 +63,7 @@ const { hasOpenSSL } = require('../common/crypto'); } // DH keys also don't support raw formats - { + if (!process.features.openssl_is_boringssl) { const privKeyObj = crypto.createPrivateKey( fixtures.readKey('dh_private.pem', 'ascii')); assert.throws(() => privKeyObj.export({ format: 'raw-private' }), @@ -69,6 +74,8 @@ const { hasOpenSSL } = require('../common/crypto'); key: Buffer.alloc(32), format, asymmetricKeyType: 'dh', }), { code: 'ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS' }); } + } else { + common.printSkipMessage('Skipping unsupported dh test case'); } } @@ -224,7 +231,12 @@ if (hasOpenSSL(3, 5)) { assert.throws(() => ecPriv.export({ format: 'raw-seed' }), { code: 'ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS' }); - for (const type of ['ed25519', 'ed448', 'x25519', 'x448']) { + if (process.features.openssl_is_boringssl) { + common.printSkipMessage('Skipping unsupported ed448/x448 test cases'); + } + for (const type of process.features.openssl_is_boringssl ? + ['ed25519', 'x25519'] : + ['ed25519', 'ed448', 'x25519', 'x448']) { const priv = crypto.createPrivateKey( fixtures.readKey(`${type}_private.pem`, 'ascii')); assert.throws(() => priv.export({ format: 'raw-seed' }), @@ -392,7 +404,12 @@ if (hasOpenSSL(3, 5)) { // x25519, ed25519, x448, and ed448 cannot be used as 'ec' namedCurve values { - for (const type of ['ed25519', 'x25519', 'ed448', 'x448']) { + if (process.features.openssl_is_boringssl) { + common.printSkipMessage('Skipping unsupported ed448/x448 test cases'); + } + for (const type of process.features.openssl_is_boringssl ? + ['ed25519', 'x25519'] : + ['ed25519', 'x25519', 'ed448', 'x448']) { const priv = crypto.createPrivateKey( fixtures.readKey(`${type}_private.pem`, 'ascii')); const pub = crypto.createPublicKey( diff --git a/test/parallel/test-crypto-key-objects-to-crypto-key.js b/test/parallel/test-crypto-key-objects-to-crypto-key.js index 141e51d1ab74a4..54449329cb551a 100644 --- a/test/parallel/test-crypto-key-objects-to-crypto-key.js +++ b/test/parallel/test-crypto-key-objects-to-crypto-key.js @@ -26,9 +26,15 @@ function assertCryptoKey(cryptoKey, keyObject, algorithm, extractable, usages) { { for (const length of [128, 192, 256]) { const key = createSecretKey(randomBytes(length >> 3)); - const algorithms = ['AES-CTR', 'AES-CBC', 'AES-GCM', 'AES-KW']; + let algorithms = ['AES-CTR', 'AES-CBC', 'AES-GCM', 'AES-KW']; if (length === 256) algorithms.push('ChaCha20-Poly1305'); + + if (process.features.openssl_is_boringssl) { + algorithms = algorithms.filter((a) => a !== 'AES-KW' && a !== 'ChaCha20-Poly1305'); + common.printSkipMessage('Skipping unsupported AES-KW/ChaCha20-Poly1305 test cases'); + } + for (const algorithm of algorithms) { const usages = algorithm === 'AES-KW' ? ['wrapKey', 'unwrapKey'] : ['encrypt', 'decrypt']; for (const extractable of [true, false]) { @@ -97,7 +103,15 @@ function assertCryptoKey(cryptoKey, keyObject, algorithm, extractable, usages) { } { - for (const algorithm of ['Ed25519', 'Ed448', 'X25519', 'X448']) { + const algorithms = ['Ed25519', 'X25519']; + + if (!process.features.openssl_is_boringssl) { + algorithms.push('X448', 'Ed448'); + } else { + common.printSkipMessage('Skipping unsupported Ed448/X448 test cases'); + } + + for (const algorithm of algorithms) { const { publicKey, privateKey } = generateKeyPairSync(algorithm.toLowerCase()); assert.throws(() => { publicKey.toCryptoKey(algorithm === 'Ed25519' ? 'X25519' : 'Ed25519', true, []); diff --git a/test/parallel/test-crypto-key-objects.js b/test/parallel/test-crypto-key-objects.js index ce93de980946e5..7c82e4dd8b97ea 100644 --- a/test/parallel/test-crypto-key-objects.js +++ b/test/parallel/test-crypto-key-objects.js @@ -330,6 +330,12 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', createPrivateKey({ key: '' }); }, hasOpenSSL3 ? { message: 'error:1E08010C:DECODER routines::unsupported', + } : process.features.openssl_is_boringssl ? { + message: 'error:0900006e:PEM routines:OPENSSL_internal:NO_START_LINE', + code: 'ERR_OSSL_PEM_NO_START_LINE', + reason: 'NO_START_LINE', + library: 'PEM routines', + function: 'OPENSSL_internal', } : { message: 'error:0909006C:PEM routines:get_name:no start line', code: 'ERR_OSSL_PEM_NO_START_LINE', @@ -357,13 +363,16 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', }, hasOpenSSL3 ? { message: /error:1E08010C:DECODER routines::unsupported/, library: 'DECODER routines' + } : process.features.openssl_is_boringssl ? { + library: 'public key routines', + message: 'error:06000066:public key routines:OPENSSL_internal:DECODE_ERROR' } : { message: /asn1 encoding/, library: 'asn1 encoding routines' }); } -[ +for (const info of [ { private: fixtures.readKey('ed25519_private.pem', 'ascii'), public: fixtures.readKey('ed25519_public.pem', 'ascii'), keyType: 'ed25519', @@ -404,9 +413,14 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', 'S0jlSYJk', kty: 'OKP' } }, -].forEach((info) => { +]) { const keyType = info.keyType; + if (process.features.openssl_is_boringssl && keyType.endsWith('448')) { + common.printSkipMessage(`Skipping unsupported ${keyType} test case`); + continue; + } + { const key = createPrivateKey(info.private); assert.strictEqual(key.type, 'private'); @@ -471,7 +485,7 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', assert.deepStrictEqual( importedPub.export({ format: 'raw-public' }), rawPub); } -}); +} // Importing an OKP private JWK where x does not match d should fail. { @@ -518,7 +532,7 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', ); } -[ +for (const info of [ { private: fixtures.readKey('ec_p256_private.pem', 'ascii'), public: fixtures.readKey('ec_p256_public.pem', 'ascii'), keyType: 'ec', @@ -566,9 +580,14 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', y: 'Ad3flexBeAfXceNzRBH128kFbOWD6W41NjwKRqqIF26vmgW_8COldGKZjFkOSEASxPB' + 'cvA2iFJRUyQ3whC00j0Np' } }, -].forEach((info) => { +]) { const { keyType, namedCurve } = info; + if (process.features.openssl_is_boringssl && !getCurves().includes(namedCurve)) { + common.printSkipMessage(`Skipping unsupported ${keyType} test case`); + continue; + } + { const key = createPrivateKey(info.private); assert.strictEqual(key.type, 'private'); @@ -648,7 +667,7 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', assert.deepStrictEqual( importedPub.export({ format: 'raw-public' }), rawPub); } -}); +} // Importing an EC private JWK where x does not match d should fail. { @@ -726,7 +745,7 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', format: 'pem', passphrase: Buffer.alloc(1024, 'a') }), { - message: /bad decrypt/ + message: /bad decrypt|BAD_DECRYPT/ }); const publicKey = createPublicKey(publicDsa); @@ -750,7 +769,7 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', { code: 'ERR_CRYPTO_JWK_UNSUPPORTED_KEY_TYPE' }); } -{ +if (!process.features.openssl_is_boringssl) { // Test RSA-PSS. { // This key pair does not restrict the message digest algorithm or salt @@ -946,6 +965,8 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', } } } +} else { + common.printSkipMessage('Skipping unsupported RSA-PSS test case'); } { @@ -1045,7 +1066,7 @@ const privateDsa = fixtures.readKey('dsa_private_encrypted_1025.pem', { const first = generateKeyPairSync('ed25519'); - const second = generateKeyPairSync('ed448'); + const second = generateKeyPairSync('x25519'); assert(!first.publicKey.equals(second.publicKey)); assert(!first.publicKey.equals(second.privateKey)); diff --git a/test/parallel/test-crypto-keygen-async-dsa-key-object.js b/test/parallel/test-crypto-keygen-async-dsa-key-object.js index a3df136230d0f8..ea35facbdc7e20 100644 --- a/test/parallel/test-crypto-keygen-async-dsa-key-object.js +++ b/test/parallel/test-crypto-keygen-async-dsa-key-object.js @@ -4,6 +4,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.features.openssl_is_boringssl) + common.skip('not supported by BoringSSL'); + const assert = require('assert'); const { generateKeyPair, diff --git a/test/parallel/test-crypto-keygen-async-dsa.js b/test/parallel/test-crypto-keygen-async-dsa.js index 41968d8cc23365..d7c857d35e214b 100644 --- a/test/parallel/test-crypto-keygen-async-dsa.js +++ b/test/parallel/test-crypto-keygen-async-dsa.js @@ -4,6 +4,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.features.openssl_is_boringssl) + common.skip('not supported by BoringSSL'); + const assert = require('assert'); const { generateKeyPair, diff --git a/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk-ec.js b/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk-ec.js index bddb4aa2fbdcd6..b0945dcc83a2cd 100644 --- a/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk-ec.js +++ b/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk-ec.js @@ -11,7 +11,11 @@ const { // Test async elliptic curve key generation with 'jwk' encoding and named // curve. -['P-384', 'P-256', 'P-521', 'secp256k1'].forEach((curve) => { +for (const curve of ['P-384', 'P-256', 'P-521', 'secp256k1']) { + if (process.features.openssl_is_boringssl && curve === 'secp256k1') { + common.printSkipMessage(`Skipping unsupported ${curve} test case`); + continue; + } generateKeyPair('ec', { namedCurve: curve, publicKeyEncoding: { @@ -32,4 +36,4 @@ const { assert.strictEqual(publicKey.crv, curve); assert.strictEqual(publicKey.crv, privateKey.crv); })); -}); +}; diff --git a/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk.js b/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk.js index 5243edd8c825b7..731960b0d56a06 100644 --- a/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk.js +++ b/test/parallel/test-crypto-keygen-async-elliptic-curve-jwk.js @@ -11,12 +11,11 @@ const { // Test async elliptic curve key generation with 'jwk' encoding. { - [ - 'ed25519', - 'ed448', - 'x25519', - 'x448', - ].forEach((type) => { + for (const type of ['ed25519', 'ed448', 'x25519', 'x448']) { + if (process.features.openssl_is_boringssl && type.endsWith('448')) { + common.printSkipMessage(`Skipping unsupported ${type} test case`); + continue; + } generateKeyPair(type, { publicKeyEncoding: { format: 'jwk' @@ -36,5 +35,5 @@ const { assert.strictEqual(publicKey.crv, expectedCrv); assert.strictEqual(publicKey.crv, privateKey.crv); })); - }); + } } diff --git a/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted-p256.js b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted-p256.js index 55aa3831c4233b..246cbe5dd1ace1 100644 --- a/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted-p256.js +++ b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted-p256.js @@ -4,6 +4,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.features.openssl_is_boringssl) + common.skip('BoringSSL does not support paramEncoding: explicit'); + const assert = require('assert'); const { generateKeyPair, diff --git a/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted.js.js b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted.js.js index 8a55d4338bc72f..c3b8ab6e8f5093 100644 --- a/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted.js.js +++ b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve-encrypted.js.js @@ -4,6 +4,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.features.openssl_is_boringssl) + common.skip('BoringSSL does not support paramEncoding: explicit'); + const assert = require('assert'); const { generateKeyPair, diff --git a/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve.js b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve.js index 46223f08d7445a..8084cdfc0b3bf1 100644 --- a/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve.js +++ b/test/parallel/test-crypto-keygen-async-explicit-elliptic-curve.js @@ -4,6 +4,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.features.openssl_is_boringssl) + common.skip('BoringSSL does not support paramEncoding: explicit'); + const assert = require('assert'); const { generateKeyPair, diff --git a/test/parallel/test-crypto-keygen-bit-length.js b/test/parallel/test-crypto-keygen-bit-length.js index 63a80659bb2f53..13234589a5d6de 100644 --- a/test/parallel/test-crypto-keygen-bit-length.js +++ b/test/parallel/test-crypto-keygen-bit-length.js @@ -4,6 +4,10 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.features.openssl_is_boringssl) + common.skip('BoringSSL does not support arbitrary RSA modulus length ' + + 'or RSA-PSS/DSA key generation'); + const assert = require('assert'); const { generateKeyPair, diff --git a/test/parallel/test-crypto-keygen-dh-classic.js b/test/parallel/test-crypto-keygen-dh-classic.js index ecf5ce7863b8a4..44af7730126afe 100644 --- a/test/parallel/test-crypto-keygen-dh-classic.js +++ b/test/parallel/test-crypto-keygen-dh-classic.js @@ -4,6 +4,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.features.openssl_is_boringssl) + common.skip('BoringSSL does not support DH key pair generation'); + const assert = require('assert'); const { generateKeyPair, diff --git a/test/parallel/test-crypto-keygen-eddsa.js b/test/parallel/test-crypto-keygen-eddsa.js index 5a097c2524f3ea..0a132235ea28ba 100644 --- a/test/parallel/test-crypto-keygen-eddsa.js +++ b/test/parallel/test-crypto-keygen-eddsa.js @@ -11,17 +11,19 @@ const { // Test EdDSA key generation. { - if (!/^1\.1\.0/.test(process.versions.openssl)) { - ['ed25519', 'ed448', 'x25519', 'x448'].forEach((keyType) => { - generateKeyPair(keyType, common.mustSucceed((publicKey, privateKey) => { - assert.strictEqual(publicKey.type, 'public'); - assert.strictEqual(publicKey.asymmetricKeyType, keyType); - assert.deepStrictEqual(publicKey.asymmetricKeyDetails, {}); + for (const keyType of ['ed25519', 'ed448', 'x25519', 'x448']) { + if (process.features.openssl_is_boringssl && keyType.endsWith('448')) { + common.printSkipMessage(`Skipping unsupported ${keyType} test case`); + continue; + } + generateKeyPair(keyType, common.mustSucceed((publicKey, privateKey) => { + assert.strictEqual(publicKey.type, 'public'); + assert.strictEqual(publicKey.asymmetricKeyType, keyType); + assert.deepStrictEqual(publicKey.asymmetricKeyDetails, {}); - assert.strictEqual(privateKey.type, 'private'); - assert.strictEqual(privateKey.asymmetricKeyType, keyType); - assert.deepStrictEqual(privateKey.asymmetricKeyDetails, {}); - })); - }); + assert.strictEqual(privateKey.type, 'private'); + assert.strictEqual(privateKey.asymmetricKeyType, keyType); + assert.deepStrictEqual(privateKey.asymmetricKeyDetails, {}); + })); } } diff --git a/test/parallel/test-crypto-keygen-invalid-parameter-encoding-dsa.js b/test/parallel/test-crypto-keygen-invalid-parameter-encoding-dsa.js index b5ff5dc2059c1b..9086e2e8a5f1ba 100644 --- a/test/parallel/test-crypto-keygen-invalid-parameter-encoding-dsa.js +++ b/test/parallel/test-crypto-keygen-invalid-parameter-encoding-dsa.js @@ -4,6 +4,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.features.openssl_is_boringssl) + common.skip('BoringSSL does not support DSA key pair generation'); + const assert = require('assert'); const { diff --git a/test/parallel/test-crypto-keygen-no-rsassa-pss-params.js b/test/parallel/test-crypto-keygen-no-rsassa-pss-params.js index 97dafe1be3cbd0..559c6f0af05163 100644 --- a/test/parallel/test-crypto-keygen-no-rsassa-pss-params.js +++ b/test/parallel/test-crypto-keygen-no-rsassa-pss-params.js @@ -4,6 +4,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.features.openssl_is_boringssl) + common.skip('BoringSSL does not support RSA-PSS key pair generation'); + const assert = require('assert'); const { generateKeyPair, diff --git a/test/parallel/test-crypto-keygen-raw.js b/test/parallel/test-crypto-keygen-raw.js index fd2971dc2c86cd..5b7abe3f72d9dd 100644 --- a/test/parallel/test-crypto-keygen-raw.js +++ b/test/parallel/test-crypto-keygen-raw.js @@ -158,12 +158,14 @@ const { hasOpenSSL } = require('../common/crypto'); } // Test error: raw with DSA. -{ +if (!process.features.openssl_is_boringssl) { assert.throws(() => generateKeyPairSync('dsa', { modulusLength: 2048, publicKeyEncoding: { format: 'raw-public' }, privateKeyEncoding: { format: 'raw-private' }, }), { code: 'ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS' }); +} else { + common.printSkipMessage(`Skipping unsupported dsa test case`); } // Test error: raw-private in publicKeyEncoding. diff --git a/test/parallel/test-crypto-keygen-rfc8017-9-1.js b/test/parallel/test-crypto-keygen-rfc8017-9-1.js index 7198be1c41343b..fbefb1b4f642b4 100644 --- a/test/parallel/test-crypto-keygen-rfc8017-9-1.js +++ b/test/parallel/test-crypto-keygen-rfc8017-9-1.js @@ -4,6 +4,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.features.openssl_is_boringssl) + common.skip('BoringSSL does not support RSA-PSS key pair generation'); + const assert = require('assert'); const { generateKeyPair, diff --git a/test/parallel/test-crypto-keygen-rfc8017-a-2-3.js b/test/parallel/test-crypto-keygen-rfc8017-a-2-3.js index f87dcf749bf6d0..bc96d57ed0cd1b 100644 --- a/test/parallel/test-crypto-keygen-rfc8017-a-2-3.js +++ b/test/parallel/test-crypto-keygen-rfc8017-a-2-3.js @@ -4,6 +4,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.features.openssl_is_boringssl) + common.skip('BoringSSL does not support RSA-PSS key pair generation'); + const assert = require('assert'); const { generateKeyPair, diff --git a/test/parallel/test-crypto-keygen-rsa-pss.js b/test/parallel/test-crypto-keygen-rsa-pss.js index 41ebec97a5d2dd..3ce0d40e8d1b2d 100644 --- a/test/parallel/test-crypto-keygen-rsa-pss.js +++ b/test/parallel/test-crypto-keygen-rsa-pss.js @@ -4,6 +4,9 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.features.openssl_is_boringssl) + common.skip('BoringSSL does not support RSA-PSS key pair generation'); + const assert = require('assert'); const { constants, diff --git a/test/parallel/test-crypto-oneshot-hash-xof.js b/test/parallel/test-crypto-oneshot-hash-xof.js index 75cb4800ff1bd5..b4363c31592763 100644 --- a/test/parallel/test-crypto-oneshot-hash-xof.js +++ b/test/parallel/test-crypto-oneshot-hash-xof.js @@ -7,6 +7,10 @@ if (!common.hasCrypto) common.skip('missing crypto'); const assert = require('assert'); const crypto = require('crypto'); +if (process.features.openssl_is_boringssl) { + common.skip('BoringSSL does not support XOF hash functions'); +} + // Test XOF hash functions and the outputLength option. { // Default outputLengths. diff --git a/test/parallel/test-crypto-pqc-key-objects-ml-dsa.js b/test/parallel/test-crypto-pqc-key-objects-ml-dsa.js index 413adf48686ede..f18c555d4653d4 100644 --- a/test/parallel/test-crypto-pqc-key-objects-ml-dsa.js +++ b/test/parallel/test-crypto-pqc-key-objects-ml-dsa.js @@ -4,6 +4,10 @@ const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); +if (process.features.openssl_is_boringssl) { + common.skip('Skipping unsupported ML-DSA key tests'); +} + const { hasOpenSSL } = require('../common/crypto'); const assert = require('assert'); diff --git a/test/parallel/test-crypto-rsa-dsa.js b/test/parallel/test-crypto-rsa-dsa.js index 119bc3c2d20ea7..35ad673020778a 100644 --- a/test/parallel/test-crypto-rsa-dsa.js +++ b/test/parallel/test-crypto-rsa-dsa.js @@ -39,10 +39,19 @@ const openssl1DecryptError = { const decryptError = hasOpenSSL3 ? { message: 'error:1C800064:Provider routines::bad decrypt' } : - openssl1DecryptError; + process.features.openssl_is_boringssl ? { + message: 'error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT', + code: 'ERR_OSSL_BAD_DECRYPT', + reason: 'BAD_DECRYPT', + function: 'OPENSSL_internal', + library: 'Cipher functions', + } : + openssl1DecryptError; const decryptPrivateKeyError = hasOpenSSL3 ? { message: 'error:1C800064:Provider routines::bad decrypt', +} : process.features.openssl_is_boringssl ? { + message: 'error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT', } : openssl1DecryptError; function getBufferCopy(buf) { @@ -325,9 +334,14 @@ function test_rsa(padding, encryptOaepHash, decryptOaepHash) { } test_rsa('RSA_NO_PADDING'); -test_rsa('RSA_PKCS1_PADDING'); test_rsa('RSA_PKCS1_OAEP_PADDING'); +if (!process.features.openssl_is_boringssl) { + test_rsa('RSA_PKCS1_PADDING'); +} else { + common.printSkipMessage('Skipping unsupported RSA_PKCS1_PADDING test case'); +} + // Test OAEP with different hash functions. test_rsa('RSA_PKCS1_OAEP_PADDING', undefined, 'sha1'); test_rsa('RSA_PKCS1_OAEP_PADDING', 'sha1', undefined); @@ -489,7 +503,7 @@ assert.throws(() => { // // Test DSA signing and verification // -{ +if (!process.features.openssl_is_boringssl) { const input = 'I AM THE WALRUS'; // DSA signatures vary across runs so there is no static string to verify @@ -512,13 +526,15 @@ assert.throws(() => { verify2.update(input); assert.strictEqual(verify2.verify(dsaPubPem, signature2, 'hex'), true); +} else { + common.printSkipMessage('Skipping unsupported DSA test case'); } // // Test DSA signing and verification with PKCS#8 private key // -{ +if (!process.features.openssl_is_boringssl) { const input = 'I AM THE WALRUS'; // DSA signatures vary across runs so there is no static string to verify @@ -531,6 +547,8 @@ assert.throws(() => { verify.update(input); assert.strictEqual(verify.verify(dsaPubPem, signature, 'hex'), true); +} else { + common.printSkipMessage('Skipping unsupported DSA test case'); } @@ -547,7 +565,7 @@ const input = 'I AM THE WALRUS'; }, decryptPrivateKeyError); } -{ +if (!process.features.openssl_is_boringssl) { // DSA signatures vary across runs so there is no static string to verify // against. const sign = crypto.createSign('SHA1'); @@ -559,4 +577,6 @@ const input = 'I AM THE WALRUS'; verify.update(input); assert.strictEqual(verify.verify(dsaPubPem, signature, 'hex'), true); +} else { + common.printSkipMessage('Skipping unsupported DSA test case'); } diff --git a/test/parallel/test-crypto-scrypt.js b/test/parallel/test-crypto-scrypt.js index eafdfe392bde8e..5effc083cda11a 100644 --- a/test/parallel/test-crypto-scrypt.js +++ b/test/parallel/test-crypto-scrypt.js @@ -192,7 +192,9 @@ for (const options of incompatibleOptions) { for (const options of toobig) { const expected = { - message: /Invalid scrypt params:.*memory limit exceeded/, + message: process.features.openssl_is_boringssl ? + /Invalid scrypt params:.*(INVALID_PARAMETERS|MEMORY_LIMIT_EXCEEDED)/ : + /Invalid scrypt params:.*memory limit exceeded/, code: 'ERR_CRYPTO_INVALID_SCRYPT_PARAMS', }; assert.throws(() => crypto.scrypt('pass', 'salt', 1, options, () => {}), diff --git a/test/parallel/test-crypto-secure-heap.js b/test/parallel/test-crypto-secure-heap.js index c20b01a91a9840..3845f49a4748b8 100644 --- a/test/parallel/test-crypto-secure-heap.js +++ b/test/parallel/test-crypto-secure-heap.js @@ -13,6 +13,10 @@ if (common.isASan) { common.skip('ASan does not play well with secure heap allocations'); } +if (process.features.openssl_is_boringssl) { + common.skip('BoringSSL does not support secure heap'); +} + const assert = require('assert'); const { fork } = require('child_process'); const fixtures = require('../common/fixtures'); diff --git a/test/parallel/test-crypto-sign-verify.js b/test/parallel/test-crypto-sign-verify.js index ba30cb17dc32df..a33eeca328ce8d 100644 --- a/test/parallel/test-crypto-sign-verify.js +++ b/test/parallel/test-crypto-sign-verify.js @@ -68,7 +68,9 @@ const keySize = 2048; }); }, { message: hasOpenSSL(3) ? 'error:1C8000A5:Provider routines::illegal or unsupported padding mode' : - 'bye, bye, error stack' }); + process.features.openssl_is_boringssl ? + 'error:0600006d:public key routines:OPENSSL_internal:ILLEGAL_OR_UNSUPPORTED_PADDING_MODE' : + 'bye, bye, error stack' }); delete Object.prototype.opensslErrorStack; } @@ -347,6 +349,9 @@ assert.throws( }, hasOpenSSL(3) ? { code: 'ERR_OSSL_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE', message: /illegal or unsupported padding mode/, + } : process.features.openssl_is_boringssl ? { + code: 'ERR_OSSL_EVP_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE', + message: /ILLEGAL_OR_UNSUPPORTED_PADDING_MODE/, } : { code: 'ERR_OSSL_RSA_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE', message: /illegal or unsupported padding mode/, @@ -418,25 +423,32 @@ assert.throws( /Invalid digest/); } -[ +for (const pair of [ { private: fixtures.readKey('ed25519_private.pem', 'ascii'), public: fixtures.readKey('ed25519_public.pem', 'ascii'), + skip: false, algo: null, supportsContext: hasOpenSSL(3, 2), sigLen: 64, raw: true }, { private: fixtures.readKey('ed448_private.pem', 'ascii'), public: fixtures.readKey('ed448_public.pem', 'ascii'), + skip: process.features.openssl_is_boringssl, algo: null, supportsContext: hasOpenSSL(3, 2), sigLen: 114, raw: true }, { private: fixtures.readKey('rsa_private_2048.pem', 'ascii'), public: fixtures.readKey('rsa_public_2048.pem', 'ascii'), + skip: false, algo: 'sha1', sigLen: 256, raw: false }, -].forEach((pair) => { +]) { + if (pair.skip) { + common.printSkipMessage('Skipping unsupported test case'); + continue; + } const algo = pair.algo; { @@ -550,7 +562,7 @@ assert.throws( }, { message: 'Context parameter is unsupported' }); } } -}); +} // Ed25519ctx: Ed25519 with context string. if (hasOpenSSL(3, 2)) { @@ -618,6 +630,10 @@ if (hasOpenSSL(3, 2)) { const keys = [['ec-key.pem', 64], ['dsa_private_1025.pem', 40]]; for (const [file, length] of keys) { + if (process.features.openssl_is_boringssl && file.startsWith('dsa_')) { + common.printSkipMessage(`Skipping unsupported ${file} test case`); + continue; + } const privKey = fixtures.readKey(file); [ crypto.createSign('sha1').update(data).sign(privKey), @@ -752,7 +768,7 @@ if (hasOpenSSL(3, 2)) { })); } -{ +if (!process.features.openssl_is_boringssl) { // Test RSA-PSS. { // This key pair does not restrict the message digest algorithm or salt @@ -861,6 +877,8 @@ if (hasOpenSSL(3, 2)) { } } } +} else { + common.printSkipMessage('Skipping unsupported RSA-PSS test cases'); } // The sign function should not swallow OpenSSL errors. @@ -873,7 +891,7 @@ if (hasOpenSSL(3, 2)) { crypto.sign('sha512', 'message', privateKey); }, { code: 'ERR_OSSL_RSA_DIGEST_TOO_BIG_FOR_RSA_KEY', - message: /digest too big for rsa key/ + message: /digest too big for rsa key|DIGEST_TOO_BIG_FOR_RSA_KEY/ }); } @@ -898,9 +916,13 @@ if (hasOpenSSL(3, 2)) { { // Ed25519 and Ed448 must use the one-shot methods const keys = [{ privateKey: fixtures.readKey('ed25519_private.pem', 'ascii'), - publicKey: fixtures.readKey('ed25519_public.pem', 'ascii') }, - { privateKey: fixtures.readKey('ed448_private.pem', 'ascii'), - publicKey: fixtures.readKey('ed448_public.pem', 'ascii') }]; + publicKey: fixtures.readKey('ed25519_public.pem', 'ascii') }]; + if (!process.features.openssl_is_boringssl) { + keys.push({ privateKey: fixtures.readKey('ed448_private.pem', 'ascii'), + publicKey: fixtures.readKey('ed448_public.pem', 'ascii') }); + } else { + common.printSkipMessage('Skipping unsupported Ed448 test case'); + } for (const { publicKey, privateKey } of keys) { assert.throws(() => { @@ -915,7 +937,7 @@ if (hasOpenSSL(3, 2)) { } } -{ +if (!process.features.openssl_is_boringssl) { // Dh, x25519 and x448 should not be used for signing/verifying // https://github.com/nodejs/node/issues/53742 for (const algo of ['dh', 'x25519', 'x448']) { @@ -931,6 +953,8 @@ if (hasOpenSSL(3, 2)) { crypto.createVerify('SHA256').update('Test123').verify(publicKey, 'sig'); }, { code: 'ERR_OSSL_EVP_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE', message: /operation not supported for this keytype/ }); } +} else { + common.printSkipMessage('Skipping unsupported dh/x25519/x448 test cases'); } // Test that sign/verify error messages use correct property paths diff --git a/test/parallel/test-crypto.js b/test/parallel/test-crypto.js index d21a6bd3d98d6d..fbb065dd442876 100644 --- a/test/parallel/test-crypto.js +++ b/test/parallel/test-crypto.js @@ -145,8 +145,10 @@ assert(crypto.getHashes().includes('sha1')); assert(crypto.getHashes().includes('sha256')); assert(!crypto.getHashes().includes('SHA1')); assert(!crypto.getHashes().includes('SHA256')); -assert(crypto.getHashes().includes('RSA-SHA1')); -assert(!crypto.getHashes().includes('rsa-sha1')); +if (!process.features.openssl_is_boringssl) { + assert(crypto.getHashes().includes('RSA-SHA1')); + assert(!crypto.getHashes().includes('rsa-sha1')); +} validateList(crypto.getHashes()); // Make sure all of the hashes are supported by OpenSSL for (const algo of crypto.getHashes()) diff --git a/test/parallel/test-tls-dhparam-auto-boringssl.js b/test/parallel/test-tls-dhparam-auto-boringssl.js new file mode 100644 index 00000000000000..54f2190d1a947b --- /dev/null +++ b/test/parallel/test-tls-dhparam-auto-boringssl.js @@ -0,0 +1,19 @@ +'use strict'; +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +if (!process.features.openssl_is_boringssl) + common.skip('only applies to BoringSSL builds'); + +const assert = require('assert'); +const tls = require('tls'); + +// BoringSSL does not provide SSL_CTX_set_dh_auto, so requesting automatic +// DH parameter selection via `dhparam: 'auto'` must throw. +assert.throws(() => { + tls.createSecureContext({ dhparam: 'auto' }); +}, { + code: 'ERR_CRYPTO_UNSUPPORTED_OPERATION', + message: 'Automatic DH parameter selection is not supported', +}); diff --git a/test/parallel/test-webcrypto-export-import-cfrg.js b/test/parallel/test-webcrypto-export-import-cfrg.js index c6e3509a4362bc..b1732bf077416c 100644 --- a/test/parallel/test-webcrypto-export-import-cfrg.js +++ b/test/parallel/test-webcrypto-export-import-cfrg.js @@ -428,7 +428,7 @@ async function testImportRaw({ name, publicUsages }) { for (const [name, publicUsages, privateUsages] of [ ['Ed25519', ['verify'], ['sign']], - ['X448', [], ['deriveBits']], + ['X25519', [], ['deriveBits']], ]) { assert.rejects(subtle.importKey( 'spki', diff --git a/test/parallel/test-webcrypto-promise-prototype-pollution.mjs b/test/parallel/test-webcrypto-promise-prototype-pollution.mjs index b4fbedba5e3242..3ea0a961f41b90 100644 --- a/test/parallel/test-webcrypto-promise-prototype-pollution.mjs +++ b/test/parallel/test-webcrypto-promise-prototype-pollution.mjs @@ -59,17 +59,21 @@ await subtle.deriveKey( true, ['encrypt', 'decrypt']); -const wrappingKey = await subtle.generateKey( - { name: 'AES-KW', length: 256 }, true, ['wrapKey', 'unwrapKey']); +if (!process.features.openssl_is_boringssl) { + const wrappingKey = await subtle.generateKey( + { name: 'AES-KW', length: 256 }, true, ['wrapKey', 'unwrapKey']); -const keyToWrap = await subtle.generateKey( - { name: 'AES-CBC', length: 256 }, true, ['encrypt', 'decrypt']); + const keyToWrap = await subtle.generateKey( + { name: 'AES-CBC', length: 256 }, true, ['encrypt', 'decrypt']); -const wrapped = await subtle.wrapKey('raw', keyToWrap, wrappingKey, 'AES-KW'); + const wrapped = await subtle.wrapKey('raw', keyToWrap, wrappingKey, 'AES-KW'); -await subtle.unwrapKey( - 'raw', wrapped, wrappingKey, 'AES-KW', - { name: 'AES-CBC', length: 256 }, true, ['encrypt', 'decrypt']); + await subtle.unwrapKey( + 'raw', wrapped, wrappingKey, 'AES-KW', + { name: 'AES-CBC', length: 256 }, true, ['encrypt', 'decrypt']); +} else { + common.printSkipMessage('Skipping unsupported AES-KW test case'); +} const { privateKey } = await subtle.generateKey( { name: 'ECDSA', namedCurve: 'P-256' }, true, ['sign', 'verify']); diff --git a/test/parallel/test-webcrypto-wrap-unwrap.js b/test/parallel/test-webcrypto-wrap-unwrap.js index a0cbe2c324f786..8c57111daebca6 100644 --- a/test/parallel/test-webcrypto-wrap-unwrap.js +++ b/test/parallel/test-webcrypto-wrap-unwrap.js @@ -179,13 +179,6 @@ async function generateKeysToWrap() { usages: ['encrypt', 'decrypt'], pair: false, }, - { - algorithm: { - name: 'ChaCha20-Poly1305' - }, - usages: ['encrypt', 'decrypt'], - pair: false, - }, { algorithm: { name: 'HMAC', @@ -210,6 +203,18 @@ async function generateKeysToWrap() { common.printSkipMessage('Skipping unsupported AES-KW test case'); } + if (!process.features.openssl_is_boringssl) { + parameters.push({ + algorithm: { + name: 'ChaCha20-Poly1305' + }, + usages: ['encrypt', 'decrypt'], + pair: false, + }); + } else { + common.printSkipMessage('Skipping unsupported ChaCha20-Poly1305 test case'); + } + if (hasOpenSSL(3, 5)) { for (const name of ['ML-DSA-44', 'ML-DSA-65', 'ML-DSA-87']) { parameters.push({ diff --git a/test/pummel/test-crypto-dh-keys.js b/test/pummel/test-crypto-dh-keys.js index ba67bc5717af62..8aa1e30e354f95 100644 --- a/test/pummel/test-crypto-dh-keys.js +++ b/test/pummel/test-crypto-dh-keys.js @@ -33,11 +33,14 @@ if (common.isPi()) { const assert = require('assert'); const crypto = require('crypto'); -[ 'modp1', 'modp2', 'modp5', 'modp14', 'modp15', 'modp16', 'modp17' ] -.forEach((name) => { - // modp1 is 768 bits, FIPS requires >= 1024 - if (name === 'modp1' && crypto.getFips()) { - return; +for (const name of ['modp1', 'modp2', 'modp5', 'modp14', 'modp15', 'modp16', 'modp17']) { + // modp1 is 768 bits, FIPS requires >= 1024. + // BoringSSL does not support modp1 or modp2. + if ((name === 'modp1' && crypto.getFips()) || + (process.features.openssl_is_boringssl && + (name === 'modp1' || name === 'modp2'))) { + common.printSkipMessage(`Skipping unsupported ${name} test case`); + continue; } const group1 = crypto.getDiffieHellman(name); const group2 = crypto.getDiffieHellman(name); @@ -46,4 +49,4 @@ const crypto = require('crypto'); const key1 = group1.computeSecret(group2.getPublicKey()); const key2 = group2.computeSecret(group1.getPublicKey()); assert.deepStrictEqual(key1, key2); -}); +} diff --git a/test/pummel/test-webcrypto-derivebits-pbkdf2.js b/test/pummel/test-webcrypto-derivebits-pbkdf2.js index 7cbcafd020edf7..cbe64bff77505c 100644 --- a/test/pummel/test-webcrypto-derivebits-pbkdf2.js +++ b/test/pummel/test-webcrypto-derivebits-pbkdf2.js @@ -24,14 +24,21 @@ const kDerivedKeyTypes = [ ['AES-CTR', 256, undefined, 'encrypt', 'decrypt'], ['AES-GCM', 128, undefined, 'encrypt', 'decrypt'], ['AES-GCM', 256, undefined, 'encrypt', 'decrypt'], - ['AES-KW', 128, undefined, 'wrapKey', 'unwrapKey'], - ['AES-KW', 256, undefined, 'wrapKey', 'unwrapKey'], ['HMAC', 256, 'SHA-1', 'sign', 'verify'], ['HMAC', 256, 'SHA-256', 'sign', 'verify'], ['HMAC', 256, 'SHA-384', 'sign', 'verify'], ['HMAC', 256, 'SHA-512', 'sign', 'verify'], ]; +if (!process.features.openssl_is_boringssl) { + kDerivedKeyTypes.push( + ['AES-KW', 128, undefined, 'wrapKey', 'unwrapKey'], + ['AES-KW', 256, undefined, 'wrapKey', 'unwrapKey'], + ); +} else { + common.printSkipMessage('Skipping unsupported AES-KW test cases'); +} + const kPasswords = { short: '5040737377307264', long: '55736572732073686f756c64207069636b206c6f6' +