Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(272)

Side by Side Diff: content/child/webcrypto/shared_crypto_unittest.cc

Issue 195893034: [webcrypto] Add JWK symmetric key RSAES-PKCS1-v1_5 wrap / unwrap for NSS. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: upload HEAD~2 Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/child/webcrypto/shared_crypto.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « content/child/webcrypto/shared_crypto.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698