OLD | NEW |
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 "content/child/webcrypto/nss/rsa_key_nss.h" | 5 #include "content/child/webcrypto/nss/rsa_key_nss.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "content/child/webcrypto/crypto_data.h" | 8 #include "content/child/webcrypto/crypto_data.h" |
9 #include "content/child/webcrypto/jwk.h" | 9 #include "content/child/webcrypto/jwk.h" |
10 #include "content/child/webcrypto/nss/key_nss.h" | 10 #include "content/child/webcrypto/nss/key_nss.h" |
11 #include "content/child/webcrypto/nss/util_nss.h" | 11 #include "content/child/webcrypto/nss/util_nss.h" |
12 #include "content/child/webcrypto/status.h" | 12 #include "content/child/webcrypto/status.h" |
13 #include "content/child/webcrypto/webcrypto_util.h" | 13 #include "content/child/webcrypto/webcrypto_util.h" |
14 #include "crypto/scoped_nss_types.h" | 14 #include "crypto/scoped_nss_types.h" |
15 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | 15 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
16 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" | 16 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" |
17 | 17 |
18 namespace content { | 18 namespace content { |
19 | 19 |
20 namespace webcrypto { | 20 namespace webcrypto { |
21 | 21 |
22 namespace { | 22 namespace { |
23 | 23 |
24 bool CreatePublicKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm, | |
25 SECKEYPublicKey* key, | |
26 blink::WebCryptoKeyAlgorithm* key_algorithm) { | |
27 // TODO(eroman): What about other key types rsaPss, rsaOaep. | |
28 if (!key || key->keyType != rsaKey) | |
29 return false; | |
30 | |
31 unsigned int modulus_length_bits = SECKEY_PublicKeyStrength(key) * 8; | |
32 CryptoData public_exponent(key->u.rsa.publicExponent.data, | |
33 key->u.rsa.publicExponent.len); | |
34 | |
35 switch (algorithm.paramsType()) { | |
36 case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams: | |
37 case blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams: | |
38 *key_algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed( | |
39 algorithm.id(), | |
40 modulus_length_bits, | |
41 public_exponent.bytes(), | |
42 public_exponent.byte_length(), | |
43 GetInnerHashAlgorithm(algorithm).id()); | |
44 return true; | |
45 default: | |
46 return false; | |
47 } | |
48 } | |
49 | |
50 bool CreatePrivateKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm, | |
51 SECKEYPrivateKey* key, | |
52 blink::WebCryptoKeyAlgorithm* key_algorithm) { | |
53 crypto::ScopedSECKEYPublicKey public_key(SECKEY_ConvertToPublicKey(key)); | |
54 return CreatePublicKeyAlgorithm(algorithm, public_key.get(), key_algorithm); | |
55 } | |
56 | |
57 #if defined(USE_NSS) && !defined(OS_CHROMEOS) | 24 #if defined(USE_NSS) && !defined(OS_CHROMEOS) |
58 Status ErrorRsaPrivateKeyImportNotSupported() { | 25 Status ErrorRsaPrivateKeyImportNotSupported() { |
59 return Status::ErrorUnsupported( | 26 return Status::ErrorUnsupported( |
60 "NSS version must be at least 3.16.2 for RSA private key import. See " | 27 "NSS version must be at least 3.16.2 for RSA private key import. See " |
61 "http://crbug.com/380424"); | 28 "http://crbug.com/380424"); |
62 } | 29 } |
63 | 30 |
64 // Prior to NSS 3.16.2 RSA key parameters were not validated. This is | 31 // Prior to NSS 3.16.2 RSA key parameters were not validated. This is |
65 // a security problem for RSA private key import from JWK which uses a | 32 // a security problem for RSA private key import from JWK which uses a |
66 // CKA_ID based on the public modulus to retrieve the private key. | 33 // CKA_ID based on the public modulus to retrieve the private key. |
(...skipping 21 matching lines...) Expand all Loading... |
88 | 55 |
89 return ErrorRsaPrivateKeyImportNotSupported(); | 56 return ErrorRsaPrivateKeyImportNotSupported(); |
90 } | 57 } |
91 #else | 58 #else |
92 Status NssSupportsRsaPrivateKeyImport() { | 59 Status NssSupportsRsaPrivateKeyImport() { |
93 return Status::Success(); | 60 return Status::Success(); |
94 } | 61 } |
95 #endif | 62 #endif |
96 | 63 |
97 bool CreateRsaHashedPublicKeyAlgorithm( | 64 bool CreateRsaHashedPublicKeyAlgorithm( |
98 const blink::WebCryptoAlgorithm& algorithm, | 65 blink::WebCryptoAlgorithmId rsa_algorithm, |
| 66 blink::WebCryptoAlgorithmId hash_algorithm, |
99 SECKEYPublicKey* key, | 67 SECKEYPublicKey* key, |
100 blink::WebCryptoKeyAlgorithm* key_algorithm) { | 68 blink::WebCryptoKeyAlgorithm* key_algorithm) { |
101 // TODO(eroman): What about other key types rsaPss, rsaOaep. | 69 // TODO(eroman): What about other key types rsaPss, rsaOaep. |
102 if (!key || key->keyType != rsaKey) | 70 if (!key || key->keyType != rsaKey) |
103 return false; | 71 return false; |
104 | 72 |
105 unsigned int modulus_length_bits = SECKEY_PublicKeyStrength(key) * 8; | 73 unsigned int modulus_length_bits = SECKEY_PublicKeyStrength(key) * 8; |
106 CryptoData public_exponent(key->u.rsa.publicExponent.data, | 74 CryptoData public_exponent(key->u.rsa.publicExponent.data, |
107 key->u.rsa.publicExponent.len); | 75 key->u.rsa.publicExponent.len); |
108 | 76 |
109 switch (algorithm.paramsType()) { | 77 *key_algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed( |
110 case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams: | 78 rsa_algorithm, |
111 case blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams: | 79 modulus_length_bits, |
112 *key_algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed( | 80 public_exponent.bytes(), |
113 algorithm.id(), | 81 public_exponent.byte_length(), |
114 modulus_length_bits, | 82 hash_algorithm); |
115 public_exponent.bytes(), | 83 return true; |
116 public_exponent.byte_length(), | |
117 GetInnerHashAlgorithm(algorithm).id()); | |
118 return true; | |
119 default: | |
120 return false; | |
121 } | |
122 } | 84 } |
123 | 85 |
124 bool CreateRsaHashedPrivateKeyAlgorithm( | 86 bool CreateRsaHashedPrivateKeyAlgorithm( |
125 const blink::WebCryptoAlgorithm& algorithm, | 87 blink::WebCryptoAlgorithmId rsa_algorithm, |
| 88 blink::WebCryptoAlgorithmId hash_algorithm, |
126 SECKEYPrivateKey* key, | 89 SECKEYPrivateKey* key, |
127 blink::WebCryptoKeyAlgorithm* key_algorithm) { | 90 blink::WebCryptoKeyAlgorithm* key_algorithm) { |
128 crypto::ScopedSECKEYPublicKey public_key(SECKEY_ConvertToPublicKey(key)); | 91 crypto::ScopedSECKEYPublicKey public_key(SECKEY_ConvertToPublicKey(key)); |
129 if (!public_key) | 92 if (!public_key) |
130 return false; | 93 return false; |
131 return CreateRsaHashedPublicKeyAlgorithm( | 94 return CreateRsaHashedPublicKeyAlgorithm( |
132 algorithm, public_key.get(), key_algorithm); | 95 rsa_algorithm, hash_algorithm, public_key.get(), key_algorithm); |
133 } | 96 } |
134 | 97 |
135 // From PKCS#1 [http://tools.ietf.org/html/rfc3447]: | 98 // From PKCS#1 [http://tools.ietf.org/html/rfc3447]: |
136 // | 99 // |
137 // RSAPrivateKey ::= SEQUENCE { | 100 // RSAPrivateKey ::= SEQUENCE { |
138 // version Version, | 101 // version Version, |
139 // modulus INTEGER, -- n | 102 // modulus INTEGER, -- n |
140 // publicExponent INTEGER, -- e | 103 // publicExponent INTEGER, -- e |
141 // privateExponent INTEGER, -- d | 104 // privateExponent INTEGER, -- d |
142 // prime1 INTEGER, -- p | 105 // prime1 INTEGER, -- p |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 | 381 |
419 // PK11_FindKeyByKeyID() may return a handle to an existing key, rather than | 382 // PK11_FindKeyByKeyID() may return a handle to an existing key, rather than |
420 // the object created by PK11_CreateGenericObject(). | 383 // the object created by PK11_CreateGenericObject(). |
421 crypto::ScopedSECKEYPrivateKey private_key( | 384 crypto::ScopedSECKEYPrivateKey private_key( |
422 SECKEY_CopyPrivateKey(private_key_tmp.get())); | 385 SECKEY_CopyPrivateKey(private_key_tmp.get())); |
423 | 386 |
424 if (!private_key) | 387 if (!private_key) |
425 return Status::OperationError(); | 388 return Status::OperationError(); |
426 | 389 |
427 blink::WebCryptoKeyAlgorithm key_algorithm; | 390 blink::WebCryptoKeyAlgorithm key_algorithm; |
428 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) | 391 if (!CreateRsaHashedPrivateKeyAlgorithm( |
| 392 algorithm.id(), |
| 393 algorithm.rsaHashedImportParams()->hash().id(), |
| 394 private_key.get(), |
| 395 &key_algorithm)) { |
429 return Status::ErrorUnexpected(); | 396 return Status::ErrorUnexpected(); |
| 397 } |
430 | 398 |
431 std::vector<uint8_t> pkcs8_data; | 399 std::vector<uint8_t> pkcs8_data; |
432 status = ExportKeyPkcs8Nss(private_key.get(), &pkcs8_data); | 400 status = ExportKeyPkcs8Nss(private_key.get(), &pkcs8_data); |
433 if (status.IsError()) | 401 if (status.IsError()) |
434 return status; | 402 return status; |
435 | 403 |
436 scoped_ptr<PrivateKeyNss> key_handle( | 404 scoped_ptr<PrivateKeyNss> key_handle( |
437 new PrivateKeyNss(private_key.Pass(), CryptoData(pkcs8_data))); | 405 new PrivateKeyNss(private_key.Pass(), CryptoData(pkcs8_data))); |
438 | 406 |
439 *key = blink::WebCryptoKey::create(key_handle.release(), | 407 *key = blink::WebCryptoKey::create(key_handle.release(), |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 if (!pubkey_der) | 472 if (!pubkey_der) |
505 return Status::OperationError(); | 473 return Status::OperationError(); |
506 | 474 |
507 // Import the DER-encoded public key to create an RSA SECKEYPublicKey. | 475 // Import the DER-encoded public key to create an RSA SECKEYPublicKey. |
508 crypto::ScopedSECKEYPublicKey pubkey( | 476 crypto::ScopedSECKEYPublicKey pubkey( |
509 SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA)); | 477 SECKEY_ImportDERPublicKey(pubkey_der.get(), CKK_RSA)); |
510 if (!pubkey) | 478 if (!pubkey) |
511 return Status::OperationError(); | 479 return Status::OperationError(); |
512 | 480 |
513 blink::WebCryptoKeyAlgorithm key_algorithm; | 481 blink::WebCryptoKeyAlgorithm key_algorithm; |
514 if (!CreatePublicKeyAlgorithm(algorithm, pubkey.get(), &key_algorithm)) | 482 if (!CreateRsaHashedPublicKeyAlgorithm( |
| 483 algorithm.id(), |
| 484 algorithm.rsaHashedImportParams()->hash().id(), |
| 485 pubkey.get(), |
| 486 &key_algorithm)) { |
515 return Status::ErrorUnexpected(); | 487 return Status::ErrorUnexpected(); |
| 488 } |
516 | 489 |
517 std::vector<uint8_t> spki_data; | 490 std::vector<uint8_t> spki_data; |
518 Status status = ExportKeySpkiNss(pubkey.get(), &spki_data); | 491 Status status = ExportKeySpkiNss(pubkey.get(), &spki_data); |
519 if (status.IsError()) | 492 if (status.IsError()) |
520 return status; | 493 return status; |
521 | 494 |
522 scoped_ptr<PublicKeyNss> key_handle( | 495 scoped_ptr<PublicKeyNss> key_handle( |
523 new PublicKeyNss(pubkey.Pass(), CryptoData(spki_data))); | 496 new PublicKeyNss(pubkey.Pass(), CryptoData(spki_data))); |
524 | 497 |
525 *key = blink::WebCryptoKey::create(key_handle.release(), | 498 *key = blink::WebCryptoKey::create(key_handle.release(), |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 &rsa_gen_params, | 560 &rsa_gen_params, |
588 &sec_public_key, | 561 &sec_public_key, |
589 attribute_flags, | 562 attribute_flags, |
590 generate_flags_, | 563 generate_flags_, |
591 operation_flags_mask, | 564 operation_flags_mask, |
592 NULL)); | 565 NULL)); |
593 if (!scoped_sec_private_key) | 566 if (!scoped_sec_private_key) |
594 return Status::OperationError(); | 567 return Status::OperationError(); |
595 | 568 |
596 blink::WebCryptoKeyAlgorithm key_algorithm; | 569 blink::WebCryptoKeyAlgorithm key_algorithm; |
597 if (!CreatePublicKeyAlgorithm(algorithm, sec_public_key, &key_algorithm)) | 570 if (!CreateRsaHashedPublicKeyAlgorithm( |
| 571 algorithm.id(), |
| 572 algorithm.rsaHashedKeyGenParams()->hash().id(), |
| 573 sec_public_key, |
| 574 &key_algorithm)) { |
598 return Status::ErrorUnexpected(); | 575 return Status::ErrorUnexpected(); |
| 576 } |
599 | 577 |
600 std::vector<uint8_t> spki_data; | 578 std::vector<uint8_t> spki_data; |
601 status = ExportKeySpkiNss(sec_public_key, &spki_data); | 579 status = ExportKeySpkiNss(sec_public_key, &spki_data); |
602 if (status.IsError()) | 580 if (status.IsError()) |
603 return status; | 581 return status; |
604 | 582 |
605 scoped_ptr<PublicKeyNss> public_key_handle(new PublicKeyNss( | 583 scoped_ptr<PublicKeyNss> public_key_handle(new PublicKeyNss( |
606 crypto::ScopedSECKEYPublicKey(sec_public_key), CryptoData(spki_data))); | 584 crypto::ScopedSECKEYPublicKey(sec_public_key), CryptoData(spki_data))); |
607 | 585 |
608 std::vector<uint8_t> pkcs8_data; | 586 std::vector<uint8_t> pkcs8_data; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 } | 653 } |
676 DCHECK(seckey_private_key); | 654 DCHECK(seckey_private_key); |
677 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); | 655 crypto::ScopedSECKEYPrivateKey private_key(seckey_private_key); |
678 | 656 |
679 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); | 657 const KeyType sec_key_type = SECKEY_GetPrivateKeyType(private_key.get()); |
680 if (sec_key_type != rsaKey) | 658 if (sec_key_type != rsaKey) |
681 return Status::DataError(); | 659 return Status::DataError(); |
682 | 660 |
683 blink::WebCryptoKeyAlgorithm key_algorithm; | 661 blink::WebCryptoKeyAlgorithm key_algorithm; |
684 if (!CreateRsaHashedPrivateKeyAlgorithm( | 662 if (!CreateRsaHashedPrivateKeyAlgorithm( |
685 algorithm, private_key.get(), &key_algorithm)) | 663 algorithm.id(), |
| 664 algorithm.rsaHashedImportParams()->hash().id(), |
| 665 private_key.get(), |
| 666 &key_algorithm)) { |
686 return Status::ErrorUnexpected(); | 667 return Status::ErrorUnexpected(); |
| 668 } |
687 | 669 |
688 // TODO(eroman): This is probably going to be the same as the input. | 670 // TODO(eroman): This is probably going to be the same as the input. |
689 std::vector<uint8_t> pkcs8_data; | 671 std::vector<uint8_t> pkcs8_data; |
690 status = ExportKeyPkcs8Nss(private_key.get(), &pkcs8_data); | 672 status = ExportKeyPkcs8Nss(private_key.get(), &pkcs8_data); |
691 if (status.IsError()) | 673 if (status.IsError()) |
692 return status; | 674 return status; |
693 | 675 |
694 scoped_ptr<PrivateKeyNss> key_handle( | 676 scoped_ptr<PrivateKeyNss> key_handle( |
695 new PrivateKeyNss(private_key.Pass(), CryptoData(pkcs8_data))); | 677 new PrivateKeyNss(private_key.Pass(), CryptoData(pkcs8_data))); |
696 | 678 |
(...skipping 27 matching lines...) Expand all Loading... |
724 SECKEY_ExtractPublicKey(spki.get())); | 706 SECKEY_ExtractPublicKey(spki.get())); |
725 if (!sec_public_key) | 707 if (!sec_public_key) |
726 return Status::DataError(); | 708 return Status::DataError(); |
727 | 709 |
728 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); | 710 const KeyType sec_key_type = SECKEY_GetPublicKeyType(sec_public_key.get()); |
729 if (sec_key_type != rsaKey) | 711 if (sec_key_type != rsaKey) |
730 return Status::DataError(); | 712 return Status::DataError(); |
731 | 713 |
732 blink::WebCryptoKeyAlgorithm key_algorithm; | 714 blink::WebCryptoKeyAlgorithm key_algorithm; |
733 if (!CreateRsaHashedPublicKeyAlgorithm( | 715 if (!CreateRsaHashedPublicKeyAlgorithm( |
734 algorithm, sec_public_key.get(), &key_algorithm)) | 716 algorithm.id(), |
| 717 algorithm.rsaHashedImportParams()->hash().id(), |
| 718 sec_public_key.get(), |
| 719 &key_algorithm)) { |
735 return Status::ErrorUnexpected(); | 720 return Status::ErrorUnexpected(); |
| 721 } |
736 | 722 |
737 // TODO(eroman): This is probably going to be the same as the input. | 723 // TODO(eroman): This is probably going to be the same as the input. |
738 std::vector<uint8_t> spki_data; | 724 std::vector<uint8_t> spki_data; |
739 Status status = ExportKeySpkiNss(sec_public_key.get(), &spki_data); | 725 Status status = ExportKeySpkiNss(sec_public_key.get(), &spki_data); |
740 if (status.IsError()) | 726 if (status.IsError()) |
741 return status; | 727 return status; |
742 | 728 |
743 scoped_ptr<PublicKeyNss> key_handle( | 729 scoped_ptr<PublicKeyNss> key_handle( |
744 new PublicKeyNss(sec_public_key.Pass(), CryptoData(spki_data))); | 730 new PublicKeyNss(sec_public_key.Pass(), CryptoData(spki_data))); |
745 | 731 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
851 return Status::Success(); | 837 return Status::Success(); |
852 } | 838 } |
853 default: | 839 default: |
854 return Status::ErrorUnexpected(); | 840 return Status::ErrorUnexpected(); |
855 } | 841 } |
856 } | 842 } |
857 | 843 |
858 } // namespace webcrypto | 844 } // namespace webcrypto |
859 | 845 |
860 } // namespace content | 846 } // namespace content |
OLD | NEW |