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

Side by Side Diff: content/child/webcrypto/jwk.cc

Issue 205913002: [webcrypto] Add JWK RSA public key export for NSS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 6 years, 9 months 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <algorithm> 5 #include <algorithm>
6 #include <functional> 6 #include <functional>
7 #include <map> 7 #include <map>
8 #include "base/json/json_reader.h" 8 #include "base/json/json_reader.h"
9 #include "base/json/json_writer.h" 9 #include "base/json/json_writer.h"
10 #include "base/lazy_instance.h" 10 #include "base/lazy_instance.h"
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 blink::WebCryptoAlgorithmIdSha1>); 85 blink::WebCryptoAlgorithmIdSha1>);
86 alg_to_info_["HS256"] = 86 alg_to_info_["HS256"] =
87 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, 87 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm,
88 blink::WebCryptoAlgorithmIdSha256>); 88 blink::WebCryptoAlgorithmIdSha256>);
89 alg_to_info_["HS384"] = 89 alg_to_info_["HS384"] =
90 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, 90 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm,
91 blink::WebCryptoAlgorithmIdSha384>); 91 blink::WebCryptoAlgorithmIdSha384>);
92 alg_to_info_["HS512"] = 92 alg_to_info_["HS512"] =
93 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm, 93 JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm,
94 blink::WebCryptoAlgorithmIdSha512>); 94 blink::WebCryptoAlgorithmIdSha512>);
95 alg_to_info_["RS1"] =
96 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm,
97 blink::WebCryptoAlgorithmIdSha1>);
95 alg_to_info_["RS256"] = 98 alg_to_info_["RS256"] =
96 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, 99 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm,
97 blink::WebCryptoAlgorithmIdSha256>); 100 blink::WebCryptoAlgorithmIdSha256>);
98 alg_to_info_["RS384"] = 101 alg_to_info_["RS384"] =
99 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, 102 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm,
100 blink::WebCryptoAlgorithmIdSha384>); 103 blink::WebCryptoAlgorithmIdSha384>);
101 alg_to_info_["RS512"] = 104 alg_to_info_["RS512"] =
102 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm, 105 JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm,
103 blink::WebCryptoAlgorithmIdSha512>); 106 blink::WebCryptoAlgorithmIdSha512>);
104 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo( 107 alg_to_info_["RSA1_5"] = JwkAlgorithmInfo(
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 // base64url encoding of the raw key. 291 // base64url encoding of the raw key.
289 DCHECK(!raw_key.isNull()); 292 DCHECK(!raw_key.isNull());
290 DCHECK(raw_key.data()); 293 DCHECK(raw_key.data());
291 DCHECK(raw_key.byteLength()); 294 DCHECK(raw_key.byteLength());
292 unsigned int key_length_bytes = raw_key.byteLength(); 295 unsigned int key_length_bytes = raw_key.byteLength();
293 const base::StringPiece key_str(static_cast<const char*>(raw_key.data()), 296 const base::StringPiece key_str(static_cast<const char*>(raw_key.data()),
294 key_length_bytes); 297 key_length_bytes);
295 jwk_dict->SetString("k", Base64EncodeUrlSafe(key_str)); 298 jwk_dict->SetString("k", Base64EncodeUrlSafe(key_str));
296 } 299 }
297 300
301 // Writes an RSA public key to a JWK dictionary
302 void WriteRsaPublicKey(const blink::WebArrayBuffer& modulus,
303 const blink::WebArrayBuffer& public_exponent,
304 base::DictionaryValue* jwk_dict) {
305 DCHECK(jwk_dict);
306 jwk_dict->SetString("kty", "RSA");
307
308 DCHECK(!modulus.isNull());
309 DCHECK(modulus.data());
310 DCHECK(modulus.byteLength());
311 const unsigned int modulus_length_bytes = modulus.byteLength();
312 const base::StringPiece modulus_str(static_cast<const char*>(modulus.data()),
eroman 2014/03/21 02:30:51 There are now 3 places in the code which do this i
padolph 2014/03/24 04:28:28 Done.
313 modulus_length_bytes);
314 jwk_dict->SetString("n", Base64EncodeUrlSafe(modulus_str));
315
316 DCHECK(!public_exponent.isNull());
eroman 2014/03/21 02:30:51 my preference is to put all input dchecks at the t
padolph 2014/03/24 04:28:28 Done.
317 DCHECK(public_exponent.data());
318 DCHECK(public_exponent.byteLength());
319 const unsigned int public_exponent_length_bytes =
320 public_exponent.byteLength();
321 const base::StringPiece public_exponent_str(
322 static_cast<const char*>(public_exponent.data()),
323 public_exponent_length_bytes);
324 jwk_dict->SetString("e", Base64EncodeUrlSafe(public_exponent_str));
325 }
326
298 // Writes a Web Crypto usage mask to a JWK dictionary. 327 // Writes a Web Crypto usage mask to a JWK dictionary.
299 void WriteKeyOps(blink::WebCryptoKeyUsageMask key_usages, 328 void WriteKeyOps(blink::WebCryptoKeyUsageMask key_usages,
300 base::DictionaryValue* jwk_dict) { 329 base::DictionaryValue* jwk_dict) {
301 jwk_dict->Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(key_usages)); 330 jwk_dict->Set("key_ops", CreateJwkKeyOpsFromWebCryptoUsages(key_usages));
302 } 331 }
303 332
304 // Writes a Web Crypto extractable value to a JWK dictionary. 333 // Writes a Web Crypto extractable value to a JWK dictionary.
305 void WriteExt(bool extractable, base::DictionaryValue* jwk_dict) { 334 void WriteExt(bool extractable, base::DictionaryValue* jwk_dict) {
306 jwk_dict->SetBoolean("ext", extractable); 335 jwk_dict->SetBoolean("ext", extractable);
307 } 336 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 case blink::WebCryptoAlgorithmIdSha512: 392 case blink::WebCryptoAlgorithmIdSha512:
364 jwk_dict->SetString("alg", "HS512"); 393 jwk_dict->SetString("alg", "HS512");
365 break; 394 break;
366 default: 395 default:
367 NOTREACHED(); 396 NOTREACHED();
368 return Status::ErrorUnexpected(); 397 return Status::ErrorUnexpected();
369 } 398 }
370 break; 399 break;
371 } 400 }
372 case blink::WebCryptoKeyAlgorithmParamsTypeRsa: 401 case blink::WebCryptoKeyAlgorithmParamsTypeRsa:
402 switch (algorithm.id()) {
403 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
404 jwk_dict->SetString("alg", "RSA1_5");
405 break;
406 case blink::WebCryptoAlgorithmIdRsaOaep:
eroman 2014/03/21 02:30:51 I don't believe this is correct. In WebCrypto RSA
padolph 2014/03/24 04:28:28 Done.
407 jwk_dict->SetString("alg", "RSA-OAEP");
408 break;
409 default:
410 NOTREACHED();
411 return Status::ErrorUnexpected();
412 }
413 break;
373 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: 414 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
374 // TODO(padolph): Handle RSA key 415 switch (algorithm.rsaHashedParams()->hash().id()) {
375 return Status::ErrorUnsupported(); 416 case blink::WebCryptoAlgorithmIdSha1:
417 jwk_dict->SetString("alg", "RS1");
418 break;
419 case blink::WebCryptoAlgorithmIdSha256:
420 jwk_dict->SetString("alg", "RS256");
421 break;
422 case blink::WebCryptoAlgorithmIdSha384:
423 jwk_dict->SetString("alg", "RS384");
424 break;
425 case blink::WebCryptoAlgorithmIdSha512:
426 jwk_dict->SetString("alg", "RS512");
427 break;
428 default:
429 NOTREACHED();
430 return Status::ErrorUnexpected();
431 }
432 break;
376 default: 433 default:
377 return Status::ErrorUnsupported(); 434 return Status::ErrorUnsupported();
378 } 435 }
379 return Status::Success(); 436 return Status::Success();
380 } 437 }
381 438
439 bool IsRsaPublicKey(const blink::WebCryptoKey& key) {
440 if (key.type() != blink::WebCryptoKeyTypePublic)
441 return false;
442 const blink::WebCryptoAlgorithmId algorithm_id = key.algorithm().id();
443 return algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
444 algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
445 algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep;
446 }
447
448 // TODO(padolph): This function is duplicated in shared_crypto.cc
449 Status ToPlatformPublicKey(const blink::WebCryptoKey& key,
450 platform::PublicKey** out) {
451 *out = static_cast<platform::Key*>(key.handle())->AsPublicKey();
452 if (!*out)
453 return Status::ErrorUnexpectedKeyType();
454 return Status::Success();
455 }
456
382 } // namespace 457 } // namespace
383 458
384 Status ImportKeyJwk(const CryptoData& key_data, 459 Status ImportKeyJwk(const CryptoData& key_data,
385 const blink::WebCryptoAlgorithm& algorithm, 460 const blink::WebCryptoAlgorithm& algorithm,
386 bool extractable, 461 bool extractable,
387 blink::WebCryptoKeyUsageMask usage_mask, 462 blink::WebCryptoKeyUsageMask usage_mask,
388 blink::WebCryptoKey* key) { 463 blink::WebCryptoKey* key) {
389 // TODO(padolph): Generalize this comment to include export, and move to top 464 // TODO(padolph): Generalize this comment to include export, and move to top
390 // of file. 465 // of file.
391 466
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 // 546 //
472 // - alg (Algorithm) 547 // - alg (Algorithm)
473 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18 548 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18
474 // +--------------+-------------------------------------------------------+ 549 // +--------------+-------------------------------------------------------+
475 // | Digital Signature or MAC Algorithm | 550 // | Digital Signature or MAC Algorithm |
476 // +--------------+-------------------------------------------------------+ 551 // +--------------+-------------------------------------------------------+
477 // | "HS1" | HMAC using SHA-1 hash algorithm | 552 // | "HS1" | HMAC using SHA-1 hash algorithm |
478 // | "HS256" | HMAC using SHA-256 hash algorithm | 553 // | "HS256" | HMAC using SHA-256 hash algorithm |
479 // | "HS384" | HMAC using SHA-384 hash algorithm | 554 // | "HS384" | HMAC using SHA-384 hash algorithm |
480 // | "HS512" | HMAC using SHA-512 hash algorithm | 555 // | "HS512" | HMAC using SHA-512 hash algorithm |
556 // | "RS1" | RSASSA using SHA-1 hash algorithm
481 // | "RS256" | RSASSA using SHA-256 hash algorithm | 557 // | "RS256" | RSASSA using SHA-256 hash algorithm |
482 // | "RS384" | RSASSA using SHA-384 hash algorithm | 558 // | "RS384" | RSASSA using SHA-384 hash algorithm |
483 // | "RS512" | RSASSA using SHA-512 hash algorithm | 559 // | "RS512" | RSASSA using SHA-512 hash algorithm |
484 // +--------------+-------------------------------------------------------| 560 // +--------------+-------------------------------------------------------|
485 // | Key Management Algorithm | 561 // | Key Management Algorithm |
486 // +--------------+-------------------------------------------------------+ 562 // +--------------+-------------------------------------------------------+
487 // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] | 563 // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] |
488 // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding | 564 // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding |
489 // | | (OAEP) [RFC3447], with the default parameters | 565 // | | (OAEP) [RFC3447], with the default parameters |
490 // | | specified by RFC3447 in Section A.2.1 | 566 // | | specified by RFC3447 in Section A.2.1 |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
707 CryptoData(jwk_e_value), 783 CryptoData(jwk_e_value),
708 key); 784 key);
709 785
710 } 786 }
711 787
712 return Status::ErrorJwkUnrecognizedKty(); 788 return Status::ErrorJwkUnrecognizedKty();
713 } 789 }
714 790
715 Status ExportKeyJwk(const blink::WebCryptoKey& key, 791 Status ExportKeyJwk(const blink::WebCryptoKey& key,
716 blink::WebArrayBuffer* buffer) { 792 blink::WebArrayBuffer* buffer) {
793 DCHECK(key.extractable());
717 base::DictionaryValue jwk_dict; 794 base::DictionaryValue jwk_dict;
718 Status status = Status::Error(); 795 Status status = Status::Error();
719 blink::WebArrayBuffer exported_key;
720 796
721 if (key.type() == blink::WebCryptoKeyTypeSecret) { 797 unsigned int key_length_bytes = 0;
722 status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key); 798 switch (key.type()) {
723 if (status.IsError()) 799 case blink::WebCryptoKeyTypeSecret: {
724 return status; 800 blink::WebArrayBuffer exported_key;
725 WriteSecretKey(exported_key, &jwk_dict); 801 status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key);
726 } else { 802 if (status.IsError())
727 // TODO(padolph): Handle asymmetric keys, at least the public key. 803 return status;
728 return Status::ErrorUnsupported(); 804 key_length_bytes = exported_key.byteLength();
805 WriteSecretKey(exported_key, &jwk_dict);
806 break;
807 }
808 case blink::WebCryptoKeyTypePublic: {
809 // Currently only RSA public key export is supported.
810 if (!IsRsaPublicKey(key))
811 return Status::ErrorUnsupported();
812 platform::PublicKey* public_key;
813 status = ToPlatformPublicKey(key, &public_key);
814 if (status.IsError())
815 return status;
816 blink::WebArrayBuffer modulus, public_exponent;
817 status =
818 platform::ExportRsaPublicKey(public_key, &modulus, &public_exponent);
819 if (status.IsError())
820 return status;
821 WriteRsaPublicKey(modulus, public_exponent, &jwk_dict);
822 break;
823 }
824 case blink::WebCryptoKeyTypePrivate: // TODO(padolph)
825 default:
826 return Status::ErrorUnsupported();
729 } 827 }
730 828
731 WriteKeyOps(key.usages(), &jwk_dict); 829 WriteKeyOps(key.usages(), &jwk_dict);
732 WriteExt(key.extractable(), &jwk_dict); 830 WriteExt(key.extractable(), &jwk_dict);
733 status = WriteAlg(key.algorithm(), exported_key.byteLength(), &jwk_dict); 831 status = WriteAlg(key.algorithm(), key_length_bytes, &jwk_dict);
734 if (status.IsError()) 832 if (status.IsError())
735 return status; 833 return status;
736 834
737 std::string json; 835 std::string json;
738 base::JSONWriter::Write(&jwk_dict, &json); 836 base::JSONWriter::Write(&jwk_dict, &json);
739 *buffer = CreateArrayBuffer(reinterpret_cast<const uint8*>(json.data()), 837 *buffer = CreateArrayBuffer(reinterpret_cast<const uint8*>(json.data()),
740 json.size()); 838 json.size());
741 return Status::Success(); 839 return Status::Success();
742 } 840 }
743 841
744 } // namespace webcrypto 842 } // namespace webcrypto
745 843
746 } // namespace content 844 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | content/child/webcrypto/platform_crypto.h » ('j') | content/child/webcrypto/platform_crypto.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698