diff options
author | deanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-16 14:32:44 +0000 |
---|---|---|
committer | deanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-09-16 14:32:44 +0000 |
commit | bc1e07c777d31055c22cc4a498a0267097063a97 (patch) | |
tree | 409ae29dd00141b225766b23a235dcb10c4d426c /base | |
parent | 8aa777462e5b19f936e82a33d3438100857499da (diff) | |
download | chromium_src-bc1e07c777d31055c22cc4a498a0267097063a97.zip chromium_src-bc1e07c777d31055c22cc4a498a0267097063a97.tar.gz chromium_src-bc1e07c777d31055c22cc4a498a0267097063a97.tar.bz2 |
Add an HMAC implementation using NSS. Include centralized NSS initialization, based on code from phajdan.jr.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2260 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/SConscript | 4 | ||||
-rw-r--r-- | base/hmac_nss.cc | 107 | ||||
-rw-r--r-- | base/nss_init.cc | 35 | ||||
-rw-r--r-- | base/nss_init.h | 17 |
4 files changed, 162 insertions, 1 deletions
diff --git a/base/SConscript b/base/SConscript index 2fbc815..5705702 100644 --- a/base/SConscript +++ b/base/SConscript @@ -158,6 +158,8 @@ if env['PLATFORM'] == 'posix': 'atomicops_internals_x86_gcc.cc', 'base_paths_linux.cc', 'file_util_linux.cc', + 'hmac_nss.cc', + 'nss_init.cc', 'sys_string_conversions_linux.cc', 'worker_pool.cc', ]) @@ -235,6 +237,7 @@ test_files = [ 'command_line_unittest.cc', 'condition_variable_unittest.cc', 'file_util_unittest.cc', + 'hmac_unittest.cc', 'histogram_unittest.cc', 'json_reader_unittest.cc', 'json_writer_unittest.cc', @@ -281,7 +284,6 @@ if env['PLATFORM'] == 'win32': test_files.extend([ 'clipboard_unittest.cc', - 'hmac_unittest.cc', 'idletimer_unittest.cc', 'process_util_unittest.cc', 'run_all_unittests.cc', diff --git a/base/hmac_nss.cc b/base/hmac_nss.cc new file mode 100644 index 0000000..6e8ef9f --- /dev/null +++ b/base/hmac_nss.cc @@ -0,0 +1,107 @@ +// Copyright (c) 2008 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/hmac.h" + +#include <nss.h> +#include <pk11pub.h> + +#include "base/logging.h" +#include "base/nss_init.h" +#include "base/scoped_ptr.h" + +namespace base { + +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 + +struct HMACPlatformData { + ScopedNSSSlot slot_; + ScopedNSSSymKey sym_key_; +}; + +HMAC::HMAC(HashAlgorithm hash_alg, const unsigned char* key, int key_length) + : hash_alg_(hash_alg), plat_(new HMACPlatformData()) { + DCHECK(hash_alg_ == SHA1); + + base::EnsureNSSInit(); + + plat_->slot_.reset(PK11_GetBestSlot(CKM_SHA_1_HMAC, NULL)); + CHECK(plat_->slot_.get()); + + SECItem key_item; + key_item.type = siBuffer; + key_item.data = const_cast<unsigned char*>(key); // NSS API isn't const. + key_item.len = key_length; + + plat_->sym_key_.reset(PK11_ImportSymKey(plat_->slot_.get(), + CKM_SHA_1_HMAC, + PK11_OriginUnwrap, + CKA_SIGN, + &key_item, + NULL)); + CHECK(plat_->sym_key_.get()); +} + +HMAC::~HMAC() { + delete plat_; +} + +bool HMAC::Sign(const std::string& data, + unsigned char* digest, + int digest_length) { + SECItem param = { siBuffer, NULL, 0 }; + ScopedNSSContext context(PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, + CKA_SIGN, + plat_->sym_key_.get(), + ¶m)); + if (!context.get()) { + NOTREACHED(); + return false; + } + + if (PK11_DigestBegin(context.get()) != SECSuccess) { + NOTREACHED(); + return false; + } + + if (PK11_DigestOp(context.get(), + reinterpret_cast<const unsigned char*>(data.data()), + data.length()) != SECSuccess) { + NOTREACHED(); + return false; + } + + unsigned int len = 0; + if (PK11_DigestFinal(context.get(), + digest, &len, digest_length) != SECSuccess) { + NOTREACHED(); + return false; + } + + return true; +} + +} // namespace base diff --git a/base/nss_init.cc b/base/nss_init.cc new file mode 100644 index 0000000..6427e94 --- /dev/null +++ b/base/nss_init.cc @@ -0,0 +1,35 @@ +// Copyright (c) 2008 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/nss_init.h" + +#include "base/logging.h" +#include "base/singleton.h" + +// Include this header last, since NSS will define "Lock" in an enum. +// https://bugzilla.mozilla.org/show_bug.cgi?id=455424 +#include <nss.h> + +namespace base { + +namespace { + +class NSSInitSingleton { + public: + NSSInitSingleton() { + CHECK(NSS_NoDB_Init(".") == SECSuccess); + } + + ~NSSInitSingleton() { + NSS_Shutdown(); + } +}; + +} // namespace + +void EnsureNSSInit() { + Singleton<NSSInitSingleton>::get(); +} + +} // namespace base diff --git a/base/nss_init.h b/base/nss_init.h new file mode 100644 index 0000000..181d292 --- /dev/null +++ b/base/nss_init.h @@ -0,0 +1,17 @@ +// Copyright (c) 2008 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_NSS_INIT_H_ +#define BASE_NSS_INIT_H_ + +namespace base { + +// Initialize NSS if it isn't already initialized. This must be called before +// any other NSS functions. This function is thread-safe, and NSS will only +// ever be initialized once. NSS will be properly shut down on program exit. +void EnsureNSSInit(); + +} // namespace base + +#endif // BASE_NSS_INIT_H_ |