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. | |
eroman
2014/03/17 19:47:47
Another solution would be to introduce an error al
padolph
2014/03/17 22:12:49
That error would tell the caller that encryption p
eroman
2014/03/18 01:02:13
If we care about distinguishing import vs decrypt
padolph
2014/03/18 02:54:16
I don't think so. At that stage it is no different
| |
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 |