summaryrefslogtreecommitdiffstats
path: root/content/child/webcrypto
diff options
context:
space:
mode:
authoreroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-18 20:27:08 +0000
committereroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-18 20:27:08 +0000
commit5daca04707be94c5b2991ae5e7f7ebd1c76352bc (patch)
tree79320ef3123d0bb8185a182724d7d704af723032 /content/child/webcrypto
parentb7e61c2219059a2b2bda9eb76fabbbba2c121e8c (diff)
downloadchromium_src-5daca04707be94c5b2991ae5e7f7ebd1c76352bc.zip
chromium_src-5daca04707be94c5b2991ae5e7f7ebd1c76352bc.tar.gz
chromium_src-5daca04707be94c5b2991ae5e7f7ebd1c76352bc.tar.bz2
[webcrypto] Implement structured clone of keys (chromium-side).
The serialized format saves keys as: * spki for public RSA keys * pkcs8 for private RSA keys * raw for AES and HMAC keys The testing for this is done on the blink side by (see https://codereview.chromium.org/195543002/) [2] PKCS8 import/export is not yet implemented. I will re-visit the serialization of private keys in a follow-up change. BUG=245025 Review URL: https://codereview.chromium.org/196513002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@257723 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/child/webcrypto')
-rw-r--r--content/child/webcrypto/shared_crypto.cc125
-rw-r--r--content/child/webcrypto/shared_crypto.h12
-rw-r--r--content/child/webcrypto/shared_crypto_unittest.cc11
-rw-r--r--content/child/webcrypto/webcrypto_impl.cc25
-rw-r--r--content/child/webcrypto/webcrypto_impl.h13
-rw-r--r--content/child/webcrypto/webcrypto_util.cc20
-rw-r--r--content/child/webcrypto/webcrypto_util.h7
7 files changed, 189 insertions, 24 deletions
diff --git a/content/child/webcrypto/shared_crypto.cc b/content/child/webcrypto/shared_crypto.cc
index b0097c1..1ce45cd 100644
--- a/content/child/webcrypto/shared_crypto.cc
+++ b/content/child/webcrypto/shared_crypto.cc
@@ -233,6 +233,83 @@ Status ImportKeyRaw(const CryptoData& key_data,
}
}
+// 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:
+ case blink::WebCryptoKeyAlgorithmParamsTypeRsa:
+ 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;
+ }
+ 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.
+Status ValidateDeserializedKey(const blink::WebCryptoKey& key,
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ blink::WebCryptoKeyType type) {
+ if (algorithm.id() != key.algorithm().id())
+ return Status::ErrorUnexpected();
+
+ if (key.type() != type)
+ return Status::ErrorUnexpected();
+
+ switch (algorithm.paramsType()) {
+ case blink::WebCryptoKeyAlgorithmParamsTypeAes:
+ if (algorithm.aesParams()->lengthBits() !=
+ key.algorithm().aesParams()->lengthBits())
+ return Status::ErrorUnexpected();
+ break;
+ case blink::WebCryptoKeyAlgorithmParamsTypeRsa:
+ case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
+ if (algorithm.rsaParams()->modulusLengthBits() !=
+ key.algorithm().rsaParams()->modulusLengthBits())
+ return Status::ErrorUnexpected();
+ if (algorithm.rsaParams()->publicExponent().size() !=
+ key.algorithm().rsaParams()->publicExponent().size())
+ return Status::ErrorUnexpected();
+ if (memcmp(algorithm.rsaParams()->publicExponent().data(),
+ key.algorithm().rsaParams()->publicExponent().data(),
+ key.algorithm().rsaParams()->publicExponent().size()) != 0)
+ return Status::ErrorUnexpected();
+ break;
+ case blink::WebCryptoKeyAlgorithmParamsTypeNone:
+ case blink::WebCryptoKeyAlgorithmParamsTypeHmac:
+ break;
+ }
+
+ return Status::Success();
+}
+
} // namespace
void Init() { platform::Init(); }
@@ -403,12 +480,10 @@ Status ImportKey(blink::WebCryptoKeyFormat format,
}
}
-Status ExportKey(blink::WebCryptoKeyFormat format,
- const blink::WebCryptoKey& key,
- blink::WebArrayBuffer* buffer) {
- if (!key.extractable())
- return Status::ErrorKeyNotExtractable();
-
+// TODO(eroman): Move this to anonymous namespace.
+Status ExportKeyDontCheckExtractability(blink::WebCryptoKeyFormat format,
+ const blink::WebCryptoKey& key,
+ blink::WebArrayBuffer* buffer) {
switch (format) {
case blink::WebCryptoKeyFormatRaw: {
platform::SymKey* sym_key;
@@ -433,6 +508,14 @@ Status ExportKey(blink::WebCryptoKeyFormat format,
}
}
+Status ExportKey(blink::WebCryptoKeyFormat format,
+ const blink::WebCryptoKey& key,
+ blink::WebArrayBuffer* buffer) {
+ if (!key.extractable())
+ return Status::ErrorKeyNotExtractable();
+ return ExportKeyDontCheckExtractability(format, key, buffer);
+}
+
Status Sign(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& data,
@@ -587,6 +670,36 @@ 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) {
+ Status status = ImportKey(GetCloneFormatForKeyType(type),
+ key_data,
+ KeyAlgorithmToImportAlgorithm(algorithm),
+ extractable,
+ usage_mask,
+ key);
+ if (status.IsError())
+ return status;
+
+ return ValidateDeserializedKey(*key, algorithm, type);
+}
+
} // namespace webcrypto
} // namespace content
diff --git a/content/child/webcrypto/shared_crypto.h b/content/child/webcrypto/shared_crypto.h
index f668a8a..6ff3af9 100644
--- a/content/child/webcrypto/shared_crypto.h
+++ b/content/child/webcrypto/shared_crypto.h
@@ -151,6 +151,18 @@ CONTENT_EXPORT Status
blink::WebCryptoKeyUsageMask usage_mask,
blink::WebCryptoKey* key);
+CONTENT_EXPORT Status
+ SerializeKeyForClone(const blink::WebCryptoKey& key,
+ blink::WebVector<unsigned char>* data);
+
+CONTENT_EXPORT Status
+ DeserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm,
+ blink::WebCryptoKeyType type,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usage_mask,
+ const CryptoData& key_data,
+ blink::WebCryptoKey* key);
+
} // namespace webcrypto
} // namespace content
diff --git a/content/child/webcrypto/shared_crypto_unittest.cc b/content/child/webcrypto/shared_crypto_unittest.cc
index a71b52f..d19ee29 100644
--- a/content/child/webcrypto/shared_crypto_unittest.cc
+++ b/content/child/webcrypto/shared_crypto_unittest.cc
@@ -319,17 +319,6 @@ void RestoreJwkRsaDictionary(base::DictionaryValue* dict) {
dict->SetString("e", "AQAB");
}
-blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm(
- blink::WebCryptoAlgorithmId algorithm_id,
- blink::WebCryptoAlgorithmId hash_id) {
- DCHECK(algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
- algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep);
- DCHECK(IsHashAlgorithm(hash_id));
- return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
- algorithm_id,
- new blink::WebCryptoRsaHashedImportParams(CreateAlgorithm(hash_id)));
-}
-
// Determines if two ArrayBuffers have identical content.
bool ArrayBuffersEqual(const blink::WebArrayBuffer& a,
const blink::WebArrayBuffer& b) {
diff --git a/content/child/webcrypto/webcrypto_impl.cc b/content/child/webcrypto/webcrypto_impl.cc
index 1af726d..97d1372 100644
--- a/content/child/webcrypto/webcrypto_impl.cc
+++ b/content/child/webcrypto/webcrypto_impl.cc
@@ -207,4 +207,29 @@ bool WebCryptoImpl::digestSynchronous(
.IsSuccess();
}
+bool WebCryptoImpl::deserializeKeyForClone(
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ blink::WebCryptoKeyType type,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ const unsigned char* key_data,
+ unsigned key_data_size,
+ blink::WebCryptoKey& key) {
+ Status status = webcrypto::DeserializeKeyForClone(
+ algorithm,
+ type,
+ extractable,
+ usages,
+ webcrypto::CryptoData(key_data, key_data_size),
+ &key);
+ return status.IsSuccess();
+}
+
+bool WebCryptoImpl::serializeKeyForClone(
+ const blink::WebCryptoKey& key,
+ blink::WebVector<unsigned char>& key_data) {
+ Status status = webcrypto::SerializeKeyForClone(key, &key_data);
+ return status.IsSuccess();
+}
+
} // namespace content
diff --git a/content/child/webcrypto/webcrypto_impl.h b/content/child/webcrypto/webcrypto_impl.h
index 0014715..261a9ef 100644
--- a/content/child/webcrypto/webcrypto_impl.h
+++ b/content/child/webcrypto/webcrypto_impl.h
@@ -9,6 +9,7 @@
#include "base/compiler_specific.h"
#include "third_party/WebKit/public/platform/WebCrypto.h"
#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
+#include "third_party/WebKit/public/platform/WebVector.h"
namespace content {
@@ -68,6 +69,18 @@ class WebCryptoImpl : public blink::WebCrypto {
unsigned int data_size,
blink::WebArrayBuffer& result);
+ virtual bool deserializeKeyForClone(
+ const blink::WebCryptoKeyAlgorithm& algorithm,
+ blink::WebCryptoKeyType type,
+ bool extractable,
+ blink::WebCryptoKeyUsageMask usages,
+ const unsigned char* key_data,
+ unsigned key_data_size,
+ blink::WebCryptoKey& key);
+
+ virtual bool serializeKeyForClone(const blink::WebCryptoKey& key,
+ blink::WebVector<unsigned char>& key_data);
+
private:
DISALLOW_COPY_AND_ASSIGN(WebCryptoImpl);
};
diff --git a/content/child/webcrypto/webcrypto_util.cc b/content/child/webcrypto/webcrypto_util.cc
index 537e551..5e5fc8e 100644
--- a/content/child/webcrypto/webcrypto_util.cc
+++ b/content/child/webcrypto/webcrypto_util.cc
@@ -340,20 +340,26 @@ blink::WebCryptoAlgorithm CreateHmacImportAlgorithm(
new blink::WebCryptoHmacImportParams(CreateAlgorithm(hash_id)));
}
-blink::WebCryptoAlgorithm CreateRsaSsaImportAlgorithm(
+blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm(
+ blink::WebCryptoAlgorithmId id,
blink::WebCryptoAlgorithmId hash_id) {
DCHECK(IsHashAlgorithm(hash_id));
+ DCHECK(id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
+ id == blink::WebCryptoAlgorithmIdRsaOaep);
return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
- blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
- new blink::WebCryptoRsaHashedImportParams(CreateAlgorithm(hash_id)));
+ id, new blink::WebCryptoRsaHashedImportParams(CreateAlgorithm(hash_id)));
+}
+
+blink::WebCryptoAlgorithm CreateRsaSsaImportAlgorithm(
+ blink::WebCryptoAlgorithmId hash_id) {
+ return CreateRsaHashedImportAlgorithm(
+ blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, hash_id);
}
blink::WebCryptoAlgorithm CreateRsaOaepImportAlgorithm(
blink::WebCryptoAlgorithmId hash_id) {
- DCHECK(IsHashAlgorithm(hash_id));
- return blink::WebCryptoAlgorithm::adoptParamsAndCreate(
- blink::WebCryptoAlgorithmIdRsaOaep,
- new blink::WebCryptoRsaHashedImportParams(CreateAlgorithm(hash_id)));
+ return CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
+ hash_id);
}
unsigned int ShaBlockSizeBytes(blink::WebCryptoAlgorithmId hash_id) {
diff --git a/content/child/webcrypto/webcrypto_util.h b/content/child/webcrypto/webcrypto_util.h
index 9d23c73..98160b5 100644
--- a/content/child/webcrypto/webcrypto_util.h
+++ b/content/child/webcrypto/webcrypto_util.h
@@ -265,6 +265,13 @@ CONTENT_EXPORT blink::WebCryptoAlgorithm CreateAlgorithm(
CONTENT_EXPORT blink::WebCryptoAlgorithm CreateHmacImportAlgorithm(
blink::WebCryptoAlgorithmId hash_id);
+// Creates an import algorithm for RSA algorithms that take a hash.
+// It is an error to call this with a hash_id that is not a SHA*.
+CONTENT_EXPORT blink::WebCryptoAlgorithm CreateRsaHashedImportAlgorithm(
+ blink::WebCryptoAlgorithmId id,
+ blink::WebCryptoAlgorithmId hash_id);
+
+// TODO(eroman): Move these to jwk.cc
// Creates an RSASSA-PKCS1-v1_5 algorithm. It is an error to call this with a
// hash_id that is not a SHA*.
blink::WebCryptoAlgorithm CreateRsaSsaImportAlgorithm(