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

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

Issue 308523003: [webcrypto] Fix a bug with JWK private key import. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address sleevi comments 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
« no previous file with comments | « no previous file | content/child/webcrypto/shared_crypto_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 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>
11 11
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/lazy_instance.h" 14 #include "base/lazy_instance.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/scoped_ptr.h"
17 #include "content/child/webcrypto/crypto_data.h" 17 #include "content/child/webcrypto/crypto_data.h"
18 #include "content/child/webcrypto/status.h" 18 #include "content/child/webcrypto/status.h"
19 #include "content/child/webcrypto/webcrypto_util.h" 19 #include "content/child/webcrypto/webcrypto_util.h"
20 #include "crypto/nss_util.h" 20 #include "crypto/nss_util.h"
21 #include "crypto/random.h"
21 #include "crypto/scoped_nss_types.h" 22 #include "crypto/scoped_nss_types.h"
22 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" 23 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
23 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" 24 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
24 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" 25 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
25 26
26 #if defined(USE_NSS) 27 #if defined(USE_NSS)
27 #include <dlfcn.h> 28 #include <dlfcn.h>
28 #include <secoid.h> 29 #include <secoid.h>
29 #endif 30 #endif
30 31
(...skipping 1679 matching lines...) Expand 10 before | Expand all | Expand 10 after
1710 AddAttribute(CKA_KEY_TYPE, &key_type, sizeof(key_type), &key_template); 1711 AddAttribute(CKA_KEY_TYPE, &key_type, sizeof(key_type), &key_template);
1711 AddAttribute(CKA_TOKEN, &ck_false, sizeof(ck_false), &key_template); 1712 AddAttribute(CKA_TOKEN, &ck_false, sizeof(ck_false), &key_template);
1712 AddAttribute(CKA_SENSITIVE, &ck_false, sizeof(ck_false), &key_template); 1713 AddAttribute(CKA_SENSITIVE, &ck_false, sizeof(ck_false), &key_template);
1713 AddAttribute(CKA_PRIVATE, &ck_false, sizeof(ck_false), &key_template); 1714 AddAttribute(CKA_PRIVATE, &ck_false, sizeof(ck_false), &key_template);
1714 1715
1715 // Required properties. 1716 // Required properties.
1716 AddOptionalAttribute(CKA_MODULUS, modulus, &key_template); 1717 AddOptionalAttribute(CKA_MODULUS, modulus, &key_template);
1717 AddOptionalAttribute(CKA_PUBLIC_EXPONENT, public_exponent, &key_template); 1718 AddOptionalAttribute(CKA_PUBLIC_EXPONENT, public_exponent, &key_template);
1718 AddOptionalAttribute(CKA_PRIVATE_EXPONENT, private_exponent, &key_template); 1719 AddOptionalAttribute(CKA_PRIVATE_EXPONENT, private_exponent, &key_template);
1719 1720
1721 // Manufacture a CKA_ID so the created key can be retrieved later as a
1722 // SECKEYPrivateKey using FindKeyByKeyID(). Unfortunately there isn't a more
1723 // direct way to do this in NSS.
1724 //
1725 // A randomly generated value is used for the ID.
1726 //
1727 // NSS assigns the CKA_ID to PK11_MakeIDFromPubKey() for the other key
1728 // creation paths. However it is incorrect to try and use that as the CKA_ID
1729 // here because:
1730 //
1731 // (1) CreateGenericObject does not validate its parameters. It is therefore
1732 // possible to construct a key using the known public modulus, and all
1733 // the other parameters are bogus. FindKeyByKeyID() returns the first
1734 // key matching the ID. So this would effectively allow an attacker to
1735 // retrieve a private key of their choice.
1736 // NSS 3.16.2 does validate parameters.
1737 //
1738 // (2) The ID space is shared by different key types. So even if parameters
1739 // were validated by NSS, FindKeyByKeyID() could still return the wrong
1740 // key. For instance it might return a DH key that happens to have same
1741 // values for its public data.
1742 // Ryan says this isn't possible in practice, because matching values for
Ryan Sleevi 2014/06/02 23:55:57 We don't do this in comments :) But I'm glad Rya
1743 // valid keys can't be easily guessed.
1744 //
1745 // (3) Even if the above two problems were non-issues, there is no guarantee
1746 // that FindKeyByKeyID() returns the object just created. If the same
1747 // private key were imported multiple times, with different flags, using
1748 // the wrong one could lead to problems.
1749 std::vector<uint8> cka_id(20);
1750 crypto::RandBytes(&cka_id[0], cka_id.size());
1751 AddOptionalAttribute(CKA_ID, CryptoData(cka_id), &key_template);
1752 SECItem object_id = MakeSECItemForBuffer(CryptoData(cka_id));
1753
1720 // Optional properties (all of these will have been specified or none). 1754 // Optional properties (all of these will have been specified or none).
1721 AddOptionalAttribute(CKA_PRIME_1, prime1, &key_template); 1755 AddOptionalAttribute(CKA_PRIME_1, prime1, &key_template);
1722 AddOptionalAttribute(CKA_PRIME_2, prime2, &key_template); 1756 AddOptionalAttribute(CKA_PRIME_2, prime2, &key_template);
1723 AddOptionalAttribute(CKA_EXPONENT_1, exponent1, &key_template); 1757 AddOptionalAttribute(CKA_EXPONENT_1, exponent1, &key_template);
1724 AddOptionalAttribute(CKA_EXPONENT_2, exponent2, &key_template); 1758 AddOptionalAttribute(CKA_EXPONENT_2, exponent2, &key_template);
1725 AddOptionalAttribute(CKA_COEFFICIENT, coefficient, &key_template); 1759 AddOptionalAttribute(CKA_COEFFICIENT, coefficient, &key_template);
1726 1760
1727 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot()); 1761 crypto::ScopedPK11Slot slot(PK11_GetInternalSlot());
1728 1762
1729 ScopedPK11GenericObject key_object(PK11_CreateGenericObject( 1763 ScopedPK11GenericObject key_object(PK11_CreateGenericObject(
1730 slot.get(), &key_template[0], key_template.size(), PR_FALSE)); 1764 slot.get(), &key_template[0], key_template.size(), PR_FALSE));
1731 1765
1732 if (!key_object) 1766 if (!key_object)
1733 return Status::OperationError(); 1767 return Status::OperationError();
1734 1768
1735 // The ID isn't guaranteed to be set by PKCS#11. However it is by softtoken so
1736 // this should work.
1737 SECItem object_id = {};
1738 if (PK11_ReadRawAttribute(
1739 PK11_TypeGeneric, key_object.get(), CKA_ID, &object_id) != SECSuccess)
1740 return Status::OperationError();
1741
1742 crypto::ScopedSECKEYPrivateKey private_key( 1769 crypto::ScopedSECKEYPrivateKey private_key(
1743 PK11_FindKeyByKeyID(slot.get(), &object_id, NULL)); 1770 PK11_FindKeyByKeyID(slot.get(), &object_id, NULL));
1744 1771
1745 SECITEM_FreeItem(&object_id, PR_FALSE);
1746
1747 if (!private_key) 1772 if (!private_key)
1748 return Status::OperationError(); 1773 return Status::OperationError();
1749 1774
1750 blink::WebCryptoKeyAlgorithm key_algorithm; 1775 blink::WebCryptoKeyAlgorithm key_algorithm;
1751 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm)) 1776 if (!CreatePrivateKeyAlgorithm(algorithm, private_key.get(), &key_algorithm))
1752 return Status::ErrorUnexpected(); 1777 return Status::ErrorUnexpected();
1753 1778
1754 scoped_ptr<PrivateKey> key_handle; 1779 scoped_ptr<PrivateKey> key_handle;
1755 Status status = 1780 Status status =
1756 PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle); 1781 PrivateKey::Create(private_key.Pass(), key_algorithm, &key_handle);
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1863 buffer->assign(key_data->data, key_data->data + key_data->len); 1888 buffer->assign(key_data->data, key_data->data + key_data->len);
1864 1889
1865 return Status::Success(); 1890 return Status::Success();
1866 } 1891 }
1867 1892
1868 } // namespace platform 1893 } // namespace platform
1869 1894
1870 } // namespace webcrypto 1895 } // namespace webcrypto
1871 1896
1872 } // namespace content 1897 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | content/child/webcrypto/shared_crypto_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698