diff options
author | albertb@chromium.org <albertb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-12 21:59:16 +0000 |
---|---|---|
committer | albertb@chromium.org <albertb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-12 21:59:16 +0000 |
commit | bb2eb35a70fcbc47be253bf50c8648c65271a19e (patch) | |
tree | ce04914685bddb9dc7187d8aed2cf674e456bd07 /base | |
parent | 3a7faa316a96f8fa452c36bf1d4d13674eb62b73 (diff) | |
download | chromium_src-bb2eb35a70fcbc47be253bf50c8648c65271a19e.zip chromium_src-bb2eb35a70fcbc47be253bf50c8648c65271a19e.tar.gz chromium_src-bb2eb35a70fcbc47be253bf50c8648c65271a19e.tar.bz2 |
Add support for SymmetricKey to import raw keys when using NSS.
BUG=48512
TEST=unittests
Review URL: http://codereview.chromium.org/2811045
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52136 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/crypto/encryptor_unittest.cc | 9 | ||||
-rw-r--r-- | base/crypto/symmetric_key.h | 20 | ||||
-rw-r--r-- | base/crypto/symmetric_key_nss.cc | 31 | ||||
-rw-r--r-- | base/crypto/symmetric_key_unittest.cc | 47 | ||||
-rw-r--r-- | base/crypto/symmetric_key_win.cc | 9 |
5 files changed, 93 insertions, 23 deletions
diff --git a/base/crypto/encryptor_unittest.cc b/base/crypto/encryptor_unittest.cc index a4f4afd..c5967fa 100644 --- a/base/crypto/encryptor_unittest.cc +++ b/base/crypto/encryptor_unittest.cc @@ -39,9 +39,8 @@ TEST(EncryptorTest, EncryptDecrypt) { // http://gladman.plushost.co.uk/oldsite/AES/index.php // http://csrc.nist.gov/groups/STM/cavp/documents/aes/KAT_AES.zip -// TODO(wtc): implement base::SymmetricKey::Import and enable this test for -// other platforms. -#if defined(OS_WIN) +// TODO(wtc): implement base::SymmetricKey::Import and enable this test on Mac. +#if defined(USE_NSS) || defined(OS_WIN) // NIST SP 800-38A test vector F.2.5 CBC-AES256.Encrypt. TEST(EncryptorTest, EncryptAES256CBC) { // From NIST SP 800-38a test cast F.2.5 CBC-AES256.Encrypt. @@ -88,7 +87,7 @@ TEST(EncryptorTest, EncryptAES256CBC) { }; scoped_ptr<base::SymmetricKey> key(base::SymmetricKey::Import( - base::SymmetricKey::AES, raw_key, sizeof(raw_key))); + base::SymmetricKey::AES, reinterpret_cast<const char*>(raw_key))); EXPECT_TRUE(NULL != key.get()); base::Encryptor encryptor; @@ -110,4 +109,4 @@ TEST(EncryptorTest, EncryptAES256CBC) { EXPECT_EQ(plaintext, decypted); } -#endif // OS_WIN +#endif // USE_NSS || OS_WIN diff --git a/base/crypto/symmetric_key.h b/base/crypto/symmetric_key.h index 48b3708..c1e6f97 100644 --- a/base/crypto/symmetric_key.h +++ b/base/crypto/symmetric_key.h @@ -44,12 +44,13 @@ class SymmetricKey { size_t iterations, size_t key_size_in_bits); - // TODO(wtc): port this method to Mac and NSS. -#if defined(OS_WIN) - // Imports a raw key. This method is only used by unit tests. - static SymmetricKey* Import(Algorithm algorithm, - const void* key_data, - size_t key_size_in_bytes); +#if defined(USE_NSS) || defined(OS_WIN) + // TODO(albertb): Port this method to mac. + // Imports a raw key. For this call to be successful, |raw_key| must have been + // generated by either GenerateRandomKey or DeriveKeyFromPassword, and + // must have been exported with GetRawKey. The caller owns the returned + // SymmetricKey. + static SymmetricKey* Import(Algorithm algorithm, const std::string& raw_key); #endif #if defined(USE_NSS) @@ -60,13 +61,14 @@ class SymmetricKey { HCRYPTKEY key() const { return key_.get(); } #endif - // Extracts the raw key from the platform specific data. This should only be - // done in unit tests to verify that keys are generated correctly. + // Extracts the raw key from the platform specific data. + // Warning: |raw_key| holds the raw key as bytes and thus must be handled + // carefully. bool GetRawKey(std::string* raw_key); private: #if defined(USE_NSS) - explicit SymmetricKey(PK11SymKey* key) : key_(key) {} + explicit SymmetricKey(PK11SymKey* key); ScopedPK11SymKey key_; #elif defined(OS_MACOSX) SymmetricKey(const void* key_data, size_t key_size_in_bits); diff --git a/base/crypto/symmetric_key_nss.cc b/base/crypto/symmetric_key_nss.cc index ed4804f..1405677 100644 --- a/base/crypto/symmetric_key_nss.cc +++ b/base/crypto/symmetric_key_nss.cc @@ -12,6 +12,10 @@ namespace base { +SymmetricKey::SymmetricKey(PK11SymKey* key) : key_(key) { + DCHECK(key); +} + SymmetricKey::~SymmetricKey() {} // static @@ -80,6 +84,33 @@ SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, return new SymmetricKey(sym_key); } +// static +SymmetricKey* SymmetricKey::Import(Algorithm algorithm, + const std::string& raw_key) { + CK_MECHANISM_TYPE cipher = + algorithm == AES ? CKM_AES_KEY_GEN : CKM_SHA_1_HMAC; + + SECItem key_item; + key_item.type = siBuffer; + key_item.data = reinterpret_cast<unsigned char*>( + const_cast<char *>(raw_key.data())); + key_item.len = raw_key.size(); + + ScopedPK11Slot slot(PK11_GetBestSlot(cipher, NULL)); + if (!slot.get()) + return NULL; + + // The exact value of the |origin| argument doesn't matter to NSS as long as + // it's not PK11_OriginFortezzaHack, so we pass PK11_OriginUnwrap as a + // placeholder. + PK11SymKey* sym_key = PK11_ImportSymKey(slot.get(), cipher, PK11_OriginUnwrap, + CKA_ENCRYPT, &key_item, NULL); + if (!sym_key) + return NULL; + + return new SymmetricKey(sym_key); +} + bool SymmetricKey::GetRawKey(std::string* raw_key) { SECStatus rv = PK11_ExtractKeyValue(key_.get()); if (SECSuccess != rv) diff --git a/base/crypto/symmetric_key_unittest.cc b/base/crypto/symmetric_key_unittest.cc index 9be846c..341e45b 100644 --- a/base/crypto/symmetric_key_unittest.cc +++ b/base/crypto/symmetric_key_unittest.cc @@ -13,7 +13,7 @@ TEST(SymmetricKeyTest, GenerateRandomKey) { scoped_ptr<base::SymmetricKey> key( base::SymmetricKey::GenerateRandomKey(base::SymmetricKey::AES, 256)); - EXPECT_TRUE(NULL != key.get()); + ASSERT_TRUE(NULL != key.get()); std::string raw_key; EXPECT_TRUE(key->GetRawKey(&raw_key)); EXPECT_EQ(32U, raw_key.size()); @@ -22,13 +22,54 @@ TEST(SymmetricKeyTest, GenerateRandomKey) { // (Note: this has a one-in-10^77 chance of failure!) scoped_ptr<base::SymmetricKey> key2( base::SymmetricKey::GenerateRandomKey(base::SymmetricKey::AES, 256)); - EXPECT_TRUE(NULL != key2.get()); + ASSERT_TRUE(NULL != key2.get()); std::string raw_key2; EXPECT_TRUE(key2->GetRawKey(&raw_key2)); EXPECT_EQ(32U, raw_key2.size()); EXPECT_NE(raw_key, raw_key2); } +// TODO(albertb): Port this test to Mac. +#if defined(USE_NSS) || defined(OS_WIN) +TEST(SymmetricKeyTest, ImportGeneratedKey) { + scoped_ptr<base::SymmetricKey> key1( + base::SymmetricKey::GenerateRandomKey(base::SymmetricKey::AES, 256)); + ASSERT_TRUE(NULL != key1.get()); + std::string raw_key1; + EXPECT_TRUE(key1->GetRawKey(&raw_key1)); + + scoped_ptr<base::SymmetricKey> key2( + base::SymmetricKey::Import(base::SymmetricKey::AES, raw_key1)); + ASSERT_TRUE(NULL != key2.get()); + + std::string raw_key2; + EXPECT_TRUE(key2->GetRawKey(&raw_key2)); + + EXPECT_EQ(raw_key1, raw_key2); +} +#endif // USE_NSS || OS_WIN + +// TODO(albertb): Port this test to Win and Mac. +#if defined(USE_NSS) +TEST(SymmetricKeyTest, ImportDerivedKey) { + scoped_ptr<base::SymmetricKey> key1( + base::SymmetricKey::DeriveKeyFromPassword(base::SymmetricKey::HMAC_SHA1, + "password", "salt", 1024, 160)); + ASSERT_TRUE(NULL != key1.get()); + std::string raw_key1; + EXPECT_TRUE(key1->GetRawKey(&raw_key1)); + + scoped_ptr<base::SymmetricKey> key2( + base::SymmetricKey::Import(base::SymmetricKey::HMAC_SHA1, raw_key1)); + ASSERT_TRUE(NULL != key2.get()); + + std::string raw_key2; + EXPECT_TRUE(key2->GetRawKey(&raw_key2)); + + EXPECT_EQ(raw_key1, raw_key2); +} +#endif // USE_NSS + struct PBKDF2TestVector { const char* password; const char* salt; @@ -37,8 +78,6 @@ struct PBKDF2TestVector { const uint8 expected[21]; // string literals need 1 extra NUL byte }; -// These are the test vectors suggested in: -// http://www.ietf.org/id/draft-josefsson-pbkdf2-test-vectors-00.txt static const PBKDF2TestVector test_vectors[] = { // These tests come from // http://www.ietf.org/id/draft-josefsson-pbkdf2-test-vectors-00.txt diff --git a/base/crypto/symmetric_key_win.cc b/base/crypto/symmetric_key_win.cc index eb772d5..7d2080c 100644 --- a/base/crypto/symmetric_key_win.cc +++ b/base/crypto/symmetric_key_win.cc @@ -454,8 +454,7 @@ SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, // static SymmetricKey* SymmetricKey::Import(Algorithm algorithm, - const void* key_data, - size_t key_size_in_bytes) { + const std::string& raw_key) { // TODO(wtc): support HMAC. DCHECK_EQ(algorithm, AES); @@ -465,16 +464,16 @@ SymmetricKey* SymmetricKey::Import(Algorithm algorithm, if (!ok) return NULL; - ALG_ID alg = GetAESAlgIDForKeySize(key_size_in_bytes * 8); + ALG_ID alg = GetAESAlgIDForKeySize(raw_key.size() * 8); if (alg == 0) return NULL; ScopedHCRYPTKEY key; - if (!ImportRawKey(provider, alg, key_data, key_size_in_bytes, &key)) + if (!ImportRawKey(provider, alg, raw_key.data(), raw_key.size(), &key)) return NULL; return new SymmetricKey(provider.release(), key.release(), - key_data, key_size_in_bytes); + raw_key.data(), raw_key.size()); } bool SymmetricKey::GetRawKey(std::string* raw_key) { |