summaryrefslogtreecommitdiffstats
path: root/base/hmac_nss.cc
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 /base/hmac_nss.cc
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
Diffstat (limited to 'base/hmac_nss.cc')
-rw-r--r--base/hmac_nss.cc107
1 files changed, 107 insertions, 0 deletions
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