| Index: content/child/webcrypto/structured_clone.cc
|
| diff --git a/content/child/webcrypto/structured_clone.cc b/content/child/webcrypto/structured_clone.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..00f617af3abf61b22c3510daa6123bb74a2daa58
|
| --- /dev/null
|
| +++ b/content/child/webcrypto/structured_clone.cc
|
| @@ -0,0 +1,136 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "content/child/webcrypto/structured_clone.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "content/child/webcrypto/algorithm_dispatch.h"
|
| +#include "content/child/webcrypto/platform_crypto.h"
|
| +#include "content/child/webcrypto/status.h"
|
| +#include "content/child/webcrypto/webcrypto_util.h"
|
| +#include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
|
| +
|
| +namespace content {
|
| +
|
| +namespace webcrypto {
|
| +
|
| +namespace {
|
| +
|
| +// Returns the key format to use for structured cloning.
|
| +blink::WebCryptoKeyFormat GetCloneFormatForKeyType(
|
| + blink::WebCryptoKeyType type) {
|
| + switch (type) {
|
| + case blink::WebCryptoKeyTypeSecret:
|
| + return blink::WebCryptoKeyFormatRaw;
|
| + case blink::WebCryptoKeyTypePublic:
|
| + return blink::WebCryptoKeyFormatSpki;
|
| + case blink::WebCryptoKeyTypePrivate:
|
| + return blink::WebCryptoKeyFormatPkcs8;
|
| + }
|
| +
|
| + NOTREACHED();
|
| + return blink::WebCryptoKeyFormatRaw;
|
| +}
|
| +
|
| +// Converts a KeyAlgorithm into an equivalent Algorithm for import.
|
| +blink::WebCryptoAlgorithm KeyAlgorithmToImportAlgorithm(
|
| + const blink::WebCryptoKeyAlgorithm& algorithm) {
|
| + switch (algorithm.paramsType()) {
|
| + case blink::WebCryptoKeyAlgorithmParamsTypeAes:
|
| + return CreateAlgorithm(algorithm.id());
|
| + case blink::WebCryptoKeyAlgorithmParamsTypeHmac:
|
| + return CreateHmacImportAlgorithm(algorithm.hmacParams()->hash().id());
|
| + case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
|
| + return CreateRsaHashedImportAlgorithm(
|
| + algorithm.id(), algorithm.rsaHashedParams()->hash().id());
|
| + case blink::WebCryptoKeyAlgorithmParamsTypeNone:
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + return blink::WebCryptoAlgorithm::createNull();
|
| +}
|
| +
|
| +// There is some duplicated information in the serialized format used by
|
| +// structured clone (since the KeyAlgorithm is serialized separately from the
|
| +// key data). Use this extra information to further validate what was
|
| +// deserialized from the key data.
|
| +//
|
| +// A failure here implies either a bug in the code, or that the serialized data
|
| +// was corrupted.
|
| +bool ValidateDeserializedKey(const blink::WebCryptoKey& key,
|
| + const blink::WebCryptoKeyAlgorithm& algorithm,
|
| + blink::WebCryptoKeyType type) {
|
| + if (algorithm.id() != key.algorithm().id())
|
| + return false;
|
| +
|
| + if (key.type() != type)
|
| + return false;
|
| +
|
| + switch (algorithm.paramsType()) {
|
| + case blink::WebCryptoKeyAlgorithmParamsTypeAes:
|
| + if (algorithm.aesParams()->lengthBits() !=
|
| + key.algorithm().aesParams()->lengthBits())
|
| + return false;
|
| + break;
|
| + case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
|
| + if (algorithm.rsaHashedParams()->modulusLengthBits() !=
|
| + key.algorithm().rsaHashedParams()->modulusLengthBits())
|
| + return false;
|
| + if (algorithm.rsaHashedParams()->publicExponent().size() !=
|
| + key.algorithm().rsaHashedParams()->publicExponent().size())
|
| + return false;
|
| + if (memcmp(algorithm.rsaHashedParams()->publicExponent().data(),
|
| + key.algorithm().rsaHashedParams()->publicExponent().data(),
|
| + key.algorithm().rsaHashedParams()->publicExponent().size()) !=
|
| + 0)
|
| + return false;
|
| + break;
|
| + case blink::WebCryptoKeyAlgorithmParamsTypeNone:
|
| + case blink::WebCryptoKeyAlgorithmParamsTypeHmac:
|
| + break;
|
| + default:
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// Note that this function is called from the target Blink thread.
|
| +bool SerializeKeyForClone(const blink::WebCryptoKey& key,
|
| + blink::WebVector<uint8>* key_data) {
|
| + return PlatformSerializeKeyForClone(key, 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),
|
| + extractable,
|
| + usage_mask,
|
| + key);
|
| + if (status.IsError())
|
| + return false;
|
| + return ValidateDeserializedKey(*key, algorithm, type);
|
| +}
|
| +
|
| +} // namespace webcrypto
|
| +
|
| +} // namespace content
|
|
|