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

Side by Side Diff: content/renderer/webcrypto/webcrypto_impl_nss.cc

Issue 68303009: [webcrypto] Add RSASSA-PKCS1-v1_5 sign and verify for NSS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fixes for eroman Created 7 years, 1 month 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
« no previous file with comments | « no previous file | content/renderer/webcrypto/webcrypto_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | content/renderer/webcrypto/webcrypto_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698