| Index: content/child/webcrypto/shared_crypto_unittest.cc
|
| diff --git a/content/child/webcrypto/shared_crypto_unittest.cc b/content/child/webcrypto/shared_crypto_unittest.cc
|
| index a71b52fc187973fbabcc1f9839237b49335ce506..67825683798e6fa9d45d318b15930eb2fc976365 100644
|
| --- a/content/child/webcrypto/shared_crypto_unittest.cc
|
| +++ b/content/child/webcrypto/shared_crypto_unittest.cc
|
| @@ -2380,6 +2380,51 @@ TEST_F(SharedCryptoTest, MAYBE(AesKwKeyImport)) {
|
| &key));
|
| }
|
|
|
| +TEST_F(SharedCryptoTest, MAYBE(UnwrapFailures)) {
|
| + // This test exercises the code path common to all unwrap operations.
|
| + scoped_ptr<base::ListValue> tests;
|
| + ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
|
| + base::DictionaryValue* test;
|
| + ASSERT_TRUE(tests->GetDictionary(0, &test));
|
| + const std::vector<uint8> test_kek = GetBytesFromHexString(test, "kek");
|
| + const std::vector<uint8> test_ciphertext =
|
| + GetBytesFromHexString(test, "ciphertext");
|
| +
|
| + // Using a key that does not have unwrapKey usage should fail.
|
| + blink::WebCryptoKey bad_wrapping_key = ImportSecretKeyFromRaw(
|
| + test_kek,
|
| + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
|
| + blink::WebCryptoKeyUsageDecrypt); // <-- should be UnwrapKey
|
| + blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
|
| + EXPECT_STATUS(
|
| + Status::ErrorUnexpected(),
|
| + UnwrapKey(blink::WebCryptoKeyFormatRaw,
|
| + CryptoData(test_ciphertext),
|
| + bad_wrapping_key,
|
| + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
|
| + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
|
| + true,
|
| + blink::WebCryptoKeyUsageEncrypt,
|
| + &unwrapped_key));
|
| +
|
| + // Using a wrapping algorithm that does not match the wrapping key algorithm
|
| + // should fail.
|
| + blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
|
| + test_kek,
|
| + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw),
|
| + blink::WebCryptoKeyUsageUnwrapKey);
|
| + EXPECT_STATUS(
|
| + Status::ErrorUnexpected(),
|
| + UnwrapKey(blink::WebCryptoKeyFormatRaw,
|
| + CryptoData(test_ciphertext),
|
| + wrapping_key,
|
| + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
|
| + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc),
|
| + true,
|
| + blink::WebCryptoKeyUsageEncrypt,
|
| + &unwrapped_key));
|
| +}
|
| +
|
| TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyWrapUnwrapKnownAnswer)) {
|
| scoped_ptr<base::ListValue> tests;
|
| ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests));
|
| @@ -2542,6 +2587,114 @@ TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyUnwrapCorruptData)) {
|
| &unwrapped_key));
|
| }
|
|
|
| +TEST_F(SharedCryptoTest, MAYBE(AesKwJwkSymkeyUnwrapKnownData)) {
|
| + // The following data lists a known HMAC SHA-256 key, then a JWK
|
| + // representation of this key which was encrypted ("wrapped") using AES-KW and
|
| + // the following wrapping key.
|
| + // For reference, the intermediate clear JWK is
|
| + // {"alg":"HS256","ext":true,"k":<b64urlKey>,"key_ops":["verify"],"kty":"oct"}
|
| + // (Not shown is space padding to ensure the cleartext meets the size
|
| + // requirements of the AES-KW algorithm.)
|
| + const std::vector<uint8> key_data = HexStringToBytes(
|
| + "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F");
|
| + const std::vector<uint8> wrapped_key_data = HexStringToBytes(
|
| + "14E6380B35FDC5B72E1994764B6CB7BFDD64E7832894356AAEE6C3768FC3D0F115E6B0"
|
| + "6729756225F999AA99FDF81FD6A359F1576D3D23DE6CB69C3937054EB497AC1E8C38D5"
|
| + "5E01B9783A20C8D930020932CF25926103002213D0FC37279888154FEBCEDF31832158"
|
| + "97938C5CFE5B10B4254D0C399F39D0");
|
| + const std::vector<uint8> wrapping_key_data =
|
| + HexStringToBytes("000102030405060708090A0B0C0D0E0F");
|
| + const blink::WebCryptoAlgorithm wrapping_algorithm =
|
| + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
|
| +
|
| + // Import the wrapping key.
|
| + blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
|
| + wrapping_key_data, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey);
|
| +
|
| + // Unwrap the known wrapped key data to produce a new key
|
| + blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
|
| + ASSERT_STATUS_SUCCESS(UnwrapKey(blink::WebCryptoKeyFormatJwk,
|
| + CryptoData(wrapped_key_data),
|
| + wrapping_key,
|
| + wrapping_algorithm,
|
| + blink::WebCryptoAlgorithm::createNull(),
|
| + true,
|
| + blink::WebCryptoKeyUsageVerify,
|
| + &unwrapped_key));
|
| +
|
| + // Validate the new key's attributes.
|
| + EXPECT_FALSE(unwrapped_key.isNull());
|
| + EXPECT_TRUE(unwrapped_key.handle());
|
| + EXPECT_EQ(blink::WebCryptoKeyTypeSecret, unwrapped_key.type());
|
| + EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, unwrapped_key.algorithm().id());
|
| + EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256,
|
| + unwrapped_key.algorithm().hmacParams()->hash().id());
|
| + EXPECT_EQ(true, unwrapped_key.extractable());
|
| + EXPECT_EQ(blink::WebCryptoKeyUsageVerify, unwrapped_key.usages());
|
| +
|
| + // Export the new key's raw data and compare to the known original.
|
| + blink::WebArrayBuffer raw_key;
|
| + EXPECT_STATUS_SUCCESS(
|
| + ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key));
|
| + EXPECT_TRUE(ArrayBufferMatches(key_data, raw_key));
|
| +}
|
| +
|
| +TEST_F(SharedCryptoTest, MAYBE(AesKwJwkSymkeyUnwrapErrors)) {
|
| + // Unwrap data that can be successfully decrypted, but contains an error in
|
| + // the plaintext JWK, and ensure that a generic error is returned instead of
|
| + // some other more specific error, to show that information about the
|
| + // plaintext JWK inside the encrypted data is not leaked.
|
| + // Specifically, wrapped_key_data below is an AES-KW encrypted version of the
|
| + // plaintext JWK
|
| + // {
|
| + // "alg":"HS256",
|
| + // "ext":true,
|
| + // "k":"AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8",
|
| + // "key_ops":["verify"],
|
| + // "kty":"foo" <-- Invalid kty value
|
| + // }
|
| + // Recall that unwrapKey = decrypt followed by import. The wrapped_key_data
|
| + // will decrypt successfully, but the import step will fail because of the bad
|
| + // kty value. But unlike the standalone ImportKey() method which returns
|
| + // ErrorJwkUnrecognizedKty in this case, the error returned must be just
|
| + // Error::Status().
|
| + // Note that it is sufficient to consider just one JWK import failure mode
|
| + // here; others are validated in the ImportJwkFailures Test.
|
| + const std::vector<uint8> wrapped_key_data = HexStringToBytes(
|
| + "8d5ad45f5be6195a7a5944f0cf521bbae255daea140d4712985bb63ca1de1a318fbc49ff"
|
| + "307bd91bfafd7e9ea2057a2ddabb42ba94e319465972d165e5cc42785ad5cfa36159d5cc"
|
| + "50084133eae85a22bf8f7cb35f3c07b7c06480dec745d9ce4d4bfce45a6cbc2d39263ab7"
|
| + "073fc346724841f872f7148d");
|
| + const std::vector<uint8> wrapping_key_data =
|
| + HexStringToBytes("000102030405060708090A0B0C0D0E0F");
|
| + const blink::WebCryptoAlgorithm wrapping_algorithm =
|
| + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw);
|
| +
|
| + // Import the wrapping key.
|
| + blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw(
|
| + wrapping_key_data, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey);
|
| +
|
| + // Unwrap and ensure a generic error is received.
|
| + blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull();
|
| + EXPECT_STATUS(Status::Error(),
|
| + UnwrapKey(blink::WebCryptoKeyFormatJwk,
|
| + CryptoData(wrapped_key_data),
|
| + wrapping_key,
|
| + wrapping_algorithm,
|
| + blink::WebCryptoAlgorithm::createNull(),
|
| + true,
|
| + blink::WebCryptoKeyUsageVerify,
|
| + &unwrapped_key));
|
| +
|
| + // FIXME(padolph): The check above can fail if the AES-KW decryption step
|
| + // failed, which masks the test result desired here. For now we have to just
|
| + // trust the result because I say so.
|
| + // Once RSA-ES unwrapping is implemented, port this test to use that wrapping
|
| + // algorithm instead of AES-KW. Unlike AES-KW, RSA-ES supports both the
|
| + // decrypt and unwrapKey usages, so we can validate successful decryption of
|
| + // wrapped_key_data prior to seeing the unwrapKey (import) failure.
|
| +}
|
| +
|
| // TODO(eroman):
|
| // * Test decryption when the tag length exceeds input size
|
| // * Test decryption with empty input
|
| @@ -2824,7 +2977,7 @@ TEST_F(SharedCryptoTest, MAYBE(RsaEsRawSymkeyWrapUnwrapErrors)) {
|
| blink::WebCryptoKeyUsageSign,
|
| &unwrapped_key));
|
|
|
| - // Unwapping data too large for the wrapping key should fail.
|
| + // Unwrapping data too large for the wrapping key should fail.
|
| EXPECT_STATUS(Status::ErrorDataTooLarge(),
|
| UnwrapKey(blink::WebCryptoKeyFormatRaw,
|
| CryptoData(big_data),
|
|
|