OLD | NEW |
---|---|
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 ¶m_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 ¶m_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 |
OLD | NEW |