[WebCrypto] Implement SubtleCrypto::DeriveKey method
authorjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Mar 2017 05:50:31 +0000 (05:50 +0000)
committerjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Mar 2017 05:50:31 +0000 (05:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=169386
<rdar://problem/23789585>

Reviewed by Brent Fulgham.

Source/WebCore:

This patch does following few things:
1. It implements SubtleCrypto::DeriveKey method according to the spec:
https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-deriveKey.
2. It implements getKeyLength operations for AES-CBC, AES-KW, AES-CFB,
AES-GCM, and HMAC, which is needed by the SubtleCrypto::DeriveKey method.
3. It enables ECDH DeriveKey operation.
4. It replaces unigned long with size_t in all the crypto codes.

Tests: crypto/subtle/derive-key-malformed-parameters.html
       crypto/subtle/ecdh-import-key-derive-aes-key.html
       crypto/subtle/ecdh-import-key-derive-hmac-key-custom-length.html
       crypto/subtle/unwrap-key-malformed-parameters.html
       crypto/subtle/wrap-key-malformed-parameters.html
       crypto/workers/subtle/ecdh-import-key-derive-key.html

* CMakeLists.txt:
* DerivedSources.make:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/JSSubtleCryptoCustom.cpp:
(WebCore::normalizeCryptoAlgorithmParameters):
(WebCore::jsSubtleCryptoFunctionEncryptPromise):
(WebCore::jsSubtleCryptoFunctionDecryptPromise):
(WebCore::jsSubtleCryptoFunctionSignPromise):
(WebCore::jsSubtleCryptoFunctionVerifyPromise):
(WebCore::jsSubtleCryptoFunctionDigestPromise):
(WebCore::jsSubtleCryptoFunctionDeriveKeyPromise):
(WebCore::jsSubtleCryptoFunctionDeriveBitsPromise):
Remove unnecessary return statement from callbacks.
* crypto/CryptoAlgorithm.cpp:
(WebCore::CryptoAlgorithm::deriveBits):
(WebCore::CryptoAlgorithm::getKeyLength):
* crypto/CryptoAlgorithm.h:
* crypto/CryptoAlgorithmParameters.h:
* crypto/algorithms/CryptoAlgorithmAES_CBC.cpp:
(WebCore::CryptoAlgorithmAES_CBC::generateKey):
(WebCore::CryptoAlgorithmAES_CBC::getKeyLength):
* crypto/algorithms/CryptoAlgorithmAES_CBC.h:
* crypto/algorithms/CryptoAlgorithmAES_CFB.cpp:
(WebCore::CryptoAlgorithmAES_CFB::generateKey):
(WebCore::CryptoAlgorithmAES_CFB::getKeyLength):
* crypto/algorithms/CryptoAlgorithmAES_CFB.h:
* crypto/algorithms/CryptoAlgorithmAES_GCM.cpp:
(WebCore::CryptoAlgorithmAES_GCM::generateKey):
(WebCore::CryptoAlgorithmAES_GCM::getKeyLength):
* crypto/algorithms/CryptoAlgorithmAES_GCM.h:
* crypto/algorithms/CryptoAlgorithmAES_KW.cpp:
(WebCore::CryptoAlgorithmAES_KW::generateKey):
(WebCore::CryptoAlgorithmAES_KW::getKeyLength):
* crypto/algorithms/CryptoAlgorithmAES_KW.h:
* crypto/algorithms/CryptoAlgorithmECDH.cpp:
(WebCore::CryptoAlgorithmECDH::deriveBits):
* crypto/algorithms/CryptoAlgorithmECDH.h:
* crypto/algorithms/CryptoAlgorithmHMAC.cpp:
(WebCore::CryptoAlgorithmHMAC::getKeyLength):
* crypto/algorithms/CryptoAlgorithmHMAC.h:
* crypto/keys/CryptoKeyAES.cpp:
(WebCore::CryptoKeyAES::getKeyLength):
* crypto/keys/CryptoKeyAES.h:
* crypto/keys/CryptoKeyHMAC.cpp:
(WebCore::getKeyLengthFromHash):
(WebCore::CryptoKeyHMAC::generate):
(WebCore::CryptoKeyHMAC::getKeyLength):
* crypto/keys/CryptoKeyHMAC.h:
* crypto/mac/CryptoAlgorithmECDHMac.cpp:
(WebCore::CryptoAlgorithmECDH::platformDeriveBits):
* crypto/parameters/AesKeyParams.idl: Renamed from Source/WebCore/crypto/parameters/AesKeyGenParams.idl.
* crypto/parameters/CryptoAlgorithmAesKeyParams.h: Renamed from Source/WebCore/crypto/parameters/CryptoAlgorithmAesKeyGenParams.h.
Rename AesKeyGenParams to AesKeyParams to represent a unified dictionary for AesKeyGenParams and AesDerivedKeyParams.
* crypto/parameters/CryptoAlgorithmHmacKeyParams.h:
* crypto/parameters/CryptoAlgorithmRsaKeyGenParams.h:

LayoutTests:

* crypto/subtle/aes-generate-key-malformed-parameters-expected.txt:
* crypto/subtle/derive-key-malformed-parameters-expected.txt: Added.
* crypto/subtle/derive-key-malformed-parameters.html: Added.
* crypto/subtle/deriveKey-malformed-parameters-expected.txt: Removed.
* crypto/subtle/deriveKey-malformed-parameters.html: Removed.
* crypto/subtle/ecdh-import-key-derive-aes-key-expected.txt: Added.
* crypto/subtle/ecdh-import-key-derive-aes-key.html: Added.
* crypto/subtle/ecdh-import-key-derive-hmac-key-custom-length-expected.txt: Added.
* crypto/subtle/ecdh-import-key-derive-hmac-key-custom-length.html: Added.
* crypto/subtle/unwrap-key-malformed-parameters-expected.txt: Renamed from LayoutTests/crypto/subtle/unwrapKey-malformed-parameters-expected.txt.
* crypto/subtle/unwrap-key-malformed-parameters.html: Renamed from LayoutTests/crypto/subtle/unwrapKey-malformed-parameters.html.
* crypto/subtle/wrap-key-malformed-parameters-expected.txt: Renamed from LayoutTests/crypto/subtle/wrapKey-malformed-parameters-expected.txt.
* crypto/subtle/wrap-key-malformed-parameters.html: Renamed from LayoutTests/crypto/subtle/wrapKey-malformed-parameters.html.
A bit renaming.
* crypto/workers/subtle/ecdh-import-key-derive-key-expected.txt: Added.
* crypto/workers/subtle/ecdh-import-key-derive-key.html: Added.
* crypto/workers/subtle/resources/ecdh-import-key-derive-key.js: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@213628 268f45cc-cd09-0410-ab3c-d52691b4dbfc

46 files changed:
LayoutTests/ChangeLog
LayoutTests/crypto/subtle/aes-generate-key-malformed-parameters-expected.txt
LayoutTests/crypto/subtle/derive-key-malformed-parameters-expected.txt [new file with mode: 0644]
LayoutTests/crypto/subtle/derive-key-malformed-parameters.html [new file with mode: 0644]
LayoutTests/crypto/subtle/deriveKey-malformed-parameters-expected.txt [deleted file]
LayoutTests/crypto/subtle/deriveKey-malformed-parameters.html [deleted file]
LayoutTests/crypto/subtle/ecdh-import-key-derive-aes-key-expected.txt [new file with mode: 0644]
LayoutTests/crypto/subtle/ecdh-import-key-derive-aes-key.html [new file with mode: 0644]
LayoutTests/crypto/subtle/ecdh-import-key-derive-hmac-key-custom-length-expected.txt [new file with mode: 0644]
LayoutTests/crypto/subtle/ecdh-import-key-derive-hmac-key-custom-length.html [new file with mode: 0644]
LayoutTests/crypto/subtle/unwrap-key-malformed-parameters-expected.txt [moved from LayoutTests/crypto/subtle/unwrapKey-malformed-parameters-expected.txt with 100% similarity]
LayoutTests/crypto/subtle/unwrap-key-malformed-parameters.html [moved from LayoutTests/crypto/subtle/unwrapKey-malformed-parameters.html with 100% similarity]
LayoutTests/crypto/subtle/wrap-key-malformed-parameters-expected.txt [moved from LayoutTests/crypto/subtle/wrapKey-malformed-parameters-expected.txt with 100% similarity]
LayoutTests/crypto/subtle/wrap-key-malformed-parameters.html [moved from LayoutTests/crypto/subtle/wrapKey-malformed-parameters.html with 100% similarity]
LayoutTests/crypto/workers/subtle/ecdh-import-key-derive-key-expected.txt [new file with mode: 0644]
LayoutTests/crypto/workers/subtle/ecdh-import-key-derive-key.html [new file with mode: 0644]
LayoutTests/crypto/workers/subtle/resources/ecdh-import-key-derive-key.js [new file with mode: 0644]
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/DerivedSources.make
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp
Source/WebCore/crypto/CryptoAlgorithm.cpp
Source/WebCore/crypto/CryptoAlgorithm.h
Source/WebCore/crypto/CryptoAlgorithmParameters.h
Source/WebCore/crypto/algorithms/CryptoAlgorithmAES_CBC.cpp
Source/WebCore/crypto/algorithms/CryptoAlgorithmAES_CBC.h
Source/WebCore/crypto/algorithms/CryptoAlgorithmAES_CFB.cpp
Source/WebCore/crypto/algorithms/CryptoAlgorithmAES_CFB.h
Source/WebCore/crypto/algorithms/CryptoAlgorithmAES_GCM.cpp
Source/WebCore/crypto/algorithms/CryptoAlgorithmAES_GCM.h
Source/WebCore/crypto/algorithms/CryptoAlgorithmAES_KW.cpp
Source/WebCore/crypto/algorithms/CryptoAlgorithmAES_KW.h
Source/WebCore/crypto/algorithms/CryptoAlgorithmECDH.cpp
Source/WebCore/crypto/algorithms/CryptoAlgorithmECDH.h
Source/WebCore/crypto/algorithms/CryptoAlgorithmHMAC.cpp
Source/WebCore/crypto/algorithms/CryptoAlgorithmHMAC.h
Source/WebCore/crypto/keys/CryptoKeyAES.cpp
Source/WebCore/crypto/keys/CryptoKeyAES.h
Source/WebCore/crypto/keys/CryptoKeyHMAC.cpp
Source/WebCore/crypto/keys/CryptoKeyHMAC.h
Source/WebCore/crypto/mac/CryptoAlgorithmECDHMac.cpp
Source/WebCore/crypto/parameters/AesKeyParams.idl [moved from Source/WebCore/crypto/parameters/AesKeyGenParams.idl with 83% similarity]
Source/WebCore/crypto/parameters/CryptoAlgorithmAesKeyParams.h [moved from Source/WebCore/crypto/parameters/CryptoAlgorithmAesKeyGenParams.h with 87% similarity]
Source/WebCore/crypto/parameters/CryptoAlgorithmHmacKeyParams.h
Source/WebCore/crypto/parameters/CryptoAlgorithmRsaKeyGenParams.h

index 86478cd..054b647 100644 (file)
@@ -1,3 +1,29 @@
+2017-03-08  Jiewen Tan  <jiewen_tan@apple.com>
+
+        [WebCrypto] Implement SubtleCrypto::DeriveKey method
+        https://bugs.webkit.org/show_bug.cgi?id=169386
+        <rdar://problem/23789585>
+
+        Reviewed by Brent Fulgham.
+
+        * crypto/subtle/aes-generate-key-malformed-parameters-expected.txt:
+        * crypto/subtle/derive-key-malformed-parameters-expected.txt: Added.
+        * crypto/subtle/derive-key-malformed-parameters.html: Added.
+        * crypto/subtle/deriveKey-malformed-parameters-expected.txt: Removed.
+        * crypto/subtle/deriveKey-malformed-parameters.html: Removed.
+        * crypto/subtle/ecdh-import-key-derive-aes-key-expected.txt: Added.
+        * crypto/subtle/ecdh-import-key-derive-aes-key.html: Added.
+        * crypto/subtle/ecdh-import-key-derive-hmac-key-custom-length-expected.txt: Added.
+        * crypto/subtle/ecdh-import-key-derive-hmac-key-custom-length.html: Added.
+        * crypto/subtle/unwrap-key-malformed-parameters-expected.txt: Renamed from LayoutTests/crypto/subtle/unwrapKey-malformed-parameters-expected.txt.
+        * crypto/subtle/unwrap-key-malformed-parameters.html: Renamed from LayoutTests/crypto/subtle/unwrapKey-malformed-parameters.html.
+        * crypto/subtle/wrap-key-malformed-parameters-expected.txt: Renamed from LayoutTests/crypto/subtle/wrapKey-malformed-parameters-expected.txt.
+        * crypto/subtle/wrap-key-malformed-parameters.html: Renamed from LayoutTests/crypto/subtle/wrapKey-malformed-parameters.html.
+        A bit renaming.
+        * crypto/workers/subtle/ecdh-import-key-derive-key-expected.txt: Added.
+        * crypto/workers/subtle/ecdh-import-key-derive-key.html: Added.
+        * crypto/workers/subtle/resources/ecdh-import-key-derive-key.js: Added.
+
 2017-03-08  Matt Baker  <mattbaker@apple.com>
 
         Web Inspector: Add DOM breakpoints UI for node/subtree modification events
index a8bdbfe..b781d00 100644 (file)
@@ -3,11 +3,11 @@ Test generating an AES key with malformed-paramters.
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS crypto.subtle.generateKey("aes-cbc", extractable, ["encrypt", "decrypt"]) rejected promise  with TypeError: Member AesKeyGenParams.length is required and must be an instance of unsigned short.
-PASS crypto.subtle.generateKey({name: "aes-cbc"}, extractable, ["encrypt", "decrypt"]) rejected promise  with TypeError: Member AesKeyGenParams.length is required and must be an instance of unsigned short.
+PASS crypto.subtle.generateKey("aes-cbc", extractable, ["encrypt", "decrypt"]) rejected promise  with TypeError: Member AesKeyParams.length is required and must be an instance of unsigned short.
+PASS crypto.subtle.generateKey({name: "aes-cbc"}, extractable, ["encrypt", "decrypt"]) rejected promise  with TypeError: Member AesKeyParams.length is required and must be an instance of unsigned short.
 PASS crypto.subtle.generateKey({name: "aes-cbc", length: true}, extractable, ["encrypt", "decrypt"]) rejected promise  with OperationError (DOM Exception 34): The operation failed for an operation-specific reason.
 PASS crypto.subtle.generateKey({name: "aes-cbc", length: null}, extractable, ["encrypt", "decrypt"]) rejected promise  with OperationError (DOM Exception 34): The operation failed for an operation-specific reason.
-PASS crypto.subtle.generateKey({name: "aes-cbc", length: undefined}, extractable, ["encrypt", "decrypt"]) rejected promise  with TypeError: Member AesKeyGenParams.length is required and must be an instance of unsigned short.
+PASS crypto.subtle.generateKey({name: "aes-cbc", length: undefined}, extractable, ["encrypt", "decrypt"]) rejected promise  with TypeError: Member AesKeyParams.length is required and must be an instance of unsigned short.
 PASS crypto.subtle.generateKey({name: "aes-cbc", length: Symbol()}, extractable, ["encrypt", "decrypt"]) rejected promise  with TypeError: Cannot convert a symbol to a number.
 PASS crypto.subtle.generateKey({name: "aes-cbc", length: { }}, extractable, ["encrypt", "decrypt"]) rejected promise  with OperationError (DOM Exception 34): The operation failed for an operation-specific reason.
 PASS crypto.subtle.generateKey({name: "aes-cbc", length: "foo"}, extractable, ["encrypt", "decrypt"]) rejected promise  with OperationError (DOM Exception 34): The operation failed for an operation-specific reason.
diff --git a/LayoutTests/crypto/subtle/derive-key-malformed-parameters-expected.txt b/LayoutTests/crypto/subtle/derive-key-malformed-parameters-expected.txt
new file mode 100644 (file)
index 0000000..67ba4a7
--- /dev/null
@@ -0,0 +1,24 @@
+Test deriveKey operation with malformed parameters
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS crypto.subtle.deriveKey() rejected promise  with TypeError: Not enough arguments.
+PASS crypto.subtle.deriveKey(1) rejected promise  with TypeError: Not enough arguments.
+PASS crypto.subtle.deriveKey(1, 2) rejected promise  with TypeError: Not enough arguments.
+PASS crypto.subtle.deriveKey(1, 2, 3) rejected promise  with TypeError: Not enough arguments.
+PASS crypto.subtle.deriveKey(1, 2, 3, 4) rejected promise  with TypeError: Not enough arguments.
+PASS crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, "AES-CBC", extractable, ["encrypt"]) rejected promise  with TypeError: Member AesKeyParams.length is required and must be an instance of unsigned short.
+PASS crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, "RSAES-PKCS1-v1_5", extractable, ["encrypt"]) rejected promise  with NotSupportedError (DOM Exception 9): The operation is not supported..
+PASS crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, {name: "RSA-OAEP", hash: "sha-1"}, extractable, ["encrypt"]) rejected promise  with NotSupportedError (DOM Exception 9): The operation is not supported..
+PASS crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, {name: "ECDH", namedCurve: "P-256"}, extractable, ["encrypt"]) rejected promise  with NotSupportedError (DOM Exception 9): The operation is not supported..
+PASS crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, wrongKey, {name: "aes-cbc", length: 128}, extractable, ["encrypt"]) rejected promise  with InvalidAccessError (DOM Exception 15): CryptoKey doesn't match AlgorithmIdentifier.
+PASS crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, wrongKey, {name: "aes-cbc", length: 128}, extractable, ["encrypt"]) rejected promise  with InvalidAccessError (DOM Exception 15): CryptoKey doesn't support CryptoKey derivation.
+PASS crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, {name: "aes-cbc", length: 1}, extractable, ["encrypt"]) rejected promise  with OperationError (DOM Exception 34): Cannot get key length from derivedKeyType.
+PASS crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, {name: "hmac", hash: "hmac"}, extractable, ["sign"]) rejected promise  with NotSupportedError (DOM Exception 9): The operation is not supported..
+PASS crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, {name: "hmac", hash: "sha-1", length: 0}, extractable, ["sign"]) rejected promise  with TypeError: Cannot get key length from derivedKeyType.
+PASS crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, {name: "aes-cbc", length: 128}, extractable, []) rejected promise  with SyntaxError (DOM Exception 12): A required parameter was missing or out-of-range.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/subtle/derive-key-malformed-parameters.html b/LayoutTests/crypto/subtle/derive-key-malformed-parameters.html
new file mode 100644 (file)
index 0000000..2b3259c
--- /dev/null
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<script src="../resources/common.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+description("Test deriveKey operation with malformed parameters");
+
+jsTestIsAsync = true;
+
+var extractable = true;
+var jwkPrivateKey = {
+    kty: "EC",
+    crv: "P-256",
+    x: "1FSVWieTvikFkG1NOyhkUCaMbdQhxwH6aCu4Ez-sRtA",
+    y: "9jmNTLqM4cjBhdAnHcNI9YQV3O8LFmo-EdZWk8ntAaI",
+    d: "ppxBSov3N8_AUcisAuvmLV4yE8e_L_BLE8bZb9Z1Xjg",
+};
+var jwkPublicKey = {
+    kty: "EC",
+    crv: "P-256",
+    x: "1FSVWieTvikFkG1NOyhkUCaMbdQhxwH6aCu4Ez-sRtA",
+    y: "9jmNTLqM4cjBhdAnHcNI9YQV3O8LFmo-EdZWk8ntAaI",
+};
+var rawKey = asciiToUint8Array("jnOw99oOZFLIEPMr");
+
+// Not enough arguments.
+shouldReject('crypto.subtle.deriveKey()');
+shouldReject('crypto.subtle.deriveKey(1)');
+shouldReject('crypto.subtle.deriveKey(1, 2)');
+shouldReject('crypto.subtle.deriveKey(1, 2, 3)');
+shouldReject('crypto.subtle.deriveKey(1, 2, 3, 4)');
+
+crypto.subtle.importKey("jwk", jwkPrivateKey, { name: "ECDH", namedCurve: "P-256" }, extractable, ["deriveKey"]).then(function(result) {
+    privateKey = result;
+    return crypto.subtle.importKey("jwk", jwkPublicKey, { name: "ECDH", namedCurve: "P-256" }, extractable, [ ]);
+}).then(function(result) {
+    publicKey = result;
+
+    // Malformed GetKeyLength AlgorithmIdentifier.
+    shouldReject('crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, "AES-CBC", extractable, ["encrypt"])');
+    // Not support GetKeyLength AlgorithmIdentifier.
+    shouldReject('crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, "RSAES-PKCS1-v1_5", extractable, ["encrypt"])');
+    shouldReject('crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, {name: "RSA-OAEP", hash: "sha-1"}, extractable, ["encrypt"])');
+    shouldReject('crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, {name: "ECDH", namedCurve: "P-256"}, extractable, ["encrypt"])');
+
+    return crypto.subtle.importKey("raw", rawKey, {name: "hmac", hash: "sha-1"}, extractable, ["sign", "verify"])
+}).then(function(result) {
+    wrongKey = result;
+
+    // Mismatched AlgorithmIdentifier.
+    shouldReject('crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, wrongKey, {name: "aes-cbc", length: 128}, extractable, ["encrypt"])');
+
+    return crypto.subtle.importKey("jwk", jwkPrivateKey, { name: "ECDH", namedCurve: "P-256" }, extractable, ["deriveBits"]);
+}).then(function(result) {
+    wrongKey = result;
+
+    // Wrong usage.
+    shouldReject('crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, wrongKey, {name: "aes-cbc", length: 128}, extractable, ["encrypt"])');
+    // derivedKeyType with wrong AES params.
+    shouldReject('crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, {name: "aes-cbc", length: 1}, extractable, ["encrypt"])');
+    // derivedKeyType with wrong HMAC params.
+    shouldReject('crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, {name: "hmac", hash: "hmac"}, extractable, ["sign"])');
+    shouldReject('crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, {name: "hmac", hash: "sha-1", length: 0}, extractable, ["sign"])');
+    // Null usages
+    return shouldReject('crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, {name: "aes-cbc", length: 128}, extractable, [])');
+}).then(finishJSTest, finishJSTest);
+
+</script>
+
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/crypto/subtle/deriveKey-malformed-parameters-expected.txt b/LayoutTests/crypto/subtle/deriveKey-malformed-parameters-expected.txt
deleted file mode 100644 (file)
index 58aa8fa..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-Test deriveKey operation with malformed parameters
-
-On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-
-
-PASS crypto.subtle.deriveKey() rejected promise  with TypeError: Not enough arguments.
-PASS crypto.subtle.deriveKey(1) rejected promise  with TypeError: Not enough arguments.
-PASS crypto.subtle.deriveKey(1, 2) rejected promise  with TypeError: Not enough arguments.
-PASS crypto.subtle.deriveKey(1, 2, 3) rejected promise  with TypeError: Not enough arguments.
-PASS crypto.subtle.deriveKey(1, 2, 3, 4) rejected promise  with TypeError: Not enough arguments.
-PASS crypto.subtle.deriveKey("ECDH", 2, 3, 4, 5) rejected promise  with NotSupportedError (DOM Exception 9): The operation is not supported..
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/LayoutTests/crypto/subtle/deriveKey-malformed-parameters.html b/LayoutTests/crypto/subtle/deriveKey-malformed-parameters.html
deleted file mode 100644 (file)
index 86f1b34..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script src="../../resources/js-test-pre.js"></script>
-<script src="../resources/common.js"></script>
-</head>
-<body>
-<p id="description"></p>
-<div id="console"></div>
-
-<script>
-description("Test deriveKey operation with malformed parameters");
-
-// Not enough arguments.
-shouldReject('crypto.subtle.deriveKey()');
-shouldReject('crypto.subtle.deriveKey(1)');
-shouldReject('crypto.subtle.deriveKey(1, 2)');
-shouldReject('crypto.subtle.deriveKey(1, 2, 3)');
-shouldReject('crypto.subtle.deriveKey(1, 2, 3, 4)');
-// Not support.
-shouldReject('crypto.subtle.deriveKey("ECDH", 2, 3, 4, 5)');
-</script>
-
-<script src="../../resources/js-test-post.js"></script>
-</body>
-</html>
diff --git a/LayoutTests/crypto/subtle/ecdh-import-key-derive-aes-key-expected.txt b/LayoutTests/crypto/subtle/ecdh-import-key-derive-aes-key-expected.txt
new file mode 100644 (file)
index 0000000..b71d4c2
--- /dev/null
@@ -0,0 +1,14 @@
+Test deriving AES Keys with imported ECDH base key
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS derivedKey.type is 'secret'
+PASS derivedKey.extractable is true
+PASS derivedKey.algorithm.name is 'AES-CBC'
+PASS derivedKey.algorithm.length is 128
+PASS derivedKey.usages is ['decrypt', 'encrypt', 'unwrapKey', 'wrapKey']
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/subtle/ecdh-import-key-derive-aes-key.html b/LayoutTests/crypto/subtle/ecdh-import-key-derive-aes-key.html
new file mode 100644 (file)
index 0000000..d8a3061
--- /dev/null
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<script src="../resources/common.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+description("Test deriving AES Keys with imported ECDH base key");
+
+jsTestIsAsync = true;
+
+var extractable = true;
+var jwkPrivateKey = {
+    kty: "EC",
+    crv: "P-256",
+    x: "1FSVWieTvikFkG1NOyhkUCaMbdQhxwH6aCu4Ez-sRtA",
+    y: "9jmNTLqM4cjBhdAnHcNI9YQV3O8LFmo-EdZWk8ntAaI",
+    d: "ppxBSov3N8_AUcisAuvmLV4yE8e_L_BLE8bZb9Z1Xjg",
+};
+var jwkPublicKey = {
+    kty: "EC",
+    crv: "P-256",
+    x: "1FSVWieTvikFkG1NOyhkUCaMbdQhxwH6aCu4Ez-sRtA",
+    y: "9jmNTLqM4cjBhdAnHcNI9YQV3O8LFmo-EdZWk8ntAaI",
+};
+
+crypto.subtle.importKey("jwk", jwkPrivateKey, { name: "ECDH", namedCurve: "P-256" }, extractable, ["deriveKey"]).then(function(result) {
+    privateKey = result;
+    return crypto.subtle.importKey("jwk", jwkPublicKey, { name: "ECDH", namedCurve: "P-256" }, extractable, [ ]);
+}).then(function(result) {
+    publicKey = result;
+    return crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, {name: "aes-cbc", length: 128}, extractable, ['decrypt', 'encrypt', 'unwrapKey', 'wrapKey']);
+}).then(function(result) {
+    derivedKey = result;
+
+    shouldBe("derivedKey.type", "'secret'");
+    shouldBe("derivedKey.extractable", "true");
+    shouldBe("derivedKey.algorithm.name", "'AES-CBC'");
+    shouldBe("derivedKey.algorithm.length", "128");
+    shouldBe("derivedKey.usages", "['decrypt', 'encrypt', 'unwrapKey', 'wrapKey']");
+
+    finishJSTest();
+});
+
+</script>
+
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/crypto/subtle/ecdh-import-key-derive-hmac-key-custom-length-expected.txt b/LayoutTests/crypto/subtle/ecdh-import-key-derive-hmac-key-custom-length-expected.txt
new file mode 100644 (file)
index 0000000..b20e604
--- /dev/null
@@ -0,0 +1,15 @@
+Test deriving HMAC Keys with imported ECDH base key
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS derivedKey.type is 'secret'
+PASS derivedKey.extractable is true
+PASS derivedKey.algorithm.name is 'HMAC'
+PASS derivedKey.algorithm.length is 128
+PASS derivedKey.algorithm.hash.name is 'SHA-1'
+PASS derivedKey.usages is ['sign', 'verify']
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/subtle/ecdh-import-key-derive-hmac-key-custom-length.html b/LayoutTests/crypto/subtle/ecdh-import-key-derive-hmac-key-custom-length.html
new file mode 100644 (file)
index 0000000..010e09a
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<script src="../resources/common.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+description("Test deriving HMAC Keys with imported ECDH base key");
+
+jsTestIsAsync = true;
+
+var extractable = true;
+var jwkPrivateKey = {
+    kty: "EC",
+    crv: "P-256",
+    x: "1FSVWieTvikFkG1NOyhkUCaMbdQhxwH6aCu4Ez-sRtA",
+    y: "9jmNTLqM4cjBhdAnHcNI9YQV3O8LFmo-EdZWk8ntAaI",
+    d: "ppxBSov3N8_AUcisAuvmLV4yE8e_L_BLE8bZb9Z1Xjg",
+};
+var jwkPublicKey = {
+    kty: "EC",
+    crv: "P-256",
+    x: "1FSVWieTvikFkG1NOyhkUCaMbdQhxwH6aCu4Ez-sRtA",
+    y: "9jmNTLqM4cjBhdAnHcNI9YQV3O8LFmo-EdZWk8ntAaI",
+};
+
+crypto.subtle.importKey("jwk", jwkPrivateKey, { name: "ECDH", namedCurve: "P-256" }, extractable, ["deriveKey"]).then(function(result) {
+    privateKey = result;
+    return crypto.subtle.importKey("jwk", jwkPublicKey, { name: "ECDH", namedCurve: "P-256" }, extractable, [ ]);
+}).then(function(result) {
+    publicKey = result;
+    return crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, {name: "hmac", hash: "sha-1", length: 128}, extractable, ['sign', 'verify']);
+}).then(function(result) {
+    derivedKey = result;
+
+    shouldBe("derivedKey.type", "'secret'");
+    shouldBe("derivedKey.extractable", "true");
+    shouldBe("derivedKey.algorithm.name", "'HMAC'");
+    shouldBe("derivedKey.algorithm.length", "128");
+    shouldBe("derivedKey.algorithm.hash.name", "'SHA-1'");
+    shouldBe("derivedKey.usages", "['sign', 'verify']");
+
+    finishJSTest();
+});
+
+</script>
+
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/crypto/workers/subtle/ecdh-import-key-derive-key-expected.txt b/LayoutTests/crypto/workers/subtle/ecdh-import-key-derive-key-expected.txt
new file mode 100644 (file)
index 0000000..adb583f
--- /dev/null
@@ -0,0 +1,15 @@
+[Worker] Test deriving AES Keys with imported ECDH base key in workers
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Starting worker: resources/ecdh-import-key-derive-key.js
+PASS [Worker] derivedKey.type is 'secret'
+PASS [Worker] derivedKey.extractable is true
+PASS [Worker] derivedKey.algorithm.name is 'AES-CBC'
+PASS [Worker] derivedKey.algorithm.length is 128
+PASS [Worker] derivedKey.usages is ['decrypt', 'encrypt', 'unwrapKey', 'wrapKey']
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/workers/subtle/ecdh-import-key-derive-key.html b/LayoutTests/crypto/workers/subtle/ecdh-import-key-derive-key.html
new file mode 100644 (file)
index 0000000..c29db2d
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+    <script>
+        worker = startWorker('resources/ecdh-import-key-derive-key.js');
+    </script>
+    <script src="../../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/crypto/workers/subtle/resources/ecdh-import-key-derive-key.js b/LayoutTests/crypto/workers/subtle/resources/ecdh-import-key-derive-key.js
new file mode 100644 (file)
index 0000000..b710435
--- /dev/null
@@ -0,0 +1,39 @@
+importScripts('../../../../resources/js-test-pre.js');
+importScripts("../../../resources/common.js");
+
+description("Test deriving AES Keys with imported ECDH base key in workers");
+
+jsTestIsAsync = true;
+
+var extractable = true;
+var jwkPrivateKey = {
+    kty: "EC",
+    crv: "P-256",
+    x: "1FSVWieTvikFkG1NOyhkUCaMbdQhxwH6aCu4Ez-sRtA",
+    y: "9jmNTLqM4cjBhdAnHcNI9YQV3O8LFmo-EdZWk8ntAaI",
+    d: "ppxBSov3N8_AUcisAuvmLV4yE8e_L_BLE8bZb9Z1Xjg",
+};
+var jwkPublicKey = {
+    kty: "EC",
+    crv: "P-256",
+    x: "1FSVWieTvikFkG1NOyhkUCaMbdQhxwH6aCu4Ez-sRtA",
+    y: "9jmNTLqM4cjBhdAnHcNI9YQV3O8LFmo-EdZWk8ntAaI",
+};
+
+crypto.subtle.importKey("jwk", jwkPrivateKey, { name: "ECDH", namedCurve: "P-256" }, extractable, ["deriveKey"]).then(function(result) {
+    privateKey = result;
+    return crypto.subtle.importKey("jwk", jwkPublicKey, { name: "ECDH", namedCurve: "P-256" }, extractable, [ ]);
+}).then(function(result) {
+    publicKey = result;
+    return crypto.subtle.deriveKey({ name:"ECDH", public:publicKey }, privateKey, {name: "aes-cbc", length: 128}, extractable, ['decrypt', 'encrypt', 'unwrapKey', 'wrapKey']);
+}).then(function(result) {
+    derivedKey = result;
+
+    shouldBe("derivedKey.type", "'secret'");
+    shouldBe("derivedKey.extractable", "true");
+    shouldBe("derivedKey.algorithm.name", "'AES-CBC'");
+    shouldBe("derivedKey.algorithm.length", "128");
+    shouldBe("derivedKey.usages", "['decrypt', 'encrypt', 'unwrapKey', 'wrapKey']");
+
+    finishJSTest();
+});
index 779ba19..fef6ce4 100644 (file)
@@ -342,7 +342,7 @@ set(WebCore_NON_SVG_IDL_FILES
 
     crypto/parameters/AesCbcCfbParams.idl
     crypto/parameters/AesGcmParams.idl
-    crypto/parameters/AesKeyGenParams.idl
+    crypto/parameters/AesKeyParams.idl
     crypto/parameters/EcKeyParams.idl
     crypto/parameters/EcdhKeyDeriveParams.idl
     crypto/parameters/HmacKeyParams.idl
index ad0e0d5..efc73d3 100644 (file)
@@ -1,3 +1,82 @@
+2017-03-08  Jiewen Tan  <jiewen_tan@apple.com>
+
+        [WebCrypto] Implement SubtleCrypto::DeriveKey method
+        https://bugs.webkit.org/show_bug.cgi?id=169386
+        <rdar://problem/23789585>
+
+        Reviewed by Brent Fulgham.
+
+        This patch does following few things:
+        1. It implements SubtleCrypto::DeriveKey method according to the spec:
+        https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-deriveKey.
+        2. It implements getKeyLength operations for AES-CBC, AES-KW, AES-CFB,
+        AES-GCM, and HMAC, which is needed by the SubtleCrypto::DeriveKey method.
+        3. It enables ECDH DeriveKey operation.
+        4. It replaces unigned long with size_t in all the crypto codes.
+
+        Tests: crypto/subtle/derive-key-malformed-parameters.html
+               crypto/subtle/ecdh-import-key-derive-aes-key.html
+               crypto/subtle/ecdh-import-key-derive-hmac-key-custom-length.html
+               crypto/subtle/unwrap-key-malformed-parameters.html
+               crypto/subtle/wrap-key-malformed-parameters.html
+               crypto/workers/subtle/ecdh-import-key-derive-key.html
+
+        * CMakeLists.txt:
+        * DerivedSources.make:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/JSSubtleCryptoCustom.cpp:
+        (WebCore::normalizeCryptoAlgorithmParameters):
+        (WebCore::jsSubtleCryptoFunctionEncryptPromise):
+        (WebCore::jsSubtleCryptoFunctionDecryptPromise):
+        (WebCore::jsSubtleCryptoFunctionSignPromise):
+        (WebCore::jsSubtleCryptoFunctionVerifyPromise):
+        (WebCore::jsSubtleCryptoFunctionDigestPromise):
+        (WebCore::jsSubtleCryptoFunctionDeriveKeyPromise):
+        (WebCore::jsSubtleCryptoFunctionDeriveBitsPromise):
+        Remove unnecessary return statement from callbacks.
+        * crypto/CryptoAlgorithm.cpp:
+        (WebCore::CryptoAlgorithm::deriveBits):
+        (WebCore::CryptoAlgorithm::getKeyLength):
+        * crypto/CryptoAlgorithm.h:
+        * crypto/CryptoAlgorithmParameters.h:
+        * crypto/algorithms/CryptoAlgorithmAES_CBC.cpp:
+        (WebCore::CryptoAlgorithmAES_CBC::generateKey):
+        (WebCore::CryptoAlgorithmAES_CBC::getKeyLength):
+        * crypto/algorithms/CryptoAlgorithmAES_CBC.h:
+        * crypto/algorithms/CryptoAlgorithmAES_CFB.cpp:
+        (WebCore::CryptoAlgorithmAES_CFB::generateKey):
+        (WebCore::CryptoAlgorithmAES_CFB::getKeyLength):
+        * crypto/algorithms/CryptoAlgorithmAES_CFB.h:
+        * crypto/algorithms/CryptoAlgorithmAES_GCM.cpp:
+        (WebCore::CryptoAlgorithmAES_GCM::generateKey):
+        (WebCore::CryptoAlgorithmAES_GCM::getKeyLength):
+        * crypto/algorithms/CryptoAlgorithmAES_GCM.h:
+        * crypto/algorithms/CryptoAlgorithmAES_KW.cpp:
+        (WebCore::CryptoAlgorithmAES_KW::generateKey):
+        (WebCore::CryptoAlgorithmAES_KW::getKeyLength):
+        * crypto/algorithms/CryptoAlgorithmAES_KW.h:
+        * crypto/algorithms/CryptoAlgorithmECDH.cpp:
+        (WebCore::CryptoAlgorithmECDH::deriveBits):
+        * crypto/algorithms/CryptoAlgorithmECDH.h:
+        * crypto/algorithms/CryptoAlgorithmHMAC.cpp:
+        (WebCore::CryptoAlgorithmHMAC::getKeyLength):
+        * crypto/algorithms/CryptoAlgorithmHMAC.h:
+        * crypto/keys/CryptoKeyAES.cpp:
+        (WebCore::CryptoKeyAES::getKeyLength):
+        * crypto/keys/CryptoKeyAES.h:
+        * crypto/keys/CryptoKeyHMAC.cpp:
+        (WebCore::getKeyLengthFromHash):
+        (WebCore::CryptoKeyHMAC::generate):
+        (WebCore::CryptoKeyHMAC::getKeyLength):
+        * crypto/keys/CryptoKeyHMAC.h:
+        * crypto/mac/CryptoAlgorithmECDHMac.cpp:
+        (WebCore::CryptoAlgorithmECDH::platformDeriveBits):
+        * crypto/parameters/AesKeyParams.idl: Renamed from Source/WebCore/crypto/parameters/AesKeyGenParams.idl.
+        * crypto/parameters/CryptoAlgorithmAesKeyParams.h: Renamed from Source/WebCore/crypto/parameters/CryptoAlgorithmAesKeyGenParams.h.
+        Rename AesKeyGenParams to AesKeyParams to represent a unified dictionary for AesKeyGenParams and AesDerivedKeyParams.
+        * crypto/parameters/CryptoAlgorithmHmacKeyParams.h:
+        * crypto/parameters/CryptoAlgorithmRsaKeyGenParams.h:
+
 2017-03-08  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         Add plumbing for WebCore to notify WebKit2 when an edit drag has concluded
index 665e0c3..a4d4586 100644 (file)
@@ -274,7 +274,7 @@ JS_BINDING_IDLS = \
     $(WebCore)/crypto/WebKitSubtleCrypto.idl \
     $(WebCore)/crypto/parameters/AesCbcCfbParams.idl \
     $(WebCore)/crypto/parameters/AesGcmParams.idl \
-    $(WebCore)/crypto/parameters/AesKeyGenParams.idl \
+    $(WebCore)/crypto/parameters/AesKeyParams.idl \
     $(WebCore)/crypto/parameters/EcKeyParams.idl \
     $(WebCore)/crypto/parameters/EcdhKeyDeriveParams.idl \
     $(WebCore)/crypto/parameters/HmacKeyParams.idl \
index c25992a..01c711d 100644 (file)
                576814351E6FE3E800E77754 /* CryptoAlgorithmECDHMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 576814341E6FE3E800E77754 /* CryptoAlgorithmECDHMac.cpp */; };
                576814401E709FA100E77754 /* JSEcdhKeyDeriveParams.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5768143D1E709C3600E77754 /* JSEcdhKeyDeriveParams.cpp */; };
                576814411E709FA400E77754 /* JSEcdhKeyDeriveParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 5768143E1E709C3600E77754 /* JSEcdhKeyDeriveParams.h */; };
+               576814441E70CB1B00E77754 /* JSAesKeyParams.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 576814421E70CB1000E77754 /* JSAesKeyParams.cpp */; };
+               576814451E70CB1F00E77754 /* JSAesKeyParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 576814431E70CB1000E77754 /* JSAesKeyParams.h */; };
                5768E4341DB7524500D0A4F7 /* JSRsaHashedKeyGenParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 5768E4331DB7524500D0A4F7 /* JSRsaHashedKeyGenParams.h */; };
                5768E4361DB7527400D0A4F7 /* JSRsaHashedKeyGenParams.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5768E4351DB7527300D0A4F7 /* JSRsaHashedKeyGenParams.cpp */; };
-               577483121DADC55D00716EF9 /* CryptoAlgorithmAesKeyGenParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 577483111DADC55D00716EF9 /* CryptoAlgorithmAesKeyGenParams.h */; };
-               577483141DAEC2EB00716EF9 /* JSAesKeyGenParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 577483131DAEC2EA00716EF9 /* JSAesKeyGenParams.h */; };
-               577483161DAEC32300716EF9 /* JSAesKeyGenParams.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 577483151DAEC32200716EF9 /* JSAesKeyGenParams.cpp */; };
+               577483121DADC55D00716EF9 /* CryptoAlgorithmAesKeyParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 577483111DADC55D00716EF9 /* CryptoAlgorithmAesKeyParams.h */; };
                577483191DB4491F00716EF9 /* CryptoAlgorithmHmacKeyParams.h in Headers */ = {isa = PBXBuildFile; fileRef = 577483181DB4491F00716EF9 /* CryptoAlgorithmHmacKeyParams.h */; };
                5778BD821DA4806C009E3009 /* SubtleCrypto.h in Headers */ = {isa = PBXBuildFile; fileRef = 5778BD811DA4802C009E3009 /* SubtleCrypto.h */; };
                5778BD841DA4817B009E3009 /* SubtleCrypto.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5778BD831DA4817B009E3009 /* SubtleCrypto.cpp */; };
                576814341E6FE3E800E77754 /* CryptoAlgorithmECDHMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CryptoAlgorithmECDHMac.cpp; sourceTree = "<group>"; };
                5768143D1E709C3600E77754 /* JSEcdhKeyDeriveParams.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSEcdhKeyDeriveParams.cpp; sourceTree = "<group>"; };
                5768143E1E709C3600E77754 /* JSEcdhKeyDeriveParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSEcdhKeyDeriveParams.h; sourceTree = "<group>"; };
+               576814421E70CB1000E77754 /* JSAesKeyParams.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAesKeyParams.cpp; sourceTree = "<group>"; };
+               576814431E70CB1000E77754 /* JSAesKeyParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAesKeyParams.h; sourceTree = "<group>"; };
                5768E4331DB7524500D0A4F7 /* JSRsaHashedKeyGenParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSRsaHashedKeyGenParams.h; sourceTree = "<group>"; };
                5768E4351DB7527300D0A4F7 /* JSRsaHashedKeyGenParams.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSRsaHashedKeyGenParams.cpp; sourceTree = "<group>"; };
-               577483101DADC49900716EF9 /* AesKeyGenParams.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = AesKeyGenParams.idl; sourceTree = "<group>"; };
-               577483111DADC55D00716EF9 /* CryptoAlgorithmAesKeyGenParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoAlgorithmAesKeyGenParams.h; sourceTree = "<group>"; };
-               577483131DAEC2EA00716EF9 /* JSAesKeyGenParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAesKeyGenParams.h; sourceTree = "<group>"; };
-               577483151DAEC32200716EF9 /* JSAesKeyGenParams.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAesKeyGenParams.cpp; sourceTree = "<group>"; };
+               577483101DADC49900716EF9 /* AesKeyParams.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = AesKeyParams.idl; sourceTree = "<group>"; };
+               577483111DADC55D00716EF9 /* CryptoAlgorithmAesKeyParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoAlgorithmAesKeyParams.h; sourceTree = "<group>"; };
                577483171DB1FE8900716EF9 /* HmacKeyParams.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = HmacKeyParams.idl; sourceTree = "<group>"; };
                577483181DB4491F00716EF9 /* CryptoAlgorithmHmacKeyParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoAlgorithmHmacKeyParams.h; sourceTree = "<group>"; };
                5778BD801DA4733E009E3009 /* SubtleCrypto.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SubtleCrypto.idl; sourceTree = "<group>"; };
                5DB1BC6810715A6400EFAA49 /* TransformSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TransformSource.h; sourceTree = "<group>"; };
                5DB1BC6910715A6400EFAA49 /* TransformSourceLibxslt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TransformSourceLibxslt.cpp; sourceTree = "<group>"; };
                5DFEBAB618592B6D00C75BEB /* WebKitAvailability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitAvailability.h; sourceTree = "<group>"; };
-               5E16A2E21BFA64FB0029A21E /* MediaEndpointPeerConnection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = MediaEndpointPeerConnection.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
-               5E16A2E31BFA64FB0029A21E /* MediaEndpointPeerConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MediaEndpointPeerConnection.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
+               5E16A2E21BFA64FB0029A21E /* MediaEndpointPeerConnection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MediaEndpointPeerConnection.cpp; sourceTree = "<group>"; };
+               5E16A2E31BFA64FB0029A21E /* MediaEndpointPeerConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaEndpointPeerConnection.h; sourceTree = "<group>"; };
                5E2C434D1BCEE2E50001E2BC /* PeerConnectionBackend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeerConnectionBackend.h; sourceTree = "<group>"; };
                5E2C43541BCEE30D0001E2BC /* RTCPeerConnection.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = RTCPeerConnection.js; sourceTree = "<group>"; };
                5E2C43551BCEE30D0001E2BC /* RTCPeerConnectionInternals.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = RTCPeerConnectionInternals.js; sourceTree = "<group>"; };
                        children = (
                                572093D11DDCEA4B00310AB0 /* AesCbcCfbParams.idl */,
                                57B5F8071E5D19F200F34F90 /* AesGcmParams.idl */,
-                               577483101DADC49900716EF9 /* AesKeyGenParams.idl */,
+                               577483101DADC49900716EF9 /* AesKeyParams.idl */,
                                572093D21DDCEB9A00310AB0 /* CryptoAlgorithmAesCbcCfbParams.h */,
                                E125F8391824104800D84CD9 /* CryptoAlgorithmAesCbcParamsDeprecated.h */,
                                57B5F8081E5D1A9800F34F90 /* CryptoAlgorithmAesGcmParams.h */,
-                               577483111DADC55D00716EF9 /* CryptoAlgorithmAesKeyGenParams.h */,
+                               577483111DADC55D00716EF9 /* CryptoAlgorithmAesKeyParams.h */,
                                E19AC3F61824E5D100349426 /* CryptoAlgorithmAesKeyGenParamsDeprecated.h */,
                                5750A97D1E6A13EF00705C4A /* CryptoAlgorithmEcKeyParams.h */,
                                576814291E6F99C100E77754 /* CryptoAlgorithmEcdhKeyDeriveParams.h */,
                                570440591E53936200356601 /* JSAesCbcCfbParams.h */,
                                57B5F80A1E5D22DA00F34F90 /* JSAesGcmParams.cpp */,
                                57B5F80B1E5D22DA00F34F90 /* JSAesGcmParams.h */,
-                               577483151DAEC32200716EF9 /* JSAesKeyGenParams.cpp */,
-                               577483131DAEC2EA00716EF9 /* JSAesKeyGenParams.h */,
+                               576814421E70CB1000E77754 /* JSAesKeyParams.cpp */,
+                               576814431E70CB1000E77754 /* JSAesKeyParams.h */,
                                5739E1301DAC7FD100E14383 /* JSCryptoAlgorithmParameters.cpp */,
                                5739E12E1DAC7F7800E14383 /* JSCryptoAlgorithmParameters.h */,
                                E157A8DE1817331C009F821D /* JSCryptoKey.cpp */,
                                E1FE137B184D21BB00892F13 /* CryptoAlgorithmAES_KW.h in Headers */,
                                572093D31DDCEB9A00310AB0 /* CryptoAlgorithmAesCbcCfbParams.h in Headers */,
                                E125F83A1824104800D84CD9 /* CryptoAlgorithmAesCbcParamsDeprecated.h in Headers */,
-                               577483121DADC55D00716EF9 /* CryptoAlgorithmAesKeyGenParams.h in Headers */,
+                               577483121DADC55D00716EF9 /* CryptoAlgorithmAesKeyParams.h in Headers */,
                                E19AC3F71824E5D100349426 /* CryptoAlgorithmAesKeyGenParamsDeprecated.h in Headers */,
                                E125F8321822F11B00D84CD9 /* CryptoAlgorithmHMAC.h in Headers */,
                                577483191DB4491F00716EF9 /* CryptoAlgorithmHmacKeyParams.h in Headers */,
                                44EFF6431A6FF92700D45EEC /* IOTypesSPI.h in Headers */,
                                07AC47021952102100EE9723 /* ISOVTTCue.h in Headers */,
                                418F88050FF957AF0080F045 /* JSAbstractWorker.h in Headers */,
-                               577483141DAEC2EB00716EF9 /* JSAesKeyGenParams.h in Headers */,
                                FDA15ECA12B03F50003A583A /* JSAnalyserNode.h in Headers */,
                                12A253E31C8FFF6600C22295 /* JSAnimatable.h in Headers */,
                                120DE3FD1C87E18400B6D4DD /* JSAnimationEffect.h in Headers */,
                                7C6523161E00DBB500677F22 /* JSApplePayPaymentContact.h in Headers */,
                                7C6523181E00DBB500677F22 /* JSApplePayPaymentMethod.h in Headers */,
                                1AE96A8D1D1A0DDD00B86768 /* JSApplePayPaymentMethodSelectedEvent.h in Headers */,
+                               576814451E70CB1F00E77754 /* JSAesKeyParams.h in Headers */,
                                7C65231A1E00DBB500677F22 /* JSApplePayPaymentPass.h in Headers */,
                                7C6579F21E00856600E3A27A /* JSApplePayPaymentRequest.h in Headers */,
                                1AE96A8F1D1A0DDD00B86768 /* JSApplePaySession.h in Headers */,
                                AD9FF6E11908391D003B61E0 /* IOSurfacePoolCocoa.mm in Sources */,
                                07AC47011952102100EE9723 /* ISOVTTCue.cpp in Sources */,
                                418F88040FF957AE0080F045 /* JSAbstractWorker.cpp in Sources */,
-                               577483161DAEC32300716EF9 /* JSAesKeyGenParams.cpp in Sources */,
                                FDA15EC912B03F50003A583A /* JSAnalyserNode.cpp in Sources */,
                                31A795C61888BADC00382F90 /* JSANGLEInstancedArrays.cpp in Sources */,
                                12A253E21C8FFF6600C22295 /* JSAnimatable.cpp in Sources */,
                                A80E7E980A1A83E3007FB8C5 /* JSHTMLInputElement.cpp in Sources */,
                                A6148A7812E41E3B0044A784 /* JSHTMLKeygenElement.cpp in Sources */,
                                1AE2AB210A1CE63B00B42B25 /* JSHTMLLabelElement.cpp in Sources */,
+                               576814441E70CB1B00E77754 /* JSAesKeyParams.cpp in Sources */,
                                1AE2AB230A1CE63B00B42B25 /* JSHTMLLegendElement.cpp in Sources */,
                                1AE2AB250A1CE63B00B42B25 /* JSHTMLLIElement.cpp in Sources */,
                                A80E7B100A19D606007FB8C5 /* JSHTMLLinkElement.cpp in Sources */,
index 8ac9728..9debb2e 100644 (file)
@@ -32,7 +32,7 @@
 #include "CryptoAlgorithmRegistry.h"
 #include "JSAesCbcCfbParams.h"
 #include "JSAesGcmParams.h"
-#include "JSAesKeyGenParams.h"
+#include "JSAesKeyParams.h"
 #include "JSCryptoAlgorithmParameters.h"
 #include "JSCryptoKey.h"
 #include "JSCryptoKeyPair.h"
@@ -61,12 +61,12 @@ enum class Operations {
     Sign,
     Verify,
     Digest,
-    DeriveKey,
-    DeriveBits,
     GenerateKey,
+    DeriveBits,
     ImportKey,
     WrapKey,
-    UnwrapKey
+    UnwrapKey,
+    GetKeyLength
 };
 
 static std::unique_ptr<CryptoAlgorithmParameters> normalizeCryptoAlgorithmParameters(ExecState&, JSValue, Operations);
@@ -160,9 +160,6 @@ static std::unique_ptr<CryptoAlgorithmParameters> normalizeCryptoAlgorithmParame
                 return nullptr;
             }
             break;
-        case Operations::DeriveKey:
-            throwNotSupportedError(state, scope);
-            return nullptr;
         case Operations::DeriveBits:
             switch (*identifier) {
             case CryptoAlgorithmIdentifier::ECDH: {
@@ -207,9 +204,9 @@ static std::unique_ptr<CryptoAlgorithmParameters> normalizeCryptoAlgorithmParame
             case CryptoAlgorithmIdentifier::AES_GCM:
             case CryptoAlgorithmIdentifier::AES_CFB:
             case CryptoAlgorithmIdentifier::AES_KW: {
-                auto params = convertDictionary<CryptoAlgorithmAesKeyGenParams>(state, value);
+                auto params = convertDictionary<CryptoAlgorithmAesKeyParams>(state, value);
                 RETURN_IF_EXCEPTION(scope, nullptr);
-                result = std::make_unique<CryptoAlgorithmAesKeyGenParams>(params);
+                result = std::make_unique<CryptoAlgorithmAesKeyParams>(params);
                 break;
             }
             case CryptoAlgorithmIdentifier::HMAC: {
@@ -286,6 +283,32 @@ static std::unique_ptr<CryptoAlgorithmParameters> normalizeCryptoAlgorithmParame
                 return nullptr;
             }
             break;
+        case Operations::GetKeyLength:
+            switch (*identifier) {
+            case CryptoAlgorithmIdentifier::AES_CTR:
+            case CryptoAlgorithmIdentifier::AES_CBC:
+            case CryptoAlgorithmIdentifier::AES_CMAC:
+            case CryptoAlgorithmIdentifier::AES_GCM:
+            case CryptoAlgorithmIdentifier::AES_CFB:
+            case CryptoAlgorithmIdentifier::AES_KW: {
+                auto params = convertDictionary<CryptoAlgorithmAesKeyParams>(state, value);
+                RETURN_IF_EXCEPTION(scope, nullptr);
+                result = std::make_unique<CryptoAlgorithmAesKeyParams>(params);
+                break;
+            }
+            case CryptoAlgorithmIdentifier::HMAC: {
+                auto params = convertDictionary<CryptoAlgorithmHmacKeyParams>(state, value);
+                RETURN_IF_EXCEPTION(scope, nullptr);
+                params.hashIdentifier = toHashIdentifier(state, params.hash);
+                RETURN_IF_EXCEPTION(scope, nullptr);
+                result = std::make_unique<CryptoAlgorithmHmacKeyParams>(params);
+                break;
+            }
+            default:
+                throwNotSupportedError(state, scope);
+                return nullptr;
+            }
+            break;
         default:
             ASSERT_NOT_REACHED();
             return nullptr;
@@ -487,7 +510,6 @@ static void jsSubtleCryptoFunctionEncryptPromise(ExecState& state, Ref<DeferredP
 
     auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& cipherText) mutable {
         fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), cipherText.data(), cipherText.size());
-        return;
     };
     auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
         rejectWithException(WTFMove(capturedPromise), ec);
@@ -535,7 +557,6 @@ static void jsSubtleCryptoFunctionDecryptPromise(ExecState& state, Ref<DeferredP
 
     auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& plainText) mutable {
         fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), plainText.data(), plainText.size());
-        return;
     };
     auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
         rejectWithException(WTFMove(capturedPromise), ec);
@@ -583,7 +604,6 @@ static void jsSubtleCryptoFunctionSignPromise(ExecState& state, Ref<DeferredProm
 
     auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& signature) mutable {
         fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), signature.data(), signature.size());
-        return;
     };
     auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
         rejectWithException(WTFMove(capturedPromise), ec);
@@ -634,7 +654,6 @@ static void jsSubtleCryptoFunctionVerifyPromise(ExecState& state, Ref<DeferredPr
 
     auto callback = [capturedPromise = promise.copyRef()](bool result) mutable {
         capturedPromise->resolve<IDLBoolean>(result);
-        return;
     };
     auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
         rejectWithException(WTFMove(capturedPromise), ec);
@@ -669,7 +688,6 @@ static void jsSubtleCryptoFunctionDigestPromise(ExecState& state, Ref<DeferredPr
 
     auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& digest) mutable {
         fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), digest.data(), digest.size());
-        return;
     };
     auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
         rejectWithException(WTFMove(capturedPromise), ec);
@@ -743,11 +761,81 @@ static void jsSubtleCryptoFunctionDeriveKeyPromise(ExecState& state, Ref<Deferre
         return;
     }
 
-    auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::DeriveKey);
+    auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::DeriveBits);
+    RETURN_IF_EXCEPTION(scope, void());
+
+    auto baseKey = toCryptoKey(state, state.uncheckedArgument(1));
+    RETURN_IF_EXCEPTION(scope, void());
+
+    auto importParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(2), Operations::ImportKey);
     RETURN_IF_EXCEPTION(scope, void());
 
-    // We should always return a NOT_SUPPORTED_ERR since we currently don't support any algorithms that has deriveKey operation.
-    ASSERT_NOT_REACHED();
+    auto getLengthParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(2), Operations::GetKeyLength);
+    RETURN_IF_EXCEPTION(scope, void());
+
+    auto extractable = state.uncheckedArgument(3).toBoolean(&state);
+    RETURN_IF_EXCEPTION(scope, void());
+
+    auto keyUsages = cryptoKeyUsageBitmapFromJSValue(state, state.uncheckedArgument(4));
+    RETURN_IF_EXCEPTION(scope, void());
+
+    if (params->identifier != baseKey->algorithmIdentifier()) {
+        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier"));
+        return;
+    }
+
+    if (!baseKey->allows(CryptoKeyUsageDeriveKey)) {
+        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't support CryptoKey derivation"));
+        return;
+    }
+
+    auto getLengthAlgorithm = CryptoAlgorithmRegistry::singleton().create(getLengthParams->identifier);
+    if (UNLIKELY(!getLengthAlgorithm)) {
+        throwNotSupportedError(state, scope);
+        return;
+    }
+    auto result = getLengthAlgorithm->getKeyLength(*getLengthParams);
+    if (result.hasException()) {
+        promise->reject(result.releaseException().code(), ASCIILiteral("Cannot get key length from derivedKeyType"));
+        return;
+    }
+    size_t length = result.releaseReturnValue();
+
+    auto importAlgorithm = CryptoAlgorithmRegistry::singleton().create(importParams->identifier);
+    if (UNLIKELY(!importAlgorithm)) {
+        throwNotSupportedError(state, scope);
+        return;
+    }
+
+    auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier);
+    if (UNLIKELY(!algorithm)) {
+        throwNotSupportedError(state, scope);
+        return;
+    }
+
+    auto callback = [promise = promise.copyRef(), importAlgorithm, importParams = WTFMove(importParams), extractable, keyUsages](const Vector<uint8_t>& derivedKey) mutable {
+        // FIXME: https://bugs.webkit.org/show_bug.cgi?id=169395
+        KeyData data = derivedKey;
+        auto callback = [capturedPromise = promise.copyRef()](CryptoKey& key) mutable {
+            if ((key.type() == CryptoKeyType::Private || key.type() == CryptoKeyType::Secret) && !key.usagesBitmap()) {
+                rejectWithException(WTFMove(capturedPromise), SYNTAX_ERR);
+                return;
+            }
+            capturedPromise->resolve<IDLInterface<CryptoKey>>(key);
+        };
+        auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
+            rejectWithException(WTFMove(capturedPromise), ec);
+        };
+
+        importAlgorithm->importKey(SubtleCrypto::KeyFormat::Raw, WTFMove(data), WTFMove(importParams), extractable, keyUsages, WTFMove(callback), WTFMove(exceptionCallback));
+    };
+    auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
+        rejectWithException(WTFMove(capturedPromise), ec);
+    };
+
+    auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(vm, state.thisValue());
+    ASSERT(subtle);
+    algorithm->deriveBits(WTFMove(params), baseKey.releaseNonNull(), length, WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue());
 }
 
 static void jsSubtleCryptoFunctionDeriveBitsPromise(ExecState& state, Ref<DeferredPromise>&& promise)
@@ -787,7 +875,6 @@ static void jsSubtleCryptoFunctionDeriveBitsPromise(ExecState& state, Ref<Deferr
 
     auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& derivedKey) mutable {
         fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), derivedKey.data(), derivedKey.size());
-        return;
     };
     auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
         rejectWithException(WTFMove(capturedPromise), ec);
index eff5ec7..34885cf 100644 (file)
@@ -62,7 +62,7 @@ void CryptoAlgorithm::generateKey(const CryptoAlgorithmParameters&, bool, Crypto
     exceptionCallback(NOT_SUPPORTED_ERR);
 }
 
-void CryptoAlgorithm::deriveBits(std::unique_ptr<CryptoAlgorithmParameters>&&, Ref<CryptoKey>&&, unsigned long, VectorCallback&&, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&, WorkQueue&)
+void CryptoAlgorithm::deriveBits(std::unique_ptr<CryptoAlgorithmParameters>&&, Ref<CryptoKey>&&, size_t, VectorCallback&&, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&, WorkQueue&)
 {
     exceptionCallback(NOT_SUPPORTED_ERR);
 }
@@ -87,6 +87,11 @@ void CryptoAlgorithm::unwrapKey(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallb
     exceptionCallback(NOT_SUPPORTED_ERR);
 }
 
+ExceptionOr<size_t> CryptoAlgorithm::getKeyLength(const CryptoAlgorithmParameters&)
+{
+    return Exception { NOT_SUPPORTED_ERR };
+}
+
 ExceptionOr<void> CryptoAlgorithm::encrypt(const CryptoAlgorithmParametersDeprecated&, const CryptoKey&, const CryptoOperationData&, VectorCallback&&, VoidCallback&&)
 {
     return Exception { NOT_SUPPORTED_ERR };
@@ -122,7 +127,7 @@ ExceptionOr<void> CryptoAlgorithm::deriveKey(const CryptoAlgorithmParametersDepr
     return Exception { NOT_SUPPORTED_ERR };
 }
 
-ExceptionOr<void> CryptoAlgorithm::deriveBits(const CryptoAlgorithmParametersDeprecated&, const CryptoKey&, unsigned long, VectorCallback&&, VoidCallback&&)
+ExceptionOr<void> CryptoAlgorithm::deriveBits(const CryptoAlgorithmParametersDeprecated&, const CryptoKey&, size_t, VectorCallback&&, VoidCallback&&)
 {
     return Exception { NOT_SUPPORTED_ERR };
 }
index 6467bca..ea0bb59 100644 (file)
@@ -61,6 +61,7 @@ public:
     using BoolCallback = WTF::Function<void(bool)>;
     using KeyCallback = WTF::Function<void(CryptoKey&)>;
     using KeyOrKeyPairCallback = WTF::Function<void(KeyOrKeyPair&&)>;
+    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=169395
     using VectorCallback = WTF::Function<void(const Vector<uint8_t>&)>;
     using VoidCallback = WTF::Function<void()>;
     using ExceptionCallback = WTF::Function<void(ExceptionCode)>;
@@ -72,12 +73,13 @@ public:
     virtual void verify(Ref<CryptoKey>&&, Vector<uint8_t>&& signature, Vector<uint8_t>&&, BoolCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&);
     virtual void digest(Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&);
     virtual void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&);
-    virtual void deriveBits(std::unique_ptr<CryptoAlgorithmParameters>&&, Ref<CryptoKey>&&, unsigned long length, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&);
+    virtual void deriveBits(std::unique_ptr<CryptoAlgorithmParameters>&&, Ref<CryptoKey>&&, size_t length, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&);
     // FIXME: https://bugs.webkit.org/show_bug.cgi?id=169262
     virtual void importKey(SubtleCrypto::KeyFormat, KeyData&&, const std::unique_ptr<CryptoAlgorithmParameters>&&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&);
     virtual void exportKey(SubtleCrypto::KeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&);
     virtual void wrapKey(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&);
     virtual void unwrapKey(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&);
+    virtual ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&);
 
     // The following will be deprecated.
     virtual ExceptionOr<void> encrypt(const CryptoAlgorithmParametersDeprecated&, const CryptoKey&, const CryptoOperationData&, VectorCallback&&, VoidCallback&& failureCallback);
@@ -87,7 +89,7 @@ public:
     virtual ExceptionOr<void> digest(const CryptoAlgorithmParametersDeprecated&, const CryptoOperationData&, VectorCallback&&, VoidCallback&& failureCallback);
     virtual ExceptionOr<void> generateKey(const CryptoAlgorithmParametersDeprecated&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, VoidCallback&& failureCallback, ScriptExecutionContext&);
     virtual ExceptionOr<void> deriveKey(const CryptoAlgorithmParametersDeprecated&, const CryptoKey& baseKey, CryptoAlgorithm* derivedKeyType, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, VoidCallback&& failureCallback);
-    virtual ExceptionOr<void> deriveBits(const CryptoAlgorithmParametersDeprecated&, const CryptoKey& baseKey, unsigned long length, VectorCallback&&, VoidCallback&& failureCallback);
+    virtual ExceptionOr<void> deriveBits(const CryptoAlgorithmParametersDeprecated&, const CryptoKey& baseKey, size_t length, VectorCallback&&, VoidCallback&& failureCallback);
     virtual ExceptionOr<void> importKey(const CryptoAlgorithmParametersDeprecated&, const CryptoKeyData&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, VoidCallback&& failureCallback);
 
     // These are only different from encrypt/decrypt because some algorithms may not expose encrypt/decrypt.
index 01ab965..c42bdcc 100644 (file)
@@ -39,7 +39,7 @@ public:
         None,
         AesCbcCfbParams,
         AesGcmParams,
-        AesKeyGenParams,
+        AesKeyParams,
         EcKeyParams,
         EcdhKeyDeriveParams,
         HmacKeyParams,
index 4fb8c91..c0b49ae 100644 (file)
@@ -30,8 +30,8 @@
 
 #include "CryptoAlgorithmAesCbcCfbParams.h"
 #include "CryptoAlgorithmAesCbcParamsDeprecated.h"
-#include "CryptoAlgorithmAesKeyGenParams.h"
 #include "CryptoAlgorithmAesKeyGenParamsDeprecated.h"
+#include "CryptoAlgorithmAesKeyParams.h"
 #include "CryptoKeyAES.h"
 #include "CryptoKeyDataOctetSequence.h"
 #include "ExceptionCode.h"
@@ -90,7 +90,7 @@ void CryptoAlgorithmAES_CBC::decrypt(std::unique_ptr<CryptoAlgorithmParameters>&
 
 void CryptoAlgorithmAES_CBC::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&)
 {
-    const auto& aesParameters = downcast<CryptoAlgorithmAesKeyGenParams>(parameters);
+    const auto& aesParameters = downcast<CryptoAlgorithmAesKeyParams>(parameters);
 
     if (usagesAreInvalidForCryptoAlgorithmAES_CBC(usages)) {
         exceptionCallback(SYNTAX_ERR);
@@ -186,6 +186,11 @@ void CryptoAlgorithmAES_CBC::exportKey(SubtleCrypto::KeyFormat format, Ref<Crypt
     callback(format, WTFMove(result));
 }
 
+ExceptionOr<size_t> CryptoAlgorithmAES_CBC::getKeyLength(const CryptoAlgorithmParameters& parameters)
+{
+    return CryptoKeyAES::getKeyLength(parameters);
+}
+
 ExceptionOr<void> CryptoAlgorithmAES_CBC::encrypt(const CryptoAlgorithmParametersDeprecated& parameters, const CryptoKey& key, const CryptoOperationData& data, VectorCallback&& callback, VoidCallback&& failureCallback)
 {
     auto& aesCBCParameters = downcast<CryptoAlgorithmAesCbcParamsDeprecated>(parameters);
index e56e48e..2f093af 100644 (file)
@@ -49,6 +49,7 @@ private:
     void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final;
     void importKey(SubtleCrypto::KeyFormat, KeyData&&, const std::unique_ptr<CryptoAlgorithmParameters>&&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final;
     void exportKey(SubtleCrypto::KeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final;
+    ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&) final;
 
     ExceptionOr<void> encrypt(const CryptoAlgorithmParametersDeprecated&, const CryptoKey&, const CryptoOperationData&, VectorCallback&&, VoidCallback&& failureCallback) final;
     ExceptionOr<void> decrypt(const CryptoAlgorithmParametersDeprecated&, const CryptoKey&, const CryptoOperationData&, VectorCallback&&, VoidCallback&& failureCallback) final;
index 6532ec6..79e0086 100644 (file)
@@ -29,7 +29,7 @@
 #if ENABLE(SUBTLE_CRYPTO)
 
 #include "CryptoAlgorithmAesCbcCfbParams.h"
-#include "CryptoAlgorithmAesKeyGenParams.h"
+#include "CryptoAlgorithmAesKeyParams.h"
 #include "CryptoKeyAES.h"
 #include "ExceptionCode.h"
 
@@ -79,7 +79,7 @@ void CryptoAlgorithmAES_CFB::decrypt(std::unique_ptr<CryptoAlgorithmParameters>&
 
 void CryptoAlgorithmAES_CFB::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&)
 {
-    const auto& aesParameters = downcast<CryptoAlgorithmAesKeyGenParams>(parameters);
+    const auto& aesParameters = downcast<CryptoAlgorithmAesKeyParams>(parameters);
 
     if (usagesAreInvalidForCryptoAlgorithmAES_CFB(usages)) {
         exceptionCallback(SYNTAX_ERR);
@@ -175,6 +175,11 @@ void CryptoAlgorithmAES_CFB::exportKey(SubtleCrypto::KeyFormat format, Ref<Crypt
     callback(format, WTFMove(result));
 }
 
+ExceptionOr<size_t> CryptoAlgorithmAES_CFB::getKeyLength(const CryptoAlgorithmParameters& parameters)
+{
+    return CryptoKeyAES::getKeyLength(parameters);
+}
+
 }
 
 #endif // ENABLE(SUBTLE_CRYPTO)
index 1238f4d..80bfdb7 100644 (file)
@@ -48,6 +48,7 @@ private:
     void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final;
     void importKey(SubtleCrypto::KeyFormat, KeyData&&, const std::unique_ptr<CryptoAlgorithmParameters>&&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final;
     void exportKey(SubtleCrypto::KeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final;
+    ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&) final;
 
     void platformEncrypt(std::unique_ptr<CryptoAlgorithmParameters>&&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&);
     void platformDecrypt(std::unique_ptr<CryptoAlgorithmParameters>&&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&);
index 2ce30c9..3120bb0 100644 (file)
@@ -29,7 +29,7 @@
 #if ENABLE(SUBTLE_CRYPTO)
 
 #include "CryptoAlgorithmAesGcmParams.h"
-#include "CryptoAlgorithmAesKeyGenParams.h"
+#include "CryptoAlgorithmAesKeyParams.h"
 #include "CryptoKeyAES.h"
 #include "ExceptionCode.h"
 
@@ -128,7 +128,7 @@ void CryptoAlgorithmAES_GCM::decrypt(std::unique_ptr<CryptoAlgorithmParameters>&
 
 void CryptoAlgorithmAES_GCM::generateKey(const CryptoAlgorithmParameters& parameters, bool extractable, CryptoKeyUsageBitmap usages, KeyOrKeyPairCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext&)
 {
-    const auto& aesParameters = downcast<CryptoAlgorithmAesKeyGenParams>(parameters);
+    const auto& aesParameters = downcast<CryptoAlgorithmAesKeyParams>(parameters);
 
     if (usagesAreInvalidForCryptoAlgorithmAES_GCM(usages)) {
         exceptionCallback(SYNTAX_ERR);
@@ -224,6 +224,11 @@ void CryptoAlgorithmAES_GCM::exportKey(SubtleCrypto::KeyFormat format, Ref<Crypt
     callback(format, WTFMove(result));
 }
 
+ExceptionOr<size_t> CryptoAlgorithmAES_GCM::getKeyLength(const CryptoAlgorithmParameters& parameters)
+{
+    return CryptoKeyAES::getKeyLength(parameters);
+}
+
 }
 
 #endif // ENABLE(SUBTLE_CRYPTO)
index 440eae7..5fae054 100644 (file)
@@ -48,6 +48,7 @@ private:
     void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final;
     void importKey(SubtleCrypto::KeyFormat, KeyData&&, const std::unique_ptr<CryptoAlgorithmParameters>&&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final;
     void exportKey(SubtleCrypto::KeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final;
+    ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&) final;
 
     void platformEncrypt(std::unique_ptr<CryptoAlgorithmParameters>&&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&);
     void platformDecrypt(std::unique_ptr<CryptoAlgorithmParameters>&&, Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&);
index 8b60efd..603c0ba 100644 (file)
@@ -28,8 +28,8 @@
 
 #if ENABLE(SUBTLE_CRYPTO)
 
-#include "CryptoAlgorithmAesKeyGenParams.h"
 #include "CryptoAlgorithmAesKeyGenParamsDeprecated.h"
+#include "CryptoAlgorithmAesKeyParams.h"
 #include "CryptoKeyAES.h"
 #include "CryptoKeyDataOctetSequence.h"
 #include "ExceptionCode.h"
@@ -71,7 +71,7 @@ void CryptoAlgorithmAES_KW::generateKey(const CryptoAlgorithmParameters& paramet
         return;
     }
 
-    auto result = CryptoKeyAES::generate(CryptoAlgorithmIdentifier::AES_KW, downcast<CryptoAlgorithmAesKeyGenParams>(parameters).length, extractable, usages);
+    auto result = CryptoKeyAES::generate(CryptoAlgorithmIdentifier::AES_KW, downcast<CryptoAlgorithmAesKeyParams>(parameters).length, extractable, usages);
     if (!result) {
         exceptionCallback(OperationError);
         return;
@@ -173,6 +173,11 @@ void CryptoAlgorithmAES_KW::unwrapKey(Ref<CryptoKey>&& key, Vector<uint8_t>&& da
     platformUnwrapKey(WTFMove(key), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback));
 }
 
+ExceptionOr<size_t> CryptoAlgorithmAES_KW::getKeyLength(const CryptoAlgorithmParameters& parameters)
+{
+    return CryptoKeyAES::getKeyLength(parameters);
+}
+
 ExceptionOr<void> CryptoAlgorithmAES_KW::encryptForWrapKey(const CryptoAlgorithmParametersDeprecated&, const CryptoKey& key, const CryptoOperationData& data, VectorCallback&& callback, VoidCallback&& failureCallback)
 {
     if (!keyAlgorithmMatches(key))
index 00294e3..0ccdb67 100644 (file)
@@ -48,6 +48,7 @@ private:
     void exportKey(SubtleCrypto::KeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final;
     void wrapKey(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&) final;
     void unwrapKey(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&) final;
+    ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&) final;
 
     ExceptionOr<void> encryptForWrapKey(const CryptoAlgorithmParametersDeprecated&, const CryptoKey&, const CryptoOperationData&, VectorCallback&&, VoidCallback&& failureCallback) final;
     ExceptionOr<void> decryptForUnwrapKey(const CryptoAlgorithmParametersDeprecated&, const CryptoKey&, const CryptoOperationData&, VectorCallback&&, VoidCallback&& failureCallback) final;
index 9de41b8..94b2278 100644 (file)
@@ -66,7 +66,7 @@ void CryptoAlgorithmECDH::generateKey(const CryptoAlgorithmParameters& parameter
     callback(WTFMove(pair));
 }
 
-void CryptoAlgorithmECDH::deriveBits(std::unique_ptr<CryptoAlgorithmParameters>&& parameters, Ref<CryptoKey>&& baseKey, unsigned long length, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue)
+void CryptoAlgorithmECDH::deriveBits(std::unique_ptr<CryptoAlgorithmParameters>&& parameters, Ref<CryptoKey>&& baseKey, size_t length, VectorCallback&& callback, ExceptionCallback&& exceptionCallback, ScriptExecutionContext& context, WorkQueue& workQueue)
 {
     // We only accept length that is a multiple of 8.
     if (length % 8) {
@@ -97,7 +97,7 @@ void CryptoAlgorithmECDH::deriveBits(std::unique_ptr<CryptoAlgorithmParameters>&
         return;
     }
 
-    auto unifiedCallback = [callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback)](std::optional<Vector<uint8_t>>&& derivedKey, unsigned long length) mutable {
+    auto unifiedCallback = [callback = WTFMove(callback), exceptionCallback = WTFMove(exceptionCallback)](std::optional<Vector<uint8_t>>&& derivedKey, size_t length) mutable {
         if (!derivedKey) {
             exceptionCallback(OperationError);
             return;
index a395a3f..1c3587c 100644 (file)
@@ -42,12 +42,12 @@ private:
     CryptoAlgorithmIdentifier identifier() const final;
 
     void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final;
-    void deriveBits(std::unique_ptr<CryptoAlgorithmParameters>&&, Ref<CryptoKey>&&, unsigned long length, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final;
+    void deriveBits(std::unique_ptr<CryptoAlgorithmParameters>&&, Ref<CryptoKey>&&, size_t length, VectorCallback&&, ExceptionCallback&&, ScriptExecutionContext&, WorkQueue&) final;
     void importKey(SubtleCrypto::KeyFormat, KeyData&&, const std::unique_ptr<CryptoAlgorithmParameters>&&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final;
     void exportKey(SubtleCrypto::KeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final;
 
-    using Callback = Function<void(std::optional<Vector<uint8_t>>&&, unsigned long)>;
-    void platformDeriveBits(Ref<CryptoKey>&& baseKey, Ref<CryptoKey>&& publicKey, unsigned long length, Callback&&, ScriptExecutionContext&, WorkQueue&);
+    using Callback = Function<void(std::optional<Vector<uint8_t>>&&, size_t)>;
+    void platformDeriveBits(Ref<CryptoKey>&& baseKey, Ref<CryptoKey>&& publicKey, size_t length, Callback&&, ScriptExecutionContext&, WorkQueue&);
 };
 
 } // namespace WebCore
index be064a3..56e5a9c 100644 (file)
@@ -197,6 +197,11 @@ void CryptoAlgorithmHMAC::exportKey(SubtleCrypto::KeyFormat format, Ref<CryptoKe
     callback(format, WTFMove(result));
 }
 
+ExceptionOr<size_t> CryptoAlgorithmHMAC::getKeyLength(const CryptoAlgorithmParameters& parameters)
+{
+    return CryptoKeyHMAC::getKeyLength(parameters);
+}
+
 ExceptionOr<void> CryptoAlgorithmHMAC::sign(const CryptoAlgorithmParametersDeprecated& parameters, const CryptoKey& key, const CryptoOperationData& data, VectorCallback&& callback, VoidCallback&& failureCallback)
 {
     auto& hmacParameters = downcast<CryptoAlgorithmHmacParamsDeprecated>(parameters);
index 3ad69c9..454b11a 100644 (file)
@@ -49,6 +49,7 @@ private:
     void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&) final;
     void importKey(SubtleCrypto::KeyFormat, KeyData&&, const std::unique_ptr<CryptoAlgorithmParameters>&&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, ExceptionCallback&&) final;
     void exportKey(SubtleCrypto::KeyFormat, Ref<CryptoKey>&&, KeyDataCallback&&, ExceptionCallback&&) final;
+    ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&) final;
 
     // The following will be deprecated.
     ExceptionOr<void> sign(const CryptoAlgorithmParametersDeprecated&, const CryptoKey&, const CryptoOperationData&, VectorCallback&&, VoidCallback&& failureCallback) final;
index 4317564..39fdb80 100644 (file)
 
 #if ENABLE(SUBTLE_CRYPTO)
 
+#include "CryptoAlgorithmAesKeyParams.h"
 #include "CryptoAlgorithmRegistry.h"
 #include "CryptoKeyDataOctetSequence.h"
+#include "ExceptionCode.h"
+#include "ExceptionOr.h"
 #include "JsonWebKey.h"
 #include <wtf/text/Base64.h>
 #include <wtf/text/WTFString.h>
@@ -114,6 +117,14 @@ JsonWebKey CryptoKeyAES::exportJwk() const
     return result;
 }
 
+ExceptionOr<size_t> CryptoKeyAES::getKeyLength(const CryptoAlgorithmParameters& parameters)
+{
+    auto& aesParameters = downcast<CryptoAlgorithmAesKeyParams>(parameters);
+    if (!lengthIsValid(aesParameters.length))
+        return Exception { OperationError };
+    return aesParameters.length;
+}
+
 std::unique_ptr<KeyAlgorithm> CryptoKeyAES::buildAlgorithm() const
 {
     return std::make_unique<AesKeyAlgorithm>(CryptoAlgorithmRegistry::singleton().name(algorithmIdentifier()), m_key.size() * 8);
index 471491d..8160d26 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "CryptoAlgorithmIdentifier.h"
 #include "CryptoKey.h"
+#include "ExceptionOr.h"
 #include <wtf/Function.h>
 #include <wtf/Vector.h>
 
@@ -34,6 +35,8 @@
 
 namespace WebCore {
 
+class CryptoAlgorithmParameters;
+
 struct JsonWebKey;
 
 class AesKeyAlgorithm final : public KeyAlgorithm {
@@ -76,6 +79,8 @@ public:
     const Vector<uint8_t>& key() const { return m_key; }
     JsonWebKey exportJwk() const;
 
+    static ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&);
+
 private:
     CryptoKeyAES(CryptoAlgorithmIdentifier, const Vector<uint8_t>& key, bool extractable, CryptoKeyUsageBitmap);
     CryptoKeyAES(CryptoAlgorithmIdentifier, Vector<uint8_t>&& key, bool extractable, CryptoKeyUsageBitmap);
index 31b00fd..b7f6cc6 100644 (file)
 #include "CryptoAlgorithmHmacKeyParams.h"
 #include "CryptoAlgorithmRegistry.h"
 #include "CryptoKeyDataOctetSequence.h"
+#include "ExceptionCode.h"
+#include "ExceptionOr.h"
 #include "JsonWebKey.h"
 #include <wtf/text/Base64.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
+static size_t getKeyLengthFromHash(CryptoAlgorithmIdentifier hash)
+{
+    switch (hash) {
+    case CryptoAlgorithmIdentifier::SHA_1:
+    case CryptoAlgorithmIdentifier::SHA_224:
+    case CryptoAlgorithmIdentifier::SHA_256:
+        return 512;
+    case CryptoAlgorithmIdentifier::SHA_384:
+    case CryptoAlgorithmIdentifier::SHA_512:
+        return 1024;
+    default:
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+}
+
 CryptoKeyHMAC::CryptoKeyHMAC(const Vector<uint8_t>& key, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsageBitmap usage)
     : CryptoKey(CryptoAlgorithmIdentifier::HMAC, CryptoKeyType::Secret, extractable, usage)
     , m_hash(hash)
@@ -58,19 +76,9 @@ CryptoKeyHMAC::~CryptoKeyHMAC()
 RefPtr<CryptoKeyHMAC> CryptoKeyHMAC::generate(size_t lengthBits, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsageBitmap usages)
 {
     if (!lengthBits) {
-        switch (hash) {
-        case CryptoAlgorithmIdentifier::SHA_1:
-        case CryptoAlgorithmIdentifier::SHA_224:
-        case CryptoAlgorithmIdentifier::SHA_256:
-            lengthBits = 512;
-            break;
-        case CryptoAlgorithmIdentifier::SHA_384:
-        case CryptoAlgorithmIdentifier::SHA_512:
-            lengthBits = 1024;
-            break;
-        default:
+        lengthBits = getKeyLengthFromHash(hash);
+        if (!lengthBits)
             return nullptr;
-        }
     }
     // CommonHMAC only supports key length that is a multiple of 8. Therefore, here we are a little bit different
     // from the spec as of 11 December 2014: https://www.w3.org/TR/WebCryptoAPI/#hmac-operations
@@ -124,6 +132,17 @@ JsonWebKey CryptoKeyHMAC::exportJwk() const
     return result;
 }
 
+ExceptionOr<size_t> CryptoKeyHMAC::getKeyLength(const CryptoAlgorithmParameters& parameters)
+{
+    auto& aesParameters = downcast<CryptoAlgorithmHmacKeyParams>(parameters);
+
+    size_t result = aesParameters.length ? *(aesParameters.length) : getKeyLengthFromHash(aesParameters.hashIdentifier);
+    if (result)
+        return result;
+
+    return Exception { TypeError };
+}
+
 std::unique_ptr<KeyAlgorithm> CryptoKeyHMAC::buildAlgorithm() const
 {
     return std::make_unique<HmacKeyAlgorithm>(CryptoAlgorithmRegistry::singleton().name(algorithmIdentifier()),
index 25c2452..3f29168 100644 (file)
 #if ENABLE(SUBTLE_CRYPTO)
 
 #include "CryptoKey.h"
+#include "ExceptionOr.h"
 #include <wtf/Function.h>
 #include <wtf/Vector.h>
 
 namespace WebCore {
 
+class CryptoAlgorithmParameters;
+
 struct JsonWebKey;
 
 class HmacKeyAlgorithm final : public KeyAlgorithm {
@@ -74,6 +77,8 @@ public:
 
     CryptoAlgorithmIdentifier hashAlgorithmIdentifier() const { return m_hash; }
 
+    static ExceptionOr<size_t> getKeyLength(const CryptoAlgorithmParameters&);
+
 private:
     CryptoKeyHMAC(const Vector<uint8_t>& key, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsageBitmap);
     CryptoKeyHMAC(Vector<uint8_t>&& key, CryptoAlgorithmIdentifier hash, bool extractable, CryptoKeyUsageBitmap);
index b38c50e..f84c72a 100644 (file)
@@ -34,7 +34,7 @@
 
 namespace WebCore {
 
-void CryptoAlgorithmECDH::platformDeriveBits(Ref<CryptoKey>&& baseKey, Ref<CryptoKey>&& publicKey, unsigned long length, Callback&& callback, ScriptExecutionContext& context, WorkQueue& workQueue)
+void CryptoAlgorithmECDH::platformDeriveBits(Ref<CryptoKey>&& baseKey, Ref<CryptoKey>&& publicKey, size_t length, Callback&& callback, ScriptExecutionContext& context, WorkQueue& workQueue)
 {
     context.ref();
     workQueue.dispatch([baseKey = WTFMove(baseKey), publicKey = WTFMove(publicKey), length, callback = WTFMove(callback), &context]() mutable {
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+// This is a unified dictionary for AesDerivedKeyParams and AesKeyGenParams.
+// https://www.w3.org/TR/WebCryptoAPI/#aes-derivedkey-params, and
+// https://www.w3.org/TR/WebCryptoAPI/#aes-keygen-params
 [
     Conditional=SUBTLE_CRYPTO,
-    ImplementedAs=CryptoAlgorithmAesKeyGenParams
-] dictionary AesKeyGenParams : CryptoAlgorithmParameters {
+    ImplementedAs=CryptoAlgorithmAesKeyParams
+] dictionary AesKeyParams : CryptoAlgorithmParameters {
     // The length, in bits, of the key.
     [EnforceRange] required unsigned short length;
 };
 
 namespace WebCore {
 
-class CryptoAlgorithmAesKeyGenParams final : public CryptoAlgorithmParameters {
+class CryptoAlgorithmAesKeyParams final : public CryptoAlgorithmParameters {
 public:
     unsigned short length;
 
-    Class parametersClass() const final { return Class::AesKeyGenParams; }
+    Class parametersClass() const final { return Class::AesKeyParams; }
 };
 
 } // namespace WebCore
 
-SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(AesKeyGenParams)
+SPECIALIZE_TYPE_TRAITS_CRYPTO_ALGORITHM_PARAMETERS(AesKeyParams)
 
 #endif // ENABLE(SUBTLE_CRYPTO)
index e4bff65..3d19e2d 100644 (file)
@@ -37,7 +37,7 @@ public:
     // FIXME: Consider merging hash and hashIdentifier.
     JSC::JSValue hash;
     CryptoAlgorithmIdentifier hashIdentifier;
-    std::optional<unsigned long> length;
+    std::optional<size_t> length;
 
     Class parametersClass() const final { return Class::HmacKeyParams; }
 };
index 13ec709..1a32dce 100644 (file)
@@ -35,7 +35,7 @@ namespace WebCore {
 
 class CryptoAlgorithmRsaKeyGenParams : public CryptoAlgorithmParameters {
 public:
-    unsigned long modulusLength;
+    size_t modulusLength;
     RefPtr<Uint8Array> publicExponent;
 
     Class parametersClass() const override { return Class::RsaKeyGenParams; }