WebCrypto keys should support structured clone
authorap@apple.com <ap@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Dec 2013 22:13:55 +0000 (22:13 +0000)
committerap@apple.com <ap@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Dec 2013 22:13:55 +0000 (22:13 +0000)
https://bugs.webkit.org/show_bug.cgi?id=125590

Reviewed by Oliver Hunt.

Source/WebCore:

Tests: crypto/subtle/aes-postMessage.html
       crypto/subtle/hmac-postMessage.html
       crypto/subtle/postMessage-worker.html
       crypto/subtle/rsa-postMessage.html

* crypto/CryptoAlgorithmIdentifier.h:
(WebCore::CryptoAlgorithmIdentifier):
* bindings/js/JSCryptoAlgorithmDictionary.cpp:
(WebCore::JSCryptoAlgorithmDictionary::createParametersForEncrypt):
(WebCore::JSCryptoAlgorithmDictionary::createParametersForDecrypt):
(WebCore::JSCryptoAlgorithmDictionary::createParametersForSign):
(WebCore::JSCryptoAlgorithmDictionary::createParametersForVerify):
(WebCore::JSCryptoAlgorithmDictionary::createParametersForDigest):
(WebCore::JSCryptoAlgorithmDictionary::createParametersForGenerateKey):
(WebCore::JSCryptoAlgorithmDictionary::createParametersForDeriveKey):
(WebCore::JSCryptoAlgorithmDictionary::createParametersForDeriveBits):
(WebCore::JSCryptoAlgorithmDictionary::createParametersForImportKey):
(WebCore::JSCryptoAlgorithmDictionary::createParametersForExportKey):
AES_KW was added to WebCrypto spec editor's draft yesterday night. Now that we're
adding a matching enum for structired clone serialization, it's as good a time as
any to update the order of values to match.

* bindings/js/SerializedScriptValue.cpp:
(WebCore::countUsages):
(WebCore::CloneSerializer::dumpIfTerminal):
(WebCore::CloneSerializer::write):
(WebCore::CloneDeserializer::read):
(WebCore::CloneDeserializer::readHMACKey):
(WebCore::CloneDeserializer::readAESKey):
(WebCore::CloneDeserializer::readRSAKey):
(WebCore::CloneDeserializer::readCryptoKey):
(WebCore::CloneDeserializer::readTerminal):
Added serialization/deserialization for CryptoKey. This doesn't update version
number, because we don't currently store structured clones in persistent storage -
and even if we did, we wouldn't want to invalidate everything users already stored.

* crypto/CryptoAlgorithmRegistry.cpp:
(WebCore::CryptoAlgorithmRegistry::shared):
(WebCore::registryMutex):
(WebCore::CryptoAlgorithmRegistry::getIdentifierForName):
(WebCore::CryptoAlgorithmRegistry::nameForIdentifier):
(WebCore::CryptoAlgorithmRegistry::create):
(WebCore::CryptoAlgorithmRegistry::registerAlgorithm):
* crypto/CryptoKey.idl:
With structured clone, it is now possible to send a Key to a web worker. That's
of no practical use because the crypto API is not exposed in workers, but we
shouldn't crash anyway.

* crypto/keys/CryptoKeyAES.cpp:
(WebCore::CryptoKeyAES::CryptoKeyAES):
(WebCore::CryptoKeyAES::isValidAESAlgorithm):
* crypto/keys/CryptoKeyAES.h:
Exposed isValidAESAlgorithm, so that a caller could know whether the constructor
will assert.

* CMakeLists.txt:
* GNUmakefile.am:
* WebCore.vcxproj/WebCore.vcxproj.filters:
* WebCore.vcxproj/WebCoreCommon.props:
Added crypto/keys to search paths to avoid build breakage.

LayoutTests:

* crypto/subtle/aes-postMessage-expected.txt: Added.
* crypto/subtle/aes-postMessage.html: Added.
* crypto/subtle/hmac-postMessage-expected.txt: Added.
* crypto/subtle/hmac-postMessage.html: Added.
* crypto/subtle/postMessage-worker-expected.txt: Added.
* crypto/subtle/postMessage-worker.html: Added.
* crypto/subtle/rsa-postMessage-expected.txt: Added.
* crypto/subtle/rsa-postMessage.html: Added.
* crypto/subtle/resources/postMessage-worker.js: Added.

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

22 files changed:
LayoutTests/ChangeLog
LayoutTests/crypto/subtle/aes-postMessage-expected.txt [new file with mode: 0644]
LayoutTests/crypto/subtle/aes-postMessage.html [new file with mode: 0644]
LayoutTests/crypto/subtle/hmac-postMessage-expected.txt [new file with mode: 0644]
LayoutTests/crypto/subtle/hmac-postMessage.html [new file with mode: 0644]
LayoutTests/crypto/subtle/postMessage-worker-expected.txt [new file with mode: 0644]
LayoutTests/crypto/subtle/postMessage-worker.html [new file with mode: 0644]
LayoutTests/crypto/subtle/resources/postMessage-worker.js [new file with mode: 0644]
LayoutTests/crypto/subtle/rsa-postMessage-expected.txt [new file with mode: 0644]
LayoutTests/crypto/subtle/rsa-postMessage.html [new file with mode: 0644]
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.am
Source/WebCore/WebCore.vcxproj/WebCore.vcxproj.filters
Source/WebCore/WebCore.vcxproj/WebCoreCommon.props
Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.cpp
Source/WebCore/bindings/js/SerializedScriptValue.cpp
Source/WebCore/crypto/CryptoAlgorithmIdentifier.h
Source/WebCore/crypto/CryptoAlgorithmRegistry.cpp
Source/WebCore/crypto/CryptoKey.idl
Source/WebCore/crypto/keys/CryptoKeyAES.cpp
Source/WebCore/crypto/keys/CryptoKeyAES.h

index 50215c2..5a2d98b 100644 (file)
@@ -1,3 +1,20 @@
+2013-12-11  Alexey Proskuryakov  <ap@apple.com>
+
+        WebCrypto keys should support structured clone
+        https://bugs.webkit.org/show_bug.cgi?id=125590
+
+        Reviewed by Oliver Hunt.
+
+        * crypto/subtle/aes-postMessage-expected.txt: Added.
+        * crypto/subtle/aes-postMessage.html: Added.
+        * crypto/subtle/hmac-postMessage-expected.txt: Added.
+        * crypto/subtle/hmac-postMessage.html: Added.
+        * crypto/subtle/postMessage-worker-expected.txt: Added.
+        * crypto/subtle/postMessage-worker.html: Added.
+        * crypto/subtle/rsa-postMessage-expected.txt: Added.
+        * crypto/subtle/rsa-postMessage.html: Added.
+        * crypto/subtle/resources/postMessage-worker.js: Added.
+
 2013-12-11  Bear Travis  <betravis@adobe.com>
 
         Web Inspector: [CSS Shapes] Highlight margin-shape for shape-outside
diff --git a/LayoutTests/crypto/subtle/aes-postMessage-expected.txt b/LayoutTests/crypto/subtle/aes-postMessage-expected.txt
new file mode 100644 (file)
index 0000000..42f605f
--- /dev/null
@@ -0,0 +1,14 @@
+Test sending crypto keys via postMessage.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS key.type is 'secret'
+PASS key.extractable is true
+PASS key.algorithm.name is 'aes-cbc'
+PASS key.algorithm.length is 128
+PASS key.usages is ["encrypt", "decrypt", "sign", "verify"]
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/subtle/aes-postMessage.html b/LayoutTests/crypto/subtle/aes-postMessage.html
new file mode 100644 (file)
index 0000000..bc63d4f
--- /dev/null
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="../../resources/js-test-pre.js"></script>
+<script src="resources/common.js"></script>
+</head>
+<body>
+<script>
+
+description("Test sending crypto keys via postMessage.");
+
+jsTestIsAsync = true;
+
+window.addEventListener("message", function(evt) {
+    key = evt.data;
+    shouldBe("key.type", "'secret'");
+    shouldBe("key.extractable", "true");
+    shouldBe("key.algorithm.name", "'aes-cbc'");
+    shouldBe("key.algorithm.length", "128");
+    shouldBe("key.usages", '["encrypt", "decrypt", "sign", "verify"]');
+
+    finishJSTest();
+}, false);
+
+importTestKeys().then(function(keys) {
+    postMessage(keys.aesCbc, "*");
+});
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/crypto/subtle/hmac-postMessage-expected.txt b/LayoutTests/crypto/subtle/hmac-postMessage-expected.txt
new file mode 100644 (file)
index 0000000..5aaefdd
--- /dev/null
@@ -0,0 +1,14 @@
+Test sending crypto keys via postMessage.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS key.type is 'secret'
+PASS key.extractable is true
+PASS key.algorithm.name is 'hmac'
+PASS key.algorithm.length is 16
+PASS key.usages is ["encrypt", "decrypt", "sign", "verify"]
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/subtle/hmac-postMessage.html b/LayoutTests/crypto/subtle/hmac-postMessage.html
new file mode 100644 (file)
index 0000000..1166d42
--- /dev/null
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="../../resources/js-test-pre.js"></script>
+<script src="resources/common.js"></script>
+</head>
+<body>
+<script>
+
+description("Test sending crypto keys via postMessage.");
+
+jsTestIsAsync = true;
+
+window.addEventListener("message", function(evt) {
+    key = evt.data;
+    shouldBe("key.type", "'secret'");
+    shouldBe("key.extractable", "true");
+    shouldBe("key.algorithm.name", "'hmac'");
+    shouldBe("key.algorithm.length", "16");
+    shouldBe("key.usages", '["encrypt", "decrypt", "sign", "verify"]');
+
+    finishJSTest();
+}, false);
+
+importTestKeys().then(function(keys) {
+    postMessage(keys.hmacSha1, "*");
+});
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/crypto/subtle/postMessage-worker-expected.txt b/LayoutTests/crypto/subtle/postMessage-worker-expected.txt
new file mode 100644 (file)
index 0000000..72ab7e6
--- /dev/null
@@ -0,0 +1,15 @@
+Test sending crypto keys via postMessage to a worker.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS All checks passed in worker
+PASS key.type is 'secret'
+PASS key.extractable is true
+PASS key.algorithm.name is 'hmac'
+PASS key.algorithm.length is 16
+PASS key.usages is ["encrypt", "decrypt", "sign", "verify"]
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/subtle/postMessage-worker.html b/LayoutTests/crypto/subtle/postMessage-worker.html
new file mode 100644 (file)
index 0000000..3e34c9d
--- /dev/null
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="../../resources/js-test-pre.js"></script>
+<script src="resources/common.js"></script>
+</head>
+<body>
+<script>
+
+description("Test sending crypto keys via postMessage to a worker.");
+
+jsTestIsAsync = true;
+
+importTestKeys().then(function(keys) {
+    var worker = new Worker("resources/postMessage-worker.js");
+    worker.onmessage = function(evt) {
+        if (!evt.data.result) {
+            testFailed("Check failed in worker: " + evt.data.message);
+        } else {
+            testPassed("All checks passed in worker");
+            key = evt.data.key;
+            shouldBe("key.type", "'secret'");
+            shouldBe("key.extractable", "true");
+            shouldBe("key.algorithm.name", "'hmac'");
+            shouldBe("key.algorithm.length", "16");
+            shouldBe("key.usages", '["encrypt", "decrypt", "sign", "verify"]');
+        }
+        finishJSTest();
+    }
+    worker.postMessage(keys.hmacSha1);
+});
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/crypto/subtle/resources/postMessage-worker.js b/LayoutTests/crypto/subtle/resources/postMessage-worker.js
new file mode 100644 (file)
index 0000000..7f98b94
--- /dev/null
@@ -0,0 +1,14 @@
+onmessage = function(evt)
+{
+    var key = evt.data;
+    if (key.type != 'secret')
+        postMessage({ result:false, message:'key.type should be "secret"' });
+    else if (!key.extractable)
+        postMessage({ result:false, message:'key.extractable should be true' });
+    else if (key.algorithm.name != "hmac")
+        postMessage({ result:false, message:'key.algorithm.name should be "hmac"' });
+    else if (key.usages.toString() != "encrypt,decrypt,sign,verify")
+        postMessage({ result:false, message:'key.usages should be ["encrypt", "decrypt", "sign", "verify"]' });
+    else
+        postMessage({ result:true, key:key });
+}
diff --git a/LayoutTests/crypto/subtle/rsa-postMessage-expected.txt b/LayoutTests/crypto/subtle/rsa-postMessage-expected.txt
new file mode 100644 (file)
index 0000000..b5d6408
--- /dev/null
@@ -0,0 +1,31 @@
+Test sending crypto keys via postMessage.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Key received in a message:
+PASS key.type is 'private'
+PASS key.extractable is true
+PASS key.algorithm.name is 'rsassa-pkcs1-v1_5'
+PASS key.algorithm.modulusLength is 2048
+PASS bytesToHexString(key.algorithm.publicExponent) is '010001'
+PASS key.usages is ["sign", "verify"]
+
+Exported back to JWK:
+PASS exportedJWK.kty is 'RSA'
+PASS exportedJWK.alg is 'RS256'
+PASS exportedJWK.ext is true
+PASS exportedJWK.use is 'sig'
+PASS exportedJWK.n is privateKeyJSON.n
+PASS exportedJWK.e is privateKeyJSON.e
+PASS exportedJWK.d is privateKeyJSON.d
+PASS exportedJWK.p is privateKeyJSON.p
+PASS exportedJWK.q is privateKeyJSON.q
+PASS exportedJWK.dp is privateKeyJSON.dp
+PASS exportedJWK.dq is privateKeyJSON.dq
+PASS exportedJWK.qi is privateKeyJSON.qi
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/subtle/rsa-postMessage.html b/LayoutTests/crypto/subtle/rsa-postMessage.html
new file mode 100644 (file)
index 0000000..6047ed5
--- /dev/null
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src="../../resources/js-test-pre.js"></script>
+<script src="resources/common.js"></script>
+</head>
+<body>
+<script>
+
+description("Test sending crypto keys via postMessage.");
+
+jsTestIsAsync = true;
+
+var privateKeyJSON = {
+    kty: "RSA",
+    alg: "RS256",
+    n: "rcCUCv7Oc1HVam1DIhCzqknThWawOp8QLk8Ziy2p10ByjQFCajoFiyuAWl-R1WXZaf4xitLRracT9agpzIzc-MbLSHIGgWQGO21lGiImy5ftZ-D8bHAqRz2y15pzD4c4CEou7XSSLDoRnR0QG5MsDhD6s2gV9mwHkrtkCxtMWdBi-77as8wGmlNRldcOSgZDLK8UnCSgA1OguZ989bFyc8tOOEIb0xUSfPSz3LPSCnyYz68aDjmKVeNH-ig857OScyWbGyEy3Biw64qun3juUlNWsJ3zngkOdteYWytx5Qr4XKNs6R-Myyq72KUp02mJDZiiyiglxML_i3-_CeecCw",
+    e: "AQAB",
+    d: "eNLS37aCz7RXSNPD_DtLBJ6j5T8cSxdzRBCjPaI6WcGqJp16lq3UTwuoDLAqlA9oGYm238dsIWpuucP_lQtbWe-7SpxoI6_vmYGf7YVUHv1-DF9qiOmSrMmdxMnVOzYXY8RaT6thPjn_J5cfLV2xI_LwsrMtmpdSyNlgX0zTUhwtuahgAKMEChYjH2EnjHdHw6sY2-wApdcQI7ULE0oo5RzbQZpmuhcN9hiBc0L3hhF0qo50mbl02_65_GQ7DpVkXBxNgRBLzlPabmzzG2oAhfefLgYmSC1opaCkXE6vRWQNWNL45RZNZFYM3uoJghOMqGeocM0BpjdChHrPOlFvSQ",
+    p: "4miTuAjKMeH5uJ5KB397QUwhbkYEgSbcA2mifmSkvE2018gb55qkBHK1eVryf1_m43LNlc6O_ak6gfzdZIZvS5NCGjPl0q09plUpu8qFOSspBwA67qGH76lFlZLn_d4yglS7wfLru4_5Ys8qLLs-DqVLviwposOnyyWqwM5AXp0",
+    q: "xHYrzkivtmnz_sGchnWGc0q-pDOkKicptRpv2pMFIIXxnFX5aMeEXIZjVujXtwUy1UlFIN2GZJSvy5KJ79mu_XyNnFHMzedH-A3ee3u8h1UUrZF-vUu1_e4U_x67NN1dedzUSKynN7pFl3OkuShMBWGV-cwzOPdcVAfVuZlxUMc",
+    dp: "fBzDzYDUBmBQGop7Hn0dvf_T27V6RqpctWo074CQZcFbP2atFVtKSj3viWT3xid2VHzcgiDHdfpM3nEVlEO1wwIonGCSvdjGEOZiiFVOjrZAOVxA8guOjyyFvqbXke06VwPIIVvfKeSU2zuhbP__1tt6F_fxow4Kb2xonGT0GGk",
+    dq: "jmE2DiIPdhwDgLXAQpIaBqQ81bO3XfVT_LRULAwwwwlPuQV148H04zlh9TJ6Y2GZHYokV1U0eOBpJxfkb7dLYtpJpuiBjRf4yIUEoGlkkI_QlJnFSFr-YjGRdfNHqWBkxlSMZL770R9mIATndGkH7z5x-r9KwBZFC4FCG2hg_zE",
+    qi: "YCX_pLwbMBA1ThVH0WcwmnytqNcrMCEwTm7ByA2eU6nWbQrULvf7m9_kzfLUcjsnpAVlBQG5JMXMy0Sq4ptwbywsa5-G8KAOOOR2L3v4hC-Eys9ftgFM_3i0o40eeQH4b3haPbntrIeMg8IzlOuVYKf9-2QuKDoWeRdd7NsdxTk"
+};
+
+window.addEventListener("message", function(evt) {
+    debug("Key received in a message:");
+    key = evt.data;
+    shouldBe("key.type", "'private'");
+    shouldBe("key.extractable", "true");
+    shouldBe("key.algorithm.name", "'rsassa-pkcs1-v1_5'");
+    shouldBe("key.algorithm.modulusLength", "2048");
+    shouldBe("bytesToHexString(key.algorithm.publicExponent)", "'010001'");
+    shouldBe("key.usages", '["sign", "verify"]');
+
+    crypto.subtle.exportKey("jwk", key).then(function(result) {
+        exportedJWK = JSON.parse(bytesToASCIIString(result));
+        debug("\nExported back to JWK:");
+        shouldBe("exportedJWK.kty", "'RSA'");
+        shouldBe("exportedJWK.alg", "'RS256'");
+        shouldBe("exportedJWK.ext", "true");
+        shouldBe("exportedJWK.use", "'sig'");
+        shouldBe("exportedJWK.n", "privateKeyJSON.n");
+        shouldBe("exportedJWK.e", "privateKeyJSON.e");
+        shouldBe("exportedJWK.d", "privateKeyJSON.d");
+        shouldBe("exportedJWK.p", "privateKeyJSON.p");
+        shouldBe("exportedJWK.q", "privateKeyJSON.q");
+        shouldBe("exportedJWK.dp", "privateKeyJSON.dp");
+        shouldBe("exportedJWK.dq", "privateKeyJSON.dq");
+        shouldBe("exportedJWK.qi", "privateKeyJSON.qi");
+        debug("");
+
+        finishJSTest();
+    });
+}, false);
+
+crypto.subtle.importKey("jwk", asciiToUint8Array(JSON.stringify(privateKeyJSON)), null, true, ["sign", "verify"]).then(function(result) {
+    postMessage(result, "*");
+});
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
index ca7c483..2862326 100644 (file)
@@ -24,6 +24,7 @@ set(WebCore_INCLUDE_DIRECTORIES
     "${WEBCORE_DIR}/bridge"
     "${WEBCORE_DIR}/bridge/c"
     "${WEBCORE_DIR}/crypto"
+    "${WEBCORE_DIR}/crypto/keys"
     "${WEBCORE_DIR}/css"
     "${WEBCORE_DIR}/dom"
     "${WEBCORE_DIR}/dom/default"
index 46a39e9..f5a8a9a 100644 (file)
@@ -1,3 +1,71 @@
+2013-12-11  Alexey Proskuryakov  <ap@apple.com>
+
+        WebCrypto keys should support structured clone
+        https://bugs.webkit.org/show_bug.cgi?id=125590
+
+        Reviewed by Oliver Hunt.
+
+        Tests: crypto/subtle/aes-postMessage.html
+               crypto/subtle/hmac-postMessage.html
+               crypto/subtle/postMessage-worker.html
+               crypto/subtle/rsa-postMessage.html
+
+        * crypto/CryptoAlgorithmIdentifier.h:
+        (WebCore::CryptoAlgorithmIdentifier):
+        * bindings/js/JSCryptoAlgorithmDictionary.cpp:
+        (WebCore::JSCryptoAlgorithmDictionary::createParametersForEncrypt):
+        (WebCore::JSCryptoAlgorithmDictionary::createParametersForDecrypt):
+        (WebCore::JSCryptoAlgorithmDictionary::createParametersForSign):
+        (WebCore::JSCryptoAlgorithmDictionary::createParametersForVerify):
+        (WebCore::JSCryptoAlgorithmDictionary::createParametersForDigest):
+        (WebCore::JSCryptoAlgorithmDictionary::createParametersForGenerateKey):
+        (WebCore::JSCryptoAlgorithmDictionary::createParametersForDeriveKey):
+        (WebCore::JSCryptoAlgorithmDictionary::createParametersForDeriveBits):
+        (WebCore::JSCryptoAlgorithmDictionary::createParametersForImportKey):
+        (WebCore::JSCryptoAlgorithmDictionary::createParametersForExportKey):
+        AES_KW was added to WebCrypto spec editor's draft yesterday night. Now that we're
+        adding a matching enum for structired clone serialization, it's as good a time as
+        any to update the order of values to match.
+
+        * bindings/js/SerializedScriptValue.cpp:
+        (WebCore::countUsages):
+        (WebCore::CloneSerializer::dumpIfTerminal):
+        (WebCore::CloneSerializer::write):
+        (WebCore::CloneDeserializer::read):
+        (WebCore::CloneDeserializer::readHMACKey):
+        (WebCore::CloneDeserializer::readAESKey):
+        (WebCore::CloneDeserializer::readRSAKey):
+        (WebCore::CloneDeserializer::readCryptoKey):
+        (WebCore::CloneDeserializer::readTerminal):
+        Added serialization/deserialization for CryptoKey. This doesn't update version
+        number, because we don't currently store structured clones in persistent storage -
+        and even if we did, we wouldn't want to invalidate everything users already stored.
+
+        * crypto/CryptoAlgorithmRegistry.cpp:
+        (WebCore::CryptoAlgorithmRegistry::shared):
+        (WebCore::registryMutex):
+        (WebCore::CryptoAlgorithmRegistry::getIdentifierForName):
+        (WebCore::CryptoAlgorithmRegistry::nameForIdentifier):
+        (WebCore::CryptoAlgorithmRegistry::create):
+        (WebCore::CryptoAlgorithmRegistry::registerAlgorithm):
+        * crypto/CryptoKey.idl:
+        With structured clone, it is now possible to send a Key to a web worker. That's
+        of no practical use because the crypto API is not exposed in workers, but we
+        shouldn't crash anyway.
+
+        * crypto/keys/CryptoKeyAES.cpp:
+        (WebCore::CryptoKeyAES::CryptoKeyAES):
+        (WebCore::CryptoKeyAES::isValidAESAlgorithm):
+        * crypto/keys/CryptoKeyAES.h:
+        Exposed isValidAESAlgorithm, so that a caller could know whether the constructor
+        will assert.
+
+        * CMakeLists.txt:
+        * GNUmakefile.am:
+        * WebCore.vcxproj/WebCore.vcxproj.filters:
+        * WebCore.vcxproj/WebCoreCommon.props:
+        Added crypto/keys to search paths to avoid build breakage.
+
 2013-12-11  Bear Travis  <betravis@adobe.com>
 
         Web Inspector: [CSS Shapes] Highlight margin-shape for shape-outside
index 21a08fc..3190512 100644 (file)
@@ -33,6 +33,7 @@ webcore_cppflags += \
        -I$(srcdir)/Source/WebCore/bridge/c \
        -I$(srcdir)/Source/WebCore/bridge/jsc \
        -I$(srcdir)/Source/WebCore/crypto \
+       -I$(srcdir)/Source/WebCore/crypto/keys \
        -I$(srcdir)/Source/WebCore/css \
        -I$(srcdir)/Source/WebCore/dom \
        -I$(srcdir)/Source/WebCore/dom/default \
index ee2580f..29dc6f9 100644 (file)
     <Filter Include="crypto">
       <UniqueIdentifier>{02334427-19d6-44c8-a5d1-e1a67a9c4997}</UniqueIdentifier>
     </Filter>
+    <Filter Include="crypto\keys">
+      <UniqueIdentifier>{edd0faa6-bb8c-4c0e-b28a-064bde7e1eba}</UniqueIdentifier>
+    </Filter>
     <Filter Include="css">
       <UniqueIdentifier>{353b76ca-c49a-41da-88da-33dc422325ef}</UniqueIdentifier>
     </Filter>
index 67cd85d..8aeb05b 100644 (file)
@@ -7,7 +7,7 @@
   </PropertyGroup>
   <ItemDefinitionGroup>
     <ClCompile>
-      <AdditionalIncludeDirectories>$(ProjectDir)..;$(ProjectDir)..\Modules\mediacontrols;$(ProjectDir)..\Modules\mediastream;$(ProjectDir)..\Modules\filesystem;$(ProjectDir)..\Modules\geolocation;$(ProjectDir)..\Modules\indexeddb;$(ProjectDir)..\Modules\mediasource;$(ProjectDir)..\Modules\navigatorcontentutils;$(ProjectDir)..\Modules\plugins;$(ProjectDir)..\Modules\speech;$(ProjectDir)..\Modules\proximity;$(ProjectDir)..\Modules\quota;$(ProjectDir)..\Modules\notifications;$(ProjectDir)..\Modules\webdatabase;$(ProjectDir)..\Modules\websockets;$(ProjectDir)..\accessibility;$(ProjectDir)..\accessibility\win;$(ProjectDir)..\bridge;$(ProjectDir)..\bridge\c;$(ProjectDir)..\bridge\jsc;$(ProjectDir)..\css;$(ProjectDir)..\editing;$(ProjectDir)..\fileapi;$(ProjectDir)..\rendering;$(ProjectDir)..\rendering\line;$(ProjectDir)..\rendering\mathml;$(ProjectDir)..\rendering\shapes;$(ProjectDir)..\rendering\style;$(ProjectDir)..\rendering\svg;$(ProjectDir)..\bindings;$(ProjectDir)..\bindings\generic;$(ProjectDir)..\bindings\js;$(ProjectDir)..\bindings\js\specialization;$(ProjectDir)..\dom;$(ProjectDir)..\dom\default;$(ProjectDir)..\history;$(ProjectDir)..\html;$(ProjectDir)..\html\canvas;$(ProjectDir)..\html\forms;$(ProjectDir)..\html\parser;$(ProjectDir)..\html\shadow;$(ProjectDir)..\html\track;$(ProjectDir)..\inspector;$(ProjectDir)..\loader;$(ProjectDir)..\loader\appcache;$(ProjectDir)..\loader\archive;$(ProjectDir)..\loader\archive\cf;$(ProjectDir)..\loader\cache;$(ProjectDir)..\loader\icon;$(ProjectDir)..\mathml;$(ProjectDir)..\page;$(ProjectDir)..\page\animation;$(ProjectDir)..\page\scrolling;$(ProjectDir)..\page\win;$(ProjectDir)..\platform;$(ProjectDir)..\platform\animation;$(ProjectDir)..\platform\mock;$(ProjectDir)..\platform\sql;$(ProjectDir)..\platform\win;$(ProjectDir)..\platform\network;$(ProjectDir)..\platform\network\win;$(ProjectDir)..\platform\cf;$(ProjectDir)..\platform\graphics;$(ProjectDir)..\platform\graphics\ca;$(ProjectDir)..\platform\graphics\cpu\arm\filters;$(ProjectDir)..\platform\graphics\filters;$(ProjectDir)..\platform\graphics\filters\arm;$(ProjectDir)..\platform\graphics\opentype;$(ProjectDir)..\platform\graphics\transforms;$(ProjectDir)..\platform\text;$(ProjectDir)..\platform\text\transcoder;$(ProjectDir)..\platform\graphics\win;$(ProjectDir)..\xml;$(ProjectDir)..\xml\parser;$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\WebCore\DerivedSources;$(ProjectDir)..\plugins;$(ProjectDir)..\plugins\win;$(ProjectDir)..\svg\animation;$(ProjectDir)..\svg\graphics;$(ProjectDir)..\svg\properties;$(ProjectDir)..\svg\graphics\filters;$(ProjectDir)..\svg;$(ProjectDir)..\testing;$(ProjectDir)..\crypto;$(ProjectDir)..\wml;$(ProjectDir)..\storage;$(ProjectDir)..\style;$(ProjectDir)..\websockets;$(ProjectDir)..\workers;$(ConfigurationBuildDir)\include;$(ConfigurationBuildDir)\include\private;$(ConfigurationBuildDir)\include\JavaScriptCore;$(ConfigurationBuildDir)\include\private\JavaScriptCore;$(ProjectDir)..\ForwardingHeaders;$(ProjectDir)..\platform\graphics\gpu;$(ProjectDir)..\platform\graphics\egl;$(ProjectDir)..\platform\graphics\surfaces;$(ProjectDir)..\platform\graphics\surfaces\egl;$(ProjectDir)..\platform\graphics\opengl;$(WebKit_Libraries)\include;$(WebKit_Libraries)\include\private;$(WebKit_Libraries)\include\private\JavaScriptCore;$(WebKit_Libraries)\include\sqlite;$(WebKit_Libraries)\include\JavaScriptCore;$(WebKit_Libraries)\include\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories>$(ProjectDir)..;$(ProjectDir)..\Modules\mediacontrols;$(ProjectDir)..\Modules\mediastream;$(ProjectDir)..\Modules\filesystem;$(ProjectDir)..\Modules\geolocation;$(ProjectDir)..\Modules\indexeddb;$(ProjectDir)..\Modules\mediasource;$(ProjectDir)..\Modules\navigatorcontentutils;$(ProjectDir)..\Modules\plugins;$(ProjectDir)..\Modules\speech;$(ProjectDir)..\Modules\proximity;$(ProjectDir)..\Modules\quota;$(ProjectDir)..\Modules\notifications;$(ProjectDir)..\Modules\webdatabase;$(ProjectDir)..\Modules\websockets;$(ProjectDir)..\accessibility;$(ProjectDir)..\accessibility\win;$(ProjectDir)..\bridge;$(ProjectDir)..\bridge\c;$(ProjectDir)..\bridge\jsc;$(ProjectDir)..\css;$(ProjectDir)..\editing;$(ProjectDir)..\fileapi;$(ProjectDir)..\rendering;$(ProjectDir)..\rendering\line;$(ProjectDir)..\rendering\mathml;$(ProjectDir)..\rendering\shapes;$(ProjectDir)..\rendering\style;$(ProjectDir)..\rendering\svg;$(ProjectDir)..\bindings;$(ProjectDir)..\bindings\generic;$(ProjectDir)..\bindings\js;$(ProjectDir)..\bindings\js\specialization;$(ProjectDir)..\dom;$(ProjectDir)..\dom\default;$(ProjectDir)..\history;$(ProjectDir)..\html;$(ProjectDir)..\html\canvas;$(ProjectDir)..\html\forms;$(ProjectDir)..\html\parser;$(ProjectDir)..\html\shadow;$(ProjectDir)..\html\track;$(ProjectDir)..\inspector;$(ProjectDir)..\loader;$(ProjectDir)..\loader\appcache;$(ProjectDir)..\loader\archive;$(ProjectDir)..\loader\archive\cf;$(ProjectDir)..\loader\cache;$(ProjectDir)..\loader\icon;$(ProjectDir)..\mathml;$(ProjectDir)..\page;$(ProjectDir)..\page\animation;$(ProjectDir)..\page\scrolling;$(ProjectDir)..\page\win;$(ProjectDir)..\platform;$(ProjectDir)..\platform\animation;$(ProjectDir)..\platform\mock;$(ProjectDir)..\platform\sql;$(ProjectDir)..\platform\win;$(ProjectDir)..\platform\network;$(ProjectDir)..\platform\network\win;$(ProjectDir)..\platform\cf;$(ProjectDir)..\platform\graphics;$(ProjectDir)..\platform\graphics\ca;$(ProjectDir)..\platform\graphics\cpu\arm\filters;$(ProjectDir)..\platform\graphics\filters;$(ProjectDir)..\platform\graphics\filters\arm;$(ProjectDir)..\platform\graphics\opentype;$(ProjectDir)..\platform\graphics\transforms;$(ProjectDir)..\platform\text;$(ProjectDir)..\platform\text\transcoder;$(ProjectDir)..\platform\graphics\win;$(ProjectDir)..\xml;$(ProjectDir)..\xml\parser;$(ConfigurationBuildDir)\obj$(PlatformArchitecture)\WebCore\DerivedSources;$(ProjectDir)..\plugins;$(ProjectDir)..\plugins\win;$(ProjectDir)..\svg\animation;$(ProjectDir)..\svg\graphics;$(ProjectDir)..\svg\properties;$(ProjectDir)..\svg\graphics\filters;$(ProjectDir)..\svg;$(ProjectDir)..\testing;$(ProjectDir)..\crypto;$(ProjectDir)..\crypto\keys;$(ProjectDir)..\wml;$(ProjectDir)..\storage;$(ProjectDir)..\style;$(ProjectDir)..\websockets;$(ProjectDir)..\workers;$(ConfigurationBuildDir)\include;$(ConfigurationBuildDir)\include\private;$(ConfigurationBuildDir)\include\JavaScriptCore;$(ConfigurationBuildDir)\include\private\JavaScriptCore;$(ProjectDir)..\ForwardingHeaders;$(ProjectDir)..\platform\graphics\gpu;$(ProjectDir)..\platform\graphics\egl;$(ProjectDir)..\platform\graphics\surfaces;$(ProjectDir)..\platform\graphics\surfaces\egl;$(ProjectDir)..\platform\graphics\opengl;$(WebKit_Libraries)\include;$(WebKit_Libraries)\include\private;$(WebKit_Libraries)\include\private\JavaScriptCore;$(WebKit_Libraries)\include\sqlite;$(WebKit_Libraries)\include\JavaScriptCore;$(WebKit_Libraries)\include\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       <PreprocessorDefinitions>DISABLE_3D_RENDERING;WEBCORE_CONTEXT_MENUS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <PrecompiledHeader>Use</PrecompiledHeader>
       <PrecompiledHeaderFile>WebCorePrefix.h</PrecompiledHeaderFile>
index 40da947..74745a4 100644 (file)
@@ -317,6 +317,10 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::AES_CMAC:
     case CryptoAlgorithmIdentifier::AES_GCM:
     case CryptoAlgorithmIdentifier::AES_CFB:
+        setDOMException(exec, NOT_SUPPORTED_ERR);
+        return nullptr;
+    case CryptoAlgorithmIdentifier::AES_KW:
+        return std::make_unique<CryptoAlgorithmParameters>();
     case CryptoAlgorithmIdentifier::HMAC:
     case CryptoAlgorithmIdentifier::DH:
     case CryptoAlgorithmIdentifier::SHA_1:
@@ -329,8 +333,6 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::PBKDF2:
         setDOMException(exec, NOT_SUPPORTED_ERR);
         return nullptr;
-    case CryptoAlgorithmIdentifier::AES_KW:
-        return std::make_unique<CryptoAlgorithmParameters>();
     }
 }
 
@@ -354,6 +356,10 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::AES_CMAC:
     case CryptoAlgorithmIdentifier::AES_GCM:
     case CryptoAlgorithmIdentifier::AES_CFB:
+        setDOMException(exec, NOT_SUPPORTED_ERR);
+        return nullptr;
+    case CryptoAlgorithmIdentifier::AES_KW:
+        return std::make_unique<CryptoAlgorithmParameters>();
     case CryptoAlgorithmIdentifier::HMAC:
     case CryptoAlgorithmIdentifier::DH:
     case CryptoAlgorithmIdentifier::SHA_1:
@@ -366,8 +372,6 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::PBKDF2:
         setDOMException(exec, NOT_SUPPORTED_ERR);
         return nullptr;
-    case CryptoAlgorithmIdentifier::AES_KW:
-        return std::make_unique<CryptoAlgorithmParameters>();
     }
 }
 
@@ -388,6 +392,7 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::AES_CMAC:
     case CryptoAlgorithmIdentifier::AES_GCM:
     case CryptoAlgorithmIdentifier::AES_CFB:
+    case CryptoAlgorithmIdentifier::AES_KW:
         setDOMException(exec, NOT_SUPPORTED_ERR);
         return nullptr;
     case CryptoAlgorithmIdentifier::HMAC:
@@ -401,7 +406,6 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::CONCAT:
     case CryptoAlgorithmIdentifier::HKDF_CTR:
     case CryptoAlgorithmIdentifier::PBKDF2:
-    case CryptoAlgorithmIdentifier::AES_KW:
         setDOMException(exec, NOT_SUPPORTED_ERR);
         return nullptr;
     }
@@ -424,6 +428,7 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::AES_CMAC:
     case CryptoAlgorithmIdentifier::AES_GCM:
     case CryptoAlgorithmIdentifier::AES_CFB:
+    case CryptoAlgorithmIdentifier::AES_KW:
         setDOMException(exec, NOT_SUPPORTED_ERR);
         return nullptr;
     case CryptoAlgorithmIdentifier::HMAC:
@@ -437,7 +442,6 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::CONCAT:
     case CryptoAlgorithmIdentifier::HKDF_CTR:
     case CryptoAlgorithmIdentifier::PBKDF2:
-    case CryptoAlgorithmIdentifier::AES_KW:
         setDOMException(exec, NOT_SUPPORTED_ERR);
         return nullptr;
     }
@@ -457,6 +461,7 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::AES_CMAC:
     case CryptoAlgorithmIdentifier::AES_GCM:
     case CryptoAlgorithmIdentifier::AES_CFB:
+    case CryptoAlgorithmIdentifier::AES_KW:
     case CryptoAlgorithmIdentifier::HMAC:
     case CryptoAlgorithmIdentifier::DH:
         setDOMException(exec, NOT_SUPPORTED_ERR);
@@ -470,7 +475,6 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::CONCAT:
     case CryptoAlgorithmIdentifier::HKDF_CTR:
     case CryptoAlgorithmIdentifier::PBKDF2:
-    case CryptoAlgorithmIdentifier::AES_KW:
         setDOMException(exec, NOT_SUPPORTED_ERR);
         return nullptr;
     }
@@ -493,6 +497,7 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::AES_CMAC:
     case CryptoAlgorithmIdentifier::AES_GCM:
     case CryptoAlgorithmIdentifier::AES_CFB:
+    case CryptoAlgorithmIdentifier::AES_KW:
         return createAesKeyGenParams(exec, value);
     case CryptoAlgorithmIdentifier::HMAC:
         return createHmacKeyParams(exec, value);
@@ -507,8 +512,6 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::PBKDF2:
         setDOMException(exec, NOT_SUPPORTED_ERR);
         return nullptr;
-    case CryptoAlgorithmIdentifier::AES_KW:
-        return createAesKeyGenParams(exec, value);
     }
 }
 
@@ -526,6 +529,7 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::AES_CMAC:
     case CryptoAlgorithmIdentifier::AES_GCM:
     case CryptoAlgorithmIdentifier::AES_CFB:
+    case CryptoAlgorithmIdentifier::AES_KW:
     case CryptoAlgorithmIdentifier::HMAC:
     case CryptoAlgorithmIdentifier::DH:
     case CryptoAlgorithmIdentifier::SHA_1:
@@ -536,7 +540,6 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::CONCAT:
     case CryptoAlgorithmIdentifier::HKDF_CTR:
     case CryptoAlgorithmIdentifier::PBKDF2:
-    case CryptoAlgorithmIdentifier::AES_KW:
         setDOMException(exec, NOT_SUPPORTED_ERR);
         return nullptr;
     }
@@ -556,6 +559,7 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::AES_CMAC:
     case CryptoAlgorithmIdentifier::AES_GCM:
     case CryptoAlgorithmIdentifier::AES_CFB:
+    case CryptoAlgorithmIdentifier::AES_KW:
     case CryptoAlgorithmIdentifier::HMAC:
     case CryptoAlgorithmIdentifier::DH:
     case CryptoAlgorithmIdentifier::SHA_1:
@@ -566,7 +570,6 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::CONCAT:
     case CryptoAlgorithmIdentifier::HKDF_CTR:
     case CryptoAlgorithmIdentifier::PBKDF2:
-    case CryptoAlgorithmIdentifier::AES_KW:
         setDOMException(exec, NOT_SUPPORTED_ERR);
         return nullptr;
     }
@@ -590,6 +593,7 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::AES_CMAC:
     case CryptoAlgorithmIdentifier::AES_GCM:
     case CryptoAlgorithmIdentifier::AES_CFB:
+    case CryptoAlgorithmIdentifier::AES_KW:
         return std::make_unique<CryptoAlgorithmParameters>();
     case CryptoAlgorithmIdentifier::HMAC:
         return createHmacParams(exec, value);
@@ -605,8 +609,6 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::PBKDF2:
         setDOMException(exec, NOT_SUPPORTED_ERR);
         return nullptr;
-    case CryptoAlgorithmIdentifier::AES_KW:
-        return std::make_unique<CryptoAlgorithmParameters>();
     }
 }
 
@@ -624,6 +626,7 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::AES_CMAC:
     case CryptoAlgorithmIdentifier::AES_GCM:
     case CryptoAlgorithmIdentifier::AES_CFB:
+    case CryptoAlgorithmIdentifier::AES_KW:
     case CryptoAlgorithmIdentifier::HMAC:
     case CryptoAlgorithmIdentifier::DH:
         return std::make_unique<CryptoAlgorithmParameters>();
@@ -637,8 +640,6 @@ std::unique_ptr<CryptoAlgorithmParameters> JSCryptoAlgorithmDictionary::createPa
     case CryptoAlgorithmIdentifier::PBKDF2:
         setDOMException(exec, NOT_SUPPORTED_ERR);
         return nullptr;
-    case CryptoAlgorithmIdentifier::AES_KW:
-        return std::make_unique<CryptoAlgorithmParameters>();
     }
 }
 
index 6f86c8b..26d8e3b 100644 (file)
 #include "SerializedScriptValue.h"
 
 #include "Blob.h"
+#include "CryptoKeyAES.h"
+#include "CryptoKeyDataOctetSequence.h"
+#include "CryptoKeyDataRSAComponents.h"
+#include "CryptoKeyHMAC.h"
+#include "CryptoKeyRSA.h"
 #include "ExceptionCode.h"
 #include "File.h"
 #include "FileList.h"
 #include "ImageData.h"
 #include "JSBlob.h"
+#include "JSCryptoKey.h"
 #include "JSDOMGlobalObject.h"
 #include "JSFile.h"
 #include "JSFileList.h"
@@ -117,6 +123,9 @@ enum SerializationTag {
     SetObjectTag = 29,
     MapObjectTag = 30,
     NonMapPropertiesTag = 31,
+#if ENABLE(SUBTLE_CRYPTO)
+    CryptoKeyTag = 32,
+#endif
     ErrorTag = 255
 };
 
@@ -156,6 +165,72 @@ static unsigned typedArrayElementSize(ArrayBufferViewSubtag tag)
 
 }
 
+#if ENABLE(SUBTLE_CRYPTO)
+
+ENUM_CLASS(CryptoKeyClassSubtag) {
+    HMAC = 0,
+    AES = 1,
+    RSA = 2
+};
+const uint8_t cryptoKeyClassSubtagMaximumValue = 2;
+
+ENUM_CLASS(CryptoKeyAsymmetricTypeSubtag) {
+    Public = 0,
+    Private = 1
+};
+const uint8_t cryptoKeyAsymmetricTypeSubtagMaximumValue = 1;
+
+ENUM_CLASS(CryptoKeyUsageTag) {
+    Encrypt = 0,
+    Decrypt = 1,
+    Sign = 2,
+    Verify = 3,
+    DeriveKey = 4,
+    DeriveBits = 5,
+    WrapKey = 6,
+    UnwrapKey = 7
+};
+const uint8_t cryptoKeyUsageTagMaximumValue = 7;
+
+ENUM_CLASS(CryptoAlgorithmIdentifierTag) {
+    RSAES_PKCS1_v1_5 = 0,
+    RSASSA_PKCS1_v1_5 = 1,
+    RSA_PSS = 2,
+    RSA_OAEP = 3,
+    ECDSA = 4,
+    ECDH = 5,
+    AES_CTR = 6,
+    AES_CBC = 7,
+    AES_CMAC = 8,
+    AES_GCM = 9,
+    AES_CFB = 10,
+    AES_KW = 11,
+    HMAC = 12,
+    DH = 13,
+    SHA_1 = 14,
+    SHA_224 = 15,
+    SHA_256 = 16,
+    SHA_384 = 17,
+    SHA_512 = 18,
+    CONCAT = 19,
+    HKDF_CTR = 20,
+    PBKDF2 = 21,
+};
+const uint8_t cryptoAlgorithmIdentifierTagMaximumValue = 21;
+
+static unsigned countUsages(CryptoKeyUsage usages)
+{
+    // Fast bit count algorithm for sparse bit maps.
+    unsigned count = 0;
+    while (usages) {
+        usages = usages & (usages - 1);
+        ++count;
+    }
+    return count;
+}
+
+#endif
+
 /* CurrentVersion tracks the serialization version so that persistent stores
  * are able to correctly bail out in the case of encountering newer formats.
  *
@@ -217,8 +292,9 @@ static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
  *    | ObjectReference
  *    | MessagePortReferenceTag <value:uint32_t>
  *    | ArrayBuffer
- *    | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint32_t> <byteLenght:uint32_t> (ArrayBuffer | ObjectReference)
+ *    | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint32_t> <byteLength:uint32_t> (ArrayBuffer | ObjectReference)
  *    | ArrayBufferTransferTag <value:uint32_t>
+ *    | CryptoKeyTag <extractable:int32_t> <usagesCount:uint32_t> <usages:byte{usagesCount}> CryptoKeyClassSubtag (CryptoKeyHMAC | CryptoKeyAES | CryptoKeyRSA)
  *
  * String :-
  *      EmptyStringTag
@@ -255,6 +331,28 @@ static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
  *
  * ArrayBuffer :-
  *    ArrayBufferTag <length:uint32_t> <contents:byte{length}>
+ *
+ * CryptoKeyHMAC :-
+ *    <keySize:uint32_t> <keyData:byte{keySize}> CryptoAlgorithmIdentifierTag // Algorithm tag inner hash function.
+ *
+ * CryptoKeyAES :-
+ *    CryptoAlgorithmIdentifierTag <keySize:uint32_t> <keyData:byte{keySize}>
+ *
+ * CryptoKeyRSA :-
+ *    CryptoAlgorithmIdentifierTag <isRestrictedToHash:int32_t> CryptoAlgorithmIdentifierTag? CryptoKeyAsymmetricTypeSubtag CryptoKeyRSAPublicComponents CryptoKeyRSAPrivateComponents?
+ *
+ * CryptoKeyRSAPublicComponents :-
+ *    <modulusSize:uint32_t> <modulus:byte{modulusSize}> <exponentSize:uint32_t> <exponent:byte{exponentSize}>
+ *
+ * CryptoKeyRSAPrivateComponents :-
+ *    <privateExponentSize:uint32_t> <privateExponent:byte{privateExponentSize}> <primeCount:uint32_t> FirstPrimeInfo? PrimeInfo{primeCount - 1}
+ *
+ * // CRT data could be computed from prime factors. It is only serialized to reuse a code path that's needed for JWK.
+ * FirstPrimeInfo :-
+ *    <factorSize:uint32_t> <factor:byte{factorSize}> <crtExponentSize:uint32_t> <crtExponent:byte{crtExponentSize}>
+ *
+ * PrimeInfo :-
+ *    <factorSize:uint32_t> <factor:byte{factorSize}> <crtExponentSize:uint32_t> <crtExponent:byte{crtExponentSize}> <crtCoefficientSize:uint32_t> <crtCoefficient:byte{crtCoefficientSize}>
  */
 
 typedef pair<JSC::JSValue, SerializationReturnCode> DeserializationResult;
@@ -724,6 +822,13 @@ private:
                 recordObject(obj);
                 return success;
             }
+#if ENABLE(SUBTLE_CRYPTO)
+            if (CryptoKey* key = toCryptoKey(obj)) {
+                write(CryptoKeyTag);
+                write(key);
+                return true;
+            }
+#endif
 
             return false;
         }
@@ -742,6 +847,28 @@ private:
         writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
     }
 
+#if ENABLE(SUBTLE_CRYPTO)
+    void write(CryptoKeyClassSubtag tag)
+    {
+        writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
+    }
+
+    void write(CryptoKeyAsymmetricTypeSubtag tag)
+    {
+        writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
+    }
+
+    void write(CryptoKeyUsageTag tag)
+    {
+        writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
+    }
+
+    void write(CryptoAlgorithmIdentifierTag tag)
+    {
+        writeLittleEndian<uint8_t>(m_buffer, static_cast<uint8_t>(tag));
+    }
+#endif
+
     void write(uint8_t c)
     {
         writeLittleEndian(m_buffer, c);
@@ -834,6 +961,13 @@ private:
             write(Identifier(m_exec, str));
     }
 
+    void write(const Vector<uint8_t>& vector)
+    {
+        uint32_t size = vector.size();
+        write(size);
+        writeLittleEndian(m_buffer, vector.data(), size);
+    }
+
     void write(const File* file)
     {
         m_blobURLs.append(file->url());
@@ -842,6 +976,166 @@ private:
         write(file->type());
     }
 
+#if ENABLE(SUBTLE_CRYPTO)
+    void write(CryptoAlgorithmIdentifier algorithm)
+    {
+        switch (algorithm) {
+        case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
+            write(CryptoAlgorithmIdentifierTag::RSAES_PKCS1_v1_5);
+            break;
+        case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+            write(CryptoAlgorithmIdentifierTag::RSASSA_PKCS1_v1_5);
+            break;
+        case CryptoAlgorithmIdentifier::RSA_PSS:
+            write(CryptoAlgorithmIdentifierTag::RSA_PSS);
+            break;
+        case CryptoAlgorithmIdentifier::RSA_OAEP:
+            write(CryptoAlgorithmIdentifierTag::RSA_OAEP);
+            break;
+        case CryptoAlgorithmIdentifier::ECDSA:
+            write(CryptoAlgorithmIdentifierTag::ECDSA);
+            break;
+        case CryptoAlgorithmIdentifier::ECDH:
+            write(CryptoAlgorithmIdentifierTag::ECDH);
+            break;
+        case CryptoAlgorithmIdentifier::AES_CTR:
+            write(CryptoAlgorithmIdentifierTag::AES_CTR);
+            break;
+        case CryptoAlgorithmIdentifier::AES_CBC:
+            write(CryptoAlgorithmIdentifierTag::AES_CBC);
+            break;
+        case CryptoAlgorithmIdentifier::AES_CMAC:
+            write(CryptoAlgorithmIdentifierTag::AES_CMAC);
+            break;
+        case CryptoAlgorithmIdentifier::AES_GCM:
+            write(CryptoAlgorithmIdentifierTag::AES_GCM);
+            break;
+        case CryptoAlgorithmIdentifier::AES_CFB:
+            write(CryptoAlgorithmIdentifierTag::AES_CFB);
+            break;
+        case CryptoAlgorithmIdentifier::AES_KW:
+            write(CryptoAlgorithmIdentifierTag::AES_KW);
+            break;
+        case CryptoAlgorithmIdentifier::HMAC:
+            write(CryptoAlgorithmIdentifierTag::HMAC);
+            break;
+        case CryptoAlgorithmIdentifier::DH:
+            write(CryptoAlgorithmIdentifierTag::DH);
+            break;
+        case CryptoAlgorithmIdentifier::SHA_1:
+            write(CryptoAlgorithmIdentifierTag::SHA_1);
+            break;
+        case CryptoAlgorithmIdentifier::SHA_224:
+            write(CryptoAlgorithmIdentifierTag::SHA_224);
+            break;
+        case CryptoAlgorithmIdentifier::SHA_256:
+            write(CryptoAlgorithmIdentifierTag::SHA_256);
+            break;
+        case CryptoAlgorithmIdentifier::SHA_384:
+            write(CryptoAlgorithmIdentifierTag::SHA_384);
+            break;
+        case CryptoAlgorithmIdentifier::SHA_512:
+            write(CryptoAlgorithmIdentifierTag::SHA_512);
+            break;
+        case CryptoAlgorithmIdentifier::CONCAT:
+            write(CryptoAlgorithmIdentifierTag::CONCAT);
+            break;
+        case CryptoAlgorithmIdentifier::HKDF_CTR:
+            write(CryptoAlgorithmIdentifierTag::HKDF_CTR);
+            break;
+        case CryptoAlgorithmIdentifier::PBKDF2:
+            write(CryptoAlgorithmIdentifierTag::PBKDF2);
+            break;
+        }
+    }
+
+    void write(CryptoKeyDataRSAComponents::Type type)
+    {
+        switch (type) {
+        case CryptoKeyDataRSAComponents::Type::Public:
+            write(CryptoKeyAsymmetricTypeSubtag::Public);
+            return;
+        case CryptoKeyDataRSAComponents::Type::Private:
+            write(CryptoKeyAsymmetricTypeSubtag::Private);
+            return;
+        }
+    }
+
+    void write(const CryptoKeyDataRSAComponents& key)
+    {
+        write(key.type());
+        write(key.modulus());
+        write(key.exponent());
+        if (key.type() == CryptoKeyDataRSAComponents::Type::Public)
+            return;
+
+        write(key.privateExponent());
+
+        unsigned primeCount = key.hasAdditionalPrivateKeyParameters() ? key.otherPrimeInfos().size() + 2 : 0;
+        write(primeCount);
+        if (!primeCount)
+            return;
+
+        write(key.firstPrimeInfo().primeFactor);
+        write(key.firstPrimeInfo().factorCRTExponent);
+        write(key.secondPrimeInfo().primeFactor);
+        write(key.secondPrimeInfo().factorCRTExponent);
+        write(key.secondPrimeInfo().factorCRTCoefficient);
+        for (unsigned i = 2; i < primeCount; ++i) {
+            write(key.otherPrimeInfos()[i].primeFactor);
+            write(key.otherPrimeInfos()[i].factorCRTExponent);
+            write(key.otherPrimeInfos()[i].factorCRTCoefficient);
+        }
+    }
+
+    void write(const CryptoKey* key)
+    {
+        write(key->extractable());
+
+        CryptoKeyUsage usages = key->usagesBitmap();
+        write(countUsages(usages));
+        if (usages & CryptoKeyUsageEncrypt)
+            write(CryptoKeyUsageTag::Encrypt);
+        if (usages & CryptoKeyUsageDecrypt)
+            write(CryptoKeyUsageTag::Decrypt);
+        if (usages & CryptoKeyUsageSign)
+            write(CryptoKeyUsageTag::Sign);
+        if (usages & CryptoKeyUsageVerify)
+            write(CryptoKeyUsageTag::Verify);
+        if (usages & CryptoKeyUsageDeriveKey)
+            write(CryptoKeyUsageTag::DeriveKey);
+        if (usages & CryptoKeyUsageDeriveBits)
+            write(CryptoKeyUsageTag::DeriveBits);
+        if (usages & CryptoKeyUsageWrapKey)
+            write(CryptoKeyUsageTag::WrapKey);
+        if (usages & CryptoKeyUsageUnwrapKey)
+            write(CryptoKeyUsageTag::UnwrapKey);
+
+        switch (key->keyClass()) {
+        case CryptoKeyClass::HMAC:
+            write(CryptoKeyClassSubtag::HMAC);
+            write(toCryptoKeyHMAC(key)->key());
+            write(toCryptoKeyHMAC(key)->hashAlgorithmIdentifier());
+            break;
+        case CryptoKeyClass::AES:
+            write(CryptoKeyClassSubtag::AES);
+            write(key->algorithmIdentifier());
+            write(toCryptoKeyAES(key)->key());
+            break;
+        case CryptoKeyClass::RSA:
+            write(CryptoKeyClassSubtag::RSA);
+            write(key->algorithmIdentifier());
+            CryptoAlgorithmIdentifier hash;
+            bool isRestrictedToHash = toCryptoKeyRSA(key)->isRestrictedToHash(hash);
+            write(isRestrictedToHash);
+            if (isRestrictedToHash)
+                write(hash);
+            write(toCryptoKeyDataRSAComponents(*key->exportData()));
+            break;
+        }
+    }
+#endif
+
     void write(const uint8_t* data, unsigned length)
     {
         m_buffer.append(data, length);
@@ -1453,6 +1747,307 @@ private:
         }
     }
 
+    bool read(Vector<uint8_t>& result)
+    {
+        ASSERT(result.isEmpty());
+        uint32_t size;
+        if (!read(size))
+            return false;
+        if (m_ptr + size > m_end)
+            return false;
+        result.append(m_ptr, size);
+        m_ptr += size;
+        return true;
+    }
+
+#if ENABLE(SUBTLE_CRYPTO)
+    bool read(CryptoAlgorithmIdentifier& result)
+    {
+        uint8_t algorithmTag;
+        if (!read(algorithmTag))
+            return false;
+        if (algorithmTag > cryptoAlgorithmIdentifierTagMaximumValue)
+            return false;
+        switch (static_cast<CryptoAlgorithmIdentifierTag>(algorithmTag)) {
+        case CryptoAlgorithmIdentifierTag::RSAES_PKCS1_v1_5:
+            result = CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5;
+            break;
+        case CryptoAlgorithmIdentifierTag::RSASSA_PKCS1_v1_5:
+            result = CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5;
+            break;
+        case CryptoAlgorithmIdentifierTag::RSA_PSS:
+            result = CryptoAlgorithmIdentifier::RSA_PSS;
+            break;
+        case CryptoAlgorithmIdentifierTag::RSA_OAEP:
+            result = CryptoAlgorithmIdentifier::RSA_OAEP;
+            break;
+        case CryptoAlgorithmIdentifierTag::ECDSA:
+            result = CryptoAlgorithmIdentifier::ECDSA;
+            break;
+        case CryptoAlgorithmIdentifierTag::ECDH:
+            result = CryptoAlgorithmIdentifier::ECDH;
+            break;
+        case CryptoAlgorithmIdentifierTag::AES_CTR:
+            result = CryptoAlgorithmIdentifier::AES_CTR;
+            break;
+        case CryptoAlgorithmIdentifierTag::AES_CBC:
+            result = CryptoAlgorithmIdentifier::AES_CBC;
+            break;
+        case CryptoAlgorithmIdentifierTag::AES_CMAC:
+            result = CryptoAlgorithmIdentifier::AES_CMAC;
+            break;
+        case CryptoAlgorithmIdentifierTag::AES_GCM:
+            result = CryptoAlgorithmIdentifier::AES_GCM;
+            break;
+        case CryptoAlgorithmIdentifierTag::AES_CFB:
+            result = CryptoAlgorithmIdentifier::AES_CFB;
+            break;
+        case CryptoAlgorithmIdentifierTag::AES_KW:
+            result = CryptoAlgorithmIdentifier::AES_KW;
+            break;
+        case CryptoAlgorithmIdentifierTag::HMAC:
+            result = CryptoAlgorithmIdentifier::HMAC;
+            break;
+        case CryptoAlgorithmIdentifierTag::DH:
+            result = CryptoAlgorithmIdentifier::DH;
+            break;
+        case CryptoAlgorithmIdentifierTag::SHA_1:
+            result = CryptoAlgorithmIdentifier::SHA_1;
+            break;
+        case CryptoAlgorithmIdentifierTag::SHA_224:
+            result = CryptoAlgorithmIdentifier::SHA_224;
+            break;
+        case CryptoAlgorithmIdentifierTag::SHA_256:
+            result = CryptoAlgorithmIdentifier::SHA_256;
+            break;
+        case CryptoAlgorithmIdentifierTag::SHA_384:
+            result = CryptoAlgorithmIdentifier::SHA_384;
+            break;
+        case CryptoAlgorithmIdentifierTag::SHA_512:
+            result = CryptoAlgorithmIdentifier::SHA_512;
+            break;
+        case CryptoAlgorithmIdentifierTag::CONCAT:
+            result = CryptoAlgorithmIdentifier::CONCAT;
+            break;
+        case CryptoAlgorithmIdentifierTag::HKDF_CTR:
+            result = CryptoAlgorithmIdentifier::HKDF_CTR;
+            break;
+        case CryptoAlgorithmIdentifierTag::PBKDF2:
+            result = CryptoAlgorithmIdentifier::PBKDF2;
+            break;
+        }
+        return true;
+    }
+
+    bool read(CryptoKeyClassSubtag& result)
+    {
+        uint8_t tag;
+        if (!read(tag))
+            return false;
+        if (tag > cryptoKeyClassSubtagMaximumValue)
+            return false;
+        result = static_cast<CryptoKeyClassSubtag>(tag);
+        return true;
+    }
+
+    bool read(CryptoKeyUsageTag& result)
+    {
+        uint8_t tag;
+        if (!read(tag))
+            return false;
+        if (tag > cryptoKeyUsageTagMaximumValue)
+            return false;
+        result = static_cast<CryptoKeyUsageTag>(tag);
+        return true;
+    }
+
+    bool read(CryptoKeyAsymmetricTypeSubtag& result)
+    {
+        uint8_t tag;
+        if (!read(tag))
+            return false;
+        if (tag > cryptoKeyAsymmetricTypeSubtagMaximumValue)
+            return false;
+        result = static_cast<CryptoKeyAsymmetricTypeSubtag>(tag);
+        return true;
+    }
+
+    bool readHMACKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result)
+    {
+        Vector<uint8_t> keyData;
+        if (!read(keyData))
+            return false;
+        CryptoAlgorithmIdentifier hash;
+        if (!read(hash))
+            return false;
+        result = CryptoKeyHMAC::create(keyData, hash, extractable, usages);
+        return true;
+    }
+
+    bool readAESKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result)
+    {
+        CryptoAlgorithmIdentifier algorithm;
+        if (!read(algorithm))
+            return false;
+        if (!CryptoKeyAES::isValidAESAlgorithm(algorithm))
+            return false;
+        Vector<uint8_t> keyData;
+        if (!read(keyData))
+            return false;
+        result = CryptoKeyAES::create(algorithm, keyData, extractable, usages);
+        return true;
+    }
+
+    bool readRSAKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result)
+    {
+        CryptoAlgorithmIdentifier algorithm;
+        if (!read(algorithm))
+            return false;
+
+        int32_t isRestrictedToHash;
+        CryptoAlgorithmIdentifier hash;
+        if (!read(isRestrictedToHash))
+            return false;
+        if (isRestrictedToHash && !read(hash))
+            return false;
+
+        CryptoKeyAsymmetricTypeSubtag type;
+        if (!read(type))
+            return false;
+
+        Vector<uint8_t> modulus;
+        if (!read(modulus))
+            return false;
+        Vector<uint8_t> exponent;
+        if (!read(exponent))
+            return false;
+
+        if (type == CryptoKeyAsymmetricTypeSubtag::Public) {
+            auto keyData = CryptoKeyDataRSAComponents::createPublic(modulus, exponent);
+            auto key = CryptoKeyRSA::create(algorithm, *keyData, extractable, usages);
+            if (isRestrictedToHash)
+                key->restrictToHash(hash);
+            result = std::move(key);
+            return true;
+        }
+
+        Vector<uint8_t> privateExponent;
+        if (!read(privateExponent))
+            return false;
+
+        uint32_t primeCount;
+        if (!read(primeCount))
+            return false;
+
+        if (!primeCount) {
+            auto keyData = CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent);
+            auto key = CryptoKeyRSA::create(algorithm, *keyData, extractable, usages);
+            if (isRestrictedToHash)
+                key->restrictToHash(hash);
+            result = std::move(key);
+            return true;
+        }
+
+        if (primeCount < 2)
+            return false;
+
+        CryptoKeyDataRSAComponents::PrimeInfo firstPrimeInfo;
+        CryptoKeyDataRSAComponents::PrimeInfo secondPrimeInfo;
+        Vector<CryptoKeyDataRSAComponents::PrimeInfo> otherPrimeInfos(primeCount - 2);
+
+        if (!read(firstPrimeInfo.primeFactor))
+            return false;
+        if (!read(firstPrimeInfo.factorCRTExponent))
+            return false;
+        if (!read(secondPrimeInfo.primeFactor))
+            return false;
+        if (!read(secondPrimeInfo.factorCRTExponent))
+            return false;
+        if (!read(secondPrimeInfo.factorCRTCoefficient))
+            return false;
+        for (unsigned i = 2; i < primeCount; ++i) {
+            if (!read(otherPrimeInfos[i].primeFactor))
+                return false;
+            if (!read(otherPrimeInfos[i].factorCRTExponent))
+                return false;
+            if (!read(otherPrimeInfos[i].factorCRTCoefficient))
+                return false;
+        }
+
+        auto keyData = CryptoKeyDataRSAComponents::createPrivateWithAdditionalData(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos);
+        auto key = CryptoKeyRSA::create(algorithm, *keyData, extractable, usages);
+        if (isRestrictedToHash)
+            key->restrictToHash(hash);
+        result = std::move(key);
+        return true;
+    }
+
+    bool readCryptoKey(JSValue& cryptoKey)
+    {
+        int32_t extractable;
+        if (!read(extractable))
+            return false;
+
+        uint32_t usagesCount;
+        if (!read(usagesCount))
+            return false;
+
+        CryptoKeyUsage usages = 0;
+        for (uint32_t i = 0; i < usagesCount; ++i) {
+            CryptoKeyUsageTag usage;
+            if (!read(usage))
+                return false;
+            switch (usage) {
+            case CryptoKeyUsageTag::Encrypt:
+                usages |= CryptoKeyUsageEncrypt;
+                break;
+            case CryptoKeyUsageTag::Decrypt:
+                usages |= CryptoKeyUsageDecrypt;
+                break;
+            case CryptoKeyUsageTag::Sign:
+                usages |= CryptoKeyUsageSign;
+                break;
+            case CryptoKeyUsageTag::Verify:
+                usages |= CryptoKeyUsageVerify;
+                break;
+            case CryptoKeyUsageTag::DeriveKey:
+                usages |= CryptoKeyUsageDeriveKey;
+                break;
+            case CryptoKeyUsageTag::DeriveBits:
+                usages |= CryptoKeyUsageDeriveBits;
+                break;
+            case CryptoKeyUsageTag::WrapKey:
+                usages |= CryptoKeyUsageWrapKey;
+                break;
+            case CryptoKeyUsageTag::UnwrapKey:
+                usages |= CryptoKeyUsageUnwrapKey;
+                break;
+            }
+        }
+
+        CryptoKeyClassSubtag cryptoKeyClass;
+        if (!read(cryptoKeyClass))
+            return false;
+        RefPtr<CryptoKey> result;
+        switch (cryptoKeyClass) {
+        case CryptoKeyClassSubtag::HMAC:
+            if (!readHMACKey(extractable, usages, result))
+                return false;
+            break;
+        case CryptoKeyClassSubtag::AES:
+            if (!readAESKey(extractable, usages, result))
+                return false;
+            break;
+        case CryptoKeyClassSubtag::RSA:
+            if (!readRSAKey(extractable, usages, result))
+                return false;
+            break;
+        }
+        cryptoKey = getJSValue(result.get());
+        return true;
+    }
+#endif
+
     template<class T>
     JSValue getJSValue(T* nativeObj)
     {
@@ -1658,6 +2253,17 @@ private:
             m_gcBuffer.append(arrayBufferView);
             return arrayBufferView;
         }
+#if ENABLE(SUBTLE_CRYPTO)
+        case CryptoKeyTag: {
+            JSValue cryptoKey;
+            if (!readCryptoKey(cryptoKey)) {
+                fail();
+                return JSValue();
+            }
+            m_gcBuffer.append(cryptoKey);
+            return cryptoKey;
+        }
+#endif
         default:
             m_ptr--; // Push the tag back
             return JSValue();
index 52822e1..862453e 100644 (file)
@@ -42,6 +42,7 @@ ENUM_CLASS(CryptoAlgorithmIdentifier) {
     AES_CMAC,
     AES_GCM,
     AES_CFB,
+    AES_KW,
     HMAC,
     DH,
     SHA_1,
@@ -51,8 +52,7 @@ ENUM_CLASS(CryptoAlgorithmIdentifier) {
     SHA_512,
     CONCAT,
     HKDF_CTR,
-    PBKDF2,
-    AES_KW // Not yet standardized.
+    PBKDF2
 };
 
 }
index 2934d71..5d79b0c 100644 (file)
@@ -35,11 +35,16 @@ namespace WebCore {
 
 CryptoAlgorithmRegistry& CryptoAlgorithmRegistry::shared()
 {
-    ASSERT(isMainThread());
     DEFINE_STATIC_LOCAL(CryptoAlgorithmRegistry, registry, ());
     return registry;
 }
 
+static Mutex& registryMutex()
+{
+    AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
+    return mutex;
+}
+
 CryptoAlgorithmRegistry::CryptoAlgorithmRegistry()
 {
     platformRegisterAlgorithms();
@@ -50,7 +55,9 @@ bool CryptoAlgorithmRegistry::getIdentifierForName(const String& name, CryptoAlg
     if (name.isEmpty())
         return false;
 
-    auto iter = m_nameToIdentifierMap.find(name.lower());
+    MutexLocker lock(registryMutex());
+
+    auto iter = m_nameToIdentifierMap.find(name.isolatedCopy().lower());
     if (iter == m_nameToIdentifierMap.end())
         return false;
 
@@ -60,11 +67,15 @@ bool CryptoAlgorithmRegistry::getIdentifierForName(const String& name, CryptoAlg
 
 String CryptoAlgorithmRegistry::nameForIdentifier(CryptoAlgorithmIdentifier identifier)
 {
-    return m_identifierToNameMap.get(static_cast<unsigned>(identifier));
+    MutexLocker lock(registryMutex());
+
+    return m_identifierToNameMap.get(static_cast<unsigned>(identifier)).isolatedCopy();
 }
 
 std::unique_ptr<CryptoAlgorithm> CryptoAlgorithmRegistry::create(CryptoAlgorithmIdentifier identifier)
 {
+    MutexLocker lock(registryMutex());
+
     auto iter = m_identifierToConstructorMap.find(static_cast<unsigned>(identifier));
     if (iter == m_identifierToConstructorMap.end())
         return nullptr;
@@ -76,6 +87,8 @@ void CryptoAlgorithmRegistry::registerAlgorithm(const String& name, CryptoAlgori
 {
     ASSERT(name == name.lower());
 
+    MutexLocker lock(registryMutex());
+
     bool added = m_nameToIdentifierMap.add(name, identifier).isNewEntry;
     ASSERT_UNUSED(added, added);
 
index 39742c8..bc14da8 100644 (file)
@@ -44,6 +44,7 @@ enum KeyUsage {
     Conditional=SUBTLE_CRYPTO,
     GenerateIsReachable=Impl,
     InterfaceName=Key,
+    JSNoStaticTables,
     NoInterfaceObject,
     SkipVTableValidation
 ] interface CryptoKey {
index b94b81c..c25bae6 100644 (file)
@@ -39,18 +39,23 @@ CryptoKeyAES::CryptoKeyAES(CryptoAlgorithmIdentifier algorithm, const Vector<uin
     : CryptoKey(algorithm, CryptoKeyType::Secret, extractable, usage)
     , m_key(key)
 {
-    ASSERT(algorithm == CryptoAlgorithmIdentifier::AES_CTR
-        || algorithm == CryptoAlgorithmIdentifier::AES_CBC
-        || algorithm == CryptoAlgorithmIdentifier::AES_CMAC
-        || algorithm == CryptoAlgorithmIdentifier::AES_GCM
-        || algorithm == CryptoAlgorithmIdentifier::AES_CFB
-        || algorithm == CryptoAlgorithmIdentifier::AES_KW);
+    ASSERT(isValidAESAlgorithm(algorithm));
 }
 
 CryptoKeyAES::~CryptoKeyAES()
 {
 }
 
+bool CryptoKeyAES::isValidAESAlgorithm(CryptoAlgorithmIdentifier algorithm)
+{
+    return algorithm == CryptoAlgorithmIdentifier::AES_CTR
+        || algorithm == CryptoAlgorithmIdentifier::AES_CBC
+        || algorithm == CryptoAlgorithmIdentifier::AES_CMAC
+        || algorithm == CryptoAlgorithmIdentifier::AES_GCM
+        || algorithm == CryptoAlgorithmIdentifier::AES_CFB
+        || algorithm == CryptoAlgorithmIdentifier::AES_KW;
+}
+
 PassRefPtr<CryptoKeyAES> CryptoKeyAES::generate(CryptoAlgorithmIdentifier algorithm, size_t lengthBits, bool extractable, CryptoKeyUsage usages)
 {
     if (lengthBits % 8)
index f8a8057..da5528b 100644 (file)
@@ -42,6 +42,8 @@ public:
     }
     virtual ~CryptoKeyAES();
 
+    static bool isValidAESAlgorithm(CryptoAlgorithmIdentifier);
+
     static PassRefPtr<CryptoKeyAES> generate(CryptoAlgorithmIdentifier, size_t lengthBits, bool extractable, CryptoKeyUsage);
 
     virtual CryptoKeyClass keyClass() const OVERRIDE { return CryptoKeyClass::AES; }