From b72552c052f0933d808ff3694565cab83b38a639 Mon Sep 17 00:00:00 2001
From: Filip Skokan <panva.ip@gmail.com>
Date: Mon, 21 Nov 2022 23:43:57 +0100
Subject: [PATCH] crypto: use DataError for webcrypto keyData import failures
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

PR-URL: https://github.com/nodejs/node/pull/45569
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Backport-PR-URL: https://github.com/nodejs/node/pull/47336
---
 lib/internal/crypto/cfrg.js | 38 ++++++++++++++++++++++-------------
 lib/internal/crypto/ec.js   | 40 ++++++++++++++++++++++++-------------
 lib/internal/crypto/rsa.js  | 30 ++++++++++++++++++----------
 3 files changed, 70 insertions(+), 38 deletions(-)

diff --git a/lib/internal/crypto/cfrg.js b/lib/internal/crypto/cfrg.js
index 37fc5c5fcf2b8e..6e9066d2cdb8fe 100644
--- a/lib/internal/crypto/cfrg.js
+++ b/lib/internal/crypto/cfrg.js
@@ -90,26 +90,26 @@ function createCFRGRawKey(name, keyData, isPublic) {
     case 'X25519':
       if (keyData.byteLength !== 32) {
         throw lazyDOMException(
-          `${name} raw keys must be exactly 32-bytes`);
+          `${name} raw keys must be exactly 32-bytes`, 'DataError');
       }
       break;
     case 'Ed448':
       if (keyData.byteLength !== 57) {
         throw lazyDOMException(
-          `${name} raw keys must be exactly 57-bytes`);
+          `${name} raw keys must be exactly 57-bytes`, 'DataError');
       }
       break;
     case 'X448':
       if (keyData.byteLength !== 56) {
         throw lazyDOMException(
-          `${name} raw keys must be exactly 56-bytes`);
+          `${name} raw keys must be exactly 56-bytes`, 'DataError');
       }
       break;
   }
 
   const keyType = isPublic ? kKeyTypePublic : kKeyTypePrivate;
   if (!handle.initEDRaw(name, keyData, keyType)) {
-    throw lazyDOMException('Failure to generate key object');
+    throw lazyDOMException('Invalid keyData', 'DataError');
   }
 
   return isPublic ? new PublicKeyObject(handle) : new PrivateKeyObject(handle);
@@ -221,20 +221,30 @@ async function cfrgImportKey(
   switch (format) {
     case 'spki': {
       verifyAcceptableCfrgKeyUse(name, 'public', usagesSet);
-      keyObject = createPublicKey({
-        key: keyData,
-        format: 'der',
-        type: 'spki'
-      });
+      try {
+        keyObject = createPublicKey({
+          key: keyData,
+          format: 'der',
+          type: 'spki'
+        });
+      } catch {
+        throw lazyDOMException(
+          'Invalid keyData', 'DataError');
+      }
       break;
     }
     case 'pkcs8': {
       verifyAcceptableCfrgKeyUse(name, 'private', usagesSet);
-      keyObject = createPrivateKey({
-        key: keyData,
-        format: 'der',
-        type: 'pkcs8'
-      });
+      try {
+        keyObject = createPrivateKey({
+          key: keyData,
+          format: 'der',
+          type: 'pkcs8'
+        });
+      } catch {
+        throw lazyDOMException(
+          'Invalid keyData', 'DataError');
+      }
       break;
     }
     case 'jwk': {
diff --git a/lib/internal/crypto/ec.js b/lib/internal/crypto/ec.js
index e39d443941dba7..aea9bc9410d4ec 100644
--- a/lib/internal/crypto/ec.js
+++ b/lib/internal/crypto/ec.js
@@ -80,8 +80,12 @@ function verifyAcceptableEcKeyUse(name, type, usages) {
 function createECPublicKeyRaw(namedCurve, keyData) {
   const handle = new KeyObjectHandle();
   keyData = getArrayBufferOrView(keyData, 'keyData');
-  if (handle.initECRaw(kNamedCurveAliases[namedCurve], keyData))
-    return new PublicKeyObject(handle);
+
+  if (!handle.initECRaw(kNamedCurveAliases[namedCurve], keyData)) {
+    throw lazyDOMException('Invalid keyData', 'DataError');
+  }
+
+  return new PublicKeyObject(handle);
 }
 
 async function ecGenerateKey(algorithm, extractable, keyUsages) {
@@ -177,20 +181,30 @@ async function ecImportKey(
   switch (format) {
     case 'spki': {
       verifyAcceptableEcKeyUse(name, 'public', usagesSet);
-      keyObject = createPublicKey({
-        key: keyData,
-        format: 'der',
-        type: 'spki'
-      });
+      try {
+        keyObject = createPublicKey({
+          key: keyData,
+          format: 'der',
+          type: 'spki'
+        });
+      } catch {
+        throw lazyDOMException(
+          'Invalid keyData', 'DataError');
+      }
       break;
     }
     case 'pkcs8': {
       verifyAcceptableEcKeyUse(name, 'private', usagesSet);
-      keyObject = createPrivateKey({
-        key: keyData,
-        format: 'der',
-        type: 'pkcs8'
-      });
+      try {
+        keyObject = createPrivateKey({
+          key: keyData,
+          format: 'der',
+          type: 'pkcs8'
+        });
+      } catch {
+        throw lazyDOMException(
+          'Invalid keyData', 'DataError');
+      }
       break;
     }
     case 'jwk': {
@@ -247,8 +261,6 @@ async function ecImportKey(
     case 'raw': {
       verifyAcceptableEcKeyUse(name, 'public', usagesSet);
       keyObject = createECPublicKeyRaw(namedCurve, keyData);
-      if (keyObject === undefined)
-        throw lazyDOMException('Unable to import EC key', 'OperationError');
       break;
     }
   }
diff --git a/lib/internal/crypto/rsa.js b/lib/internal/crypto/rsa.js
index 3fe7f4fef4aef3..dad158a264e7cd 100644
--- a/lib/internal/crypto/rsa.js
+++ b/lib/internal/crypto/rsa.js
@@ -246,20 +246,30 @@ async function rsaImportKey(
   switch (format) {
     case 'spki': {
       verifyAcceptableRsaKeyUse(algorithm.name, 'public', usagesSet);
-      keyObject = createPublicKey({
-        key: keyData,
-        format: 'der',
-        type: 'spki'
-      });
+      try {
+        keyObject = createPublicKey({
+          key: keyData,
+          format: 'der',
+          type: 'spki'
+        });
+      } catch {
+        throw lazyDOMException(
+          'Invalid keyData', 'DataError');
+      }
       break;
     }
     case 'pkcs8': {
       verifyAcceptableRsaKeyUse(algorithm.name, 'private', usagesSet);
-      keyObject = createPrivateKey({
-        key: keyData,
-        format: 'der',
-        type: 'pkcs8'
-      });
+      try {
+        keyObject = createPrivateKey({
+          key: keyData,
+          format: 'der',
+          type: 'pkcs8'
+        });
+      } catch {
+        throw lazyDOMException(
+          'Invalid keyData', 'DataError');
+      }
       break;
     }
     case 'jwk': {