Update SubtleCrypto::wrapKey to match the latest spec
authorjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 30 Nov 2016 22:26:10 +0000 (22:26 +0000)
committerjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 30 Nov 2016 22:26:10 +0000 (22:26 +0000)
https://bugs.webkit.org/show_bug.cgi?id=164746
<rdar://problem/29258160>

Reviewed by Brent Fulgham.

LayoutTests/imported/w3c:

* WebCryptoAPI/idlharness-expected.txt:

Source/WebCore:

This patch does following few things:
1. It updates the SubtleCrypto::wrapKey method to match the latest spec:
   https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-wrapKey.
   It also refers to the latest Editor's Draft to a certain degree:
   https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-wrapKey.
2. It implements wrapKey operations of the following algorithms: AES-KW.
3. It also replaces JSSubtleCrypto* with auto in all promise functions.

Tests: crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-private.html
       crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-public.html
       crypto/subtle/aes-kw-import-key-wrap-raw-key.html
       crypto/subtle/aes-kw-wrap-key-malformed-parameters.html
       crypto/subtle/rsa-oaep-import-key-wrap-jwk-oct-key.html
       crypto/subtle/wrapKey-malformed-parameters.html
       crypto/workers/subtle/aes-cbc-import-key-wrap-key.html
       crypto/workers/subtle/aes-kw-import-key-wrap-key.html
       crypto/workers/subtle/rsa-oaep-import-key-wrap-key.html

* bindings/js/JSSubtleCryptoCustom.cpp:
(WebCore::normalizeCryptoAlgorithmParameters):
(WebCore::supportExportKeyThrow):
(WebCore::jsSubtleCryptoFunctionEncryptPromise):
(WebCore::jsSubtleCryptoFunctionDecryptPromise):
(WebCore::jsSubtleCryptoFunctionExportKeyPromise):
(WebCore::jsSubtleCryptoFunctionWrapKeyPromise):
(WebCore::JSSubtleCrypto::wrapKey):
* crypto/CryptoAlgorithm.cpp:
(WebCore::CryptoAlgorithm::wrapKey):
* crypto/CryptoAlgorithm.h:
* crypto/SubtleCrypto.idl:
* crypto/algorithms/CryptoAlgorithmAES_KW.cpp:
(WebCore::CryptoAlgorithmAES_KW::wrapKey):
* crypto/algorithms/CryptoAlgorithmAES_KW.h:
* crypto/gnutls/CryptoAlgorithmAES_KWGnuTLS.cpp:
(WebCore::CryptoAlgorithmAES_KW::platformWrapKey):
* crypto/mac/CryptoAlgorithmAES_KWMac.cpp:
(WebCore::wrapKeyAES_KW):
(WebCore::CryptoAlgorithmAES_KW::platformWrapKey):
(WebCore::CryptoAlgorithmAES_KW::platformEncrypt):

LayoutTests:

* crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-private-expected.txt: Added.
* crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-private.html: Added.
* crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-public-expected.txt: Added.
* crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-public.html: Added.
* crypto/subtle/aes-kw-import-key-wrap-raw-key-expected.txt: Added.
* crypto/subtle/aes-kw-import-key-wrap-raw-key.html: Added.
* crypto/subtle/aes-kw-wrap-key-malformed-parameters-expected.txt: Added.
* crypto/subtle/aes-kw-wrap-key-malformed-parameters.html: Added.
* crypto/subtle/rsa-oaep-import-key-wrap-jwk-oct-key-expected.txt: Added.
* crypto/subtle/rsa-oaep-import-key-wrap-jwk-oct-key.html: Added.
* crypto/subtle/wrapKey-malformed-parameters-expected.txt: Added.
* crypto/subtle/wrapKey-malformed-parameters.html: Added.
* crypto/workers/subtle/aes-cbc-import-key-wrap-key-expected.txt: Added.
* crypto/workers/subtle/aes-cbc-import-key-wrap-key.html: Added.
* crypto/workers/subtle/aes-kw-import-key-wrap-key-expected.txt: Added.
* crypto/workers/subtle/aes-kw-import-key-wrap-key.html: Added.
* crypto/workers/subtle/resources/aes-cbc-import-key-wrap-key.js: Added.
* crypto/workers/subtle/resources/aes-kw-import-key-wrap-key.js: Added.
* crypto/workers/subtle/resources/rsa-oaep-import-key-wrap-key.js: Added.
* crypto/workers/subtle/rsa-oaep-import-key-wrap-key-expected.txt: Added.
* crypto/workers/subtle/rsa-oaep-import-key-wrap-key.html: Added.

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

33 files changed:
LayoutTests/ChangeLog
LayoutTests/crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-private-expected.txt [new file with mode: 0644]
LayoutTests/crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-private.html [new file with mode: 0644]
LayoutTests/crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-public-expected.txt [new file with mode: 0644]
LayoutTests/crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-public.html [new file with mode: 0644]
LayoutTests/crypto/subtle/aes-kw-import-key-wrap-raw-key-expected.txt [new file with mode: 0644]
LayoutTests/crypto/subtle/aes-kw-import-key-wrap-raw-key.html [new file with mode: 0644]
LayoutTests/crypto/subtle/aes-kw-wrap-key-malformed-parameters-expected.txt [new file with mode: 0644]
LayoutTests/crypto/subtle/aes-kw-wrap-key-malformed-parameters.html [new file with mode: 0644]
LayoutTests/crypto/subtle/rsa-oaep-import-key-wrap-jwk-oct-key-expected.txt [new file with mode: 0644]
LayoutTests/crypto/subtle/rsa-oaep-import-key-wrap-jwk-oct-key.html [new file with mode: 0644]
LayoutTests/crypto/subtle/wrapKey-malformed-parameters-expected.txt [new file with mode: 0644]
LayoutTests/crypto/subtle/wrapKey-malformed-parameters.html [new file with mode: 0644]
LayoutTests/crypto/workers/subtle/aes-cbc-import-key-wrap-key-expected.txt [new file with mode: 0644]
LayoutTests/crypto/workers/subtle/aes-cbc-import-key-wrap-key.html [new file with mode: 0644]
LayoutTests/crypto/workers/subtle/aes-kw-import-key-wrap-key-expected.txt [new file with mode: 0644]
LayoutTests/crypto/workers/subtle/aes-kw-import-key-wrap-key.html [new file with mode: 0644]
LayoutTests/crypto/workers/subtle/resources/aes-cbc-import-key-wrap-key.js [new file with mode: 0644]
LayoutTests/crypto/workers/subtle/resources/aes-kw-import-key-wrap-key.js [new file with mode: 0644]
LayoutTests/crypto/workers/subtle/resources/rsa-oaep-import-key-wrap-key.js [new file with mode: 0644]
LayoutTests/crypto/workers/subtle/rsa-oaep-import-key-wrap-key-expected.txt [new file with mode: 0644]
LayoutTests/crypto/workers/subtle/rsa-oaep-import-key-wrap-key.html [new file with mode: 0644]
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/WebCryptoAPI/idlharness-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp
Source/WebCore/crypto/CryptoAlgorithm.cpp
Source/WebCore/crypto/CryptoAlgorithm.h
Source/WebCore/crypto/SubtleCrypto.idl
Source/WebCore/crypto/algorithms/CryptoAlgorithmAES_KW.cpp
Source/WebCore/crypto/algorithms/CryptoAlgorithmAES_KW.h
Source/WebCore/crypto/gnutls/CryptoAlgorithmAES_KWGnuTLS.cpp
Source/WebCore/crypto/mac/CryptoAlgorithmAES_KWMac.cpp

index 1f4e6d6..c5d8c81 100644 (file)
@@ -1,3 +1,33 @@
+2016-11-30  Jiewen Tan  <jiewen_tan@apple.com>
+
+        Update SubtleCrypto::wrapKey to match the latest spec
+        https://bugs.webkit.org/show_bug.cgi?id=164746
+        <rdar://problem/29258160>
+
+        Reviewed by Brent Fulgham.
+
+        * crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-private-expected.txt: Added.
+        * crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-private.html: Added.
+        * crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-public-expected.txt: Added.
+        * crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-public.html: Added.
+        * crypto/subtle/aes-kw-import-key-wrap-raw-key-expected.txt: Added.
+        * crypto/subtle/aes-kw-import-key-wrap-raw-key.html: Added.
+        * crypto/subtle/aes-kw-wrap-key-malformed-parameters-expected.txt: Added.
+        * crypto/subtle/aes-kw-wrap-key-malformed-parameters.html: Added.
+        * crypto/subtle/rsa-oaep-import-key-wrap-jwk-oct-key-expected.txt: Added.
+        * crypto/subtle/rsa-oaep-import-key-wrap-jwk-oct-key.html: Added.
+        * crypto/subtle/wrapKey-malformed-parameters-expected.txt: Added.
+        * crypto/subtle/wrapKey-malformed-parameters.html: Added.
+        * crypto/workers/subtle/aes-cbc-import-key-wrap-key-expected.txt: Added.
+        * crypto/workers/subtle/aes-cbc-import-key-wrap-key.html: Added.
+        * crypto/workers/subtle/aes-kw-import-key-wrap-key-expected.txt: Added.
+        * crypto/workers/subtle/aes-kw-import-key-wrap-key.html: Added.
+        * crypto/workers/subtle/resources/aes-cbc-import-key-wrap-key.js: Added.
+        * crypto/workers/subtle/resources/aes-kw-import-key-wrap-key.js: Added.
+        * crypto/workers/subtle/resources/rsa-oaep-import-key-wrap-key.js: Added.
+        * crypto/workers/subtle/rsa-oaep-import-key-wrap-key-expected.txt: Added.
+        * crypto/workers/subtle/rsa-oaep-import-key-wrap-key.html: Added.
+
 2016-11-30  Joseph Pecoraro  <pecoraro@apple.com>
 
         REGRESSION: inspector/sampling-profiler/* LayoutTests are flaky timeouts
diff --git a/LayoutTests/crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-private-expected.txt b/LayoutTests/crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-private-expected.txt
new file mode 100644 (file)
index 0000000..f2521bb
--- /dev/null
@@ -0,0 +1,10 @@
+Test wrapping a JWK RSA private key with AES-CBC using an imported key
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS bytesToHexString(wrappedKey) is expectWrappedKey
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-private.html b/LayoutTests/crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-private.html
new file mode 100644 (file)
index 0000000..3698886
--- /dev/null
@@ -0,0 +1,57 @@
+<!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 wrapping a JWK RSA private key with AES-CBC using an imported key");
+
+jsTestIsAsync = true;
+
+var extractable = true;
+var jwkKey = {
+    kty: "RSA",
+    alg: "RSA-OAEP",
+    use: "enc",
+    key_ops: ["decrypt", "unwrapKey"],
+    ext: true,
+    n: "lxHN0N9VRZ0_pl0xv3-NXx70WnjkODSkQ5LjHXTFy3DOQsvkagFzD9HqYQezCmcewLjdK5PLwSesDoMdfL6tusBHcvyit1kvydYFQ3NLbENNkYsiBG5_nW4IQGL6JKbZ5iGdUop98QHKm6YZR1u4zrAtxM6bVEo05VvhjRS0M8yWoZVi-7Vdsc0LqI0Qdq_NoctX5Fu-AqiBN7Uo1HkYGcP2oC82J_J5cjw98BQiP5kDWThq9RK-X6S-EUALx_m4iG6iOYKTA3SQyf1xBqFaXXoEJjcckbOqkegecz5b-YWUh8iZPvhwnt-RZwpIbLJgKwz19ndkn9KvoEEw7YbEow",
+    e: "AQAB",
+    d: "cj5DkDakjM2bKduGWJREO-_zyEtuA1dD9doqKMd7IRuA0CDS7puEAS20-oXRDwfmyMXEdEUDrGGtCxh6fzDPvs_T-JA3GUK4EgHo3xZcrlXDXlKCeil6Fnr0gISZOIh5dkBrcdVL4quBJe4ZZc5mVuAC7Ld13et0TxMJ4iALGrPuqPVUOGSYIcZ9idx5zKKBWhY3tPggEdKpnHBmPfTRO4yZaf0Nw1QXrgSMZY9ejeuaurAh4Q8o4-6-r8O2LUe7ufMh_ccKkXISEh4KdOnT17EM9BQTn9UNS9GoK2ZZU0U3io5DSu_kpasr4uOVWcGlE2wczOv2nkGwG39F3sFF0Q",
+    p: "x5vnco5j-TD6hTOzyN4DhkZ44m05NycxT6SUE2qTurT3-uze_L7TYutLRIRkovRMhTHZAr2pziRlasEs13PEz9Zvx1I_T68srsonrdbak-SFMecM7EjHc5C-J13gXhw9HIW28_Sx9rQ-JkGwEwE9PEdIUfuvdqpgh3SmXwPJrEs",
+    q: "wb9vllg_2n-kNge0bThg_7xu1UwTzipM8vxSUkkV2IipJKIAekkU3aAB8LoPhUI0-17pSGw3ETOO27t163TI9qIPpzLbhTH9aUi7qLGbKlzPlgnqP43Z0LHxc3xKDgit-Ar29QLaX2uoJBX6VVWvhmh7BIPDHNVM5GZjwWORYgk",
+    dp: "C2c8sa6wx2uk5Dcv7inAycr83PKgciYrCwG78-AC0IfGIu-lTYsZSG1ov2FQ3n5WYMWYQC_Vo5EwugiPJz_V3onBmQF53HOFefbSjXvYwNotQcyRUG5X9qIuOtGCH949H4QED6vK_u0NH-JgzLUlamwoFYbrXzwch6CCYKs2ukE",
+    dq: "hbtRloDLclHwUqr2yvzDV0IFbozYjtF706x-VfXEcnXB6ls34TBYirFLJZIH7H9KeseEVkz7pY_k5555QlCV9kbebxYXl9RtiiJ-BW6yH4d4caPeYIfU9MweUQxVQWKUUkWfOHcDrCFvKZlR9Vzzjt7HKtKX9mr0bCKQcIf9baE",
+    qi: "a-7hUTTnclUPKOfSgH8zEKGJ-AvdFEzxvZ5sq46Qf2MbORxVjN4dJamVvM-FoqcwN-9cuUlyr9bSFTwUBW4vXa8Xj9a8JfViuMCqzR-mL1rGIUQ5ARGhNcSsRlyKTqz5BlWlVKmXIx_p-DeVwPWiJJy4k_FqyBxrnxkzomHfrxk",
+};
+var rawKey = asciiToUint8Array("jnOw99oOZFLIEPMr");
+var aesCbcParams = {
+    name: "aes-cbc",
+    iv: asciiToUint8Array("jnOw99oOZFLIEPMr"),
+}
+var expectWrappedKey = "848aa2f70ee18e2953520132a79cf479b03a8732a3cc73f8c51c68456d3c2557e8be9d5911b2a74267e282a87ffeed88dfbac38a22c26ba621f83915d7539420a4dc0b2329c585b442967367c1ea6c1126f98c4f13b7c8cb7402b86a5844c19420ea333dc33d908be89172f8bac59b403fe202f32c8eed19f431cedfc3383f536f3557163b1311ae42ee5486c6dafee968640d6b6999c687f37fba8d65cc662f1c84f16245665e4af41c98e8b63632cc1d19e2bece2154c7eab1905f3f6ab17b495cefec3508e9b451f2ea1422b97f275dfdc118f46af02040250d0e55d8d8d172b969bbcf7314a257f10b98d2c47c6c72a727acaf4c96340d590ebcebc61f73b7a868b490f3c1e17c59ea479a3b8db5574153de46cfdbb07cfc5e95ebcf7ad3d5fa057ba946d6da872c4bef3af6d7013e222c227650d0022c94d306cb14e203aad378d171c7c24f824c31b81fd18265e0de2f4b415584ebc4adeb5880c4eddbc88b854699f7aa74d6a10ca5df8978f27b5d1372b31ea67a9c4841ae101ea6ad78df0580b70358e6933ac92f7faee5320af329d8349a7b98690708a388737604be0affaa0669410d8d93dc4e4f57e14583253f11e5b27c89b84f1f3038bae6d9b37e3eb64b63ad1880627aef3b19e3e851cfae639ec46dd06fd131b51f530b37260b836d9013d8ad7c8640096070f96984c528ee5e20b69f3cd98a269621cd886ccb16d9c526a87cd5c458541309bb7fa4f3337305d76fc050d39ca8b1fdb0675a11a40ffde9cebb33ddc485e5dc5e7667b08c2a3e0136d063a447aee5a8f650429c5e422a706c4c240a4d11f4a9b5782f2cba2575f0c32cb477a9f0cef97fa993977104181315ff90e46f3b12b8b00f4a7611c42b1bb53d0e6021ab21ee8ae606d9f06dfedb891763007e020977c28b46d5f33bc35c12061d90ebbe02cab58783c0cac0c6f14ed735204f23d0eb6a9fe9edea2aecb1ac213f58b42d5d96374ec70ca288a31016ba02adef43250d717e9fab8982a1a180b1f3944d450c159010fd23f354d88502ec702882ae3edd567c6a6edf3cb2e34edc13f410a25d97298ab9062ddb566576fa8b6599bba205bab55aa5f3f37edaf7733cf249e69c74da975ef249ca673da749d86babebdf55410a389720ac943f1e9d921f5d69c5789636cb904fb9263744236eade9acae889a01c237ab3436101463dfa9d92f936c1b652c80f3abba76023ebe5b9bfdd54735e3a3494de18a456967f58758e546021feef3fa3e6c239981aa06f1f7ddc415d957ff9919bbec5f36af092a81ba6c14fe644d2ee98a2fcdee2ed70b87a53ffa327b25b4569c5886b15f2bd583d6f5bd7e951a915142baa08c6a9c343c200678a005fad22a337d2c5627f8c816db2525a7e121849b9da756eee68a240452849ffdb9651f998257c62e8fdcdc48dadfc3ebb18f7eb5461442008846a629ec8149c052f357bf5889095047b272bce0ff505953e7cd525b24c838ba6e9ed91922a30eeb858de8556f19f761d0287d768876346a5dcac3dbadd7a30072c9338162be5812166d961f4031f962ef668781d39d0fc69fe5f4494e31ec082d4a0140e368b69975beeba120ef9b651ead531b4d44296bd3cfe2ce7f97bb5bb4921061b12c2e1c4c10928c0980ff8d488a2282d0c056a40260167410e39664f75ff1f1249820e174eed978318a05e654b8aa6c60b70001a7a04f0aff17597dd9ab3ccc34f5ba2e352b7244dd3dccb462d7175b95ae3970ec5858e2312aac7c2c79a37b53d089f988720a4c04df6328a384004d0d51eafb9486623099a98e69be5169201c88824acc2bb0e1790889014a1797c168e98d19f0787c2935cfbc3bf24c4adad69a81e0e6adf8c21e3c4789064aa31a025dff5cc6eaba3f3e43f10a9d531f47963372120e2366b84c281ed968d9d11c1d103826c9362741e1267d1a3e8d2188761fa876b7b09617df14130c07209f1f1188ff40971b86607dee14d556a880447901c69d29cb16c027c3aae316ff00132bdfcd0e39c5e201252c9771483ccb275b0c67b3cb4dcd19198c7718634460254dfd6f8df4374b8bedee7dd20ce411b5f987cac2ce17492aa78f919c6d5e555000f47f7b8a9896d448bc4fc13e40a9e5c02258d509a7289f44d7250e89260233bf96702bb3d350451f03d802e0e37d9f01cce4c78869403493eb9890c2c09109d1f427f59cf091cd1c836e25a9bb065041407c2183f643bce2e72db1e7caeac42e2d8379f8b84df2cc7b1d055f42d6f62e0cb5771a14ae8872792350e5f770115a86564f60a785c53325c8c084afe214da3cac1783e2be9099d96ddbe9cc3ea3dd1d3ae50526b4afe24397420a3e4fa697613421";
+
+crypto.subtle.importKey("raw", rawKey, "aes-cbc", extractable, ["wrapKey"]).then(function(result) {
+    wrappingKey = result;
+    return crypto.subtle.importKey("jwk", jwkKey, { name: "rsa-oaep", hash: "sha-1" }, extractable, ["decrypt"]);
+}).then(function(result) {
+    key = result;
+    return crypto.subtle.wrapKey("jwk", key, wrappingKey, aesCbcParams);
+}).then(function(result) {
+    wrappedKey = result;
+
+    shouldBe("bytesToHexString(wrappedKey)", "expectWrappedKey");
+
+    finishJSTest();
+});
+
+</script>
+
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-public-expected.txt b/LayoutTests/crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-public-expected.txt
new file mode 100644 (file)
index 0000000..3096922
--- /dev/null
@@ -0,0 +1,10 @@
+Test wrapping a JWK RSA public key with AES-CBC using an imported key
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS bytesToHexString(wrappedKey) is expectWrappedKey
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-public.html b/LayoutTests/crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-public.html
new file mode 100644 (file)
index 0000000..c429e5b
--- /dev/null
@@ -0,0 +1,51 @@
+<!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 wrapping a JWK RSA public key with AES-CBC using an imported key");
+
+jsTestIsAsync = true;
+
+var extractable = true;
+var jwkKey = {
+    kty: "RSA",
+    alg: "RSA-OAEP",
+    use: "enc",
+    key_ops: ["encrypt"],
+    ext: true,
+    n: "rcCUCv7Oc1HVam1DIhCzqknThWawOp8QLk8Ziy2p10ByjQFCajoFiyuAWl-R1WXZaf4xitLRracT9agpzIzc-MbLSHIGgWQGO21lGiImy5ftZ-D8bHAqRz2y15pzD4c4CEou7XSSLDoRnR0QG5MsDhD6s2gV9mwHkrtkCxtMWdBi-77as8wGmlNRldcOSgZDLK8UnCSgA1OguZ989bFyc8tOOEIb0xUSfPSz3LPSCnyYz68aDjmKVeNH-ig857OScyWbGyEy3Biw64qun3juUlNWsJ3zngkOdteYWytx5Qr4XKNs6R-Myyq72KUp02mJDZiiyiglxML_i3-_CeecCw",
+    e: "AQAB"
+};
+var rawKey = asciiToUint8Array("jnOw99oOZFLIEPMr");
+var aesCbcParams = {
+    name: "aes-cbc",
+    iv: asciiToUint8Array("jnOw99oOZFLIEPMr"),
+}
+var expectWrappedKey = "848aa2f70ee18e2953520132a79cf47946e00c99362340bb690edc9ab5315757462c128278c6232e770e7437c56ed722a8e1703855f7f3e565394e1a6a0305c4ef1b30fa4c7f72d1a239cc6c6ba067898798a36a75132c66b4a2d3fb942886affd3ea3b2756b0ddc886c01e3b93107469b82124468408ef8ab548b85aa8f206c312d74ce4f2c679eb147a275cefda64d5bdc4a2b5b90a4ac9ad3eb5f2cf19f5f87653211f59b4731ba61125582a233951097dea65db05899d587d1dcfccab9ab7410ab3010b89066506dbacbc6b73e4b564792751388fa0f58d55c59c14a08c9dfb0f78100b0f5cc29d62328822636d30a6a153ec5cd4727ad5e47b419c48544565637ac5789863d43b7da78cf4383d09d66e9d458e436dbfbee75e382b2bab49eec2c7491ff93cf099fe92feaf4658e30889fd12d3ae61cd5e8c8e1e56a079b662f90cd10cdbdbb4d12eefb36d825e1a043e82f5a98f8960d655d3f9ed5af31e581fa846cc582f6cee5c25e0b3c32050534ae957ce27860d470ba26da2c7d6fa621b0faa8becad58e9e55bb2a9d984b042f25df21482529870d271cbf5508a0edfc3cb37316c11f16b342bc1f1f98aa";
+
+crypto.subtle.importKey("raw", rawKey, "aes-cbc", extractable, ["wrapKey"]).then(function(result) {
+    wrappingKey = result;
+    return crypto.subtle.importKey("jwk", jwkKey, { name: "rsa-oaep", hash: "sha-1" }, extractable, ["encrypt"]);
+}).then(function(result) {
+    key = result;
+    return crypto.subtle.wrapKey("jwk", key, wrappingKey, aesCbcParams);
+}).then(function(result) {
+    wrappedKey = result;
+
+    shouldBe("bytesToHexString(wrappedKey)", "expectWrappedKey");
+
+    finishJSTest();
+});
+
+</script>
+
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/crypto/subtle/aes-kw-import-key-wrap-raw-key-expected.txt b/LayoutTests/crypto/subtle/aes-kw-import-key-wrap-raw-key-expected.txt
new file mode 100644 (file)
index 0000000..d02a084
--- /dev/null
@@ -0,0 +1,10 @@
+Test wrapping a raw key with AES-KW using an imported key
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS bytesToHexString(wrappedKey) is expectWrappedKey
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/subtle/aes-kw-import-key-wrap-raw-key.html b/LayoutTests/crypto/subtle/aes-kw-import-key-wrap-raw-key.html
new file mode 100644 (file)
index 0000000..e10eb96
--- /dev/null
@@ -0,0 +1,38 @@
+<!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 wrapping a raw key with AES-KW using an imported key");
+
+jsTestIsAsync = true;
+
+var extractable = true;
+var rawKey = asciiToUint8Array("jnOw99oOZFLIEPMr");
+var expectWrappedKey = "d64787ab3e048dbdc30bb62781c9f18e58ad7dbfc64aab16";
+
+crypto.subtle.importKey("raw", rawKey, "aes-kw", extractable, ["wrapKey", "unwrapKey"]).then(function(result) {
+    wrappingKey = result;
+    return crypto.subtle.importKey("raw", rawKey, "aes-cbc", extractable, ["encrypt", "decrypt"]);
+}).then(function(result) {
+    key = result;
+    return crypto.subtle.wrapKey("raw", key, wrappingKey, "AES-KW");
+}).then(function(result) {
+    wrappedKey = result;
+
+    shouldBe("bytesToHexString(wrappedKey)", "expectWrappedKey");
+
+    finishJSTest();
+});
+
+</script>
+
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/crypto/subtle/aes-kw-wrap-key-malformed-parameters-expected.txt b/LayoutTests/crypto/subtle/aes-kw-wrap-key-malformed-parameters-expected.txt
new file mode 100644 (file)
index 0000000..1ad4808
--- /dev/null
@@ -0,0 +1,10 @@
+Test AES-KW WrapKey operation with malformed parameters
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS crypto.subtle.wrapKey("jwk", key, wrappingKey, "AES-KW") rejected promise  with OperationError (DOM Exception 34): The operation failed for an operation-specific reason.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/subtle/aes-kw-wrap-key-malformed-parameters.html b/LayoutTests/crypto/subtle/aes-kw-wrap-key-malformed-parameters.html
new file mode 100644 (file)
index 0000000..61ea383
--- /dev/null
@@ -0,0 +1,31 @@
+<!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 AES-KW WrapKey operation with malformed parameters");
+
+jsTestIsAsync = true;
+
+var extractable = true;
+var rawKey = asciiToUint8Array("jnOw99oOZFLIEPMr");
+
+crypto.subtle.importKey("raw", rawKey, "aes-kw", extractable, ["wrapKey", "unwrapKey"]).then(function(result) {
+    wrappingKey = result;
+    return crypto.subtle.importKey("raw", rawKey, "aes-cbc", extractable, ["encrypt", "decrypt"]);
+}).then(function(result) {
+    key = result;
+    shouldReject('crypto.subtle.wrapKey("jwk", key, wrappingKey, "AES-KW")').then(finishJSTest);
+});
+
+</script>
+
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/crypto/subtle/rsa-oaep-import-key-wrap-jwk-oct-key-expected.txt b/LayoutTests/crypto/subtle/rsa-oaep-import-key-wrap-jwk-oct-key-expected.txt
new file mode 100644 (file)
index 0000000..637b091
--- /dev/null
@@ -0,0 +1,10 @@
+Test wrapping a JWK oct key with RSA-OAEP using an imported key
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS wrappedKey.byteLength is 256
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/subtle/rsa-oaep-import-key-wrap-jwk-oct-key.html b/LayoutTests/crypto/subtle/rsa-oaep-import-key-wrap-jwk-oct-key.html
new file mode 100644 (file)
index 0000000..da7714c
--- /dev/null
@@ -0,0 +1,46 @@
+<!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 wrapping a JWK oct key with RSA-OAEP using an imported key");
+
+jsTestIsAsync = true;
+
+var extractable = true;
+var jwkKey = {
+    kty: "RSA",
+    alg: "RSA-OAEP",
+    use: "enc",
+    key_ops: ["wrapKey"],
+    ext: true,
+    n: "rcCUCv7Oc1HVam1DIhCzqknThWawOp8QLk8Ziy2p10ByjQFCajoFiyuAWl-R1WXZaf4xitLRracT9agpzIzc-MbLSHIGgWQGO21lGiImy5ftZ-D8bHAqRz2y15pzD4c4CEou7XSSLDoRnR0QG5MsDhD6s2gV9mwHkrtkCxtMWdBi-77as8wGmlNRldcOSgZDLK8UnCSgA1OguZ989bFyc8tOOEIb0xUSfPSz3LPSCnyYz68aDjmKVeNH-ig857OScyWbGyEy3Biw64qun3juUlNWsJ3zngkOdteYWytx5Qr4XKNs6R-Myyq72KUp02mJDZiiyiglxML_i3-_CeecCw",
+    e: "AQAB"
+};
+var rawKey = asciiToUint8Array("jnOw99oOZFLIEPMr");
+
+crypto.subtle.importKey("jwk", jwkKey, {name: "rsa-oaep", hash: "sha-1"}, extractable, ["wrapKey"]).then(function(result) {
+    wrappingKey = result;
+    return crypto.subtle.importKey("raw", rawKey, "aes-cbc", extractable, ["encrypt", "decrypt"]);
+}).then(function(result) {
+    key = result;
+    return crypto.subtle.wrapKey("jwk", key, wrappingKey, "rsa-oaep");
+}).then(function(result) {
+    wrappedKey = result;
+
+    shouldBe("wrappedKey.byteLength", "256");
+
+    finishJSTest();
+});
+
+</script>
+
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/crypto/subtle/wrapKey-malformed-parameters-expected.txt b/LayoutTests/crypto/subtle/wrapKey-malformed-parameters-expected.txt
new file mode 100644 (file)
index 0000000..827bdf6
--- /dev/null
@@ -0,0 +1,17 @@
+Test WrapKey operation with malformed parameters
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS crypto.subtle.wrapKey() rejected promise  with TypeError: Not enough arguments.
+PASS crypto.subtle.wrapKey(1) rejected promise  with TypeError: Not enough arguments.
+PASS crypto.subtle.wrapKey(1, 2) rejected promise  with TypeError: Not enough arguments.
+PASS crypto.subtle.wrapKey(1, 2, 3) rejected promise  with TypeError: Not enough arguments.
+PASS crypto.subtle.wrapKey("raw", key, wrappingKey, "HMAC") rejected promise  with NotSupportedError (DOM Exception 9): The operation is not supported..
+PASS crypto.subtle.wrapKey("raw", key, wrappingKey, aesCbcParams) rejected promise  with InvalidAccessError (DOM Exception 15): Wrapping CryptoKey doesn't match AlgorithmIdentifier.
+PASS crypto.subtle.wrapKey("raw", key, wrappingKey, "AES-KW") rejected promise  with InvalidAccessError (DOM Exception 15): The CryptoKey is nonextractable.
+PASS crypto.subtle.wrapKey("raw", key, wrappingKey, "AES-KW") rejected promise  with InvalidAccessError (DOM Exception 15): Wrapping CryptoKey doesn't support wrapKey operation.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/subtle/wrapKey-malformed-parameters.html b/LayoutTests/crypto/subtle/wrapKey-malformed-parameters.html
new file mode 100644 (file)
index 0000000..43873ca
--- /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 WrapKey operation with malformed parameters");
+
+jsTestIsAsync = true;
+
+var extractable = true;
+var nonExtractable = false;
+var rawKey = asciiToUint8Array("jnOw99oOZFLIEPMr");
+var aesCbcParams = {
+    name: "aes-cbc",
+    iv: asciiToUint8Array("jnOw99oOZFLIEPMr"),
+}
+
+// Not enough arguments.
+shouldReject('crypto.subtle.wrapKey()');
+shouldReject('crypto.subtle.wrapKey(1)');
+shouldReject('crypto.subtle.wrapKey(1, 2)');
+shouldReject('crypto.subtle.wrapKey(1, 2, 3)');
+
+crypto.subtle.importKey("raw", rawKey, "aes-kw", extractable, ["wrapKey", "unwrapKey"]).then(function(result) {
+    wrappingKey = result;
+    return crypto.subtle.importKey("raw", rawKey, "aes-cbc", nonExtractable, ["encrypt", "decrypt"]);
+}).then(function(result) {
+    key = result;
+
+    // Wrong AlgorithmIdentifier
+    shouldReject('crypto.subtle.wrapKey("raw", key, wrappingKey, "HMAC")');
+    shouldReject('crypto.subtle.wrapKey("raw", key, wrappingKey, aesCbcParams)');
+    // Non-extractable
+    shouldReject('crypto.subtle.wrapKey("raw", key, wrappingKey, "AES-KW")');
+
+    return crypto.subtle.importKey("raw", rawKey, "aes-kw", extractable, ["unwrapKey"]);
+}).then(function(result) {
+    wrappingKey = result;
+
+    // Wrong usage
+    shouldReject('crypto.subtle.wrapKey("raw", key, wrappingKey, "AES-KW")').then(finishJSTest);
+});
+
+</script>
+
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/crypto/workers/subtle/aes-cbc-import-key-wrap-key-expected.txt b/LayoutTests/crypto/workers/subtle/aes-cbc-import-key-wrap-key-expected.txt
new file mode 100644 (file)
index 0000000..8ed359d
--- /dev/null
@@ -0,0 +1,11 @@
+[Worker] Test wrapping a JWK RSA public key with AES-CBC using an imported key in workers
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Starting worker: resources/aes-cbc-import-key-wrap-key.js
+PASS [Worker] bytesToHexString(wrappedKey) is expectWrappedKey
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/workers/subtle/aes-cbc-import-key-wrap-key.html b/LayoutTests/crypto/workers/subtle/aes-cbc-import-key-wrap-key.html
new file mode 100644 (file)
index 0000000..31de029
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+    <script>
+        worker = startWorker('resources/aes-cbc-import-key-wrap-key.js');
+    </script>
+    <script src="../../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/crypto/workers/subtle/aes-kw-import-key-wrap-key-expected.txt b/LayoutTests/crypto/workers/subtle/aes-kw-import-key-wrap-key-expected.txt
new file mode 100644 (file)
index 0000000..e327dae
--- /dev/null
@@ -0,0 +1,12 @@
+[Worker] Test wrapping a raw key with AES-KW using an imported key in workers
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Starting worker: resources/aes-kw-import-key-wrap-key.js
+PASS [Worker] bytesToHexString(wrappedKey) is expectWrappedKey
+PASS [Worker] crypto.subtle.wrapKey("jwk", key, wrappingKey, "AES-KW") rejected promise  with OperationError (DOM Exception 34): The operation failed for an operation-specific reason.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/workers/subtle/aes-kw-import-key-wrap-key.html b/LayoutTests/crypto/workers/subtle/aes-kw-import-key-wrap-key.html
new file mode 100644 (file)
index 0000000..a208a30
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+    <script>
+        worker = startWorker('resources/aes-kw-import-key-wrap-key.js');
+    </script>
+    <script src="../../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/crypto/workers/subtle/resources/aes-cbc-import-key-wrap-key.js b/LayoutTests/crypto/workers/subtle/resources/aes-cbc-import-key-wrap-key.js
new file mode 100644 (file)
index 0000000..486753b
--- /dev/null
@@ -0,0 +1,37 @@
+importScripts('../../../../resources/js-test-pre.js');
+importScripts('../../../resources/common.js');
+
+description("Test wrapping a JWK RSA public key with AES-CBC using an imported key in workers");
+
+jsTestIsAsync = true;
+
+var extractable = true;
+var jwkKey = {
+    kty: "RSA",
+    alg: "RSA-OAEP",
+    use: "enc",
+    key_ops: ["encrypt"],
+    ext: true,
+    n: "rcCUCv7Oc1HVam1DIhCzqknThWawOp8QLk8Ziy2p10ByjQFCajoFiyuAWl-R1WXZaf4xitLRracT9agpzIzc-MbLSHIGgWQGO21lGiImy5ftZ-D8bHAqRz2y15pzD4c4CEou7XSSLDoRnR0QG5MsDhD6s2gV9mwHkrtkCxtMWdBi-77as8wGmlNRldcOSgZDLK8UnCSgA1OguZ989bFyc8tOOEIb0xUSfPSz3LPSCnyYz68aDjmKVeNH-ig857OScyWbGyEy3Biw64qun3juUlNWsJ3zngkOdteYWytx5Qr4XKNs6R-Myyq72KUp02mJDZiiyiglxML_i3-_CeecCw",
+    e: "AQAB"
+};
+var rawKey = asciiToUint8Array("jnOw99oOZFLIEPMr");
+var aesCbcParams = {
+    name: "aes-cbc",
+    iv: asciiToUint8Array("jnOw99oOZFLIEPMr"),
+}
+var expectWrappedKey = "848aa2f70ee18e2953520132a79cf47946e00c99362340bb690edc9ab5315757462c128278c6232e770e7437c56ed722a8e1703855f7f3e565394e1a6a0305c4ef1b30fa4c7f72d1a239cc6c6ba067898798a36a75132c66b4a2d3fb942886affd3ea3b2756b0ddc886c01e3b93107469b82124468408ef8ab548b85aa8f206c312d74ce4f2c679eb147a275cefda64d5bdc4a2b5b90a4ac9ad3eb5f2cf19f5f87653211f59b4731ba61125582a233951097dea65db05899d587d1dcfccab9ab7410ab3010b89066506dbacbc6b73e4b564792751388fa0f58d55c59c14a08c9dfb0f78100b0f5cc29d62328822636d30a6a153ec5cd4727ad5e47b419c48544565637ac5789863d43b7da78cf4383d09d66e9d458e436dbfbee75e382b2bab49eec2c7491ff93cf099fe92feaf4658e30889fd12d3ae61cd5e8c8e1e56a079b662f90cd10cdbdbb4d12eefb36d825e1a043e82f5a98f8960d655d3f9ed5af31e581fa846cc582f6cee5c25e0b3c32050534ae957ce27860d470ba26da2c7d6fa621b0faa8becad58e9e55bb2a9d984b042f25df21482529870d271cbf5508a0edfc3cb37316c11f16b342bc1f1f98aa";
+
+crypto.subtle.importKey("raw", rawKey, "aes-cbc", extractable, ["wrapKey"]).then(function(result) {
+    wrappingKey = result;
+    return crypto.subtle.importKey("jwk", jwkKey, { name: "rsa-oaep", hash: "sha-1" }, extractable, ["encrypt"]);
+}).then(function(result) {
+    key = result;
+    return crypto.subtle.wrapKey("jwk", key, wrappingKey, aesCbcParams);
+}).then(function(result) {
+    wrappedKey = result;
+
+    shouldBe("bytesToHexString(wrappedKey)", "expectWrappedKey");
+
+    finishJSTest();
+});
diff --git a/LayoutTests/crypto/workers/subtle/resources/aes-kw-import-key-wrap-key.js b/LayoutTests/crypto/workers/subtle/resources/aes-kw-import-key-wrap-key.js
new file mode 100644 (file)
index 0000000..6e83047
--- /dev/null
@@ -0,0 +1,23 @@
+importScripts('../../../../resources/js-test-pre.js');
+importScripts('../../../resources/common.js');
+
+description("Test wrapping a raw key with AES-KW using an imported key in workers");
+
+jsTestIsAsync = true;
+
+var extractable = true;
+var rawKey = asciiToUint8Array("jnOw99oOZFLIEPMr");
+var expectWrappedKey = "d64787ab3e048dbdc30bb62781c9f18e58ad7dbfc64aab16";
+
+crypto.subtle.importKey("raw", rawKey, "aes-kw", extractable, ["wrapKey", "unwrapKey"]).then(function(result) {
+    wrappingKey = result;
+    return crypto.subtle.importKey("raw", rawKey, "aes-cbc", extractable, ["encrypt", "decrypt"]);
+}).then(function(result) {
+    key = result;
+    return crypto.subtle.wrapKey("raw", key, wrappingKey, "AES-KW");
+}).then(function(result) {
+    wrappedKey = result;
+
+    shouldBe("bytesToHexString(wrappedKey)", "expectWrappedKey");
+    shouldReject('crypto.subtle.wrapKey("jwk", key, wrappingKey, "AES-KW")').then(finishJSTest);
+});
diff --git a/LayoutTests/crypto/workers/subtle/resources/rsa-oaep-import-key-wrap-key.js b/LayoutTests/crypto/workers/subtle/resources/rsa-oaep-import-key-wrap-key.js
new file mode 100644 (file)
index 0000000..aeb1510
--- /dev/null
@@ -0,0 +1,32 @@
+importScripts('../../../../resources/js-test-pre.js');
+importScripts('../../../resources/common.js');
+
+description("Test wrapping a JWK oct key with RSA-OAEP using an imported key in workers");
+
+jsTestIsAsync = true;
+
+var extractable = true;
+var jwkKey = {
+    kty: "RSA",
+    alg: "RSA-OAEP",
+    use: "enc",
+    key_ops: ["wrapKey"],
+    ext: true,
+    n: "rcCUCv7Oc1HVam1DIhCzqknThWawOp8QLk8Ziy2p10ByjQFCajoFiyuAWl-R1WXZaf4xitLRracT9agpzIzc-MbLSHIGgWQGO21lGiImy5ftZ-D8bHAqRz2y15pzD4c4CEou7XSSLDoRnR0QG5MsDhD6s2gV9mwHkrtkCxtMWdBi-77as8wGmlNRldcOSgZDLK8UnCSgA1OguZ989bFyc8tOOEIb0xUSfPSz3LPSCnyYz68aDjmKVeNH-ig857OScyWbGyEy3Biw64qun3juUlNWsJ3zngkOdteYWytx5Qr4XKNs6R-Myyq72KUp02mJDZiiyiglxML_i3-_CeecCw",
+    e: "AQAB"
+};
+var rawKey = asciiToUint8Array("jnOw99oOZFLIEPMr");
+
+crypto.subtle.importKey("jwk", jwkKey, {name: "rsa-oaep", hash: "sha-1"}, extractable, ["wrapKey"]).then(function(result) {
+    wrappingKey = result;
+    return crypto.subtle.importKey("raw", rawKey, "aes-cbc", extractable, ["encrypt", "decrypt"]);
+}).then(function(result) {
+    key = result;
+    return crypto.subtle.wrapKey("jwk", key, wrappingKey, "rsa-oaep");
+}).then(function(result) {
+    wrappedKey = result;
+
+    shouldBe("wrappedKey.byteLength", "256");
+
+    finishJSTest();
+});
diff --git a/LayoutTests/crypto/workers/subtle/rsa-oaep-import-key-wrap-key-expected.txt b/LayoutTests/crypto/workers/subtle/rsa-oaep-import-key-wrap-key-expected.txt
new file mode 100644 (file)
index 0000000..136961b
--- /dev/null
@@ -0,0 +1,11 @@
+[Worker] Test wrapping a JWK oct key with RSA-OAEP using an imported key in workers
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Starting worker: resources/rsa-oaep-import-key-wrap-key.js
+PASS [Worker] wrappedKey.byteLength is 256
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/workers/subtle/rsa-oaep-import-key-wrap-key.html b/LayoutTests/crypto/workers/subtle/rsa-oaep-import-key-wrap-key.html
new file mode 100644 (file)
index 0000000..db5c698
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../../../resources/js-test-pre.js"></script>
+</head>
+<body>
+    <script>
+        worker = startWorker('resources/rsa-oaep-import-key-wrap-key.js');
+    </script>
+    <script src="../../../resources/js-test-post.js"></script>
+</body>
+</html>
index d59766b..3bda441 100644 (file)
@@ -1,5 +1,15 @@
 2016-11-30  Jiewen Tan  <jiewen_tan@apple.com>
 
+        Update SubtleCrypto::wrapKey to match the latest spec
+        https://bugs.webkit.org/show_bug.cgi?id=164746
+        <rdar://problem/29258160>
+
+        Reviewed by Brent Fulgham.
+
+        * WebCryptoAPI/idlharness-expected.txt:
+
+2016-11-30  Jiewen Tan  <jiewen_tan@apple.com>
+
         Update SubtleCrypto::verify to match the latest spec
         https://bugs.webkit.org/show_bug.cgi?id=164741
         <rdar://problem/29257935>
index c7871bd..a31b241 100644 (file)
@@ -63,8 +63,8 @@ PASS SubtleCrypto interface: crypto.subtle must inherit property "importKey" wit
 PASS SubtleCrypto interface: calling importKey(KeyFormat,[object Object],[object Object],AlgorithmIdentifier,boolean,[object Object]) on crypto.subtle with too few arguments must throw TypeError 
 PASS SubtleCrypto interface: crypto.subtle must inherit property "exportKey" with the proper type (9) 
 PASS SubtleCrypto interface: calling exportKey(KeyFormat,CryptoKey) on crypto.subtle with too few arguments must throw TypeError 
-FAIL SubtleCrypto interface: crypto.subtle must inherit property "wrapKey" with the proper type (10) assert_inherits: property "wrapKey" not found in prototype chain
-FAIL SubtleCrypto interface: calling wrapKey(KeyFormat,CryptoKey,CryptoKey,AlgorithmIdentifier) on crypto.subtle with too few arguments must throw TypeError assert_inherits: property "wrapKey" not found in prototype chain
+PASS SubtleCrypto interface: crypto.subtle must inherit property "wrapKey" with the proper type (10) 
+PASS SubtleCrypto interface: calling wrapKey(KeyFormat,CryptoKey,CryptoKey,AlgorithmIdentifier) on crypto.subtle with too few arguments must throw TypeError 
 FAIL SubtleCrypto interface: crypto.subtle must inherit property "unwrapKey" with the proper type (11) assert_inherits: property "unwrapKey" not found in prototype chain
 FAIL SubtleCrypto interface: calling unwrapKey(KeyFormat,BufferSource,CryptoKey,AlgorithmIdentifier,AlgorithmIdentifier,boolean,[object Object]) on crypto.subtle with too few arguments must throw TypeError assert_inherits: property "unwrapKey" not found in prototype chain
 
index 615d2e3..f6852e1 100644 (file)
@@ -1,3 +1,51 @@
+2016-11-30  Jiewen Tan  <jiewen_tan@apple.com>
+
+        Update SubtleCrypto::wrapKey to match the latest spec
+        https://bugs.webkit.org/show_bug.cgi?id=164746
+        <rdar://problem/29258160>
+
+        Reviewed by Brent Fulgham.
+
+        This patch does following few things:
+        1. It updates the SubtleCrypto::wrapKey method to match the latest spec:
+           https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-wrapKey.
+           It also refers to the latest Editor's Draft to a certain degree:
+           https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-wrapKey.
+        2. It implements wrapKey operations of the following algorithms: AES-KW.
+        3. It also replaces JSSubtleCrypto* with auto in all promise functions.
+
+        Tests: crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-private.html
+               crypto/subtle/aes-cbc-import-key-wrap-jwk-rsa-key-public.html
+               crypto/subtle/aes-kw-import-key-wrap-raw-key.html
+               crypto/subtle/aes-kw-wrap-key-malformed-parameters.html
+               crypto/subtle/rsa-oaep-import-key-wrap-jwk-oct-key.html
+               crypto/subtle/wrapKey-malformed-parameters.html
+               crypto/workers/subtle/aes-cbc-import-key-wrap-key.html
+               crypto/workers/subtle/aes-kw-import-key-wrap-key.html
+               crypto/workers/subtle/rsa-oaep-import-key-wrap-key.html
+
+        * bindings/js/JSSubtleCryptoCustom.cpp:
+        (WebCore::normalizeCryptoAlgorithmParameters):
+        (WebCore::supportExportKeyThrow):
+        (WebCore::jsSubtleCryptoFunctionEncryptPromise):
+        (WebCore::jsSubtleCryptoFunctionDecryptPromise):
+        (WebCore::jsSubtleCryptoFunctionExportKeyPromise):
+        (WebCore::jsSubtleCryptoFunctionWrapKeyPromise):
+        (WebCore::JSSubtleCrypto::wrapKey):
+        * crypto/CryptoAlgorithm.cpp:
+        (WebCore::CryptoAlgorithm::wrapKey):
+        * crypto/CryptoAlgorithm.h:
+        * crypto/SubtleCrypto.idl:
+        * crypto/algorithms/CryptoAlgorithmAES_KW.cpp:
+        (WebCore::CryptoAlgorithmAES_KW::wrapKey):
+        * crypto/algorithms/CryptoAlgorithmAES_KW.h:
+        * crypto/gnutls/CryptoAlgorithmAES_KWGnuTLS.cpp:
+        (WebCore::CryptoAlgorithmAES_KW::platformWrapKey):
+        * crypto/mac/CryptoAlgorithmAES_KWMac.cpp:
+        (WebCore::wrapKeyAES_KW):
+        (WebCore::CryptoAlgorithmAES_KW::platformWrapKey):
+        (WebCore::CryptoAlgorithmAES_KW::platformEncrypt):
+
 2016-11-29  Sam Weinig  <sam@webkit.org>
 
         [WebIDL] Add support for more missing / exotic IDLTypes
index 25d282a..81533f1 100644 (file)
@@ -46,6 +46,7 @@
 #include <runtime/Error.h>
 #include <runtime/IteratorOperations.h>
 #include <runtime/JSArray.h>
+#include <runtime/JSONObject.h>
 
 using namespace JSC;
 
@@ -59,6 +60,7 @@ enum class Operations {
     Digest,
     GenerateKey,
     ImportKey,
+    WrapKey,
 };
 
 static std::unique_ptr<CryptoAlgorithmParameters> normalizeCryptoAlgorithmParameters(ExecState&, JSValue, Operations);
@@ -223,6 +225,16 @@ static std::unique_ptr<CryptoAlgorithmParameters> normalizeCryptoAlgorithmParame
                 return nullptr;
             }
             break;
+        case Operations::WrapKey:
+            switch (*identifier) {
+            case CryptoAlgorithmIdentifier::AES_KW:
+                result = std::make_unique<CryptoAlgorithmParameters>(params);
+                break;
+            default:
+                setDOMException(&state, NOT_SUPPORTED_ERR);
+                return nullptr;
+            }
+            break;
         default:
             ASSERT_NOT_REACHED();
             return nullptr;
@@ -430,6 +442,26 @@ static Vector<uint8_t> toVector(ExecState& state, JSValue value)
     return dataVector;
 }
 
+static void supportExportKeyThrow(ExecState& state, CryptoAlgorithmIdentifier identifier)
+{
+    switch (identifier) {
+    case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
+    case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+    case CryptoAlgorithmIdentifier::RSA_PSS:
+    case CryptoAlgorithmIdentifier::RSA_OAEP:
+    case CryptoAlgorithmIdentifier::AES_CTR:
+    case CryptoAlgorithmIdentifier::AES_CBC:
+    case CryptoAlgorithmIdentifier::AES_CMAC:
+    case CryptoAlgorithmIdentifier::AES_GCM:
+    case CryptoAlgorithmIdentifier::AES_CFB:
+    case CryptoAlgorithmIdentifier::AES_KW:
+    case CryptoAlgorithmIdentifier::HMAC:
+        return;
+    default:
+        setDOMException(&state, NOT_SUPPORTED_ERR);
+    }
+}
+
 static void jsSubtleCryptoFunctionEncryptPromise(ExecState& state, Ref<DeferredPromise>&& promise)
 {
     VM& vm = state.vm();
@@ -470,7 +502,7 @@ static void jsSubtleCryptoFunctionEncryptPromise(ExecState& state, Ref<DeferredP
         rejectWithException(WTFMove(capturedPromise), ec);
     };
 
-    JSSubtleCrypto* subtle = jsDynamicDowncast<JSSubtleCrypto*>(state.thisValue());
+    auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(state.thisValue());
     ASSERT(subtle);
     algorithm->encrypt(WTFMove(params), key.releaseNonNull(), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue());
 }
@@ -515,7 +547,7 @@ static void jsSubtleCryptoFunctionDecryptPromise(ExecState& state, Ref<DeferredP
         rejectWithException(WTFMove(capturedPromise), ec);
     };
 
-    JSSubtleCrypto* subtle = jsDynamicDowncast<JSSubtleCrypto*>(state.thisValue());
+    auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(state.thisValue());
     ASSERT(subtle);
     algorithm->decrypt(WTFMove(params), key.releaseNonNull(), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue());
 }
@@ -723,23 +755,8 @@ static void jsSubtleCryptoFunctionExportKeyPromise(ExecState& state, Ref<Deferre
     auto key = toCryptoKey(state, state.uncheckedArgument(1));
     RETURN_IF_EXCEPTION(scope, void());
 
-    switch (key->algorithmIdentifier()) {
-    case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
-    case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
-    case CryptoAlgorithmIdentifier::RSA_PSS:
-    case CryptoAlgorithmIdentifier::RSA_OAEP:
-    case CryptoAlgorithmIdentifier::AES_CTR:
-    case CryptoAlgorithmIdentifier::AES_CBC:
-    case CryptoAlgorithmIdentifier::AES_CMAC:
-    case CryptoAlgorithmIdentifier::AES_GCM:
-    case CryptoAlgorithmIdentifier::AES_CFB:
-    case CryptoAlgorithmIdentifier::AES_KW:
-    case CryptoAlgorithmIdentifier::HMAC:
-        break;
-    default:
-        promise->reject(NOT_SUPPORTED_ERR, ASCIILiteral("The operation is not supported"));
-        return;
-    }
+    supportExportKeyThrow(state, key->algorithmIdentifier());
+    RETURN_IF_EXCEPTION(scope, void());
 
     if (!key->extractable()) {
         promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("The CryptoKey is nonextractable"));
@@ -774,6 +791,105 @@ static void jsSubtleCryptoFunctionExportKeyPromise(ExecState& state, Ref<Deferre
     algorithm->exportKey(format, key.releaseNonNull(), WTFMove(callback), WTFMove(exceptionCallback));
 }
 
+static void jsSubtleCryptoFunctionWrapKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise)
+{
+    VM& vm = state.vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    if (UNLIKELY(state.argumentCount() < 4)) {
+        promise->reject<JSValue>(createNotEnoughArgumentsError(&state));
+        return;
+    }
+
+    auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0));
+    RETURN_IF_EXCEPTION(scope, void());
+
+    auto key = toCryptoKey(state, state.uncheckedArgument(1));
+    RETURN_IF_EXCEPTION(scope, void());
+
+    auto wrappingKey = toCryptoKey(state, state.uncheckedArgument(2));
+    RETURN_IF_EXCEPTION(scope, void());
+
+    auto catchScope = DECLARE_CATCH_SCOPE(vm);
+    bool isEncryption = false;
+    auto wrapParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(3), Operations::WrapKey);
+    if (catchScope.exception()) {
+        catchScope.clearException();
+        wrapParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(3), Operations::Encrypt);
+        RETURN_IF_EXCEPTION(scope, void());
+        isEncryption = true;
+    }
+
+    if (wrapParams->identifier != wrappingKey->algorithmIdentifier()) {
+        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("Wrapping CryptoKey doesn't match AlgorithmIdentifier"));
+        return;
+    }
+
+    if (!wrappingKey->allows(CryptoKeyUsageWrapKey)) {
+        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("Wrapping CryptoKey doesn't support wrapKey operation"));
+        return;
+    }
+
+    supportExportKeyThrow(state, key->algorithmIdentifier());
+    RETURN_IF_EXCEPTION(scope, void());
+
+    if (!key->extractable()) {
+        promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("The CryptoKey is nonextractable"));
+        return;
+    }
+
+    auto exportAlgorithm = createAlgorithm(state, key->algorithmIdentifier());
+    RETURN_IF_EXCEPTION(scope, void());
+
+    auto wrapAlgorithm = createAlgorithm(state, wrappingKey->algorithmIdentifier());
+    RETURN_IF_EXCEPTION(scope, void());
+
+    auto context = scriptExecutionContextFromExecState(&state);
+
+    auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(state.thisValue());
+    ASSERT(subtle);
+    auto& workQueue = subtle->wrapped().workQueue();
+
+    auto callback = [promise = promise.copyRef(), wrapAlgorithm, wrappingKey = WTFMove(wrappingKey), wrapParams = WTFMove(wrapParams), isEncryption, context, &workQueue](SubtleCrypto::KeyFormat format, KeyData&& key) mutable {
+        Vector<uint8_t> bytes;
+        switch (format) {
+        case SubtleCrypto::KeyFormat::Spki:
+        case SubtleCrypto::KeyFormat::Pkcs8:
+        case SubtleCrypto::KeyFormat::Raw:
+            bytes = WTF::get<Vector<uint8_t>>(key);
+            break;
+        case SubtleCrypto::KeyFormat::Jwk: {
+            auto jwk = toJSValueFromJsonWebKey(*(promise->globalObject()), WTFMove(WTF::get<JsonWebKey>(key)));
+            String jwkString = JSONStringify(promise->globalObject()->globalExec(), jwk, 0);
+            CString jwkUtf8String = jwkString.utf8(StrictConversion);
+            bytes.append(jwkUtf8String.data(), jwkUtf8String.length());
+        }
+        }
+
+        auto callback = [promise = promise.copyRef()](const Vector<uint8_t>& wrappedKey) mutable {
+            fulfillPromiseWithArrayBuffer(WTFMove(promise), wrappedKey.data(), wrappedKey.size());
+            return;
+        };
+        auto exceptionCallback = [promise = WTFMove(promise)](ExceptionCode ec) mutable {
+            rejectWithException(WTFMove(promise), ec);
+        };
+
+        if (!isEncryption) {
+            // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously:
+            // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-wrapKey
+            // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously.
+            wrapAlgorithm->wrapKey(wrappingKey.releaseNonNull(), WTFMove(bytes), WTFMove(callback), WTFMove(exceptionCallback));
+            return;
+        }
+        wrapAlgorithm->encrypt(WTFMove(wrapParams), wrappingKey.releaseNonNull(), WTFMove(bytes), WTFMove(callback), WTFMove(exceptionCallback), *context, workQueue);
+    };
+    auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
+        rejectWithException(WTFMove(capturedPromise), ec);
+    };
+
+    exportAlgorithm->exportKey(format, key.releaseNonNull(), WTFMove(callback), WTFMove(exceptionCallback));
+}
+
 JSValue JSSubtleCrypto::encrypt(ExecState& state)
 {
     return callPromiseFunction<jsSubtleCryptoFunctionEncryptPromise, PromiseExecutionScope::WindowOrWorker>(state);
@@ -809,6 +925,11 @@ JSValue JSSubtleCrypto::exportKey(ExecState& state)
     return callPromiseFunction<jsSubtleCryptoFunctionExportKeyPromise, PromiseExecutionScope::WindowOrWorker>(state);
 }
 
+JSValue JSSubtleCrypto::wrapKey(ExecState& state)
+{
+    return callPromiseFunction<jsSubtleCryptoFunctionWrapKeyPromise, PromiseExecutionScope::WindowOrWorker>(state);
+}
+
 } // namespace WebCore
 
 #endif
index 27c63e7..b1681ce 100644 (file)
@@ -67,6 +67,11 @@ void CryptoAlgorithm::exportKey(SubtleCrypto::KeyFormat, Ref<CryptoKey>&&, KeyDa
     exceptionCallback(NOT_SUPPORTED_ERR);
 }
 
+void CryptoAlgorithm::wrapKey(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&& exceptionCallback)
+{
+    exceptionCallback(NOT_SUPPORTED_ERR);
+}
+
 ExceptionOr<void> CryptoAlgorithm::encrypt(const CryptoAlgorithmParametersDeprecated&, const CryptoKey&, const CryptoOperationData&, VectorCallback&&, VoidCallback&&)
 {
     return Exception { NOT_SUPPORTED_ERR };
index d3c7c66..22bb545 100644 (file)
@@ -71,6 +71,7 @@ public:
     virtual void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsageBitmap, KeyOrKeyPairCallback&&, ExceptionCallback&&, ScriptExecutionContext&);
     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&&);
 
     // The following will be deprecated.
     virtual ExceptionOr<void> encrypt(const CryptoAlgorithmParametersDeprecated&, const CryptoKey&, const CryptoOperationData&, VectorCallback&&, VoidCallback&& failureCallback);
index bd86317..53143df 100644 (file)
@@ -39,4 +39,5 @@ enum KeyFormat { "raw", "spki", "pkcs8", "jwk" };
     [Custom] Promise<any> generateKey(AlgorithmIdentifier algorithm, boolean extractable, sequence<CryptoKeyUsage> keyUsages);
     [Custom] Promise<CryptoKey> importKey(KeyFormat format, (BufferSource or JsonWebKey) keyData, AlgorithmIdentifier algorithm, boolen extractable, sequence<CryptoKeyUsage> keyUsages);
     [Custom] Promise<any> exportKey(KeyFormat format, CryptoKey key);
+    [Custom] Promise<any> wrapKey(KeyFormat format, CryptoKey key, CryptoKey wrappingKey, AlgorithmIdentifier wrapAlgorithm);
 };
index 819028f..7b12ed5 100644 (file)
@@ -158,6 +158,15 @@ void CryptoAlgorithmAES_KW::exportKey(SubtleCrypto::KeyFormat format, Ref<Crypto
     callback(format, WTFMove(result));
 }
 
+void CryptoAlgorithmAES_KW::wrapKey(Ref<CryptoKey>&& key, Vector<uint8_t>&& data, VectorCallback&& callback, ExceptionCallback&& exceptionCallback)
+{
+    if (data.size() % 8) {
+        exceptionCallback(OperationError);
+        return;
+    }
+    platformWrapKey(WTFMove(key), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback));
+}
+
 ExceptionOr<void> CryptoAlgorithmAES_KW::encryptForWrapKey(const CryptoAlgorithmParametersDeprecated&, const CryptoKey& key, const CryptoOperationData& data, VectorCallback&& callback, VoidCallback&& failureCallback)
 {
     if (!keyAlgorithmMatches(key))
index 435ee13..8ea8ec3 100644 (file)
@@ -46,6 +46,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;
+    void wrapKey(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&) 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;
@@ -53,6 +54,7 @@ private:
     ExceptionOr<void> importKey(const CryptoAlgorithmParametersDeprecated&, const CryptoKeyData&, bool extractable, CryptoKeyUsageBitmap, KeyCallback&&, VoidCallback&& failureCallback) final;
 
     bool keyAlgorithmMatches(const CryptoKey&) const;
+    void platformWrapKey(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&);
     ExceptionOr<void> platformEncrypt(const CryptoKeyAES&, const CryptoOperationData&, VectorCallback&&, VoidCallback&& failureCallback);
     ExceptionOr<void> platformDecrypt(const CryptoKeyAES&, const CryptoOperationData&, VectorCallback&&, VoidCallback&& failureCallback);
 };
index fabac1a..c9ed3db 100644 (file)
 
 namespace WebCore {
 
+void CryptoAlgorithmAES_KW::platformWrapKey(Ref<CryptoKey>&&, Vector<uint8_t>&&, VectorCallback&&, ExceptionCallback&&)
+{
+    notImplemented();
+}
+
 ExceptionOr<void> CryptoAlgorithmAES_KW::platformEncrypt(const CryptoKeyAES&, const CryptoOperationData&, VectorCallback&&, VoidCallback&&)
 {
     notImplemented();
index 6fbd297..feebc64 100644 (file)
 
 namespace WebCore {
 
+// FIXME: We should change data to Vector<uint8_t> type once WebKitSubtleCrypto is deprecated.
+// https://bugs.webkit.org/show_bug.cgi?id=164939
+static ExceptionOr<Vector<uint8_t>> wrapKeyAES_KW(const Vector<uint8_t>& key, const uint8_t* data, size_t dataLength)
+{
+    Vector<uint8_t> result(CCSymmetricWrappedSize(kCCWRAPAES, dataLength));
+    size_t resultSize = result.size();
+    if (CCSymmetricKeyWrap(kCCWRAPAES, CCrfc3394_iv, CCrfc3394_ivLen, key.data(), key.size(), data, dataLength, result.data(), &resultSize))
+        return Exception { OperationError };
+
+    result.shrink(resultSize);
+    return WTFMove(result);
+}
+
+void CryptoAlgorithmAES_KW::platformWrapKey(Ref<CryptoKey>&& key, Vector<uint8_t>&& data, VectorCallback&& callback, ExceptionCallback&& exceptionCallback)
+{
+    auto& aesKey = downcast<CryptoKeyAES>(key.get());
+    auto result = wrapKeyAES_KW(aesKey.key(), data.data(), data.size());
+    if (result.hasException()) {
+        exceptionCallback(result.releaseException().code());
+        return;
+    }
+    callback(result.releaseReturnValue());
+}
+
 ExceptionOr<void> CryptoAlgorithmAES_KW::platformEncrypt(const CryptoKeyAES& key, const CryptoOperationData& data, VectorCallback&& callback, VoidCallback&& failureCallback)
 {
     if (data.second % 8) {
@@ -43,15 +67,12 @@ ExceptionOr<void> CryptoAlgorithmAES_KW::platformEncrypt(const CryptoKeyAES& key
         return { };
     }
 
-    Vector<uint8_t> result(CCSymmetricWrappedSize(kCCWRAPAES, data.second));
-    size_t resultSize = result.size();
-    int status = CCSymmetricKeyWrap(kCCWRAPAES, CCrfc3394_iv, CCrfc3394_ivLen, key.key().data(), key.key().size(), data.first, data.second, result.data(), &resultSize);
-    if (status) {
+    auto result = wrapKeyAES_KW(key.key(), data.first, data.second);
+    if (result.hasException()) {
         failureCallback();
         return { };
     }
-    result.shrink(resultSize);
-    callback(result);
+    callback(result.releaseReturnValue());
     return { };
 }