Chromium Code Reviews| 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 33daf935b5ba1b197effa7d82838f642846c8eef..aac677e1c9cb881741d094fecd32f45a765aa30b 100644 |
| --- a/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp |
| +++ b/third_party/WebKit/Source/modules/crypto/SubtleCrypto.cpp |
| @@ -31,6 +31,9 @@ |
| #include "modules/crypto/SubtleCrypto.h" |
| #include "bindings/core/v8/Dictionary.h" |
| +#include "core/dom/DOMArrayBuffer.h" |
| +#include "core/dom/DOMArrayBufferView.h" |
| +#include "core/dom/DOMArrayPiece.h" |
| #include "core/dom/ExecutionContext.h" |
| #include "modules/crypto/CryptoHistograms.h" |
| #include "modules/crypto/CryptoKey.h" |
| @@ -41,6 +44,10 @@ |
| #include "public/platform/WebCrypto.h" |
| #include "public/platform/WebCryptoAlgorithm.h" |
| +// FIXME: Change the public blink::WebCrypto interface to allow transferring |
|
haraken
2016/07/18 22:41:57
TODO(your name)
eroman
2016/07/18 23:15:25
Done.
|
| +// ownership of data buffers instead of just taking a raw pointer+length. |
| +// This will avoid an extra copy. |
| + |
| namespace blink { |
| static bool parseAlgorithm(const AlgorithmIdentifier& raw, WebCryptoOperation op, WebCryptoAlgorithm& algorithm, CryptoResult* result) |
| @@ -88,7 +95,7 @@ static bool copySequenceOfStringProperty(const char* property, const Dictionary& |
| // 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) |
| +static bool copyJwkDictionaryToJson(const Dictionary& dict, Vector<uint8_t>& jsonUtf8, CryptoResult* result) |
| { |
| RefPtr<JSONObject> jsonObject = JSONObject::create(); |
| @@ -110,22 +117,36 @@ static bool copyJwkDictionaryToJson(const Dictionary& dict, CString& jsonUtf8, C |
| copyStringProperty(propertyNames[i], dict, jsonObject.get()); |
| String json = jsonObject->toJSONString(); |
| - jsonUtf8 = json.utf8(); |
| + jsonUtf8.clear(); |
| + jsonUtf8.append(json.utf8().data(), json.utf8().length()); |
| return true; |
| } |
| +static Vector<uint8_t> copyBytes(const DOMArrayPiece& source) |
| +{ |
| + Vector<uint8_t> result; |
| + result.append(reinterpret_cast<const uint8_t*>(source.data()), source.byteLength()); |
| + return result; |
| +} |
| + |
| SubtleCrypto::SubtleCrypto() |
| { |
| } |
| -ScriptPromise SubtleCrypto::encrypt(ScriptState* scriptState, const AlgorithmIdentifier& rawAlgorithm, CryptoKey* key, const DOMArrayPiece& data) |
| +ScriptPromise SubtleCrypto::encrypt(ScriptState* scriptState, const AlgorithmIdentifier& rawAlgorithm, CryptoKey* key, const BufferSource& rawData) |
| { |
| + // Method described by: https://w3c.github.io/webcrypto/Overview.html#dfn-SubtleCrypto-method-encrypt |
| + |
| CryptoResultImpl* result = CryptoResultImpl::create(scriptState); |
| ScriptPromise promise = result->promise(); |
| if (!canAccessWebCrypto(scriptState, result)) |
| return promise; |
| + // 14.3.1.2: Let data be the result of getting a copy of the bytes held by |
| + // the data parameter passed to the encrypt method. |
| + Vector<uint8_t> data = copyBytes(rawData); |
| + |
| WebCryptoAlgorithm algorithm; |
| if (!parseAlgorithm(rawAlgorithm, WebCryptoOperationEncrypt, algorithm, result)) |
| return promise; |
| @@ -134,18 +155,24 @@ ScriptPromise SubtleCrypto::encrypt(ScriptState* scriptState, const AlgorithmIde |
| return promise; |
| histogramAlgorithmAndKey(scriptState->getExecutionContext(), algorithm, key->key()); |
| - Platform::current()->crypto()->encrypt(algorithm, key->key(), data.bytes(), data.byteLength(), result->result()); |
| + Platform::current()->crypto()->encrypt(algorithm, key->key(), data.data(), data.size(), result->result()); |
| return promise; |
| } |
| -ScriptPromise SubtleCrypto::decrypt(ScriptState* scriptState, const AlgorithmIdentifier& rawAlgorithm, CryptoKey* key, const DOMArrayPiece& data) |
| +ScriptPromise SubtleCrypto::decrypt(ScriptState* scriptState, const AlgorithmIdentifier& rawAlgorithm, CryptoKey* key, const BufferSource& rawData) |
| { |
| + // Method described by: https://w3c.github.io/webcrypto/Overview.html#dfn-SubtleCrypto-method-decrypt |
| + |
| CryptoResultImpl* result = CryptoResultImpl::create(scriptState); |
| ScriptPromise promise = result->promise(); |
| if (!canAccessWebCrypto(scriptState, result)) |
| return promise; |
| + // 14.3.2.2: Let data be the result of getting a copy of the bytes held by |
| + // the data parameter passed to the decrypt method. |
| + Vector<uint8_t> data = copyBytes(rawData); |
| + |
| WebCryptoAlgorithm algorithm; |
| if (!parseAlgorithm(rawAlgorithm, WebCryptoOperationDecrypt, algorithm, result)) |
| return promise; |
| @@ -154,18 +181,24 @@ ScriptPromise SubtleCrypto::decrypt(ScriptState* scriptState, const AlgorithmIde |
| return promise; |
| histogramAlgorithmAndKey(scriptState->getExecutionContext(), algorithm, key->key()); |
| - Platform::current()->crypto()->decrypt(algorithm, key->key(), data.bytes(), data.byteLength(), result->result()); |
| + Platform::current()->crypto()->decrypt(algorithm, key->key(), data.data(), data.size(), result->result()); |
| return promise; |
| } |
| -ScriptPromise SubtleCrypto::sign(ScriptState* scriptState, const AlgorithmIdentifier& rawAlgorithm, CryptoKey* key, const DOMArrayPiece& data) |
| +ScriptPromise SubtleCrypto::sign(ScriptState* scriptState, const AlgorithmIdentifier& rawAlgorithm, CryptoKey* key, const BufferSource& rawData) |
| { |
| + // Method described by: https://w3c.github.io/webcrypto/Overview.html#dfn-SubtleCrypto-method-sign |
| + |
| CryptoResultImpl* result = CryptoResultImpl::create(scriptState); |
| ScriptPromise promise = result->promise(); |
| if (!canAccessWebCrypto(scriptState, result)) |
| return promise; |
| + // 14.3.3.2: Let data be the result of getting a copy of the bytes held by |
| + // the data parameter passed to the sign method. |
| + Vector<uint8_t> data = copyBytes(rawData); |
| + |
| WebCryptoAlgorithm algorithm; |
| if (!parseAlgorithm(rawAlgorithm, WebCryptoOperationSign, algorithm, result)) |
| return promise; |
| @@ -174,44 +207,60 @@ ScriptPromise SubtleCrypto::sign(ScriptState* scriptState, const AlgorithmIdenti |
| return promise; |
| histogramAlgorithmAndKey(scriptState->getExecutionContext(), algorithm, key->key()); |
| - Platform::current()->crypto()->sign(algorithm, key->key(), data.bytes(), data.byteLength(), result->result()); |
| + Platform::current()->crypto()->sign(algorithm, key->key(), data.data(), data.size(), result->result()); |
| return promise; |
| } |
| -ScriptPromise SubtleCrypto::verifySignature(ScriptState* scriptState, const AlgorithmIdentifier& rawAlgorithm, CryptoKey* key, const DOMArrayPiece& signature, const DOMArrayPiece& data) |
| +ScriptPromise SubtleCrypto::verifySignature(ScriptState* scriptState, const AlgorithmIdentifier& rawAlgorithm, CryptoKey* key, const BufferSource& rawSignature, const BufferSource& rawData) |
| { |
| + // Method described by: https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-verify |
| + |
| CryptoResultImpl* result = CryptoResultImpl::create(scriptState); |
| ScriptPromise promise = result->promise(); |
| if (!canAccessWebCrypto(scriptState, result)) |
| return promise; |
| + // 14.3.4.2: Let signature be the result of getting a copy of the bytes |
| + // held by the signature parameter passed to the verify method. |
| + Vector<uint8_t> signature = copyBytes(rawSignature); |
| + |
| WebCryptoAlgorithm algorithm; |
| if (!parseAlgorithm(rawAlgorithm, WebCryptoOperationVerify, algorithm, result)) |
| return promise; |
| + // 14.3.4.5: Let data be the result of getting a copy of the bytes held by |
| + // the data parameter passed to the verify method. |
| + Vector<uint8_t> data = copyBytes(rawData); |
| + |
| if (!key->canBeUsedForAlgorithm(algorithm, WebCryptoKeyUsageVerify, result)) |
| return promise; |
| histogramAlgorithmAndKey(scriptState->getExecutionContext(), algorithm, key->key()); |
| - Platform::current()->crypto()->verifySignature(algorithm, key->key(), signature.bytes(), signature.byteLength(), data.bytes(), data.byteLength(), result->result()); |
| + Platform::current()->crypto()->verifySignature(algorithm, key->key(), signature.data(), signature.size(), data.data(), data.size(), result->result()); |
| return promise; |
| } |
| -ScriptPromise SubtleCrypto::digest(ScriptState* scriptState, const AlgorithmIdentifier& rawAlgorithm, const DOMArrayPiece& data) |
| +ScriptPromise SubtleCrypto::digest(ScriptState* scriptState, const AlgorithmIdentifier& rawAlgorithm, const BufferSource& rawData) |
| { |
| + // Method described by: https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-digest |
| + |
| CryptoResultImpl* result = CryptoResultImpl::create(scriptState); |
| ScriptPromise promise = result->promise(); |
| if (!canAccessWebCrypto(scriptState, result)) |
| return promise; |
| + // 14.3.5.2: Let data be the result of getting a copy of the bytes held |
| + // by the data parameter passed to the digest method. |
| + Vector<uint8_t> data = copyBytes(rawData); |
| + |
| WebCryptoAlgorithm algorithm; |
| if (!parseAlgorithm(rawAlgorithm, WebCryptoOperationDigest, algorithm, result)) |
| return promise; |
| histogramAlgorithm(scriptState->getExecutionContext(), algorithm); |
| - Platform::current()->crypto()->digest(algorithm, data.bytes(), data.byteLength(), result->result()); |
| + Platform::current()->crypto()->digest(algorithm, data.data(), data.size(), result->result()); |
| return promise; |
| } |
| @@ -236,8 +285,10 @@ ScriptPromise SubtleCrypto::generateKey(ScriptState* scriptState, const Algorith |
| return promise; |
| } |
| -ScriptPromise SubtleCrypto::importKey(ScriptState* scriptState, const String& rawFormat, const ArrayBufferOrArrayBufferViewOrDictionary& keyData, const AlgorithmIdentifier& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages) |
| +ScriptPromise SubtleCrypto::importKey(ScriptState* scriptState, const String& rawFormat, const ArrayBufferOrArrayBufferViewOrDictionary& rawKeyData, const AlgorithmIdentifier& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages) |
| { |
| + // Method described by: https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-importKey |
| + |
| CryptoResultImpl* result = CryptoResultImpl::create(scriptState); |
| ScriptPromise promise = result->promise(); |
| @@ -248,7 +299,7 @@ ScriptPromise SubtleCrypto::importKey(ScriptState* scriptState, const String& ra |
| if (!CryptoKey::parseFormat(rawFormat, format, result)) |
| return promise; |
| - if (keyData.isDictionary()) { |
| + if (rawKeyData.isDictionary()) { |
| if (format != WebCryptoKeyFormatJwk) { |
| result->completeWithError(WebCryptoErrorTypeData, "Key data must be a buffer for non-JWK formats"); |
| return promise; |
| @@ -266,24 +317,17 @@ ScriptPromise SubtleCrypto::importKey(ScriptState* scriptState, const String& ra |
| if (!parseAlgorithm(rawAlgorithm, WebCryptoOperationImportKey, algorithm, result)) |
| return promise; |
| - const unsigned char* ptr = nullptr; |
| - unsigned len = 0; |
| - |
| - CString jsonUtf8; |
| - if (keyData.isArrayBuffer()) { |
| - ptr = static_cast<const unsigned char*>(keyData.getAsArrayBuffer()->data()); |
| - len = keyData.getAsArrayBuffer()->byteLength(); |
| - } else if (keyData.isArrayBufferView()) { |
| - ptr = static_cast<const unsigned char*>(keyData.getAsArrayBufferView()->baseAddress()); |
| - len = keyData.getAsArrayBufferView()->byteLength(); |
| - } else if (keyData.isDictionary()) { |
| - if (!copyJwkDictionaryToJson(keyData.getAsDictionary(), jsonUtf8, result)) |
| + Vector<uint8_t> keyData; |
| + 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)) |
| return promise; |
| - ptr = reinterpret_cast<const unsigned char*>(jsonUtf8.data()); |
| - len = jsonUtf8.length(); |
| } |
| histogramAlgorithm(scriptState->getExecutionContext(), algorithm); |
| - Platform::current()->crypto()->importKey(format, ptr, len, algorithm, extractable, keyUsages, result->result()); |
| + Platform::current()->crypto()->importKey(format, keyData.data(), keyData.size(), algorithm, extractable, keyUsages, result->result()); |
| return promise; |
| } |
| @@ -339,8 +383,10 @@ ScriptPromise SubtleCrypto::wrapKey(ScriptState* scriptState, const String& rawF |
| return promise; |
| } |
| -ScriptPromise SubtleCrypto::unwrapKey(ScriptState* scriptState, const String& rawFormat, const DOMArrayPiece& wrappedKey, CryptoKey* unwrappingKey, const AlgorithmIdentifier& rawUnwrapAlgorithm, const AlgorithmIdentifier& rawUnwrappedKeyAlgorithm, bool extractable, const Vector<String>& rawKeyUsages) |
| +ScriptPromise SubtleCrypto::unwrapKey(ScriptState* scriptState, const String& rawFormat, const BufferSource& rawWrappedKey, CryptoKey* unwrappingKey, const AlgorithmIdentifier& rawUnwrapAlgorithm, const AlgorithmIdentifier& rawUnwrappedKeyAlgorithm, bool extractable, const Vector<String>& rawKeyUsages) |
| { |
| + // Method described by: https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-unwrapKey |
| + |
| CryptoResultImpl* result = CryptoResultImpl::create(scriptState); |
| ScriptPromise promise = result->promise(); |
| @@ -355,6 +401,11 @@ ScriptPromise SubtleCrypto::unwrapKey(ScriptState* scriptState, const String& ra |
| if (!CryptoKey::parseUsageMask(rawKeyUsages, keyUsages, result)) |
| return promise; |
| + // 14.3.12.2: Let wrappedKey be the result of getting a copy of the bytes |
| + // held by the wrappedKey parameter passed to the unwrapKey |
| + // method. |
| + Vector<uint8_t> wrappedKey = copyBytes(rawWrappedKey); |
| + |
| WebCryptoAlgorithm unwrapAlgorithm; |
| if (!parseAlgorithm(rawUnwrapAlgorithm, WebCryptoOperationUnwrapKey, unwrapAlgorithm, result)) |
| return promise; |
| @@ -368,7 +419,7 @@ ScriptPromise SubtleCrypto::unwrapKey(ScriptState* scriptState, const String& ra |
| histogramAlgorithmAndKey(scriptState->getExecutionContext(), unwrapAlgorithm, unwrappingKey->key()); |
| histogramAlgorithm(scriptState->getExecutionContext(), unwrappedKeyAlgorithm); |
| - Platform::current()->crypto()->unwrapKey(format, wrappedKey.bytes(), wrappedKey.byteLength(), unwrappingKey->key(), unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages, result->result()); |
| + Platform::current()->crypto()->unwrapKey(format, wrappedKey.data(), wrappedKey.size(), unwrappingKey->key(), unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages, result->result()); |
| return promise; |
| } |