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 <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 2362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2373 "72d4e475ff34215416c9ad9c8281247a4d730c5f275ac23f376e73e3bce8d7d5a"; | 2373 "72d4e475ff34215416c9ad9c8281247a4d730c5f275ac23f376e73e3bce8d7d5a"; |
2374 EXPECT_STATUS(Status::Error(), | 2374 EXPECT_STATUS(Status::Error(), |
2375 ImportKey(blink::WebCryptoKeyFormatRaw, | 2375 ImportKey(blink::WebCryptoKeyFormatRaw, |
2376 CryptoData(HexStringToBytes(key_raw_hex_in)), | 2376 CryptoData(HexStringToBytes(key_raw_hex_in)), |
2377 algorithm, | 2377 algorithm, |
2378 true, | 2378 true, |
2379 blink::WebCryptoKeyUsageWrapKey, | 2379 blink::WebCryptoKeyUsageWrapKey, |
2380 &key)); | 2380 &key)); |
2381 } | 2381 } |
2382 | 2382 |
| 2383 TEST_F(SharedCryptoTest, MAYBE(UnwrapFailures)) { |
| 2384 // This test exercises the code path common to all unwrap operations. |
| 2385 scoped_ptr<base::ListValue> tests; |
| 2386 ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests)); |
| 2387 base::DictionaryValue* test; |
| 2388 ASSERT_TRUE(tests->GetDictionary(0, &test)); |
| 2389 const std::vector<uint8> test_kek = GetBytesFromHexString(test, "kek"); |
| 2390 const std::vector<uint8> test_ciphertext = |
| 2391 GetBytesFromHexString(test, "ciphertext"); |
| 2392 |
| 2393 // Using a key that does not have unwrapKey usage should fail. |
| 2394 blink::WebCryptoKey bad_wrapping_key = ImportSecretKeyFromRaw( |
| 2395 test_kek, |
| 2396 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw), |
| 2397 blink::WebCryptoKeyUsageDecrypt); // <-- should be UnwrapKey |
| 2398 blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull(); |
| 2399 EXPECT_STATUS( |
| 2400 Status::ErrorUnexpected(), |
| 2401 UnwrapKey(blink::WebCryptoKeyFormatRaw, |
| 2402 CryptoData(test_ciphertext), |
| 2403 bad_wrapping_key, |
| 2404 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw), |
| 2405 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), |
| 2406 true, |
| 2407 blink::WebCryptoKeyUsageEncrypt, |
| 2408 &unwrapped_key)); |
| 2409 |
| 2410 // Using a wrapping algorithm that does not match the wrapping key algorithm |
| 2411 // should fail. |
| 2412 blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw( |
| 2413 test_kek, |
| 2414 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw), |
| 2415 blink::WebCryptoKeyUsageUnwrapKey); |
| 2416 EXPECT_STATUS( |
| 2417 Status::ErrorUnexpected(), |
| 2418 UnwrapKey(blink::WebCryptoKeyFormatRaw, |
| 2419 CryptoData(test_ciphertext), |
| 2420 wrapping_key, |
| 2421 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), |
| 2422 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), |
| 2423 true, |
| 2424 blink::WebCryptoKeyUsageEncrypt, |
| 2425 &unwrapped_key)); |
| 2426 } |
| 2427 |
2383 TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyWrapUnwrapKnownAnswer)) { | 2428 TEST_F(SharedCryptoTest, MAYBE(AesKwRawSymkeyWrapUnwrapKnownAnswer)) { |
2384 scoped_ptr<base::ListValue> tests; | 2429 scoped_ptr<base::ListValue> tests; |
2385 ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests)); | 2430 ASSERT_TRUE(ReadJsonTestFileToList("aes_kw.json", &tests)); |
2386 | 2431 |
2387 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) { | 2432 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) { |
2388 SCOPED_TRACE(test_index); | 2433 SCOPED_TRACE(test_index); |
2389 base::DictionaryValue* test; | 2434 base::DictionaryValue* test; |
2390 ASSERT_TRUE(tests->GetDictionary(test_index, &test)); | 2435 ASSERT_TRUE(tests->GetDictionary(test_index, &test)); |
2391 const std::vector<uint8> test_kek = GetBytesFromHexString(test, "kek"); | 2436 const std::vector<uint8> test_kek = GetBytesFromHexString(test, "kek"); |
2392 const std::vector<uint8> test_key = GetBytesFromHexString(test, "key"); | 2437 const std::vector<uint8> test_key = GetBytesFromHexString(test, "key"); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2535 UnwrapKey(blink::WebCryptoKeyFormatRaw, | 2580 UnwrapKey(blink::WebCryptoKeyFormatRaw, |
2536 CryptoData(Corrupted(test_ciphertext)), | 2581 CryptoData(Corrupted(test_ciphertext)), |
2537 wrapping_key, | 2582 wrapping_key, |
2538 wrapping_algorithm, | 2583 wrapping_algorithm, |
2539 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), | 2584 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), |
2540 true, | 2585 true, |
2541 blink::WebCryptoKeyUsageEncrypt, | 2586 blink::WebCryptoKeyUsageEncrypt, |
2542 &unwrapped_key)); | 2587 &unwrapped_key)); |
2543 } | 2588 } |
2544 | 2589 |
| 2590 TEST_F(SharedCryptoTest, MAYBE(AesKwJwkSymkeyUnwrapKnownData)) { |
| 2591 // The following data lists a known HMAC SHA-256 key, then a JWK |
| 2592 // representation of this key which was encrypted ("wrapped") using AES-KW and |
| 2593 // the following wrapping key. |
| 2594 // For reference, the intermediate clear JWK is |
| 2595 // {"alg":"HS256","ext":true,"k":<b64urlKey>,"key_ops":["verify"],"kty":"oct"} |
| 2596 // (Not shown is space padding to ensure the cleartext meets the size |
| 2597 // requirements of the AES-KW algorithm.) |
| 2598 const std::vector<uint8> key_data = HexStringToBytes( |
| 2599 "000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"); |
| 2600 const std::vector<uint8> wrapped_key_data = HexStringToBytes( |
| 2601 "14E6380B35FDC5B72E1994764B6CB7BFDD64E7832894356AAEE6C3768FC3D0F115E6B0" |
| 2602 "6729756225F999AA99FDF81FD6A359F1576D3D23DE6CB69C3937054EB497AC1E8C38D5" |
| 2603 "5E01B9783A20C8D930020932CF25926103002213D0FC37279888154FEBCEDF31832158" |
| 2604 "97938C5CFE5B10B4254D0C399F39D0"); |
| 2605 const std::vector<uint8> wrapping_key_data = |
| 2606 HexStringToBytes("000102030405060708090A0B0C0D0E0F"); |
| 2607 const blink::WebCryptoAlgorithm wrapping_algorithm = |
| 2608 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); |
| 2609 |
| 2610 // Import the wrapping key. |
| 2611 blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw( |
| 2612 wrapping_key_data, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey); |
| 2613 |
| 2614 // Unwrap the known wrapped key data to produce a new key |
| 2615 blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull(); |
| 2616 ASSERT_STATUS_SUCCESS(UnwrapKey(blink::WebCryptoKeyFormatJwk, |
| 2617 CryptoData(wrapped_key_data), |
| 2618 wrapping_key, |
| 2619 wrapping_algorithm, |
| 2620 blink::WebCryptoAlgorithm::createNull(), |
| 2621 true, |
| 2622 blink::WebCryptoKeyUsageVerify, |
| 2623 &unwrapped_key)); |
| 2624 |
| 2625 // Validate the new key's attributes. |
| 2626 EXPECT_FALSE(unwrapped_key.isNull()); |
| 2627 EXPECT_TRUE(unwrapped_key.handle()); |
| 2628 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, unwrapped_key.type()); |
| 2629 EXPECT_EQ(blink::WebCryptoAlgorithmIdHmac, unwrapped_key.algorithm().id()); |
| 2630 EXPECT_EQ(blink::WebCryptoAlgorithmIdSha256, |
| 2631 unwrapped_key.algorithm().hmacParams()->hash().id()); |
| 2632 EXPECT_EQ(true, unwrapped_key.extractable()); |
| 2633 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, unwrapped_key.usages()); |
| 2634 |
| 2635 // Export the new key's raw data and compare to the known original. |
| 2636 blink::WebArrayBuffer raw_key; |
| 2637 EXPECT_STATUS_SUCCESS( |
| 2638 ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key)); |
| 2639 EXPECT_TRUE(ArrayBufferMatches(key_data, raw_key)); |
| 2640 } |
| 2641 |
| 2642 TEST_F(SharedCryptoTest, MAYBE(AesKwJwkSymkeyUnwrapErrors)) { |
| 2643 // Unwrap data that can be successfully decrypted, but contains an error in |
| 2644 // the plaintext JWK, and ensure that a generic error is returned instead of |
| 2645 // some other more specific error, to show that information about the |
| 2646 // plaintext JWK inside the encrypted data is not leaked. |
| 2647 // Specifically, wrapped_key_data below is an AES-KW encrypted version of the |
| 2648 // plaintext JWK |
| 2649 // { |
| 2650 // "alg":"HS256", |
| 2651 // "ext":true, |
| 2652 // "k":"AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8", |
| 2653 // "key_ops":["verify"], |
| 2654 // "kty":"foo" <-- Invalid kty value |
| 2655 // } |
| 2656 // Recall that unwrapKey = decrypt followed by import. The wrapped_key_data |
| 2657 // will decrypt successfully, but the import step will fail because of the bad |
| 2658 // kty value. But unlike the standalone ImportKey() method which returns |
| 2659 // ErrorJwkUnrecognizedKty in this case, the error returned must be just |
| 2660 // Error::Status(). |
| 2661 // Note that it is sufficient to consider just one JWK import failure mode |
| 2662 // here; others are validated in the ImportJwkFailures Test. |
| 2663 const std::vector<uint8> wrapped_key_data = HexStringToBytes( |
| 2664 "8d5ad45f5be6195a7a5944f0cf521bbae255daea140d4712985bb63ca1de1a318fbc49ff" |
| 2665 "307bd91bfafd7e9ea2057a2ddabb42ba94e319465972d165e5cc42785ad5cfa36159d5cc" |
| 2666 "50084133eae85a22bf8f7cb35f3c07b7c06480dec745d9ce4d4bfce45a6cbc2d39263ab7" |
| 2667 "073fc346724841f872f7148d"); |
| 2668 const std::vector<uint8> wrapping_key_data = |
| 2669 HexStringToBytes("000102030405060708090A0B0C0D0E0F"); |
| 2670 const blink::WebCryptoAlgorithm wrapping_algorithm = |
| 2671 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); |
| 2672 |
| 2673 // Import the wrapping key. |
| 2674 blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw( |
| 2675 wrapping_key_data, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey); |
| 2676 |
| 2677 // Unwrap and ensure a generic error is received. |
| 2678 blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull(); |
| 2679 EXPECT_STATUS(Status::Error(), |
| 2680 UnwrapKey(blink::WebCryptoKeyFormatJwk, |
| 2681 CryptoData(wrapped_key_data), |
| 2682 wrapping_key, |
| 2683 wrapping_algorithm, |
| 2684 blink::WebCryptoAlgorithm::createNull(), |
| 2685 true, |
| 2686 blink::WebCryptoKeyUsageVerify, |
| 2687 &unwrapped_key)); |
| 2688 |
| 2689 // FIXME(padolph): The check above can fail if the AES-KW decryption step |
| 2690 // failed, which masks the test result desired here. For now we have to just |
| 2691 // trust the result because I say so. |
| 2692 // Once RSA-ES unwrapping is implemented, port this test to use that wrapping |
| 2693 // algorithm instead of AES-KW. Unlike AES-KW, RSA-ES supports both the |
| 2694 // decrypt and unwrapKey usages, so we can validate successful decryption of |
| 2695 // wrapped_key_data prior to seeing the unwrapKey (import) failure. |
| 2696 } |
| 2697 |
2545 // TODO(eroman): | 2698 // TODO(eroman): |
2546 // * Test decryption when the tag length exceeds input size | 2699 // * Test decryption when the tag length exceeds input size |
2547 // * Test decryption with empty input | 2700 // * Test decryption with empty input |
2548 // * Test decryption with tag length of 0. | 2701 // * Test decryption with tag length of 0. |
2549 TEST_F(SharedCryptoTest, MAYBE(AesGcmSampleSets)) { | 2702 TEST_F(SharedCryptoTest, MAYBE(AesGcmSampleSets)) { |
2550 // Some Linux test runners may not have a new enough version of NSS. | 2703 // Some Linux test runners may not have a new enough version of NSS. |
2551 if (!SupportsAesGcm()) { | 2704 if (!SupportsAesGcm()) { |
2552 LOG(WARNING) << "AES GCM not supported, skipping tests"; | 2705 LOG(WARNING) << "AES GCM not supported, skipping tests"; |
2553 return; | 2706 return; |
2554 } | 2707 } |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2817 EXPECT_STATUS(Status::ErrorDataTooSmall(), | 2970 EXPECT_STATUS(Status::ErrorDataTooSmall(), |
2818 UnwrapKey(blink::WebCryptoKeyFormatRaw, | 2971 UnwrapKey(blink::WebCryptoKeyFormatRaw, |
2819 CryptoData(emtpy_data), | 2972 CryptoData(emtpy_data), |
2820 private_key, | 2973 private_key, |
2821 wrapping_algorithm, | 2974 wrapping_algorithm, |
2822 key_algorithm, | 2975 key_algorithm, |
2823 true, | 2976 true, |
2824 blink::WebCryptoKeyUsageSign, | 2977 blink::WebCryptoKeyUsageSign, |
2825 &unwrapped_key)); | 2978 &unwrapped_key)); |
2826 | 2979 |
2827 // Unwapping data too large for the wrapping key should fail. | 2980 // Unwrapping data too large for the wrapping key should fail. |
2828 EXPECT_STATUS(Status::ErrorDataTooLarge(), | 2981 EXPECT_STATUS(Status::ErrorDataTooLarge(), |
2829 UnwrapKey(blink::WebCryptoKeyFormatRaw, | 2982 UnwrapKey(blink::WebCryptoKeyFormatRaw, |
2830 CryptoData(big_data), | 2983 CryptoData(big_data), |
2831 private_key, | 2984 private_key, |
2832 wrapping_algorithm, | 2985 wrapping_algorithm, |
2833 key_algorithm, | 2986 key_algorithm, |
2834 true, | 2987 true, |
2835 blink::WebCryptoKeyUsageSign, | 2988 blink::WebCryptoKeyUsageSign, |
2836 &unwrapped_key)); | 2989 &unwrapped_key)); |
2837 } | 2990 } |
2838 | 2991 |
2839 } // namespace webcrypto | 2992 } // namespace webcrypto |
2840 | 2993 |
2841 } // namespace content | 2994 } // namespace content |
OLD | NEW |