Chromium Code Reviews| 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, |
|
Ryan Sleevi
2014/08/27 17:14:09
Is the assumption that |rsa_algorithm| holds label
eroman
2014/08/27 17:27:38
The containing function (CreateRsaHashedPublicKeyA
| |
| 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 |