Replace CryptoOperationData with BufferSource for WebKitSubtleCrypto
authorjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 May 2017 20:09:47 +0000 (20:09 +0000)
committerjiewen_tan@apple.com <jiewen_tan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 May 2017 20:09:47 +0000 (20:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=172146
<rdar://problem/32122256>

Reviewed by Brent Fulgham.

Source/WebCore:

In this patch, we replaces CryptoOperationData with BufferSource for WebKitSubtleCrypto in
the custom binding codes.

Test: crypto/webkitSubtle/import-export-raw-key-leak.html

* bindings/js/JSWebKitSubtleCryptoCustom.cpp:
(WebCore::JSWebKitSubtleCrypto::encrypt):
(WebCore::JSWebKitSubtleCrypto::decrypt):
(WebCore::JSWebKitSubtleCrypto::sign):
(WebCore::JSWebKitSubtleCrypto::verify):
(WebCore::JSWebKitSubtleCrypto::digest):
(WebCore::JSWebKitSubtleCrypto::importKey):
(WebCore::JSWebKitSubtleCrypto::unwrapKey):
* crypto/WebKitSubtleCrypto.idl:

LayoutTests:

* crypto/webkitSubtle/argument-conversion-expected.txt:
* crypto/webkitSubtle/import-export-raw-key-leak-expected.txt: Added.
* crypto/webkitSubtle/import-export-raw-key-leak.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/crypto/webkitSubtle/argument-conversion-expected.txt
LayoutTests/crypto/webkitSubtle/import-export-raw-key-leak-expected.txt [new file with mode: 0644]
LayoutTests/crypto/webkitSubtle/import-export-raw-key-leak.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSWebKitSubtleCryptoCustom.cpp
Source/WebCore/crypto/WebKitSubtleCrypto.idl

index 4716be4..2cc2802 100644 (file)
@@ -1,3 +1,15 @@
+2017-05-15  Jiewen Tan  <jiewen_tan@apple.com>
+
+        Replace CryptoOperationData with BufferSource for WebKitSubtleCrypto
+        https://bugs.webkit.org/show_bug.cgi?id=172146
+        <rdar://problem/32122256>
+
+        Reviewed by Brent Fulgham.
+
+        * crypto/webkitSubtle/argument-conversion-expected.txt:
+        * crypto/webkitSubtle/import-export-raw-key-leak-expected.txt: Added.
+        * crypto/webkitSubtle/import-export-raw-key-leak.html: Added.
+
 2017-05-17  Chris Dumez  <cdumez@apple.com>
 
         Unreviewed, skip newly imported notifications tests on iOS
index f1cb03d..5730d8e 100644 (file)
@@ -16,10 +16,10 @@ PASS ...succeeded
 
 Passing invalid data to digest()
 PASS crypto.webkitSubtle.digest({name: 'sha-1'}) threw exception TypeError: Not enough arguments.
-PASS crypto.webkitSubtle.digest({name: 'sha-1'}, null) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData.
-PASS crypto.webkitSubtle.digest({name: 'sha-1'}, 10) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData.
-PASS crypto.webkitSubtle.digest({name: 'sha-1'}, [10]) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData.
-PASS crypto.webkitSubtle.digest({name: 'sha-1'}, [new Uint8Array([0])]) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData.
+PASS crypto.webkitSubtle.digest({name: 'sha-1'}, null) threw exception TypeError: Type error.
+PASS crypto.webkitSubtle.digest({name: 'sha-1'}, 10) threw exception TypeError: Type error.
+PASS crypto.webkitSubtle.digest({name: 'sha-1'}, [10]) threw exception TypeError: Type error.
+PASS crypto.webkitSubtle.digest({name: 'sha-1'}, [new Uint8Array([0])]) threw exception TypeError: Type error.
 
 Passing invalid algorithmIdentifiers to digest()
 PASS crypto.webkitSubtle.digest({ toString:function() { return 'sha-1' } }, data) threw exception NotSupportedError (DOM Exception 9): The operation is not supported..
diff --git a/LayoutTests/crypto/webkitSubtle/import-export-raw-key-leak-expected.txt b/LayoutTests/crypto/webkitSubtle/import-export-raw-key-leak-expected.txt
new file mode 100644 (file)
index 0000000..8725b7b
--- /dev/null
@@ -0,0 +1,8 @@
+CONSOLE MESSAGE: line 44: WebKitSubtleCrypto is deprecated. Please use SubtleCrypto instead.
+Sending Worker Message
+Worker Terminated
+PASS exportedKey.byteLength is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/crypto/webkitSubtle/import-export-raw-key-leak.html b/LayoutTests/crypto/webkitSubtle/import-export-raw-key-leak.html
new file mode 100644 (file)
index 0000000..3291837
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../../resources/js-test-pre.js"></script>
+    <script type="text/javascript">
+    jsTestIsAsync = true;
+
+    var keySize = 0x100;
+    var blob = new Blob([""], {type : 'application/javascript'});
+    var worker = new Worker(URL.createObjectURL(blob));
+
+    function run()
+    {
+        if (window.testRunner)
+            testRunner.dumpAsText();
+
+        function arrayBufferNeuter(ab)
+        {
+            /* Neuter the ArrayBuffer */
+            debug("Sending Worker Message");
+            worker.postMessage(ab, [ab]);
+            worker.terminate();
+            debug("Worker Terminated");
+        }
+
+        var a = new ArrayBuffer(keySize);
+        var b = { };
+        b.__defineGetter__('name', function(){
+            arrayBufferNeuter(a);
+            return "AES-CBC";
+        });
+        var result = window.crypto.webkitSubtle.importKey("raw", a, b, true);
+        result.then(function(key) {
+            window.crypto.webkitSubtle.exportKey("raw", key).then(function(result) {
+                exportedKey = result;
+                shouldBeZero("exportedKey.byteLength");
+                finishJSTest();
+            });
+        });
+    }
+    </script>
+    <script src="../../resources/js-test-post.js"></script>
+</head>
+<body onload="run()"></body>
+</html>
index efce8e4..204da44 100644 (file)
@@ -1,3 +1,26 @@
+2017-05-15  Jiewen Tan  <jiewen_tan@apple.com>
+
+        Replace CryptoOperationData with BufferSource for WebKitSubtleCrypto
+        https://bugs.webkit.org/show_bug.cgi?id=172146
+        <rdar://problem/32122256>
+
+        Reviewed by Brent Fulgham.
+
+        In this patch, we replaces CryptoOperationData with BufferSource for WebKitSubtleCrypto in
+        the custom binding codes.
+
+        Test: crypto/webkitSubtle/import-export-raw-key-leak.html
+
+        * bindings/js/JSWebKitSubtleCryptoCustom.cpp:
+        (WebCore::JSWebKitSubtleCrypto::encrypt):
+        (WebCore::JSWebKitSubtleCrypto::decrypt):
+        (WebCore::JSWebKitSubtleCrypto::sign):
+        (WebCore::JSWebKitSubtleCrypto::verify):
+        (WebCore::JSWebKitSubtleCrypto::digest):
+        (WebCore::JSWebKitSubtleCrypto::importKey):
+        (WebCore::JSWebKitSubtleCrypto::unwrapKey):
+        * crypto/WebKitSubtleCrypto.idl:
+
 2017-05-17  Youenn Fablet  <youenn@apple.com>
 
         Move-related refactoring on UserMediaPermissionRequestProxy
index 733b6a7..83548ce 100644 (file)
@@ -28,6 +28,7 @@
 
 #if ENABLE(SUBTLE_CRYPTO)
 
+#include "BufferSource.h"
 #include "CryptoAlgorithm.h"
 #include "CryptoAlgorithmParametersDeprecated.h"
 #include "CryptoAlgorithmRegistry.h"
@@ -39,7 +40,6 @@
 #include "JSCryptoKey.h"
 #include "JSCryptoKeyPair.h"
 #include "JSCryptoKeySerializationJWK.h"
-#include "JSCryptoOperationData.h"
 #include "JSDOMPromiseDeferred.h"
 #include "ScriptState.h"
 #include <runtime/Error.h>
@@ -148,7 +148,7 @@ JSValue JSWebKitSubtleCrypto::encrypt(ExecState& state)
         return jsUndefined();
     }
 
-    auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(2));
+    auto data = BufferSource(convert<IDLBufferSource>(state, state.uncheckedArgument(2)));
     RETURN_IF_EXCEPTION(scope, { });
 
     RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
@@ -160,7 +160,7 @@ JSValue JSWebKitSubtleCrypto::encrypt(ExecState& state)
         wrapper->reject(); // FIXME: This should reject with an Exception.
     };
 
-    auto result = algorithm->encrypt(*parameters, *key, data, WTFMove(successCallback), WTFMove(failureCallback));
+    auto result = algorithm->encrypt(*parameters, *key, { data.data(), data.length() }, WTFMove(successCallback), WTFMove(failureCallback));
     if (result.hasException()) {
         propagateException(state, scope, result.releaseException());
         return { };
@@ -193,7 +193,7 @@ JSValue JSWebKitSubtleCrypto::decrypt(ExecState& state)
         return jsUndefined();
     }
 
-    auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(2));
+    auto data = BufferSource(convert<IDLBufferSource>(state, state.uncheckedArgument(2)));
     RETURN_IF_EXCEPTION(scope, { });
 
     RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
@@ -205,7 +205,7 @@ JSValue JSWebKitSubtleCrypto::decrypt(ExecState& state)
         wrapper->reject(); // FIXME: This should reject with an Exception.
     };
 
-    auto result = algorithm->decrypt(*parameters, *key, data, WTFMove(successCallback), WTFMove(failureCallback));
+    auto result = algorithm->decrypt(*parameters, *key, { data.data(), data.length() }, WTFMove(successCallback), WTFMove(failureCallback));
     if (result.hasException()) {
         propagateException(state, scope, result.releaseException());
         return { };
@@ -238,7 +238,7 @@ JSValue JSWebKitSubtleCrypto::sign(ExecState& state)
         return jsUndefined();
     }
 
-    auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(2));
+    auto data = BufferSource(convert<IDLBufferSource>(state, state.uncheckedArgument(2)));
     RETURN_IF_EXCEPTION(scope, { });
 
     RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
@@ -250,7 +250,7 @@ JSValue JSWebKitSubtleCrypto::sign(ExecState& state)
         wrapper->reject(); // FIXME: This should reject with an Exception.
     };
 
-    auto result = algorithm->sign(*parameters, *key, data, WTFMove(successCallback), WTFMove(failureCallback));
+    auto result = algorithm->sign(*parameters, *key, { data.data(), data.length() }, WTFMove(successCallback), WTFMove(failureCallback));
     if (result.hasException()) {
         propagateException(state, scope, result.releaseException());
         return { };
@@ -283,10 +283,10 @@ JSValue JSWebKitSubtleCrypto::verify(ExecState& state)
         return jsUndefined();
     }
 
-    auto signature = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(2));
+    auto signature = BufferSource(convert<IDLBufferSource>(state, state.uncheckedArgument(2)));
     RETURN_IF_EXCEPTION(scope, { });
 
-    auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(3));
+    auto data = BufferSource(convert<IDLBufferSource>(state, state.uncheckedArgument(3)));
     RETURN_IF_EXCEPTION(scope, { });
 
     RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
@@ -298,7 +298,7 @@ JSValue JSWebKitSubtleCrypto::verify(ExecState& state)
         wrapper->reject(); // FIXME: This should reject with an Exception.
     };
 
-    auto result = algorithm->verify(*parameters, *key, signature, data, WTFMove(successCallback), WTFMove(failureCallback));
+    auto result = algorithm->verify(*parameters, *key, { signature.data(), signature.length() }, { data.data(), data.length() }, WTFMove(successCallback), WTFMove(failureCallback));
     if (result.hasException()) {
         propagateException(state, scope, result.releaseException());
         return { };
@@ -321,7 +321,7 @@ JSValue JSWebKitSubtleCrypto::digest(ExecState& state)
     auto parameters = JSCryptoAlgorithmDictionary::createParametersForDigest(state, scope, algorithm->identifier(), state.uncheckedArgument(0));
     RETURN_IF_EXCEPTION(scope, { });
 
-    auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1));
+    auto data = BufferSource(convert<IDLBufferSource>(state, state.uncheckedArgument(1)));
     RETURN_IF_EXCEPTION(scope, { });
 
     RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
@@ -333,7 +333,7 @@ JSValue JSWebKitSubtleCrypto::digest(ExecState& state)
         wrapper->reject(); // FIXME: This should reject with an Exception.
     };
 
-    auto result = algorithm->digest(*parameters, data, WTFMove(successCallback), WTFMove(failureCallback));
+    auto result = algorithm->digest(*parameters, { data.data(), data.length() }, WTFMove(successCallback), WTFMove(failureCallback));
     if (result.hasException()) {
         propagateException(state, scope, result.releaseException());
         return { };
@@ -456,7 +456,7 @@ JSValue JSWebKitSubtleCrypto::importKey(ExecState& state)
     auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0));
     RETURN_IF_EXCEPTION(scope, { });
 
-    auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1));
+    auto data = BufferSource(convert<IDLBufferSource>(state, state.uncheckedArgument(1)));
     RETURN_IF_EXCEPTION(scope, { });
 
     RefPtr<CryptoAlgorithm> algorithm;
@@ -487,7 +487,7 @@ JSValue JSWebKitSubtleCrypto::importKey(ExecState& state)
         wrapper->reject(); // FIXME: This should reject with an Exception.
     };
 
-    WebCore::importKey(state, keyFormat, data, WTFMove(algorithm), WTFMove(parameters), extractable, keyUsages, WTFMove(successCallback), WTFMove(failureCallback));
+    WebCore::importKey(state, keyFormat, { data.data(), data.length() }, WTFMove(algorithm), WTFMove(parameters), extractable, keyUsages, WTFMove(successCallback), WTFMove(failureCallback));
     RETURN_IF_EXCEPTION(scope, JSValue());
 
     return promise;
@@ -625,7 +625,7 @@ JSValue JSWebKitSubtleCrypto::unwrapKey(ExecState& state)
     auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0));
     RETURN_IF_EXCEPTION(scope, { });
 
-    auto wrappedKeyData = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1));
+    auto wrappedKeyData = BufferSource(convert<IDLBufferSource>(state, state.uncheckedArgument(1)));
     RETURN_IF_EXCEPTION(scope, { });
 
     RefPtr<CryptoKey> unwrappingKey = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(2));
@@ -691,7 +691,7 @@ JSValue JSWebKitSubtleCrypto::unwrapKey(ExecState& state)
         wrapper->reject(); // FIXME: This should reject with an Exception.
     };
 
-    auto result = unwrapAlgorithm->decryptForUnwrapKey(*unwrapAlgorithmParameters, *unwrappingKey, wrappedKeyData, WTFMove(decryptSuccessCallback), WTFMove(decryptFailureCallback));
+    auto result = unwrapAlgorithm->decryptForUnwrapKey(*unwrapAlgorithmParameters, *unwrappingKey, { wrappedKeyData.data(), wrappedKeyData.length() }, WTFMove(decryptSuccessCallback), WTFMove(decryptFailureCallback));
     if (result.hasException()) {
         propagateException(state, scope, result.releaseException());
         return { };
index 0f85393..556101f 100644 (file)
     GenerateIsReachable=ImplDocument,
     NoInterfaceObject,
 ] interface WebKitSubtleCrypto {
-    [Custom] Promise<ArrayBuffer> encrypt(AlgorithmIdentifier algorithm, Key key, sequence<CryptoOperationData> data);
-    [Custom] Promise<ArrayBuffer> decrypt(AlgorithmIdentifier algorithm, Key key, sequence<CryptoOperationData> data);
-    [Custom] Promise<ArrayBuffer> sign(AlgorithmIdentifier algorithm, Key key, sequence<CryptoOperationData> data);
-    [Custom] Promise<boolean> verify(AlgorithmIdentifier algorithm, Key key, CryptoOperationData signature, sequence<CryptoOperationData> data);
-    [Custom] Promise<ArrayBuffer> digest(AlgorithmIdentifier algorithm, sequence<CryptoOperationData> data);
+    [Custom] Promise<ArrayBuffer> encrypt(AlgorithmIdentifier algorithm, Key key, sequence<BufferSource> data);
+    [Custom] Promise<ArrayBuffer> decrypt(AlgorithmIdentifier algorithm, Key key, sequence<BufferSource> data);
+    [Custom] Promise<ArrayBuffer> sign(AlgorithmIdentifier algorithm, Key key, sequence<BufferSource> data);
+    [Custom] Promise<boolean> verify(AlgorithmIdentifier algorithm, Key key, BufferSource signature, sequence<BufferSource> data);
+    [Custom] Promise<ArrayBuffer> digest(AlgorithmIdentifier algorithm, sequence<BufferSource> data);
     [Custom] Promise<(CryptoKey or CryptoKeyPair)> generateKey(AlgorithmIdentifier algorithm, optional boolean extractable, optional sequence<KeyUsage> keyUsages);
-    [Custom] Promise<CryptoKey> importKey(KeyFormat format, CryptoOperationData keyData, AlgorithmIdentifier? algorithm, optional boolean extractable, optional sequence<KeyUsage> keyUsages);
+    [Custom] Promise<CryptoKey> importKey(KeyFormat format, BufferSource keyData, AlgorithmIdentifier? algorithm, optional boolean extractable, optional sequence<KeyUsage> keyUsages);
     [Custom] Promise<ArrayBuffer> exportKey(KeyFormat format, Key key);
     [Custom] Promise<ArrayBuffer> wrapKey(KeyFormat format, Key key, Key wrappingKey, AlgorithmIdentifier wrapAlgorithm);
-    [Custom] Promise<CryptoKey> unwrapKey(KeyFormat format, CryptoOperationData wrappedKey, Key unwrappingKey, AlgorithmIdentifier unwrapAlgorithm, AlgorithmIdentifier? unwrappedKeyAlgorithm, optional boolean extractable, optional sequence<KeyUsage> keyUsages);
+    [Custom] Promise<CryptoKey> unwrapKey(KeyFormat format, BufferSource wrappedKey, Key unwrappingKey, AlgorithmIdentifier unwrapAlgorithm, AlgorithmIdentifier? unwrappedKeyAlgorithm, optional boolean extractable, optional sequence<KeyUsage> keyUsages);
 };