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

Side by Side Diff: content/child/webcrypto/shared_crypto.cc

Issue 233733004: [webcrypto] Make operations run on worker threads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix a crash (RSA-OAEP keys not supported) Created 6 years, 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/child/webcrypto/shared_crypto.h" 5 #include "content/child/webcrypto/shared_crypto.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "content/child/webcrypto/crypto_data.h" 8 #include "content/child/webcrypto/crypto_data.h"
9 #include "content/child/webcrypto/jwk.h" 9 #include "content/child/webcrypto/jwk.h"
10 #include "content/child/webcrypto/platform_crypto.h" 10 #include "content/child/webcrypto/platform_crypto.h"
11 #include "content/child/webcrypto/status.h" 11 #include "content/child/webcrypto/status.h"
12 #include "content/child/webcrypto/webcrypto_util.h" 12 #include "content/child/webcrypto/webcrypto_util.h"
13 #include "crypto/secure_util.h" 13 #include "crypto/secure_util.h"
14 #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" 15 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
16 #include "third_party/WebKit/public/platform/WebCryptoKey.h" 16 #include "third_party/WebKit/public/platform/WebCryptoKey.h"
17 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" 17 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
18 18
19 namespace content { 19 namespace content {
20 20
21 namespace webcrypto { 21 namespace webcrypto {
22 22
23 // ------------
24 // Threading:
25 // ------------
26 //
27 // All functions in this file are called from the webcrypto worker pool except
28 // for:
29 //
30 // * SerializeKeyForClone()
31 // * DeserializeKeyForClone()
32 // * ImportKey() // TODO(eroman): Change this.
33
23 namespace { 34 namespace {
24 35
25 // TODO(eroman): Move this helper to WebCryptoKey. 36 // TODO(eroman): Move this helper to WebCryptoKey.
26 bool KeyUsageAllows(const blink::WebCryptoKey& key, 37 bool KeyUsageAllows(const blink::WebCryptoKey& key,
27 const blink::WebCryptoKeyUsage usage) { 38 const blink::WebCryptoKeyUsage usage) {
28 return ((key.usages() & usage) != 0); 39 return ((key.usages() & usage) != 0);
29 } 40 }
30 41
31 bool IsValidAesKeyLengthBits(unsigned int length_bits) { 42 bool IsValidAesKeyLengthBits(unsigned int length_bits) {
32 return length_bits == 128 || length_bits == 192 || length_bits == 256; 43 return length_bits == 128 || length_bits == 192 || length_bits == 256;
(...skipping 26 matching lines...) Expand all
59 return Status::ErrorUnexpectedKeyType(); 70 return Status::ErrorUnexpectedKeyType();
60 return Status::Success(); 71 return Status::Success();
61 } 72 }
62 73
63 const size_t kAesBlockSizeBytes = 16; 74 const size_t kAesBlockSizeBytes = 16;
64 75
65 Status EncryptDecryptAesCbc(EncryptOrDecrypt mode, 76 Status EncryptDecryptAesCbc(EncryptOrDecrypt mode,
66 const blink::WebCryptoAlgorithm& algorithm, 77 const blink::WebCryptoAlgorithm& algorithm,
67 const blink::WebCryptoKey& key, 78 const blink::WebCryptoKey& key,
68 const CryptoData& data, 79 const CryptoData& data,
69 blink::WebArrayBuffer* buffer) { 80 std::vector<uint8>* buffer) {
70 platform::SymKey* sym_key; 81 platform::SymKey* sym_key;
71 Status status = ToPlatformSymKey(key, &sym_key); 82 Status status = ToPlatformSymKey(key, &sym_key);
72 if (status.IsError()) 83 if (status.IsError())
73 return status; 84 return status;
74 85
75 const blink::WebCryptoAesCbcParams* params = algorithm.aesCbcParams(); 86 const blink::WebCryptoAesCbcParams* params = algorithm.aesCbcParams();
76 if (!params) 87 if (!params)
77 return Status::ErrorUnexpected(); 88 return Status::ErrorUnexpected();
78 89
79 CryptoData iv(params->iv().data(), params->iv().size()); 90 CryptoData iv(params->iv().data(), params->iv().size());
80 if (iv.byte_length() != kAesBlockSizeBytes) 91 if (iv.byte_length() != kAesBlockSizeBytes)
81 return Status::ErrorIncorrectSizeAesCbcIv(); 92 return Status::ErrorIncorrectSizeAesCbcIv();
82 93
83 return platform::EncryptDecryptAesCbc(mode, sym_key, data, iv, buffer); 94 return platform::EncryptDecryptAesCbc(mode, sym_key, data, iv, buffer);
84 } 95 }
85 96
86 Status EncryptDecryptAesGcm(EncryptOrDecrypt mode, 97 Status EncryptDecryptAesGcm(EncryptOrDecrypt mode,
87 const blink::WebCryptoAlgorithm& algorithm, 98 const blink::WebCryptoAlgorithm& algorithm,
88 const blink::WebCryptoKey& key, 99 const blink::WebCryptoKey& key,
89 const CryptoData& data, 100 const CryptoData& data,
90 blink::WebArrayBuffer* buffer) { 101 std::vector<uint8>* buffer) {
91 platform::SymKey* sym_key; 102 platform::SymKey* sym_key;
92 Status status = ToPlatformSymKey(key, &sym_key); 103 Status status = ToPlatformSymKey(key, &sym_key);
93 if (status.IsError()) 104 if (status.IsError())
94 return status; 105 return status;
95 106
96 const blink::WebCryptoAesGcmParams* params = algorithm.aesGcmParams(); 107 const blink::WebCryptoAesGcmParams* params = algorithm.aesGcmParams();
97 if (!params) 108 if (!params)
98 return Status::ErrorUnexpected(); 109 return Status::ErrorUnexpected();
99 110
100 unsigned int tag_length_bits = 128; 111 unsigned int tag_length_bits = 128;
(...skipping 11 matching lines...) Expand all
112 data, 123 data,
113 CryptoData(params->iv()), 124 CryptoData(params->iv()),
114 CryptoData(params->optionalAdditionalData()), 125 CryptoData(params->optionalAdditionalData()),
115 tag_length_bits, 126 tag_length_bits,
116 buffer); 127 buffer);
117 } 128 }
118 129
119 Status EncryptRsaEsPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm, 130 Status EncryptRsaEsPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm,
120 const blink::WebCryptoKey& key, 131 const blink::WebCryptoKey& key,
121 const CryptoData& data, 132 const CryptoData& data,
122 blink::WebArrayBuffer* buffer) { 133 std::vector<uint8>* buffer) {
123 platform::PublicKey* public_key; 134 platform::PublicKey* public_key;
124 Status status = ToPlatformPublicKey(key, &public_key); 135 Status status = ToPlatformPublicKey(key, &public_key);
125 if (status.IsError()) 136 if (status.IsError())
126 return status; 137 return status;
127 138
128 // RSAES encryption does not support empty input 139 // RSAES encryption does not support empty input
129 if (!data.byte_length()) 140 if (!data.byte_length())
130 return Status::Error(); 141 return Status::Error();
131 142
132 return platform::EncryptRsaEsPkcs1v1_5(public_key, data, buffer); 143 return platform::EncryptRsaEsPkcs1v1_5(public_key, data, buffer);
133 } 144 }
134 145
135 Status DecryptRsaEsPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm, 146 Status DecryptRsaEsPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm,
136 const blink::WebCryptoKey& key, 147 const blink::WebCryptoKey& key,
137 const CryptoData& data, 148 const CryptoData& data,
138 blink::WebArrayBuffer* buffer) { 149 std::vector<uint8>* buffer) {
139 platform::PrivateKey* private_key; 150 platform::PrivateKey* private_key;
140 Status status = ToPlatformPrivateKey(key, &private_key); 151 Status status = ToPlatformPrivateKey(key, &private_key);
141 if (status.IsError()) 152 if (status.IsError())
142 return status; 153 return status;
143 154
144 // RSAES decryption does not support empty input 155 // RSAES decryption does not support empty input
145 if (!data.byte_length()) 156 if (!data.byte_length())
146 return Status::Error(); 157 return Status::Error();
147 158
148 return platform::DecryptRsaEsPkcs1v1_5(private_key, data, buffer); 159 return platform::DecryptRsaEsPkcs1v1_5(private_key, data, buffer);
149 } 160 }
150 161
151 Status SignHmac(const blink::WebCryptoAlgorithm& algorithm, 162 Status SignHmac(const blink::WebCryptoAlgorithm& algorithm,
152 const blink::WebCryptoKey& key, 163 const blink::WebCryptoKey& key,
153 const CryptoData& data, 164 const CryptoData& data,
154 blink::WebArrayBuffer* buffer) { 165 std::vector<uint8>* buffer) {
155 platform::SymKey* sym_key; 166 platform::SymKey* sym_key;
156 Status status = ToPlatformSymKey(key, &sym_key); 167 Status status = ToPlatformSymKey(key, &sym_key);
157 if (status.IsError()) 168 if (status.IsError())
158 return status; 169 return status;
159 170
160 return platform::SignHmac( 171 return platform::SignHmac(
161 sym_key, key.algorithm().hmacParams()->hash(), data, buffer); 172 sym_key, key.algorithm().hmacParams()->hash(), data, buffer);
162 } 173 }
163 174
164 Status VerifyHmac(const blink::WebCryptoAlgorithm& algorithm, 175 Status VerifyHmac(const blink::WebCryptoAlgorithm& algorithm,
165 const blink::WebCryptoKey& key, 176 const blink::WebCryptoKey& key,
166 const CryptoData& signature, 177 const CryptoData& signature,
167 const CryptoData& data, 178 const CryptoData& data,
168 bool* signature_match) { 179 bool* signature_match) {
169 blink::WebArrayBuffer result; 180 std::vector<uint8> result;
170 Status status = SignHmac(algorithm, key, data, &result); 181 Status status = SignHmac(algorithm, key, data, &result);
171 if (status.IsError()) 182 if (status.IsError())
172 return status; 183 return status;
173 184
174 // Do not allow verification of truncated MACs. 185 // Do not allow verification of truncated MACs.
175 *signature_match = 186 *signature_match =
176 result.byteLength() == signature.byte_length() && 187 result.size() == signature.byte_length() &&
177 crypto::SecureMemEqual( 188 crypto::SecureMemEqual(
178 result.data(), signature.bytes(), signature.byte_length()); 189 Uint8VectorStart(result), signature.bytes(), signature.byte_length());
179 190
180 return Status::Success(); 191 return Status::Success();
181 } 192 }
182 193
183 Status SignRsaSsaPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm, 194 Status SignRsaSsaPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm,
184 const blink::WebCryptoKey& key, 195 const blink::WebCryptoKey& key,
185 const CryptoData& data, 196 const CryptoData& data,
186 blink::WebArrayBuffer* buffer) { 197 std::vector<uint8>* buffer) {
187 platform::PrivateKey* private_key; 198 platform::PrivateKey* private_key;
188 Status status = ToPlatformPrivateKey(key, &private_key); 199 Status status = ToPlatformPrivateKey(key, &private_key);
189 if (status.IsError()) 200 if (status.IsError())
190 return status; 201 return status;
191 202
192 return platform::SignRsaSsaPkcs1v1_5( 203 return platform::SignRsaSsaPkcs1v1_5(
193 private_key, key.algorithm().rsaHashedParams()->hash(), data, buffer); 204 private_key, key.algorithm().rsaHashedParams()->hash(), data, buffer);
194 } 205 }
195 206
196 Status VerifyRsaSsaPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm, 207 Status VerifyRsaSsaPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm,
197 const blink::WebCryptoKey& key, 208 const blink::WebCryptoKey& key,
198 const CryptoData& signature, 209 const CryptoData& signature,
199 const CryptoData& data, 210 const CryptoData& data,
200 bool* signature_match) { 211 bool* signature_match) {
201 platform::PublicKey* public_key; 212 platform::PublicKey* public_key;
202 Status status = ToPlatformPublicKey(key, &public_key); 213 Status status = ToPlatformPublicKey(key, &public_key);
203 if (status.IsError()) 214 if (status.IsError())
204 return status; 215 return status;
205 216
206 return platform::VerifyRsaSsaPkcs1v1_5( 217 return platform::VerifyRsaSsaPkcs1v1_5(
207 public_key, 218 public_key,
208 key.algorithm().rsaHashedParams()->hash(), 219 key.algorithm().rsaHashedParams()->hash(),
209 signature, 220 signature,
210 data, 221 data,
211 signature_match); 222 signature_match);
212 } 223 }
213 224
225 // Note that this function may be called from the target Blink thread.
214 Status ImportKeyRaw(const CryptoData& key_data, 226 Status ImportKeyRaw(const CryptoData& key_data,
215 const blink::WebCryptoAlgorithm& algorithm, 227 const blink::WebCryptoAlgorithm& algorithm,
216 bool extractable, 228 bool extractable,
217 blink::WebCryptoKeyUsageMask usage_mask, 229 blink::WebCryptoKeyUsageMask usage_mask,
218 blink::WebCryptoKey* key) { 230 blink::WebCryptoKey* key) {
219 switch (algorithm.id()) { 231 switch (algorithm.id()) {
220 case blink::WebCryptoAlgorithmIdAesCtr: 232 case blink::WebCryptoAlgorithmIdAesCtr:
221 case blink::WebCryptoAlgorithmIdAesCbc: 233 case blink::WebCryptoAlgorithmIdAesCbc:
222 case blink::WebCryptoAlgorithmIdAesGcm: 234 case blink::WebCryptoAlgorithmIdAesGcm:
223 case blink::WebCryptoAlgorithmIdAesKw: 235 case blink::WebCryptoAlgorithmIdAesKw:
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 return blink::WebCryptoAlgorithm::createNull(); 278 return blink::WebCryptoAlgorithm::createNull();
267 } 279 }
268 280
269 // There is some duplicated information in the serialized format used by 281 // There is some duplicated information in the serialized format used by
270 // structured clone (since the KeyAlgorithm is serialized separately from the 282 // structured clone (since the KeyAlgorithm is serialized separately from the
271 // key data). Use this extra information to further validate what was 283 // key data). Use this extra information to further validate what was
272 // deserialized from the key data. 284 // deserialized from the key data.
273 // 285 //
274 // A failure here implies either a bug in the code, or that the serialized data 286 // A failure here implies either a bug in the code, or that the serialized data
275 // was corrupted. 287 // was corrupted.
276 Status ValidateDeserializedKey(const blink::WebCryptoKey& key, 288 bool ValidateDeserializedKey(const blink::WebCryptoKey& key,
277 const blink::WebCryptoKeyAlgorithm& algorithm, 289 const blink::WebCryptoKeyAlgorithm& algorithm,
278 blink::WebCryptoKeyType type) { 290 blink::WebCryptoKeyType type) {
279 if (algorithm.id() != key.algorithm().id()) 291 if (algorithm.id() != key.algorithm().id())
280 return Status::ErrorUnexpected(); 292 return false;
281 293
282 if (key.type() != type) 294 if (key.type() != type)
283 return Status::ErrorUnexpected(); 295 return false;
284 296
285 switch (algorithm.paramsType()) { 297 switch (algorithm.paramsType()) {
286 case blink::WebCryptoKeyAlgorithmParamsTypeAes: 298 case blink::WebCryptoKeyAlgorithmParamsTypeAes:
287 if (algorithm.aesParams()->lengthBits() != 299 if (algorithm.aesParams()->lengthBits() !=
288 key.algorithm().aesParams()->lengthBits()) 300 key.algorithm().aesParams()->lengthBits())
289 return Status::ErrorUnexpected(); 301 return false;
290 break; 302 break;
291 case blink::WebCryptoKeyAlgorithmParamsTypeRsa: 303 case blink::WebCryptoKeyAlgorithmParamsTypeRsa:
292 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: 304 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
293 if (algorithm.rsaParams()->modulusLengthBits() != 305 if (algorithm.rsaParams()->modulusLengthBits() !=
294 key.algorithm().rsaParams()->modulusLengthBits()) 306 key.algorithm().rsaParams()->modulusLengthBits())
295 return Status::ErrorUnexpected(); 307 return false;
296 if (algorithm.rsaParams()->publicExponent().size() != 308 if (algorithm.rsaParams()->publicExponent().size() !=
297 key.algorithm().rsaParams()->publicExponent().size()) 309 key.algorithm().rsaParams()->publicExponent().size())
298 return Status::ErrorUnexpected(); 310 return false;
299 if (memcmp(algorithm.rsaParams()->publicExponent().data(), 311 if (memcmp(algorithm.rsaParams()->publicExponent().data(),
300 key.algorithm().rsaParams()->publicExponent().data(), 312 key.algorithm().rsaParams()->publicExponent().data(),
301 key.algorithm().rsaParams()->publicExponent().size()) != 0) 313 key.algorithm().rsaParams()->publicExponent().size()) != 0)
302 return Status::ErrorUnexpected(); 314 return false;
303 break; 315 break;
304 case blink::WebCryptoKeyAlgorithmParamsTypeNone: 316 case blink::WebCryptoKeyAlgorithmParamsTypeNone:
305 case blink::WebCryptoKeyAlgorithmParamsTypeHmac: 317 case blink::WebCryptoKeyAlgorithmParamsTypeHmac:
306 break; 318 break;
307 } 319 }
308 320
309 return Status::Success(); 321 return true;
310 } 322 }
311 323
312 // Validates the size of data input to AES-KW. AES-KW requires the input data 324 // Validates the size of data input to AES-KW. AES-KW requires the input data
313 // size to be at least 24 bytes and a multiple of 8 bytes. 325 // size to be at least 24 bytes and a multiple of 8 bytes.
314 Status CheckAesKwInputSize(const CryptoData& aeskw_input_data) { 326 Status CheckAesKwInputSize(const CryptoData& aeskw_input_data) {
315 if (aeskw_input_data.byte_length() < 24) 327 if (aeskw_input_data.byte_length() < 24)
316 return Status::ErrorDataTooSmall(); 328 return Status::ErrorDataTooSmall();
317 if (aeskw_input_data.byte_length() % 8) 329 if (aeskw_input_data.byte_length() % 8)
318 return Status::ErrorInvalidAesKwDataLength(); 330 return Status::ErrorInvalidAesKwDataLength();
319 return Status::Success(); 331 return Status::Success();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 key); 371 key);
360 } 372 }
361 default: 373 default:
362 return Status::ErrorUnsupported(); 374 return Status::ErrorUnsupported();
363 } 375 }
364 } 376 }
365 377
366 Status WrapKeyRaw(const blink::WebCryptoKey& wrapping_key, 378 Status WrapKeyRaw(const blink::WebCryptoKey& wrapping_key,
367 const blink::WebCryptoKey& key_to_wrap, 379 const blink::WebCryptoKey& key_to_wrap,
368 const blink::WebCryptoAlgorithm& wrapping_algorithm, 380 const blink::WebCryptoAlgorithm& wrapping_algorithm,
369 blink::WebArrayBuffer* buffer) { 381 std::vector<uint8>* buffer) {
370 // A raw key is always a symmetric key. 382 // A raw key is always a symmetric key.
371 platform::SymKey* platform_key; 383 platform::SymKey* platform_key;
372 Status status = ToPlatformSymKey(key_to_wrap, &platform_key); 384 Status status = ToPlatformSymKey(key_to_wrap, &platform_key);
373 if (status.IsError()) 385 if (status.IsError())
374 return status; 386 return status;
375 387
376 // TODO(padolph): Handle other wrapping algorithms 388 // TODO(padolph): Handle other wrapping algorithms
377 switch (wrapping_algorithm.id()) { 389 switch (wrapping_algorithm.id()) {
378 case blink::WebCryptoAlgorithmIdAesKw: { 390 case blink::WebCryptoAlgorithmIdAesKw: {
379 platform::SymKey* platform_wrapping_key; 391 platform::SymKey* platform_wrapping_key;
(...skipping 12 matching lines...) Expand all
392 platform_wrapping_key, platform_key, buffer); 404 platform_wrapping_key, platform_key, buffer);
393 } 405 }
394 default: 406 default:
395 return Status::ErrorUnsupported(); 407 return Status::ErrorUnsupported();
396 } 408 }
397 } 409 }
398 410
399 Status DecryptAesKw(const blink::WebCryptoAlgorithm& algorithm, 411 Status DecryptAesKw(const blink::WebCryptoAlgorithm& algorithm,
400 const blink::WebCryptoKey& key, 412 const blink::WebCryptoKey& key,
401 const CryptoData& data, 413 const CryptoData& data,
402 blink::WebArrayBuffer* buffer) { 414 std::vector<uint8>* buffer) {
403 platform::SymKey* sym_key; 415 platform::SymKey* sym_key;
404 Status status = ToPlatformSymKey(key, &sym_key); 416 Status status = ToPlatformSymKey(key, &sym_key);
405 if (status.IsError()) 417 if (status.IsError())
406 return status; 418 return status;
407 status = CheckAesKwInputSize(data); 419 status = CheckAesKwInputSize(data);
408 if (status.IsError()) 420 if (status.IsError())
409 return status; 421 return status;
410 return platform::DecryptAesKw(sym_key, data, buffer); 422 return platform::DecryptAesKw(sym_key, data, buffer);
411 } 423 }
412 424
413 Status DecryptDontCheckKeyUsage(const blink::WebCryptoAlgorithm& algorithm, 425 Status DecryptDontCheckKeyUsage(const blink::WebCryptoAlgorithm& algorithm,
414 const blink::WebCryptoKey& key, 426 const blink::WebCryptoKey& key,
415 const CryptoData& data, 427 const CryptoData& data,
416 blink::WebArrayBuffer* buffer) { 428 std::vector<uint8>* buffer) {
417 if (algorithm.id() != key.algorithm().id()) 429 if (algorithm.id() != key.algorithm().id())
418 return Status::ErrorUnexpected(); 430 return Status::ErrorUnexpected();
419 switch (algorithm.id()) { 431 switch (algorithm.id()) {
420 case blink::WebCryptoAlgorithmIdAesCbc: 432 case blink::WebCryptoAlgorithmIdAesCbc:
421 return EncryptDecryptAesCbc(DECRYPT, algorithm, key, data, buffer); 433 return EncryptDecryptAesCbc(DECRYPT, algorithm, key, data, buffer);
422 case blink::WebCryptoAlgorithmIdAesGcm: 434 case blink::WebCryptoAlgorithmIdAesGcm:
423 return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer); 435 return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer);
424 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: 436 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
425 return DecryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); 437 return DecryptRsaEsPkcs1v1_5(algorithm, key, data, buffer);
426 case blink::WebCryptoAlgorithmIdAesKw: 438 case blink::WebCryptoAlgorithmIdAesKw:
427 return DecryptAesKw(algorithm, key, data, buffer); 439 return DecryptAesKw(algorithm, key, data, buffer);
428 default: 440 default:
429 return Status::ErrorUnsupported(); 441 return Status::ErrorUnsupported();
430 } 442 }
431 } 443 }
432 444
433 Status EncryptDontCheckUsage(const blink::WebCryptoAlgorithm& algorithm, 445 Status EncryptDontCheckUsage(const blink::WebCryptoAlgorithm& algorithm,
434 const blink::WebCryptoKey& key, 446 const blink::WebCryptoKey& key,
435 const CryptoData& data, 447 const CryptoData& data,
436 blink::WebArrayBuffer* buffer) { 448 std::vector<uint8>* buffer) {
437 if (algorithm.id() != key.algorithm().id()) 449 if (algorithm.id() != key.algorithm().id())
438 return Status::ErrorUnexpected(); 450 return Status::ErrorUnexpected();
439 switch (algorithm.id()) { 451 switch (algorithm.id()) {
440 case blink::WebCryptoAlgorithmIdAesCbc: 452 case blink::WebCryptoAlgorithmIdAesCbc:
441 return EncryptDecryptAesCbc(ENCRYPT, algorithm, key, data, buffer); 453 return EncryptDecryptAesCbc(ENCRYPT, algorithm, key, data, buffer);
442 case blink::WebCryptoAlgorithmIdAesGcm: 454 case blink::WebCryptoAlgorithmIdAesGcm:
443 return EncryptDecryptAesGcm(ENCRYPT, algorithm, key, data, buffer); 455 return EncryptDecryptAesGcm(ENCRYPT, algorithm, key, data, buffer);
444 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: 456 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
445 return EncryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); 457 return EncryptRsaEsPkcs1v1_5(algorithm, key, data, buffer);
446 default: 458 default:
447 return Status::ErrorUnsupported(); 459 return Status::ErrorUnsupported();
448 } 460 }
449 } 461 }
450 462
451 Status UnwrapKeyDecryptAndImport( 463 Status UnwrapKeyDecryptAndImport(
452 blink::WebCryptoKeyFormat format, 464 blink::WebCryptoKeyFormat format,
453 const CryptoData& wrapped_key_data, 465 const CryptoData& wrapped_key_data,
454 const blink::WebCryptoKey& wrapping_key, 466 const blink::WebCryptoKey& wrapping_key,
455 const blink::WebCryptoAlgorithm& wrapping_algorithm, 467 const blink::WebCryptoAlgorithm& wrapping_algorithm,
456 const blink::WebCryptoAlgorithm& algorithm, 468 const blink::WebCryptoAlgorithm& algorithm,
457 bool extractable, 469 bool extractable,
458 blink::WebCryptoKeyUsageMask usage_mask, 470 blink::WebCryptoKeyUsageMask usage_mask,
459 blink::WebCryptoKey* key) { 471 blink::WebCryptoKey* key) {
460 blink::WebArrayBuffer buffer; 472 std::vector<uint8> buffer;
461 Status status = DecryptDontCheckKeyUsage( 473 Status status = DecryptDontCheckKeyUsage(
462 wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer); 474 wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer);
463 if (status.IsError()) 475 if (status.IsError())
464 return status; 476 return status;
465 status = ImportKey( 477 status = ImportKey(
466 format, CryptoData(buffer), algorithm, extractable, usage_mask, key); 478 format, CryptoData(buffer), algorithm, extractable, usage_mask, key);
467 // NOTE! Returning the details of any ImportKey() failure here would leak 479 // NOTE! Returning the details of any ImportKey() failure here would leak
468 // information about the plaintext internals of the encrypted key. Instead, 480 // information about the plaintext internals of the encrypted key. Instead,
469 // collapse any error into the generic Status::Error(). 481 // collapse any error into the generic Status::Error().
470 return status.IsError() ? Status::Error() : Status::Success(); 482 return status.IsError() ? Status::Error() : Status::Success();
471 } 483 }
472 484
473 Status WrapKeyExportAndEncrypt( 485 Status WrapKeyExportAndEncrypt(
474 blink::WebCryptoKeyFormat format, 486 blink::WebCryptoKeyFormat format,
475 const blink::WebCryptoKey& wrapping_key, 487 const blink::WebCryptoKey& wrapping_key,
476 const blink::WebCryptoKey& key_to_wrap, 488 const blink::WebCryptoKey& key_to_wrap,
477 const blink::WebCryptoAlgorithm& wrapping_algorithm, 489 const blink::WebCryptoAlgorithm& wrapping_algorithm,
478 blink::WebArrayBuffer* buffer) { 490 std::vector<uint8>* buffer) {
479 blink::WebArrayBuffer exported_data; 491 std::vector<uint8> exported_data;
480 Status status = ExportKey(format, key_to_wrap, &exported_data); 492 Status status = ExportKey(format, key_to_wrap, &exported_data);
481 if (status.IsError()) 493 if (status.IsError())
482 return status; 494 return status;
483 return EncryptDontCheckUsage( 495 return EncryptDontCheckUsage(
484 wrapping_algorithm, wrapping_key, CryptoData(exported_data), buffer); 496 wrapping_algorithm, wrapping_key, CryptoData(exported_data), buffer);
485 } 497 }
486 498
487 // Returns the internal block size for SHA-* 499 // Returns the internal block size for SHA-*
488 unsigned int ShaBlockSizeBytes(blink::WebCryptoAlgorithmId hash_id) { 500 unsigned int ShaBlockSizeBytes(blink::WebCryptoAlgorithmId hash_id) {
489 switch (hash_id) { 501 switch (hash_id) {
490 case blink::WebCryptoAlgorithmIdSha1: 502 case blink::WebCryptoAlgorithmIdSha1:
491 case blink::WebCryptoAlgorithmIdSha256: 503 case blink::WebCryptoAlgorithmIdSha256:
492 return 64; 504 return 64;
493 case blink::WebCryptoAlgorithmIdSha384: 505 case blink::WebCryptoAlgorithmIdSha384:
494 case blink::WebCryptoAlgorithmIdSha512: 506 case blink::WebCryptoAlgorithmIdSha512:
495 return 128; 507 return 128;
496 default: 508 default:
497 NOTREACHED(); 509 NOTREACHED();
498 return 0; 510 return 0;
499 } 511 }
500 } 512 }
501 513
502 } // namespace 514 } // namespace
503 515
504 void Init() { platform::Init(); } 516 void Init() { platform::Init(); }
505 517
506 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, 518 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
507 const blink::WebCryptoKey& key, 519 const blink::WebCryptoKey& key,
508 const CryptoData& data, 520 const CryptoData& data,
509 blink::WebArrayBuffer* buffer) { 521 std::vector<uint8>* buffer) {
510 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt)) 522 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt))
511 return Status::ErrorUnexpected(); 523 return Status::ErrorUnexpected();
512 return EncryptDontCheckUsage(algorithm, key, data, buffer); 524 return EncryptDontCheckUsage(algorithm, key, data, buffer);
513 } 525 }
514 526
515 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, 527 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
516 const blink::WebCryptoKey& key, 528 const blink::WebCryptoKey& key,
517 const CryptoData& data, 529 const CryptoData& data,
518 blink::WebArrayBuffer* buffer) { 530 std::vector<uint8>* buffer) {
519 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt)) 531 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt))
520 return Status::ErrorUnexpected(); 532 return Status::ErrorUnexpected();
521 return DecryptDontCheckKeyUsage(algorithm, key, data, buffer); 533 return DecryptDontCheckKeyUsage(algorithm, key, data, buffer);
522 } 534 }
523 535
524 Status Digest(const blink::WebCryptoAlgorithm& algorithm, 536 Status Digest(const blink::WebCryptoAlgorithm& algorithm,
525 const CryptoData& data, 537 const CryptoData& data,
526 blink::WebArrayBuffer* buffer) { 538 std::vector<uint8>* buffer) {
527 switch (algorithm.id()) { 539 switch (algorithm.id()) {
528 case blink::WebCryptoAlgorithmIdSha1: 540 case blink::WebCryptoAlgorithmIdSha1:
529 case blink::WebCryptoAlgorithmIdSha256: 541 case blink::WebCryptoAlgorithmIdSha256:
530 case blink::WebCryptoAlgorithmIdSha384: 542 case blink::WebCryptoAlgorithmIdSha384:
531 case blink::WebCryptoAlgorithmIdSha512: 543 case blink::WebCryptoAlgorithmIdSha512:
532 return platform::DigestSha(algorithm.id(), data, buffer); 544 return platform::DigestSha(algorithm.id(), data, buffer);
533 default: 545 default:
534 return Status::ErrorUnsupported(); 546 return Status::ErrorUnsupported();
535 } 547 }
536 } 548 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 publicExponent, 631 publicExponent,
620 hash_or_null, 632 hash_or_null,
621 public_key, 633 public_key,
622 private_key); 634 private_key);
623 } 635 }
624 default: 636 default:
625 return Status::ErrorUnsupported(); 637 return Status::ErrorUnsupported();
626 } 638 }
627 } 639 }
628 640
641 // Note that this function may be called from the target Blink thread.
629 Status ImportKey(blink::WebCryptoKeyFormat format, 642 Status ImportKey(blink::WebCryptoKeyFormat format,
630 const CryptoData& key_data, 643 const CryptoData& key_data,
631 const blink::WebCryptoAlgorithm& algorithm, 644 const blink::WebCryptoAlgorithm& algorithm,
632 bool extractable, 645 bool extractable,
633 blink::WebCryptoKeyUsageMask usage_mask, 646 blink::WebCryptoKeyUsageMask usage_mask,
634 blink::WebCryptoKey* key) { 647 blink::WebCryptoKey* key) {
635 switch (format) { 648 switch (format) {
636 case blink::WebCryptoKeyFormatRaw: 649 case blink::WebCryptoKeyFormatRaw:
637 return ImportKeyRaw(key_data, algorithm, extractable, usage_mask, key); 650 return ImportKeyRaw(key_data, algorithm, extractable, usage_mask, key);
638 case blink::WebCryptoKeyFormatSpki: 651 case blink::WebCryptoKeyFormatSpki:
639 return platform::ImportKeySpki( 652 return platform::ImportKeySpki(
640 algorithm, key_data, extractable, usage_mask, key); 653 algorithm, key_data, extractable, usage_mask, key);
641 case blink::WebCryptoKeyFormatPkcs8: 654 case blink::WebCryptoKeyFormatPkcs8:
642 return platform::ImportKeyPkcs8( 655 return platform::ImportKeyPkcs8(
643 algorithm, key_data, extractable, usage_mask, key); 656 algorithm, key_data, extractable, usage_mask, key);
644 case blink::WebCryptoKeyFormatJwk: 657 case blink::WebCryptoKeyFormatJwk:
645 return ImportKeyJwk(key_data, algorithm, extractable, usage_mask, key); 658 return ImportKeyJwk(key_data, algorithm, extractable, usage_mask, key);
646 default: 659 default:
647 return Status::ErrorUnsupported(); 660 return Status::ErrorUnsupported();
648 } 661 }
649 } 662 }
650 663
651 // TODO(eroman): Move this to anonymous namespace. 664 // TODO(eroman): Move this to anonymous namespace.
652 Status ExportKeyDontCheckExtractability(blink::WebCryptoKeyFormat format, 665 Status ExportKeyDontCheckExtractability(blink::WebCryptoKeyFormat format,
653 const blink::WebCryptoKey& key, 666 const blink::WebCryptoKey& key,
654 blink::WebArrayBuffer* buffer) { 667 std::vector<uint8>* buffer) {
655 switch (format) { 668 switch (format) {
656 case blink::WebCryptoKeyFormatRaw: { 669 case blink::WebCryptoKeyFormatRaw: {
657 platform::SymKey* sym_key; 670 platform::SymKey* sym_key;
658 Status status = ToPlatformSymKey(key, &sym_key); 671 Status status = ToPlatformSymKey(key, &sym_key);
659 if (status.IsError()) 672 if (status.IsError())
660 return status; 673 return status;
661 return platform::ExportKeyRaw(sym_key, buffer); 674 return platform::ExportKeyRaw(sym_key, buffer);
662 } 675 }
663 case blink::WebCryptoKeyFormatSpki: { 676 case blink::WebCryptoKeyFormatSpki: {
664 platform::PublicKey* public_key; 677 platform::PublicKey* public_key;
(...skipping 11 matching lines...) Expand all
676 } 689 }
677 case blink::WebCryptoKeyFormatJwk: 690 case blink::WebCryptoKeyFormatJwk:
678 return ExportKeyJwk(key, buffer); 691 return ExportKeyJwk(key, buffer);
679 default: 692 default:
680 return Status::ErrorUnsupported(); 693 return Status::ErrorUnsupported();
681 } 694 }
682 } 695 }
683 696
684 Status ExportKey(blink::WebCryptoKeyFormat format, 697 Status ExportKey(blink::WebCryptoKeyFormat format,
685 const blink::WebCryptoKey& key, 698 const blink::WebCryptoKey& key,
686 blink::WebArrayBuffer* buffer) { 699 std::vector<uint8>* buffer) {
687 if (!key.extractable()) 700 if (!key.extractable())
688 return Status::ErrorKeyNotExtractable(); 701 return Status::ErrorKeyNotExtractable();
689 return ExportKeyDontCheckExtractability(format, key, buffer); 702 return ExportKeyDontCheckExtractability(format, key, buffer);
690 } 703 }
691 704
692 Status Sign(const blink::WebCryptoAlgorithm& algorithm, 705 Status Sign(const blink::WebCryptoAlgorithm& algorithm,
693 const blink::WebCryptoKey& key, 706 const blink::WebCryptoKey& key,
694 const CryptoData& data, 707 const CryptoData& data,
695 blink::WebArrayBuffer* buffer) { 708 std::vector<uint8>* buffer) {
696 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageSign)) 709 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageSign))
697 return Status::ErrorUnexpected(); 710 return Status::ErrorUnexpected();
698 if (algorithm.id() != key.algorithm().id()) 711 if (algorithm.id() != key.algorithm().id())
699 return Status::ErrorUnexpected(); 712 return Status::ErrorUnexpected();
700 713
701 switch (algorithm.id()) { 714 switch (algorithm.id()) {
702 case blink::WebCryptoAlgorithmIdHmac: 715 case blink::WebCryptoAlgorithmIdHmac:
703 return SignHmac(algorithm, key, data, buffer); 716 return SignHmac(algorithm, key, data, buffer);
704 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: 717 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
705 return SignRsaSsaPkcs1v1_5(algorithm, key, data, buffer); 718 return SignRsaSsaPkcs1v1_5(algorithm, key, data, buffer);
(...skipping 28 matching lines...) Expand all
734 algorithm, key, signature, data, signature_match); 747 algorithm, key, signature, data, signature_match);
735 default: 748 default:
736 return Status::ErrorUnsupported(); 749 return Status::ErrorUnsupported();
737 } 750 }
738 } 751 }
739 752
740 Status WrapKey(blink::WebCryptoKeyFormat format, 753 Status WrapKey(blink::WebCryptoKeyFormat format,
741 const blink::WebCryptoKey& wrapping_key, 754 const blink::WebCryptoKey& wrapping_key,
742 const blink::WebCryptoKey& key_to_wrap, 755 const blink::WebCryptoKey& key_to_wrap,
743 const blink::WebCryptoAlgorithm& wrapping_algorithm, 756 const blink::WebCryptoAlgorithm& wrapping_algorithm,
744 blink::WebArrayBuffer* buffer) { 757 std::vector<uint8>* buffer) {
745 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageWrapKey)) 758 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageWrapKey))
746 return Status::ErrorUnexpected(); 759 return Status::ErrorUnexpected();
747 if (wrapping_algorithm.id() != wrapping_key.algorithm().id()) 760 if (wrapping_algorithm.id() != wrapping_key.algorithm().id())
748 return Status::ErrorUnexpected(); 761 return Status::ErrorUnexpected();
749 762
750 switch (format) { 763 switch (format) {
751 case blink::WebCryptoKeyFormatRaw: 764 case blink::WebCryptoKeyFormatRaw:
752 return WrapKeyRaw(wrapping_key, key_to_wrap, wrapping_algorithm, buffer); 765 return WrapKeyRaw(wrapping_key, key_to_wrap, wrapping_algorithm, buffer);
753 case blink::WebCryptoKeyFormatJwk: 766 case blink::WebCryptoKeyFormatJwk:
754 return WrapKeyExportAndEncrypt( 767 return WrapKeyExportAndEncrypt(
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 key); 808 key);
796 case blink::WebCryptoKeyFormatSpki: 809 case blink::WebCryptoKeyFormatSpki:
797 case blink::WebCryptoKeyFormatPkcs8: 810 case blink::WebCryptoKeyFormatPkcs8:
798 return Status::ErrorUnsupported(); // TODO(padolph) 811 return Status::ErrorUnsupported(); // TODO(padolph)
799 default: 812 default:
800 NOTREACHED(); 813 NOTREACHED();
801 return Status::ErrorUnsupported(); 814 return Status::ErrorUnsupported();
802 } 815 }
803 } 816 }
804 817
805 Status SerializeKeyForClone(const blink::WebCryptoKey& key, 818 // Note that this function is called from the target Blink thread.
806 blink::WebVector<unsigned char>* data) { 819 bool SerializeKeyForClone(const blink::WebCryptoKey& key,
807 blink::WebArrayBuffer buffer; 820 blink::WebVector<uint8>* key_data) {
808 Status status = ExportKeyDontCheckExtractability( 821 return static_cast<webcrypto::platform::Key*>(key.handle())
809 GetCloneFormatForKeyType(key.type()), key, &buffer); 822 ->ThreadSafeSerializeForClone(key_data);
810 if (status.IsError())
811 return status;
812 data->assign(
813 reinterpret_cast<unsigned char*>(buffer.data()), buffer.byteLength());
814 return Status::Success();
815 } 823 }
816 824
817 Status DeserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm, 825 // Note that this function is called from the target Blink thread.
818 blink::WebCryptoKeyType type, 826 bool DeserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm,
819 bool extractable, 827 blink::WebCryptoKeyType type,
820 blink::WebCryptoKeyUsageMask usage_mask, 828 bool extractable,
821 const CryptoData& key_data, 829 blink::WebCryptoKeyUsageMask usage_mask,
822 blink::WebCryptoKey* key) { 830 const CryptoData& key_data,
831 blink::WebCryptoKey* key) {
832 // TODO(eroman): This should not call into the platform crypto layer.
833 // Otherwise it runs the risk of stalling while the NSS/OpenSSL global locks
834 // are held.
835 //
836 // An alternate approach is to defer the key import until the key is used.
837 // However this means that any deserialization errors would have to be
838 // surfaced as WebCrypto errors which isn't quite correct.
Ryan Sleevi 2014/04/18 00:51:26 Why isn't it quite correct? I tried to make sure t
eroman 2014/04/18 18:45:56 I wrote that to highlight that the behavior is obs
823 Status status = ImportKey(GetCloneFormatForKeyType(type), 839 Status status = ImportKey(GetCloneFormatForKeyType(type),
824 key_data, 840 key_data,
825 KeyAlgorithmToImportAlgorithm(algorithm), 841 KeyAlgorithmToImportAlgorithm(algorithm),
826 extractable, 842 extractable,
827 usage_mask, 843 usage_mask,
828 key); 844 key);
829 if (status.IsError()) 845 if (status.IsError())
830 return status; 846 return false;
831
832 return ValidateDeserializedKey(*key, algorithm, type); 847 return ValidateDeserializedKey(*key, algorithm, type);
833 } 848 }
834 849
835 } // namespace webcrypto 850 } // namespace webcrypto
836 851
837 } // namespace content 852 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698