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

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

Issue 335463002: [webcrypto] Remove a special case for AES-KW wrapping/unwrapping. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Try to placate a compiler warning Created 6 years, 6 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 | Annotate | Revision Log
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 "content/child/webcrypto/platform_crypto.h" 5 #include "content/child/webcrypto/platform_crypto.h"
6 6
7 #include <cryptohi.h> 7 #include <cryptohi.h>
8 #include <pk11pub.h> 8 #include <pk11pub.h>
9 #include <secerr.h> 9 #include <secerr.h>
10 #include <sechash.h> 10 #include <sechash.h>
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 CK_FLAGS* flags) { 577 CK_FLAGS* flags) {
578 // Flags are verified at the Blink layer; here the flags are set to all 578 // Flags are verified at the Blink layer; here the flags are set to all
579 // possible operations of a key for the input algorithm type. 579 // possible operations of a key for the input algorithm type.
580 switch (algorithm.id()) { 580 switch (algorithm.id()) {
581 case blink::WebCryptoAlgorithmIdHmac: { 581 case blink::WebCryptoAlgorithmIdHmac: {
582 const blink::WebCryptoAlgorithm hash = GetInnerHashAlgorithm(algorithm); 582 const blink::WebCryptoAlgorithm hash = GetInnerHashAlgorithm(algorithm);
583 *mechanism = WebCryptoHashToHMACMechanism(hash); 583 *mechanism = WebCryptoHashToHMACMechanism(hash);
584 if (*mechanism == CKM_INVALID_MECHANISM) 584 if (*mechanism == CKM_INVALID_MECHANISM)
585 return Status::ErrorUnsupported(); 585 return Status::ErrorUnsupported();
586 *flags = CKF_SIGN | CKF_VERIFY; 586 *flags = CKF_SIGN | CKF_VERIFY;
587 break; 587 return Status::Success();
588 } 588 }
589 case blink::WebCryptoAlgorithmIdAesCbc: { 589 case blink::WebCryptoAlgorithmIdAesCbc: {
590 *mechanism = CKM_AES_CBC; 590 *mechanism = CKM_AES_CBC;
591 *flags = CKF_ENCRYPT | CKF_DECRYPT; 591 *flags = CKF_ENCRYPT | CKF_DECRYPT;
592 break; 592 return Status::Success();
593 } 593 }
594 case blink::WebCryptoAlgorithmIdAesKw: { 594 case blink::WebCryptoAlgorithmIdAesKw: {
595 *mechanism = CKM_NSS_AES_KEY_WRAP; 595 *mechanism = CKM_NSS_AES_KEY_WRAP;
596 *flags = CKF_WRAP | CKF_WRAP; 596 *flags = CKF_WRAP | CKF_WRAP;
597 break; 597 return Status::Success();
598 } 598 }
599 case blink::WebCryptoAlgorithmIdAesGcm: { 599 case blink::WebCryptoAlgorithmIdAesGcm: {
600 if (!g_nss_runtime_support.Get().IsAesGcmSupported()) 600 if (!g_nss_runtime_support.Get().IsAesGcmSupported())
601 return Status::ErrorUnsupported(); 601 return Status::ErrorUnsupported();
602 *mechanism = CKM_AES_GCM; 602 *mechanism = CKM_AES_GCM;
603 *flags = CKF_ENCRYPT | CKF_DECRYPT; 603 *flags = CKF_ENCRYPT | CKF_DECRYPT;
604 break; 604 return Status::Success();
605 } 605 }
606 default: 606 default:
607 return Status::ErrorUnsupported(); 607 return Status::ErrorUnsupported();
608 } 608 }
609 return Status::Success();
610 } 609 }
611 610
612 Status DoUnwrapSymKeyAesKw(const CryptoData& wrapped_key_data, 611 Status DoUnwrapSymKeyAesKw(const CryptoData& wrapped_key_data,
613 SymKey* wrapping_key, 612 SymKey* wrapping_key,
614 CK_MECHANISM_TYPE mechanism, 613 CK_MECHANISM_TYPE mechanism,
615 CK_FLAGS flags, 614 CK_FLAGS flags,
616 crypto::ScopedPK11SymKey* unwrapped_key) { 615 crypto::ScopedPK11SymKey* unwrapped_key) {
617 DCHECK_GE(wrapped_key_data.byte_length(), 24u); 616 DCHECK_GE(wrapped_key_data.byte_length(), 24u);
618 DCHECK_EQ(wrapped_key_data.byte_length() % 8, 0u); 617 DCHECK_EQ(wrapped_key_data.byte_length() % 8, 0u);
619 618
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
876 unsigned char result_[HASH_LENGTH_MAX]; 875 unsigned char result_[HASH_LENGTH_MAX];
877 }; 876 };
878 877
879 Status ImportKeyRaw(const blink::WebCryptoAlgorithm& algorithm, 878 Status ImportKeyRaw(const blink::WebCryptoAlgorithm& algorithm,
880 const CryptoData& key_data, 879 const CryptoData& key_data,
881 bool extractable, 880 bool extractable,
882 blink::WebCryptoKeyUsageMask usage_mask, 881 blink::WebCryptoKeyUsageMask usage_mask,
883 blink::WebCryptoKey* key) { 882 blink::WebCryptoKey* key) {
884 DCHECK(!algorithm.isNull()); 883 DCHECK(!algorithm.isNull());
885 884
886 CK_MECHANISM_TYPE mechanism; 885 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
887 CK_FLAGS flags; 886 CK_FLAGS flags = 0;
888 Status status = 887 Status status =
889 WebCryptoAlgorithmToNssMechFlags(algorithm, &mechanism, &flags); 888 WebCryptoAlgorithmToNssMechFlags(algorithm, &mechanism, &flags);
890 if (status.IsError()) 889 if (status.IsError())
891 return status; 890 return status;
892 891
893 SECItem key_item = MakeSECItemForBuffer(key_data); 892 SECItem key_item = MakeSECItemForBuffer(key_data);
894 893
895 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); 894 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
896 crypto::ScopedPK11SymKey pk11_sym_key( 895 crypto::ScopedPK11SymKey pk11_sym_key(
897 PK11_ImportSymKeyWithFlags(slot.get(), 896 PK11_ImportSymKeyWithFlags(slot.get(),
(...skipping 859 matching lines...) Expand 10 before | Expand all | Expand 10 after
1757 return status; 1756 return status;
1758 1757
1759 *key = blink::WebCryptoKey::create(key_handle.release(), 1758 *key = blink::WebCryptoKey::create(key_handle.release(),
1760 blink::WebCryptoKeyTypePrivate, 1759 blink::WebCryptoKeyTypePrivate,
1761 extractable, 1760 extractable,
1762 key_algorithm, 1761 key_algorithm,
1763 usage_mask); 1762 usage_mask);
1764 return Status::Success(); 1763 return Status::Success();
1765 } 1764 }
1766 1765
1767 Status WrapSymKeyAesKw(SymKey* key, 1766 Status WrapSymKeyAesKw(PK11SymKey* key,
1768 SymKey* wrapping_key, 1767 SymKey* wrapping_key,
1769 std::vector<uint8>* buffer) { 1768 std::vector<uint8>* buffer) {
1770 // The data size must be at least 16 bytes and a multiple of 8 bytes. 1769 // The data size must be at least 16 bytes and a multiple of 8 bytes.
1771 // RFC 3394 does not specify a maximum allowed data length, but since only 1770 // RFC 3394 does not specify a maximum allowed data length, but since only
1772 // keys are being wrapped in this application (which are small), a reasonable 1771 // keys are being wrapped in this application (which are small), a reasonable
1773 // max limit is whatever will fit into an unsigned. For the max size test, 1772 // max limit is whatever will fit into an unsigned. For the max size test,
1774 // note that AES Key Wrap always adds 8 bytes to the input data size. 1773 // note that AES Key Wrap always adds 8 bytes to the input data size.
1775 const unsigned int input_length = PK11_GetKeyLength(key->key()); 1774 const unsigned int input_length = PK11_GetKeyLength(key);
1776 if (input_length < 16) 1775 DCHECK_GE(input_length, 16u);
1777 return Status::ErrorDataTooSmall(); 1776 DCHECK((input_length % 8) == 0);
1778 if (input_length > UINT_MAX - 8) 1777 if (input_length > UINT_MAX - 8)
1779 return Status::ErrorDataTooLarge(); 1778 return Status::ErrorDataTooLarge();
1780 if (input_length % 8)
1781 return Status::ErrorInvalidAesKwDataLength();
1782 1779
1783 SECItem iv_item = MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv))); 1780 SECItem iv_item = MakeSECItemForBuffer(CryptoData(kAesIv, sizeof(kAesIv)));
1784 crypto::ScopedSECItem param_item( 1781 crypto::ScopedSECItem param_item(
1785 PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item)); 1782 PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP, &iv_item));
1786 if (!param_item) 1783 if (!param_item)
1787 return Status::ErrorUnexpected(); 1784 return Status::ErrorUnexpected();
1788 1785
1789 const unsigned int output_length = input_length + 8; 1786 const unsigned int output_length = input_length + 8;
1790 buffer->resize(output_length); 1787 buffer->resize(output_length);
1791 SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer)); 1788 SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(*buffer));
1792 1789
1793 if (SECSuccess != PK11_WrapSymKey(CKM_NSS_AES_KEY_WRAP, 1790 if (SECSuccess != PK11_WrapSymKey(CKM_NSS_AES_KEY_WRAP,
1794 param_item.get(), 1791 param_item.get(),
1795 wrapping_key->key(), 1792 wrapping_key->key(),
1796 key->key(), 1793 key,
1797 &wrapped_key_item)) { 1794 &wrapped_key_item)) {
1798 return Status::OperationError(); 1795 return Status::OperationError();
1799 } 1796 }
1800 if (output_length != wrapped_key_item.len) 1797 if (output_length != wrapped_key_item.len)
1801 return Status::ErrorUnexpected(); 1798 return Status::ErrorUnexpected();
1802 1799
1803 return Status::Success(); 1800 return Status::Success();
1804 } 1801 }
1805 1802
1806 Status UnwrapSymKeyAesKw(const CryptoData& wrapped_key_data,
1807 SymKey* wrapping_key,
1808 const blink::WebCryptoAlgorithm& algorithm,
1809 bool extractable,
1810 blink::WebCryptoKeyUsageMask usage_mask,
1811 blink::WebCryptoKey* key) {
1812 // Determine the proper NSS key properties from the input algorithm.
1813 CK_MECHANISM_TYPE mechanism;
1814 CK_FLAGS flags;
1815 Status status =
1816 WebCryptoAlgorithmToNssMechFlags(algorithm, &mechanism, &flags);
1817 if (status.IsError())
1818 return status;
1819
1820 crypto::ScopedPK11SymKey unwrapped_key;
1821 status = DoUnwrapSymKeyAesKw(
1822 wrapped_key_data, wrapping_key, mechanism, flags, &unwrapped_key);
1823 if (status.IsError())
1824 return status;
1825
1826 blink::WebCryptoKeyAlgorithm key_algorithm;
1827 if (!CreateSecretKeyAlgorithm(
1828 algorithm, PK11_GetKeyLength(unwrapped_key.get()), &key_algorithm))
1829 return Status::ErrorUnexpected();
1830
1831 scoped_ptr<SymKey> key_handle;
1832 status = SymKey::Create(unwrapped_key.Pass(), &key_handle);
1833 if (status.IsError())
1834 return status;
1835
1836 *key = blink::WebCryptoKey::create(key_handle.release(),
1837 blink::WebCryptoKeyTypeSecret,
1838 extractable,
1839 key_algorithm,
1840 usage_mask);
1841 return Status::Success();
1842 }
1843
1844 Status DecryptAesKw(SymKey* wrapping_key, 1803 Status DecryptAesKw(SymKey* wrapping_key,
1845 const CryptoData& data, 1804 const CryptoData& data,
1846 std::vector<uint8>* buffer) { 1805 std::vector<uint8>* buffer) {
1847 // Due to limitations in the NSS API for the AES-KW algorithm, |data| must be 1806 // Due to limitations in the NSS API for the AES-KW algorithm, |data| must be
1848 // temporarily viewed as a symmetric key to be unwrapped (decrypted). 1807 // temporarily viewed as a symmetric key to be unwrapped (decrypted).
1849 crypto::ScopedPK11SymKey decrypted; 1808 crypto::ScopedPK11SymKey decrypted;
1850 Status status = DoUnwrapSymKeyAesKw( 1809 Status status = DoUnwrapSymKeyAesKw(
1851 data, wrapping_key, CKK_GENERIC_SECRET, 0, &decrypted); 1810 data, wrapping_key, CKK_GENERIC_SECRET, 0, &decrypted);
1852 if (status.IsError()) 1811 if (status.IsError())
1853 return status; 1812 return status;
1854 1813
1855 // Once the decrypt is complete, extract the resultant raw bytes from NSS and 1814 // Once the decrypt is complete, extract the resultant raw bytes from NSS and
1856 // return them to the caller. 1815 // return them to the caller.
1857 if (PK11_ExtractKeyValue(decrypted.get()) != SECSuccess) 1816 if (PK11_ExtractKeyValue(decrypted.get()) != SECSuccess)
1858 return Status::OperationError(); 1817 return Status::OperationError();
1859 const SECItem* const key_data = PK11_GetKeyData(decrypted.get()); 1818 const SECItem* const key_data = PK11_GetKeyData(decrypted.get());
1860 if (!key_data) 1819 if (!key_data)
1861 return Status::OperationError(); 1820 return Status::OperationError();
1862 buffer->assign(key_data->data, key_data->data + key_data->len); 1821 buffer->assign(key_data->data, key_data->data + key_data->len);
1863 1822
1864 return Status::Success(); 1823 return Status::Success();
1865 } 1824 }
1866 1825
1826 Status EncryptAesKw(SymKey* wrapping_key,
1827 const CryptoData& data,
1828 std::vector<uint8>* buffer) {
1829 // Due to limitations in the NSS API for the AES-KW algorithm, |data| must be
1830 // temporarily viewed as a symmetric key to be wrapped (encrypted).
1831 SECItem data_item = MakeSECItemForBuffer(data);
1832 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
1833 crypto::ScopedPK11SymKey data_as_sym_key(PK11_ImportSymKey(slot.get(),
1834 CKK_GENERIC_SECRET,
1835 PK11_OriginUnwrap,
1836 CKA_SIGN,
1837 &data_item,
1838 NULL));
1839 if (!data_as_sym_key)
1840 return Status::OperationError();
1841
1842 return WrapSymKeyAesKw(data_as_sym_key.get(), wrapping_key, buffer);
1843 }
1844
1845 Status EncryptDecryptAesKw(EncryptOrDecrypt mode,
1846 SymKey* wrapping_key,
1847 const CryptoData& data,
1848 std::vector<uint8>* buffer) {
1849 return mode == ENCRYPT ? EncryptAesKw(wrapping_key, data, buffer)
1850 : DecryptAesKw(wrapping_key, data, buffer);
1851 }
1852
1867 } // namespace platform 1853 } // namespace platform
1868 1854
1869 } // namespace webcrypto 1855 } // namespace webcrypto
1870 1856
1871 } // namespace content 1857 } // namespace content
OLDNEW
« no previous file with comments | « content/child/webcrypto/platform_crypto.h ('k') | content/child/webcrypto/platform_crypto_openssl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698