rsa_ssa_unittest.cc 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include <stddef.h>
  5. #include <stdint.h>
  6. #include "base/check_op.h"
  7. #include "base/containers/span.h"
  8. #include "base/values.h"
  9. #include "components/webcrypto/algorithm_dispatch.h"
  10. #include "components/webcrypto/algorithms/test_helpers.h"
  11. #include "components/webcrypto/status.h"
  12. #include "testing/gtest/include/gtest/gtest.h"
  13. #include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
  14. #include "third_party/blink/public/platform/web_crypto_key.h"
  15. #include "third_party/blink/public/platform/web_crypto_key_algorithm.h"
  16. namespace webcrypto {
  17. namespace {
  18. // Helper for ImportJwkRsaFailures. Restores the JWK JSON
  19. // dictionary to a good state
  20. void RestoreJwkRsaDictionary(base::DictionaryValue* dict) {
  21. dict->DictClear();
  22. dict->SetString("kty", "RSA");
  23. dict->SetString("alg", "RS256");
  24. dict->SetString("use", "sig");
  25. dict->SetBoolean("ext", false);
  26. dict->SetString(
  27. "n",
  28. "qLOyhK-OtQs4cDSoYPFGxJGfMYdjzWxVmMiuSBGh4KvEx-CwgtaTpef87Wdc9GaFEncsDLxk"
  29. "p0LGxjD1M8jMcvYq6DPEC_JYQumEu3i9v5fAEH1VvbZi9cTg-rmEXLUUjvc5LdOq_5OuHmtm"
  30. "e7PUJHYW1PW6ENTP0ibeiNOfFvs");
  31. dict->SetString("e", "AQAB");
  32. }
  33. class WebCryptoRsaSsaTest : public WebCryptoTestBase {};
  34. TEST_F(WebCryptoRsaSsaTest, ImportExportSpki) {
  35. // Passing case: Import a valid RSA key in SPKI format.
  36. blink::WebCryptoKey key;
  37. ASSERT_EQ(Status::Success(),
  38. ImportKey(blink::kWebCryptoKeyFormatSpki,
  39. HexStringToBytes(kPublicKeySpkiDerHex),
  40. CreateRsaHashedImportAlgorithm(
  41. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  42. blink::kWebCryptoAlgorithmIdSha256),
  43. true, blink::kWebCryptoKeyUsageVerify, &key));
  44. EXPECT_TRUE(key.Handle());
  45. EXPECT_EQ(blink::kWebCryptoKeyTypePublic, key.GetType());
  46. EXPECT_TRUE(key.Extractable());
  47. EXPECT_EQ(blink::kWebCryptoKeyUsageVerify, key.Usages());
  48. EXPECT_EQ(kModulusLengthBits,
  49. key.Algorithm().RsaHashedParams()->ModulusLengthBits());
  50. EXPECT_BYTES_EQ_HEX("010001",
  51. key.Algorithm().RsaHashedParams()->PublicExponent());
  52. // Failing case: Import RSA key but provide an inconsistent input algorithm.
  53. EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
  54. ImportKey(blink::kWebCryptoKeyFormatSpki,
  55. HexStringToBytes(kPublicKeySpkiDerHex),
  56. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesCbc), true,
  57. blink::kWebCryptoKeyUsageEncrypt, &key));
  58. // Passing case: Export a previously imported RSA public key in SPKI format
  59. // and compare to original data.
  60. std::vector<uint8_t> output;
  61. ASSERT_EQ(Status::Success(),
  62. ExportKey(blink::kWebCryptoKeyFormatSpki, key, &output));
  63. EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, output);
  64. // Failing case: Try to export a previously imported RSA public key in raw
  65. // format (not allowed for a public key).
  66. EXPECT_EQ(Status::ErrorUnsupportedExportKeyFormat(),
  67. ExportKey(blink::kWebCryptoKeyFormatRaw, key, &output));
  68. // Failing case: Try to export a non-extractable key
  69. ASSERT_EQ(Status::Success(),
  70. ImportKey(blink::kWebCryptoKeyFormatSpki,
  71. HexStringToBytes(kPublicKeySpkiDerHex),
  72. CreateRsaHashedImportAlgorithm(
  73. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  74. blink::kWebCryptoAlgorithmIdSha256),
  75. false, blink::kWebCryptoKeyUsageVerify, &key));
  76. EXPECT_TRUE(key.Handle());
  77. EXPECT_FALSE(key.Extractable());
  78. EXPECT_EQ(Status::ErrorKeyNotExtractable(),
  79. ExportKey(blink::kWebCryptoKeyFormatSpki, key, &output));
  80. // TODO(eroman): Failing test: Import a SPKI with an unrecognized hash OID
  81. // TODO(eroman): Failing test: Import a SPKI with invalid algorithm params
  82. // TODO(eroman): Failing test: Import a SPKI with inconsistent parameters
  83. // (e.g. SHA-1 in OID, SHA-256 in params)
  84. // TODO(eroman): Failing test: Import a SPKI for RSA-SSA, but with params
  85. // as OAEP/PSS
  86. }
  87. TEST_F(WebCryptoRsaSsaTest, ImportExportPkcs8) {
  88. // Passing case: Import a valid RSA key in PKCS#8 format.
  89. blink::WebCryptoKey key;
  90. ASSERT_EQ(Status::Success(),
  91. ImportKey(blink::kWebCryptoKeyFormatPkcs8,
  92. HexStringToBytes(kPrivateKeyPkcs8DerHex),
  93. CreateRsaHashedImportAlgorithm(
  94. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  95. blink::kWebCryptoAlgorithmIdSha1),
  96. true, blink::kWebCryptoKeyUsageSign, &key));
  97. EXPECT_TRUE(key.Handle());
  98. EXPECT_EQ(blink::kWebCryptoKeyTypePrivate, key.GetType());
  99. EXPECT_TRUE(key.Extractable());
  100. EXPECT_EQ(blink::kWebCryptoKeyUsageSign, key.Usages());
  101. EXPECT_EQ(blink::kWebCryptoAlgorithmIdSha1,
  102. key.Algorithm().RsaHashedParams()->GetHash().Id());
  103. EXPECT_EQ(kModulusLengthBits,
  104. key.Algorithm().RsaHashedParams()->ModulusLengthBits());
  105. EXPECT_BYTES_EQ_HEX("010001",
  106. key.Algorithm().RsaHashedParams()->PublicExponent());
  107. std::vector<uint8_t> exported_key;
  108. ASSERT_EQ(Status::Success(),
  109. ExportKey(blink::kWebCryptoKeyFormatPkcs8, key, &exported_key));
  110. EXPECT_BYTES_EQ_HEX(kPrivateKeyPkcs8DerHex, exported_key);
  111. // Failing case: Import RSA key but provide an inconsistent input algorithm
  112. // and usage. Several issues here:
  113. // * AES-CBC doesn't support PKCS8 key format
  114. // * AES-CBC doesn't support "sign" usage
  115. EXPECT_EQ(Status::ErrorUnsupportedImportKeyFormat(),
  116. ImportKey(blink::kWebCryptoKeyFormatPkcs8,
  117. HexStringToBytes(kPrivateKeyPkcs8DerHex),
  118. CreateAlgorithm(blink::kWebCryptoAlgorithmIdAesCbc), true,
  119. blink::kWebCryptoKeyUsageSign, &key));
  120. }
  121. // Tests JWK import and export by doing a roundtrip key conversion and ensuring
  122. // it was lossless:
  123. //
  124. // PKCS8 --> JWK --> PKCS8
  125. TEST_F(WebCryptoRsaSsaTest, ImportRsaPrivateKeyJwkToPkcs8RoundTrip) {
  126. blink::WebCryptoKey key;
  127. ASSERT_EQ(Status::Success(),
  128. ImportKey(blink::kWebCryptoKeyFormatPkcs8,
  129. HexStringToBytes(kPrivateKeyPkcs8DerHex),
  130. CreateRsaHashedImportAlgorithm(
  131. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  132. blink::kWebCryptoAlgorithmIdSha1),
  133. true, blink::kWebCryptoKeyUsageSign, &key));
  134. std::vector<uint8_t> exported_key_jwk;
  135. ASSERT_EQ(Status::Success(),
  136. ExportKey(blink::kWebCryptoKeyFormatJwk, key, &exported_key_jwk));
  137. // All of the optional parameters (p, q, dp, dq, qi) should be present in the
  138. // output.
  139. const char* expected_jwk =
  140. "{\"alg\":\"RS1\",\"d\":\"M6UEKpCyfU9UUcqbu9C0R3GhAa-IQ0Cu-YhfKku-"
  141. "kuiUpySsPFaMj5eFOtB8AmbIxqPKCSnx6PESMYhEKfxNmuVf7olqEM5wfD7X5zTkRyejlXRQ"
  142. "GlMmgxCcKrrKuig8MbS9L1PD7jfjUs7jT55QO9gMBiKtecbc7og1R8ajsyU\",\"dp\":"
  143. "\"KPoTk4ZVvh-"
  144. "KFZy6ylpy6hkMMAieGc0nSlVvNsT24Z9VSzTAd3kEJ7vdjdPt4kSDKPOF2Bsw6OQ7L_-"
  145. "gJ4YZeQ\",\"dq\":\"Gos485j6cSBJiY1_t57gp3ZoeRKZzfoJ78DlB6yyHtdDAe9b_Ui-"
  146. "RV6utuFnglWCdYCo5OjhQVHRUQqCo_LnKQ\",\"e\":\"AQAB\",\"ext\":true,\"key_"
  147. "ops\":[\"sign\"],\"kty\":\"RSA\",\"n\":"
  148. "\"pW5KDnAQF1iaUYfcfqhB0Vby7A42rVKkTf6x5h962ZHYxRBW_-2xYrTA8oOhKoijlN_"
  149. "1JqtykcuzB86r_OCx39XNlQgJbVsri2311nHvY3fAkhyyPCcKcOJZjm_4nRnxBazC0_"
  150. "DLNfKSgOE4a29kxO8i4eHyDQzoz_siSb2aITc\",\"p\":\"5-"
  151. "iUJyCod1Fyc6NWBT6iobwMlKpy1VxuhilrLfyWeUjApyy8zKfqyzVwbgmh31WhU1vZs8w0Fg"
  152. "s7bc0-2o5kQw\",\"q\":\"tp3KHPfU1-yB51uQ_MqHSrzeEj_"
  153. "ScAGAqpBHm25I3o1n7ST58Z2FuidYdPVCzSDccj5pYzZKH5QlRSsmmmeZ_Q\",\"qi\":"
  154. "\"JxVqukEm0kqB86Uoy_sn9WiG-"
  155. "ECp9uhuF6RLlP6TGVhLjiL93h5aLjvYqluo2FhBlOshkKz4MrhH8To9JKefTQ\"}";
  156. EXPECT_BYTES_EQ(
  157. base::as_bytes(base::make_span(base::StringPiece(expected_jwk))),
  158. exported_key_jwk);
  159. ASSERT_EQ(Status::Success(),
  160. ImportKey(blink::kWebCryptoKeyFormatJwk, exported_key_jwk,
  161. CreateRsaHashedImportAlgorithm(
  162. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  163. blink::kWebCryptoAlgorithmIdSha1),
  164. true, blink::kWebCryptoKeyUsageSign, &key));
  165. std::vector<uint8_t> exported_key_pkcs8;
  166. ASSERT_EQ(Status::Success(), ExportKey(blink::kWebCryptoKeyFormatPkcs8, key,
  167. &exported_key_pkcs8));
  168. ASSERT_EQ(HexStringToBytes(kPrivateKeyPkcs8DerHex), exported_key_pkcs8);
  169. }
  170. // Tests importing multiple RSA private keys from JWK, and then exporting to
  171. // PKCS8.
  172. //
  173. // This is a regression test for http://crbug.com/378315, for which importing
  174. // a sequence of keys from JWK could yield the wrong key. The first key would
  175. // be imported correctly, however every key after that would actually import
  176. // the first key.
  177. TEST_F(WebCryptoRsaSsaTest, ImportMultipleRSAPrivateKeysJwk) {
  178. // For this test to be meaningful the keys MUST be kept alive before importing
  179. // new keys.
  180. std::vector<blink::WebCryptoKey> live_keys;
  181. base::Value::List keys = ReadJsonTestFileAsList("rsa_private_keys.json");
  182. for (const auto& key_values : keys) {
  183. SCOPED_TRACE(&key_values - &keys[0]);
  184. ASSERT_TRUE(key_values.is_dict());
  185. const base::DictionaryValue* key_values_dict =
  186. &base::Value::AsDictionaryValue(key_values);
  187. // Get the JWK representation of the key.
  188. const base::DictionaryValue* key_jwk;
  189. ASSERT_TRUE(key_values_dict->GetDictionary("jwk", &key_jwk));
  190. // Get the PKCS8 representation of the key.
  191. std::string pkcs8_hex_string;
  192. ASSERT_TRUE(key_values_dict->GetString("pkcs8", &pkcs8_hex_string));
  193. std::vector<uint8_t> pkcs8_bytes = HexStringToBytes(pkcs8_hex_string);
  194. // Get the modulus length for the key.
  195. absl::optional<int> modulus_length_bits =
  196. key_values_dict->FindIntKey("modulusLength");
  197. ASSERT_TRUE(modulus_length_bits);
  198. blink::WebCryptoKey private_key;
  199. // Import the key from JWK.
  200. ASSERT_EQ(Status::Success(),
  201. ImportKeyJwkFromDict(
  202. *key_jwk,
  203. CreateRsaHashedImportAlgorithm(
  204. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  205. blink::kWebCryptoAlgorithmIdSha256),
  206. true, blink::kWebCryptoKeyUsageSign, &private_key));
  207. live_keys.push_back(private_key);
  208. EXPECT_EQ(
  209. *modulus_length_bits,
  210. static_cast<int>(
  211. private_key.Algorithm().RsaHashedParams()->ModulusLengthBits()));
  212. // Export to PKCS8 and verify that it matches expectation.
  213. std::vector<uint8_t> exported_key_pkcs8;
  214. ASSERT_EQ(Status::Success(), ExportKey(blink::kWebCryptoKeyFormatPkcs8,
  215. private_key, &exported_key_pkcs8));
  216. EXPECT_BYTES_EQ(pkcs8_bytes, exported_key_pkcs8);
  217. }
  218. }
  219. // Import an RSA private key using JWK. Next import a JWK containing the same
  220. // modulus, but mismatched parameters for the rest. It should NOT be possible
  221. // that the second import retrieves the first key. See http://crbug.com/378315
  222. // for how that could happen.
  223. TEST_F(WebCryptoRsaSsaTest, ImportJwkExistingModulusAndInvalid) {
  224. base::Value::List key_list = ReadJsonTestFileAsList("rsa_private_keys.json");
  225. // Import a 1024-bit private key.
  226. const base::Value& key1_props_value = key_list[1];
  227. ASSERT_TRUE(key1_props_value.is_dict());
  228. const base::DictionaryValue* key1_props =
  229. &base::Value::AsDictionaryValue(key1_props_value);
  230. const base::DictionaryValue* key1_jwk;
  231. ASSERT_TRUE(key1_props->GetDictionary("jwk", &key1_jwk));
  232. blink::WebCryptoKey key1;
  233. ASSERT_EQ(
  234. Status::Success(),
  235. ImportKeyJwkFromDict(*key1_jwk,
  236. CreateRsaHashedImportAlgorithm(
  237. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  238. blink::kWebCryptoAlgorithmIdSha256),
  239. true, blink::kWebCryptoKeyUsageSign, &key1));
  240. ASSERT_EQ(1024u, key1.Algorithm().RsaHashedParams()->ModulusLengthBits());
  241. // Construct a JWK using the modulus of key1, but all the other fields from
  242. // another key (also a 1024-bit private key).
  243. base::Value& key2_props_value = key_list[5];
  244. ASSERT_TRUE(key2_props_value.is_dict());
  245. base::DictionaryValue* key2_props = const_cast<base::DictionaryValue*>(
  246. &base::Value::AsDictionaryValue(key2_props_value));
  247. base::DictionaryValue* key2_jwk;
  248. ASSERT_TRUE(key2_props->GetDictionary("jwk", &key2_jwk));
  249. std::string modulus;
  250. key1_jwk->GetString("n", &modulus);
  251. key2_jwk->SetString("n", modulus);
  252. // This should fail, as the n,e,d parameters are not consistent. It MUST NOT
  253. // somehow return the key created earlier.
  254. blink::WebCryptoKey key2;
  255. ASSERT_EQ(
  256. Status::OperationError(),
  257. ImportKeyJwkFromDict(*key2_jwk,
  258. CreateRsaHashedImportAlgorithm(
  259. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  260. blink::kWebCryptoAlgorithmIdSha256),
  261. true, blink::kWebCryptoKeyUsageSign, &key2));
  262. }
  263. TEST_F(WebCryptoRsaSsaTest, GenerateKeyPairRsa) {
  264. // Note: using unrealistic short key lengths here to avoid bogging down tests.
  265. // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha256)
  266. const unsigned int modulus_length = 256;
  267. const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
  268. blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
  269. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  270. blink::kWebCryptoAlgorithmIdSha256, modulus_length, public_exponent);
  271. bool extractable = true;
  272. const blink::WebCryptoKeyUsageMask public_usages =
  273. blink::kWebCryptoKeyUsageVerify;
  274. const blink::WebCryptoKeyUsageMask private_usages =
  275. blink::kWebCryptoKeyUsageSign;
  276. const blink::WebCryptoKeyUsageMask usages = public_usages | private_usages;
  277. blink::WebCryptoKey public_key;
  278. blink::WebCryptoKey private_key;
  279. EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, extractable, usages,
  280. &public_key, &private_key));
  281. ASSERT_FALSE(public_key.IsNull());
  282. ASSERT_FALSE(private_key.IsNull());
  283. EXPECT_EQ(blink::kWebCryptoKeyTypePublic, public_key.GetType());
  284. EXPECT_EQ(blink::kWebCryptoKeyTypePrivate, private_key.GetType());
  285. EXPECT_EQ(modulus_length,
  286. public_key.Algorithm().RsaHashedParams()->ModulusLengthBits());
  287. EXPECT_EQ(modulus_length,
  288. private_key.Algorithm().RsaHashedParams()->ModulusLengthBits());
  289. EXPECT_EQ(blink::kWebCryptoAlgorithmIdSha256,
  290. public_key.Algorithm().RsaHashedParams()->GetHash().Id());
  291. EXPECT_EQ(blink::kWebCryptoAlgorithmIdSha256,
  292. private_key.Algorithm().RsaHashedParams()->GetHash().Id());
  293. EXPECT_TRUE(public_key.Extractable());
  294. EXPECT_EQ(extractable, private_key.Extractable());
  295. EXPECT_EQ(public_usages, public_key.Usages());
  296. EXPECT_EQ(private_usages, private_key.Usages());
  297. // Try exporting the generated key pair, and then re-importing to verify that
  298. // the exported data was valid.
  299. std::vector<uint8_t> public_key_spki;
  300. EXPECT_EQ(Status::Success(), ExportKey(blink::kWebCryptoKeyFormatSpki,
  301. public_key, &public_key_spki));
  302. public_key = blink::WebCryptoKey::CreateNull();
  303. ASSERT_EQ(Status::Success(),
  304. ImportKey(blink::kWebCryptoKeyFormatSpki, public_key_spki,
  305. CreateRsaHashedImportAlgorithm(
  306. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  307. blink::kWebCryptoAlgorithmIdSha256),
  308. true, public_usages, &public_key));
  309. EXPECT_EQ(modulus_length,
  310. public_key.Algorithm().RsaHashedParams()->ModulusLengthBits());
  311. std::vector<uint8_t> private_key_pkcs8;
  312. EXPECT_EQ(Status::Success(), ExportKey(blink::kWebCryptoKeyFormatPkcs8,
  313. private_key, &private_key_pkcs8));
  314. private_key = blink::WebCryptoKey::CreateNull();
  315. ASSERT_EQ(Status::Success(),
  316. ImportKey(blink::kWebCryptoKeyFormatPkcs8, private_key_pkcs8,
  317. CreateRsaHashedImportAlgorithm(
  318. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  319. blink::kWebCryptoAlgorithmIdSha256),
  320. true, private_usages, &private_key));
  321. EXPECT_EQ(modulus_length,
  322. private_key.Algorithm().RsaHashedParams()->ModulusLengthBits());
  323. // Fail with bad modulus.
  324. algorithm = CreateRsaHashedKeyGenAlgorithm(
  325. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  326. blink::kWebCryptoAlgorithmIdSha256, 0, public_exponent);
  327. EXPECT_EQ(Status::ErrorGenerateRsaUnsupportedModulus(),
  328. GenerateKeyPair(algorithm, extractable, usages, &public_key,
  329. &private_key));
  330. // Fail with bad exponent: larger than unsigned long.
  331. unsigned int exponent_length = sizeof(unsigned long) + 1; // NOLINT
  332. const std::vector<uint8_t> long_exponent(exponent_length, 0x01);
  333. algorithm = CreateRsaHashedKeyGenAlgorithm(
  334. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  335. blink::kWebCryptoAlgorithmIdSha256, modulus_length, long_exponent);
  336. EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
  337. GenerateKeyPair(algorithm, extractable, usages, &public_key,
  338. &private_key));
  339. // Fail with bad exponent: empty.
  340. const std::vector<uint8_t> empty_exponent;
  341. algorithm = CreateRsaHashedKeyGenAlgorithm(
  342. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  343. blink::kWebCryptoAlgorithmIdSha256, modulus_length, empty_exponent);
  344. EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
  345. GenerateKeyPair(algorithm, extractable, usages, &public_key,
  346. &private_key));
  347. // Fail with bad exponent: all zeros.
  348. std::vector<uint8_t> exponent_with_leading_zeros(15, 0x00);
  349. algorithm = CreateRsaHashedKeyGenAlgorithm(
  350. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  351. blink::kWebCryptoAlgorithmIdSha256, modulus_length,
  352. exponent_with_leading_zeros);
  353. EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
  354. GenerateKeyPair(algorithm, extractable, usages, &public_key,
  355. &private_key));
  356. // Key generation success using exponent with leading zeros.
  357. exponent_with_leading_zeros.insert(exponent_with_leading_zeros.end(),
  358. public_exponent.begin(),
  359. public_exponent.end());
  360. algorithm = CreateRsaHashedKeyGenAlgorithm(
  361. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  362. blink::kWebCryptoAlgorithmIdSha256, modulus_length,
  363. exponent_with_leading_zeros);
  364. EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, extractable, usages,
  365. &public_key, &private_key));
  366. EXPECT_FALSE(public_key.IsNull());
  367. EXPECT_FALSE(private_key.IsNull());
  368. EXPECT_EQ(blink::kWebCryptoKeyTypePublic, public_key.GetType());
  369. EXPECT_EQ(blink::kWebCryptoKeyTypePrivate, private_key.GetType());
  370. EXPECT_TRUE(public_key.Extractable());
  371. EXPECT_EQ(extractable, private_key.Extractable());
  372. EXPECT_EQ(public_usages, public_key.Usages());
  373. EXPECT_EQ(private_usages, private_key.Usages());
  374. // Successful WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 key generation (sha1)
  375. algorithm = CreateRsaHashedKeyGenAlgorithm(
  376. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  377. blink::kWebCryptoAlgorithmIdSha1, modulus_length, public_exponent);
  378. EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, false, usages,
  379. &public_key, &private_key));
  380. EXPECT_FALSE(public_key.IsNull());
  381. EXPECT_FALSE(private_key.IsNull());
  382. EXPECT_EQ(blink::kWebCryptoKeyTypePublic, public_key.GetType());
  383. EXPECT_EQ(blink::kWebCryptoKeyTypePrivate, private_key.GetType());
  384. EXPECT_EQ(modulus_length,
  385. public_key.Algorithm().RsaHashedParams()->ModulusLengthBits());
  386. EXPECT_EQ(modulus_length,
  387. private_key.Algorithm().RsaHashedParams()->ModulusLengthBits());
  388. EXPECT_EQ(blink::kWebCryptoAlgorithmIdSha1,
  389. public_key.Algorithm().RsaHashedParams()->GetHash().Id());
  390. EXPECT_EQ(blink::kWebCryptoAlgorithmIdSha1,
  391. private_key.Algorithm().RsaHashedParams()->GetHash().Id());
  392. // Even though "extractable" was set to false, the public key remains
  393. // extractable.
  394. EXPECT_TRUE(public_key.Extractable());
  395. EXPECT_FALSE(private_key.Extractable());
  396. EXPECT_EQ(public_usages, public_key.Usages());
  397. EXPECT_EQ(private_usages, private_key.Usages());
  398. // Exporting a private key as SPKI format doesn't make sense. However this
  399. // will first fail because the key is not extractable.
  400. std::vector<uint8_t> output;
  401. EXPECT_EQ(Status::ErrorKeyNotExtractable(),
  402. ExportKey(blink::kWebCryptoKeyFormatSpki, private_key, &output));
  403. // Re-generate an extractable private_key and try to export it as SPKI format.
  404. // This should fail since spki is for public keys.
  405. EXPECT_EQ(Status::Success(), GenerateKeyPair(algorithm, true, usages,
  406. &public_key, &private_key));
  407. EXPECT_EQ(Status::ErrorUnexpectedKeyType(),
  408. ExportKey(blink::kWebCryptoKeyFormatSpki, private_key, &output));
  409. }
  410. TEST_F(WebCryptoRsaSsaTest, GenerateKeyPairRsaBadModulusLength) {
  411. const unsigned int kBadModulusBits[] = {
  412. 0,
  413. 248, // Too small.
  414. 257, // Not a multiple of 8.
  415. 1023, // Not a multiple of 8.
  416. 0xFFFFFFFF, // Too big.
  417. 16384 + 8, // 16384 is the maxmimum length that NSS succeeds for.
  418. };
  419. const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
  420. for (auto modulus_length_bits : kBadModulusBits) {
  421. blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
  422. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  423. blink::kWebCryptoAlgorithmIdSha256, modulus_length_bits,
  424. public_exponent);
  425. bool extractable = true;
  426. const blink::WebCryptoKeyUsageMask usages = blink::kWebCryptoKeyUsageSign;
  427. blink::WebCryptoKey public_key;
  428. blink::WebCryptoKey private_key;
  429. EXPECT_EQ(Status::ErrorGenerateRsaUnsupportedModulus(),
  430. GenerateKeyPair(algorithm, extractable, usages, &public_key,
  431. &private_key));
  432. }
  433. }
  434. // Try generating RSA key pairs using unsupported public exponents. Only
  435. // exponents of 3 and 65537 are supported. Although OpenSSL can support other
  436. // values, it can also hang when given invalid exponents. To avoid hanging, use
  437. // a whitelist of known safe exponents.
  438. TEST_F(WebCryptoRsaSsaTest, GenerateKeyPairRsaBadExponent) {
  439. const unsigned int modulus_length = 1024;
  440. const char* const kPublicExponents[] = {
  441. "11", // 17 - This is a valid public exponent, but currently disallowed.
  442. "00",
  443. "01",
  444. "02",
  445. "010000", // 65536
  446. };
  447. for (auto* const exponent : kPublicExponents) {
  448. SCOPED_TRACE(&exponent - &kPublicExponents[0]);
  449. blink::WebCryptoAlgorithm algorithm = CreateRsaHashedKeyGenAlgorithm(
  450. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  451. blink::kWebCryptoAlgorithmIdSha256, modulus_length,
  452. HexStringToBytes(exponent));
  453. blink::WebCryptoKey public_key;
  454. blink::WebCryptoKey private_key;
  455. EXPECT_EQ(Status::ErrorGenerateKeyPublicExponent(),
  456. GenerateKeyPair(algorithm, true, blink::kWebCryptoKeyUsageSign,
  457. &public_key, &private_key));
  458. }
  459. }
  460. TEST_F(WebCryptoRsaSsaTest, SignVerifyFailures) {
  461. // Import a key pair.
  462. blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
  463. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  464. blink::kWebCryptoAlgorithmIdSha1);
  465. blink::WebCryptoKey public_key;
  466. blink::WebCryptoKey private_key;
  467. ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
  468. HexStringToBytes(kPublicKeySpkiDerHex),
  469. HexStringToBytes(kPrivateKeyPkcs8DerHex), import_algorithm, false,
  470. blink::kWebCryptoKeyUsageVerify, blink::kWebCryptoKeyUsageSign,
  471. &public_key, &private_key));
  472. blink::WebCryptoAlgorithm algorithm =
  473. CreateAlgorithm(blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
  474. std::vector<uint8_t> signature;
  475. bool signature_match;
  476. // Compute a signature.
  477. const std::vector<uint8_t> data = HexStringToBytes("010203040506070809");
  478. ASSERT_EQ(Status::Success(), Sign(algorithm, private_key, data, &signature));
  479. // Ensure truncated signature does not verify by passing one less byte.
  480. EXPECT_EQ(Status::Success(),
  481. Verify(algorithm, public_key,
  482. base::make_span(signature).first(signature.size() - 1), data,
  483. &signature_match));
  484. EXPECT_FALSE(signature_match);
  485. // Ensure truncated signature does not verify by passing no bytes.
  486. EXPECT_EQ(Status::Success(),
  487. Verify(algorithm, public_key, {}, data, &signature_match));
  488. EXPECT_FALSE(signature_match);
  489. // Ensure corrupted signature does not verify.
  490. std::vector<uint8_t> corrupt_sig = signature;
  491. corrupt_sig[corrupt_sig.size() / 2] ^= 0x1;
  492. EXPECT_EQ(Status::Success(),
  493. Verify(algorithm, public_key, corrupt_sig, data, &signature_match));
  494. EXPECT_FALSE(signature_match);
  495. // Ensure signatures that are greater than the modulus size fail.
  496. const size_t long_message_size_bytes = 1024;
  497. DCHECK_GT(long_message_size_bytes, kModulusLengthBits / 8);
  498. const unsigned char kLongSignature[long_message_size_bytes] = {0};
  499. EXPECT_EQ(Status::Success(), Verify(algorithm, public_key, kLongSignature,
  500. data, &signature_match));
  501. EXPECT_FALSE(signature_match);
  502. // Ensure that signing and verifying with an incompatible algorithm fails.
  503. algorithm = CreateAlgorithm(blink::kWebCryptoAlgorithmIdRsaOaep);
  504. EXPECT_EQ(Status::ErrorUnexpected(),
  505. Sign(algorithm, private_key, data, &signature));
  506. EXPECT_EQ(Status::ErrorUnexpected(),
  507. Verify(algorithm, public_key, signature, data, &signature_match));
  508. // Some crypto libraries (NSS) can automatically select the RSA SSA inner hash
  509. // based solely on the contents of the input signature data. In the Web Crypto
  510. // implementation, the inner hash should be specified uniquely by the key
  511. // algorithm parameter. To validate this behavior, call Verify with a computed
  512. // signature that used one hash type (SHA-1), but pass in a key with a
  513. // different inner hash type (SHA-256). If the hash type is determined by the
  514. // signature itself (undesired), the verify will pass, while if the hash type
  515. // is specified by the key algorithm (desired), the verify will fail.
  516. // Compute a signature using SHA-1 as the inner hash.
  517. EXPECT_EQ(Status::Success(),
  518. Sign(CreateAlgorithm(blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
  519. private_key, data, &signature));
  520. blink::WebCryptoKey public_key_256;
  521. EXPECT_EQ(Status::Success(),
  522. ImportKey(blink::kWebCryptoKeyFormatSpki,
  523. HexStringToBytes(kPublicKeySpkiDerHex),
  524. CreateRsaHashedImportAlgorithm(
  525. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  526. blink::kWebCryptoAlgorithmIdSha256),
  527. true, blink::kWebCryptoKeyUsageVerify, &public_key_256));
  528. // Now verify using an algorithm whose inner hash is SHA-256, not SHA-1. The
  529. // signature should not verify.
  530. // NOTE: public_key was produced by generateKey, and so its associated
  531. // algorithm has WebCryptoRsaKeyGenParams and not WebCryptoRsaSsaParams. Thus
  532. // it has no inner hash to conflict with the input algorithm.
  533. EXPECT_EQ(blink::kWebCryptoAlgorithmIdSha1,
  534. private_key.Algorithm().RsaHashedParams()->GetHash().Id());
  535. EXPECT_EQ(blink::kWebCryptoAlgorithmIdSha256,
  536. public_key_256.Algorithm().RsaHashedParams()->GetHash().Id());
  537. bool is_match;
  538. EXPECT_EQ(Status::Success(),
  539. Verify(CreateAlgorithm(blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5),
  540. public_key_256, signature, data, &is_match));
  541. EXPECT_FALSE(is_match);
  542. }
  543. TEST_F(WebCryptoRsaSsaTest, SignVerifyKnownAnswer) {
  544. // Import the key pair.
  545. blink::WebCryptoAlgorithm import_algorithm = CreateRsaHashedImportAlgorithm(
  546. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  547. blink::kWebCryptoAlgorithmIdSha1);
  548. blink::WebCryptoKey public_key;
  549. blink::WebCryptoKey private_key;
  550. ASSERT_NO_FATAL_FAILURE(ImportRsaKeyPair(
  551. HexStringToBytes(kPublicKeySpkiDerHex),
  552. HexStringToBytes(kPrivateKeyPkcs8DerHex), import_algorithm, false,
  553. blink::kWebCryptoKeyUsageVerify, blink::kWebCryptoKeyUsageSign,
  554. &public_key, &private_key));
  555. blink::WebCryptoAlgorithm algorithm =
  556. CreateAlgorithm(blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5);
  557. // Validate the signatures are computed and verified as expected.
  558. base::Value::List tests = ReadJsonTestFileAsList("pkcs1v15_sign.json");
  559. std::vector<uint8_t> signature;
  560. for (const auto& test_value : tests) {
  561. SCOPED_TRACE(&test_value - &tests[0]);
  562. ASSERT_TRUE(test_value.is_dict());
  563. const base::DictionaryValue* test =
  564. &base::Value::AsDictionaryValue(test_value);
  565. std::vector<uint8_t> test_message =
  566. GetBytesFromHexString(test, "message_hex");
  567. std::vector<uint8_t> test_signature =
  568. GetBytesFromHexString(test, "signature_hex");
  569. signature.clear();
  570. ASSERT_EQ(Status::Success(),
  571. Sign(algorithm, private_key, test_message, &signature));
  572. EXPECT_BYTES_EQ(test_signature, signature);
  573. bool is_match = false;
  574. ASSERT_EQ(Status::Success(), Verify(algorithm, public_key, test_signature,
  575. test_message, &is_match));
  576. EXPECT_TRUE(is_match);
  577. }
  578. }
  579. // Try importing an RSA-SSA public key with unsupported key usages using SPKI
  580. // format. RSA-SSA public keys only support the 'verify' usage.
  581. TEST_F(WebCryptoRsaSsaTest, ImportRsaSsaPublicKeyBadUsage_SPKI) {
  582. const blink::WebCryptoAlgorithm algorithm = CreateRsaHashedImportAlgorithm(
  583. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  584. blink::kWebCryptoAlgorithmIdSha256);
  585. const blink::WebCryptoKeyUsageMask kBadUsages[] = {
  586. blink::kWebCryptoKeyUsageSign,
  587. blink::kWebCryptoKeyUsageSign | blink::kWebCryptoKeyUsageVerify,
  588. blink::kWebCryptoKeyUsageEncrypt,
  589. blink::kWebCryptoKeyUsageEncrypt | blink::kWebCryptoKeyUsageDecrypt,
  590. };
  591. for (auto usage : kBadUsages) {
  592. blink::WebCryptoKey public_key;
  593. ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
  594. ImportKey(blink::kWebCryptoKeyFormatSpki,
  595. HexStringToBytes(kPublicKeySpkiDerHex), algorithm,
  596. false, usage, &public_key));
  597. }
  598. }
  599. // Try importing an RSA-SSA public key with unsupported key usages using JWK
  600. // format. RSA-SSA public keys only support the 'verify' usage.
  601. TEST_F(WebCryptoRsaSsaTest, ImportRsaSsaPublicKeyBadUsage_JWK) {
  602. const blink::WebCryptoAlgorithm algorithm = CreateRsaHashedImportAlgorithm(
  603. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  604. blink::kWebCryptoAlgorithmIdSha256);
  605. const blink::WebCryptoKeyUsageMask kBadUsages[] = {
  606. blink::kWebCryptoKeyUsageSign,
  607. blink::kWebCryptoKeyUsageSign | blink::kWebCryptoKeyUsageVerify,
  608. blink::kWebCryptoKeyUsageEncrypt,
  609. blink::kWebCryptoKeyUsageEncrypt | blink::kWebCryptoKeyUsageDecrypt,
  610. };
  611. base::DictionaryValue dict;
  612. RestoreJwkRsaDictionary(&dict);
  613. dict.RemoveKey("use");
  614. dict.SetString("alg", "RS256");
  615. for (auto usage : kBadUsages) {
  616. blink::WebCryptoKey public_key;
  617. ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
  618. ImportKeyJwkFromDict(dict, algorithm, false, usage, &public_key));
  619. }
  620. }
  621. // Generate an RSA-SSA key pair with invalid usages. RSA-SSA supports:
  622. // 'sign', 'verify'
  623. TEST_F(WebCryptoRsaSsaTest, GenerateKeyBadUsages) {
  624. const blink::WebCryptoKeyUsageMask kBadUsages[] = {
  625. blink::kWebCryptoKeyUsageDecrypt,
  626. blink::kWebCryptoKeyUsageVerify | blink::kWebCryptoKeyUsageDecrypt,
  627. blink::kWebCryptoKeyUsageWrapKey,
  628. };
  629. const unsigned int modulus_length = 256;
  630. const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
  631. for (auto usage : kBadUsages) {
  632. blink::WebCryptoKey public_key;
  633. blink::WebCryptoKey private_key;
  634. ASSERT_EQ(Status::ErrorCreateKeyBadUsages(),
  635. GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
  636. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  637. blink::kWebCryptoAlgorithmIdSha256,
  638. modulus_length, public_exponent),
  639. true, usage, &public_key, &private_key));
  640. }
  641. }
  642. // Generate an RSA-SSA key pair. The public and private keys should select the
  643. // key usages which are applicable, and not have the exact same usages as was
  644. // specified to GenerateKey
  645. TEST_F(WebCryptoRsaSsaTest, GenerateKeyPairIntersectUsages) {
  646. const unsigned int modulus_length = 256;
  647. const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
  648. blink::WebCryptoKey public_key;
  649. blink::WebCryptoKey private_key;
  650. ASSERT_EQ(
  651. Status::Success(),
  652. GenerateKeyPair(
  653. CreateRsaHashedKeyGenAlgorithm(
  654. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  655. blink::kWebCryptoAlgorithmIdSha256, modulus_length,
  656. public_exponent),
  657. true, blink::kWebCryptoKeyUsageSign | blink::kWebCryptoKeyUsageVerify,
  658. &public_key, &private_key));
  659. EXPECT_EQ(blink::kWebCryptoKeyUsageVerify, public_key.Usages());
  660. EXPECT_EQ(blink::kWebCryptoKeyUsageSign, private_key.Usages());
  661. // Try again but this time without the Verify usages.
  662. ASSERT_EQ(Status::Success(),
  663. GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
  664. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  665. blink::kWebCryptoAlgorithmIdSha256,
  666. modulus_length, public_exponent),
  667. true, blink::kWebCryptoKeyUsageSign, &public_key,
  668. &private_key));
  669. EXPECT_EQ(0, public_key.Usages());
  670. EXPECT_EQ(blink::kWebCryptoKeyUsageSign, private_key.Usages());
  671. }
  672. TEST_F(WebCryptoRsaSsaTest, GenerateKeyPairEmptyUsages) {
  673. const unsigned int modulus_length = 256;
  674. const std::vector<uint8_t> public_exponent = HexStringToBytes("010001");
  675. blink::WebCryptoKey public_key;
  676. blink::WebCryptoKey private_key;
  677. ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(),
  678. GenerateKeyPair(CreateRsaHashedKeyGenAlgorithm(
  679. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  680. blink::kWebCryptoAlgorithmIdSha256,
  681. modulus_length, public_exponent),
  682. true, 0, &public_key, &private_key));
  683. }
  684. TEST_F(WebCryptoRsaSsaTest, ImportKeyEmptyUsages) {
  685. blink::WebCryptoKey public_key;
  686. blink::WebCryptoKey private_key;
  687. // Public without usage does not throw an error.
  688. ASSERT_EQ(Status::Success(),
  689. ImportKey(blink::kWebCryptoKeyFormatSpki,
  690. HexStringToBytes(kPublicKeySpkiDerHex),
  691. CreateRsaHashedImportAlgorithm(
  692. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  693. blink::kWebCryptoAlgorithmIdSha256),
  694. true, 0, &public_key));
  695. EXPECT_EQ(0, public_key.Usages());
  696. // Private empty usage will throw an error.
  697. ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(),
  698. ImportKey(blink::kWebCryptoKeyFormatPkcs8,
  699. HexStringToBytes(kPrivateKeyPkcs8DerHex),
  700. CreateRsaHashedImportAlgorithm(
  701. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  702. blink::kWebCryptoAlgorithmIdSha1),
  703. true, 0, &private_key));
  704. std::vector<uint8_t> public_jwk;
  705. ASSERT_EQ(Status::Success(),
  706. ExportKey(blink::kWebCryptoKeyFormatJwk, public_key, &public_jwk));
  707. ASSERT_EQ(Status::Success(),
  708. ImportKey(blink::kWebCryptoKeyFormatJwk, public_jwk,
  709. CreateRsaHashedImportAlgorithm(
  710. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  711. blink::kWebCryptoAlgorithmIdSha256),
  712. true, 0, &public_key));
  713. EXPECT_EQ(0, public_key.Usages());
  714. // With correct usage to get correct imported private_key
  715. std::vector<uint8_t> private_jwk;
  716. ImportKey(blink::kWebCryptoKeyFormatPkcs8,
  717. HexStringToBytes(kPrivateKeyPkcs8DerHex),
  718. CreateRsaHashedImportAlgorithm(
  719. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  720. blink::kWebCryptoAlgorithmIdSha1),
  721. true, blink::kWebCryptoKeyUsageSign, &private_key);
  722. ASSERT_EQ(Status::Success(), ExportKey(blink::kWebCryptoKeyFormatJwk,
  723. private_key, &private_jwk));
  724. ASSERT_EQ(Status::ErrorCreateKeyEmptyUsages(),
  725. ImportKey(blink::kWebCryptoKeyFormatJwk, private_jwk,
  726. CreateRsaHashedImportAlgorithm(
  727. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  728. blink::kWebCryptoAlgorithmIdSha1),
  729. true, 0, &private_key));
  730. }
  731. TEST_F(WebCryptoRsaSsaTest, ImportExportJwkRsaPublicKey) {
  732. struct TestCase {
  733. const blink::WebCryptoAlgorithmId hash;
  734. const blink::WebCryptoKeyUsageMask usage;
  735. const char* const jwk_alg;
  736. };
  737. const TestCase kTests[] = {{blink::kWebCryptoAlgorithmIdSha1,
  738. blink::kWebCryptoKeyUsageVerify, "RS1"},
  739. {blink::kWebCryptoAlgorithmIdSha256,
  740. blink::kWebCryptoKeyUsageVerify, "RS256"},
  741. {blink::kWebCryptoAlgorithmIdSha384,
  742. blink::kWebCryptoKeyUsageVerify, "RS384"},
  743. {blink::kWebCryptoAlgorithmIdSha512,
  744. blink::kWebCryptoKeyUsageVerify, "RS512"}};
  745. for (const auto& test : kTests) {
  746. SCOPED_TRACE(&test - &kTests[0]);
  747. const blink::WebCryptoAlgorithm import_algorithm =
  748. CreateRsaHashedImportAlgorithm(
  749. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5, test.hash);
  750. // Import the spki to create a public key
  751. blink::WebCryptoKey public_key;
  752. ASSERT_EQ(Status::Success(),
  753. ImportKey(blink::kWebCryptoKeyFormatSpki,
  754. HexStringToBytes(kPublicKeySpkiDerHex),
  755. import_algorithm, true, test.usage, &public_key));
  756. // Export the public key as JWK and verify its contents
  757. std::vector<uint8_t> jwk;
  758. ASSERT_EQ(Status::Success(),
  759. ExportKey(blink::kWebCryptoKeyFormatJwk, public_key, &jwk));
  760. EXPECT_TRUE(VerifyPublicJwk(jwk, test.jwk_alg, kPublicKeyModulusHex,
  761. kPublicKeyExponentHex, test.usage));
  762. // Import the JWK back in to create a new key
  763. blink::WebCryptoKey public_key2;
  764. ASSERT_EQ(Status::Success(),
  765. ImportKey(blink::kWebCryptoKeyFormatJwk, jwk, import_algorithm,
  766. true, test.usage, &public_key2));
  767. ASSERT_TRUE(public_key2.Handle());
  768. EXPECT_EQ(blink::kWebCryptoKeyTypePublic, public_key2.GetType());
  769. EXPECT_TRUE(public_key2.Extractable());
  770. EXPECT_EQ(import_algorithm.Id(), public_key2.Algorithm().Id());
  771. // Export the new key as spki and compare to the original.
  772. std::vector<uint8_t> spki;
  773. ASSERT_EQ(Status::Success(),
  774. ExportKey(blink::kWebCryptoKeyFormatSpki, public_key2, &spki));
  775. EXPECT_BYTES_EQ_HEX(kPublicKeySpkiDerHex, spki);
  776. }
  777. }
  778. TEST_F(WebCryptoRsaSsaTest, ImportJwkRsaFailures) {
  779. base::DictionaryValue dict;
  780. RestoreJwkRsaDictionary(&dict);
  781. blink::WebCryptoAlgorithm algorithm = CreateRsaHashedImportAlgorithm(
  782. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  783. blink::kWebCryptoAlgorithmIdSha256);
  784. blink::WebCryptoKeyUsageMask usages = blink::kWebCryptoKeyUsageVerify;
  785. blink::WebCryptoKey key;
  786. // An RSA public key JWK _must_ have an "n" (modulus) and an "e" (exponent)
  787. // entry, while an RSA private key must have those plus at least a "d"
  788. // (private exponent) entry.
  789. // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
  790. // section 6.3.
  791. // Baseline pass.
  792. EXPECT_EQ(Status::Success(),
  793. ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
  794. EXPECT_EQ(algorithm.Id(), key.Algorithm().Id());
  795. EXPECT_FALSE(key.Extractable());
  796. EXPECT_EQ(blink::kWebCryptoKeyUsageVerify, key.Usages());
  797. EXPECT_EQ(blink::kWebCryptoKeyTypePublic, key.GetType());
  798. // The following are specific failure cases for when kty = "RSA".
  799. // Fail if either "n" or "e" is not present or malformed.
  800. for (auto* const parm : {"n", "e"}) {
  801. // Fail on missing parameter.
  802. dict.RemoveKey(parm);
  803. EXPECT_NE(Status::Success(),
  804. ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
  805. RestoreJwkRsaDictionary(&dict);
  806. // Fail on bad b64 parameter encoding.
  807. dict.SetString(parm, "Qk3f0DsytU8lfza2au #$% Htaw2xpop9yTuH0");
  808. EXPECT_NE(Status::Success(),
  809. ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
  810. RestoreJwkRsaDictionary(&dict);
  811. // Fail on empty parameter.
  812. dict.SetString(parm, "");
  813. EXPECT_EQ(Status::ErrorJwkEmptyBigInteger(parm),
  814. ImportKeyJwkFromDict(dict, algorithm, false, usages, &key));
  815. RestoreJwkRsaDictionary(&dict);
  816. }
  817. }
  818. // Try importing an RSA-SSA key from JWK format, having specified both Sign and
  819. // Verify usage, AND an invalid JWK.
  820. //
  821. // Parsing the invalid JWK will fail before the usage check is done.
  822. TEST_F(WebCryptoRsaSsaTest, ImportRsaSsaJwkBadUsageAndData) {
  823. std::string bad_data = "hello";
  824. blink::WebCryptoKey key;
  825. ASSERT_EQ(
  826. Status::ErrorJwkNotDictionary(),
  827. ImportKey(blink::kWebCryptoKeyFormatJwk,
  828. base::as_bytes(base::make_span(bad_data)),
  829. CreateRsaHashedImportAlgorithm(
  830. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  831. blink::kWebCryptoAlgorithmIdSha256),
  832. true,
  833. blink::kWebCryptoKeyUsageVerify | blink::kWebCryptoKeyUsageSign,
  834. &key));
  835. }
  836. // Imports invalid JWK/SPKI/PKCS8 data and verifies that it fails as expected.
  837. TEST_F(WebCryptoRsaSsaTest, ImportInvalidKeyData) {
  838. base::Value::List tests = ReadJsonTestFileAsList("bad_rsa_keys.json");
  839. for (const auto& test_value : tests) {
  840. SCOPED_TRACE(&test_value - &tests[0]);
  841. ASSERT_TRUE(test_value.is_dict());
  842. const base::DictionaryValue* test =
  843. &base::Value::AsDictionaryValue(test_value);
  844. blink::WebCryptoKeyFormat key_format = GetKeyFormatFromJsonTestCase(test);
  845. std::vector<uint8_t> key_data =
  846. GetKeyDataFromJsonTestCase(test, key_format);
  847. std::string test_error;
  848. ASSERT_TRUE(test->GetString("error", &test_error));
  849. blink::WebCryptoKeyUsageMask usages = blink::kWebCryptoKeyUsageSign;
  850. if (key_format == blink::kWebCryptoKeyFormatSpki)
  851. usages = blink::kWebCryptoKeyUsageVerify;
  852. blink::WebCryptoKey key;
  853. Status status = ImportKey(key_format, key_data,
  854. CreateRsaHashedImportAlgorithm(
  855. blink::kWebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
  856. blink::kWebCryptoAlgorithmIdSha256),
  857. true, usages, &key);
  858. EXPECT_EQ(test_error, StatusToString(status));
  859. }
  860. }
  861. } // namespace
  862. } // namespace webcrypto