lib: improve Web Cryptography key validation ordering · nodejs/node@314dacd
@@ -927,6 +927,14 @@ async function wrapKey(format, key, wrappingKey, algorithm) {
927927} catch {
928928algorithm = normalizeAlgorithm(algorithm, 'encrypt');
929929}
930+931+if (algorithm.name !== wrappingKey[kAlgorithm].name)
932+throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
933+934+if (!ArrayPrototypeIncludes(wrappingKey[kKeyUsages], 'wrapKey'))
935+throw lazyDOMException(
936+'Unable to use this key to wrapKey', 'InvalidAccessError');
937+930938let keyData = await FunctionPrototypeCall(exportKey, this, format, key);
931939932940if (format === 'jwk') {
@@ -1005,6 +1013,13 @@ async function unwrapKey(
1005101310061014unwrappedKeyAlgo = normalizeAlgorithm(unwrappedKeyAlgo, 'importKey');
100710151016+if (unwrapAlgo.name !== unwrappingKey[kAlgorithm].name)
1017+throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
1018+1019+if (!ArrayPrototypeIncludes(unwrappingKey[kKeyUsages], 'unwrapKey'))
1020+throw lazyDOMException(
1021+'Unable to use this key to unwrapKey', 'InvalidAccessError');
1022+10081023let keyData = await cipherOrWrap(
10091024kWebCryptoCipherDecrypt,
10101025unwrapAlgo,
@@ -1038,12 +1053,12 @@ async function signVerify(algorithm, key, data, signature) {
10381053}
10391054algorithm = normalizeAlgorithm(algorithm, usage);
104010551041-if (!ArrayPrototypeIncludes(key[kKeyUsages], usage) ||
1042-algorithm.name !== key[kAlgorithm].name) {
1056+if (algorithm.name !== key[kAlgorithm].name)
1057+throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
1058+1059+if (!ArrayPrototypeIncludes(key[kKeyUsages], usage))
10431060throw lazyDOMException(
1044-`Unable to use this key to ${usage}`,
1045-'InvalidAccessError');
1046-}
1061+`Unable to use this key to ${usage}`, 'InvalidAccessError');
1047106210481063switch (algorithm.name) {
10491064case 'RSA-PSS':
@@ -1128,18 +1143,6 @@ async function verify(algorithm, key, signature, data) {
11281143}
1129114411301145async function cipherOrWrap(mode, algorithm, key, data, op) {
1131-// We use a Node.js style error here instead of a DOMException because
1132-// the WebCrypto spec is not specific what kind of error is to be thrown
1133-// in this case. Both Firefox and Chrome throw simple TypeErrors here.
1134-// The key algorithm and cipher algorithm must match, and the
1135-// key must have the proper usage.
1136-if (key[kAlgorithm].name !== algorithm.name ||
1137-!ArrayPrototypeIncludes(key[kKeyUsages], op)) {
1138-throw lazyDOMException(
1139-'The requested operation is not valid for the provided key',
1140-'InvalidAccessError');
1141-}
1142-11431146// While WebCrypto allows for larger input buffer sizes, we limit
11441147// those to sizes that can fit within uint32_t because of limitations
11451148// in the OpenSSL API.
@@ -1190,6 +1193,14 @@ async function encrypt(algorithm, key, data) {
11901193});
1191119411921195algorithm = normalizeAlgorithm(algorithm, 'encrypt');
1196+1197+if (algorithm.name !== key[kAlgorithm].name)
1198+throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
1199+1200+if (!ArrayPrototypeIncludes(key[kKeyUsages], 'encrypt'))
1201+throw lazyDOMException(
1202+'Unable to use this key to encrypt', 'InvalidAccessError');
1203+11931204return await cipherOrWrap(
11941205kWebCryptoCipherEncrypt,
11951206algorithm,
@@ -1219,6 +1230,14 @@ async function decrypt(algorithm, key, data) {
12191230});
1220123112211232algorithm = normalizeAlgorithm(algorithm, 'decrypt');
1233+1234+if (algorithm.name !== key[kAlgorithm].name)
1235+throw lazyDOMException('Key algorithm mismatch', 'InvalidAccessError');
1236+1237+if (!ArrayPrototypeIncludes(key[kKeyUsages], 'decrypt'))
1238+throw lazyDOMException(
1239+'Unable to use this key to decrypt', 'InvalidAccessError');
1240+12221241return await cipherOrWrap(
12231242kWebCryptoCipherDecrypt,
12241243algorithm,