Chromium Code Reviews| 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 |