Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/renderer/webcrypto/webcrypto_impl.h" | 5 #include "content/renderer/webcrypto/webcrypto_impl.h" |
| 6 | 6 |
| 7 #include <cryptohi.h> | 7 #include <cryptohi.h> |
| 8 #include <pk11pub.h> | 8 #include <pk11pub.h> |
| 9 #include <sechash.h> | 9 #include <sechash.h> |
| 10 | 10 |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 231 size_t reverse_i = data_size - i - 1; | 231 size_t reverse_i = data_size - i - 1; |
| 232 | 232 |
| 233 if (reverse_i >= sizeof(unsigned long) && data[i]) | 233 if (reverse_i >= sizeof(unsigned long) && data[i]) |
| 234 return false; // Too large for a long. | 234 return false; // Too large for a long. |
| 235 | 235 |
| 236 *result |= data[i] << 8 * reverse_i; | 236 *result |= data[i] << 8 * reverse_i; |
| 237 } | 237 } |
| 238 return true; | 238 return true; |
| 239 } | 239 } |
| 240 | 240 |
| 241 // TODO(padolph): Move to webcrypto_util | |
| 242 blink::WebCryptoAlgorithm GetInnerHashAlgorithm( | |
| 243 const blink::WebCryptoAlgorithm& algorithm) { | |
| 244 DCHECK(!algorithm.isNull()); | |
| 245 switch (algorithm.id()) { | |
| 246 case blink::WebCryptoAlgorithmIdHmac: | |
| 247 if (algorithm.hmacParams()) | |
| 248 return algorithm.hmacParams()->hash(); | |
| 249 else if (algorithm.hmacKeyParams()) | |
| 250 return algorithm.hmacKeyParams()->hash(); | |
| 251 break; | |
| 252 case blink::WebCryptoAlgorithmIdRsaOaep: | |
| 253 if (algorithm.rsaOaepParams()) | |
| 254 return algorithm.rsaOaepParams()->hash(); | |
| 255 break; | |
| 256 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: | |
| 257 if (algorithm.rsaSsaParams()) | |
| 258 return algorithm.rsaSsaParams()->hash(); | |
| 259 break; | |
| 260 default: | |
| 261 break; | |
| 262 } | |
| 263 return blink::WebCryptoAlgorithm::createNull(); | |
| 264 } | |
| 265 | |
| 241 } // namespace | 266 } // namespace |
| 242 | 267 |
| 243 void WebCryptoImpl::Init() { | 268 void WebCryptoImpl::Init() { |
| 244 crypto::EnsureNSSInit(); | 269 crypto::EnsureNSSInit(); |
| 245 } | 270 } |
| 246 | 271 |
| 247 bool WebCryptoImpl::EncryptInternal( | 272 bool WebCryptoImpl::EncryptInternal( |
| 248 const blink::WebCryptoAlgorithm& algorithm, | 273 const blink::WebCryptoAlgorithm& algorithm, |
| 249 const blink::WebCryptoKey& key, | 274 const blink::WebCryptoKey& key, |
| 250 const unsigned char* data, | 275 const unsigned char* data, |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 550 type, extractable, algorithm, usage_mask); | 575 type, extractable, algorithm, usage_mask); |
| 551 return true; | 576 return true; |
| 552 } | 577 } |
| 553 | 578 |
| 554 bool WebCryptoImpl::SignInternal( | 579 bool WebCryptoImpl::SignInternal( |
| 555 const blink::WebCryptoAlgorithm& algorithm, | 580 const blink::WebCryptoAlgorithm& algorithm, |
| 556 const blink::WebCryptoKey& key, | 581 const blink::WebCryptoKey& key, |
| 557 const unsigned char* data, | 582 const unsigned char* data, |
| 558 unsigned data_size, | 583 unsigned data_size, |
| 559 blink::WebArrayBuffer* buffer) { | 584 blink::WebArrayBuffer* buffer) { |
| 585 | |
| 586 // Note: It is not an error to sign empty data. | |
| 587 | |
| 588 DCHECK(buffer); | |
| 589 DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign); | |
| 590 | |
| 560 blink::WebArrayBuffer result; | 591 blink::WebArrayBuffer result; |
| 561 | 592 |
| 562 switch (algorithm.id()) { | 593 switch (algorithm.id()) { |
| 563 case blink::WebCryptoAlgorithmIdHmac: { | 594 case blink::WebCryptoAlgorithmIdHmac: { |
| 564 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); | 595 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); |
| 565 if (!params) { | 596 if (!params) { |
| 566 return false; | 597 return false; |
| 567 } | 598 } |
| 568 | 599 |
| 569 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); | 600 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); |
| 570 | 601 |
| 571 DCHECK_EQ(PK11_GetMechanism(sym_key->key()), | 602 DCHECK_EQ(PK11_GetMechanism(sym_key->key()), |
| 572 WebCryptoAlgorithmToHMACMechanism(params->hash())); | 603 WebCryptoAlgorithmToHMACMechanism(params->hash())); |
| 573 DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign); | |
| 574 | 604 |
| 575 SECItem param_item = { siBuffer, NULL, 0 }; | 605 SECItem param_item = { siBuffer, NULL, 0 }; |
| 576 SECItem data_item = { | 606 SECItem data_item = { |
| 577 siBuffer, | 607 siBuffer, |
| 578 const_cast<unsigned char*>(data), | 608 const_cast<unsigned char*>(data), |
| 579 data_size | 609 data_size |
| 580 }; | 610 }; |
| 581 // First call is to figure out the length. | 611 // First call is to figure out the length. |
| 582 SECItem signature_item = { siBuffer, NULL, 0 }; | 612 SECItem signature_item = { siBuffer, NULL, 0 }; |
| 583 | 613 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 601 &signature_item, | 631 &signature_item, |
| 602 &data_item) != SECSuccess) { | 632 &data_item) != SECSuccess) { |
| 603 NOTREACHED(); | 633 NOTREACHED(); |
| 604 return false; | 634 return false; |
| 605 } | 635 } |
| 606 | 636 |
| 607 DCHECK_EQ(result.byteLength(), signature_item.len); | 637 DCHECK_EQ(result.byteLength(), signature_item.len); |
| 608 | 638 |
| 609 break; | 639 break; |
| 610 } | 640 } |
| 641 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: { | |
| 642 // Only private key signing is supported. | |
| 643 if (key.type() != blink::WebCryptoKeyTypePrivate) | |
| 644 return false; | |
| 645 | |
| 646 const blink::WebCryptoAlgorithm hash_algorithm = | |
| 647 GetInnerHashAlgorithm(algorithm); | |
| 648 if (hash_algorithm.isNull()) // TODO(padolph): DCHECK instead? | |
| 649 return false; | |
| 650 blink::WebArrayBuffer digest; | |
| 651 if (!DigestInternal(hash_algorithm, data, data_size, &digest)) | |
|
Ryan Sleevi
2013/11/21 01:45:57
I'm not sure this is the right approach.
Why not
padolph
2013/11/28 02:29:09
Done. Rewrote to use SEC_SignData (a sequence of S
| |
| 652 return false; | |
| 653 const SECItem digest_item = { | |
| 654 siBuffer, | |
| 655 reinterpret_cast<unsigned char*>(digest.data()), | |
| 656 digest.byteLength() | |
| 657 }; | |
| 658 | |
| 659 PrivateKeyHandle* const private_key = | |
| 660 reinterpret_cast<PrivateKeyHandle*>(key.handle()); | |
| 661 DCHECK(private_key); | |
| 662 DCHECK(private_key->key()); | |
| 663 const int signature_length = PK11_SignatureLen(private_key->key()); | |
| 664 if (signature_length <= 0) | |
| 665 return false; | |
| 666 result = blink::WebArrayBuffer::create(signature_length, 1); | |
| 667 SECItem signature_item = { | |
| 668 siBuffer, | |
| 669 reinterpret_cast<unsigned char*>(result.data()), | |
| 670 signature_length | |
| 671 }; | |
| 672 if (PK11_Sign(private_key->key(), | |
| 673 &signature_item, | |
| 674 &digest_item) != SECSuccess ) { | |
| 675 return false; | |
| 676 } | |
| 677 DCHECK_EQ(result.byteLength(), signature_item.len); | |
| 678 | |
| 679 break; | |
| 680 } | |
| 611 default: | 681 default: |
| 612 return false; | 682 return false; |
| 613 } | 683 } |
| 614 | 684 |
| 615 *buffer = result; | 685 *buffer = result; |
| 616 return true; | 686 return true; |
| 617 } | 687 } |
| 618 | 688 |
| 619 bool WebCryptoImpl::VerifySignatureInternal( | 689 bool WebCryptoImpl::VerifySignatureInternal( |
| 620 const blink::WebCryptoAlgorithm& algorithm, | 690 const blink::WebCryptoAlgorithm& algorithm, |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 634 // Handling of truncated signatures is underspecified in the WebCrypto | 704 // Handling of truncated signatures is underspecified in the WebCrypto |
| 635 // spec, so here we fail verification if a truncated signature is being | 705 // spec, so here we fail verification if a truncated signature is being |
| 636 // verified. | 706 // verified. |
| 637 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 | 707 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 |
| 638 *signature_match = | 708 *signature_match = |
| 639 result.byteLength() == signature_size && | 709 result.byteLength() == signature_size && |
| 640 crypto::SecureMemEqual(result.data(), signature, signature_size); | 710 crypto::SecureMemEqual(result.data(), signature, signature_size); |
| 641 | 711 |
| 642 break; | 712 break; |
| 643 } | 713 } |
| 714 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: { | |
| 715 // Only public key signature verification is supported. | |
| 716 if (key.type() != blink::WebCryptoKeyTypePublic) | |
| 717 return false; | |
| 718 | |
| 719 const blink::WebCryptoAlgorithm hash_algorithm = | |
| 720 GetInnerHashAlgorithm(algorithm); | |
| 721 if (hash_algorithm.isNull()) // TODO(padolph): DCHECK instead? | |
| 722 return false; | |
| 723 blink::WebArrayBuffer digest; | |
| 724 if (!DigestInternal(hash_algorithm, data, data_size, &digest)) | |
| 725 return false; | |
| 726 const SECItem digest_item = { | |
| 727 siBuffer, | |
| 728 reinterpret_cast<unsigned char*>(digest.data()), | |
| 729 digest.byteLength() | |
| 730 }; | |
| 731 | |
| 732 PublicKeyHandle* const public_key = | |
| 733 reinterpret_cast<PublicKeyHandle*>(key.handle()); | |
| 734 DCHECK(public_key); | |
| 735 DCHECK(public_key->key()); | |
| 736 const SECItem signature_item = { | |
| 737 siBuffer, | |
| 738 const_cast<unsigned char*>(signature), | |
| 739 signature_size | |
| 740 }; | |
| 741 *signature_match = PK11_Verify(public_key->key(), | |
| 742 &signature_item, | |
| 743 &digest_item, | |
| 744 NULL) == SECSuccess; | |
| 745 | |
| 746 break; | |
| 747 } | |
| 644 default: | 748 default: |
| 645 return false; | 749 return false; |
| 646 } | 750 } |
| 647 | 751 |
| 648 return true; | 752 return true; |
| 649 } | 753 } |
| 650 | 754 |
| 651 } // namespace content | 755 } // namespace content |
| OLD | NEW |