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

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

Issue 76363006: [webcrypto] Add JWK import of RSA public key for NSS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 1 month 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 7d580fb9bdc9c6cc46325b658fc25a12754881c2..d275fb214f67baec06e73beb3cdb81eec47fb454 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");
@@ -59,6 +60,21 @@ void RestoreDictionaryForImportBadJwkTest(base::DictionaryValue* dict) {
dict->SetString("k", "GADWrMRHwQfoNaXU5fZvTg==");
}
+// 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");
+}
+
#if !defined(USE_OPENSSL)
blink::WebCryptoAlgorithm CreateRsaAlgorithm(
blink::WebCryptoAlgorithmId algorithm_id,
@@ -691,7 +707,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 =
@@ -703,9 +719,9 @@ 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(
@@ -722,70 +738,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 =
+ 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 =
+ 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.
@@ -893,6 +982,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) {
@@ -935,8 +1029,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)

Powered by Google App Engine
This is Rietveld 408576698