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

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: Fixes to NSS; removal of redundant storage. Rebased. 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 <pk11pub.h>
7 #include <sechash.h> 8 #include <sechash.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 namespace {
20
21 class SymKeyHandle : public WebKit::WebCryptoKeyHandle {
22 public:
23 SymKeyHandle() {}
24
25 void set_key(crypto::ScopedPK11SymKey key) {
eroman 2013/09/13 00:48:38 This could be an argument to the ctor instead
Bryan Eyler 2013/09/13 20:37:36 Done.
26 DCHECK(!key_.get());
27 key_ = key.Pass();
28 }
29
30 PK11SymKey* key() { return key_.get(); }
31
32 private:
33 crypto::ScopedPK11SymKey key_;
34
35 DISALLOW_COPY_AND_ASSIGN(SymKeyHandle);
36 };
37
38 HASH_HashType WebCryptoAlgorithmToNSSHashType(
39 const WebKit::WebCryptoAlgorithm& algorithm) {
40 switch (algorithm.id()) {
41 case WebKit::WebCryptoAlgorithmIdSha1:
42 return HASH_AlgSHA1;
43 case WebKit::WebCryptoAlgorithmIdSha224:
44 return HASH_AlgSHA224;
45 case WebKit::WebCryptoAlgorithmIdSha256:
46 return HASH_AlgSHA256;
47 case WebKit::WebCryptoAlgorithmIdSha384:
48 return HASH_AlgSHA384;
49 case WebKit::WebCryptoAlgorithmIdSha512:
50 return HASH_AlgSHA512;
51 default:
52 // Not a digest algorithm.
53 return HASH_AlgNULL;
54 }
55 }
56
57 CK_MECHANISM_TYPE WebCryptoAlgorithmToHMACMechanism(
58 const WebKit::WebCryptoAlgorithm& algorithm) {
59 switch (algorithm.id()) {
60 case WebKit::WebCryptoAlgorithmIdSha1:
61 return CKM_SHA_1_HMAC;
62 case WebKit::WebCryptoAlgorithmIdSha256:
63 return CKM_SHA256_HMAC;
64 default:
65 // Not a supported algorithm.
66 return CKM_INVALID_MECHANISM;
67 }
68 }
69
70 } // namespace
71
16 void WebCryptoImpl::Init() { 72 void WebCryptoImpl::Init() {
17 crypto::EnsureNSSInit(); 73 crypto::EnsureNSSInit();
18 } 74 }
19 75
20 bool WebCryptoImpl::DigestInternal( 76 bool WebCryptoImpl::DigestInternal(
21 const WebKit::WebCryptoAlgorithm& algorithm, 77 const WebKit::WebCryptoAlgorithm& algorithm,
22 const unsigned char* data, 78 const unsigned char* data,
23 unsigned data_size, 79 unsigned data_size,
24 WebKit::WebArrayBuffer* buffer) { 80 WebKit::WebArrayBuffer* buffer) {
25 HASH_HashType hash_type = HASH_AlgNULL; 81 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm);
26 82 if (hash_type == HASH_AlgNULL) {
27 switch (algorithm.id()) { 83 return false;
28 case WebKit::WebCryptoAlgorithmIdSha1:
29 hash_type = HASH_AlgSHA1;
30 break;
31 case WebKit::WebCryptoAlgorithmIdSha224:
32 hash_type = HASH_AlgSHA224;
33 break;
34 case WebKit::WebCryptoAlgorithmIdSha256:
35 hash_type = HASH_AlgSHA256;
36 break;
37 case WebKit::WebCryptoAlgorithmIdSha384:
38 hash_type = HASH_AlgSHA384;
39 break;
40 case WebKit::WebCryptoAlgorithmIdSha512:
41 hash_type = HASH_AlgSHA512;
42 break;
43 default:
44 // Not a digest algorithm.
45 return false;
46 } 84 }
47 85
48 HASHContext* context = HASH_Create(hash_type); 86 HASHContext* context = HASH_Create(hash_type);
49 if (!context) { 87 if (!context) {
50 return false; 88 return false;
51 } 89 }
52 90
53 HASH_Begin(context); 91 HASH_Begin(context);
54 92
55 HASH_Update(context, data, data_size); 93 HASH_Update(context, data, data_size);
56 94
57 size_t hash_result_length = HASH_ResultLenContext(context); 95 unsigned hash_result_length = HASH_ResultLenContext(context);
58 DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX)); 96 DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX));
59 97
60 *buffer = WebKit::WebArrayBuffer::create(hash_result_length, 1); 98 *buffer = WebKit::WebArrayBuffer::create(hash_result_length, 1);
61 99
62 unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data()); 100 unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data());
63 101
64 uint32 result_length = 0; 102 unsigned result_length = 0;
65 HASH_End(context, digest, &result_length, hash_result_length); 103 HASH_End(context, digest, &result_length, hash_result_length);
66 104
67 HASH_Destroy(context); 105 HASH_Destroy(context);
68 106
69 return result_length == hash_result_length; 107 return result_length == hash_result_length;
70 } 108 }
71 109
110 bool WebCryptoImpl::ImportKeyInternal(
111 WebKit::WebCryptoKeyFormat format,
112 const unsigned char* key_data,
113 unsigned key_data_size,
114 const WebKit::WebCryptoAlgorithm& algorithm,
115 WebKit::WebCryptoKeyUsageMask usage_mask,
116 scoped_ptr<WebKit::WebCryptoKeyHandle>* handle,
117 WebKit::WebCryptoKeyType* type) {
118 switch (algorithm.id()) {
119 case WebKit::WebCryptoAlgorithmIdHmac:
120 *type = WebKit::WebCryptoKeyTypeSecret;
121 break;
122 // TODO(bryaneyler): Support more key types.
123 default:
124 return false;
125 }
126
127 // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys.
128 // Currently only supporting symmetric.
129 scoped_ptr<SymKeyHandle> sym_key(new SymKeyHandle());
130 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM;
131 // Flags are verified at the Blink layer; here the flags are set to all
132 // possible operations for this key type.
133 CK_FLAGS flags = 0;
134
135 switch(algorithm.id()) {
136 case WebKit::WebCryptoAlgorithmIdHmac: {
137 const WebKit::WebCryptoHmacParams* params = algorithm.hmacParams();
138 if (!params) {
139 return false;
140 }
141
142 mechanism = WebCryptoAlgorithmToHMACMechanism(params->hash());
143 if (mechanism == CKM_INVALID_MECHANISM) {
144 return false;
145 }
146
147 flags |= CKF_SIGN | CKF_VERIFY;
148
149 break;
150 }
151 default:
152 return false;
153 }
154
155 DCHECK_NE(CKM_INVALID_MECHANISM, mechanism);
156 DCHECK_NE(0ul, flags);
157
158 SECItem key_item = { siBuffer, NULL, 0 };
159
160 switch (format) {
161 case WebKit::WebCryptoKeyFormatRaw:
162 key_item.data = const_cast<unsigned char*>(key_data);
163 key_item.len = key_data_size;
164 break;
165 // TODO(bryaneyler): Handle additional formats.
166 default:
167 return false;
168 }
169
170 crypto::ScopedPK11SymKey pk11_sym_key(
171 PK11_ImportSymKeyWithFlags(PK11_GetInternalSlot(),
172 mechanism,
173 PK11_OriginUnwrap,
174 CKA_FLAGS_ONLY,
175 &key_item,
176 flags,
177 false,
178 NULL));
179 sym_key->set_key(pk11_sym_key.Pass());
180 if (!sym_key->key()) {
eroman 2013/09/13 00:48:38 I think it would be more readable to do this test
Bryan Eyler 2013/09/13 20:37:36 Done.
181 NOTREACHED();
182 return false;
183 }
184
185 *handle = sym_key.Pass();
186
187 return true;
188 }
189
190 bool WebCryptoImpl::SignInternal(
191 const WebKit::WebCryptoAlgorithm& algorithm,
192 const WebKit::WebCryptoKey& key,
193 const unsigned char* data,
194 unsigned data_size,
195 WebKit::WebArrayBuffer* buffer) {
196 WebKit::WebArrayBuffer result;
197
198 switch (algorithm.id()) {
199 case WebKit::WebCryptoAlgorithmIdHmac: {
200 const WebKit::WebCryptoHmacParams* params = algorithm.hmacParams();
201 if (!params) {
202 return false;
203 }
204
205 SymKeyHandle* sym_key =
206 const_cast<SymKeyHandle*>(
eroman 2013/09/13 00:48:38 no need for the const-cast; just don't add "const"
Bryan Eyler 2013/09/13 20:37:36 Done.
207 reinterpret_cast<const SymKeyHandle*>(key.handle()));
208
209 DCHECK_EQ(PK11_GetMechanism(sym_key->key()),
210 WebCryptoAlgorithmToHMACMechanism(params->hash()));
211 DCHECK_NE(0, key.usages() & WebKit::WebCryptoKeyUsageSign);
212
213 SECItem param_item = { siBuffer, NULL, 0 };
214 SECItem data_item = {
215 siBuffer,
216 const_cast<unsigned char*>(data),
217 data_size
218 };
219 // First call is to figure out the length.
220 SECItem signature_item = { siBuffer, NULL, 0 };
221
222 if (PK11_SignWithSymKey(sym_key->key(),
223 PK11_GetMechanism(sym_key->key()),
224 &param_item,
225 &signature_item,
226 &data_item) != SECSuccess) {
227 NOTREACHED();
228 return false;
229 }
230
231 DCHECK_LT(0u, signature_item.len);
eroman 2013/09/13 00:48:38 This check can never fail: signature_item.len is u
Bryan Eyler 2013/09/13 20:37:36 This is DCHECK_LT, not DCHECK_LE. I'm validating
232
233 result = WebKit::WebArrayBuffer::create(signature_item.len, 1);
234 signature_item.data = reinterpret_cast<unsigned char*>(result.data());
235
236 if (PK11_SignWithSymKey(sym_key->key(),
237 PK11_GetMechanism(sym_key->key()),
238 &param_item,
239 &signature_item,
240 &data_item) != SECSuccess) {
241 NOTREACHED();
242 return false;
243 }
244
245 DCHECK_EQ(result.byteLength(), signature_item.len);
246
247 break;
248 }
249 default:
250 return false;
251 }
252
253 *buffer = result;
254 return true;
255 }
256
72 } // namespace content 257 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698