| 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);
|
| }
|
|
|
|
|