OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "base/hmac.h" | |
6 | |
7 #include <nss.h> | |
8 #include <pk11pub.h> | |
9 | |
10 #include "base/crypto/scoped_nss_types.h" | |
11 #include "base/logging.h" | |
12 #include "base/memory/scoped_ptr.h" | |
13 #include "base/nss_util.h" | |
14 | |
15 namespace base { | |
16 | |
17 struct HMACPlatformData { | |
18 CK_MECHANISM_TYPE mechanism_; | |
19 ScopedPK11Slot slot_; | |
20 ScopedPK11SymKey sym_key_; | |
21 }; | |
22 | |
23 HMAC::HMAC(HashAlgorithm hash_alg) | |
24 : hash_alg_(hash_alg), plat_(new HMACPlatformData()) { | |
25 // 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"; | |
35 break; | |
36 } | |
37 } | |
38 | |
39 HMAC::~HMAC() { | |
40 } | |
41 | |
42 bool HMAC::Init(const unsigned char *key, int key_length) { | |
43 base::EnsureNSSInit(); | |
44 | |
45 if (plat_->slot_.get()) { | |
46 // Init must not be called more than twice on the same HMAC object. | |
47 NOTREACHED(); | |
48 return false; | |
49 } | |
50 | |
51 plat_->slot_.reset(PK11_GetBestSlot(plat_->mechanism_, NULL)); | |
52 if (!plat_->slot_.get()) { | |
53 NOTREACHED(); | |
54 return false; | |
55 } | |
56 | |
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(), | |
63 plat_->mechanism_, | |
64 PK11_OriginUnwrap, | |
65 CKA_SIGN, | |
66 &key_item, | |
67 NULL)); | |
68 if (!plat_->sym_key_.get()) { | |
69 NOTREACHED(); | |
70 return false; | |
71 } | |
72 | |
73 return true; | |
74 } | |
75 | |
76 bool HMAC::Sign(const std::string& data, | |
77 unsigned char* digest, | |
78 int digest_length) { | |
79 if (!plat_->sym_key_.get()) { | |
80 // Init has not been called before Sign. | |
81 NOTREACHED(); | |
82 return false; | |
83 } | |
84 | |
85 SECItem param = { siBuffer, NULL, 0 }; | |
86 ScopedPK11Context context(PK11_CreateContextBySymKey(plat_->mechanism_, | |
87 CKA_SIGN, | |
88 plat_->sym_key_.get(), | |
89 ¶m)); | |
90 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 | |
117 } // namespace base | |
OLD | NEW |