Index: Source/modules/crypto/SubtleCrypto.cpp |
diff --git a/Source/modules/crypto/SubtleCrypto.cpp b/Source/modules/crypto/SubtleCrypto.cpp |
index 832f916541561c73da9c175f00c8229f9d9976be..ca705a87c5f74f36a959f6ebbc98a2ade219fa2c 100644 |
--- a/Source/modules/crypto/SubtleCrypto.cpp |
+++ b/Source/modules/crypto/SubtleCrypto.cpp |
@@ -36,6 +36,7 @@ |
#include "modules/crypto/CryptoResultImpl.h" |
#include "modules/crypto/Key.h" |
#include "modules/crypto/NormalizeAlgorithm.h" |
+#include "platform/JSONValues.h" |
#include "public/platform/Platform.h" |
#include "public/platform/WebCrypto.h" |
#include "public/platform/WebCryptoAlgorithm.h" |
@@ -65,7 +66,7 @@ static bool ensureNotNull(Key* key, const char* paramName, CryptoResult* result) |
return true; |
} |
-bool parseAlgorithm(const Dictionary& raw, blink::WebCryptoOperation op, blink::WebCryptoAlgorithm& algorithm, CryptoResult* result) |
+static bool parseAlgorithm(const Dictionary& raw, blink::WebCryptoOperation op, blink::WebCryptoAlgorithm& algorithm, CryptoResult* result) |
{ |
AlgorithmError error; |
bool success = normalizeAlgorithm(raw, op, algorithm, &error); |
@@ -136,6 +137,57 @@ static ScriptPromise startCryptoOperation(ScriptState* scriptState, const Dictio |
return promise; |
} |
+static bool copyStringProperty(const char* property, const Dictionary& source, JSONObject* destination) |
+{ |
+ String value; |
+ if (!source.get(property, value)) |
+ return false; |
+ destination->setString(property, value); |
+ return true; |
+} |
+ |
+static bool copySequenceOfStringProperty(const char* property, const Dictionary& source, JSONObject* destination) |
+{ |
+ Vector<String> value; |
+ if (!source.get(property, value)) |
+ return false; |
+ RefPtr<JSONArray> jsonArray = JSONArray::create(); |
+ for (unsigned i = 0; i < value.size(); ++i) |
+ jsonArray->pushString(value[i]); |
+ destination->setArray(property, jsonArray.release()); |
+ return true; |
+} |
+ |
+// FIXME: At the time of writing this is not a part of the spec. It is based an |
+// an unpublished editor's draft for: |
+// https://www.w3.org/Bugs/Public/show_bug.cgi?id=24963 |
+// See http://crbug.com/373917. |
+static bool copyJwkDictionaryToJson(const Dictionary& dict, CString& jsonUtf8, CryptoResult* result) |
+{ |
+ RefPtr<JSONObject> jsonObject = JSONObject::create(); |
+ |
+ if (!copyStringProperty("kty", dict, jsonObject.get())) { |
+ result->completeWithError(blink::WebCryptoErrorTypeData, "The required JWK property \"kty\" was missing"); |
+ return false; |
+ } |
+ |
+ copyStringProperty("use", dict, jsonObject.get()); |
+ copySequenceOfStringProperty("key_ops", dict, jsonObject.get()); |
+ copyStringProperty("alg", dict, jsonObject.get()); |
+ |
+ bool ext; |
+ if (dict.get("ext", ext)) |
+ jsonObject->setBoolean("ext", ext); |
+ |
+ const char* const propertyNames[] = { "d", "n", "e", "p", "q", "dp", "dq", "qi", "k" }; |
+ for (unsigned i = 0; i < WTF_ARRAY_LENGTH(propertyNames); ++i) |
+ copyStringProperty(propertyNames[i], dict, jsonObject.get()); |
+ |
+ String json = jsonObject->toJSONString(); |
+ jsonUtf8 = json.utf8(); |
+ return true; |
+} |
+ |
SubtleCrypto::SubtleCrypto() |
{ |
ScriptWrappable::init(this); |
@@ -201,6 +253,11 @@ ScriptPromise SubtleCrypto::importKey(ScriptState* scriptState, const String& ra |
if (!Key::parseFormat(rawFormat, format, result.get())) |
return promise; |
+ if (format == blink::WebCryptoKeyFormatJwk) { |
+ result->completeWithError(blink::WebCryptoErrorTypeData, "Key data must be an object for JWK import"); |
+ return promise; |
+ } |
+ |
blink::WebCryptoKeyUsageMask keyUsages; |
if (!Key::parseUsageMask(rawKeyUsages, keyUsages, result.get())) |
return promise; |
@@ -213,6 +270,39 @@ ScriptPromise SubtleCrypto::importKey(ScriptState* scriptState, const String& ra |
return promise; |
} |
+ScriptPromise SubtleCrypto::importKey(ScriptState* scriptState, const String& rawFormat, const Dictionary& keyData, const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages) |
+{ |
+ RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(scriptState); |
+ ScriptPromise promise = result->promise(); |
+ |
+ if (!canAccessWebCrypto(scriptState, result.get())) |
+ return promise; |
+ |
+ blink::WebCryptoKeyFormat format; |
+ if (!Key::parseFormat(rawFormat, format, result.get())) |
+ return promise; |
+ |
+ blink::WebCryptoKeyUsageMask keyUsages; |
+ if (!Key::parseUsageMask(rawKeyUsages, keyUsages, result.get())) |
+ return promise; |
+ |
+ if (format != blink::WebCryptoKeyFormatJwk) { |
+ result->completeWithError(blink::WebCryptoErrorTypeData, "Key data must be a buffer for non-JWK formats"); |
+ return promise; |
+ } |
+ |
+ blink::WebCryptoAlgorithm algorithm; |
+ if (!parseAlgorithm(rawAlgorithm, blink::WebCryptoOperationImportKey, algorithm, result.get())) |
+ return promise; |
+ |
+ CString jsonUtf8; |
+ if (!copyJwkDictionaryToJson(keyData, jsonUtf8, result.get())) |
+ return promise; |
+ |
+ blink::Platform::current()->crypto()->importKey(format, reinterpret_cast<const unsigned char*>(jsonUtf8.data()), jsonUtf8.length(), algorithm, extractable, keyUsages, result->result()); |
+ return promise; |
+} |
+ |
ScriptPromise SubtleCrypto::exportKey(ScriptState* scriptState, const String& rawFormat, Key* key) |
{ |
RefPtr<CryptoResultImpl> result = CryptoResultImpl::create(scriptState); |