Chromium Code Reviews| Index: content/child/webcrypto/shared_crypto.cc |
| diff --git a/content/child/webcrypto/shared_crypto.cc b/content/child/webcrypto/shared_crypto.cc |
| index 1677270a86c2c94c2947fa6fafb11538a0c063d0..9fefcc25020cc22c3407e81a98c5b12a2f73a88e 100644 |
| --- a/content/child/webcrypto/shared_crypto.cc |
| +++ b/content/child/webcrypto/shared_crypto.cc |
| @@ -21,8 +21,7 @@ namespace webcrypto { |
| namespace { |
| // TODO(eroman): Move this helper to WebCryptoKey. |
| -bool KeyUsageAllows(const blink::WebCryptoKey& key, |
| - const blink::WebCryptoKeyUsage usage) { |
| +bool KeyUsageAllows(const blink::WebCryptoKey& key, unsigned int usage) { |
|
eroman
2014/03/14 22:14:53
This is not what I expect as a caller to KeyUsageA
padolph
2014/03/17 03:24:36
Done.
|
| return ((key.usages() & usage) != 0); |
| } |
| @@ -233,6 +232,100 @@ 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; |
| + return ImportKey(format, |
|
eroman
2014/03/14 22:14:53
I don't think we should return the error from Impo
padolph
2014/03/17 03:24:36
Thanks. I had seen your earlier comment in the cod
|
| + CryptoData(buffer), |
| + algorithm_or_null, |
| + extractable, |
| + usage_mask, |
| + key); |
| +} |
| + |
| +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 +355,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)) |
| + return Status::ErrorUnexpected(); |
| + break; |
| + case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
| + if (!KeyUsageAllows(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(); |
| } |
| @@ -430,8 +543,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: |
| @@ -545,50 +659,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(); |
| } |
| } |