summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordeanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-16 14:32:44 +0000
committerdeanm@google.com <deanm@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-16 14:32:44 +0000
commitbc1e07c777d31055c22cc4a498a0267097063a97 (patch)
tree409ae29dd00141b225766b23a235dcb10c4d426c
parent8aa777462e5b19f936e82a33d3438100857499da (diff)
downloadchromium_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
-rw-r--r--base/SConscript4
-rw-r--r--base/hmac_nss.cc107
-rw-r--r--base/nss_init.cc35
-rw-r--r--base/nss_init.h17
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(),
+ &param));
+ 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_