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 2621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2632 EXPECT_EQ(true, unwrapped_key.extractable()); | 2632 EXPECT_EQ(true, unwrapped_key.extractable()); |
2633 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, unwrapped_key.usages()); | 2633 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, unwrapped_key.usages()); |
2634 | 2634 |
2635 // Export the new key's raw data and compare to the known original. | 2635 // Export the new key's raw data and compare to the known original. |
2636 blink::WebArrayBuffer raw_key; | 2636 blink::WebArrayBuffer raw_key; |
2637 EXPECT_STATUS_SUCCESS( | 2637 EXPECT_STATUS_SUCCESS( |
2638 ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key)); | 2638 ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key)); |
2639 EXPECT_TRUE(ArrayBufferMatches(key_data, raw_key)); | 2639 EXPECT_TRUE(ArrayBufferMatches(key_data, raw_key)); |
2640 } | 2640 } |
2641 | 2641 |
2642 TEST_F(SharedCryptoTest, MAYBE(AesKwJwkSymkeyUnwrapErrors)) { | |
eroman
2014/03/18 06:18:39
ditto: these diffs should not be in here
padolph
2014/03/18 17:52:19
Will rebase once the other CL lands.
| |
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 | |
2698 // TODO(eroman): | 2642 // TODO(eroman): |
2699 // * Test decryption when the tag length exceeds input size | 2643 // * Test decryption when the tag length exceeds input size |
2700 // * Test decryption with empty input | 2644 // * Test decryption with empty input |
2701 // * Test decryption with tag length of 0. | 2645 // * Test decryption with tag length of 0. |
2702 TEST_F(SharedCryptoTest, MAYBE(AesGcmSampleSets)) { | 2646 TEST_F(SharedCryptoTest, MAYBE(AesGcmSampleSets)) { |
2703 // Some Linux test runners may not have a new enough version of NSS. | 2647 // Some Linux test runners may not have a new enough version of NSS. |
2704 if (!SupportsAesGcm()) { | 2648 if (!SupportsAesGcm()) { |
2705 LOG(WARNING) << "AES GCM not supported, skipping tests"; | 2649 LOG(WARNING) << "AES GCM not supported, skipping tests"; |
2706 return; | 2650 return; |
2707 } | 2651 } |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2982 UnwrapKey(blink::WebCryptoKeyFormatRaw, | 2926 UnwrapKey(blink::WebCryptoKeyFormatRaw, |
2983 CryptoData(big_data), | 2927 CryptoData(big_data), |
2984 private_key, | 2928 private_key, |
2985 wrapping_algorithm, | 2929 wrapping_algorithm, |
2986 key_algorithm, | 2930 key_algorithm, |
2987 true, | 2931 true, |
2988 blink::WebCryptoKeyUsageSign, | 2932 blink::WebCryptoKeyUsageSign, |
2989 &unwrapped_key)); | 2933 &unwrapped_key)); |
2990 } | 2934 } |
2991 | 2935 |
2936 TEST_F(SharedCryptoTest, MAYBE(RsaEsJwkSymkeyUnwrapKnownAnswer)) { | |
eroman
2014/03/18 06:18:39
Is this test related to the code changes? Seems li
padolph
2014/03/18 17:52:19
This CL covers both RSAES-PKCS1-v1_5 wrap and unwr
| |
2937 // The following data lists a known 128-bit AES-CBC key, then a JWK | |
2938 // representation of this key that was encrypted ("wrapped") using | |
2939 // RSAES-PKCS1-v1_5 and kPublicKeySpkiDerHex as the wrapping key. | |
2940 // For reference, the intermediate clear JWK is | |
2941 // {"alg":"A128CBC","ext":true,"k":<b64url>,"key_ops":["encrypt"],"kty":"oct"} | |
2942 const std::vector<uint8> key_data = | |
2943 HexStringToBytes("8f56a26e7e8b77dca15ed54339724bf5"); | |
2944 const std::vector<uint8> wrapped_key_data = HexStringToBytes( | |
2945 "9debcabd9c731d6a779622dbef38635419c409b3077af67b3cf0601b2da7054f2ec26156" | |
2946 "06bb764e4986f45dd09ce660432a7abbac48b5249924f12dea52275b6d67d8b8a2f63525" | |
2947 "fbbf67d61244c1afa9e30857b87b7a48cdc0b3196dc1477738cbf9e42ea65d5e0edc3b05" | |
2948 "afafadc7d7400e26a51270d251040d51ce46cecc"); | |
2949 const blink::WebCryptoAlgorithm wrapping_algorithm = | |
2950 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); | |
2951 | |
2952 // Import the private wrapping key. | |
2953 blink::WebCryptoKey private_wrapping_key = blink::WebCryptoKey::createNull(); | |
2954 ASSERT_STATUS_SUCCESS(ImportKey( | |
2955 blink::WebCryptoKeyFormatPkcs8, | |
2956 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)), | |
2957 wrapping_algorithm, | |
2958 false, | |
2959 blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageUnwrapKey, | |
eroman
2014/03/18 06:18:39
Would it be more interesting if the unwrapping key
padolph
2014/03/18 17:52:19
Good idea. Yes, I'll make a change to use separate
| |
2960 &private_wrapping_key)); | |
2961 | |
2962 // Unwrap the key. | |
2963 blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull(); | |
2964 EXPECT_STATUS_SUCCESS( | |
2965 UnwrapKey(blink::WebCryptoKeyFormatJwk, | |
2966 CryptoData(wrapped_key_data), | |
2967 private_wrapping_key, | |
2968 wrapping_algorithm, | |
2969 CreateAesCbcAlgorithm(std::vector<uint8>(0, 16)), | |
2970 true, | |
2971 blink::WebCryptoKeyUsageEncrypt, | |
2972 &unwrapped_key)); | |
2973 EXPECT_FALSE(unwrapped_key.isNull()); | |
2974 EXPECT_TRUE(unwrapped_key.handle()); | |
2975 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, unwrapped_key.type()); | |
2976 EXPECT_EQ(blink::WebCryptoAlgorithmIdAesCbc, unwrapped_key.algorithm().id()); | |
2977 EXPECT_EQ(true, unwrapped_key.extractable()); | |
2978 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, unwrapped_key.usages()); | |
2979 | |
2980 // Export the unwrapped key and compare to the original. | |
2981 blink::WebArrayBuffer raw_key; | |
2982 EXPECT_STATUS_SUCCESS( | |
2983 ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key)); | |
2984 EXPECT_TRUE(ArrayBufferMatches(key_data, raw_key)); | |
2985 } | |
2986 | |
2987 TEST_F(SharedCryptoTest, MAYBE(RsaEsJwkSymkeyWrapUnwrapRoundTrip)) { | |
2988 // Generate the symkey to be wrapped (256-bit AES-CBC key). | |
2989 const blink::WebCryptoAlgorithm algorithm = CreateAesCbcKeyGenAlgorithm(256); | |
2990 blink::WebCryptoKey key_to_wrap = blink::WebCryptoKey::createNull(); | |
2991 ASSERT_STATUS_SUCCESS(GenerateSecretKey( | |
2992 algorithm, true, blink::WebCryptoKeyUsageEncrypt, &key_to_wrap)); | |
2993 | |
2994 // Import the wrapping key pair. | |
2995 const blink::WebCryptoAlgorithm wrapping_algorithm = | |
2996 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); | |
2997 blink::WebCryptoKey public_wrapping_key = blink::WebCryptoKey::createNull(); | |
2998 blink::WebCryptoKey private_wrapping_key = blink::WebCryptoKey::createNull(); | |
2999 ImportRsaKeyPair( | |
3000 HexStringToBytes(kPublicKeySpkiDerHex), | |
3001 HexStringToBytes(kPrivateKeyPkcs8DerHex), | |
3002 wrapping_algorithm, | |
3003 false, | |
3004 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey, | |
3005 &public_wrapping_key, | |
3006 &private_wrapping_key); | |
3007 | |
3008 // Wrap the symkey in JWK format, using the public wrapping key. | |
3009 blink::WebArrayBuffer wrapped_data; | |
3010 ASSERT_STATUS_SUCCESS(WrapKey(blink::WebCryptoKeyFormatJwk, | |
3011 public_wrapping_key, | |
3012 key_to_wrap, | |
3013 wrapping_algorithm, | |
3014 &wrapped_data)); | |
3015 | |
3016 // Unwrap the key using the private wrapping key. | |
3017 blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull(); | |
3018 ASSERT_STATUS_SUCCESS(UnwrapKey(blink::WebCryptoKeyFormatJwk, | |
3019 CryptoData(wrapped_data), | |
3020 private_wrapping_key, | |
3021 wrapping_algorithm, | |
3022 algorithm, | |
3023 true, | |
3024 blink::WebCryptoKeyUsageEncrypt, | |
3025 &unwrapped_key)); | |
3026 | |
3027 // Export the original symkey and the unwrapped key and compare. | |
3028 blink::WebArrayBuffer raw_key1, raw_key2; | |
3029 EXPECT_STATUS_SUCCESS( | |
3030 ExportKey(blink::WebCryptoKeyFormatRaw, key_to_wrap, &raw_key1)); | |
3031 EXPECT_STATUS_SUCCESS( | |
3032 ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key2)); | |
3033 EXPECT_TRUE(ArrayBuffersEqual(raw_key1, raw_key2)); | |
3034 } | |
3035 | |
3036 TEST_F(SharedCryptoTest, MAYBE(RsaEsJwkSymkeyWrapUnwrapErrors)) { | |
3037 // Unwrap JWK-formatted data that can be successfully decrypted, but contains | |
3038 // an error in the plaintext JWK so it cannot be subsequently imported, and | |
3039 // ensure that a generic error is returned instead of some other more specific | |
3040 // error. This shows that information about the plaintext JWK inside the | |
3041 // encrypted data is not leaked. | |
3042 // Note that it is sufficient to consider just one JWK import failure mode | |
3043 // here; others are validated in the ImportJwkFailures Test. The specific | |
3044 // error in the cleartext data below is kty = "foo", which is an invalid kty | |
3045 // value. | |
3046 const std::string cleartext = | |
3047 "{\"alg\":\"A128CBC\",\"ext\":true,\"k\":" | |
3048 "\"j1aibn6Ld9yhXtVDOXJL9Q\",\"key_ops\":[\"encrypt\"],\"kty\":\"foo\"}"; | |
3049 // ciphertext is the cleartext above encrypted with kPublicKeySpkiDerHex, and | |
3050 // can be decrypted with kPrivateKeyPkcs8DerHex | |
3051 const std::vector<uint8> ciphertext = HexStringToBytes( | |
3052 "93bc7bb2ca8502fcf3224e19b12ba455ac32d01695611022c76d3dbdd797c044de047d44" | |
3053 "6c5ed5de5b8f79147ffe1df8da9c894b58881b238d39bd24cecd5c1a98a7c0b07354aee6" | |
3054 "24791b2d549b7ecf1219c49513a1bcbb0fac5c6b59d350b564c44dc3678dadf84b4ea3d1" | |
3055 "32e576e88f8d4a2d27c173e033a97bbda7e47bb9"); | |
3056 | |
3057 // Import the private wrapping key. | |
3058 const blink::WebCryptoAlgorithm wrapping_algorithm = | |
3059 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); | |
3060 blink::WebCryptoKey private_wrapping_key = blink::WebCryptoKey::createNull(); | |
3061 ASSERT_STATUS_SUCCESS(ImportKey( | |
3062 blink::WebCryptoKeyFormatPkcs8, | |
3063 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)), | |
3064 wrapping_algorithm, | |
3065 false, | |
3066 blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageUnwrapKey, | |
3067 &private_wrapping_key)); | |
3068 | |
3069 // Decrypt the ciphertext and validate the result, to prove that decryption is | |
3070 // successful. | |
3071 blink::WebArrayBuffer decrypted_data; | |
3072 ASSERT_STATUS_SUCCESS(Decrypt(wrapping_algorithm, | |
3073 private_wrapping_key, | |
3074 CryptoData(ciphertext), | |
3075 &decrypted_data)); | |
3076 const std::string decrypted(static_cast<const char*>(decrypted_data.data()), | |
3077 decrypted_data.byteLength()); | |
3078 EXPECT_EQ(cleartext, decrypted); | |
3079 | |
3080 // Now treat the ciphertext as a wrapped key and try to unwrap it. Ensure a | |
3081 // generic error is received. | |
3082 blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull(); | |
3083 EXPECT_STATUS(Status::Error(), | |
3084 UnwrapKey(blink::WebCryptoKeyFormatJwk, | |
3085 CryptoData(ciphertext), | |
3086 private_wrapping_key, | |
3087 wrapping_algorithm, | |
3088 CreateAesCbcAlgorithm(std::vector<uint8>(0, 16)), | |
3089 true, | |
3090 blink::WebCryptoKeyUsageEncrypt, | |
3091 &unwrapped_key)); | |
3092 } | |
3093 | |
2992 } // namespace webcrypto | 3094 } // namespace webcrypto |
2993 | 3095 |
2994 } // namespace content | 3096 } // namespace content |
OLD | NEW |