| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/stl_util.h" |
| #include "content/child/webcrypto/algorithm_dispatch.h" |
| #include "content/child/webcrypto/crypto_data.h" |
| #include "content/child/webcrypto/status.h" |
| #include "content/child/webcrypto/test/test_helpers.h" |
| #include "content/child/webcrypto/webcrypto_util.h" |
| #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
| #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" |
| |
| namespace content { |
| |
| namespace webcrypto { |
| |
| namespace { |
| |
| blink::WebCryptoAlgorithm CreateAesKwKeyGenAlgorithm( |
| unsigned short key_length_bits) { |
| return CreateAesKeyGenAlgorithm(blink::WebCryptoAlgorithmIdAesKw, |
| key_length_bits); |
| } |
| |
| TEST(WebCryptoAesKwTest, GenerateKeyBadLength) { |
| const unsigned short kKeyLen[] = {0, 127, 257}; |
| blink::WebCryptoKey key; |
| for (size_t i = 0; i < arraysize(kKeyLen); ++i) { |
| SCOPED_TRACE(i); |
| EXPECT_EQ(Status::ErrorGenerateKeyLength(), |
| GenerateSecretKey( |
| CreateAesKwKeyGenAlgorithm(kKeyLen[i]), true, 0, &key)); |
| } |
| } |
| |
| TEST(WebCryptoAesKwTest, ImportKeyJwkKeyOpsWrapUnwrap) { |
| blink::WebCryptoKey key; |
| base::DictionaryValue dict; |
| dict.SetString("kty", "oct"); |
| dict.SetString("k", "GADWrMRHwQfoNaXU5fZvTg=="); |
| base::ListValue* key_ops = new base::ListValue; |
| dict.Set("key_ops", key_ops); // Takes ownership. |
| |
| key_ops->AppendString("wrapKey"); |
| |
| EXPECT_EQ( |
| Status::Success(), |
| ImportKeyJwkFromDict(dict, |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw), |
| false, |
| blink::WebCryptoKeyUsageWrapKey, |
| &key)); |
| |
| EXPECT_EQ(blink::WebCryptoKeyUsageWrapKey, key.usages()); |
| |
| key_ops->AppendString("unwrapKey"); |
| |
| EXPECT_EQ( |
| Status::Success(), |
| ImportKeyJwkFromDict(dict, |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw), |
| false, |
| blink::WebCryptoKeyUsageUnwrapKey, |
| &key)); |
| |
| EXPECT_EQ(blink::WebCryptoKeyUsageUnwrapKey, key.usages()); |
| } |
| |
| TEST(WebCryptoAesKwTest, ImportExportJwk) { |
| const blink::WebCryptoAlgorithm algorithm = |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); |
| |
| // AES-KW 128 |
| ImportExportJwkSymmetricKey( |
| 128, |
| algorithm, |
| blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey, |
| "A128KW"); |
| |
| // AES-KW 256 |
| ImportExportJwkSymmetricKey( |
| 256, |
| algorithm, |
| blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey, |
| "A256KW"); |
| } |
| |
| TEST(WebCryptoAesKwTest, AesKwKeyImport) { |
| blink::WebCryptoKey key; |
| blink::WebCryptoAlgorithm algorithm = |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); |
| |
| // Import a 128-bit Key Encryption Key (KEK) |
| std::string key_raw_hex_in = "025a8cf3f08b4f6c5f33bbc76a471939"; |
| ASSERT_EQ(Status::Success(), |
| ImportKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(HexStringToBytes(key_raw_hex_in)), |
| algorithm, |
| true, |
| blink::WebCryptoKeyUsageWrapKey, |
| &key)); |
| std::vector<uint8_t> key_raw_out; |
| EXPECT_EQ(Status::Success(), |
| ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out)); |
| EXPECT_BYTES_EQ_HEX(key_raw_hex_in, key_raw_out); |
| |
| // Import a 192-bit KEK |
| key_raw_hex_in = "c0192c6466b2370decbb62b2cfef4384544ffeb4d2fbc103"; |
| ASSERT_EQ(Status::ErrorAes192BitUnsupported(), |
| ImportKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(HexStringToBytes(key_raw_hex_in)), |
| algorithm, |
| true, |
| blink::WebCryptoKeyUsageWrapKey, |
| &key)); |
| |
| // Import a 256-bit Key Encryption Key (KEK) |
| key_raw_hex_in = |
| "e11fe66380d90fa9ebefb74e0478e78f95664d0c67ca20ce4a0b5842863ac46f"; |
| ASSERT_EQ(Status::Success(), |
| ImportKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(HexStringToBytes(key_raw_hex_in)), |
| algorithm, |
| true, |
| blink::WebCryptoKeyUsageWrapKey, |
| &key)); |
| EXPECT_EQ(Status::Success(), |
| ExportKey(blink::WebCryptoKeyFormatRaw, key, &key_raw_out)); |
| EXPECT_BYTES_EQ_HEX(key_raw_hex_in, key_raw_out); |
| |
| // Fail import of 0 length key |
| EXPECT_EQ(Status::ErrorImportAesKeyLength(), |
| ImportKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(HexStringToBytes("")), |
| algorithm, |
| true, |
| blink::WebCryptoKeyUsageWrapKey, |
| &key)); |
| |
| // Fail import of 124-bit KEK |
| key_raw_hex_in = "3e4566a2bdaa10cb68134fa66c15ddb"; |
| EXPECT_EQ(Status::ErrorImportAesKeyLength(), |
| ImportKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(HexStringToBytes(key_raw_hex_in)), |
| algorithm, |
| true, |
| blink::WebCryptoKeyUsageWrapKey, |
| &key)); |
| |
| // Fail import of 200-bit KEK |
| key_raw_hex_in = "0a1d88608a5ad9fec64f1ada269ebab4baa2feeb8d95638c0e"; |
| EXPECT_EQ(Status::ErrorImportAesKeyLength(), |
| ImportKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(HexStringToBytes(key_raw_hex_in)), |
| algorithm, |
| true, |
| blink::WebCryptoKeyUsageWrapKey, |
| &key)); |
| |
| // Fail import of 260-bit KEK |
| key_raw_hex_in = |
| "72d4e475ff34215416c9ad9c8281247a4d730c5f275ac23f376e73e3bce8d7d5a"; |
| EXPECT_EQ(Status::ErrorImportAesKeyLength(), |
| ImportKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(HexStringToBytes(key_raw_hex_in)), |
| algorithm, |
| true, |
| blink::WebCryptoKeyUsageWrapKey, |
| &key)); |
| } |
| |
| TEST(WebCryptoAesKwTest, 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_t> test_kek = GetBytesFromHexString(test, "kek"); |
| const std::vector<uint8_t> test_ciphertext = |
| GetBytesFromHexString(test, "ciphertext"); |
| |
| blink::WebCryptoKey unwrapped_key; |
| |
| // Using a wrapping algorithm that does not match the wrapping key algorithm |
| // should fail. |
| blink::WebCryptoKey wrapping_key = |
| ImportSecretKeyFromRaw(test_kek, |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw), |
| blink::WebCryptoKeyUsageUnwrapKey); |
| EXPECT_EQ(Status::ErrorUnexpected(), |
| UnwrapKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(test_ciphertext), |
| wrapping_key, |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), |
| true, |
| blink::WebCryptoKeyUsageEncrypt, |
| &unwrapped_key)); |
| } |
| |
| TEST(WebCryptoAesKwTest, AesKwRawSymkeyWrapUnwrapKnownAnswer) { |
| scoped_ptr<base::ListValue> tests; |
| ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests)); |
| |
| for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) { |
| SCOPED_TRACE(test_index); |
| base::DictionaryValue* test; |
| ASSERT_TRUE(tests->GetDictionary(test_index, &test)); |
| const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek"); |
| const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key"); |
| const std::vector<uint8_t> test_ciphertext = |
| GetBytesFromHexString(test, "ciphertext"); |
| const blink::WebCryptoAlgorithm wrapping_algorithm = |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); |
| |
| // Import the wrapping key. |
| blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw( |
| test_kek, |
| wrapping_algorithm, |
| blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey); |
| |
| // Import the key to be wrapped. |
| blink::WebCryptoKey key = ImportSecretKeyFromRaw( |
| test_key, |
| CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1), |
| blink::WebCryptoKeyUsageSign); |
| |
| // Wrap the key and verify the ciphertext result against the known answer. |
| std::vector<uint8_t> wrapped_key; |
| ASSERT_EQ(Status::Success(), |
| WrapKey(blink::WebCryptoKeyFormatRaw, |
| key, |
| wrapping_key, |
| wrapping_algorithm, |
| &wrapped_key)); |
| EXPECT_BYTES_EQ(test_ciphertext, wrapped_key); |
| |
| // Unwrap the known ciphertext to get a new test_key. |
| blink::WebCryptoKey unwrapped_key; |
| ASSERT_EQ( |
| Status::Success(), |
| UnwrapKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(test_ciphertext), |
| wrapping_key, |
| wrapping_algorithm, |
| CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1), |
| true, |
| blink::WebCryptoKeyUsageSign, |
| &unwrapped_key)); |
| EXPECT_FALSE(key.isNull()); |
| EXPECT_TRUE(key.handle()); |
| EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); |
| EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id()); |
| EXPECT_EQ(true, key.extractable()); |
| EXPECT_EQ(blink::WebCryptoKeyUsageSign, key.usages()); |
| |
| // Export the new key and compare its raw bytes with the original known key. |
| std::vector<uint8_t> raw_key; |
| EXPECT_EQ(Status::Success(), |
| ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key)); |
| EXPECT_BYTES_EQ(test_key, raw_key); |
| } |
| } |
| |
| // Unwrap a HMAC key using AES-KW, and then try doing a sign/verify with the |
| // unwrapped key |
| TEST(WebCryptoAesKwTest, AesKwRawSymkeyUnwrapSignVerifyHmac) { |
| 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_t> test_kek = GetBytesFromHexString(test, "kek"); |
| const std::vector<uint8_t> test_ciphertext = |
| GetBytesFromHexString(test, "ciphertext"); |
| const blink::WebCryptoAlgorithm wrapping_algorithm = |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); |
| |
| // Import the wrapping key. |
| blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw( |
| test_kek, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey); |
| |
| // Unwrap the known ciphertext. |
| blink::WebCryptoKey key; |
| ASSERT_EQ( |
| Status::Success(), |
| UnwrapKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(test_ciphertext), |
| wrapping_key, |
| wrapping_algorithm, |
| CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha1), |
| false, |
| blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify, |
| &key)); |
| |
| EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); |
| EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, key.algorithm().id()); |
| EXPECT_FALSE(key.extractable()); |
| EXPECT_EQ(blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify, |
| key.usages()); |
| |
| // Sign an empty message and ensure it is verified. |
| std::vector<uint8_t> test_message; |
| std::vector<uint8_t> signature; |
| |
| ASSERT_EQ(Status::Success(), |
| Sign(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac), |
| key, |
| CryptoData(test_message), |
| &signature)); |
| |
| EXPECT_GT(signature.size(), 0u); |
| |
| bool verify_result; |
| ASSERT_EQ(Status::Success(), |
| Verify(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac), |
| key, |
| CryptoData(signature), |
| CryptoData(test_message), |
| &verify_result)); |
| } |
| |
| TEST(WebCryptoAesKwTest, AesKwRawSymkeyWrapUnwrapErrors) { |
| scoped_ptr<base::ListValue> tests; |
| ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests)); |
| base::DictionaryValue* test; |
| // Use 256 bits of data with a 256-bit KEK |
| ASSERT_TRUE(tests->GetDictionary(3, &test)); |
| const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek"); |
| const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key"); |
| const std::vector<uint8_t> test_ciphertext = |
| GetBytesFromHexString(test, "ciphertext"); |
| const blink::WebCryptoAlgorithm wrapping_algorithm = |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); |
| const blink::WebCryptoAlgorithm key_algorithm = |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc); |
| // Import the wrapping key. |
| blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw( |
| test_kek, |
| wrapping_algorithm, |
| blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey); |
| // Import the key to be wrapped. |
| blink::WebCryptoKey key = |
| ImportSecretKeyFromRaw(test_key, |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), |
| blink::WebCryptoKeyUsageEncrypt); |
| |
| // Unwrap with wrapped data too small must fail. |
| const std::vector<uint8_t> small_data(test_ciphertext.begin(), |
| test_ciphertext.begin() + 23); |
| blink::WebCryptoKey unwrapped_key; |
| EXPECT_EQ(Status::ErrorDataTooSmall(), |
| UnwrapKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(small_data), |
| wrapping_key, |
| wrapping_algorithm, |
| key_algorithm, |
| true, |
| blink::WebCryptoKeyUsageEncrypt, |
| &unwrapped_key)); |
| |
| // Unwrap with wrapped data size not a multiple of 8 bytes must fail. |
| const std::vector<uint8_t> unaligned_data(test_ciphertext.begin(), |
| test_ciphertext.end() - 2); |
| EXPECT_EQ(Status::ErrorInvalidAesKwDataLength(), |
| UnwrapKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(unaligned_data), |
| wrapping_key, |
| wrapping_algorithm, |
| key_algorithm, |
| true, |
| blink::WebCryptoKeyUsageEncrypt, |
| &unwrapped_key)); |
| } |
| |
| TEST(WebCryptoAesKwTest, AesKwRawSymkeyUnwrapCorruptData) { |
| scoped_ptr<base::ListValue> tests; |
| ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests)); |
| base::DictionaryValue* test; |
| // Use 256 bits of data with a 256-bit KEK |
| ASSERT_TRUE(tests->GetDictionary(3, &test)); |
| const std::vector<uint8_t> test_kek = GetBytesFromHexString(test, "kek"); |
| const std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key"); |
| const std::vector<uint8_t> test_ciphertext = |
| GetBytesFromHexString(test, "ciphertext"); |
| const blink::WebCryptoAlgorithm wrapping_algorithm = |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); |
| |
| // Import the wrapping key. |
| blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw( |
| test_kek, |
| wrapping_algorithm, |
| blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey); |
| |
| // Unwrap of a corrupted version of the known ciphertext should fail, due to |
| // AES-KW's built-in integrity check. |
| blink::WebCryptoKey unwrapped_key; |
| EXPECT_EQ(Status::OperationError(), |
| UnwrapKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(Corrupted(test_ciphertext)), |
| wrapping_key, |
| wrapping_algorithm, |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), |
| true, |
| blink::WebCryptoKeyUsageEncrypt, |
| &unwrapped_key)); |
| } |
| |
| TEST(WebCryptoAesKwTest, 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_t> key_data = HexStringToBytes( |
| "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"); |
| const std::vector<uint8_t> wrapped_key_data = HexStringToBytes( |
| "14E6380B35FDC5B72E1994764B6CB7BFDD64E7832894356AAEE6C3768FC3D0F115E6B0" |
| "6729756225F999AA99FDF81FD6A359F1576D3D23DE6CB69C3937054EB497AC1E8C38D5" |
| "5E01B9783A20C8D930020932CF25926103002213D0FC37279888154FEBCEDF31832158" |
| "97938C5CFE5B10B4254D0C399F39D0"); |
| const std::vector<uint8_t> wrapping_key_data = |
| HexStringToBytes("000102030405060708090A0B0C0D0E0F"); |
| const blink::WebCryptoAlgorithm wrapping_algorithm = |
| 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; |
| ASSERT_EQ( |
| Status::Success(), |
| UnwrapKey(blink::WebCryptoKeyFormatJwk, |
| CryptoData(wrapped_key_data), |
| wrapping_key, |
| wrapping_algorithm, |
| CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256), |
| 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(256u, unwrapped_key.algorithm().hmacParams()->lengthBits()); |
| 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. |
| std::vector<uint8_t> raw_key; |
| EXPECT_EQ(Status::Success(), |
| ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key)); |
| EXPECT_BYTES_EQ(key_data, raw_key); |
| } |
| |
| // Try importing an AES-KW key with unsupported key usages using raw |
| // format. AES-KW keys support the following usages: |
| // 'wrapKey', 'unwrapKey' |
| TEST(WebCryptoAesKwTest, ImportKeyBadUsage_Raw) { |
| const blink::WebCryptoAlgorithm algorithm = |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); |
| |
| blink::WebCryptoKeyUsageMask bad_usages[] = { |
| blink::WebCryptoKeyUsageEncrypt, |
| blink::WebCryptoKeyUsageDecrypt, |
| blink::WebCryptoKeyUsageSign, |
| blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageUnwrapKey, |
| blink::WebCryptoKeyUsageDeriveBits, |
| blink::WebCryptoKeyUsageUnwrapKey | blink::WebCryptoKeyUsageVerify, |
| }; |
| |
| std::vector<uint8_t> key_bytes(16); |
| |
| for (size_t i = 0; i < arraysize(bad_usages); ++i) { |
| SCOPED_TRACE(i); |
| |
| blink::WebCryptoKey key; |
| ASSERT_EQ(Status::ErrorCreateKeyBadUsages(), |
| ImportKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(key_bytes), |
| algorithm, |
| true, |
| bad_usages[i], |
| &key)); |
| } |
| } |
| |
| // Try unwrapping an HMAC key with unsupported usages using JWK format and |
| // AES-KW. HMAC keys support the following usages: |
| // 'sign', 'verify' |
| TEST(WebCryptoAesKwTest, UnwrapHmacKeyBadUsage_JWK) { |
| const blink::WebCryptoAlgorithm unwrap_algorithm = |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); |
| |
| blink::WebCryptoKeyUsageMask bad_usages[] = { |
| blink::WebCryptoKeyUsageEncrypt, |
| blink::WebCryptoKeyUsageDecrypt, |
| blink::WebCryptoKeyUsageWrapKey, |
| blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageWrapKey, |
| blink::WebCryptoKeyUsageVerify | blink::WebCryptoKeyUsageDeriveKey, |
| }; |
| |
| // Import the wrapping key. |
| blink::WebCryptoKey wrapping_key; |
| ASSERT_EQ(Status::Success(), |
| ImportKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(std::vector<uint8_t>(16)), |
| unwrap_algorithm, |
| true, |
| blink::WebCryptoKeyUsageUnwrapKey, |
| &wrapping_key)); |
| |
| // The JWK plain text is: |
| // { "kty": "oct","alg": "HS256","k": "GADWrMRHwQfoNaXU5fZvTg=="} |
| const char* kWrappedJwk = |
| "0AA245F17064FFB2A7A094436A39BEBFC962C627303D1327EA750CE9F917688C2782A943" |
| "7AE7586547AC490E8AE7D5B02D63868D5C3BB57D36C4C8C5BF3962ACEC6F42E767E5706" |
| "4"; |
| |
| for (size_t i = 0; i < arraysize(bad_usages); ++i) { |
| SCOPED_TRACE(i); |
| |
| blink::WebCryptoKey key; |
| |
| ASSERT_EQ( |
| Status::ErrorCreateKeyBadUsages(), |
| UnwrapKey(blink::WebCryptoKeyFormatJwk, |
| CryptoData(HexStringToBytes(kWrappedJwk)), |
| wrapping_key, |
| unwrap_algorithm, |
| CreateHmacImportAlgorithm(blink::WebCryptoAlgorithmIdSha256), |
| true, |
| bad_usages[i], |
| &key)); |
| } |
| } |
| |
| // Try unwrapping an RSA-SSA public key with unsupported usages using JWK format |
| // and AES-KW. RSA-SSA public keys support the following usages: |
| // 'verify' |
| TEST(WebCryptoAesKwTest, UnwrapRsaSsaPublicKeyBadUsage_JWK) { |
| const blink::WebCryptoAlgorithm unwrap_algorithm = |
| CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); |
| |
| blink::WebCryptoKeyUsageMask bad_usages[] = { |
| blink::WebCryptoKeyUsageEncrypt, |
| blink::WebCryptoKeyUsageSign, |
| blink::WebCryptoKeyUsageDecrypt, |
| blink::WebCryptoKeyUsageWrapKey, |
| blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageWrapKey, |
| }; |
| |
| // Import the wrapping key. |
| blink::WebCryptoKey wrapping_key; |
| ASSERT_EQ(Status::Success(), |
| ImportKey(blink::WebCryptoKeyFormatRaw, |
| CryptoData(std::vector<uint8_t>(16)), |
| unwrap_algorithm, |
| true, |
| blink::WebCryptoKeyUsageUnwrapKey, |
| &wrapping_key)); |
| |
| // The JWK plaintext is: |
| // { "kty": "RSA","alg": "RS256","n": "...","e": "AQAB"} |
| |
| const char* kWrappedJwk = |
| "CE8DAEF99E977EE58958B8C4494755C846E883B2ECA575C5366622839AF71AB30875F152" |
| "E8E33E15A7817A3A2874EB53EFE05C774D98BC936BA9BA29BEB8BB3F3C3CE2323CB3359D" |
| "E3F426605CF95CCF0E01E870ABD7E35F62E030B5FB6E520A5885514D1D850FB64B57806D" |
| "1ADA57C6E27DF345D8292D80F6B074F1BE51C4CF3D76ECC8886218551308681B44FAC60B" |
| "8CF6EA439BC63239103D0AE81ADB96F908680586C6169284E32EB7DD09D31103EBDAC0C2" |
| "40C72DCF0AEA454113CC47457B13305B25507CBEAB9BDC8D8E0F867F9167F9DCEF0D9F9B" |
| "30F2EE83CEDFD51136852C8A5939B768"; |
| |
| for (size_t i = 0; i < arraysize(bad_usages); ++i) { |
| SCOPED_TRACE(i); |
| |
| blink::WebCryptoKey key; |
| |
| ASSERT_EQ(Status::ErrorCreateKeyBadUsages(), |
| UnwrapKey(blink::WebCryptoKeyFormatJwk, |
| CryptoData(HexStringToBytes(kWrappedJwk)), |
| wrapping_key, |
| unwrap_algorithm, |
| CreateRsaHashedImportAlgorithm( |
| blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, |
| blink::WebCryptoAlgorithmIdSha256), |
| true, |
| bad_usages[i], |
| &key)); |
| } |
| } |
| |
| } // namespace |
| |
| } // namespace webcrypto |
| |
| } // namespace content |