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 |