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 2632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2643 EXPECT_EQ(true, unwrapped_key.extractable()); | 2643 EXPECT_EQ(true, unwrapped_key.extractable()); |
2644 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, unwrapped_key.usages()); | 2644 EXPECT_EQ(blink::WebCryptoKeyUsageVerify, unwrapped_key.usages()); |
2645 | 2645 |
2646 // Export the new key's raw data and compare to the known original. | 2646 // Export the new key's raw data and compare to the known original. |
2647 blink::WebArrayBuffer raw_key; | 2647 blink::WebArrayBuffer raw_key; |
2648 EXPECT_STATUS_SUCCESS( | 2648 EXPECT_STATUS_SUCCESS( |
2649 ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key)); | 2649 ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key)); |
2650 EXPECT_TRUE(ArrayBufferMatches(key_data, raw_key)); | 2650 EXPECT_TRUE(ArrayBufferMatches(key_data, raw_key)); |
2651 } | 2651 } |
2652 | 2652 |
2653 TEST_F(SharedCryptoTest, MAYBE(AesKwJwkSymkeyUnwrapErrors)) { | |
2654 // Unwrap data that can be successfully decrypted, but contains an error in | |
2655 // the plaintext JWK, and ensure that a generic error is returned instead of | |
2656 // some other more specific error, to show that information about the | |
2657 // plaintext JWK inside the encrypted data is not leaked. | |
2658 // Specifically, wrapped_key_data below is an AES-KW encrypted version of the | |
2659 // plaintext JWK | |
2660 // { | |
2661 // "alg":"HS256", | |
2662 // "ext":true, | |
2663 // "k":"AAECAwQFBgcICQoLDA0ODwABAgMEBQYHCAkKCwwNDg8", | |
2664 // "key_ops":["verify"], | |
2665 // "kty":"foo" <-- Invalid kty value | |
2666 // } | |
2667 // Recall that unwrapKey = decrypt followed by import. The wrapped_key_data | |
2668 // will decrypt successfully, but the import step will fail because of the bad | |
2669 // kty value. But unlike the standalone ImportKey() method which returns | |
2670 // ErrorJwkUnrecognizedKty in this case, the error returned must be just | |
2671 // Error::Status(). | |
2672 // Note that it is sufficient to consider just one JWK import failure mode | |
2673 // here; others are validated in the ImportJwkFailures Test. | |
2674 const std::vector<uint8> wrapped_key_data = HexStringToBytes( | |
2675 "8d5ad45f5be6195a7a5944f0cf521bbae255daea140d4712985bb63ca1de1a318fbc49ff" | |
2676 "307bd91bfafd7e9ea2057a2ddabb42ba94e319465972d165e5cc42785ad5cfa36159d5cc" | |
2677 "50084133eae85a22bf8f7cb35f3c07b7c06480dec745d9ce4d4bfce45a6cbc2d39263ab7" | |
2678 "073fc346724841f872f7148d"); | |
2679 const std::vector<uint8> wrapping_key_data = | |
2680 HexStringToBytes("000102030405060708090A0B0C0D0E0F"); | |
2681 const blink::WebCryptoAlgorithm wrapping_algorithm = | |
2682 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdAesKw); | |
2683 | |
2684 // Import the wrapping key. | |
2685 blink::WebCryptoKey wrapping_key = ImportSecretKeyFromRaw( | |
2686 wrapping_key_data, wrapping_algorithm, blink::WebCryptoKeyUsageUnwrapKey); | |
2687 | |
2688 // Unwrap and ensure a generic error is received. | |
2689 blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull(); | |
2690 EXPECT_STATUS(Status::Error(), | |
2691 UnwrapKey(blink::WebCryptoKeyFormatJwk, | |
2692 CryptoData(wrapped_key_data), | |
2693 wrapping_key, | |
2694 wrapping_algorithm, | |
2695 blink::WebCryptoAlgorithm::createNull(), | |
2696 true, | |
2697 blink::WebCryptoKeyUsageVerify, | |
2698 &unwrapped_key)); | |
2699 | |
2700 // FIXME(padolph): The check above can fail if the AES-KW decryption step | |
2701 // failed, which masks the test result desired here. For now we have to just | |
2702 // trust the result because I say so. | |
2703 // Once RSA-ES unwrapping is implemented, port this test to use that wrapping | |
2704 // algorithm instead of AES-KW. Unlike AES-KW, RSA-ES supports both the | |
2705 // decrypt and unwrapKey usages, so we can validate successful decryption of | |
2706 // wrapped_key_data prior to seeing the unwrapKey (import) failure. | |
2707 } | |
2708 | |
2709 // TODO(eroman): | 2653 // TODO(eroman): |
2710 // * Test decryption when the tag length exceeds input size | 2654 // * Test decryption when the tag length exceeds input size |
2711 // * Test decryption with empty input | 2655 // * Test decryption with empty input |
2712 // * Test decryption with tag length of 0. | 2656 // * Test decryption with tag length of 0. |
2713 TEST_F(SharedCryptoTest, MAYBE(AesGcmSampleSets)) { | 2657 TEST_F(SharedCryptoTest, MAYBE(AesGcmSampleSets)) { |
2714 // Some Linux test runners may not have a new enough version of NSS. | 2658 // Some Linux test runners may not have a new enough version of NSS. |
2715 if (!SupportsAesGcm()) { | 2659 if (!SupportsAesGcm()) { |
2716 LOG(WARNING) << "AES GCM not supported, skipping tests"; | 2660 LOG(WARNING) << "AES GCM not supported, skipping tests"; |
2717 return; | 2661 return; |
2718 } | 2662 } |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2993 UnwrapKey(blink::WebCryptoKeyFormatRaw, | 2937 UnwrapKey(blink::WebCryptoKeyFormatRaw, |
2994 CryptoData(big_data), | 2938 CryptoData(big_data), |
2995 private_key, | 2939 private_key, |
2996 wrapping_algorithm, | 2940 wrapping_algorithm, |
2997 key_algorithm, | 2941 key_algorithm, |
2998 true, | 2942 true, |
2999 blink::WebCryptoKeyUsageSign, | 2943 blink::WebCryptoKeyUsageSign, |
3000 &unwrapped_key)); | 2944 &unwrapped_key)); |
3001 } | 2945 } |
3002 | 2946 |
| 2947 TEST_F(SharedCryptoTest, MAYBE(RsaEsJwkSymkeyUnwrapKnownAnswer)) { |
| 2948 // The following data lists a known 128-bit AES-CBC key, then a JWK |
| 2949 // representation of this key that was encrypted ("wrapped") using |
| 2950 // RSAES-PKCS1-v1_5 and kPublicKeySpkiDerHex as the wrapping key. |
| 2951 // For reference, the intermediate clear JWK is |
| 2952 // {"alg":"A128CBC","ext":true,"k":<b64url>,"key_ops":["encrypt"],"kty":"oct"} |
| 2953 const std::vector<uint8> key_data = |
| 2954 HexStringToBytes("8f56a26e7e8b77dca15ed54339724bf5"); |
| 2955 const std::vector<uint8> wrapped_key_data = HexStringToBytes( |
| 2956 "9debcabd9c731d6a779622dbef38635419c409b3077af67b3cf0601b2da7054f2ec26156" |
| 2957 "06bb764e4986f45dd09ce660432a7abbac48b5249924f12dea52275b6d67d8b8a2f63525" |
| 2958 "fbbf67d61244c1afa9e30857b87b7a48cdc0b3196dc1477738cbf9e42ea65d5e0edc3b05" |
| 2959 "afafadc7d7400e26a51270d251040d51ce46cecc"); |
| 2960 const blink::WebCryptoAlgorithm wrapping_algorithm = |
| 2961 webcrypto::CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); |
| 2962 |
| 2963 // Import the private wrapping key. |
| 2964 blink::WebCryptoKey private_wrapping_key = blink::WebCryptoKey::createNull(); |
| 2965 ASSERT_STATUS_SUCCESS(ImportKey( |
| 2966 blink::WebCryptoKeyFormatPkcs8, |
| 2967 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)), |
| 2968 wrapping_algorithm, |
| 2969 false, |
| 2970 blink::WebCryptoKeyUsageDecrypt | blink::WebCryptoKeyUsageUnwrapKey, |
| 2971 &private_wrapping_key)); |
| 2972 |
| 2973 // Unwrap the key. |
| 2974 blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull(); |
| 2975 EXPECT_STATUS_SUCCESS( |
| 2976 UnwrapKey(blink::WebCryptoKeyFormatJwk, |
| 2977 CryptoData(wrapped_key_data), |
| 2978 private_wrapping_key, |
| 2979 wrapping_algorithm, |
| 2980 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), |
| 2981 true, |
| 2982 blink::WebCryptoKeyUsageEncrypt, |
| 2983 &unwrapped_key)); |
| 2984 EXPECT_FALSE(unwrapped_key.isNull()); |
| 2985 EXPECT_TRUE(unwrapped_key.handle()); |
| 2986 EXPECT_EQ(blink::WebCryptoKeyTypeSecret, unwrapped_key.type()); |
| 2987 EXPECT_EQ(blink::WebCryptoAlgorithmIdAesCbc, unwrapped_key.algorithm().id()); |
| 2988 EXPECT_EQ(true, unwrapped_key.extractable()); |
| 2989 EXPECT_EQ(blink::WebCryptoKeyUsageEncrypt, unwrapped_key.usages()); |
| 2990 |
| 2991 // Export the unwrapped key and compare to the original. |
| 2992 blink::WebArrayBuffer raw_key; |
| 2993 EXPECT_STATUS_SUCCESS( |
| 2994 ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key)); |
| 2995 EXPECT_TRUE(ArrayBufferMatches(key_data, raw_key)); |
| 2996 } |
| 2997 |
| 2998 TEST_F(SharedCryptoTest, MAYBE(RsaEsJwkSymkeyWrapUnwrapRoundTrip)) { |
| 2999 // Generate the symkey to be wrapped (256-bit AES-CBC key). |
| 3000 const blink::WebCryptoAlgorithm gen_algorithm = |
| 3001 CreateAesCbcKeyGenAlgorithm(256); |
| 3002 blink::WebCryptoKey key_to_wrap = blink::WebCryptoKey::createNull(); |
| 3003 ASSERT_STATUS_SUCCESS(GenerateSecretKey( |
| 3004 gen_algorithm, true, blink::WebCryptoKeyUsageEncrypt, &key_to_wrap)); |
| 3005 |
| 3006 // Import the wrapping key pair. |
| 3007 const blink::WebCryptoAlgorithm wrapping_algorithm = |
| 3008 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); |
| 3009 blink::WebCryptoKey public_wrapping_key = blink::WebCryptoKey::createNull(); |
| 3010 blink::WebCryptoKey private_wrapping_key = blink::WebCryptoKey::createNull(); |
| 3011 ImportRsaKeyPair( |
| 3012 HexStringToBytes(kPublicKeySpkiDerHex), |
| 3013 HexStringToBytes(kPrivateKeyPkcs8DerHex), |
| 3014 wrapping_algorithm, |
| 3015 false, |
| 3016 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey, |
| 3017 &public_wrapping_key, |
| 3018 &private_wrapping_key); |
| 3019 |
| 3020 // Wrap the symkey in JWK format, using the public wrapping key. |
| 3021 blink::WebArrayBuffer wrapped_data; |
| 3022 ASSERT_STATUS_SUCCESS(WrapKey(blink::WebCryptoKeyFormatJwk, |
| 3023 public_wrapping_key, |
| 3024 key_to_wrap, |
| 3025 wrapping_algorithm, |
| 3026 &wrapped_data)); |
| 3027 |
| 3028 // Unwrap the key using the private wrapping key. |
| 3029 blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull(); |
| 3030 ASSERT_STATUS_SUCCESS( |
| 3031 UnwrapKey(blink::WebCryptoKeyFormatJwk, |
| 3032 CryptoData(wrapped_data), |
| 3033 private_wrapping_key, |
| 3034 wrapping_algorithm, |
| 3035 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCbc), |
| 3036 true, |
| 3037 blink::WebCryptoKeyUsageEncrypt, |
| 3038 &unwrapped_key)); |
| 3039 |
| 3040 // Export the original symkey and the unwrapped key and compare. |
| 3041 blink::WebArrayBuffer raw_key1, raw_key2; |
| 3042 EXPECT_STATUS_SUCCESS( |
| 3043 ExportKey(blink::WebCryptoKeyFormatRaw, key_to_wrap, &raw_key1)); |
| 3044 EXPECT_STATUS_SUCCESS( |
| 3045 ExportKey(blink::WebCryptoKeyFormatRaw, unwrapped_key, &raw_key2)); |
| 3046 EXPECT_TRUE(ArrayBuffersEqual(raw_key1, raw_key2)); |
| 3047 } |
| 3048 |
| 3049 TEST_F(SharedCryptoTest, MAYBE(RsaEsJwkSymkeyWrapUnwrapErrors)) { |
| 3050 // Unwrap JWK-formatted data that can be successfully decrypted, but contains |
| 3051 // an error in the plaintext JWK so it cannot be subsequently imported, and |
| 3052 // ensure that a generic error is returned instead of some other more specific |
| 3053 // error. This shows that information about the plaintext JWK inside the |
| 3054 // encrypted data is not leaked. |
| 3055 // Note that it is sufficient to consider just one JWK import failure mode |
| 3056 // here; others are validated in the ImportJwkFailures Test. The specific |
| 3057 // error in the cleartext data below is kty = "foo", which is an invalid kty |
| 3058 // value. |
| 3059 const std::string cleartext = |
| 3060 "{\"alg\":\"A128CBC\",\"ext\":true,\"k\":" |
| 3061 "\"j1aibn6Ld9yhXtVDOXJL9Q\",\"key_ops\":[\"encrypt\"],\"kty\":\"foo\"}"; |
| 3062 // ciphertext is the cleartext above encrypted with kPublicKeySpkiDerHex, and |
| 3063 // can be decrypted with kPrivateKeyPkcs8DerHex |
| 3064 const std::vector<uint8> ciphertext = HexStringToBytes( |
| 3065 "93bc7bb2ca8502fcf3224e19b12ba455ac32d01695611022c76d3dbdd797c044de047d44" |
| 3066 "6c5ed5de5b8f79147ffe1df8da9c894b58881b238d39bd24cecd5c1a98a7c0b07354aee6" |
| 3067 "24791b2d549b7ecf1219c49513a1bcbb0fac5c6b59d350b564c44dc3678dadf84b4ea3d1" |
| 3068 "32e576e88f8d4a2d27c173e033a97bbda7e47bb9"); |
| 3069 |
| 3070 // Import the private decryption key. |
| 3071 const blink::WebCryptoAlgorithm algorithm = |
| 3072 CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5); |
| 3073 blink::WebCryptoKey private_decryption_key = |
| 3074 blink::WebCryptoKey::createNull(); |
| 3075 ASSERT_STATUS_SUCCESS( |
| 3076 ImportKey(blink::WebCryptoKeyFormatPkcs8, |
| 3077 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)), |
| 3078 algorithm, |
| 3079 false, |
| 3080 blink::WebCryptoKeyUsageDecrypt, |
| 3081 &private_decryption_key)); |
| 3082 |
| 3083 // Decrypt the ciphertext and validate the result, to prove that decryption is |
| 3084 // successful. |
| 3085 blink::WebArrayBuffer decrypted_data; |
| 3086 ASSERT_STATUS_SUCCESS(Decrypt(algorithm, |
| 3087 private_decryption_key, |
| 3088 CryptoData(ciphertext), |
| 3089 &decrypted_data)); |
| 3090 const std::string decrypted(static_cast<const char*>(decrypted_data.data()), |
| 3091 decrypted_data.byteLength()); |
| 3092 EXPECT_EQ(cleartext, decrypted); |
| 3093 |
| 3094 // Import the private wrapping key. Note this is the same underlying keying |
| 3095 // material used for private_decryption_key above. The only difference is that |
| 3096 // it has unwrap rather than decrypt usage. |
| 3097 blink::WebCryptoKey private_wrapping_key = blink::WebCryptoKey::createNull(); |
| 3098 ASSERT_STATUS_SUCCESS( |
| 3099 ImportKey(blink::WebCryptoKeyFormatPkcs8, |
| 3100 CryptoData(HexStringToBytes(kPrivateKeyPkcs8DerHex)), |
| 3101 algorithm, |
| 3102 false, |
| 3103 blink::WebCryptoKeyUsageUnwrapKey, |
| 3104 &private_wrapping_key)); |
| 3105 |
| 3106 // Treat the ciphertext as a wrapped key and try to unwrap it. Ensure a |
| 3107 // generic error is received. |
| 3108 blink::WebCryptoKey unwrapped_key = blink::WebCryptoKey::createNull(); |
| 3109 EXPECT_STATUS(Status::Error(), |
| 3110 UnwrapKey(blink::WebCryptoKeyFormatJwk, |
| 3111 CryptoData(ciphertext), |
| 3112 private_wrapping_key, |
| 3113 algorithm, |
| 3114 CreateAesCbcAlgorithm(std::vector<uint8>(0, 16)), |
| 3115 true, |
| 3116 blink::WebCryptoKeyUsageEncrypt, |
| 3117 &unwrapped_key)); |
| 3118 } |
| 3119 |
3003 } // namespace webcrypto | 3120 } // namespace webcrypto |
3004 | 3121 |
3005 } // namespace content | 3122 } // namespace content |
OLD | NEW |