rsa.cc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  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 "components/webcrypto/algorithms/rsa.h"
  5. #include <utility>
  6. #include "base/check_op.h"
  7. #include "base/containers/span.h"
  8. #include "components/webcrypto/algorithms/asymmetric_key_util.h"
  9. #include "components/webcrypto/algorithms/util.h"
  10. #include "components/webcrypto/blink_key_handle.h"
  11. #include "components/webcrypto/generate_key_result.h"
  12. #include "components/webcrypto/jwk.h"
  13. #include "components/webcrypto/status.h"
  14. #include "crypto/openssl_util.h"
  15. #include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
  16. #include "third_party/blink/public/platform/web_crypto_key_algorithm.h"
  17. #include "third_party/boringssl/src/include/openssl/bn.h"
  18. #include "third_party/boringssl/src/include/openssl/evp.h"
  19. #include "third_party/boringssl/src/include/openssl/rsa.h"
  20. namespace webcrypto {
  21. namespace {
  22. // Describes the RSA components for a parsed key. The names of the properties
  23. // correspond with those from the JWK spec. Note that Chromium's WebCrypto
  24. // implementation does not support multi-primes, so there is no parsed field
  25. // for "oth".
  26. struct JwkRsaInfo {
  27. bool is_private_key = false;
  28. std::vector<uint8_t> n;
  29. std::vector<uint8_t> e;
  30. std::vector<uint8_t> d;
  31. std::vector<uint8_t> p;
  32. std::vector<uint8_t> q;
  33. std::vector<uint8_t> dp;
  34. std::vector<uint8_t> dq;
  35. std::vector<uint8_t> qi;
  36. };
  37. // Parses a UTF-8 encoded JWK (key_data), and extracts the RSA components to
  38. // |*result|. Returns Status::Success() on success, otherwise an error.
  39. // In order for this to succeed:
  40. // * expected_alg must match the JWK's "alg", if present.
  41. // * expected_extractable must be consistent with the JWK's "ext", if
  42. // present.
  43. // * expected_usages must be a subset of the JWK's "key_ops" if present.
  44. Status ReadRsaKeyJwk(base::span<const uint8_t> key_data,
  45. const std::string& expected_alg,
  46. bool expected_extractable,
  47. blink::WebCryptoKeyUsageMask expected_usages,
  48. JwkRsaInfo* result) {
  49. JwkReader jwk;
  50. Status status = jwk.Init(key_data, expected_extractable, expected_usages,
  51. "RSA", expected_alg);
  52. if (status.IsError())
  53. return status;
  54. // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry
  55. // in the JWK, while an RSA private key must have those, plus at least a "d"
  56. // (private exponent) entry.
  57. // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
  58. // section 6.3.
  59. status = jwk.GetBigInteger("n", &result->n);
  60. if (status.IsError())
  61. return status;
  62. status = jwk.GetBigInteger("e", &result->e);
  63. if (status.IsError())
  64. return status;
  65. result->is_private_key = jwk.HasMember("d");
  66. if (!result->is_private_key)
  67. return Status::Success();
  68. status = jwk.GetBigInteger("d", &result->d);
  69. if (status.IsError())
  70. return status;
  71. // The "p", "q", "dp", "dq", and "qi" properties are optional in the JWA
  72. // spec. However they are required by Chromium's WebCrypto implementation.
  73. status = jwk.GetBigInteger("p", &result->p);
  74. if (status.IsError())
  75. return status;
  76. status = jwk.GetBigInteger("q", &result->q);
  77. if (status.IsError())
  78. return status;
  79. status = jwk.GetBigInteger("dp", &result->dp);
  80. if (status.IsError())
  81. return status;
  82. status = jwk.GetBigInteger("dq", &result->dq);
  83. if (status.IsError())
  84. return status;
  85. status = jwk.GetBigInteger("qi", &result->qi);
  86. if (status.IsError())
  87. return status;
  88. return Status::Success();
  89. }
  90. // Creates a blink::WebCryptoAlgorithm having the modulus length and public
  91. // exponent of |key|.
  92. Status CreateRsaHashedKeyAlgorithm(
  93. blink::WebCryptoAlgorithmId rsa_algorithm,
  94. blink::WebCryptoAlgorithmId hash_algorithm,
  95. EVP_PKEY* key,
  96. blink::WebCryptoKeyAlgorithm* key_algorithm) {
  97. DCHECK_EQ(EVP_PKEY_RSA, EVP_PKEY_id(key));
  98. RSA* rsa = EVP_PKEY_get0_RSA(key);
  99. if (!rsa)
  100. return Status::ErrorUnexpected();
  101. unsigned int modulus_length_bits = BN_num_bits(rsa->n);
  102. // Convert the public exponent to big-endian representation.
  103. std::vector<uint8_t> e(BN_num_bytes(rsa->e));
  104. if (e.size() == 0)
  105. return Status::ErrorUnexpected();
  106. if (e.size() != BN_bn2bin(rsa->e, &e[0]))
  107. return Status::ErrorUnexpected();
  108. *key_algorithm = blink::WebCryptoKeyAlgorithm::CreateRsaHashed(
  109. rsa_algorithm, modulus_length_bits, &e[0],
  110. static_cast<unsigned int>(e.size()), hash_algorithm);
  111. return Status::Success();
  112. }
  113. // Creates a WebCryptoKey that wraps |private_key|.
  114. Status CreateWebCryptoRsaPrivateKey(
  115. bssl::UniquePtr<EVP_PKEY> private_key,
  116. const blink::WebCryptoAlgorithmId rsa_algorithm_id,
  117. const blink::WebCryptoAlgorithm& hash,
  118. bool extractable,
  119. blink::WebCryptoKeyUsageMask usages,
  120. blink::WebCryptoKey* key) {
  121. blink::WebCryptoKeyAlgorithm key_algorithm;
  122. Status status = CreateRsaHashedKeyAlgorithm(
  123. rsa_algorithm_id, hash.Id(), private_key.get(), &key_algorithm);
  124. if (status.IsError())
  125. return status;
  126. return CreateWebCryptoPrivateKey(std::move(private_key), key_algorithm,
  127. extractable, usages, key);
  128. }
  129. // Creates a WebCryptoKey that wraps |public_key|.
  130. Status CreateWebCryptoRsaPublicKey(
  131. bssl::UniquePtr<EVP_PKEY> public_key,
  132. const blink::WebCryptoAlgorithmId rsa_algorithm_id,
  133. const blink::WebCryptoAlgorithm& hash,
  134. bool extractable,
  135. blink::WebCryptoKeyUsageMask usages,
  136. blink::WebCryptoKey* key) {
  137. blink::WebCryptoKeyAlgorithm key_algorithm;
  138. Status status = CreateRsaHashedKeyAlgorithm(rsa_algorithm_id, hash.Id(),
  139. public_key.get(), &key_algorithm);
  140. if (status.IsError())
  141. return status;
  142. return CreateWebCryptoPublicKey(std::move(public_key), key_algorithm,
  143. extractable, usages, key);
  144. }
  145. Status ImportRsaPrivateKey(const blink::WebCryptoAlgorithm& algorithm,
  146. bool extractable,
  147. blink::WebCryptoKeyUsageMask usages,
  148. const JwkRsaInfo& params,
  149. blink::WebCryptoKey* key) {
  150. bssl::UniquePtr<RSA> rsa(RSA_new());
  151. rsa->n = BN_bin2bn(params.n.data(), params.n.size(), nullptr);
  152. rsa->e = BN_bin2bn(params.e.data(), params.e.size(), nullptr);
  153. rsa->d = BN_bin2bn(params.d.data(), params.d.size(), nullptr);
  154. rsa->p = BN_bin2bn(params.p.data(), params.p.size(), nullptr);
  155. rsa->q = BN_bin2bn(params.q.data(), params.q.size(), nullptr);
  156. rsa->dmp1 = BN_bin2bn(params.dp.data(), params.dp.size(), nullptr);
  157. rsa->dmq1 = BN_bin2bn(params.dq.data(), params.dq.size(), nullptr);
  158. rsa->iqmp = BN_bin2bn(params.qi.data(), params.qi.size(), nullptr);
  159. if (!rsa->n || !rsa->e || !rsa->d || !rsa->p || !rsa->q || !rsa->dmp1 ||
  160. !rsa->dmq1 || !rsa->iqmp) {
  161. return Status::OperationError();
  162. }
  163. // TODO(eroman): This should be a DataError.
  164. if (!RSA_check_key(rsa.get()))
  165. return Status::OperationError();
  166. // Create a corresponding EVP_PKEY.
  167. bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
  168. if (!pkey || !EVP_PKEY_set1_RSA(pkey.get(), rsa.get()))
  169. return Status::OperationError();
  170. return CreateWebCryptoRsaPrivateKey(
  171. std::move(pkey), algorithm.Id(),
  172. algorithm.RsaHashedImportParams()->GetHash(), extractable, usages, key);
  173. }
  174. Status ImportRsaPublicKey(const blink::WebCryptoAlgorithm& algorithm,
  175. bool extractable,
  176. blink::WebCryptoKeyUsageMask usages,
  177. base::span<const uint8_t> n,
  178. base::span<const uint8_t> e,
  179. blink::WebCryptoKey* key) {
  180. bssl::UniquePtr<RSA> rsa(RSA_new());
  181. rsa->n = BN_bin2bn(n.data(), n.size(), nullptr);
  182. rsa->e = BN_bin2bn(e.data(), e.size(), nullptr);
  183. if (!rsa->n || !rsa->e)
  184. return Status::OperationError();
  185. // Create a corresponding EVP_PKEY.
  186. bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
  187. if (!pkey || !EVP_PKEY_set1_RSA(pkey.get(), rsa.get()))
  188. return Status::OperationError();
  189. return CreateWebCryptoRsaPublicKey(
  190. std::move(pkey), algorithm.Id(),
  191. algorithm.RsaHashedImportParams()->GetHash(), extractable, usages, key);
  192. }
  193. // Converts a BIGNUM to a big endian byte array.
  194. std::vector<uint8_t> BIGNUMToVector(const BIGNUM* n) {
  195. std::vector<uint8_t> v(BN_num_bytes(n));
  196. BN_bn2bin(n, v.data());
  197. return v;
  198. }
  199. // Synthesizes an import algorithm given a key algorithm, so that
  200. // deserialization can re-use the ImportKey*() methods.
  201. blink::WebCryptoAlgorithm SynthesizeImportAlgorithmForClone(
  202. const blink::WebCryptoKeyAlgorithm& algorithm) {
  203. return blink::WebCryptoAlgorithm::AdoptParamsAndCreate(
  204. algorithm.Id(), new blink::WebCryptoRsaHashedImportParams(
  205. algorithm.RsaHashedParams()->GetHash()));
  206. }
  207. } // namespace
  208. Status RsaHashedAlgorithm::GenerateKey(
  209. const blink::WebCryptoAlgorithm& algorithm,
  210. bool extractable,
  211. blink::WebCryptoKeyUsageMask combined_usages,
  212. GenerateKeyResult* result) const {
  213. blink::WebCryptoKeyUsageMask public_usages = 0;
  214. blink::WebCryptoKeyUsageMask private_usages = 0;
  215. Status status = GetUsagesForGenerateAsymmetricKey(
  216. combined_usages, all_public_key_usages_, all_private_key_usages_,
  217. &public_usages, &private_usages);
  218. if (status.IsError())
  219. return status;
  220. const blink::WebCryptoRsaHashedKeyGenParams* params =
  221. algorithm.RsaHashedKeyGenParams();
  222. unsigned int modulus_length_bits = params->ModulusLengthBits();
  223. // Limit the RSA key sizes to:
  224. // * Multiple of 8 bits
  225. // * 256 bits to 16K bits
  226. //
  227. // These correspond with limitations at the time there was an NSS WebCrypto
  228. // implementation. However in practice the upper bound is also helpful
  229. // because generating large RSA keys is very slow.
  230. if (modulus_length_bits < 256 || modulus_length_bits > 16384 ||
  231. (modulus_length_bits % 8) != 0) {
  232. return Status::ErrorGenerateRsaUnsupportedModulus();
  233. }
  234. unsigned int public_exponent = 0;
  235. if (!params->ConvertPublicExponentToUnsigned(public_exponent))
  236. return Status::ErrorGenerateKeyPublicExponent();
  237. // OpenSSL hangs when given bad public exponents. Use a whitelist.
  238. if (public_exponent != 3 && public_exponent != 65537)
  239. return Status::ErrorGenerateKeyPublicExponent();
  240. crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
  241. // Generate an RSA key pair.
  242. bssl::UniquePtr<RSA> rsa_private_key(RSA_new());
  243. bssl::UniquePtr<BIGNUM> bn(BN_new());
  244. if (!rsa_private_key.get() || !bn.get() ||
  245. !BN_set_word(bn.get(), public_exponent)) {
  246. return Status::OperationError();
  247. }
  248. if (!RSA_generate_key_ex(rsa_private_key.get(), modulus_length_bits, bn.get(),
  249. nullptr)) {
  250. return Status::OperationError();
  251. }
  252. // Construct an EVP_PKEY for the private key.
  253. bssl::UniquePtr<EVP_PKEY> private_pkey(EVP_PKEY_new());
  254. if (!private_pkey ||
  255. !EVP_PKEY_set1_RSA(private_pkey.get(), rsa_private_key.get())) {
  256. return Status::OperationError();
  257. }
  258. // Construct an EVP_PKEY for the public key.
  259. bssl::UniquePtr<RSA> rsa_public_key(RSAPublicKey_dup(rsa_private_key.get()));
  260. bssl::UniquePtr<EVP_PKEY> public_pkey(EVP_PKEY_new());
  261. if (!public_pkey ||
  262. !EVP_PKEY_set1_RSA(public_pkey.get(), rsa_public_key.get())) {
  263. return Status::OperationError();
  264. }
  265. blink::WebCryptoKey public_key;
  266. blink::WebCryptoKey private_key;
  267. // Note that extractable is unconditionally set to true. This is because per
  268. // the WebCrypto spec generated public keys are always extractable.
  269. status = CreateWebCryptoRsaPublicKey(std::move(public_pkey), algorithm.Id(),
  270. params->GetHash(), true, public_usages,
  271. &public_key);
  272. if (status.IsError())
  273. return status;
  274. status = CreateWebCryptoRsaPrivateKey(std::move(private_pkey), algorithm.Id(),
  275. params->GetHash(), extractable,
  276. private_usages, &private_key);
  277. if (status.IsError())
  278. return status;
  279. result->AssignKeyPair(public_key, private_key);
  280. return Status::Success();
  281. }
  282. Status RsaHashedAlgorithm::ImportKey(blink::WebCryptoKeyFormat format,
  283. base::span<const uint8_t> key_data,
  284. const blink::WebCryptoAlgorithm& algorithm,
  285. bool extractable,
  286. blink::WebCryptoKeyUsageMask usages,
  287. blink::WebCryptoKey* key) const {
  288. switch (format) {
  289. case blink::kWebCryptoKeyFormatPkcs8:
  290. return ImportKeyPkcs8(key_data, algorithm, extractable, usages, key);
  291. case blink::kWebCryptoKeyFormatSpki:
  292. return ImportKeySpki(key_data, algorithm, extractable, usages, key);
  293. case blink::kWebCryptoKeyFormatJwk:
  294. return ImportKeyJwk(key_data, algorithm, extractable, usages, key);
  295. default:
  296. return Status::ErrorUnsupportedImportKeyFormat();
  297. }
  298. }
  299. Status RsaHashedAlgorithm::ExportKey(blink::WebCryptoKeyFormat format,
  300. const blink::WebCryptoKey& key,
  301. std::vector<uint8_t>* buffer) const {
  302. switch (format) {
  303. case blink::kWebCryptoKeyFormatPkcs8:
  304. return ExportKeyPkcs8(key, buffer);
  305. case blink::kWebCryptoKeyFormatSpki:
  306. return ExportKeySpki(key, buffer);
  307. case blink::kWebCryptoKeyFormatJwk:
  308. return ExportKeyJwk(key, buffer);
  309. default:
  310. return Status::ErrorUnsupportedExportKeyFormat();
  311. }
  312. }
  313. Status RsaHashedAlgorithm::ImportKeyPkcs8(
  314. base::span<const uint8_t> key_data,
  315. const blink::WebCryptoAlgorithm& algorithm,
  316. bool extractable,
  317. blink::WebCryptoKeyUsageMask usages,
  318. blink::WebCryptoKey* key) const {
  319. Status status = CheckKeyCreationUsages(all_private_key_usages_, usages);
  320. if (status.IsError())
  321. return status;
  322. bssl::UniquePtr<EVP_PKEY> private_key;
  323. status = ImportUnverifiedPkeyFromPkcs8(key_data, EVP_PKEY_RSA, &private_key);
  324. if (status.IsError())
  325. return status;
  326. // Verify the parameters of the key.
  327. RSA* rsa = EVP_PKEY_get0_RSA(private_key.get());
  328. if (!rsa)
  329. return Status::ErrorUnexpected();
  330. if (!RSA_check_key(rsa))
  331. return Status::DataError();
  332. // TODO(eroman): Validate the algorithm OID against the webcrypto provided
  333. // hash. http://crbug.com/389400
  334. return CreateWebCryptoRsaPrivateKey(
  335. std::move(private_key), algorithm.Id(),
  336. algorithm.RsaHashedImportParams()->GetHash(), extractable, usages, key);
  337. }
  338. Status RsaHashedAlgorithm::ImportKeySpki(
  339. base::span<const uint8_t> key_data,
  340. const blink::WebCryptoAlgorithm& algorithm,
  341. bool extractable,
  342. blink::WebCryptoKeyUsageMask usages,
  343. blink::WebCryptoKey* key) const {
  344. Status status = CheckKeyCreationUsages(all_public_key_usages_, usages);
  345. if (status.IsError())
  346. return status;
  347. bssl::UniquePtr<EVP_PKEY> public_key;
  348. status = ImportUnverifiedPkeyFromSpki(key_data, EVP_PKEY_RSA, &public_key);
  349. if (status.IsError())
  350. return status;
  351. // TODO(eroman): Validate the algorithm OID against the webcrypto provided
  352. // hash. http://crbug.com/389400
  353. return CreateWebCryptoRsaPublicKey(
  354. std::move(public_key), algorithm.Id(),
  355. algorithm.RsaHashedImportParams()->GetHash(), extractable, usages, key);
  356. }
  357. Status RsaHashedAlgorithm::ImportKeyJwk(
  358. base::span<const uint8_t> key_data,
  359. const blink::WebCryptoAlgorithm& algorithm,
  360. bool extractable,
  361. blink::WebCryptoKeyUsageMask usages,
  362. blink::WebCryptoKey* key) const {
  363. crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
  364. const char* jwk_algorithm =
  365. GetJwkAlgorithm(algorithm.RsaHashedImportParams()->GetHash().Id());
  366. if (!jwk_algorithm)
  367. return Status::ErrorUnexpected();
  368. JwkRsaInfo jwk;
  369. Status status =
  370. ReadRsaKeyJwk(key_data, jwk_algorithm, extractable, usages, &jwk);
  371. if (status.IsError())
  372. return status;
  373. // Once the key type is known, verify the usages.
  374. if (jwk.is_private_key) {
  375. status = CheckKeyCreationUsages(all_private_key_usages_, usages);
  376. } else {
  377. status = CheckKeyCreationUsages(all_public_key_usages_, usages);
  378. }
  379. if (status.IsError())
  380. return status;
  381. return jwk.is_private_key
  382. ? ImportRsaPrivateKey(algorithm, extractable, usages, jwk, key)
  383. : ImportRsaPublicKey(algorithm, extractable, usages, jwk.n, jwk.e,
  384. key);
  385. }
  386. Status RsaHashedAlgorithm::ExportKeyPkcs8(const blink::WebCryptoKey& key,
  387. std::vector<uint8_t>* buffer) const {
  388. if (key.GetType() != blink::kWebCryptoKeyTypePrivate)
  389. return Status::ErrorUnexpectedKeyType();
  390. return ExportPKeyPkcs8(GetEVP_PKEY(key), buffer);
  391. }
  392. Status RsaHashedAlgorithm::ExportKeySpki(const blink::WebCryptoKey& key,
  393. std::vector<uint8_t>* buffer) const {
  394. if (key.GetType() != blink::kWebCryptoKeyTypePublic)
  395. return Status::ErrorUnexpectedKeyType();
  396. return ExportPKeySpki(GetEVP_PKEY(key), buffer);
  397. }
  398. Status RsaHashedAlgorithm::ExportKeyJwk(const blink::WebCryptoKey& key,
  399. std::vector<uint8_t>* buffer) const {
  400. crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
  401. EVP_PKEY* pkey = GetEVP_PKEY(key);
  402. RSA* rsa = EVP_PKEY_get0_RSA(pkey);
  403. if (!rsa)
  404. return Status::ErrorUnexpected();
  405. const char* jwk_algorithm =
  406. GetJwkAlgorithm(key.Algorithm().RsaHashedParams()->GetHash().Id());
  407. if (!jwk_algorithm)
  408. return Status::ErrorUnexpected();
  409. switch (key.GetType()) {
  410. case blink::kWebCryptoKeyTypePublic: {
  411. JwkWriter writer(jwk_algorithm, key.Extractable(), key.Usages(), "RSA");
  412. writer.SetBytes("n", BIGNUMToVector(RSA_get0_n(rsa)));
  413. writer.SetBytes("e", BIGNUMToVector(RSA_get0_e(rsa)));
  414. writer.ToJson(buffer);
  415. return Status::Success();
  416. }
  417. case blink::kWebCryptoKeyTypePrivate: {
  418. JwkWriter writer(jwk_algorithm, key.Extractable(), key.Usages(), "RSA");
  419. writer.SetBytes("n", BIGNUMToVector(RSA_get0_n(rsa)));
  420. writer.SetBytes("e", BIGNUMToVector(RSA_get0_e(rsa)));
  421. writer.SetBytes("d", BIGNUMToVector(RSA_get0_d(rsa)));
  422. // Although these are "optional" in the JWA, WebCrypto spec requires them
  423. // to be emitted.
  424. writer.SetBytes("p", BIGNUMToVector(RSA_get0_p(rsa)));
  425. writer.SetBytes("q", BIGNUMToVector(RSA_get0_q(rsa)));
  426. writer.SetBytes("dp", BIGNUMToVector(RSA_get0_dmp1(rsa)));
  427. writer.SetBytes("dq", BIGNUMToVector(RSA_get0_dmq1(rsa)));
  428. writer.SetBytes("qi", BIGNUMToVector(RSA_get0_iqmp(rsa)));
  429. writer.ToJson(buffer);
  430. return Status::Success();
  431. }
  432. default:
  433. return Status::ErrorUnexpected();
  434. }
  435. }
  436. // TODO(eroman): Defer import to the crypto thread. http://crbug.com/430763
  437. Status RsaHashedAlgorithm::DeserializeKeyForClone(
  438. const blink::WebCryptoKeyAlgorithm& algorithm,
  439. blink::WebCryptoKeyType type,
  440. bool extractable,
  441. blink::WebCryptoKeyUsageMask usages,
  442. base::span<const uint8_t> key_data,
  443. blink::WebCryptoKey* key) const {
  444. if (algorithm.ParamsType() !=
  445. blink::kWebCryptoKeyAlgorithmParamsTypeRsaHashed)
  446. return Status::ErrorUnexpected();
  447. blink::WebCryptoAlgorithm import_algorithm =
  448. SynthesizeImportAlgorithmForClone(algorithm);
  449. Status status;
  450. // The serialized data will be either SPKI or PKCS8 formatted.
  451. switch (type) {
  452. case blink::kWebCryptoKeyTypePublic:
  453. status =
  454. ImportKeySpki(key_data, import_algorithm, extractable, usages, key);
  455. break;
  456. case blink::kWebCryptoKeyTypePrivate:
  457. status =
  458. ImportKeyPkcs8(key_data, import_algorithm, extractable, usages, key);
  459. break;
  460. default:
  461. return Status::ErrorUnexpected();
  462. }
  463. if (!status.IsSuccess())
  464. return status;
  465. // There is some duplicated information in the serialized format used by
  466. // structured clone (since the KeyAlgorithm is serialized separately from the
  467. // key data). Use this extra information to further validate what was
  468. // deserialized from the key data.
  469. if (algorithm.Id() != key->Algorithm().Id())
  470. return Status::ErrorUnexpected();
  471. if (key->GetType() != type)
  472. return Status::ErrorUnexpected();
  473. if (algorithm.RsaHashedParams()->ModulusLengthBits() !=
  474. key->Algorithm().RsaHashedParams()->ModulusLengthBits()) {
  475. return Status::ErrorUnexpected();
  476. }
  477. if (algorithm.RsaHashedParams()->PublicExponent().size() !=
  478. key->Algorithm().RsaHashedParams()->PublicExponent().size() ||
  479. 0 !=
  480. memcmp(algorithm.RsaHashedParams()->PublicExponent().data(),
  481. key->Algorithm().RsaHashedParams()->PublicExponent().data(),
  482. key->Algorithm().RsaHashedParams()->PublicExponent().size())) {
  483. return Status::ErrorUnexpected();
  484. }
  485. return Status::Success();
  486. }
  487. } // namespace webcrypto