OLD | NEW |
---|---|
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/platform_crypto.h" | 9 #include "content/child/webcrypto/platform_crypto.h" |
10 #include "content/child/webcrypto/webcrypto_util.h" | 10 #include "content/child/webcrypto/webcrypto_util.h" |
11 #include "crypto/secure_util.h" | 11 #include "crypto/secure_util.h" |
12 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" | 12 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" |
13 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | 13 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
14 #include "third_party/WebKit/public/platform/WebCryptoKey.h" | 14 #include "third_party/WebKit/public/platform/WebCryptoKey.h" |
15 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" | 15 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" |
16 | 16 |
17 namespace content { | 17 namespace content { |
18 | 18 |
19 namespace webcrypto { | 19 namespace webcrypto { |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
23 // TODO(eroman): Move this helper to WebCryptoKey. | 23 // TODO(eroman): Move this helper to WebCryptoKey. |
24 bool KeyUsageAllows(const blink::WebCryptoKey& key, | 24 bool KeyUsageAllows(const blink::WebCryptoKey& key, |
25 const blink::WebCryptoKeyUsage usage) { | 25 const blink::WebCryptoKeyUsage usage) { |
26 return ((key.usages() & usage) != 0); | 26 return ((key.usages() & usage) != 0); |
27 } | 27 } |
28 | 28 |
29 bool KeyUsageAllowsAnyOf(const blink::WebCryptoKey& key, | |
eroman
2014/03/18 06:18:39
this probably needs to be rebased, these diffs sho
padolph
2014/03/18 17:52:19
'git cl rebase' does not work for me. I get the er
| |
30 const blink::WebCryptoKeyUsageMask usage_mask) { | |
31 return ((key.usages() & usage_mask) != 0); | |
32 } | |
33 | |
34 bool IsValidAesKeyLengthBits(unsigned int length_bits) { | 29 bool IsValidAesKeyLengthBits(unsigned int length_bits) { |
35 return length_bits == 128 || length_bits == 192 || length_bits == 256; | 30 return length_bits == 128 || length_bits == 192 || length_bits == 256; |
36 } | 31 } |
37 | 32 |
38 bool IsValidAesKeyLengthBytes(unsigned int length_bytes) { | 33 bool IsValidAesKeyLengthBytes(unsigned int length_bytes) { |
39 return length_bytes == 16 || length_bytes == 24 || length_bytes == 32; | 34 return length_bytes == 16 || length_bytes == 24 || length_bytes == 32; |
40 } | 35 } |
41 | 36 |
42 Status ToPlatformSymKey(const blink::WebCryptoKey& key, | 37 Status ToPlatformSymKey(const blink::WebCryptoKey& key, |
43 platform::SymKey** out) { | 38 platform::SymKey** out) { |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
289 algorithm_or_null, | 284 algorithm_or_null, |
290 extractable, | 285 extractable, |
291 usage_mask, | 286 usage_mask, |
292 key); | 287 key); |
293 } | 288 } |
294 default: | 289 default: |
295 return Status::ErrorUnsupported(); | 290 return Status::ErrorUnsupported(); |
296 } | 291 } |
297 } | 292 } |
298 | 293 |
294 Status WrapKeyRaw(const blink::WebCryptoKey& wrapping_key, | |
295 const blink::WebCryptoKey& key_to_wrap, | |
296 const blink::WebCryptoAlgorithm& wrapping_algorithm, | |
297 blink::WebArrayBuffer* buffer) { | |
298 // A raw key is always a symmetric key. | |
299 platform::SymKey* platform_key; | |
300 Status status = ToPlatformSymKey(key_to_wrap, &platform_key); | |
301 if (status.IsError()) | |
302 return status; | |
303 | |
304 // TODO(padolph): Handle other wrapping algorithms | |
305 switch (wrapping_algorithm.id()) { | |
306 case blink::WebCryptoAlgorithmIdAesKw: { | |
307 platform::SymKey* platform_wrapping_key; | |
308 status = ToPlatformSymKey(wrapping_key, &platform_wrapping_key); | |
309 if (status.IsError()) | |
310 return status; | |
311 return platform::WrapSymKeyAesKw( | |
312 platform_wrapping_key, platform_key, buffer); | |
313 } | |
314 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: { | |
315 platform::PublicKey* platform_wrapping_key; | |
316 status = ToPlatformPublicKey(wrapping_key, &platform_wrapping_key); | |
317 if (status.IsError()) | |
318 return status; | |
319 return platform::WrapSymKeyRsaEs( | |
320 platform_wrapping_key, platform_key, buffer); | |
321 } | |
322 default: | |
323 return Status::ErrorUnsupported(); | |
324 } | |
325 } | |
326 | |
299 Status DecryptAesKw(const blink::WebCryptoAlgorithm& algorithm, | 327 Status DecryptAesKw(const blink::WebCryptoAlgorithm& algorithm, |
300 const blink::WebCryptoKey& key, | 328 const blink::WebCryptoKey& key, |
301 const CryptoData& data, | 329 const CryptoData& data, |
302 blink::WebArrayBuffer* buffer) { | 330 blink::WebArrayBuffer* buffer) { |
303 platform::SymKey* sym_key; | 331 platform::SymKey* sym_key; |
304 Status status = ToPlatformSymKey(key, &sym_key); | 332 Status status = ToPlatformSymKey(key, &sym_key); |
305 if (status.IsError()) | 333 if (status.IsError()) |
306 return status; | 334 return status; |
307 status = CheckAesKwInputSize(data); | 335 status = CheckAesKwInputSize(data); |
308 if (status.IsError()) | 336 if (status.IsError()) |
(...skipping 14 matching lines...) Expand all Loading... | |
323 return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer); | 351 return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer); |
324 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | 352 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
325 return DecryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); | 353 return DecryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); |
326 case blink::WebCryptoAlgorithmIdAesKw: | 354 case blink::WebCryptoAlgorithmIdAesKw: |
327 return DecryptAesKw(algorithm, key, data, buffer); | 355 return DecryptAesKw(algorithm, key, data, buffer); |
328 default: | 356 default: |
329 return Status::ErrorUnsupported(); | 357 return Status::ErrorUnsupported(); |
330 } | 358 } |
331 } | 359 } |
332 | 360 |
361 Status EncryptDontCheckUsage(const blink::WebCryptoAlgorithm& algorithm, | |
362 const blink::WebCryptoKey& key, | |
363 const CryptoData& data, | |
364 blink::WebArrayBuffer* buffer) { | |
365 if (algorithm.id() != key.algorithm().id()) | |
366 return Status::ErrorUnexpected(); | |
367 switch (algorithm.id()) { | |
368 case blink::WebCryptoAlgorithmIdAesCbc: | |
369 return EncryptDecryptAesCbc(ENCRYPT, algorithm, key, data, buffer); | |
370 case blink::WebCryptoAlgorithmIdAesGcm: | |
371 return EncryptDecryptAesGcm(ENCRYPT, algorithm, key, data, buffer); | |
372 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | |
373 return EncryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); | |
374 default: | |
375 return Status::ErrorUnsupported(); | |
376 } | |
377 } | |
378 | |
333 Status UnwrapKeyDecryptAndImport( | 379 Status UnwrapKeyDecryptAndImport( |
334 blink::WebCryptoKeyFormat format, | 380 blink::WebCryptoKeyFormat format, |
335 const CryptoData& wrapped_key_data, | 381 const CryptoData& wrapped_key_data, |
336 const blink::WebCryptoKey& wrapping_key, | 382 const blink::WebCryptoKey& wrapping_key, |
337 const blink::WebCryptoAlgorithm& wrapping_algorithm, | 383 const blink::WebCryptoAlgorithm& wrapping_algorithm, |
338 const blink::WebCryptoAlgorithm& algorithm_or_null, | 384 const blink::WebCryptoAlgorithm& algorithm_or_null, |
339 bool extractable, | 385 bool extractable, |
340 blink::WebCryptoKeyUsageMask usage_mask, | 386 blink::WebCryptoKeyUsageMask usage_mask, |
341 blink::WebCryptoKey* key) { | 387 blink::WebCryptoKey* key) { |
342 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey)) | |
343 return Status::ErrorUnexpected(); | |
344 blink::WebArrayBuffer buffer; | 388 blink::WebArrayBuffer buffer; |
345 Status status = DecryptDontCheckKeyUsage( | 389 Status status = DecryptDontCheckKeyUsage( |
346 wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer); | 390 wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer); |
347 if (status.IsError()) | 391 if (status.IsError()) |
348 return status; | 392 return status; |
349 status = ImportKey(format, | 393 status = ImportKey(format, |
350 CryptoData(buffer), | 394 CryptoData(buffer), |
351 algorithm_or_null, | 395 algorithm_or_null, |
352 extractable, | 396 extractable, |
353 usage_mask, | 397 usage_mask, |
354 key); | 398 key); |
355 // NOTE! Returning the details of any ImportKey() failure here would leak | 399 // NOTE! Returning the details of any ImportKey() failure here would leak |
356 // information about the plaintext internals of the encrypted key. Instead, | 400 // information about the plaintext internals of the encrypted key. Instead, |
357 // collapse any error into the generic Status::Error(). | 401 // collapse any error into the generic Status::Error(). |
358 return status.IsError() ? Status::Error() : Status::Success(); | 402 return status.IsError() ? Status::Error() : Status::Success(); |
359 } | 403 } |
360 | 404 |
405 Status WrapKeyExportAndEncrypt( | |
406 blink::WebCryptoKeyFormat format, | |
407 const blink::WebCryptoKey& wrapping_key, | |
408 const blink::WebCryptoKey& key_to_wrap, | |
409 const blink::WebCryptoAlgorithm& wrapping_algorithm, | |
410 blink::WebArrayBuffer* buffer) { | |
411 blink::WebArrayBuffer exported_data; | |
412 Status status = ExportKey(format, key_to_wrap, &exported_data); | |
413 if (status.IsError()) | |
414 return status; | |
415 return EncryptDontCheckUsage( | |
416 wrapping_algorithm, wrapping_key, CryptoData(exported_data), buffer); | |
417 } | |
418 | |
361 } // namespace | 419 } // namespace |
362 | 420 |
363 void Init() { platform::Init(); } | 421 void Init() { platform::Init(); } |
364 | 422 |
365 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, | 423 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, |
366 const blink::WebCryptoKey& key, | 424 const blink::WebCryptoKey& key, |
367 const CryptoData& data, | 425 const CryptoData& data, |
368 blink::WebArrayBuffer* buffer) { | 426 blink::WebArrayBuffer* buffer) { |
369 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt)) | 427 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt)) |
370 return Status::ErrorUnexpected(); | 428 return Status::ErrorUnexpected(); |
371 if (algorithm.id() != key.algorithm().id()) | 429 return EncryptDontCheckUsage(algorithm, key, data, buffer); |
372 return Status::ErrorUnexpected(); | |
373 | |
374 switch (algorithm.id()) { | |
375 case blink::WebCryptoAlgorithmIdAesCbc: | |
376 return EncryptDecryptAesCbc(ENCRYPT, algorithm, key, data, buffer); | |
377 case blink::WebCryptoAlgorithmIdAesGcm: | |
378 return EncryptDecryptAesGcm(ENCRYPT, algorithm, key, data, buffer); | |
379 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | |
380 return EncryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); | |
381 default: | |
382 return Status::ErrorUnsupported(); | |
383 } | |
384 } | 430 } |
385 | 431 |
386 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, | 432 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, |
387 const blink::WebCryptoKey& key, | 433 const blink::WebCryptoKey& key, |
388 const CryptoData& data, | 434 const CryptoData& data, |
389 blink::WebArrayBuffer* buffer) { | 435 blink::WebArrayBuffer* buffer) { |
390 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt)) | 436 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt)) |
391 return Status::ErrorUnexpected(); | 437 return Status::ErrorUnexpected(); |
392 return DecryptDontCheckKeyUsage(algorithm, key, data, buffer); | 438 return DecryptDontCheckKeyUsage(algorithm, key, data, buffer); |
393 } | 439 } |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
593 default: | 639 default: |
594 return Status::ErrorUnsupported(); | 640 return Status::ErrorUnsupported(); |
595 } | 641 } |
596 } | 642 } |
597 | 643 |
598 Status WrapKey(blink::WebCryptoKeyFormat format, | 644 Status WrapKey(blink::WebCryptoKeyFormat format, |
599 const blink::WebCryptoKey& wrapping_key, | 645 const blink::WebCryptoKey& wrapping_key, |
600 const blink::WebCryptoKey& key_to_wrap, | 646 const blink::WebCryptoKey& key_to_wrap, |
601 const blink::WebCryptoAlgorithm& wrapping_algorithm, | 647 const blink::WebCryptoAlgorithm& wrapping_algorithm, |
602 blink::WebArrayBuffer* buffer) { | 648 blink::WebArrayBuffer* buffer) { |
603 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageUnwrapKey)) | 649 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageWrapKey)) |
eroman
2014/03/18 06:18:39
hah! these checks are mainly a precaution, since t
padolph
2014/03/18 17:52:19
Was hoping I could sneak this fix in unnoticed ;-)
| |
604 return Status::ErrorUnexpected(); | 650 return Status::ErrorUnexpected(); |
605 if (wrapping_algorithm.id() != wrapping_key.algorithm().id()) | 651 if (wrapping_algorithm.id() != wrapping_key.algorithm().id()) |
606 return Status::ErrorUnexpected(); | 652 return Status::ErrorUnexpected(); |
607 | 653 |
608 // TODO (padolph): Handle formats other than raw | 654 switch (format) { |
609 if (format != blink::WebCryptoKeyFormatRaw) | 655 case blink::WebCryptoKeyFormatRaw: |
610 return Status::ErrorUnsupported(); | 656 return WrapKeyRaw(wrapping_key, key_to_wrap, wrapping_algorithm, buffer); |
611 // TODO (padolph): Handle key-to-wrap types other than secret/symmetric | 657 case blink::WebCryptoKeyFormatJwk: |
612 if (key_to_wrap.type() != blink::WebCryptoKeyTypeSecret) | 658 return WrapKeyExportAndEncrypt( |
613 return Status::ErrorUnsupported(); | 659 format, wrapping_key, key_to_wrap, wrapping_algorithm, buffer); |
614 | 660 case blink::WebCryptoKeyFormatSpki: |
615 platform::SymKey* platform_key; | 661 case blink::WebCryptoKeyFormatPkcs8: |
616 Status status = ToPlatformSymKey(key_to_wrap, &platform_key); | 662 return Status::ErrorUnsupported(); // TODO(padolph) |
617 if (status.IsError()) | |
618 return status; | |
619 | |
620 // TODO(padolph): Handle other wrapping algorithms | |
621 switch (wrapping_algorithm.id()) { | |
622 case blink::WebCryptoAlgorithmIdAesKw: { | |
623 platform::SymKey* platform_wrapping_key; | |
624 status = ToPlatformSymKey(wrapping_key, &platform_wrapping_key); | |
625 if (status.IsError()) | |
626 return status; | |
627 return platform::WrapSymKeyAesKw( | |
628 platform_wrapping_key, platform_key, buffer); | |
629 } | |
630 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: { | |
631 platform::PublicKey* platform_wrapping_key; | |
632 status = ToPlatformPublicKey(wrapping_key, &platform_wrapping_key); | |
633 if (status.IsError()) | |
634 return status; | |
635 return platform::WrapSymKeyRsaEs( | |
636 platform_wrapping_key, platform_key, buffer); | |
637 } | |
638 default: | 663 default: |
664 NOTREACHED(); | |
639 return Status::ErrorUnsupported(); | 665 return Status::ErrorUnsupported(); |
640 } | 666 } |
641 } | 667 } |
642 | 668 |
643 Status UnwrapKey(blink::WebCryptoKeyFormat format, | 669 Status UnwrapKey(blink::WebCryptoKeyFormat format, |
644 const CryptoData& wrapped_key_data, | 670 const CryptoData& wrapped_key_data, |
645 const blink::WebCryptoKey& wrapping_key, | 671 const blink::WebCryptoKey& wrapping_key, |
646 const blink::WebCryptoAlgorithm& wrapping_algorithm, | 672 const blink::WebCryptoAlgorithm& wrapping_algorithm, |
647 const blink::WebCryptoAlgorithm& algorithm_or_null, | 673 const blink::WebCryptoAlgorithm& algorithm_or_null, |
648 bool extractable, | 674 bool extractable, |
(...skipping 27 matching lines...) Expand all Loading... | |
676 return Status::ErrorUnsupported(); // TODO(padolph) | 702 return Status::ErrorUnsupported(); // TODO(padolph) |
677 default: | 703 default: |
678 NOTREACHED(); | 704 NOTREACHED(); |
679 return Status::ErrorUnsupported(); | 705 return Status::ErrorUnsupported(); |
680 } | 706 } |
681 } | 707 } |
682 | 708 |
683 } // namespace webcrypto | 709 } // namespace webcrypto |
684 | 710 |
685 } // namespace content | 711 } // namespace content |
OLD | NEW |