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/webcrypto_impl.h" | 5 #include "content/renderer/webcrypto/webcrypto_impl.h" |
6 | 6 |
7 #include <cryptohi.h> | 7 #include <cryptohi.h> |
8 #include <pk11pub.h> | 8 #include <pk11pub.h> |
9 #include <sechash.h> | 9 #include <sechash.h> |
10 | 10 |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "crypto/nss_util.h" | 14 #include "crypto/nss_util.h" |
15 #include "crypto/scoped_nss_types.h" | 15 #include "crypto/scoped_nss_types.h" |
16 #include "crypto/secure_util.h" | 16 #include "crypto/secure_util.h" |
17 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" | 17 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" |
18 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" | 18 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" |
19 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | 19 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
20 | 20 |
21 namespace content { | 21 namespace content { |
22 | 22 |
23 namespace { | 23 namespace { |
24 | 24 |
25 class SymKeyHandle : public WebKit::WebCryptoKeyHandle { | 25 class SymKeyHandle : public blink::WebCryptoKeyHandle { |
26 public: | 26 public: |
27 explicit SymKeyHandle(crypto::ScopedPK11SymKey key) : key_(key.Pass()) {} | 27 explicit SymKeyHandle(crypto::ScopedPK11SymKey key) : key_(key.Pass()) {} |
28 | 28 |
29 PK11SymKey* key() { return key_.get(); } | 29 PK11SymKey* key() { return key_.get(); } |
30 | 30 |
31 private: | 31 private: |
32 crypto::ScopedPK11SymKey key_; | 32 crypto::ScopedPK11SymKey key_; |
33 | 33 |
34 DISALLOW_COPY_AND_ASSIGN(SymKeyHandle); | 34 DISALLOW_COPY_AND_ASSIGN(SymKeyHandle); |
35 }; | 35 }; |
36 | 36 |
37 class PublicKeyHandle : public WebKit::WebCryptoKeyHandle { | 37 class PublicKeyHandle : public blink::WebCryptoKeyHandle { |
38 public: | 38 public: |
39 explicit PublicKeyHandle(crypto::ScopedSECKEYPublicKey key) | 39 explicit PublicKeyHandle(crypto::ScopedSECKEYPublicKey key) |
40 : key_(key.Pass()) {} | 40 : key_(key.Pass()) {} |
41 | 41 |
42 SECKEYPublicKey* key() { return key_.get(); } | 42 SECKEYPublicKey* key() { return key_.get(); } |
43 | 43 |
44 private: | 44 private: |
45 crypto::ScopedSECKEYPublicKey key_; | 45 crypto::ScopedSECKEYPublicKey key_; |
46 | 46 |
47 DISALLOW_COPY_AND_ASSIGN(PublicKeyHandle); | 47 DISALLOW_COPY_AND_ASSIGN(PublicKeyHandle); |
48 }; | 48 }; |
49 | 49 |
50 class PrivateKeyHandle : public WebKit::WebCryptoKeyHandle { | 50 class PrivateKeyHandle : public blink::WebCryptoKeyHandle { |
51 public: | 51 public: |
52 explicit PrivateKeyHandle(crypto::ScopedSECKEYPrivateKey key) | 52 explicit PrivateKeyHandle(crypto::ScopedSECKEYPrivateKey key) |
53 : key_(key.Pass()) {} | 53 : key_(key.Pass()) {} |
54 | 54 |
55 SECKEYPrivateKey* key() { return key_.get(); } | 55 SECKEYPrivateKey* key() { return key_.get(); } |
56 | 56 |
57 private: | 57 private: |
58 crypto::ScopedSECKEYPrivateKey key_; | 58 crypto::ScopedSECKEYPrivateKey key_; |
59 | 59 |
60 DISALLOW_COPY_AND_ASSIGN(PrivateKeyHandle); | 60 DISALLOW_COPY_AND_ASSIGN(PrivateKeyHandle); |
61 }; | 61 }; |
62 | 62 |
63 HASH_HashType WebCryptoAlgorithmToNSSHashType( | 63 HASH_HashType WebCryptoAlgorithmToNSSHashType( |
64 const WebKit::WebCryptoAlgorithm& algorithm) { | 64 const blink::WebCryptoAlgorithm& algorithm) { |
65 switch (algorithm.id()) { | 65 switch (algorithm.id()) { |
66 case WebKit::WebCryptoAlgorithmIdSha1: | 66 case blink::WebCryptoAlgorithmIdSha1: |
67 return HASH_AlgSHA1; | 67 return HASH_AlgSHA1; |
68 case WebKit::WebCryptoAlgorithmIdSha224: | 68 case blink::WebCryptoAlgorithmIdSha224: |
69 return HASH_AlgSHA224; | 69 return HASH_AlgSHA224; |
70 case WebKit::WebCryptoAlgorithmIdSha256: | 70 case blink::WebCryptoAlgorithmIdSha256: |
71 return HASH_AlgSHA256; | 71 return HASH_AlgSHA256; |
72 case WebKit::WebCryptoAlgorithmIdSha384: | 72 case blink::WebCryptoAlgorithmIdSha384: |
73 return HASH_AlgSHA384; | 73 return HASH_AlgSHA384; |
74 case WebKit::WebCryptoAlgorithmIdSha512: | 74 case blink::WebCryptoAlgorithmIdSha512: |
75 return HASH_AlgSHA512; | 75 return HASH_AlgSHA512; |
76 default: | 76 default: |
77 // Not a digest algorithm. | 77 // Not a digest algorithm. |
78 return HASH_AlgNULL; | 78 return HASH_AlgNULL; |
79 } | 79 } |
80 } | 80 } |
81 | 81 |
82 CK_MECHANISM_TYPE WebCryptoAlgorithmToHMACMechanism( | 82 CK_MECHANISM_TYPE WebCryptoAlgorithmToHMACMechanism( |
83 const WebKit::WebCryptoAlgorithm& algorithm) { | 83 const blink::WebCryptoAlgorithm& algorithm) { |
84 switch (algorithm.id()) { | 84 switch (algorithm.id()) { |
85 case WebKit::WebCryptoAlgorithmIdSha1: | 85 case blink::WebCryptoAlgorithmIdSha1: |
86 return CKM_SHA_1_HMAC; | 86 return CKM_SHA_1_HMAC; |
87 case WebKit::WebCryptoAlgorithmIdSha256: | 87 case blink::WebCryptoAlgorithmIdSha256: |
88 return CKM_SHA256_HMAC; | 88 return CKM_SHA256_HMAC; |
89 default: | 89 default: |
90 // Not a supported algorithm. | 90 // Not a supported algorithm. |
91 return CKM_INVALID_MECHANISM; | 91 return CKM_INVALID_MECHANISM; |
92 } | 92 } |
93 } | 93 } |
94 | 94 |
95 bool AesCbcEncryptDecrypt( | 95 bool AesCbcEncryptDecrypt( |
96 CK_ATTRIBUTE_TYPE operation, | 96 CK_ATTRIBUTE_TYPE operation, |
97 const WebKit::WebCryptoAlgorithm& algorithm, | 97 const blink::WebCryptoAlgorithm& algorithm, |
98 const WebKit::WebCryptoKey& key, | 98 const blink::WebCryptoKey& key, |
99 const unsigned char* data, | 99 const unsigned char* data, |
100 unsigned data_size, | 100 unsigned data_size, |
101 WebKit::WebArrayBuffer* buffer) { | 101 blink::WebArrayBuffer* buffer) { |
102 DCHECK_EQ(WebKit::WebCryptoAlgorithmIdAesCbc, algorithm.id()); | 102 DCHECK_EQ(blink::WebCryptoAlgorithmIdAesCbc, algorithm.id()); |
103 DCHECK_EQ(algorithm.id(), key.algorithm().id()); | 103 DCHECK_EQ(algorithm.id(), key.algorithm().id()); |
104 DCHECK_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); | 104 DCHECK_EQ(blink::WebCryptoKeyTypeSecret, key.type()); |
105 DCHECK(operation == CKA_ENCRYPT || operation == CKA_DECRYPT); | 105 DCHECK(operation == CKA_ENCRYPT || operation == CKA_DECRYPT); |
106 | 106 |
107 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); | 107 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); |
108 | 108 |
109 const WebKit::WebCryptoAesCbcParams* params = algorithm.aesCbcParams(); | 109 const blink::WebCryptoAesCbcParams* params = algorithm.aesCbcParams(); |
110 if (params->iv().size() != AES_BLOCK_SIZE) | 110 if (params->iv().size() != AES_BLOCK_SIZE) |
111 return false; | 111 return false; |
112 | 112 |
113 SECItem iv_item; | 113 SECItem iv_item; |
114 iv_item.type = siBuffer; | 114 iv_item.type = siBuffer; |
115 iv_item.data = const_cast<unsigned char*>(params->iv().data()); | 115 iv_item.data = const_cast<unsigned char*>(params->iv().data()); |
116 iv_item.len = params->iv().size(); | 116 iv_item.len = params->iv().size(); |
117 | 117 |
118 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); | 118 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); |
119 if (!param) | 119 if (!param) |
(...skipping 21 matching lines...) Expand all Loading... |
141 if (operation == CKA_DECRYPT && | 141 if (operation == CKA_DECRYPT && |
142 (data_size == 0 || (data_size % AES_BLOCK_SIZE != 0))) { | 142 (data_size == 0 || (data_size % AES_BLOCK_SIZE != 0))) { |
143 return false; | 143 return false; |
144 } | 144 } |
145 | 145 |
146 // TODO(eroman): Refine the output buffer size. It can be computed exactly for | 146 // TODO(eroman): Refine the output buffer size. It can be computed exactly for |
147 // encryption, and can be smaller for decryption. | 147 // encryption, and can be smaller for decryption. |
148 unsigned output_max_len = data_size + AES_BLOCK_SIZE; | 148 unsigned output_max_len = data_size + AES_BLOCK_SIZE; |
149 CHECK_GT(output_max_len, data_size); | 149 CHECK_GT(output_max_len, data_size); |
150 | 150 |
151 *buffer = WebKit::WebArrayBuffer::create(output_max_len, 1); | 151 *buffer = blink::WebArrayBuffer::create(output_max_len, 1); |
152 | 152 |
153 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); | 153 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); |
154 | 154 |
155 int output_len; | 155 int output_len; |
156 if (SECSuccess != PK11_CipherOp(context.get(), | 156 if (SECSuccess != PK11_CipherOp(context.get(), |
157 buffer_data, | 157 buffer_data, |
158 &output_len, | 158 &output_len, |
159 buffer->byteLength(), | 159 buffer->byteLength(), |
160 data, | 160 data, |
161 data_size)) { | 161 data_size)) { |
162 return false; | 162 return false; |
163 } | 163 } |
164 | 164 |
165 unsigned int final_output_chunk_len; | 165 unsigned int final_output_chunk_len; |
166 if (SECSuccess != PK11_DigestFinal(context.get(), | 166 if (SECSuccess != PK11_DigestFinal(context.get(), |
167 buffer_data + output_len, | 167 buffer_data + output_len, |
168 &final_output_chunk_len, | 168 &final_output_chunk_len, |
169 output_max_len - output_len)) { | 169 output_max_len - output_len)) { |
170 return false; | 170 return false; |
171 } | 171 } |
172 | 172 |
173 WebCryptoImpl::ShrinkBuffer(buffer, final_output_chunk_len + output_len); | 173 WebCryptoImpl::ShrinkBuffer(buffer, final_output_chunk_len + output_len); |
174 return true; | 174 return true; |
175 } | 175 } |
176 | 176 |
177 CK_MECHANISM_TYPE HmacAlgorithmToGenMechanism( | 177 CK_MECHANISM_TYPE HmacAlgorithmToGenMechanism( |
178 const WebKit::WebCryptoAlgorithm& algorithm) { | 178 const blink::WebCryptoAlgorithm& algorithm) { |
179 DCHECK_EQ(algorithm.id(), WebKit::WebCryptoAlgorithmIdHmac); | 179 DCHECK_EQ(algorithm.id(), blink::WebCryptoAlgorithmIdHmac); |
180 const WebKit::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams(); | 180 const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams(); |
181 DCHECK(params); | 181 DCHECK(params); |
182 switch (params->hash().id()) { | 182 switch (params->hash().id()) { |
183 case WebKit::WebCryptoAlgorithmIdSha1: | 183 case blink::WebCryptoAlgorithmIdSha1: |
184 return CKM_SHA_1_HMAC; | 184 return CKM_SHA_1_HMAC; |
185 case WebKit::WebCryptoAlgorithmIdSha256: | 185 case blink::WebCryptoAlgorithmIdSha256: |
186 return CKM_SHA256_HMAC; | 186 return CKM_SHA256_HMAC; |
187 default: | 187 default: |
188 return CKM_INVALID_MECHANISM; | 188 return CKM_INVALID_MECHANISM; |
189 } | 189 } |
190 } | 190 } |
191 | 191 |
192 CK_MECHANISM_TYPE WebCryptoAlgorithmToGenMechanism( | 192 CK_MECHANISM_TYPE WebCryptoAlgorithmToGenMechanism( |
193 const WebKit::WebCryptoAlgorithm& algorithm) { | 193 const blink::WebCryptoAlgorithm& algorithm) { |
194 switch (algorithm.id()) { | 194 switch (algorithm.id()) { |
195 case WebKit::WebCryptoAlgorithmIdAesCbc: | 195 case blink::WebCryptoAlgorithmIdAesCbc: |
196 return CKM_AES_KEY_GEN; | 196 return CKM_AES_KEY_GEN; |
197 case WebKit::WebCryptoAlgorithmIdHmac: | 197 case blink::WebCryptoAlgorithmIdHmac: |
198 return HmacAlgorithmToGenMechanism(algorithm); | 198 return HmacAlgorithmToGenMechanism(algorithm); |
199 default: | 199 default: |
200 return CKM_INVALID_MECHANISM; | 200 return CKM_INVALID_MECHANISM; |
201 } | 201 } |
202 } | 202 } |
203 | 203 |
204 unsigned int WebCryptoHmacAlgorithmToBlockSize( | 204 unsigned int WebCryptoHmacAlgorithmToBlockSize( |
205 const WebKit::WebCryptoAlgorithm& algorithm) { | 205 const blink::WebCryptoAlgorithm& algorithm) { |
206 DCHECK_EQ(algorithm.id(), WebKit::WebCryptoAlgorithmIdHmac); | 206 DCHECK_EQ(algorithm.id(), blink::WebCryptoAlgorithmIdHmac); |
207 const WebKit::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams(); | 207 const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams(); |
208 DCHECK(params); | 208 DCHECK(params); |
209 switch (params->hash().id()) { | 209 switch (params->hash().id()) { |
210 case WebKit::WebCryptoAlgorithmIdSha1: | 210 case blink::WebCryptoAlgorithmIdSha1: |
211 return 512; | 211 return 512; |
212 case WebKit::WebCryptoAlgorithmIdSha256: | 212 case blink::WebCryptoAlgorithmIdSha256: |
213 return 512; | 213 return 512; |
214 default: | 214 default: |
215 return 0; | 215 return 0; |
216 } | 216 } |
217 } | 217 } |
218 | 218 |
219 // Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros, | 219 // Converts a (big-endian) WebCrypto BigInteger, with or without leading zeros, |
220 // to unsigned long. | 220 // to unsigned long. |
221 bool BigIntegerToLong(const uint8* data, | 221 bool BigIntegerToLong(const uint8* data, |
222 unsigned data_size, | 222 unsigned data_size, |
(...skipping 15 matching lines...) Expand all Loading... |
238 return true; | 238 return true; |
239 } | 239 } |
240 | 240 |
241 } // namespace | 241 } // namespace |
242 | 242 |
243 void WebCryptoImpl::Init() { | 243 void WebCryptoImpl::Init() { |
244 crypto::EnsureNSSInit(); | 244 crypto::EnsureNSSInit(); |
245 } | 245 } |
246 | 246 |
247 bool WebCryptoImpl::EncryptInternal( | 247 bool WebCryptoImpl::EncryptInternal( |
248 const WebKit::WebCryptoAlgorithm& algorithm, | 248 const blink::WebCryptoAlgorithm& algorithm, |
249 const WebKit::WebCryptoKey& key, | 249 const blink::WebCryptoKey& key, |
250 const unsigned char* data, | 250 const unsigned char* data, |
251 unsigned data_size, | 251 unsigned data_size, |
252 WebKit::WebArrayBuffer* buffer) { | 252 blink::WebArrayBuffer* buffer) { |
253 if (algorithm.id() == WebKit::WebCryptoAlgorithmIdAesCbc) { | 253 if (algorithm.id() == blink::WebCryptoAlgorithmIdAesCbc) { |
254 return AesCbcEncryptDecrypt( | 254 return AesCbcEncryptDecrypt( |
255 CKA_ENCRYPT, algorithm, key, data, data_size, buffer); | 255 CKA_ENCRYPT, algorithm, key, data, data_size, buffer); |
256 } | 256 } |
257 | 257 |
258 return false; | 258 return false; |
259 } | 259 } |
260 | 260 |
261 bool WebCryptoImpl::DecryptInternal( | 261 bool WebCryptoImpl::DecryptInternal( |
262 const WebKit::WebCryptoAlgorithm& algorithm, | 262 const blink::WebCryptoAlgorithm& algorithm, |
263 const WebKit::WebCryptoKey& key, | 263 const blink::WebCryptoKey& key, |
264 const unsigned char* data, | 264 const unsigned char* data, |
265 unsigned data_size, | 265 unsigned data_size, |
266 WebKit::WebArrayBuffer* buffer) { | 266 blink::WebArrayBuffer* buffer) { |
267 if (algorithm.id() == WebKit::WebCryptoAlgorithmIdAesCbc) { | 267 if (algorithm.id() == blink::WebCryptoAlgorithmIdAesCbc) { |
268 return AesCbcEncryptDecrypt( | 268 return AesCbcEncryptDecrypt( |
269 CKA_DECRYPT, algorithm, key, data, data_size, buffer); | 269 CKA_DECRYPT, algorithm, key, data, data_size, buffer); |
270 } | 270 } |
271 | 271 |
272 return false; | 272 return false; |
273 } | 273 } |
274 | 274 |
275 bool WebCryptoImpl::DigestInternal( | 275 bool WebCryptoImpl::DigestInternal( |
276 const WebKit::WebCryptoAlgorithm& algorithm, | 276 const blink::WebCryptoAlgorithm& algorithm, |
277 const unsigned char* data, | 277 const unsigned char* data, |
278 unsigned data_size, | 278 unsigned data_size, |
279 WebKit::WebArrayBuffer* buffer) { | 279 blink::WebArrayBuffer* buffer) { |
280 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); | 280 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); |
281 if (hash_type == HASH_AlgNULL) { | 281 if (hash_type == HASH_AlgNULL) { |
282 return false; | 282 return false; |
283 } | 283 } |
284 | 284 |
285 HASHContext* context = HASH_Create(hash_type); | 285 HASHContext* context = HASH_Create(hash_type); |
286 if (!context) { | 286 if (!context) { |
287 return false; | 287 return false; |
288 } | 288 } |
289 | 289 |
290 HASH_Begin(context); | 290 HASH_Begin(context); |
291 | 291 |
292 HASH_Update(context, data, data_size); | 292 HASH_Update(context, data, data_size); |
293 | 293 |
294 unsigned hash_result_length = HASH_ResultLenContext(context); | 294 unsigned hash_result_length = HASH_ResultLenContext(context); |
295 DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX)); | 295 DCHECK_LE(hash_result_length, static_cast<size_t>(HASH_LENGTH_MAX)); |
296 | 296 |
297 *buffer = WebKit::WebArrayBuffer::create(hash_result_length, 1); | 297 *buffer = blink::WebArrayBuffer::create(hash_result_length, 1); |
298 | 298 |
299 unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data()); | 299 unsigned char* digest = reinterpret_cast<unsigned char*>(buffer->data()); |
300 | 300 |
301 unsigned result_length = 0; | 301 unsigned result_length = 0; |
302 HASH_End(context, digest, &result_length, hash_result_length); | 302 HASH_End(context, digest, &result_length, hash_result_length); |
303 | 303 |
304 HASH_Destroy(context); | 304 HASH_Destroy(context); |
305 | 305 |
306 return result_length == hash_result_length; | 306 return result_length == hash_result_length; |
307 } | 307 } |
308 | 308 |
309 bool WebCryptoImpl::GenerateKeyInternal( | 309 bool WebCryptoImpl::GenerateKeyInternal( |
310 const WebKit::WebCryptoAlgorithm& algorithm, | 310 const blink::WebCryptoAlgorithm& algorithm, |
311 bool extractable, | 311 bool extractable, |
312 WebKit::WebCryptoKeyUsageMask usage_mask, | 312 blink::WebCryptoKeyUsageMask usage_mask, |
313 WebKit::WebCryptoKey* key) { | 313 blink::WebCryptoKey* key) { |
314 | 314 |
315 CK_MECHANISM_TYPE mech = WebCryptoAlgorithmToGenMechanism(algorithm); | 315 CK_MECHANISM_TYPE mech = WebCryptoAlgorithmToGenMechanism(algorithm); |
316 unsigned int keylen_bytes = 0; | 316 unsigned int keylen_bytes = 0; |
317 WebKit::WebCryptoKeyType key_type = WebKit::WebCryptoKeyTypeSecret; | 317 blink::WebCryptoKeyType key_type = blink::WebCryptoKeyTypeSecret; |
318 | 318 |
319 if (mech == CKM_INVALID_MECHANISM) { | 319 if (mech == CKM_INVALID_MECHANISM) { |
320 return false; | 320 return false; |
321 } | 321 } |
322 | 322 |
323 switch (algorithm.id()) { | 323 switch (algorithm.id()) { |
324 case WebKit::WebCryptoAlgorithmIdAesCbc: { | 324 case blink::WebCryptoAlgorithmIdAesCbc: { |
325 const WebKit::WebCryptoAesKeyGenParams* params = | 325 const blink::WebCryptoAesKeyGenParams* params = |
326 algorithm.aesKeyGenParams(); | 326 algorithm.aesKeyGenParams(); |
327 DCHECK(params); | 327 DCHECK(params); |
328 keylen_bytes = params->length() / 8; | 328 keylen_bytes = params->length() / 8; |
329 if (params->length() % 8) | 329 if (params->length() % 8) |
330 return false; | 330 return false; |
331 key_type = WebKit::WebCryptoKeyTypeSecret; | 331 key_type = blink::WebCryptoKeyTypeSecret; |
332 break; | 332 break; |
333 } | 333 } |
334 case WebKit::WebCryptoAlgorithmIdHmac: { | 334 case blink::WebCryptoAlgorithmIdHmac: { |
335 const WebKit::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams(); | 335 const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams(); |
336 DCHECK(params); | 336 DCHECK(params); |
337 if (!params->getLength(keylen_bytes)) { | 337 if (!params->getLength(keylen_bytes)) { |
338 keylen_bytes = WebCryptoHmacAlgorithmToBlockSize(algorithm) / 8; | 338 keylen_bytes = WebCryptoHmacAlgorithmToBlockSize(algorithm) / 8; |
339 } | 339 } |
340 | 340 |
341 key_type = WebKit::WebCryptoKeyTypeSecret; | 341 key_type = blink::WebCryptoKeyTypeSecret; |
342 break; | 342 break; |
343 } | 343 } |
344 | 344 |
345 default: { | 345 default: { |
346 return false; | 346 return false; |
347 } | 347 } |
348 } | 348 } |
349 | 349 |
350 if (keylen_bytes == 0) { | 350 if (keylen_bytes == 0) { |
351 return false; | 351 return false; |
352 } | 352 } |
353 | 353 |
354 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); | 354 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); |
355 if (!slot) { | 355 if (!slot) { |
356 return false; | 356 return false; |
357 } | 357 } |
358 | 358 |
359 crypto::ScopedPK11SymKey pk11_key( | 359 crypto::ScopedPK11SymKey pk11_key( |
360 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL)); | 360 PK11_KeyGen(slot.get(), mech, NULL, keylen_bytes, NULL)); |
361 | 361 |
362 if (!pk11_key) { | 362 if (!pk11_key) { |
363 return false; | 363 return false; |
364 } | 364 } |
365 | 365 |
366 *key = WebKit::WebCryptoKey::create( | 366 *key = blink::WebCryptoKey::create( |
367 new SymKeyHandle(pk11_key.Pass()), | 367 new SymKeyHandle(pk11_key.Pass()), |
368 key_type, extractable, algorithm, usage_mask); | 368 key_type, extractable, algorithm, usage_mask); |
369 return true; | 369 return true; |
370 } | 370 } |
371 | 371 |
372 bool WebCryptoImpl::GenerateKeyPairInternal( | 372 bool WebCryptoImpl::GenerateKeyPairInternal( |
373 const WebKit::WebCryptoAlgorithm& algorithm, | 373 const blink::WebCryptoAlgorithm& algorithm, |
374 bool extractable, | 374 bool extractable, |
375 WebKit::WebCryptoKeyUsageMask usage_mask, | 375 blink::WebCryptoKeyUsageMask usage_mask, |
376 WebKit::WebCryptoKey* public_key, | 376 blink::WebCryptoKey* public_key, |
377 WebKit::WebCryptoKey* private_key) { | 377 blink::WebCryptoKey* private_key) { |
378 | 378 |
379 // TODO(padolph): Handle other asymmetric algorithm key generation. | 379 // TODO(padolph): Handle other asymmetric algorithm key generation. |
380 switch (algorithm.id()) { | 380 switch (algorithm.id()) { |
381 case WebKit::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | 381 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
382 case WebKit::WebCryptoAlgorithmIdRsaOaep: | 382 case blink::WebCryptoAlgorithmIdRsaOaep: |
383 case WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: { | 383 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: { |
384 const WebKit::WebCryptoRsaKeyGenParams* const params = | 384 const blink::WebCryptoRsaKeyGenParams* const params = |
385 algorithm.rsaKeyGenParams(); | 385 algorithm.rsaKeyGenParams(); |
386 DCHECK(params); | 386 DCHECK(params); |
387 | 387 |
388 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); | 388 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); |
389 unsigned long public_exponent; | 389 unsigned long public_exponent; |
390 if (!slot || !params->modulusLength() || | 390 if (!slot || !params->modulusLength() || |
391 !BigIntegerToLong(params->publicExponent().data(), | 391 !BigIntegerToLong(params->publicExponent().data(), |
392 params->publicExponent().size(), | 392 params->publicExponent().size(), |
393 &public_exponent) || | 393 &public_exponent) || |
394 !public_exponent) { | 394 !public_exponent) { |
395 return false; | 395 return false; |
396 } | 396 } |
397 | 397 |
398 PK11RSAGenParams rsa_gen_params; | 398 PK11RSAGenParams rsa_gen_params; |
399 rsa_gen_params.keySizeInBits = params->modulusLength(); | 399 rsa_gen_params.keySizeInBits = params->modulusLength(); |
400 rsa_gen_params.pe = public_exponent; | 400 rsa_gen_params.pe = public_exponent; |
401 | 401 |
402 // Flags are verified at the Blink layer; here the flags are set to all | 402 // Flags are verified at the Blink layer; here the flags are set to all |
403 // possible operations for the given key type. | 403 // possible operations for the given key type. |
404 CK_FLAGS operation_flags; | 404 CK_FLAGS operation_flags; |
405 switch (algorithm.id()) { | 405 switch (algorithm.id()) { |
406 case WebKit::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | 406 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
407 case WebKit::WebCryptoAlgorithmIdRsaOaep: | 407 case blink::WebCryptoAlgorithmIdRsaOaep: |
408 operation_flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP; | 408 operation_flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP; |
409 break; | 409 break; |
410 case WebKit::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: | 410 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: |
411 operation_flags = CKF_SIGN | CKF_VERIFY; | 411 operation_flags = CKF_SIGN | CKF_VERIFY; |
412 break; | 412 break; |
413 default: | 413 default: |
414 NOTREACHED(); | 414 NOTREACHED(); |
415 return false; | 415 return false; |
416 } | 416 } |
417 const CK_FLAGS operation_flags_mask = CKF_ENCRYPT | CKF_DECRYPT | | 417 const CK_FLAGS operation_flags_mask = CKF_ENCRYPT | CKF_DECRYPT | |
418 CKF_SIGN | CKF_VERIFY | CKF_WRAP | | 418 CKF_SIGN | CKF_VERIFY | CKF_WRAP | |
419 CKF_UNWRAP; | 419 CKF_UNWRAP; |
420 const PK11AttrFlags attribute_flags = 0; // Default all PK11_ATTR_ flags. | 420 const PK11AttrFlags attribute_flags = 0; // Default all PK11_ATTR_ flags. |
(...skipping 13 matching lines...) Expand all Loading... |
434 if (!private_key) { | 434 if (!private_key) { |
435 return false; | 435 return false; |
436 } | 436 } |
437 | 437 |
438 // One extractable input parameter is provided, and the Web Crypto API | 438 // One extractable input parameter is provided, and the Web Crypto API |
439 // spec at this time says it applies to both members of the key pair. | 439 // spec at this time says it applies to both members of the key pair. |
440 // This is probably not correct: it makes more operational sense to have | 440 // This is probably not correct: it makes more operational sense to have |
441 // extractable apply only to the private key and make the public key | 441 // extractable apply only to the private key and make the public key |
442 // always extractable. For now implement what the spec says and track the | 442 // always extractable. For now implement what the spec says and track the |
443 // spec bug here: https://www.w3.org/Bugs/Public/show_bug.cgi?id=23695 | 443 // spec bug here: https://www.w3.org/Bugs/Public/show_bug.cgi?id=23695 |
444 *public_key = WebKit::WebCryptoKey::create( | 444 *public_key = blink::WebCryptoKey::create( |
445 new PublicKeyHandle(crypto::ScopedSECKEYPublicKey(sec_public_key)), | 445 new PublicKeyHandle(crypto::ScopedSECKEYPublicKey(sec_public_key)), |
446 WebKit::WebCryptoKeyTypePublic, | 446 blink::WebCryptoKeyTypePublic, |
447 extractable, // probably should be 'true' always | 447 extractable, // probably should be 'true' always |
448 algorithm, | 448 algorithm, |
449 usage_mask); | 449 usage_mask); |
450 *private_key = WebKit::WebCryptoKey::create( | 450 *private_key = blink::WebCryptoKey::create( |
451 new PrivateKeyHandle(scoped_sec_private_key.Pass()), | 451 new PrivateKeyHandle(scoped_sec_private_key.Pass()), |
452 WebKit::WebCryptoKeyTypePrivate, | 452 blink::WebCryptoKeyTypePrivate, |
453 extractable, | 453 extractable, |
454 algorithm, | 454 algorithm, |
455 usage_mask); | 455 usage_mask); |
456 | 456 |
457 return true; | 457 return true; |
458 } | 458 } |
459 default: | 459 default: |
460 return false; | 460 return false; |
461 } | 461 } |
462 } | 462 } |
463 | 463 |
464 bool WebCryptoImpl::ImportKeyInternal( | 464 bool WebCryptoImpl::ImportKeyInternal( |
465 WebKit::WebCryptoKeyFormat format, | 465 blink::WebCryptoKeyFormat format, |
466 const unsigned char* key_data, | 466 const unsigned char* key_data, |
467 unsigned key_data_size, | 467 unsigned key_data_size, |
468 const WebKit::WebCryptoAlgorithm& algorithm_or_null, | 468 const blink::WebCryptoAlgorithm& algorithm_or_null, |
469 bool extractable, | 469 bool extractable, |
470 WebKit::WebCryptoKeyUsageMask usage_mask, | 470 blink::WebCryptoKeyUsageMask usage_mask, |
471 WebKit::WebCryptoKey* key) { | 471 blink::WebCryptoKey* key) { |
472 // TODO(eroman): Currently expects algorithm to always be specified, as it is | 472 // TODO(eroman): Currently expects algorithm to always be specified, as it is |
473 // required for raw format. | 473 // required for raw format. |
474 if (algorithm_or_null.isNull()) | 474 if (algorithm_or_null.isNull()) |
475 return false; | 475 return false; |
476 const WebKit::WebCryptoAlgorithm& algorithm = algorithm_or_null; | 476 const blink::WebCryptoAlgorithm& algorithm = algorithm_or_null; |
477 | 477 |
478 WebKit::WebCryptoKeyType type; | 478 blink::WebCryptoKeyType type; |
479 switch (algorithm.id()) { | 479 switch (algorithm.id()) { |
480 case WebKit::WebCryptoAlgorithmIdHmac: | 480 case blink::WebCryptoAlgorithmIdHmac: |
481 case WebKit::WebCryptoAlgorithmIdAesCbc: | 481 case blink::WebCryptoAlgorithmIdAesCbc: |
482 type = WebKit::WebCryptoKeyTypeSecret; | 482 type = blink::WebCryptoKeyTypeSecret; |
483 break; | 483 break; |
484 // TODO(bryaneyler): Support more key types. | 484 // TODO(bryaneyler): Support more key types. |
485 default: | 485 default: |
486 return false; | 486 return false; |
487 } | 487 } |
488 | 488 |
489 // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys. | 489 // TODO(bryaneyler): Need to split handling for symmetric and asymmetric keys. |
490 // Currently only supporting symmetric. | 490 // Currently only supporting symmetric. |
491 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; | 491 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; |
492 // Flags are verified at the Blink layer; here the flags are set to all | 492 // Flags are verified at the Blink layer; here the flags are set to all |
493 // possible operations for this key type. | 493 // possible operations for this key type. |
494 CK_FLAGS flags = 0; | 494 CK_FLAGS flags = 0; |
495 | 495 |
496 switch(algorithm.id()) { | 496 switch(algorithm.id()) { |
497 case WebKit::WebCryptoAlgorithmIdHmac: { | 497 case blink::WebCryptoAlgorithmIdHmac: { |
498 const WebKit::WebCryptoHmacParams* params = algorithm.hmacParams(); | 498 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); |
499 if (!params) { | 499 if (!params) { |
500 return false; | 500 return false; |
501 } | 501 } |
502 | 502 |
503 mechanism = WebCryptoAlgorithmToHMACMechanism(params->hash()); | 503 mechanism = WebCryptoAlgorithmToHMACMechanism(params->hash()); |
504 if (mechanism == CKM_INVALID_MECHANISM) { | 504 if (mechanism == CKM_INVALID_MECHANISM) { |
505 return false; | 505 return false; |
506 } | 506 } |
507 | 507 |
508 flags |= CKF_SIGN | CKF_VERIFY; | 508 flags |= CKF_SIGN | CKF_VERIFY; |
509 | 509 |
510 break; | 510 break; |
511 } | 511 } |
512 case WebKit::WebCryptoAlgorithmIdAesCbc: { | 512 case blink::WebCryptoAlgorithmIdAesCbc: { |
513 mechanism = CKM_AES_CBC; | 513 mechanism = CKM_AES_CBC; |
514 flags |= CKF_ENCRYPT | CKF_DECRYPT; | 514 flags |= CKF_ENCRYPT | CKF_DECRYPT; |
515 break; | 515 break; |
516 } | 516 } |
517 default: | 517 default: |
518 return false; | 518 return false; |
519 } | 519 } |
520 | 520 |
521 DCHECK_NE(CKM_INVALID_MECHANISM, mechanism); | 521 DCHECK_NE(CKM_INVALID_MECHANISM, mechanism); |
522 DCHECK_NE(0ul, flags); | 522 DCHECK_NE(0ul, flags); |
523 | 523 |
524 SECItem key_item = { siBuffer, NULL, 0 }; | 524 SECItem key_item = { siBuffer, NULL, 0 }; |
525 | 525 |
526 switch (format) { | 526 switch (format) { |
527 case WebKit::WebCryptoKeyFormatRaw: | 527 case blink::WebCryptoKeyFormatRaw: |
528 key_item.data = const_cast<unsigned char*>(key_data); | 528 key_item.data = const_cast<unsigned char*>(key_data); |
529 key_item.len = key_data_size; | 529 key_item.len = key_data_size; |
530 break; | 530 break; |
531 // TODO(bryaneyler): Handle additional formats. | 531 // TODO(bryaneyler): Handle additional formats. |
532 default: | 532 default: |
533 return false; | 533 return false; |
534 } | 534 } |
535 | 535 |
536 crypto::ScopedPK11SymKey pk11_sym_key( | 536 crypto::ScopedPK11SymKey pk11_sym_key( |
537 PK11_ImportSymKeyWithFlags(PK11_GetInternalSlot(), | 537 PK11_ImportSymKeyWithFlags(PK11_GetInternalSlot(), |
538 mechanism, | 538 mechanism, |
539 PK11_OriginUnwrap, | 539 PK11_OriginUnwrap, |
540 CKA_FLAGS_ONLY, | 540 CKA_FLAGS_ONLY, |
541 &key_item, | 541 &key_item, |
542 flags, | 542 flags, |
543 false, | 543 false, |
544 NULL)); | 544 NULL)); |
545 if (!pk11_sym_key.get()) { | 545 if (!pk11_sym_key.get()) { |
546 return false; | 546 return false; |
547 } | 547 } |
548 | 548 |
549 *key = WebKit::WebCryptoKey::create(new SymKeyHandle(pk11_sym_key.Pass()), | 549 *key = blink::WebCryptoKey::create(new SymKeyHandle(pk11_sym_key.Pass()), |
550 type, extractable, algorithm, usage_mask); | 550 type, extractable, algorithm, usage_mask); |
551 return true; | 551 return true; |
552 } | 552 } |
553 | 553 |
554 bool WebCryptoImpl::SignInternal( | 554 bool WebCryptoImpl::SignInternal( |
555 const WebKit::WebCryptoAlgorithm& algorithm, | 555 const blink::WebCryptoAlgorithm& algorithm, |
556 const WebKit::WebCryptoKey& key, | 556 const blink::WebCryptoKey& key, |
557 const unsigned char* data, | 557 const unsigned char* data, |
558 unsigned data_size, | 558 unsigned data_size, |
559 WebKit::WebArrayBuffer* buffer) { | 559 blink::WebArrayBuffer* buffer) { |
560 WebKit::WebArrayBuffer result; | 560 blink::WebArrayBuffer result; |
561 | 561 |
562 switch (algorithm.id()) { | 562 switch (algorithm.id()) { |
563 case WebKit::WebCryptoAlgorithmIdHmac: { | 563 case blink::WebCryptoAlgorithmIdHmac: { |
564 const WebKit::WebCryptoHmacParams* params = algorithm.hmacParams(); | 564 const blink::WebCryptoHmacParams* params = algorithm.hmacParams(); |
565 if (!params) { | 565 if (!params) { |
566 return false; | 566 return false; |
567 } | 567 } |
568 | 568 |
569 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); | 569 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); |
570 | 570 |
571 DCHECK_EQ(PK11_GetMechanism(sym_key->key()), | 571 DCHECK_EQ(PK11_GetMechanism(sym_key->key()), |
572 WebCryptoAlgorithmToHMACMechanism(params->hash())); | 572 WebCryptoAlgorithmToHMACMechanism(params->hash())); |
573 DCHECK_NE(0, key.usages() & WebKit::WebCryptoKeyUsageSign); | 573 DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign); |
574 | 574 |
575 SECItem param_item = { siBuffer, NULL, 0 }; | 575 SECItem param_item = { siBuffer, NULL, 0 }; |
576 SECItem data_item = { | 576 SECItem data_item = { |
577 siBuffer, | 577 siBuffer, |
578 const_cast<unsigned char*>(data), | 578 const_cast<unsigned char*>(data), |
579 data_size | 579 data_size |
580 }; | 580 }; |
581 // First call is to figure out the length. | 581 // First call is to figure out the length. |
582 SECItem signature_item = { siBuffer, NULL, 0 }; | 582 SECItem signature_item = { siBuffer, NULL, 0 }; |
583 | 583 |
584 if (PK11_SignWithSymKey(sym_key->key(), | 584 if (PK11_SignWithSymKey(sym_key->key(), |
585 PK11_GetMechanism(sym_key->key()), | 585 PK11_GetMechanism(sym_key->key()), |
586 ¶m_item, | 586 ¶m_item, |
587 &signature_item, | 587 &signature_item, |
588 &data_item) != SECSuccess) { | 588 &data_item) != SECSuccess) { |
589 NOTREACHED(); | 589 NOTREACHED(); |
590 return false; | 590 return false; |
591 } | 591 } |
592 | 592 |
593 DCHECK_NE(0u, signature_item.len); | 593 DCHECK_NE(0u, signature_item.len); |
594 | 594 |
595 result = WebKit::WebArrayBuffer::create(signature_item.len, 1); | 595 result = blink::WebArrayBuffer::create(signature_item.len, 1); |
596 signature_item.data = reinterpret_cast<unsigned char*>(result.data()); | 596 signature_item.data = reinterpret_cast<unsigned char*>(result.data()); |
597 | 597 |
598 if (PK11_SignWithSymKey(sym_key->key(), | 598 if (PK11_SignWithSymKey(sym_key->key(), |
599 PK11_GetMechanism(sym_key->key()), | 599 PK11_GetMechanism(sym_key->key()), |
600 ¶m_item, | 600 ¶m_item, |
601 &signature_item, | 601 &signature_item, |
602 &data_item) != SECSuccess) { | 602 &data_item) != SECSuccess) { |
603 NOTREACHED(); | 603 NOTREACHED(); |
604 return false; | 604 return false; |
605 } | 605 } |
606 | 606 |
607 DCHECK_EQ(result.byteLength(), signature_item.len); | 607 DCHECK_EQ(result.byteLength(), signature_item.len); |
608 | 608 |
609 break; | 609 break; |
610 } | 610 } |
611 default: | 611 default: |
612 return false; | 612 return false; |
613 } | 613 } |
614 | 614 |
615 *buffer = result; | 615 *buffer = result; |
616 return true; | 616 return true; |
617 } | 617 } |
618 | 618 |
619 bool WebCryptoImpl::VerifySignatureInternal( | 619 bool WebCryptoImpl::VerifySignatureInternal( |
620 const WebKit::WebCryptoAlgorithm& algorithm, | 620 const blink::WebCryptoAlgorithm& algorithm, |
621 const WebKit::WebCryptoKey& key, | 621 const blink::WebCryptoKey& key, |
622 const unsigned char* signature, | 622 const unsigned char* signature, |
623 unsigned signature_size, | 623 unsigned signature_size, |
624 const unsigned char* data, | 624 const unsigned char* data, |
625 unsigned data_size, | 625 unsigned data_size, |
626 bool* signature_match) { | 626 bool* signature_match) { |
627 switch (algorithm.id()) { | 627 switch (algorithm.id()) { |
628 case WebKit::WebCryptoAlgorithmIdHmac: { | 628 case blink::WebCryptoAlgorithmIdHmac: { |
629 WebKit::WebArrayBuffer result; | 629 blink::WebArrayBuffer result; |
630 if (!SignInternal(algorithm, key, data, data_size, &result)) { | 630 if (!SignInternal(algorithm, key, data, data_size, &result)) { |
631 return false; | 631 return false; |
632 } | 632 } |
633 | 633 |
634 // Handling of truncated signatures is underspecified in the WebCrypto | 634 // Handling of truncated signatures is underspecified in the WebCrypto |
635 // spec, so here we fail verification if a truncated signature is being | 635 // spec, so here we fail verification if a truncated signature is being |
636 // verified. | 636 // verified. |
637 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 | 637 // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 |
638 *signature_match = | 638 *signature_match = |
639 result.byteLength() == signature_size && | 639 result.byteLength() == signature_size && |
640 crypto::SecureMemEqual(result.data(), signature, signature_size); | 640 crypto::SecureMemEqual(result.data(), signature, signature_size); |
641 | 641 |
642 break; | 642 break; |
643 } | 643 } |
644 default: | 644 default: |
645 return false; | 645 return false; |
646 } | 646 } |
647 | 647 |
648 return true; | 648 return true; |
649 } | 649 } |
650 | 650 |
651 } // namespace content | 651 } // namespace content |
OLD | NEW |