Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Unified Diff: content/child/webcrypto/shared_crypto.cc

Issue 195983010: [webcrypto] Add JWK symmetric key AES-KW unwrap for NSS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..7d54bdf26168614cdc5cdcf73f04fafcb58c6211 100644
--- a/content/child/webcrypto/shared_crypto.cc
+++ b/content/child/webcrypto/shared_crypto.cc
@@ -26,6 +26,11 @@ bool KeyUsageAllows(const blink::WebCryptoKey& key,
return ((key.usages() & usage) != 0);
}
+bool KeyUsageAllowsAnyOf(const blink::WebCryptoKey& key,
+ const blink::WebCryptoKeyUsageMask usage_mask) {
+ return ((key.usages() & usage_mask) != 0);
+}
+
bool IsValidAesKeyLengthBits(unsigned int length_bits) {
return length_bits == 128 || length_bits == 192 || length_bits == 256;
}
@@ -233,6 +238,104 @@ 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 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) {
+ blink::WebArrayBuffer buffer;
+ Status status =
+ Decrypt(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();
+}
+
+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);
+}
+
} // namespace
void Init() { platform::Init(); }
@@ -262,18 +365,38 @@ Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
const blink::WebCryptoKey& key,
const CryptoData& data,
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:
+ case blink::WebCryptoAlgorithmIdAesGcm:
+ if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt))
eroman 2014/03/17 19:47:47 I don't like having an extra switch for verifying
padolph 2014/03/17 22:12:49 Done.
+ return Status::ErrorUnexpected();
+ break;
+ case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
+ if (!KeyUsageAllowsAnyOf(key,
+ blink::WebCryptoKeyUsageDecrypt |
+ blink::WebCryptoKeyUsageUnwrapKey))
+ return Status::ErrorUnexpected();
+ break;
+ case blink::WebCryptoAlgorithmIdAesKw:
+ if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageUnwrapKey))
+ return Status::ErrorUnexpected();
+ break;
+ default:
+ return Status::ErrorUnsupported();
+ }
+
+ 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();
}
@@ -424,8 +547,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 +663,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();
}
}

Powered by Google App Engine
This is Rietveld 408576698