Index: third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp |
diff --git a/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp b/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp |
index 2394328b8b247ebed1e8a828a505f545ecb40919..0bba452cdc02477dcb7ee1402bb30323b276d7a9 100644 |
--- a/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp |
+++ b/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp |
@@ -87,12 +87,52 @@ static bool copySequenceOfStringProperty(const char* property, const Dictionary& |
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, WebVector<uint8_t>& jsonUtf8, CryptoResult* result) |
+// Parses a JsonWebKey dictionary. On success writes the result to |
+// |jsonUtf8| as a UTF8-encoded JSON octet string and returns true. |
+// On failure sets an error on |result| and returns false. |
+// |
+// Note: The choice of output as an octet string is to facilitate interop |
+// with the non-JWK formats, but does mean there is a second parsing step. |
+// This design choice should be revisited after crbug.com/614385). |
+// |
+// Defined by the WebCrypto spec as: |
+// |
+// dictionary JsonWebKey { |
+// DOMString kty; |
+// DOMString use; |
+// sequence<DOMString> key_ops; |
+// DOMString alg; |
+// |
+// boolean ext; |
+// |
+// DOMString crv; |
+// DOMString x; |
+// DOMString y; |
+// DOMString d; |
+// DOMString n; |
+// DOMString e; |
+// DOMString p; |
+// DOMString q; |
+// DOMString dp; |
+// DOMString dq; |
+// DOMString qi; |
+// sequence<RsaOtherPrimesInfo> oth; |
+// DOMString k; |
+// }; |
+// |
+// dictionary RsaOtherPrimesInfo { |
+// DOMString r; |
+// DOMString d; |
+// DOMString t; |
+// }; |
+static bool parseJsonWebKey(const Dictionary& dict, WebVector<uint8_t>& jsonUtf8, CryptoResult* result) |
{ |
+ // TODO(eroman): This implementation is incomplete and not spec compliant: |
+ // * Properties need to be read in the definition order above |
+ // * Preserve the type of optional parameters (crbug.com/385376) |
+ // * Parse "oth" (crbug.com/441396) |
+ // * Fail with TypeError (not DataError) if the input does not conform |
+ // to a JsonWebKey |
RefPtr<JSONObject> jsonObject = JSONObject::create(); |
if (!copyStringProperty("kty", dict, jsonObject.get())) { |
@@ -346,29 +386,49 @@ ScriptPromise SubtleCrypto::importKey(ScriptState* scriptState, const String& ra |
if (!parseAlgorithm(rawAlgorithm, WebCryptoOperationImportKey, normalizedAlgorithm, result)) |
return promise; |
- // TODO(eroman): Match the procedure given in the spec to more |
- // easily provide a normative reference. |
- if (rawKeyData.isDictionary()) { |
- if (format != WebCryptoKeyFormatJwk) { |
- result->completeWithError(WebCryptoErrorTypeType, "Key data must be a buffer for non-JWK formats"); |
- return promise; |
- } |
- } else if (format == WebCryptoKeyFormatJwk) { |
- result->completeWithError(WebCryptoErrorTypeType, "Key data must be an object for JWK import"); |
- return promise; |
- } |
- |
+ // In the case of JWK keyData will hold the UTF8-encoded JSON for the |
+ // JsonWebKey, otherwise it holds a copy of the BufferSource. |
WebVector<uint8_t> keyData; |
- // TODO(eroman): Match the procedure given in the spec to more |
- // easily provide a normative reference. |
- if (rawKeyData.isArrayBuffer()) { |
- keyData = copyBytes(rawKeyData.getAsArrayBuffer()); |
- } else if (rawKeyData.isArrayBufferView()) { |
- keyData = copyBytes(rawKeyData.getAsArrayBufferView()); |
- } else if (rawKeyData.isDictionary()) { |
- if (!copyJwkDictionaryToJson(rawKeyData.getAsDictionary(), keyData, result)) |
+ switch (format) { |
+ // 14.3.9.6: If format is equal to the string "raw", "pkcs8", or "spki": |
+ // |
+ // (1) If the keyData parameter passed to the importKey method is a |
+ // JsonWebKey dictionary, throw a TypeError. |
+ // |
+ // (2) Let keyData be the result of getting a copy of the bytes held by |
+ // the keyData parameter passed to the importKey method. |
+ case WebCryptoKeyFormatRaw: |
+ case WebCryptoKeyFormatPkcs8: |
+ case WebCryptoKeyFormatSpki: |
+ if (rawKeyData.isArrayBuffer()) { |
+ keyData = copyBytes(rawKeyData.getAsArrayBuffer()); |
+ } else if (rawKeyData.isArrayBufferView()) { |
+ keyData = copyBytes(rawKeyData.getAsArrayBufferView()); |
+ } else { |
+ result->completeWithError(WebCryptoErrorTypeType, "Key data must be a BufferSource for non-JWK formats"); |
+ return promise; |
+ } |
+ break; |
+ // 14.3.9.6: If format is equal to the string "jwk": |
+ // |
+ // (1) If the keyData parameter passed to the importKey method is not a |
+ // JsonWebKey dictionary, throw a TypeError. |
+ // |
+ // (2) Let keyData be the keyData parameter passed to the importKey |
+ // method. |
+ case WebCryptoKeyFormatJwk: |
+ if (rawKeyData.isDictionary()) { |
+ // TODO(eroman): To match the spec error order, parsing of the |
+ // JsonWebKey should be done earlier (at the WebIDL layer of |
+ // parameter checking), regardless of the format being "jwk". |
+ if (!parseJsonWebKey(rawKeyData.getAsDictionary(), keyData, result)) |
+ return promise; |
+ } else { |
+ result->completeWithError(WebCryptoErrorTypeType, "Key data must be an object for JWK import"); |
return promise; |
+ } |
+ break; |
} |
histogramAlgorithm(scriptState->getExecutionContext(), normalizedAlgorithm); |
Platform::current()->crypto()->importKey(format, std::move(keyData), normalizedAlgorithm, extractable, keyUsages, result->result()); |