| Index: content/child/webcrypto/shared_crypto.cc
|
| diff --git a/content/child/webcrypto/shared_crypto.cc b/content/child/webcrypto/shared_crypto.cc
|
| index b0097c1cad593c903258e167bf641a44c76f8aa1..5488353c21b0c3e3a68b947c83d6aeee66b84466 100644
|
| --- a/content/child/webcrypto/shared_crypto.cc
|
| +++ b/content/child/webcrypto/shared_crypto.cc
|
| @@ -233,6 +233,126 @@ Status ImportKeyRaw(const CryptoData& key_data,
|
| }
|
| }
|
|
|
| +// Validates the size of data input to AES-KW. AES-KW requires the input data
|
| +// size to be at least 24 bytes and a multiple of 8 bytes.
|
| +Status CheckAesKwInputSize(const CryptoData& aeskw_input_data) {
|
| + if (aeskw_input_data.byte_length() < 24)
|
| + return Status::ErrorDataTooSmall();
|
| + if (aeskw_input_data.byte_length() % 8)
|
| + return Status::ErrorInvalidAesKwDataLength();
|
| + return Status::Success();
|
| +}
|
| +
|
| +Status UnwrapKeyRaw(const CryptoData& wrapped_key_data,
|
| + const blink::WebCryptoKey& wrapping_key,
|
| + const blink::WebCryptoAlgorithm& wrapping_algorithm,
|
| + const blink::WebCryptoAlgorithm& algorithm_or_null,
|
| + bool extractable,
|
| + blink::WebCryptoKeyUsageMask usage_mask,
|
| + blink::WebCryptoKey* key) {
|
| + // Must provide an algorithm when unwrapping a raw key
|
| + if (algorithm_or_null.isNull())
|
| + return Status::ErrorMissingAlgorithmUnwrapRawKey();
|
| +
|
| + // TODO(padolph): Handle other wrapping algorithms
|
| + switch (wrapping_algorithm.id()) {
|
| + case blink::WebCryptoAlgorithmIdAesKw: {
|
| + platform::SymKey* platform_wrapping_key;
|
| + Status status = ToPlatformSymKey(wrapping_key, &platform_wrapping_key);
|
| + if (status.IsError())
|
| + return status;
|
| + status = CheckAesKwInputSize(wrapped_key_data);
|
| + if (status.IsError())
|
| + return status;
|
| + return platform::UnwrapSymKeyAesKw(wrapped_key_data,
|
| + platform_wrapping_key,
|
| + algorithm_or_null,
|
| + extractable,
|
| + usage_mask,
|
| + key);
|
| + }
|
| + case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: {
|
| + platform::PrivateKey* platform_wrapping_key;
|
| + Status status =
|
| + ToPlatformPrivateKey(wrapping_key, &platform_wrapping_key);
|
| + if (status.IsError())
|
| + return status;
|
| + if (!wrapped_key_data.byte_length())
|
| + return Status::ErrorDataTooSmall();
|
| + return platform::UnwrapSymKeyRsaEs(wrapped_key_data,
|
| + platform_wrapping_key,
|
| + algorithm_or_null,
|
| + extractable,
|
| + usage_mask,
|
| + key);
|
| + }
|
| + default:
|
| + return Status::ErrorUnsupported();
|
| + }
|
| +}
|
| +
|
| +Status DecryptAesKw(const blink::WebCryptoAlgorithm& algorithm,
|
| + const blink::WebCryptoKey& key,
|
| + const CryptoData& data,
|
| + blink::WebArrayBuffer* buffer) {
|
| + platform::SymKey* sym_key;
|
| + Status status = ToPlatformSymKey(key, &sym_key);
|
| + if (status.IsError())
|
| + return status;
|
| + status = CheckAesKwInputSize(data);
|
| + if (status.IsError())
|
| + return status;
|
| + return platform::DecryptAesKw(sym_key, data, buffer);
|
| +}
|
| +
|
| +Status DecryptDontCheckKeyUsage(const blink::WebCryptoAlgorithm& algorithm,
|
| + const blink::WebCryptoKey& key,
|
| + const CryptoData& data,
|
| + blink::WebArrayBuffer* buffer) {
|
| + if (algorithm.id() != key.algorithm().id())
|
| + return Status::ErrorUnexpected();
|
| + switch (algorithm.id()) {
|
| + case blink::WebCryptoAlgorithmIdAesCbc:
|
| + return EncryptDecryptAesCbc(DECRYPT, algorithm, key, data, buffer);
|
| + case blink::WebCryptoAlgorithmIdAesGcm:
|
| + return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer);
|
| + case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
|
| + return DecryptRsaEsPkcs1v1_5(algorithm, key, data, buffer);
|
| + case blink::WebCryptoAlgorithmIdAesKw:
|
| + return DecryptAesKw(algorithm, key, data, buffer);
|
| + default:
|
| + return Status::ErrorUnsupported();
|
| + }
|
| +}
|
| +
|
| +Status UnwrapKeyDecryptAndImport(
|
| + blink::WebCryptoKeyFormat format,
|
| + const CryptoData& wrapped_key_data,
|
| + const blink::WebCryptoKey& wrapping_key,
|
| + const blink::WebCryptoAlgorithm& wrapping_algorithm,
|
| + const blink::WebCryptoAlgorithm& algorithm_or_null,
|
| + bool extractable,
|
| + blink::WebCryptoKeyUsageMask usage_mask,
|
| + blink::WebCryptoKey* key) {
|
| + if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey))
|
| + return Status::ErrorUnexpected();
|
| + blink::WebArrayBuffer buffer;
|
| + Status status = DecryptDontCheckKeyUsage(
|
| + wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer);
|
| + if (status.IsError())
|
| + return status;
|
| + status = ImportKey(format,
|
| + CryptoData(buffer),
|
| + algorithm_or_null,
|
| + extractable,
|
| + usage_mask,
|
| + key);
|
| + // NOTE! Returning the details of any ImportKey() failure here would leak
|
| + // information about the plaintext internals of the encrypted key. Instead,
|
| + // collapse any error into the generic Status::Error().
|
| + return status.IsError() ? Status::Error() : Status::Success();
|
| +}
|
| +
|
| } // namespace
|
|
|
| void Init() { platform::Init(); }
|
| @@ -264,19 +384,7 @@ Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
|
| blink::WebArrayBuffer* buffer) {
|
| if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt))
|
| return Status::ErrorUnexpected();
|
| - if (algorithm.id() != key.algorithm().id())
|
| - return Status::ErrorUnexpected();
|
| -
|
| - switch (algorithm.id()) {
|
| - case blink::WebCryptoAlgorithmIdAesCbc:
|
| - return EncryptDecryptAesCbc(DECRYPT, algorithm, key, data, buffer);
|
| - case blink::WebCryptoAlgorithmIdAesGcm:
|
| - return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer);
|
| - case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
|
| - return DecryptRsaEsPkcs1v1_5(algorithm, key, data, buffer);
|
| - default:
|
| - return Status::ErrorUnsupported();
|
| - }
|
| + return DecryptDontCheckKeyUsage(algorithm, key, data, buffer);
|
| }
|
|
|
| Status Digest(const blink::WebCryptoAlgorithm& algorithm,
|
| @@ -424,8 +532,9 @@ Status ExportKey(blink::WebCryptoKeyFormat format,
|
| return status;
|
| return platform::ExportKeySpki(public_key, buffer);
|
| }
|
| - case blink::WebCryptoKeyFormatPkcs8:
|
| case blink::WebCryptoKeyFormatJwk:
|
| + return ExportKeyJwk(key, buffer);
|
| + case blink::WebCryptoKeyFormatPkcs8:
|
| // TODO(eroman):
|
| return Status::ErrorUnsupported();
|
| default:
|
| @@ -539,50 +648,29 @@ Status UnwrapKey(blink::WebCryptoKeyFormat format,
|
| if (wrapping_algorithm.id() != wrapping_key.algorithm().id())
|
| return Status::ErrorUnexpected();
|
|
|
| - // TODO(padolph): Handle formats other than raw
|
| - if (format != blink::WebCryptoKeyFormatRaw)
|
| - return Status::ErrorUnsupported();
|
| -
|
| - // Must provide an algorithm when unwrapping a raw key
|
| - if (format == blink::WebCryptoKeyFormatRaw && algorithm_or_null.isNull())
|
| - return Status::ErrorMissingAlgorithmUnwrapRawKey();
|
| -
|
| - // TODO(padolph): Handle other wrapping algorithms
|
| - switch (wrapping_algorithm.id()) {
|
| - case blink::WebCryptoAlgorithmIdAesKw: {
|
| - platform::SymKey* platform_wrapping_key;
|
| - Status status = ToPlatformSymKey(wrapping_key, &platform_wrapping_key);
|
| - if (status.IsError())
|
| - return status;
|
| - // AES-KW requires the wrapped key data size must be at least 24 bytes and
|
| - // also a multiple of 8 bytes.
|
| - if (wrapped_key_data.byte_length() < 24)
|
| - return Status::ErrorDataTooSmall();
|
| - if (wrapped_key_data.byte_length() % 8)
|
| - return Status::ErrorInvalidAesKwDataLength();
|
| - return platform::UnwrapSymKeyAesKw(wrapped_key_data,
|
| - platform_wrapping_key,
|
| - algorithm_or_null,
|
| - extractable,
|
| - usage_mask,
|
| - key);
|
| - }
|
| - case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: {
|
| - platform::PrivateKey* platform_wrapping_key;
|
| - Status status =
|
| - ToPlatformPrivateKey(wrapping_key, &platform_wrapping_key);
|
| - if (status.IsError())
|
| - return status;
|
| - if (!wrapped_key_data.byte_length())
|
| - return Status::ErrorDataTooSmall();
|
| - return platform::UnwrapSymKeyRsaEs(wrapped_key_data,
|
| - platform_wrapping_key,
|
| - algorithm_or_null,
|
| - extractable,
|
| - usage_mask,
|
| - key);
|
| - }
|
| + switch (format) {
|
| + case blink::WebCryptoKeyFormatRaw:
|
| + return UnwrapKeyRaw(wrapped_key_data,
|
| + wrapping_key,
|
| + wrapping_algorithm,
|
| + algorithm_or_null,
|
| + extractable,
|
| + usage_mask,
|
| + key);
|
| + case blink::WebCryptoKeyFormatJwk:
|
| + return UnwrapKeyDecryptAndImport(format,
|
| + wrapped_key_data,
|
| + wrapping_key,
|
| + wrapping_algorithm,
|
| + algorithm_or_null,
|
| + extractable,
|
| + usage_mask,
|
| + key);
|
| + case blink::WebCryptoKeyFormatSpki:
|
| + case blink::WebCryptoKeyFormatPkcs8:
|
| + return Status::ErrorUnsupported(); // TODO(padolph)
|
| default:
|
| + NOTREACHED();
|
| return Status::ErrorUnsupported();
|
| }
|
| }
|
|
|