Skip to content

Commit d3f8c35

Browse files
panvatargos
authored andcommitted
crypto: ensure invalid SubtleCrypto JWK data import results in DataError
PR-URL: #55041 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
1 parent 452bc9b commit d3f8c35

8 files changed

+79
-20
lines changed

lib/internal/crypto/aes.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,12 @@ async function aesImportKey(
295295
}
296296

297297
const handle = new KeyObjectHandle();
298-
handle.initJwk(keyData);
298+
try {
299+
handle.initJwk(keyData);
300+
} catch (err) {
301+
throw lazyDOMException(
302+
'Invalid keyData', { name: 'DataError', cause: err });
303+
}
299304

300305
({ length } = handle.keyDetail({ }));
301306
validateKeyLength(length);

lib/internal/crypto/cfrg.js

+24-14
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ const {
1717
kSignJobModeVerify,
1818
} = internalBinding('crypto');
1919

20+
const {
21+
codes: {
22+
ERR_CRYPTO_INVALID_JWK,
23+
},
24+
} = require('internal/errors');
25+
2026
const {
2127
getUsagesUnion,
2228
hasAnyNotIn,
@@ -277,22 +283,26 @@ async function cfrgImportKey(
277283
isPublic,
278284
usagesSet);
279285

280-
const publicKeyObject = createCFRGRawKey(
281-
name,
282-
Buffer.from(keyData.x, 'base64'),
283-
true);
284-
285-
if (isPublic) {
286-
keyObject = publicKeyObject;
287-
} else {
288-
keyObject = createCFRGRawKey(
286+
try {
287+
const publicKeyObject = createCFRGRawKey(
289288
name,
290-
Buffer.from(keyData.d, 'base64'),
291-
false);
292-
293-
if (!createPublicKey(keyObject).equals(publicKeyObject)) {
294-
throw lazyDOMException('Invalid JWK', 'DataError');
289+
Buffer.from(keyData.x, 'base64'),
290+
true);
291+
292+
if (isPublic) {
293+
keyObject = publicKeyObject;
294+
} else {
295+
keyObject = createCFRGRawKey(
296+
name,
297+
Buffer.from(keyData.d, 'base64'),
298+
false);
299+
300+
if (!createPublicKey(keyObject).equals(publicKeyObject)) {
301+
throw new ERR_CRYPTO_INVALID_JWK();
302+
}
295303
}
304+
} catch (err) {
305+
throw lazyDOMException('Invalid keyData', { name: 'DataError', cause: err });
296306
}
297307
break;
298308
}

lib/internal/crypto/ec.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,15 @@ async function ecImportKey(
240240
}
241241

242242
const handle = new KeyObjectHandle();
243-
const type = handle.initJwk(keyData, namedCurve);
243+
let type;
244+
try {
245+
type = handle.initJwk(keyData, namedCurve);
246+
} catch (err) {
247+
throw lazyDOMException(
248+
'Invalid keyData', { name: 'DataError', cause: err });
249+
}
244250
if (type === undefined)
245-
throw lazyDOMException('Invalid JWK', 'DataError');
251+
throw lazyDOMException('Invalid keyData', 'DataError');
246252
keyObject = type === kKeyTypePrivate ?
247253
new PrivateKeyObject(handle) :
248254
new PublicKeyObject(handle);

lib/internal/crypto/mac.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,12 @@ async function hmacImportKey(
145145
}
146146

147147
const handle = new KeyObjectHandle();
148-
handle.initJwk(keyData);
148+
try {
149+
handle.initJwk(keyData);
150+
} catch (err) {
151+
throw lazyDOMException(
152+
'Invalid keyData', { name: 'DataError', cause: err });
153+
}
149154
keyObject = new SecretKeyObject(handle);
150155
break;
151156
}

lib/internal/crypto/rsa.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,15 @@ async function rsaImportKey(
275275
}
276276

277277
const handle = new KeyObjectHandle();
278-
const type = handle.initJwk(keyData);
278+
let type;
279+
try {
280+
type = handle.initJwk(keyData);
281+
} catch (err) {
282+
throw lazyDOMException(
283+
'Invalid keyData', { name: 'DataError', cause: err });
284+
}
279285
if (type === undefined)
280-
throw lazyDOMException('Invalid JWK', 'DataError');
286+
throw lazyDOMException('Invalid keyData', 'DataError');
281287

282288
keyObject = type === kKeyTypePrivate ?
283289
new PrivateKeyObject(handle) :

test/parallel/test-webcrypto-export-import-cfrg.js

+9
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,15 @@ async function testImportJwk({ name, publicUsages, privateUsages }, extractable)
322322
extractable,
323323
[/* empty usages */]),
324324
{ name: 'SyntaxError', message: 'Usages cannot be empty when importing a private key.' });
325+
326+
await assert.rejects(
327+
subtle.importKey(
328+
'jwk',
329+
{ kty: jwk.kty, /* missing x */ crv: jwk.crv },
330+
{ name },
331+
extractable,
332+
publicUsages),
333+
{ name: 'DataError', message: 'Invalid keyData' });
325334
}
326335

327336
async function testImportRaw({ name, publicUsages }) {

test/parallel/test-webcrypto-export-import-ec.js

+9
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,15 @@ async function testImportJwk(
330330
extractable,
331331
[/* empty usages */]),
332332
{ name: 'SyntaxError', message: 'Usages cannot be empty when importing a private key.' });
333+
334+
await assert.rejects(
335+
subtle.importKey(
336+
'jwk',
337+
{ kty: jwk.kty, /* missing x */ y: jwk.y, crv: jwk.crv },
338+
{ name, namedCurve },
339+
extractable,
340+
publicUsages),
341+
{ name: 'DataError', message: 'Invalid keyData' });
333342
}
334343

335344
async function testImportRaw({ name, publicUsages }, namedCurve) {

test/parallel/test-webcrypto-export-import-rsa.js

+9
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,15 @@ async function testImportJwk(
513513
extractable,
514514
[/* empty usages */]),
515515
{ name: 'SyntaxError', message: 'Usages cannot be empty when importing a private key.' });
516+
517+
await assert.rejects(
518+
subtle.importKey(
519+
'jwk',
520+
{ kty: jwk.kty, /* missing e */ n: jwk.n },
521+
{ name, hash },
522+
extractable,
523+
publicUsages),
524+
{ name: 'DataError', message: 'Invalid keyData' });
516525
}
517526

518527
// combinations to test

0 commit comments

Comments
 (0)