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

Unified Diff: content/renderer/webcrypto/webcrypto_impl_unittest.cc

Issue 25906002: [webcrypto] Add JWK import for HMAC and AES-CBC key. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed some DCHECK's and TODO's. Created 7 years, 2 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/renderer/webcrypto/webcrypto_impl_unittest.cc
diff --git a/content/renderer/webcrypto/webcrypto_impl_unittest.cc b/content/renderer/webcrypto/webcrypto_impl_unittest.cc
index e448c5267d22b05aa2d99400c3fc8f6896a25139..4a67356b440090e1bb890456f1c64bedb81f5711 100644
--- a/content/renderer/webcrypto/webcrypto_impl_unittest.cc
+++ b/content/renderer/webcrypto/webcrypto_impl_unittest.cc
@@ -5,6 +5,7 @@
#include "webcrypto_impl.h"
#include "base/basictypes.h"
+#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_number_conversions.h"
@@ -59,6 +60,16 @@ WebKit::WebCryptoAlgorithm CreateAesCbcAlgorithm(
new WebKit::WebCryptoAesCbcParams(Start(iv), iv.size()));
}
+std::vector<unsigned char> MakeJsonVector(const std::string& json_string) {
+ return std::vector<unsigned char>(json_string.begin(), json_string.end());
+}
+
+std::vector<unsigned char> MakeJsonVector(const base::DictionaryValue& dict) {
+ std::string json;
+ base::JSONWriter::Write(&dict, &json);
+ return MakeJsonVector(json);
+}
+
} // namespace
namespace content {
@@ -176,6 +187,23 @@ class WebCryptoImplTest : public testing::Test {
algorithm, key, Start(data), data.size(), buffer);
}
+ bool ImportKeyJwk(
+ const unsigned char* key_data,
+ unsigned key_data_size,
+ scoped_ptr<WebKit::WebCryptoKeyHandle>* handle,
+ WebKit::WebCryptoKeyType* type,
+ bool* extractable,
+ WebKit::WebCryptoAlgorithm* algorithm,
+ WebKit::WebCryptoKeyUsageMask* usage_mask) {
+ return crypto_.ImportKeyJwk(key_data,
+ key_data_size,
+ handle,
+ type,
+ extractable,
+ algorithm,
+ usage_mask);
+ }
+
private:
WebCryptoImpl crypto_;
};
@@ -264,7 +292,7 @@ TEST_F(WebCryptoImplTest, DigestSampleSets) {
}
}
-#endif // #if !defined(USE_OPENSSL)
+#endif // #if !defined(USE_OPENSSL)
TEST_F(WebCryptoImplTest, HMACSampleSets) {
struct TestCase {
@@ -601,6 +629,243 @@ TEST_F(WebCryptoImplTest, AesCbcSampleSets) {
}
}
-#endif // !defined(USE_OPENSSL)
+#endif // !defined(USE_OPENSSL)
+
+TEST_F(WebCryptoImplTest, ImportJwkBadJwk) {
+
+ WebKit::WebCryptoKeyType type;
+ scoped_ptr<WebKit::WebCryptoKeyHandle> handle;
+ std::vector<uint8> iv(16);
+ WebKit::WebCryptoAlgorithm algorithm = CreateAesCbcAlgorithm(iv);
+ bool extractable = false;
+ WebKit::WebCryptoKeyUsageMask usage_mask = WebKit::WebCryptoKeyUsageSign;
+
+ // Empty JSON
+ std::vector<unsigned char> json_vec = MakeJsonVector("");
+ EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
+ json_vec.size(),
+ &handle,
+ &type,
+ &extractable,
+ &algorithm,
+ &usage_mask));
+
+ // Bad JSON
+ json_vec = MakeJsonVector(
+ "{"
+ "\"kty\" : \"oct\","
+ "\"alg\" : \"HS256\","
+ "\"use\" : "
+ );
+ EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
+ json_vec.size(),
+ &handle,
+ &type,
+ &extractable,
+ &algorithm,
+ &usage_mask));
+
+ // Note, each subtest below resets the dictionary so there is less chance of
+ // failure if they happen to be reordered.
+
+ // Invalid kty
+ base::DictionaryValue dict;
+ dict.SetString("kty", "foo");
+ dict.SetString("alg", "HS256");
+ dict.SetString("use", "sig");
+ dict.SetBoolean("extractable", true);
+ dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
+ json_vec = MakeJsonVector(dict);
+ EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
+ json_vec.size(),
+ &handle,
+ &type,
+ &extractable,
+ &algorithm,
+ &usage_mask));
+ dict.SetString("kty", "oct");
+
+ // Missing kty
+ dict.Remove("kty", NULL);
+ json_vec = MakeJsonVector(dict);
+ EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
+ json_vec.size(),
+ &handle,
+ &type,
+ &extractable,
+ &algorithm,
+ &usage_mask));
+ dict.SetString("kty", "oct");
+
+ // Invalid alg
+ dict.SetString("alg", "foo");
+ json_vec = MakeJsonVector(dict);
+ EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
+ json_vec.size(),
+ &handle,
+ &type,
+ &extractable,
+ &algorithm,
+ &usage_mask));
+ dict.SetString("alg", "HS256");
+
+ // Invalid use
+ dict.SetString("use", "foo");
+ json_vec = MakeJsonVector(dict);
+ EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
+ json_vec.size(),
+ &handle,
+ &type,
+ &extractable,
+ &algorithm,
+ &usage_mask));
+ dict.SetString("use", "sig");
+
+ // Missing k when kty = "oct"
+ dict.Remove("k", NULL);
+ json_vec = MakeJsonVector(dict);
+ EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
+ json_vec.size(),
+ &handle,
+ &type,
+ &extractable,
+ &algorithm,
+ &usage_mask));
+ dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
+
+ // Bad encoding for k
+ dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3r #$% jhdY8vOkbIvh4lxTuMao9Y_--hdg");
+ json_vec = MakeJsonVector(dict);
+ EXPECT_FALSE(ImportKeyJwk(Start(json_vec),
+ json_vec.size(),
+ &handle,
+ &type,
+ &extractable,
+ &algorithm,
+ &usage_mask));
+ dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
+
+ // TODO(padolph) RSA public key bad data:
+ // Missing n or e when kty = "RSA"
+ // Bad encoding for n or e
+ // Size check on n??
+ // Value check on e??
+}
+
+TEST_F(WebCryptoImplTest, ImportJwkCollision) {
+
+ WebKit::WebCryptoKeyType type;
+ scoped_ptr<WebKit::WebCryptoKeyHandle> handle;
+ std::vector<uint8> iv(16);
+ WebKit::WebCryptoAlgorithm algorithm = CreateAesCbcAlgorithm(iv);
+ bool extractable = false;
+ WebKit::WebCryptoKeyUsageMask usage_mask = WebKit::WebCryptoKeyUsageSign;
+
+ // Collision rules when JWK value exists:
+ // Input _type_ should be ignored.
+ // Input _algorithm_ should be overridden by the JWK value.
+ // Output _extractable_ should be AND of input and JWK value.
+ // Input _usage_mask_ should be overridden by the JWK value.
+ type = WebKit::WebCryptoKeyTypePublic;
+ algorithm = CreateAesCbcAlgorithm(iv);
+ extractable = true;
+ usage_mask = WebKit::WebCryptoKeyUsageWrapKey;
+
+ base::DictionaryValue dict;
+ dict.SetString("kty", "oct");
+ dict.SetString("alg", "HS256");
+ dict.SetString("use", "sig");
+ dict.SetBoolean("extractable", false);
+ dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
+ std::vector<unsigned char> json_vec = MakeJsonVector(dict);
+
+ EXPECT_TRUE(ImportKeyJwk(Start(json_vec),
+ json_vec.size(),
+ &handle,
+ &type,
+ &extractable,
+ &algorithm,
+ &usage_mask));
+ EXPECT_EQ(WebKit::WebCryptoKeyTypeSecret, type);
+ EXPECT_EQ(WebKit::WebCryptoAlgorithmIdHmac, algorithm.id());
+ const WebKit::WebCryptoHmacParams* const hmac_params = algorithm.hmacParams();
+ ASSERT_TRUE(hmac_params != NULL);
+ EXPECT_EQ(hmac_params->hash().id(), WebKit::WebCryptoAlgorithmIdSha256);
+ EXPECT_FALSE(extractable);
+ EXPECT_EQ(WebKit::WebCryptoKeyUsageSign | WebKit::WebCryptoKeyUsageVerify,
+ usage_mask);
+
+ // Collision rules when JWK value is not present:
+ // Inputs should be unmodified.
+ algorithm = CreateHmacAlgorithm(WebKit::WebCryptoAlgorithmIdSha256);
+ extractable = true;
+ usage_mask = WebKit::WebCryptoKeyUsageSign;
+
+ dict.Clear();
+ dict.SetString("kty", "oct");
+ dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
+ json_vec = MakeJsonVector(dict);
+
+ EXPECT_TRUE(ImportKeyJwk(Start(json_vec),
+ json_vec.size(),
+ &handle,
+ &type,
+ &extractable,
+ &algorithm,
+ &usage_mask));
+ EXPECT_EQ(WebKit::WebCryptoAlgorithmIdHmac, algorithm.id());
+ EXPECT_TRUE(extractable);
+ EXPECT_EQ(WebKit::WebCryptoKeyUsageSign, usage_mask);
+}
+
+TEST_F(WebCryptoImplTest, ImportJwkHappy) {
+
+ WebKit::WebCryptoKeyType type;
+ scoped_ptr<WebKit::WebCryptoKeyHandle> handle;
+ std::vector<uint8> iv(16);
+ WebKit::WebCryptoAlgorithm algorithm = CreateAesCbcAlgorithm(iv);
+ bool extractable = false;
+ WebKit::WebCryptoKeyUsageMask usage_mask = WebKit::WebCryptoKeyUsageSign;
+
+ // Import a symmetric key JWK and HMAC-SHA256 sign()
+ // Uses the first SHA256 test vector from the HMAC sample set above.
+
+ base::DictionaryValue dict;
+ dict.SetString("kty", "oct");
+ dict.SetString("alg", "HS256");
+ dict.SetString("use", "sig");
+ dict.SetBoolean("extractable", true);
+ dict.SetString("k", "l3nZEgZCeX8XRwJdWyK3rGB8qwjhdY8vOkbIvh4lxTuMao9Y_--hdg");
+ std::vector<unsigned char> json_vec = MakeJsonVector(dict);
+
+ EXPECT_TRUE(ImportKeyJwk(Start(json_vec),
+ json_vec.size(),
+ &handle,
+ &type,
+ &extractable,
+ &algorithm,
+ &usage_mask));
+
+ WebKit::WebCryptoKey key = WebKit::WebCryptoKey::create(handle.release(),
+ type, extractable, algorithm, usage_mask);
+
+ const std::vector<uint8> message_raw = HexStringToBytes(
+ "b1689c2591eaf3c9e66070f8a77954ffb81749f1b00346f9dfe0b2ee905dcc288baf4a"
+ "92de3f4001dd9f44c468c3d07d6c6ee82faceafc97c2fc0fc0601719d2dcd0aa2aec92"
+ "d1b0ae933c65eb06a03c9c935c2bad0459810241347ab87e9f11adb30415424c6c7f5f"
+ "22a003b8ab8de54f6ded0e3ab9245fa79568451dfa258e");
+
+ WebKit::WebArrayBuffer output;
+
+ ASSERT_TRUE(SignInternal(algorithm, key, message_raw, &output));
+
+ const std::string mac_raw =
+ "769f00d3e6a6cc1fb426a14a4f76c6462e6149726e0dee0ec0cf97a16605ac8b";
+
+ ExpectArrayBufferMatchesHex(mac_raw, output);
+
+ // TODO(padolph)
+ // Import an RSA public key JWK and use it
+}
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698