blob: e14282c916616ce1146dd8b2820f0d5226f5b482 [file] [log] [blame]
[email protected]3b63f8f42011-03-28 01:54:151// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]bc1e07c72008-09-16 14:32:442// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]4b559b4d2011-04-14 17:37:145#include "crypto/hmac.h"
[email protected]bc1e07c72008-09-16 14:32:446
7#include <nss.h>
8#include <pk11pub.h>
9
10#include "base/logging.h"
[email protected]3b63f8f42011-03-28 01:54:1511#include "base/memory/scoped_ptr.h"
[email protected]4b559b4d2011-04-14 17:37:1412#include "crypto/nss_util.h"
13#include "crypto/scoped_nss_types.h"
[email protected]bc1e07c72008-09-16 14:32:4414
[email protected]4b559b4d2011-04-14 17:37:1415namespace crypto {
[email protected]c1444fe2008-09-17 09:42:5116
[email protected]bc1e07c72008-09-16 14:32:4417struct HMACPlatformData {
[email protected]1b47ce22010-03-31 16:18:3018 CK_MECHANISM_TYPE mechanism_;
[email protected]41c78fa2010-03-22 20:08:4119 ScopedPK11Slot slot_;
20 ScopedPK11SymKey sym_key_;
[email protected]bc1e07c72008-09-16 14:32:4421};
22
[email protected]d91f8432009-05-05 23:55:5923HMAC::HMAC(HashAlgorithm hash_alg)
[email protected]bc1e07c72008-09-16 14:32:4424 : hash_alg_(hash_alg), plat_(new HMACPlatformData()) {
[email protected]1b47ce22010-03-31 16:18:3025 // Only SHA-1 and SHA-256 hash algorithms are supported.
26 switch (hash_alg_) {
27 case SHA1:
28 plat_->mechanism_ = CKM_SHA_1_HMAC;
29 break;
30 case SHA256:
31 plat_->mechanism_ = CKM_SHA256_HMAC;
32 break;
33 default:
34 NOTREACHED() << "Unsupported hash algorithm";
[email protected]db163f82010-04-02 21:01:3535 break;
[email protected]1b47ce22010-03-31 16:18:3036 }
[email protected]d91f8432009-05-05 23:55:5937}
[email protected]bc1e07c72008-09-16 14:32:4438
[email protected]eae9c062011-01-11 00:50:5939HMAC::~HMAC() {
40}
41
[email protected]673266c42012-12-04 00:50:3542bool HMAC::Init(const unsigned char *key, size_t key_length) {
[email protected]4b559b4d2011-04-14 17:37:1443 EnsureNSSInit();
[email protected]bc1e07c72008-09-16 14:32:4444
[email protected]2f89e6a22009-07-22 18:34:1445 if (plat_->slot_.get()) {
[email protected]d91f8432009-05-05 23:55:5946 // Init must not be called more than twice on the same HMAC object.
47 NOTREACHED();
48 return false;
49 }
50
[email protected]f55d1b02011-10-23 21:52:0751 plat_->slot_.reset(PK11_GetInternalSlot());
[email protected]d91f8432009-05-05 23:55:5952 if (!plat_->slot_.get()) {
53 NOTREACHED();
54 return false;
55 }
[email protected]bc1e07c72008-09-16 14:32:4456
57 SECItem key_item;
58 key_item.type = siBuffer;
59 key_item.data = const_cast<unsigned char*>(key); // NSS API isn't const.
60 key_item.len = key_length;
61
62 plat_->sym_key_.reset(PK11_ImportSymKey(plat_->slot_.get(),
[email protected]1b47ce22010-03-31 16:18:3063 plat_->mechanism_,
[email protected]bc1e07c72008-09-16 14:32:4464 PK11_OriginUnwrap,
65 CKA_SIGN,
66 &key_item,
67 NULL));
[email protected]d91f8432009-05-05 23:55:5968 if (!plat_->sym_key_.get()) {
69 NOTREACHED();
70 return false;
71 }
72
73 return true;
[email protected]bc1e07c72008-09-16 14:32:4474}
75
[email protected]c28986ee2011-06-06 22:00:1176bool HMAC::Sign(const base::StringPiece& data,
[email protected]bc1e07c72008-09-16 14:32:4477 unsigned char* digest,
[email protected]673266c42012-12-04 00:50:3578 size_t digest_length) const {
[email protected]d91f8432009-05-05 23:55:5979 if (!plat_->sym_key_.get()) {
80 // Init has not been called before Sign.
81 NOTREACHED();
82 return false;
83 }
84
[email protected]bc1e07c72008-09-16 14:32:4485 SECItem param = { siBuffer, NULL, 0 };
[email protected]1b47ce22010-03-31 16:18:3086 ScopedPK11Context context(PK11_CreateContextBySymKey(plat_->mechanism_,
[email protected]41c78fa2010-03-22 20:08:4187 CKA_SIGN,
88 plat_->sym_key_.get(),
89 &param));
[email protected]bc1e07c72008-09-16 14:32:4490 if (!context.get()) {
91 NOTREACHED();
92 return false;
93 }
94
95 if (PK11_DigestBegin(context.get()) != SECSuccess) {
96 NOTREACHED();
97 return false;
98 }
99
100 if (PK11_DigestOp(context.get(),
101 reinterpret_cast<const unsigned char*>(data.data()),
102 data.length()) != SECSuccess) {
103 NOTREACHED();
104 return false;
105 }
106
107 unsigned int len = 0;
108 if (PK11_DigestFinal(context.get(),
109 digest, &len, digest_length) != SECSuccess) {
110 NOTREACHED();
111 return false;
112 }
113
114 return true;
115}
116
[email protected]4b559b4d2011-04-14 17:37:14117} // namespace crypto