summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta-oe/recipes-devtools/nodejs/nodejs/CVE-2023-46809.patch625
-rw-r--r--meta-oe/recipes-devtools/nodejs/nodejs_16.20.2.bb1
2 files changed, 626 insertions, 0 deletions
diff --git a/meta-oe/recipes-devtools/nodejs/nodejs/CVE-2023-46809.patch b/meta-oe/recipes-devtools/nodejs/nodejs/CVE-2023-46809.patch
new file mode 100644
index 0000000000..991d39fcf9
--- /dev/null
+++ b/meta-oe/recipes-devtools/nodejs/nodejs/CVE-2023-46809.patch
@@ -0,0 +1,625 @@
1From d3d357ab096884f10f5d2f164149727eea875635 Mon Sep 17 00:00:00 2001
2From: Michael Dawson <midawson@redhat.com>
3Date: Thu, 4 Jan 2024 21:32:51 +0000
4Subject: [PATCH] crypto: disable PKCS#1 padding for privateDecrypt
5
6Refs: https://hackerone.com/bugs?subject=nodejs&report_id=2269177
7
8Disable RSA_PKCS1_PADDING for crypto.privateDecrypt() in order
9to protect against the Marvin attack.
10
11Includes a security revert flag that can be used to restore
12support.
13
14Signed-off-by: Michael Dawson <midawson@redhat.com>
15PR-URL: https://github.com/nodejs-private/node-private/pull/525
16Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
17Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
18
19CVE-ID: CVE-2023-46809
20
21Upstream-Status: Backport [https://github.com/nodejs/node/commit/d3d357ab096884f1]
22Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com>
23---
24 src/crypto/crypto_cipher.cc | 28 ++
25 src/node_revert.h | 1 +
26 test/parallel/test-crypto-rsa-dsa-revert.js | 475 ++++++++++++++++++++
27 test/parallel/test-crypto-rsa-dsa.js | 42 +-
28 4 files changed, 533 insertions(+), 13 deletions(-)
29 create mode 100644 test/parallel/test-crypto-rsa-dsa-revert.js
30
31diff --git a/src/crypto/crypto_cipher.cc b/src/crypto/crypto_cipher.cc
32index 10579ce..0311c68 100644
33--- a/src/crypto/crypto_cipher.cc
34+++ b/src/crypto/crypto_cipher.cc
35@@ -6,6 +6,7 @@
36 #include "node_buffer.h"
37 #include "node_internals.h"
38 #include "node_process-inl.h"
39+#include "node_revert.h"
40 #include "v8.h"
41
42 namespace node {
43@@ -1061,6 +1062,33 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
44 uint32_t padding;
45 if (!args[offset + 1]->Uint32Value(env->context()).To(&padding)) return;
46
47+ if (EVP_PKEY_cipher == EVP_PKEY_decrypt &&
48+ operation == PublicKeyCipher::kPrivate && padding == RSA_PKCS1_PADDING &&
49+ !IsReverted(SECURITY_REVERT_CVE_2023_46809)) {
50+ EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
51+ CHECK(ctx);
52+
53+ if (EVP_PKEY_decrypt_init(ctx.get()) <= 0) {
54+ return ThrowCryptoError(env, ERR_get_error());
55+ }
56+
57+ int rsa_pkcs1_implicit_rejection =
58+ EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_pkcs1_implicit_rejection", "1");
59+ // From the doc -2 means that the option is not supported.
60+ // The default for the option is enabled and if it has been
61+ // specifically disabled we want to respect that so we will
62+ // not throw an error if the option is supported regardless
63+ // of how it is set. The call to set the value
64+ // will not affect what is used since a different context is
65+ // used in the call if the option is supported
66+ if (rsa_pkcs1_implicit_rejection <= 0) {
67+ return THROW_ERR_INVALID_ARG_VALUE(
68+ env,
69+ "RSA_PKCS1_PADDING is no longer supported for private decryption,"
70+ " this can be reverted with --security-revert=CVE-2023-46809");
71+ }
72+ }
73+
74 const EVP_MD* digest = nullptr;
75 if (args[offset + 2]->IsString()) {
76 const Utf8Value oaep_str(env->isolate(), args[offset + 2]);
77diff --git a/src/node_revert.h b/src/node_revert.h
78index 83dcb62..bc2a288 100644
79--- a/src/node_revert.h
80+++ b/src/node_revert.h
81@@ -18,6 +18,7 @@ namespace node {
82 #define SECURITY_REVERSIONS(XX) \
83 XX(CVE_2021_44531, "CVE-2021-44531", "Cert Verif Bypass via URI SAN") \
84 XX(CVE_2021_44532, "CVE-2021-44532", "Cert Verif Bypass via Str Inject") \
85+ XX(CVE_2023_46809, "CVE-2023-46809", "Marvin attack on PKCS#1 padding") \
86 // XX(CVE_2016_PEND, "CVE-2016-PEND", "Vulnerability Title")
87
88 enum reversion {
89diff --git a/test/parallel/test-crypto-rsa-dsa-revert.js b/test/parallel/test-crypto-rsa-dsa-revert.js
90new file mode 100644
91index 0000000..84ec8f6
92--- /dev/null
93+++ b/test/parallel/test-crypto-rsa-dsa-revert.js
94@@ -0,0 +1,475 @@
95+'use strict';
96+// Flags: --security-revert=CVE-2023-46809
97+const common = require('../common');
98+if (!common.hasCrypto)
99+ common.skip('missing crypto');
100+
101+const assert = require('assert');
102+const crypto = require('crypto');
103+
104+const constants = crypto.constants;
105+
106+const fixtures = require('../common/fixtures');
107+
108+// Test certificates
109+const certPem = fixtures.readKey('rsa_cert.crt');
110+const keyPem = fixtures.readKey('rsa_private.pem');
111+const rsaKeySize = 2048;
112+const rsaPubPem = fixtures.readKey('rsa_public.pem', 'ascii');
113+const rsaKeyPem = fixtures.readKey('rsa_private.pem', 'ascii');
114+const rsaKeyPemEncrypted = fixtures.readKey('rsa_private_encrypted.pem',
115+ 'ascii');
116+const dsaPubPem = fixtures.readKey('dsa_public.pem', 'ascii');
117+const dsaKeyPem = fixtures.readKey('dsa_private.pem', 'ascii');
118+const dsaKeyPemEncrypted = fixtures.readKey('dsa_private_encrypted.pem',
119+ 'ascii');
120+const rsaPkcs8KeyPem = fixtures.readKey('rsa_private_pkcs8.pem');
121+const dsaPkcs8KeyPem = fixtures.readKey('dsa_private_pkcs8.pem');
122+
123+const ec = new TextEncoder();
124+
125+const openssl1DecryptError = {
126+ message: 'error:06065064:digital envelope routines:EVP_DecryptFinal_ex:' +
127+ 'bad decrypt',
128+ code: 'ERR_OSSL_EVP_BAD_DECRYPT',
129+ reason: 'bad decrypt',
130+ function: 'EVP_DecryptFinal_ex',
131+ library: 'digital envelope routines',
132+};
133+
134+const decryptError = common.hasOpenSSL3 ?
135+ { message: 'error:1C800064:Provider routines::bad decrypt' } :
136+ openssl1DecryptError;
137+
138+const decryptPrivateKeyError = common.hasOpenSSL3 ? {
139+ message: 'error:1C800064:Provider routines::bad decrypt',
140+} : openssl1DecryptError;
141+
142+function getBufferCopy(buf) {
143+ return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
144+}
145+
146+// Test RSA encryption/decryption
147+{
148+ const input = 'I AM THE WALRUS';
149+ const bufferToEncrypt = Buffer.from(input);
150+ const bufferPassword = Buffer.from('password');
151+
152+ let encryptedBuffer = crypto.publicEncrypt(rsaPubPem, bufferToEncrypt);
153+
154+ // Test other input types
155+ let otherEncrypted;
156+ {
157+ const ab = getBufferCopy(ec.encode(rsaPubPem));
158+ const ab2enc = getBufferCopy(bufferToEncrypt);
159+
160+ crypto.publicEncrypt(ab, ab2enc);
161+ crypto.publicEncrypt(new Uint8Array(ab), new Uint8Array(ab2enc));
162+ crypto.publicEncrypt(new DataView(ab), new DataView(ab2enc));
163+ otherEncrypted = crypto.publicEncrypt({
164+ key: Buffer.from(ab).toString('hex'),
165+ encoding: 'hex'
166+ }, Buffer.from(ab2enc).toString('hex'));
167+ }
168+
169+ let decryptedBuffer = crypto.privateDecrypt(rsaKeyPem, encryptedBuffer);
170+ const otherDecrypted = crypto.privateDecrypt(rsaKeyPem, otherEncrypted);
171+ assert.strictEqual(decryptedBuffer.toString(), input);
172+ assert.strictEqual(otherDecrypted.toString(), input);
173+
174+ decryptedBuffer = crypto.privateDecrypt(rsaPkcs8KeyPem, encryptedBuffer);
175+ assert.strictEqual(decryptedBuffer.toString(), input);
176+
177+ let decryptedBufferWithPassword = crypto.privateDecrypt({
178+ key: rsaKeyPemEncrypted,
179+ passphrase: 'password'
180+ }, encryptedBuffer);
181+
182+ const otherDecryptedBufferWithPassword = crypto.privateDecrypt({
183+ key: rsaKeyPemEncrypted,
184+ passphrase: ec.encode('password')
185+ }, encryptedBuffer);
186+
187+ assert.strictEqual(
188+ otherDecryptedBufferWithPassword.toString(),
189+ decryptedBufferWithPassword.toString());
190+
191+ decryptedBufferWithPassword = crypto.privateDecrypt({
192+ key: rsaKeyPemEncrypted,
193+ passphrase: 'password'
194+ }, encryptedBuffer);
195+
196+ assert.strictEqual(decryptedBufferWithPassword.toString(), input);
197+
198+ encryptedBuffer = crypto.publicEncrypt({
199+ key: rsaKeyPemEncrypted,
200+ passphrase: 'password'
201+ }, bufferToEncrypt);
202+
203+ decryptedBufferWithPassword = crypto.privateDecrypt({
204+ key: rsaKeyPemEncrypted,
205+ passphrase: 'password'
206+ }, encryptedBuffer);
207+ assert.strictEqual(decryptedBufferWithPassword.toString(), input);
208+
209+ encryptedBuffer = crypto.privateEncrypt({
210+ key: rsaKeyPemEncrypted,
211+ passphrase: bufferPassword
212+ }, bufferToEncrypt);
213+
214+ decryptedBufferWithPassword = crypto.publicDecrypt({
215+ key: rsaKeyPemEncrypted,
216+ passphrase: bufferPassword
217+ }, encryptedBuffer);
218+ assert.strictEqual(decryptedBufferWithPassword.toString(), input);
219+
220+ // Now with explicit RSA_PKCS1_PADDING.
221+ encryptedBuffer = crypto.privateEncrypt({
222+ padding: crypto.constants.RSA_PKCS1_PADDING,
223+ key: rsaKeyPemEncrypted,
224+ passphrase: bufferPassword
225+ }, bufferToEncrypt);
226+
227+ decryptedBufferWithPassword = crypto.publicDecrypt({
228+ padding: crypto.constants.RSA_PKCS1_PADDING,
229+ key: rsaKeyPemEncrypted,
230+ passphrase: bufferPassword
231+ }, encryptedBuffer);
232+ assert.strictEqual(decryptedBufferWithPassword.toString(), input);
233+
234+ // Omitting padding should be okay because RSA_PKCS1_PADDING is the default.
235+ decryptedBufferWithPassword = crypto.publicDecrypt({
236+ key: rsaKeyPemEncrypted,
237+ passphrase: bufferPassword
238+ }, encryptedBuffer);
239+ assert.strictEqual(decryptedBufferWithPassword.toString(), input);
240+
241+ // Now with RSA_NO_PADDING. Plaintext needs to match key size.
242+ // OpenSSL 3.x has a rsa_check_padding that will cause an error if
243+ // RSA_NO_PADDING is used.
244+ if (!common.hasOpenSSL3) {
245+ {
246+ const plaintext = 'x'.repeat(rsaKeySize / 8);
247+ encryptedBuffer = crypto.privateEncrypt({
248+ padding: crypto.constants.RSA_NO_PADDING,
249+ key: rsaKeyPemEncrypted,
250+ passphrase: bufferPassword
251+ }, Buffer.from(plaintext));
252+
253+ decryptedBufferWithPassword = crypto.publicDecrypt({
254+ padding: crypto.constants.RSA_NO_PADDING,
255+ key: rsaKeyPemEncrypted,
256+ passphrase: bufferPassword
257+ }, encryptedBuffer);
258+ assert.strictEqual(decryptedBufferWithPassword.toString(), plaintext);
259+ }
260+ }
261+
262+ encryptedBuffer = crypto.publicEncrypt(certPem, bufferToEncrypt);
263+
264+ decryptedBuffer = crypto.privateDecrypt(keyPem, encryptedBuffer);
265+ assert.strictEqual(decryptedBuffer.toString(), input);
266+
267+ encryptedBuffer = crypto.publicEncrypt(keyPem, bufferToEncrypt);
268+
269+ decryptedBuffer = crypto.privateDecrypt(keyPem, encryptedBuffer);
270+ assert.strictEqual(decryptedBuffer.toString(), input);
271+
272+ encryptedBuffer = crypto.privateEncrypt(keyPem, bufferToEncrypt);
273+
274+ decryptedBuffer = crypto.publicDecrypt(keyPem, encryptedBuffer);
275+ assert.strictEqual(decryptedBuffer.toString(), input);
276+
277+ assert.throws(() => {
278+ crypto.privateDecrypt({
279+ key: rsaKeyPemEncrypted,
280+ passphrase: 'wrong'
281+ }, bufferToEncrypt);
282+ }, decryptError);
283+
284+ assert.throws(() => {
285+ crypto.publicEncrypt({
286+ key: rsaKeyPemEncrypted,
287+ passphrase: 'wrong'
288+ }, encryptedBuffer);
289+ }, decryptError);
290+
291+ encryptedBuffer = crypto.privateEncrypt({
292+ key: rsaKeyPemEncrypted,
293+ passphrase: Buffer.from('password')
294+ }, bufferToEncrypt);
295+
296+ assert.throws(() => {
297+ crypto.publicDecrypt({
298+ key: rsaKeyPemEncrypted,
299+ passphrase: Buffer.from('wrong')
300+ }, encryptedBuffer);
301+ }, decryptError);
302+}
303+
304+function test_rsa(padding, encryptOaepHash, decryptOaepHash) {
305+ const size = (padding === 'RSA_NO_PADDING') ? rsaKeySize / 8 : 32;
306+ const input = Buffer.allocUnsafe(size);
307+ for (let i = 0; i < input.length; i++)
308+ input[i] = (i * 7 + 11) & 0xff;
309+ const bufferToEncrypt = Buffer.from(input);
310+
311+ padding = constants[padding];
312+
313+ const encryptedBuffer = crypto.publicEncrypt({
314+ key: rsaPubPem,
315+ padding: padding,
316+ oaepHash: encryptOaepHash
317+ }, bufferToEncrypt);
318+
319+ let decryptedBuffer = crypto.privateDecrypt({
320+ key: rsaKeyPem,
321+ padding: padding,
322+ oaepHash: decryptOaepHash
323+ }, encryptedBuffer);
324+ assert.deepStrictEqual(decryptedBuffer, input);
325+
326+ decryptedBuffer = crypto.privateDecrypt({
327+ key: rsaPkcs8KeyPem,
328+ padding: padding,
329+ oaepHash: decryptOaepHash
330+ }, encryptedBuffer);
331+ assert.deepStrictEqual(decryptedBuffer, input);
332+}
333+
334+test_rsa('RSA_NO_PADDING');
335+test_rsa('RSA_PKCS1_PADDING');
336+test_rsa('RSA_PKCS1_OAEP_PADDING');
337+
338+// Test OAEP with different hash functions.
339+test_rsa('RSA_PKCS1_OAEP_PADDING', undefined, 'sha1');
340+test_rsa('RSA_PKCS1_OAEP_PADDING', 'sha1', undefined);
341+test_rsa('RSA_PKCS1_OAEP_PADDING', 'sha256', 'sha256');
342+test_rsa('RSA_PKCS1_OAEP_PADDING', 'sha512', 'sha512');
343+assert.throws(() => {
344+ test_rsa('RSA_PKCS1_OAEP_PADDING', 'sha256', 'sha512');
345+}, {
346+ code: 'ERR_OSSL_RSA_OAEP_DECODING_ERROR'
347+});
348+
349+// The following RSA-OAEP test cases were created using the WebCrypto API to
350+// ensure compatibility when using non-SHA1 hash functions.
351+{
352+ const { decryptionTests } =
353+ JSON.parse(fixtures.readSync('rsa-oaep-test-vectors.js', 'utf8'));
354+
355+ for (const { ct, oaepHash, oaepLabel } of decryptionTests) {
356+ const label = oaepLabel ? Buffer.from(oaepLabel, 'hex') : undefined;
357+ const copiedLabel = oaepLabel ? getBufferCopy(label) : undefined;
358+
359+ const decrypted = crypto.privateDecrypt({
360+ key: rsaPkcs8KeyPem,
361+ oaepHash,
362+ oaepLabel: oaepLabel ? label : undefined
363+ }, Buffer.from(ct, 'hex'));
364+
365+ assert.strictEqual(decrypted.toString('utf8'), 'Hello Node.js');
366+
367+ const otherDecrypted = crypto.privateDecrypt({
368+ key: rsaPkcs8KeyPem,
369+ oaepHash,
370+ oaepLabel: copiedLabel
371+ }, Buffer.from(ct, 'hex'));
372+
373+ assert.strictEqual(otherDecrypted.toString('utf8'), 'Hello Node.js');
374+ }
375+}
376+
377+// Test invalid oaepHash and oaepLabel options.
378+for (const fn of [crypto.publicEncrypt, crypto.privateDecrypt]) {
379+ assert.throws(() => {
380+ fn({
381+ key: rsaPubPem,
382+ oaepHash: 'Hello world'
383+ }, Buffer.alloc(10));
384+ }, {
385+ code: 'ERR_OSSL_EVP_INVALID_DIGEST'
386+ });
387+
388+ for (const oaepHash of [0, false, null, Symbol(), () => {}]) {
389+ assert.throws(() => {
390+ fn({
391+ key: rsaPubPem,
392+ oaepHash
393+ }, Buffer.alloc(10));
394+ }, {
395+ code: 'ERR_INVALID_ARG_TYPE'
396+ });
397+ }
398+
399+ for (const oaepLabel of [0, false, null, Symbol(), () => {}, {}]) {
400+ assert.throws(() => {
401+ fn({
402+ key: rsaPubPem,
403+ oaepLabel
404+ }, Buffer.alloc(10));
405+ }, {
406+ code: 'ERR_INVALID_ARG_TYPE'
407+ });
408+ }
409+}
410+
411+// Test RSA key signing/verification
412+let rsaSign = crypto.createSign('SHA1');
413+let rsaVerify = crypto.createVerify('SHA1');
414+assert.ok(rsaSign);
415+assert.ok(rsaVerify);
416+
417+const expectedSignature = fixtures.readKey(
418+ 'rsa_public_sha1_signature_signedby_rsa_private_pkcs8.sha1',
419+ 'hex'
420+);
421+
422+rsaSign.update(rsaPubPem);
423+let rsaSignature = rsaSign.sign(rsaKeyPem, 'hex');
424+assert.strictEqual(rsaSignature, expectedSignature);
425+
426+rsaVerify.update(rsaPubPem);
427+assert.strictEqual(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), true);
428+
429+// Test RSA PKCS#8 key signing/verification
430+rsaSign = crypto.createSign('SHA1');
431+rsaSign.update(rsaPubPem);
432+rsaSignature = rsaSign.sign(rsaPkcs8KeyPem, 'hex');
433+assert.strictEqual(rsaSignature, expectedSignature);
434+
435+rsaVerify = crypto.createVerify('SHA1');
436+rsaVerify.update(rsaPubPem);
437+assert.strictEqual(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), true);
438+
439+// Test RSA key signing/verification with encrypted key
440+rsaSign = crypto.createSign('SHA1');
441+rsaSign.update(rsaPubPem);
442+const signOptions = { key: rsaKeyPemEncrypted, passphrase: 'password' };
443+rsaSignature = rsaSign.sign(signOptions, 'hex');
444+assert.strictEqual(rsaSignature, expectedSignature);
445+
446+rsaVerify = crypto.createVerify('SHA1');
447+rsaVerify.update(rsaPubPem);
448+assert.strictEqual(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), true);
449+
450+rsaSign = crypto.createSign('SHA1');
451+rsaSign.update(rsaPubPem);
452+assert.throws(() => {
453+ const signOptions = { key: rsaKeyPemEncrypted, passphrase: 'wrong' };
454+ rsaSign.sign(signOptions, 'hex');
455+}, decryptPrivateKeyError);
456+
457+//
458+// Test RSA signing and verification
459+//
460+{
461+ const privateKey = fixtures.readKey('rsa_private_b.pem');
462+ const publicKey = fixtures.readKey('rsa_public_b.pem');
463+
464+ const input = 'I AM THE WALRUS';
465+
466+ const signature = fixtures.readKey(
467+ 'I_AM_THE_WALRUS_sha256_signature_signedby_rsa_private_b.sha256',
468+ 'hex'
469+ );
470+
471+ const sign = crypto.createSign('SHA256');
472+ sign.update(input);
473+
474+ const output = sign.sign(privateKey, 'hex');
475+ assert.strictEqual(output, signature);
476+
477+ const verify = crypto.createVerify('SHA256');
478+ verify.update(input);
479+
480+ assert.strictEqual(verify.verify(publicKey, signature, 'hex'), true);
481+
482+ // Test the legacy signature algorithm name.
483+ const sign2 = crypto.createSign('RSA-SHA256');
484+ sign2.update(input);
485+
486+ const output2 = sign2.sign(privateKey, 'hex');
487+ assert.strictEqual(output2, signature);
488+
489+ const verify2 = crypto.createVerify('SHA256');
490+ verify2.update(input);
491+
492+ assert.strictEqual(verify2.verify(publicKey, signature, 'hex'), true);
493+}
494+
495+
496+//
497+// Test DSA signing and verification
498+//
499+{
500+ const input = 'I AM THE WALRUS';
501+
502+ // DSA signatures vary across runs so there is no static string to verify
503+ // against.
504+ const sign = crypto.createSign('SHA1');
505+ sign.update(input);
506+ const signature = sign.sign(dsaKeyPem, 'hex');
507+
508+ const verify = crypto.createVerify('SHA1');
509+ verify.update(input);
510+
511+ assert.strictEqual(verify.verify(dsaPubPem, signature, 'hex'), true);
512+
513+ // Test the legacy 'DSS1' name.
514+ const sign2 = crypto.createSign('DSS1');
515+ sign2.update(input);
516+ const signature2 = sign2.sign(dsaKeyPem, 'hex');
517+
518+ const verify2 = crypto.createVerify('DSS1');
519+ verify2.update(input);
520+
521+ assert.strictEqual(verify2.verify(dsaPubPem, signature2, 'hex'), true);
522+}
523+
524+
525+//
526+// Test DSA signing and verification with PKCS#8 private key
527+//
528+{
529+ const input = 'I AM THE WALRUS';
530+
531+ // DSA signatures vary across runs so there is no static string to verify
532+ // against.
533+ const sign = crypto.createSign('SHA1');
534+ sign.update(input);
535+ const signature = sign.sign(dsaPkcs8KeyPem, 'hex');
536+
537+ const verify = crypto.createVerify('SHA1');
538+ verify.update(input);
539+
540+ assert.strictEqual(verify.verify(dsaPubPem, signature, 'hex'), true);
541+}
542+
543+
544+//
545+// Test DSA signing and verification with encrypted key
546+//
547+const input = 'I AM THE WALRUS';
548+
549+{
550+ const sign = crypto.createSign('SHA1');
551+ sign.update(input);
552+ assert.throws(() => {
553+ sign.sign({ key: dsaKeyPemEncrypted, passphrase: 'wrong' }, 'hex');
554+ }, decryptPrivateKeyError);
555+}
556+
557+{
558+ // DSA signatures vary across runs so there is no static string to verify
559+ // against.
560+ const sign = crypto.createSign('SHA1');
561+ sign.update(input);
562+ const signOptions = { key: dsaKeyPemEncrypted, passphrase: 'password' };
563+ const signature = sign.sign(signOptions, 'hex');
564+
565+ const verify = crypto.createVerify('SHA1');
566+ verify.update(input);
567+
568+ assert.strictEqual(verify.verify(dsaPubPem, signature, 'hex'), true);
569+}
570diff --git a/test/parallel/test-crypto-rsa-dsa.js b/test/parallel/test-crypto-rsa-dsa.js
571index 9afcb38..fd27827 100644
572--- a/test/parallel/test-crypto-rsa-dsa.js
573+++ b/test/parallel/test-crypto-rsa-dsa.js
574@@ -220,20 +220,36 @@ function test_rsa(padding, encryptOaepHash, decryptOaepHash) {
575 padding: padding,
576 oaepHash: encryptOaepHash
577 }, bufferToEncrypt);
578+ if (padding === constants.RSA_PKCS1_PADDING) {
579+ assert.throws(() => {
580+ crypto.privateDecrypt({
581+ key: rsaKeyPem,
582+ padding: padding,
583+ oaepHash: decryptOaepHash
584+ }, encryptedBuffer);
585+ }, { code: 'ERR_INVALID_ARG_VALUE' });
586+ assert.throws(() => {
587+ crypto.privateDecrypt({
588+ key: rsaPkcs8KeyPem,
589+ padding: padding,
590+ oaepHash: decryptOaepHash
591+ }, encryptedBuffer);
592+ }, { code: 'ERR_INVALID_ARG_VALUE' });
593+ } else {
594+ let decryptedBuffer = crypto.privateDecrypt({
595+ key: rsaKeyPem,
596+ padding: padding,
597+ oaepHash: decryptOaepHash
598+ }, encryptedBuffer);
599+ assert.deepStrictEqual(decryptedBuffer, input);
600
601- let decryptedBuffer = crypto.privateDecrypt({
602- key: rsaKeyPem,
603- padding: padding,
604- oaepHash: decryptOaepHash
605- }, encryptedBuffer);
606- assert.deepStrictEqual(decryptedBuffer, input);
607-
608- decryptedBuffer = crypto.privateDecrypt({
609- key: rsaPkcs8KeyPem,
610- padding: padding,
611- oaepHash: decryptOaepHash
612- }, encryptedBuffer);
613- assert.deepStrictEqual(decryptedBuffer, input);
614+ decryptedBuffer = crypto.privateDecrypt({
615+ key: rsaPkcs8KeyPem,
616+ padding: padding,
617+ oaepHash: decryptOaepHash
618+ }, encryptedBuffer);
619+ assert.deepStrictEqual(decryptedBuffer, input);
620+ }
621 }
622
623 test_rsa('RSA_NO_PADDING');
624--
6252.40.0
diff --git a/meta-oe/recipes-devtools/nodejs/nodejs_16.20.2.bb b/meta-oe/recipes-devtools/nodejs/nodejs_16.20.2.bb
index 79e37214d4..95b36c926d 100644
--- a/meta-oe/recipes-devtools/nodejs/nodejs_16.20.2.bb
+++ b/meta-oe/recipes-devtools/nodejs/nodejs_16.20.2.bb
@@ -29,6 +29,7 @@ SRC_URI = "http://nodejs.org/dist/v${PV}/node-v${PV}.tar.xz \
29 file://CVE-2022-25883.patch \ 29 file://CVE-2022-25883.patch \
30 file://CVE-2024-22019.patch \ 30 file://CVE-2024-22019.patch \
31 file://CVE-2024-22025.patch \ 31 file://CVE-2024-22025.patch \
32 file://CVE-2023-46809.patch \
32 " 33 "
33SRC_URI:append:class-target = " \ 34SRC_URI:append:class-target = " \
34 file://0001-Using-native-binaries.patch \ 35 file://0001-Using-native-binaries.patch \