| 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 c59de0e3d856f5c1fe171d3a73e775dad341134f..48552b76e62bb32a1fe5d0f2b6609a5f9fc13d5f 100644
|
| --- a/content/renderer/webcrypto/webcrypto_impl_unittest.cc
|
| +++ b/content/renderer/webcrypto/webcrypto_impl_unittest.cc
|
| @@ -49,8 +49,9 @@ std::vector<uint8> MakeJsonVector(const base::DictionaryValue& dict) {
|
| return MakeJsonVector(json);
|
| }
|
|
|
| -// Helper for ImportJwkBadJwk; restores JWK JSON dictionary to a good state
|
| -void RestoreDictionaryForImportBadJwkTest(base::DictionaryValue* dict) {
|
| +// Helper for ImportJwkFailures and ImportJwkOctFailures. Restores the JWK JSON
|
| +// dictionary to a good state
|
| +void RestoreJwkOctDictionary(base::DictionaryValue* dict) {
|
| dict->Clear();
|
| dict->SetString("kty", "oct");
|
| dict->SetString("alg", "A128CBC");
|
| @@ -58,8 +59,24 @@ void RestoreDictionaryForImportBadJwkTest(base::DictionaryValue* dict) {
|
| dict->SetBoolean("extractable", false);
|
| dict->SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
|
| }
|
| +
|
| #if !defined(USE_OPENSSL)
|
|
|
| +// Helper for ImportJwkRsaFailures. Restores the JWK JSON
|
| +// dictionary to a good state
|
| +void RestoreJwkRsaDictionary(base::DictionaryValue* dict) {
|
| + dict->Clear();
|
| + dict->SetString("kty", "RSA");
|
| + dict->SetString("alg", "RSA1_5");
|
| + dict->SetString("use", "enc");
|
| + dict->SetBoolean("extractable", false);
|
| + dict->SetString("n",
|
| + "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
|
| + "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
|
| + "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
|
| + dict->SetString("e", "AQAB");
|
| +}
|
| +
|
| blink::WebCryptoAlgorithm CreateRsaKeyGenAlgorithm(
|
| blink::WebCryptoAlgorithmId algorithm_id,
|
| unsigned modulus_length,
|
| @@ -707,7 +724,7 @@ TEST_F(WebCryptoImplTest, ImportSecretKeyNoAlgorithm) {
|
|
|
| #endif //#if !defined(USE_OPENSSL)
|
|
|
| -TEST_F(WebCryptoImplTest, ImportJwkBadJwk) {
|
| +TEST_F(WebCryptoImplTest, ImportJwkFailures) {
|
|
|
| blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
|
| blink::WebCryptoAlgorithm algorithm =
|
| @@ -719,13 +736,13 @@ TEST_F(WebCryptoImplTest, ImportJwkBadJwk) {
|
| // Each breaking subtest below resets the dictionary to this passing case when
|
| // complete.
|
| base::DictionaryValue dict;
|
| - RestoreDictionaryForImportBadJwkTest(&dict);
|
| - std::vector<uint8> json_vec = MakeJsonVector(dict);
|
| - EXPECT_TRUE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key));
|
| + RestoreJwkOctDictionary(&dict);
|
| + EXPECT_TRUE(ImportKeyJwk(
|
| + MakeJsonVector(dict), algorithm, false, usage_mask, &key));
|
|
|
| // Fail on empty JSON.
|
| - EXPECT_FALSE(
|
| - ImportKeyJwk(MakeJsonVector(""), algorithm, false, usage_mask, &key));
|
| + EXPECT_FALSE(ImportKeyJwk(
|
| + MakeJsonVector(""), algorithm, false, usage_mask, &key));
|
|
|
| // Fail on invalid JSON.
|
| const std::vector<uint8> bad_json_vec = MakeJsonVector(
|
| @@ -738,70 +755,143 @@ TEST_F(WebCryptoImplTest, ImportJwkBadJwk) {
|
|
|
| // Fail on JWK alg present but unrecognized.
|
| dict.SetString("alg", "A127CBC");
|
| - json_vec = MakeJsonVector(dict);
|
| - EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key));
|
| - RestoreDictionaryForImportBadJwkTest(&dict);
|
| + EXPECT_FALSE(ImportKeyJwk(
|
| + MakeJsonVector(dict), algorithm, false, usage_mask, &key));
|
| + RestoreJwkOctDictionary(&dict);
|
|
|
| // Fail on both JWK and input algorithm missing.
|
| dict.Remove("alg", NULL);
|
| - json_vec = MakeJsonVector(dict);
|
| - EXPECT_FALSE(ImportKeyJwk(json_vec,
|
| + EXPECT_FALSE(ImportKeyJwk(MakeJsonVector(dict),
|
| blink::WebCryptoAlgorithm::createNull(),
|
| false,
|
| usage_mask,
|
| &key));
|
| - RestoreDictionaryForImportBadJwkTest(&dict);
|
| + RestoreJwkOctDictionary(&dict);
|
|
|
| // Fail on invalid kty.
|
| dict.SetString("kty", "foo");
|
| - json_vec = MakeJsonVector(dict);
|
| - EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key));
|
| - RestoreDictionaryForImportBadJwkTest(&dict);
|
| + EXPECT_FALSE(ImportKeyJwk(
|
| + MakeJsonVector(dict), algorithm, false, usage_mask, &key));
|
| + RestoreJwkOctDictionary(&dict);
|
|
|
| // Fail on missing kty.
|
| dict.Remove("kty", NULL);
|
| - json_vec = MakeJsonVector(dict);
|
| - EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key));
|
| - RestoreDictionaryForImportBadJwkTest(&dict);
|
| + EXPECT_FALSE(ImportKeyJwk(
|
| + MakeJsonVector(dict), algorithm, false, usage_mask, &key));
|
| + RestoreJwkOctDictionary(&dict);
|
|
|
| // Fail on invalid use.
|
| dict.SetString("use", "foo");
|
| - json_vec = MakeJsonVector(dict);
|
| - EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key));
|
| - RestoreDictionaryForImportBadJwkTest(&dict);
|
| + EXPECT_FALSE(ImportKeyJwk(
|
| + MakeJsonVector(dict), algorithm, false, usage_mask, &key));
|
| + RestoreJwkOctDictionary(&dict);
|
| +}
|
| +
|
| +TEST_F(WebCryptoImplTest, ImportJwkOctFailures) {
|
| +
|
| + base::DictionaryValue dict;
|
| + RestoreJwkOctDictionary(&dict);
|
| + blink::WebCryptoAlgorithm algorithm =
|
| + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc);
|
| + blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
|
| + blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
|
| +
|
| + // Baseline pass.
|
| + EXPECT_TRUE(ImportKeyJwk(
|
| + MakeJsonVector(dict), algorithm, false, usage_mask, &key));
|
| + EXPECT_EQ(algorithm.id(), key.algorithm().id());
|
| + EXPECT_FALSE(key.extractable());
|
| + EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
|
| + EXPECT_EQ(blink::WebCryptoKeyTypeSecret, key.type());
|
|
|
| - // Fail on missing k when kty = "oct".
|
| + // The following are specific failure cases for when kty = "oct".
|
| +
|
| + // Fail on missing k.
|
| dict.Remove("k", NULL);
|
| - json_vec = MakeJsonVector(dict);
|
| - EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key));
|
| - RestoreDictionaryForImportBadJwkTest(&dict);
|
| + EXPECT_FALSE(ImportKeyJwk(
|
| + MakeJsonVector(dict), algorithm, false, usage_mask, &key));
|
| + RestoreJwkOctDictionary(&dict);
|
|
|
| // Fail on bad b64 encoding for k.
|
| dict.SetString("k", "Qk3f0DsytU8lfza2au #$% Htaw2xpop9GYyTuH0p5GghxTI=");
|
| - json_vec = MakeJsonVector(dict);
|
| - EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key));
|
| - RestoreDictionaryForImportBadJwkTest(&dict);
|
| + EXPECT_FALSE(ImportKeyJwk(
|
| + MakeJsonVector(dict), algorithm, false, usage_mask, &key));
|
| + RestoreJwkOctDictionary(&dict);
|
|
|
| // Fail on empty k.
|
| dict.SetString("k", "");
|
| - json_vec = MakeJsonVector(dict);
|
| - EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key));
|
| - RestoreDictionaryForImportBadJwkTest(&dict);
|
| + EXPECT_FALSE(ImportKeyJwk(
|
| + MakeJsonVector(dict), algorithm, false, usage_mask, &key));
|
| + RestoreJwkOctDictionary(&dict);
|
|
|
| // Fail on k actual length (120 bits) inconsistent with the embedded JWK alg
|
| // value (128) for an AES key.
|
| dict.SetString("k", "AVj42h0Y5aqGtE3yluKL");
|
| - json_vec = MakeJsonVector(dict);
|
| - EXPECT_FALSE(ImportKeyJwk(json_vec, algorithm, false, usage_mask, &key));
|
| - RestoreDictionaryForImportBadJwkTest(&dict);
|
| -
|
| - // 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??
|
| + EXPECT_FALSE(ImportKeyJwk(
|
| + MakeJsonVector(dict), algorithm, false, usage_mask, &key));
|
| + RestoreJwkOctDictionary(&dict);
|
| +}
|
| +
|
| +#if !defined(USE_OPENSSL)
|
| +
|
| +TEST_F(WebCryptoImplTest, ImportJwkRsaFailures) {
|
| +
|
| + base::DictionaryValue dict;
|
| + RestoreJwkRsaDictionary(&dict);
|
| + blink::WebCryptoAlgorithm algorithm =
|
| + webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5);
|
| + blink::WebCryptoKeyUsageMask usage_mask = blink::WebCryptoKeyUsageEncrypt;
|
| + blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
|
| +
|
| + // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
|
| + // entry, while an RSA private key must have those plus at least a "d"
|
| + // (private exponent) entry.
|
| + // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
|
| + // section 6.3.
|
| +
|
| + // Baseline pass.
|
| + EXPECT_TRUE(ImportKeyJwk(
|
| + MakeJsonVector(dict), algorithm, false, usage_mask, &key));
|
| + EXPECT_EQ(algorithm.id(), key.algorithm().id());
|
| + EXPECT_FALSE(key.extractable());
|
| + EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, key.usages());
|
| + EXPECT_EQ(blink::WebCryptoKeyTypePublic, key.type());
|
| +
|
| + // The following are specific failure cases for when kty = "RSA".
|
| +
|
| + // Fail if either "n" or "e" is not present or malformed.
|
| + const std::string kKtyParmName[] = {"n", "e"};
|
| + for (size_t idx = 0; idx < ARRAYSIZE_UNSAFE(kKtyParmName); ++idx) {
|
| +
|
| + // Fail on missing parameter.
|
| + dict.Remove(kKtyParmName[idx], NULL);
|
| + EXPECT_FALSE(ImportKeyJwk(
|
| + MakeJsonVector(dict), algorithm, false, usage_mask, &key));
|
| + RestoreJwkRsaDictionary(&dict);
|
| +
|
| + // Fail on bad b64 parameter encoding.
|
| + dict.SetString(kKtyParmName[idx], "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
|
| + EXPECT_FALSE(ImportKeyJwk(
|
| + MakeJsonVector(dict), algorithm, false, usage_mask, &key));
|
| + RestoreJwkRsaDictionary(&dict);
|
| +
|
| + // Fail on empty parameter.
|
| + dict.SetString(kKtyParmName[idx], "");
|
| + EXPECT_FALSE(ImportKeyJwk(
|
| + MakeJsonVector(dict), algorithm, false, usage_mask, &key));
|
| + RestoreJwkRsaDictionary(&dict);
|
| + }
|
| +
|
| + // Fail if "d" parameter is present, implying the JWK is a private key, which
|
| + // is not supported.
|
| + dict.SetString("d", "Qk3f0Dsyt");
|
| + EXPECT_FALSE(ImportKeyJwk(
|
| + MakeJsonVector(dict), algorithm, false, usage_mask, &key));
|
| + RestoreJwkRsaDictionary(&dict);
|
| }
|
|
|
| +#endif // #if !defined(USE_OPENSSL)
|
| +
|
| TEST_F(WebCryptoImplTest, ImportJwkInputConsistency) {
|
| // The Web Crypto spec says that if a JWK value is present, but is
|
| // inconsistent with the input value, the operation must fail.
|
| @@ -904,6 +994,11 @@ TEST_F(WebCryptoImplTest, ImportJwkInputConsistency) {
|
| EXPECT_FALSE(
|
| ImportKeyJwk(json_vec, algorithm, extractable, usage_mask, &key));
|
| usage_mask = blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
|
| +
|
| + // TODO(padolph): kty vs alg consistency tests: Depending on the kty value,
|
| + // only certain alg values are permitted. For example, when kty = "RSA" alg
|
| + // must be of the RSA family, or when kty = "oct" alg must be symmetric
|
| + // algorithm.
|
| }
|
|
|
| TEST_F(WebCryptoImplTest, ImportJwkHappy) {
|
| @@ -945,8 +1040,7 @@ TEST_F(WebCryptoImplTest, ImportJwkHappy) {
|
|
|
| ExpectArrayBufferMatchesHex(mac_raw, output);
|
|
|
| - // TODO(padolph)
|
| - // Import an RSA public key JWK and use it
|
| + // TODO(padolph): Import an RSA public key JWK and use it
|
| }
|
|
|
| #if !defined(USE_OPENSSL)
|
|
|