diff options
author | albertb@chromium.org <albertb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-22 20:08:41 +0000 |
---|---|---|
committer | albertb@chromium.org <albertb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-22 20:08:41 +0000 |
commit | 41c78fa1896c5f849c2160ae5de84c232e2c3de9 (patch) | |
tree | dbfa2145004d5de028626fb674c479c888b6183d /base/crypto | |
parent | 7e563816b35dcc102eb69849295b5f6f9d048a63 (diff) | |
download | chromium_src-41c78fa1896c5f849c2160ae5de84c232e2c3de9.zip chromium_src-41c78fa1896c5f849c2160ae5de84c232e2c3de9.tar.gz chromium_src-41c78fa1896c5f849c2160ae5de84c232e2c3de9.tar.bz2 |
PBKDF2 implemetation using NSS.
BUG=none
TEST=unit test
Review URL: http://codereview.chromium.org/1024001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42247 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/crypto')
-rw-r--r-- | base/crypto/pbkdf2.h | 22 | ||||
-rw-r--r-- | base/crypto/pbkdf2_mac.cc | 17 | ||||
-rw-r--r-- | base/crypto/pbkdf2_nss.cc | 56 | ||||
-rw-r--r-- | base/crypto/pbkdf2_unittest.cc | 79 | ||||
-rw-r--r-- | base/crypto/pbkdf2_win.cc | 17 | ||||
-rw-r--r-- | base/crypto/scoped_nss_types.h | 47 | ||||
-rw-r--r-- | base/crypto/symmetric_key.h | 46 | ||||
-rw-r--r-- | base/crypto/symmetric_key_mac.cc | 14 | ||||
-rw-r--r-- | base/crypto/symmetric_key_nss.cc | 27 | ||||
-rw-r--r-- | base/crypto/symmetric_key_win.cc | 14 |
10 files changed, 339 insertions, 0 deletions
diff --git a/base/crypto/pbkdf2.h b/base/crypto/pbkdf2.h new file mode 100644 index 0000000..e5c0821 --- /dev/null +++ b/base/crypto/pbkdf2.h @@ -0,0 +1,22 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_CRYPTO_PBKDF2_H_ +#define BASE_CRYPTO_PBKDF2_H_ + +#include <string> + +#include "base/crypto/symmetric_key.h" + +namespace base { + +// Derives a key from the supplied password and salt using PBKDF2. +SymmetricKey* DeriveKeyFromPassword(const std::string& password, + const std::string& salt, + unsigned int iterations, + unsigned int key_size); + +} // namespace base + +#endif // BASE_CRYPTO_PBKDF2_H_ diff --git a/base/crypto/pbkdf2_mac.cc b/base/crypto/pbkdf2_mac.cc new file mode 100644 index 0000000..64e661e --- /dev/null +++ b/base/crypto/pbkdf2_mac.cc @@ -0,0 +1,17 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/crypto/pbkdf2.h" + +namespace base { + +SymmetricKey* DeriveKeyFromPassword(const std::string& password, + const std::string& salt, + unsigned int iterations, + unsigned int key_size) { + // TODO(albertb): Implement this on Mac. + return NULL; +} + +} // namespace base diff --git a/base/crypto/pbkdf2_nss.cc b/base/crypto/pbkdf2_nss.cc new file mode 100644 index 0000000..df1d898 --- /dev/null +++ b/base/crypto/pbkdf2_nss.cc @@ -0,0 +1,56 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/crypto/pbkdf2.h" + +#include <nss.h> +#include <pk11pub.h> + +#include "base/crypto/scoped_nss_types.h" +#include "base/nss_util.h" + +namespace base { + +SymmetricKey* DeriveKeyFromPassword(const std::string& password, + const std::string& salt, + unsigned int iterations, + unsigned int key_size) { + EnsureNSSInit(); + if (salt.empty() || iterations == 0 || key_size == 0) + return NULL; + + SECItem password_item; + password_item.type = siBuffer; + password_item.data = reinterpret_cast<unsigned char*>( + const_cast<char *>(password.data())); + password_item.len = password.size(); + + SECItem salt_item; + salt_item.type = siBuffer; + salt_item.data = reinterpret_cast<unsigned char*>( + const_cast<char *>(salt.data())); + salt_item.len = salt.size(); + + ScopedSECAlgorithmID alg_id(PK11_CreatePBEV2AlgorithmID(SEC_OID_PKCS5_PBKDF2, + SEC_OID_PKCS5_PBKDF2, + SEC_OID_HMAC_SHA1, + key_size, + iterations, + &salt_item)); + if (!alg_id.get()) + return NULL; + + ScopedPK11Slot slot(PK11_GetBestSlot(SEC_OID_PKCS5_PBKDF2, NULL)); + if (!slot.get()) + return NULL; + + PK11SymKey* sym_key = PK11_PBEKeyGen(slot.get(), alg_id.get(), &password_item, + PR_FALSE, NULL); + if (!sym_key) + return NULL; + + return new SymmetricKey(sym_key); +} + +} // namespace base diff --git a/base/crypto/pbkdf2_unittest.cc b/base/crypto/pbkdf2_unittest.cc new file mode 100644 index 0000000..377bd61 --- /dev/null +++ b/base/crypto/pbkdf2_unittest.cc @@ -0,0 +1,79 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/crypto/pbkdf2.h" + +#include <string> + +#include "base/scoped_ptr.h" +#include "base/string_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +struct TestVector { + const char* password; + const char* salt; + unsigned int rounds; + unsigned int key_size; + const char* expected; +}; + +// These are the test vectors suggested in: +// http://www.ietf.org/id/draft-josefsson-pbkdf2-test-vectors-00.txt +static const TestVector test_vectors[] = { + { + "password", + "salt", + 1, + 20, + "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9" + "\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6", + }, + { + "password", + "salt", + 2, + 20, + "\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e" + "\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57", + }, + { + "password", + "salt", + 4096, + 20, + "\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad" + "\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1", + }, + // This test takes over 30s to run on the trybots. +#if 0 + { + "password", + "salt", + 16777216, + 20, + "\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94" + "\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84", + }, +#endif +}; + +#if defined(USE_NSS) +#define MAYBE_TestVectors TestVectors +#else +#define MAYBE_TestVectors DISABLED_TestVectors +#endif +TEST(PBKDF2Test, MAYBE_TestVectors) { + for (unsigned int i = 0; i < ARRAYSIZE_UNSAFE(test_vectors); ++i) { + SCOPED_TRACE(StringPrintf("Test[%u]", i)); + scoped_ptr<base::SymmetricKey> key(base::DeriveKeyFromPassword( + test_vectors[i].password, test_vectors[i].salt, test_vectors[i].rounds, + test_vectors[i].key_size)); + EXPECT_TRUE(NULL != key.get()); + + std::string raw_key; + key->GetRawKey(&raw_key); + EXPECT_EQ(test_vectors[i].key_size, raw_key.size()); + EXPECT_STREQ(test_vectors[i].expected, raw_key.c_str()); + } +} diff --git a/base/crypto/pbkdf2_win.cc b/base/crypto/pbkdf2_win.cc new file mode 100644 index 0000000..172199b --- /dev/null +++ b/base/crypto/pbkdf2_win.cc @@ -0,0 +1,17 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/crypto/pbkdf2.h" + +namespace base { + +SymmetricKey* DeriveKeyFromPassword(const std::string& password, + const std::string& salt, + unsigned int iterations, + unsigned int key_size) { + // TODO(albertb): Implement this on Windows. + return NULL; +} + +} // namespace base diff --git a/base/crypto/scoped_nss_types.h b/base/crypto/scoped_nss_types.h new file mode 100644 index 0000000..5d67ba1 --- /dev/null +++ b/base/crypto/scoped_nss_types.h @@ -0,0 +1,47 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_SCOPED_NSS_TYPES_H_ +#define BASE_SCOPED_NSS_TYPES_H_ + +#include <nss.h> +#include <pk11pub.h> + +#include "base/scoped_ptr.h" + +namespace base { + +template <typename Type, void (*Destroyer)(Type*)> +struct NSSDestroyer { + void operator()(Type* ptr) const { + if (ptr) + Destroyer(ptr); + } +}; + +template <typename Type, void (*Destroyer)(Type*, PRBool), PRBool freeit> +struct NSSDestroyer1 { + void operator()(Type* ptr) const { + if (ptr) + Destroyer(ptr, freeit); + } +}; + +// Define some convenient scopers around NSS pointers. +typedef scoped_ptr_malloc< + SECAlgorithmID, NSSDestroyer1<SECAlgorithmID, + SECOID_DestroyAlgorithmID, + PR_TRUE> > ScopedSECAlgorithmID; +typedef scoped_ptr_malloc< + PK11Context, NSSDestroyer1<PK11Context, + PK11_DestroyContext, + PR_TRUE> > ScopedPK11Context; +typedef scoped_ptr_malloc< + PK11SlotInfo, NSSDestroyer<PK11SlotInfo, PK11_FreeSlot> > ScopedPK11Slot; +typedef scoped_ptr_malloc< + PK11SymKey, NSSDestroyer<PK11SymKey, PK11_FreeSymKey> > ScopedPK11SymKey; + +} // namespace base + +#endif // BASE_SCOPED_NSS_TYPES_H_ diff --git a/base/crypto/symmetric_key.h b/base/crypto/symmetric_key.h new file mode 100644 index 0000000..c298048 --- /dev/null +++ b/base/crypto/symmetric_key.h @@ -0,0 +1,46 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_CRYPTO_SYMMETRIC_KEY_H_ +#define BASE_CRYPTO_SYMMETRIC_KEY_H_ + +#include <string> + +#include "base/basictypes.h" + +#if defined(USE_NSS) +#include "base/crypto/scoped_nss_types.h" +#endif // USE_NSS + +namespace base { + +// Wraps a platform-specific symmetric key and allows it to be held in a +// scoped_ptr. +class SymmetricKey { + public: +#if defined(USE_NSS) + explicit SymmetricKey(PK11SymKey* key) : key_(key) {} +#endif // USE_NSS + + virtual ~SymmetricKey() {} + +#if defined(USE_NSS) + PK11SymKey* key() const { return key_.get(); } +#endif // USE_NSS + + // Extracts the raw key from the platform specific data. This should only be + // done in unit tests to verify that keys are generated correctly. + bool GetRawKey(std::string* raw_key); + + private: +#if defined(USE_NSS) + ScopedPK11SymKey key_; +#endif // USE_NSS + + DISALLOW_COPY_AND_ASSIGN(SymmetricKey); +}; + +} // namespace base + +#endif // BASE_CRYPTO_SYMMETRIC_KEY_H_ diff --git a/base/crypto/symmetric_key_mac.cc b/base/crypto/symmetric_key_mac.cc new file mode 100644 index 0000000..b24b434 --- /dev/null +++ b/base/crypto/symmetric_key_mac.cc @@ -0,0 +1,14 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/crypto/symmetric_key.h" + +namespace base { + +bool SymmetricKey::GetRawKey(std::string* raw_key) { + // TODO(albertb): Implement on Mac. + return false; +} + +} // namespace base diff --git a/base/crypto/symmetric_key_nss.cc b/base/crypto/symmetric_key_nss.cc new file mode 100644 index 0000000..2c6c1ac --- /dev/null +++ b/base/crypto/symmetric_key_nss.cc @@ -0,0 +1,27 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/crypto/symmetric_key.h" + +#include <nss.h> +#include <pk11pub.h> + +#include "base/logging.h" + +namespace base { + +bool SymmetricKey::GetRawKey(std::string* raw_key) { + SECStatus rv = PK11_ExtractKeyValue(key_.get()); + if (SECSuccess != rv) + return false; + + SECItem* key_item = PK11_GetKeyData(key_.get()); + if (!key_item) + return false; + + raw_key->assign(reinterpret_cast<char*>(key_item->data), key_item->len); + return true; +} + +} // namespace base diff --git a/base/crypto/symmetric_key_win.cc b/base/crypto/symmetric_key_win.cc new file mode 100644 index 0000000..5a302aa --- /dev/null +++ b/base/crypto/symmetric_key_win.cc @@ -0,0 +1,14 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/crypto/symmetric_key.h" + +namespace base { + +bool SymmetricKey::GetRawKey(std::string* raw_key) { + // TODO(albertb): Implement on Windows. + return false; +} + +} // namespace base |