From cd636729b2ffc613f90fa22c605d15d1fe2ba70e Mon Sep 17 00:00:00 2001 From: "eroman@chromium.org" Date: Fri, 9 May 2014 13:34:42 +0000 Subject: [webcrypto] Fix AES-KW unwrapping for symmetric keys (NSS). The unwrapped key did not have the proper flags so it could not be used in other operations (like signing). BUG=370712,245025 Review URL: https://codereview.chromium.org/269313004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269262 0039d316-1c4b-4281-b951-d872f2087c98 --- content/child/webcrypto/platform_crypto_nss.cc | 19 ++++--- content/child/webcrypto/shared_crypto_unittest.cc | 62 +++++++++++++++++++++-- 2 files changed, 70 insertions(+), 11 deletions(-) (limited to 'content') diff --git a/content/child/webcrypto/platform_crypto_nss.cc b/content/child/webcrypto/platform_crypto_nss.cc index ffa62a5..65dbb2f 100644 --- a/content/child/webcrypto/platform_crypto_nss.cc +++ b/content/child/webcrypto/platform_crypto_nss.cc @@ -560,13 +560,16 @@ Status DoUnwrapSymKeyAesKw(const CryptoData& wrapped_key_data, PORT_SetError(0); #endif - crypto::ScopedPK11SymKey new_key(PK11_UnwrapSymKey(wrapping_key->key(), - CKM_NSS_AES_KEY_WRAP, - param_item.get(), - &cipher_text, - mechanism, - flags, - plaintext_length)); + crypto::ScopedPK11SymKey new_key( + PK11_UnwrapSymKeyWithFlags(wrapping_key->key(), + CKM_NSS_AES_KEY_WRAP, + param_item.get(), + &cipher_text, + mechanism, + CKA_FLAGS_ONLY, + plaintext_length, + flags)); + // TODO(padolph): Use NSS PORT_GetError() and friends to report a more // accurate error, providing if doesn't leak any information to web pages // about other web crypto users, key details, etc. @@ -1575,7 +1578,7 @@ Status DecryptAesKw(SymKey* wrapping_key, // temporarily viewed as a symmetric key to be unwrapped (decrypted). crypto::ScopedPK11SymKey decrypted; Status status = DoUnwrapSymKeyAesKw( - data, wrapping_key, CKK_GENERIC_SECRET, CKA_ENCRYPT, &decrypted); + data, wrapping_key, CKK_GENERIC_SECRET, 0, &decrypted); if (status.IsError()) return status; diff --git a/content/child/webcrypto/shared_crypto_unittest.cc b/content/child/webcrypto/shared_crypto_unittest.cc index 3beadc4..20f1ad5 100644 --- a/content/child/webcrypto/shared_crypto_unittest.cc +++ b/content/child/webcrypto/shared_crypto_unittest.cc @@ -2785,9 +2785,7 @@ TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyWrapUnwrapKnownAnswer)) { EXPECT_FALSE(key.isNull()); EXPECT_TRUE(key.handle()); EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type()); - EXPECT_EQ( - webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc).id(), - key.algorithm().id()); + EXPECT_EQ(blink::WebCryptoAlgorithmIdAesCbc, key.algorithm().id()); EXPECT_EQ(true, key.extractable()); EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages()); @@ -2799,6 +2797,64 @@ TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyWrapUnwrapKnownAnswer)) { } } +// Unwrap a HMAC key using AES-KW, and then try doing a sign/verify with the +// unwrapped key +TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyUnwrapSignVerifyHmac)) { + scoped_ptr tests; + ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests)); + + base::DictionaryValue* test; + ASSERT_TRUE(tests->GetDictionary(0, &test)); + const std::vector test_kek = GetBytesFromHexString(test, "kek"); + const std::vector 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 = blink::WebCryptoKey::createNull(); + 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 test_message; + std::vector 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(), + VerifySignature(CreateAlgorithm(blink::WebCryptoAlgorithmIdHmac), + key, + CryptoData(signature), + CryptoData(test_message), + &verify_result)); +} + TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyWrapUnwrapErrors)) { scoped_ptr tests; ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests)); -- cgit v1.1