Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit de1338d

Browse filesBrowse files
panvaMoLow
authored andcommitted
crypto: fix webcrypto private/secret import with empty usages
Refs: #47864 PR-URL: #47877 Refs: #47864 Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 81d8d95 commit de1338d
Copy full SHA for de1338d
Expand file treeCollapse file tree

9 files changed

+101
-47
lines changed
Open diff view settings
Collapse file

‎lib/internal/crypto/webcrypto.js‎

Copy file name to clipboardExpand all lines: lib/internal/crypto/webcrypto.js
+22-7Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -600,52 +600,67 @@ async function importKey(
600600
});
601601

602602
algorithm = normalizeAlgorithm(algorithm, 'importKey');
603+
let result;
603604
switch (algorithm.name) {
604605
case 'RSASSA-PKCS1-v1_5':
605606
// Fall through
606607
case 'RSA-PSS':
607608
// Fall through
608609
case 'RSA-OAEP':
609-
return require('internal/crypto/rsa')
610+
result = await require('internal/crypto/rsa')
610611
.rsaImportKey(format, keyData, algorithm, extractable, keyUsages);
612+
break;
611613
case 'ECDSA':
612614
// Fall through
613615
case 'ECDH':
614-
return require('internal/crypto/ec')
616+
result = await require('internal/crypto/ec')
615617
.ecImportKey(format, keyData, algorithm, extractable, keyUsages);
618+
break;
616619
case 'Ed25519':
617620
// Fall through
618621
case 'Ed448':
619622
// Fall through
620623
case 'X25519':
621624
// Fall through
622625
case 'X448':
623-
return require('internal/crypto/cfrg')
626+
result = await require('internal/crypto/cfrg')
624627
.cfrgImportKey(format, keyData, algorithm, extractable, keyUsages);
628+
break;
625629
case 'HMAC':
626-
return require('internal/crypto/mac')
630+
result = await require('internal/crypto/mac')
627631
.hmacImportKey(format, keyData, algorithm, extractable, keyUsages);
632+
break;
628633
case 'AES-CTR':
629634
// Fall through
630635
case 'AES-CBC':
631636
// Fall through
632637
case 'AES-GCM':
633638
// Fall through
634639
case 'AES-KW':
635-
return require('internal/crypto/aes')
640+
result = await require('internal/crypto/aes')
636641
.aesImportKey(algorithm, format, keyData, extractable, keyUsages);
642+
break;
637643
case 'HKDF':
638644
// Fall through
639645
case 'PBKDF2':
640-
return importGenericSecretKey(
646+
result = await importGenericSecretKey(
641647
algorithm,
642648
format,
643649
keyData,
644650
extractable,
645651
keyUsages);
652+
break;
653+
default:
654+
throw lazyDOMException('Unrecognized algorithm name', 'NotSupportedError');
646655
}
647656

648-
throw lazyDOMException('Unrecognized algorithm name', 'NotSupportedError');
657+
if ((result.type === 'secret' || result.type === 'private') && result.usages.length === 0) {
658+
throw lazyDOMException(
659+
`Usages cannot be empty when importing a ${result.type} key.`,
660+
'SyntaxError');
661+
}
662+
663+
return result;
649664
}
650665

651666
// subtle.wrapKey() is essentially a subtle.exportKey() followed
Collapse file

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

Copy file name to clipboardExpand all lines: test/parallel/test-webcrypto-export-import-cfrg.js
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,15 @@ async function testImportPkcs8({ name, privateUsages }, extractable) {
164164
message: /key is not extractable/
165165
});
166166
}
167+
168+
await assert.rejects(
169+
subtle.importKey(
170+
'pkcs8',
171+
keyData[name].pkcs8,
172+
{ name },
173+
extractable,
174+
[/* empty usages */]),
175+
{ name: 'SyntaxError', message: 'Usages cannot be empty when importing a private key.' });
167176
}
168177

169178
async function testImportJwk({ name, publicUsages, privateUsages }, extractable) {
@@ -311,6 +320,15 @@ async function testImportJwk({ name, publicUsages, privateUsages }, extractable)
311320
publicUsages),
312321
{ message: 'JWK "crv" Parameter and algorithm name mismatch' });
313322
}
323+
324+
await assert.rejects(
325+
subtle.importKey(
326+
'jwk',
327+
{ ...jwk },
328+
{ name },
329+
extractable,
330+
[/* empty usages */]),
331+
{ name: 'SyntaxError', message: 'Usages cannot be empty when importing a private key.' });
314332
}
315333

316334
async function testImportRaw({ name, publicUsages }) {
Collapse file

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

Copy file name to clipboardExpand all lines: test/parallel/test-webcrypto-export-import-ec.js
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,15 @@ async function testImportPkcs8(
164164
message: /key is not extractable/
165165
});
166166
}
167+
168+
await assert.rejects(
169+
subtle.importKey(
170+
'pkcs8',
171+
keyData[namedCurve].pkcs8,
172+
{ name, namedCurve },
173+
extractable,
174+
[/* empty usages */]),
175+
{ name: 'SyntaxError', message: 'Usages cannot be empty when importing a private key.' });
167176
}
168177

169178
async function testImportJwk(
@@ -312,6 +321,15 @@ async function testImportJwk(
312321
privateUsages),
313322
{ message: 'JWK "crv" does not match the requested algorithm' });
314323
}
324+
325+
await assert.rejects(
326+
subtle.importKey(
327+
'jwk',
328+
{ ...jwk },
329+
{ name, namedCurve },
330+
extractable,
331+
[/* empty usages */]),
332+
{ name: 'SyntaxError', message: 'Usages cannot be empty when importing a private key.' });
315333
}
316334

317335
async function testImportRaw({ name, publicUsages }, namedCurve) {
Collapse file

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

Copy file name to clipboardExpand all lines: test/parallel/test-webcrypto-export-import-rsa.js
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,15 @@ async function testImportPkcs8(
361361
message: /key is not extractable/
362362
});
363363
}
364+
365+
await assert.rejects(
366+
subtle.importKey(
367+
'pkcs8',
368+
keyData[size].pkcs8,
369+
{ name, hash },
370+
extractable,
371+
[/* empty usages */]),
372+
{ name: 'SyntaxError', message: 'Usages cannot be empty when importing a private key.' });
364373
}
365374

366375
async function testImportJwk(
@@ -495,6 +504,15 @@ async function testImportJwk(
495504
privateUsages),
496505
{ message: 'JWK "alg" does not match the requested algorithm' });
497506
}
507+
508+
await assert.rejects(
509+
subtle.importKey(
510+
'jwk',
511+
{ ...jwk },
512+
{ name, hash },
513+
extractable,
514+
[/* empty usages */]),
515+
{ name: 'SyntaxError', message: 'Usages cannot be empty when importing a private key.' });
498516
}
499517

500518
// combinations to test
Collapse file

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

Copy file name to clipboardExpand all lines: test/parallel/test-webcrypto-export-import.js
+24Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,18 @@ const { subtle } = webcrypto;
9696
assert.deepStrictEqual(
9797
Buffer.from(jwk.k, 'base64').toString('hex'),
9898
Buffer.from(raw).toString('hex'));
99+
100+
await assert.rejects(
101+
subtle.importKey(
102+
'raw',
103+
keyData,
104+
{
105+
name: 'HMAC',
106+
hash: 'SHA-256'
107+
},
108+
true,
109+
[/* empty usages */]),
110+
{ name: 'SyntaxError', message: 'Usages cannot be empty when importing a secret key.' });
99111
}
100112

101113
test().then(common.mustCall());
@@ -126,6 +138,18 @@ const { subtle } = webcrypto;
126138
assert.deepStrictEqual(
127139
Buffer.from(jwk.k, 'base64').toString('hex'),
128140
Buffer.from(raw).toString('hex'));
141+
142+
await assert.rejects(
143+
subtle.importKey(
144+
'raw',
145+
keyData,
146+
{
147+
name: 'AES-CTR',
148+
length: 256,
149+
},
150+
true,
151+
[/* empty usages */]),
152+
{ name: 'SyntaxError', message: 'Usages cannot be empty when importing a secret key.' });
129153
}
130154

131155
test().then(common.mustCall());
Collapse file

‎test/parallel/test-webcrypto-sign-verify-ecdsa.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-webcrypto-sign-verify-ecdsa.js
-13Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,6 @@ async function testSign({ name,
149149
plaintext }) {
150150
const [
151151
publicKey,
152-
noSignPrivateKey,
153152
privateKey,
154153
hmacKey,
155154
rsaKeys,
@@ -161,12 +160,6 @@ async function testSign({ name,
161160
{ name, namedCurve },
162161
false,
163162
['verify']),
164-
subtle.importKey(
165-
'pkcs8',
166-
privateKeyBuffer,
167-
{ name, namedCurve },
168-
false,
169-
[ /* No usages */ ]),
170163
subtle.importKey(
171164
'pkcs8',
172165
privateKeyBuffer,
@@ -214,12 +207,6 @@ async function testSign({ name,
214207
message: /Unable to use this key to sign/
215208
});
216209

217-
// Test failure when no sign usage
218-
await assert.rejects(
219-
subtle.sign({ name, hash }, noSignPrivateKey, plaintext), {
220-
message: /Unable to use this key to sign/
221-
});
222-
223210
// Test failure when using the wrong algorithms
224211
await assert.rejects(
225212
subtle.sign({ name, hash }, hmacKey, plaintext), {
Collapse file

‎test/parallel/test-webcrypto-sign-verify-eddsa.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-webcrypto-sign-verify-eddsa.js
-13Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ async function testSign({ name,
131131
data }) {
132132
const [
133133
publicKey,
134-
noSignPrivateKey,
135134
privateKey,
136135
hmacKey,
137136
rsaKeys,
@@ -143,12 +142,6 @@ async function testSign({ name,
143142
{ name },
144143
false,
145144
['verify']),
146-
subtle.importKey(
147-
'pkcs8',
148-
privateKeyBuffer,
149-
{ name },
150-
false,
151-
[ /* No usages */ ]),
152145
subtle.importKey(
153146
'pkcs8',
154147
privateKeyBuffer,
@@ -197,12 +190,6 @@ async function testSign({ name,
197190
message: /Unable to use this key to sign/
198191
});
199192

200-
// Test failure when no sign usage
201-
await assert.rejects(
202-
subtle.sign({ name }, noSignPrivateKey, data), {
203-
message: /Unable to use this key to sign/
204-
});
205-
206193
// Test failure when using the wrong algorithms
207194
await assert.rejects(
208195
subtle.sign({ name }, hmacKey, data), {
Collapse file

‎test/parallel/test-webcrypto-sign-verify-hmac.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-webcrypto-sign-verify-hmac.js
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ async function testVerify({ hash,
3131
keyBuffer,
3232
{ name, hash },
3333
false,
34-
[ /* No usages */ ]),
34+
['sign']),
3535
subtle.generateKey(
3636
{
3737
name: 'RSA-PSS',
Collapse file

‎test/parallel/test-webcrypto-sign-verify-rsa.js‎

Copy file name to clipboardExpand all lines: test/parallel/test-webcrypto-sign-verify-rsa.js
-13Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ async function testSign({
132132
}) {
133133
const [
134134
publicKey,
135-
noSignPrivateKey,
136135
privateKey,
137136
hmacKey,
138137
ecdsaKeys,
@@ -143,12 +142,6 @@ async function testSign({
143142
{ name: algorithm.name, hash },
144143
false,
145144
['verify']),
146-
subtle.importKey(
147-
'pkcs8',
148-
privateKeyBuffer,
149-
{ name: algorithm.name, hash },
150-
false,
151-
[ /* No usages */ ]),
152145
subtle.importKey(
153146
'pkcs8',
154147
privateKeyBuffer,
@@ -189,12 +182,6 @@ async function testSign({
189182
message: /Unable to use this key to sign/
190183
});
191184

192-
// Test failure when no sign usage
193-
await assert.rejects(
194-
subtle.sign(algorithm, noSignPrivateKey, plaintext), {
195-
message: /Unable to use this key to sign/
196-
});
197-
198185
// Test failure when using the wrong algorithms
199186
await assert.rejects(
200187
subtle.sign(algorithm, hmacKey, plaintext), {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.