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 "crypto/hmac.h" | |
6 | |
7 #include <nss.h> | |
8 #include <pk11pub.h> | |
9 #include <stddef.h> | |
10 | |
11 #include <memory> | |
12 | |
13 #include "base/logging.h" | |
14 #include "crypto/nss_util.h" | |
15 #include "crypto/scoped_nss_types.h" | |
16 | |
17 namespace crypto { | |
18 | |
19 struct HMACPlatformData { | |
20 CK_MECHANISM_TYPE mechanism_; | |
21 ScopedPK11Slot slot_; | |
22 ScopedPK11SymKey sym_key_; | |
23 }; | |
24 | |
25 HMAC::HMAC(HashAlgorithm hash_alg) | |
26 : hash_alg_(hash_alg), plat_(new HMACPlatformData()) { | |
27 // Only SHA-1 and SHA-256 hash algorithms are supported. | |
28 switch (hash_alg_) { | |
29 case SHA1: | |
30 plat_->mechanism_ = CKM_SHA_1_HMAC; | |
31 break; | |
32 case SHA256: | |
33 plat_->mechanism_ = CKM_SHA256_HMAC; | |
34 break; | |
35 default: | |
36 NOTREACHED() << "Unsupported hash algorithm"; | |
37 break; | |
38 } | |
39 } | |
40 | |
41 HMAC::~HMAC() { | |
42 } | |
43 | |
44 bool HMAC::Init(const unsigned char *key, size_t key_length) { | |
45 EnsureNSSInit(); | |
46 | |
47 if (plat_->slot_.get()) { | |
48 // Init must not be called more than twice on the same HMAC object. | |
49 NOTREACHED(); | |
50 return false; | |
51 } | |
52 | |
53 plat_->slot_.reset(PK11_GetInternalSlot()); | |
54 if (!plat_->slot_.get()) { | |
55 NOTREACHED(); | |
56 return false; | |
57 } | |
58 | |
59 SECItem key_item; | |
60 key_item.type = siBuffer; | |
61 key_item.data = const_cast<unsigned char*>(key); // NSS API isn't const. | |
62 key_item.len = key_length; | |
63 | |
64 plat_->sym_key_.reset(PK11_ImportSymKey(plat_->slot_.get(), | |
65 plat_->mechanism_, | |
66 PK11_OriginUnwrap, | |
67 CKA_SIGN, | |
68 &key_item, | |
69 NULL)); | |
70 if (!plat_->sym_key_.get()) { | |
71 NOTREACHED(); | |
72 return false; | |
73 } | |
74 | |
75 return true; | |
76 } | |
77 | |
78 bool HMAC::Sign(const base::StringPiece& data, | |
79 unsigned char* digest, | |
80 size_t digest_length) const { | |
81 if (!plat_->sym_key_.get()) { | |
82 // Init has not been called before Sign. | |
83 NOTREACHED(); | |
84 return false; | |
85 } | |
86 | |
87 SECItem param = { siBuffer, NULL, 0 }; | |
88 ScopedPK11Context context(PK11_CreateContextBySymKey(plat_->mechanism_, | |
89 CKA_SIGN, | |
90 plat_->sym_key_.get(), | |
91 ¶m)); | |
92 if (!context.get()) { | |
93 NOTREACHED(); | |
94 return false; | |
95 } | |
96 | |
97 if (PK11_DigestBegin(context.get()) != SECSuccess) { | |
98 NOTREACHED(); | |
99 return false; | |
100 } | |
101 | |
102 if (PK11_DigestOp(context.get(), | |
103 reinterpret_cast<const unsigned char*>(data.data()), | |
104 data.length()) != SECSuccess) { | |
105 NOTREACHED(); | |
106 return false; | |
107 } | |
108 | |
109 unsigned int len = 0; | |
110 if (PK11_DigestFinal(context.get(), | |
111 digest, &len, digest_length) != SECSuccess) { | |
112 NOTREACHED(); | |
113 return false; | |
114 } | |
115 | |
116 return true; | |
117 } | |
118 | |
119 } // namespace crypto | |
OLD | NEW |