Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: content/renderer/webcrypto_impl_nss.cc

Issue 23569007: WebCrypto: Implement importKey() and sign() for HMAC in NSS (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/webcrypto_impl.h" 5 #include "content/renderer/webcrypto_impl.h"
6 6
7 #include <sechash.h> 7 #include <nss/sechash.h>
8 #include <nss/pk11pub.h>
8 9
9 #include "base/logging.h" 10 #include "base/logging.h"
10 #include "crypto/nss_util.h" 11 #include "crypto/nss_util.h"
12 #include "crypto/scoped_nss_types.h"
11 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" 13 #include "third_party/WebKit/public/platform/WebArrayBuffer.h"
12 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" 14 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
15 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
13 16
14 namespace content { 17 namespace content {
15 18
19 class WebCryptoSymKeyHandle : public WebKit::WebCryptoKeyHandle {
20 public:
21 void set_mechanism(CK_MECHANISM_TYPE mechanism) {
22 mechanism_ = mechanism;
eroman 2013/09/05 01:57:51 What is the initial value? I would rather this be
Bryan Eyler 2013/09/06 01:27:51 Yeah, initial value appears to be not clear. Move
23 }
24 void set_slot(PK11SlotInfo* slot) {
eroman 2013/09/05 01:57:51 I don't see any current need to specify a slot oth
Bryan Eyler 2013/09/06 01:27:51 Sure, makes sense.
25 slot_.reset(slot);
26 }
27 void set_key(PK11SymKey* key) {
eroman 2013/09/05 01:57:51 This effectively passes ownership of the key. I th
Bryan Eyler 2013/09/06 01:27:51 It gets complicated as the slot is needed for crea
28 key_.reset(key);
29 }
30
31 const CK_MECHANISM_TYPE mechanism() const { return mechanism_; }
32 PK11SlotInfo* slot() { return slot_.get(); }
33 const PK11SymKey* key() const { return key_.get(); }
eroman 2013/09/06 23:03:16 Don't make the pointer const. Then there is no nee
Bryan Eyler 2013/09/09 22:32:10 Done.
34
35 private:
36 CK_MECHANISM_TYPE mechanism_;
37 crypto::ScopedPK11Slot slot_;
38 crypto::ScopedPK11SymKey key_;
39 };
40
16 bool WebCryptoImpl::digestInternal( 41 bool WebCryptoImpl::digestInternal(
17 const WebKit::WebCryptoAlgorithm& algorithm, 42 const WebKit::WebCryptoAlgorithm& algorithm,
18 const unsigned char* data, 43 const unsigned char* data,
19 size_t data_size, 44 size_t data_size,
20 WebKit::WebArrayBuffer* buffer) { 45 WebKit::WebArrayBuffer* buffer) {
21 HASH_HashType hash_type = HASH_AlgNULL; 46 HASH_HashType hash_type = HASH_AlgNULL;
22 47
23 switch (algorithm.id()) { 48 switch (algorithm.id()) {
24 case WebKit::WebCryptoAlgorithmIdSha1: 49 case WebKit::WebCryptoAlgorithmIdSha1:
25 hash_type = HASH_AlgSHA1; 50 hash_type = HASH_AlgSHA1;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data()); 85 unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data());
61 86
62 uint32 result_length = 0; 87 uint32 result_length = 0;
63 HASH_End(context, digest, &result_length, hash_result_length); 88 HASH_End(context, digest, &result_length, hash_result_length);
64 89
65 HASH_Destroy(context); 90 HASH_Destroy(context);
66 91
67 return result_length == hash_result_length; 92 return result_length == hash_result_length;
68 } 93 }
69 94
95 bool WebCryptoImpl::importKeyInternal(
96 WebKit::WebCryptoKeyFormat format,
97 const unsigned char* key_data,
98 size_t key_data_size,
99 const WebKit::WebCryptoAlgorithm& algorithm,
100 bool extractable,
101 WebKit::WebCryptoKeyUsageMask usage_mask,
102 WebKit::WebCryptoKeyHandle** handle) {
103 // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys.
104 // Currently only supporting symmetric.
105 scoped_ptr<WebCryptoSymKeyHandle> sym_key(new WebCryptoSymKeyHandle);
106
107 switch(algorithm.id()) {
108 case WebKit::WebCryptoAlgorithmIdHmac: {
109 WebKit::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams();
eroman 2013/09/05 01:57:51 Ah! I should have defined these as "const" pointer
Bryan Eyler 2013/09/06 01:27:51 Done.
110 if (!params) {
111 return false;
112 }
113
114 switch (params->hash().id()) {
eroman 2013/09/05 01:57:51 You will have to coordinate with Elly's changelist
Bryan Eyler 2013/09/06 01:27:51 Yeah, I realized there would be a bit of overlap/m
115 case WebKit::WebCryptoAlgorithmIdSha1:
116 sym_key->set_mechanism(CKM_SHA_1_HMAC);
117 break;
118 case WebKit::WebCryptoAlgorithmIdSha256:
119 sym_key->set_mechanism(CKM_SHA256_HMAC);
120 break;
121 default:
122 return false;
123 }
124 break;
125 }
126 default:
127 return false;
128 }
129
130 sym_key->set_slot(PK11_GetInternalSlot());
131 if (!sym_key->slot()) {
132 NOTREACHED();
133 return false;
134 }
135
136 CK_FLAGS flags =
137 ((usage_mask & WebKit::WebCryptoKeyUsageEncrypt) ? CKF_ENCRYPT : 0) |
eroman 2013/09/05 01:57:51 sleevi: My understanding is the NSS usage flags ar
Bryan Eyler 2013/09/06 01:27:51 I tried not setting the appropriate flags and it f
Ryan Sleevi 2013/09/06 19:39:02 Not for softoken (effectively), but definitely for
138 ((usage_mask & WebKit::WebCryptoKeyUsageDecrypt) ? CKF_DECRYPT : 0) |
139 ((usage_mask & WebKit::WebCryptoKeyUsageSign) ? CKF_SIGN : 0) |
140 ((usage_mask & WebKit::WebCryptoKeyUsageVerify) ? CKF_VERIFY : 0) |
141 ((usage_mask & WebKit::WebCryptoKeyUsageDeriveKey) ? CKF_DERIVE : 0) |
142 ((usage_mask & WebKit::WebCryptoKeyUsageWrapKey) ? CKF_WRAP : 0) |
143 ((usage_mask & WebKit::WebCryptoKeyUsageUnwrapKey) ? CKF_UNWRAP : 0);
144
145 unsigned char* raw_key_data = NULL;
146 size_t raw_key_data_size = 0;
147
148 switch (format) {
149 case WebKit::WebCryptoKeyFormatRaw:
150 raw_key_data_size = key_data_size;
151 raw_key_data = new unsigned char[raw_key_data_size];
152 memcpy(raw_key_data, key_data, raw_key_data_size);
eroman 2013/09/05 01:57:51 This is unnecessary. You can just pass a SECItem w
Bryan Eyler 2013/09/06 01:27:51 Yes, true. Done.
Ryan Sleevi 2013/09/06 19:39:02 Right
153 break;
154 // TODO(bryaneyler): Handle additional formats.
155 default:
156 return false;
157 }
158
159 SECItem key_item = {
160 siBuffer,
161 raw_key_data,
162 raw_key_data_size
163 };
164
165 sym_key->set_key(
166 PK11_ImportSymKeyWithFlags(sym_key->slot(),
167 sym_key->mechanism(),
168 PK11_OriginUnwrap,
169 CKA_FLAGS_ONLY,
170 &key_item,
171 flags,
172 false,
173 NULL));
174 if (!sym_key->key()) {
175 NOTREACHED();
176 delete[] raw_key_data;
eroman 2013/09/05 01:57:51 See my comment above. We don't want to duplicate t
Bryan Eyler 2013/09/06 01:27:51 Done.
177 return false;
178 }
179
180 *handle = sym_key.release();
181
182 delete[] raw_key_data;
eroman 2013/09/05 01:57:51 See above. We try hard in Chromium not to do manua
Bryan Eyler 2013/09/06 01:27:51 Done.
183 return true;
184 }
185
186 bool WebCryptoImpl::signInternal(
187 const WebKit::WebCryptoAlgorithm& algorithm,
188 const WebKit::WebCryptoKeyHandle* key,
189 const unsigned char* data,
190 size_t data_size,
191 WebKit::WebArrayBuffer* buffer) {
192 WebKit::WebArrayBuffer result;
193
194 switch (algorithm.id()) {
195 case WebKit::WebCryptoAlgorithmIdHmac: {
196 WebKit::WebCryptoHmacParams* params = algorithm.hmacParams();
eroman 2013/09/05 01:57:51 const-ify please. I will change the API to disallo
Bryan Eyler 2013/09/06 01:27:51 Done.
197 if (!params) {
198 return false;
199 }
200
201 const WebCryptoSymKeyHandle* sym_key =
202 reinterpret_cast<const WebCryptoSymKeyHandle*>(key);
203
204 size_t digest_length = 0;
205 switch (params->hash().id()) {
206 case WebKit::WebCryptoAlgorithmIdSha1:
207 digest_length = 20;
eroman 2013/09/05 01:57:51 Rather than hardcode this, can you use a function
Bryan Eyler 2013/09/06 01:27:51 Done. In order to do the DCHECK, I also needed to
Ryan Sleevi 2013/09/06 19:39:02 +1 to your recommended way.
208 DCHECK_EQ(sym_key->mechanism(),
209 static_cast<CK_MECHANISM_TYPE>(CKM_SHA_1_HMAC));
210 break;
211 case WebKit::WebCryptoAlgorithmIdSha256:
212 digest_length = 32;
213 DCHECK_EQ(sym_key->mechanism(),
214 static_cast<CK_MECHANISM_TYPE>(CKM_SHA256_HMAC));
215 break;
216 default:
217 return false;
218 }
219
220 result = WebKit::WebArrayBuffer::create(digest_length, 1);
221
222 SECItem param_item = { siBuffer, NULL, 0 };
223 SECItem data_item = {
224 siBuffer,
225 const_cast<unsigned char*>(data),
226 data_size
227 };
228 SECItem signature_item = {
229 siBuffer,
230 reinterpret_cast<unsigned char*>(result.data()),
231 digest_length
232 };
233
234 if (PK11_SignWithSymKey(const_cast<PK11SymKey*>(sym_key->key()),
eroman 2013/09/05 01:57:51 Please make key() return a non-const PK11SymKey ra
Bryan Eyler 2013/09/06 01:27:51 I need to const_cast at some point because the key
eroman 2013/09/06 23:03:16 Yep, make sym_key non-const, and then change the m
Bryan Eyler 2013/09/09 22:32:10 Done.
235 sym_key->mechanism(),
236 &param_item,
237 &signature_item,
238 &data_item) != SECSuccess) {
239 NOTREACHED();
240 return false;
241 }
242
243 break;
244 }
245 default:
246 return false;
247 }
248
249 *buffer = result;
250 return true;
251 }
252
70 } // namespace content 253 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698