diff options
-rw-r--r-- | base/base.gyp | 1 | ||||
-rw-r--r-- | base/base.gypi | 8 | ||||
-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 | ||||
-rw-r--r-- | base/hmac_nss.cc | 37 | ||||
-rw-r--r-- | base/nss_util.h | 3 |
14 files changed, 358 insertions, 30 deletions
diff --git a/base/base.gyp b/base/base.gyp index 581b38b..74a22f5 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -58,6 +58,7 @@ 'cancellation_flag_unittest.cc', 'command_line_unittest.cc', 'condition_variable_unittest.cc', + 'crypto/pbkdf2_unittest.cc', 'crypto/rsa_private_key_unittest.cc', 'crypto/signature_creator_unittest.cc', 'crypto/signature_verifier_unittest.cc', diff --git a/base/base.gypi b/base/base.gypi index 9ba6ca3..3325b63 100644 --- a/base/base.gypi +++ b/base/base.gypi @@ -457,6 +457,10 @@ 'sources': [ 'crypto/cssm_init.cc', 'crypto/cssm_init.h', + 'crypto/pbkdf2.h', + 'crypto/pbkdf2_mac.cc', + 'crypto/pbkdf2_nss.cc', + 'crypto/pbkdf2_win.cc', 'crypto/rsa_private_key.h', 'crypto/rsa_private_key.cc', 'crypto/rsa_private_key_mac.cc', @@ -470,6 +474,10 @@ 'crypto/signature_verifier_mac.cc', 'crypto/signature_verifier_nss.cc', 'crypto/signature_verifier_win.cc', + 'crypto/symmetric_key.h', + 'crypto/symmetric_key_mac.cc', + 'crypto/symmetric_key_nss.cc', + 'crypto/symmetric_key_win.cc', 'third_party/nspr/prcpucfg.h', 'third_party/nspr/prcpucfg_win.h', 'third_party/nspr/prtypes.h', 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 diff --git a/base/hmac_nss.cc b/base/hmac_nss.cc index d55bc64..8f63d04 100644 --- a/base/hmac_nss.cc +++ b/base/hmac_nss.cc @@ -7,39 +7,16 @@ #include <nss.h> #include <pk11pub.h> +#include "base/crypto/scoped_nss_types.h" #include "base/logging.h" #include "base/nss_util.h" #include "base/scoped_ptr.h" -namespace { - -template <typename Type, void (*Destroyer)(Type*)> -struct NSSDestroyer { - void operator()(Type* ptr) const { - if (ptr) - Destroyer(ptr); - } -}; - -void DestroyContext(PK11Context* context) { - PK11_DestroyContext(context, PR_TRUE); -} - -// Define some convenient scopers around NSS pointers. -typedef scoped_ptr_malloc< - PK11SlotInfo, NSSDestroyer<PK11SlotInfo, PK11_FreeSlot> > ScopedNSSSlot; -typedef scoped_ptr_malloc< - PK11SymKey, NSSDestroyer<PK11SymKey, PK11_FreeSymKey> > ScopedNSSSymKey; -typedef scoped_ptr_malloc< - PK11Context, NSSDestroyer<PK11Context, DestroyContext> > ScopedNSSContext; - -} // namespace - namespace base { struct HMACPlatformData { - ScopedNSSSlot slot_; - ScopedNSSSymKey sym_key_; + ScopedPK11Slot slot_; + ScopedPK11SymKey sym_key_; }; HMAC::HMAC(HashAlgorithm hash_alg) @@ -100,10 +77,10 @@ bool HMAC::Sign(const std::string& data, } SECItem param = { siBuffer, NULL, 0 }; - ScopedNSSContext context(PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, - CKA_SIGN, - plat_->sym_key_.get(), - ¶m)); + ScopedPK11Context context(PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, + CKA_SIGN, + plat_->sym_key_.get(), + ¶m)); if (!context.get()) { NOTREACHED(); return false; diff --git a/base/nss_util.h b/base/nss_util.h index f766228..5c8e0f6 100644 --- a/base/nss_util.h +++ b/base/nss_util.h @@ -7,6 +7,9 @@ #include "base/basictypes.h" +// This file specifically doesn't depend on any NSS or NSPR headers because it +// is included by various (non-crypto) parts of chrome to call the +// initialization functions. namespace base { class Time; |