Skip to content

Commit 195951b

Browse files
committed
fixup! crypto: split OpenSSL 3, BoringSSL, and legacy backends
1 parent ef00769 commit 195951b

5 files changed

Lines changed: 109 additions & 0 deletions

File tree

deps/ncrypto/ncrypto.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5693,6 +5693,7 @@ Rsa::Rsa(const EVP_PKEY* pkey) : Rsa() {
56935693
GetOptionalPKeyBnParam(pkey, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, &qi_);
56945694

56955695
if (type == EVP_PKEY_RSA_PSS) {
5696+
MarkPopErrorOnReturn pop_errors;
56965697
PssParams params;
56975698
if (ReadRsaPssParams(pkey, &params)) pss_params_ = params;
56985699
}

src/crypto/crypto_dh.cc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,13 @@ void New(const FunctionCallbackInfo<Value>& args) {
206206
}
207207
}
208208

209+
#ifndef OPENSSL_IS_BORINGSSL
210+
if (BN_num_bits(bn_p.get()) >= 512 && BN_cmp(bn_g.get(), bn_p.get()) >= 0) {
211+
PutDhError(DH_R_BAD_GENERATOR);
212+
return ThrowCryptoError(env, ERR_get_error(), "Invalid generator");
213+
}
214+
#endif
215+
209216
auto dh = DHPointer::New(std::move(bn_p), std::move(bn_g));
210217
if (!dh) {
211218
return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid DH parameters");

src/node_constants.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,22 @@
5757
#if !defined(RSA_PKCS1_PSS_PADDING)
5858
#define RSA_PKCS1_PSS_PADDING 6
5959
#endif
60+
#if !defined(OPENSSL_IS_BORINGSSL) && OPENSSL_VERSION_MAJOR >= 3
61+
// OpenSSL hides these deprecated DH check constants under
62+
// OPENSSL_NO_DEPRECATED, but the numeric verifyError values remain public API.
63+
#if !defined(DH_CHECK_P_NOT_PRIME)
64+
#define DH_CHECK_P_NOT_PRIME 0x01
65+
#endif
66+
#if !defined(DH_CHECK_P_NOT_SAFE_PRIME)
67+
#define DH_CHECK_P_NOT_SAFE_PRIME 0x02
68+
#endif
69+
#if !defined(DH_UNABLE_TO_CHECK_GENERATOR)
70+
#define DH_UNABLE_TO_CHECK_GENERATOR 0x04
71+
#endif
72+
#if !defined(DH_NOT_SUITABLE_GENERATOR)
73+
#define DH_NOT_SUITABLE_GENERATOR 0x08
74+
#endif
75+
#endif
6076
#ifndef OPENSSL_NO_ENGINE
6177
#if !defined(OPENSSL_IS_BORINGSSL) && OPENSSL_VERSION_MAJOR >= 3
6278
// Engine constants remain public API while engine implementation lives in the

test/parallel/test-crypto-dh-curves.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ if (!common.hasCrypto)
66
const assert = require('assert');
77
const crypto = require('crypto');
88
const { hasOpenSSL } = require('../common/crypto');
9+
const {
10+
DH_CHECK_P_NOT_PRIME,
11+
DH_CHECK_P_NOT_SAFE_PRIME,
12+
} = crypto.constants;
913

1014
// Second OAKLEY group, see
1115
// https://github.com/nodejs/node-v0.x-archive/issues/2338 and
@@ -16,6 +20,47 @@ const p = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74' +
1620
'EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF';
1721
crypto.createDiffieHellman(p, 'hex');
1822

23+
if (!process.features.openssl_is_boringssl) {
24+
const notPrime = Buffer.from(p, 'hex');
25+
notPrime[notPrime.length - 1] = 0xfd;
26+
assert.strictEqual(
27+
crypto.createDiffieHellman(notPrime, Buffer.from([2])).verifyError,
28+
DH_CHECK_P_NOT_PRIME);
29+
30+
const notSafePrime = Buffer.from(
31+
'd2d6d13e1c1e0bbb63c742199dee010411f089ac74f0f7213348388280700fd6' +
32+
'0ef9c1e7b096a4257dcbce61c544a5d1d23db4c49c63ce302f63be5cf5804327',
33+
'hex');
34+
assert.strictEqual(
35+
crypto.createDiffieHellman(notSafePrime, Buffer.from([2])).verifyError,
36+
DH_CHECK_P_NOT_SAFE_PRIME);
37+
38+
const group = crypto.getDiffieHellman('modp14');
39+
const alice = crypto.createDiffieHellman(
40+
group.getPrime(), group.getGenerator());
41+
alice.generateKeys();
42+
const groupPrime = BigInt(`0x${group.getPrime('hex')}`);
43+
assert.throws(
44+
() => alice.computeSecret(Buffer.from([1])),
45+
{
46+
code: 'ERR_CRYPTO_INVALID_KEYLEN',
47+
message: 'Supplied key is too small'
48+
});
49+
assert.throws(
50+
() => alice.computeSecret(group.getPrime()),
51+
{
52+
code: 'ERR_CRYPTO_INVALID_KEYLEN',
53+
message: 'Supplied key is too large'
54+
});
55+
assert.throws(
56+
() => alice.computeSecret(
57+
Buffer.from((groupPrime - 1n).toString(16), 'hex')),
58+
{
59+
code: 'ERR_CRYPTO_INVALID_KEYLEN',
60+
message: 'Supplied key is too large'
61+
});
62+
}
63+
1964
// Confirm DH_check() results are exposed for optional examination.
2065
const bad_dh = process.features.openssl_is_boringssl ?
2166
crypto.createDiffieHellman('abcd', 'hex', 0) :
@@ -26,6 +71,11 @@ if (hasOpenSSL(3)) {
2671
const smallSafePrime = crypto.createDiffieHellman(
2772
Buffer.from([23]), Buffer.from([2]));
2873
assert.notStrictEqual(smallSafePrime.verifyError, 0);
74+
75+
assert.throws(
76+
() => crypto.createDiffieHellman(Buffer.from(p, 'hex'),
77+
Buffer.from(p, 'hex')),
78+
{ code: 'ERR_OSSL_DH_BAD_GENERATOR' });
2979
}
3080

3181
const availableCurves = new Set(crypto.getCurves());

test/parallel/test-crypto-key-objects.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,41 @@ if (!process.features.openssl_is_boringssl) {
909909
}
910910
}
911911
}
912+
913+
const der = publicKey.export({ format: 'der', type: 'spki' });
914+
const saltLengthParam = Buffer.from([0xa2, 0x03, 0x02, 0x01, 0x10]);
915+
const saltLengthOffset = der.indexOf(saltLengthParam);
916+
assert.notStrictEqual(saltLengthOffset, -1);
917+
918+
const importMalformedPublicKey = (key) => {
919+
const malformedKey = createPublicKey({
920+
key,
921+
format: 'der',
922+
type: 'spki'
923+
});
924+
assert.strictEqual(malformedKey.asymmetricKeyType, 'rsa-pss');
925+
assert.strictEqual(malformedKey.asymmetricKeyDetails.modulusLength, 2048);
926+
assert.strictEqual(malformedKey.asymmetricKeyDetails.publicExponent,
927+
65537n);
928+
};
929+
930+
{
931+
const negativeSaltLength = Buffer.from(der);
932+
negativeSaltLength[saltLengthOffset + saltLengthParam.length - 1] = 0x80;
933+
importMalformedPublicKey(negativeSaltLength);
934+
}
935+
936+
{
937+
const oversizedSaltLength = Buffer.concat([
938+
der.subarray(0, saltLengthOffset),
939+
Buffer.from([0xa2, 0x0b, 0x02, 0x09, 1, 0, 0, 0, 0, 0, 0, 0, 0x10]),
940+
der.subarray(saltLengthOffset + saltLengthParam.length),
941+
]);
942+
oversizedSaltLength.writeUInt16BE(der.readUInt16BE(2) + 8, 2);
943+
oversizedSaltLength[5] = der[5] + 8;
944+
oversizedSaltLength[18] = der[18] + 8;
945+
importMalformedPublicKey(oversizedSaltLength);
946+
}
912947
}
913948

914949
{

0 commit comments

Comments
 (0)