Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(293)

Unified Diff: content/child/webcrypto/shared_crypto.cc

Issue 233733004: [webcrypto] Make operations run on worker threads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix argument ordering bug Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/child/webcrypto/shared_crypto.cc
diff --git a/content/child/webcrypto/shared_crypto.cc b/content/child/webcrypto/shared_crypto.cc
index ee9789547dd5dade06d383621d0cf0a8243b581f..81c66cf983f80d3d7444f09624cf21b77fe41b14 100644
--- a/content/child/webcrypto/shared_crypto.cc
+++ b/content/child/webcrypto/shared_crypto.cc
@@ -20,6 +20,17 @@ namespace content {
namespace webcrypto {
+// ------------
+// Threading:
+// ------------
+//
+// All functions in this file are called from the webcrypto worker pool except
+// for:
+//
+// * SerializeKeyForClone()
+// * DeserializeKeyForClone()
+// * ImportKey() // TODO(eroman): Change this.
+
namespace {
// TODO(eroman): Move this helper to WebCryptoKey.
@@ -66,7 +77,7 @@ Status EncryptDecryptAesCbc(EncryptOrDecrypt mode,
const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
platform::SymKey* sym_key;
Status status = ToPlatformSymKey(key, &sym_key);
if (status.IsError())
@@ -87,7 +98,7 @@ Status EncryptDecryptAesGcm(EncryptOrDecrypt mode,
const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
platform::SymKey* sym_key;
Status status = ToPlatformSymKey(key, &sym_key);
if (status.IsError())
@@ -119,7 +130,7 @@ Status EncryptDecryptAesGcm(EncryptOrDecrypt mode,
Status EncryptRsaEsPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
platform::PublicKey* public_key;
Status status = ToPlatformPublicKey(key, &public_key);
if (status.IsError())
@@ -135,7 +146,7 @@ Status EncryptRsaEsPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm,
Status DecryptRsaEsPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
platform::PrivateKey* private_key;
Status status = ToPlatformPrivateKey(key, &private_key);
if (status.IsError())
@@ -151,7 +162,7 @@ Status DecryptRsaEsPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm,
Status SignHmac(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
platform::SymKey* sym_key;
Status status = ToPlatformSymKey(key, &sym_key);
if (status.IsError())
@@ -166,16 +177,16 @@ Status VerifyHmac(const blink::WebCryptoAlgorithm& algorithm,
const CryptoData& signature,
const CryptoData& data,
bool* signature_match) {
- blink::WebArrayBuffer result;
+ std::vector<uint8> result;
Status status = SignHmac(algorithm, key, data, &result);
if (status.IsError())
return status;
// Do not allow verification of truncated MACs.
*signature_match =
- result.byteLength() == signature.byte_length() &&
+ result.size() == signature.byte_length() &&
crypto::SecureMemEqual(
- result.data(), signature.bytes(), signature.byte_length());
+ Uint8VectorStart(result), signature.bytes(), signature.byte_length());
return Status::Success();
}
@@ -183,7 +194,7 @@ Status VerifyHmac(const blink::WebCryptoAlgorithm& algorithm,
Status SignRsaSsaPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
platform::PrivateKey* private_key;
Status status = ToPlatformPrivateKey(key, &private_key);
if (status.IsError())
@@ -211,6 +222,7 @@ Status VerifyRsaSsaPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm,
signature_match);
}
+// Note that this function may be called from the target Blink thread.
Status ImportKeyRaw(const CryptoData& key_data,
const blink::WebCryptoAlgorithm& algorithm,
bool extractable,
@@ -273,40 +285,40 @@ blink::WebCryptoAlgorithm KeyAlgorithmToImportAlgorithm(
//
// A failure here implies either a bug in the code, or that the serialized data
// was corrupted.
-Status ValidateDeserializedKey(const blink::WebCryptoKey& key,
- const blink::WebCryptoKeyAlgorithm& algorithm,
- blink::WebCryptoKeyType type) {
+bool ValidateDeserializedKey(const blink::WebCryptoKey& key,
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ blink::WebCryptoKeyType type) {
if (algorithm.id() != key.algorithm().id())
- return Status::ErrorUnexpected();
+ return false;
if (key.type() != type)
- return Status::ErrorUnexpected();
+ return false;
switch (algorithm.paramsType()) {
case blink::WebCryptoKeyAlgorithmParamsTypeAes:
if (algorithm.aesParams()->lengthBits() !=
key.algorithm().aesParams()->lengthBits())
- return Status::ErrorUnexpected();
+ return false;
break;
case blink::WebCryptoKeyAlgorithmParamsTypeRsa:
case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
if (algorithm.rsaParams()->modulusLengthBits() !=
key.algorithm().rsaParams()->modulusLengthBits())
- return Status::ErrorUnexpected();
+ return false;
if (algorithm.rsaParams()->publicExponent().size() !=
key.algorithm().rsaParams()->publicExponent().size())
- return Status::ErrorUnexpected();
+ return false;
if (memcmp(algorithm.rsaParams()->publicExponent().data(),
key.algorithm().rsaParams()->publicExponent().data(),
key.algorithm().rsaParams()->publicExponent().size()) != 0)
- return Status::ErrorUnexpected();
+ return false;
break;
case blink::WebCryptoKeyAlgorithmParamsTypeNone:
case blink::WebCryptoKeyAlgorithmParamsTypeHmac:
break;
}
- return Status::Success();
+ return true;
}
// Validates the size of data input to AES-KW. AES-KW requires the input data
@@ -366,7 +378,7 @@ Status UnwrapKeyRaw(const CryptoData& wrapped_key_data,
Status WrapKeyRaw(const blink::WebCryptoKey& wrapping_key,
const blink::WebCryptoKey& key_to_wrap,
const blink::WebCryptoAlgorithm& wrapping_algorithm,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
// A raw key is always a symmetric key.
platform::SymKey* platform_key;
Status status = ToPlatformSymKey(key_to_wrap, &platform_key);
@@ -399,7 +411,7 @@ Status WrapKeyRaw(const blink::WebCryptoKey& wrapping_key,
Status DecryptAesKw(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
platform::SymKey* sym_key;
Status status = ToPlatformSymKey(key, &sym_key);
if (status.IsError())
@@ -413,7 +425,7 @@ Status DecryptAesKw(const blink::WebCryptoAlgorithm& algorithm,
Status DecryptDontCheckKeyUsage(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
if (algorithm.id() != key.algorithm().id())
return Status::ErrorUnexpected();
switch (algorithm.id()) {
@@ -433,7 +445,7 @@ Status DecryptDontCheckKeyUsage(const blink::WebCryptoAlgorithm& algorithm,
Status EncryptDontCheckUsage(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
if (algorithm.id() != key.algorithm().id())
return Status::ErrorUnexpected();
switch (algorithm.id()) {
@@ -457,7 +469,7 @@ Status UnwrapKeyDecryptAndImport(
bool extractable,
blink::WebCryptoKeyUsageMask usage_mask,
blink::WebCryptoKey* key) {
- blink::WebArrayBuffer buffer;
+ std::vector<uint8> buffer;
Status status = DecryptDontCheckKeyUsage(
wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer);
if (status.IsError())
@@ -475,8 +487,8 @@ Status WrapKeyExportAndEncrypt(
const blink::WebCryptoKey& wrapping_key,
const blink::WebCryptoKey& key_to_wrap,
const blink::WebCryptoAlgorithm& wrapping_algorithm,
- blink::WebArrayBuffer* buffer) {
- blink::WebArrayBuffer exported_data;
+ std::vector<uint8>* buffer) {
+ std::vector<uint8> exported_data;
Status status = ExportKey(format, key_to_wrap, &exported_data);
if (status.IsError())
return status;
@@ -506,7 +518,7 @@ void Init() { platform::Init(); }
Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt))
return Status::ErrorUnexpected();
return EncryptDontCheckUsage(algorithm, key, data, buffer);
@@ -515,7 +527,7 @@ Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt))
return Status::ErrorUnexpected();
return DecryptDontCheckKeyUsage(algorithm, key, data, buffer);
@@ -523,7 +535,7 @@ Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
Status Digest(const blink::WebCryptoAlgorithm& algorithm,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
switch (algorithm.id()) {
case blink::WebCryptoAlgorithmIdSha1:
case blink::WebCryptoAlgorithmIdSha256:
@@ -626,6 +638,7 @@ Status GenerateKeyPair(const blink::WebCryptoAlgorithm& algorithm,
}
}
+// Note that this function may be called from the target Blink thread.
Status ImportKey(blink::WebCryptoKeyFormat format,
const CryptoData& key_data,
const blink::WebCryptoAlgorithm& algorithm,
@@ -651,7 +664,7 @@ Status ImportKey(blink::WebCryptoKeyFormat format,
// TODO(eroman): Move this to anonymous namespace.
Status ExportKeyDontCheckExtractability(blink::WebCryptoKeyFormat format,
const blink::WebCryptoKey& key,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
switch (format) {
case blink::WebCryptoKeyFormatRaw: {
platform::SymKey* sym_key;
@@ -683,7 +696,7 @@ Status ExportKeyDontCheckExtractability(blink::WebCryptoKeyFormat format,
Status ExportKey(blink::WebCryptoKeyFormat format,
const blink::WebCryptoKey& key,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
if (!key.extractable())
return Status::ErrorKeyNotExtractable();
return ExportKeyDontCheckExtractability(format, key, buffer);
@@ -692,7 +705,7 @@ Status ExportKey(blink::WebCryptoKeyFormat format,
Status Sign(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& data,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageSign))
return Status::ErrorUnexpected();
if (algorithm.id() != key.algorithm().id())
@@ -741,7 +754,7 @@ Status WrapKey(blink::WebCryptoKeyFormat format,
const blink::WebCryptoKey& wrapping_key,
const blink::WebCryptoKey& key_to_wrap,
const blink::WebCryptoAlgorithm& wrapping_algorithm,
- blink::WebArrayBuffer* buffer) {
+ std::vector<uint8>* buffer) {
if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageWrapKey))
return Status::ErrorUnexpected();
if (wrapping_algorithm.id() != wrapping_key.algorithm().id())
@@ -802,24 +815,28 @@ Status UnwrapKey(blink::WebCryptoKeyFormat format,
}
}
-Status SerializeKeyForClone(const blink::WebCryptoKey& key,
- blink::WebVector<unsigned char>* data) {
- blink::WebArrayBuffer buffer;
- Status status = ExportKeyDontCheckExtractability(
- GetCloneFormatForKeyType(key.type()), key, &buffer);
- if (status.IsError())
- return status;
- data->assign(
- reinterpret_cast<unsigned char*>(buffer.data()), buffer.byteLength());
- return Status::Success();
-}
-
-Status DeserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm,
- blink::WebCryptoKeyType type,
- bool extractable,
- blink::WebCryptoKeyUsageMask usage_mask,
- const CryptoData& key_data,
- blink::WebCryptoKey* key) {
+// Note that this function is called from the target Blink thread.
+bool SerializeKeyForClone(const blink::WebCryptoKey& key,
+ blink::WebVector<uint8>* key_data) {
+ return static_cast<webcrypto::platform::Key*>(key.handle())
+ ->ThreadSafeSerializeForClone(key_data);
+}
+
+// Note that this function is called from the target Blink thread.
+bool DeserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm,
+ blink::WebCryptoKeyType type,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ const CryptoData& key_data,
+ blink::WebCryptoKey* key) {
+ // TODO(eroman): This should not call into the platform crypto layer.
+ // Otherwise it runs the risk of stalling while the NSS/OpenSSL global locks
+ // are held.
+ //
+ // An alternate approach is to defer the key import until the key is used.
+ // However this means that any deserialization errors would have to be
+ // surfaced as WebCrypto errors, leading to slightly different behaviors. For
+ // instance you could clone a key which fails to be deserialized.
Status status = ImportKey(GetCloneFormatForKeyType(type),
key_data,
KeyAlgorithmToImportAlgorithm(algorithm),
@@ -827,8 +844,7 @@ Status DeserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm,
usage_mask,
key);
if (status.IsError())
- return status;
-
+ return false;
return ValidateDeserializedKey(*key, algorithm, type);
}

Powered by Google App Engine
This is Rietveld 408576698