| 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
|
|
|