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 <algorithm> | 5 #include <algorithm> |
6 #include <string> | 6 #include <string> |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 // TODO(eroman): Exclude version test for OS_CHROMEOS | 115 // TODO(eroman): Exclude version test for OS_CHROMEOS |
116 #if defined(USE_NSS) | 116 #if defined(USE_NSS) |
117 if (!NSS_VersionCheck("3.16.2")) | 117 if (!NSS_VersionCheck("3.16.2")) |
118 return false; | 118 return false; |
119 #endif | 119 #endif |
120 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); | 120 crypto::ScopedPK11Slot slot(PK11_GetInternalKeySlot()); |
121 return !!PK11_DoesMechanism(slot.get(), CKM_RSA_PKCS_OAEP); | 121 return !!PK11_DoesMechanism(slot.get(), CKM_RSA_PKCS_OAEP); |
122 #endif | 122 #endif |
123 } | 123 } |
124 | 124 |
| 125 bool SupportsAesCtr() { |
| 126 #if defined(USE_OPENSSL) |
| 127 return true; |
| 128 #else |
| 129 return false; |
| 130 #endif |
| 131 } |
| 132 |
125 bool SupportsRsaKeyImport() { | 133 bool SupportsRsaKeyImport() { |
126 // TODO(eroman): Exclude version test for OS_CHROMEOS | 134 // TODO(eroman): Exclude version test for OS_CHROMEOS |
127 #if defined(USE_NSS) | 135 #if defined(USE_NSS) |
128 crypto::EnsureNSSInit(); | 136 crypto::EnsureNSSInit(); |
129 if (!NSS_VersionCheck("3.16.2")) { | 137 if (!NSS_VersionCheck("3.16.2")) { |
130 LOG(WARNING) << "RSA key import is not supported by this version of NSS. " | 138 LOG(WARNING) << "RSA key import is not supported by this version of NSS. " |
131 "Skipping some tests"; | 139 "Skipping some tests"; |
132 return false; | 140 return false; |
133 } | 141 } |
134 #endif | 142 #endif |
(...skipping 27 matching lines...) Expand all Loading... |
162 } | 170 } |
163 | 171 |
164 // Creates an AES-CBC algorithm. | 172 // Creates an AES-CBC algorithm. |
165 blink::WebCryptoAlgorithm CreateAesCbcAlgorithm( | 173 blink::WebCryptoAlgorithm CreateAesCbcAlgorithm( |
166 const std::vector<uint8_t>& iv) { | 174 const std::vector<uint8_t>& iv) { |
167 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( | 175 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( |
168 blink::WebCryptoAlgorithmIdAesCbc, | 176 blink::WebCryptoAlgorithmIdAesCbc, |
169 new blink::WebCryptoAesCbcParams(vector_as_array(&iv), iv.size())); | 177 new blink::WebCryptoAesCbcParams(vector_as_array(&iv), iv.size())); |
170 } | 178 } |
171 | 179 |
| 180 // Creates an AES-CTR algorithm for encryption/decryption. |
| 181 blink::WebCryptoAlgorithm CreateAesCtrAlgorithm( |
| 182 const std::vector<uint8_t>& counter, |
| 183 uint8_t length_bits) { |
| 184 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( |
| 185 blink::WebCryptoAlgorithmIdAesCtr, |
| 186 new blink::WebCryptoAesCtrParams( |
| 187 length_bits, vector_as_array(&counter), counter.size())); |
| 188 } |
| 189 |
172 // Creates an AES-GCM algorithm. | 190 // Creates an AES-GCM algorithm. |
173 blink::WebCryptoAlgorithm CreateAesGcmAlgorithm( | 191 blink::WebCryptoAlgorithm CreateAesGcmAlgorithm( |
174 const std::vector<uint8_t>& iv, | 192 const std::vector<uint8_t>& iv, |
175 const std::vector<uint8_t>& additional_data, | 193 const std::vector<uint8_t>& additional_data, |
176 unsigned int tag_length_bits) { | 194 unsigned int tag_length_bits) { |
177 EXPECT_TRUE(SupportsAesGcm()); | 195 EXPECT_TRUE(SupportsAesGcm()); |
178 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( | 196 return blink::WebCryptoAlgorithm::adoptParamsAndCreate( |
179 blink::WebCryptoAlgorithmIdAesGcm, | 197 blink::WebCryptoAlgorithmIdAesGcm, |
180 new blink::WebCryptoAesGcmParams(vector_as_array(&iv), | 198 new blink::WebCryptoAesGcmParams(vector_as_array(&iv), |
181 iv.size(), | 199 iv.size(), |
(...skipping 4671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4853 unwrapped_private_key, | 4871 unwrapped_private_key, |
4854 &unwrapped_private_key_pkcs8)); | 4872 &unwrapped_private_key_pkcs8)); |
4855 | 4873 |
4856 EXPECT_EQ(public_key_spki, unwrapped_public_key_spki); | 4874 EXPECT_EQ(public_key_spki, unwrapped_public_key_spki); |
4857 EXPECT_EQ(private_key_pkcs8, unwrapped_private_key_pkcs8); | 4875 EXPECT_EQ(private_key_pkcs8, unwrapped_private_key_pkcs8); |
4858 | 4876 |
4859 EXPECT_NE(public_key_spki, wrapped_public_key); | 4877 EXPECT_NE(public_key_spki, wrapped_public_key); |
4860 EXPECT_NE(private_key_pkcs8, wrapped_private_key); | 4878 EXPECT_NE(private_key_pkcs8, wrapped_private_key); |
4861 } | 4879 } |
4862 | 4880 |
| 4881 TEST(WebCryptoAesCtrTest, EncryptDecryptKnownAnswer) { |
| 4882 if (!SupportsAesCtr()) { |
| 4883 LOG(WARNING) << "Skipping test because AES-CTR is not supported"; |
| 4884 return; |
| 4885 } |
| 4886 |
| 4887 scoped_ptr<base::ListValue> tests; |
| 4888 ASSERT_TRUE(ReadJsonTestFileToList("aes_ctr.json", &tests)); |
| 4889 |
| 4890 for (size_t test_index = 0; test_index < tests->GetSize(); ++test_index) { |
| 4891 SCOPED_TRACE(test_index); |
| 4892 base::DictionaryValue* test; |
| 4893 ASSERT_TRUE(tests->GetDictionary(test_index, &test)); |
| 4894 |
| 4895 std::vector<uint8_t> test_key = GetBytesFromHexString(test, "key"); |
| 4896 std::vector<uint8_t> test_counter = GetBytesFromHexString(test, "counter"); |
| 4897 int counter_length_bits = 0; |
| 4898 ASSERT_TRUE(test->GetInteger("length", &counter_length_bits)); |
| 4899 |
| 4900 std::vector<uint8_t> test_plain_text = |
| 4901 GetBytesFromHexString(test, "plain_text"); |
| 4902 std::vector<uint8_t> test_cipher_text = |
| 4903 GetBytesFromHexString(test, "cipher_text"); |
| 4904 |
| 4905 blink::WebCryptoKey key = ImportSecretKeyFromRaw( |
| 4906 test_key, |
| 4907 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCtr), |
| 4908 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); |
| 4909 |
| 4910 EXPECT_EQ(test_key.size() * 8, key.algorithm().aesParams()->lengthBits()); |
| 4911 |
| 4912 std::vector<uint8_t> output; |
| 4913 |
| 4914 // Test encryption. |
| 4915 EXPECT_EQ(Status::Success(), |
| 4916 Encrypt(CreateAesCtrAlgorithm(test_counter, counter_length_bits), |
| 4917 key, |
| 4918 CryptoData(test_plain_text), |
| 4919 &output)); |
| 4920 EXPECT_BYTES_EQ(test_cipher_text, output); |
| 4921 |
| 4922 // Test decryption. |
| 4923 EXPECT_EQ(Status::Success(), |
| 4924 Decrypt(CreateAesCtrAlgorithm(test_counter, counter_length_bits), |
| 4925 key, |
| 4926 CryptoData(test_cipher_text), |
| 4927 &output)); |
| 4928 EXPECT_BYTES_EQ(test_plain_text, output); |
| 4929 } |
| 4930 } |
| 4931 |
| 4932 // The counter block must be exactly 16 bytes. |
| 4933 TEST(WebCryptoAesCtrTest, InvalidCounterBlockLength) { |
| 4934 if (!SupportsAesCtr()) { |
| 4935 LOG(WARNING) << "Skipping test because AES-CTR is not supported"; |
| 4936 return; |
| 4937 } |
| 4938 |
| 4939 const unsigned int kBadCounterBlockLengthBytes[] = {0, 15, 17}; |
| 4940 |
| 4941 blink::WebCryptoKey key = ImportSecretKeyFromRaw( |
| 4942 std::vector<uint8>(16), // 128-bit key of all zeros. |
| 4943 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCtr), |
| 4944 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); |
| 4945 |
| 4946 std::vector<uint8_t> input(32); |
| 4947 std::vector<uint8_t> output; |
| 4948 |
| 4949 for (size_t i = 0; i < arraysize(kBadCounterBlockLengthBytes); ++i) { |
| 4950 std::vector<uint8_t> bad_counter(kBadCounterBlockLengthBytes[i]); |
| 4951 |
| 4952 EXPECT_EQ(Status::ErrorIncorrectSizeAesCtrCounter(), |
| 4953 Encrypt(CreateAesCtrAlgorithm(bad_counter, 128), |
| 4954 key, |
| 4955 CryptoData(input), |
| 4956 &output)); |
| 4957 |
| 4958 EXPECT_EQ(Status::ErrorIncorrectSizeAesCtrCounter(), |
| 4959 Decrypt(CreateAesCtrAlgorithm(bad_counter, 128), |
| 4960 key, |
| 4961 CryptoData(input), |
| 4962 &output)); |
| 4963 } |
| 4964 } |
| 4965 |
| 4966 // The counter length cannot be less than 1 or greater than 128. |
| 4967 TEST(WebCryptoAesCtrTest, InvalidCounterLength) { |
| 4968 if (!SupportsAesCtr()) { |
| 4969 LOG(WARNING) << "Skipping test because AES-CTR is not supported"; |
| 4970 return; |
| 4971 } |
| 4972 |
| 4973 const uint8_t kBadCounterLengthBits[] = {0, 129}; |
| 4974 |
| 4975 blink::WebCryptoKey key = ImportSecretKeyFromRaw( |
| 4976 std::vector<uint8>(16), // 128-bit key of all zeros. |
| 4977 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCtr), |
| 4978 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); |
| 4979 |
| 4980 std::vector<uint8_t> counter(16); |
| 4981 std::vector<uint8_t> input(32); |
| 4982 std::vector<uint8_t> output; |
| 4983 |
| 4984 for (size_t i = 0; i < arraysize(kBadCounterLengthBits); ++i) { |
| 4985 uint8_t bad_counter_length_bits = kBadCounterLengthBits[i]; |
| 4986 |
| 4987 EXPECT_EQ(Status::ErrorInvalidAesCtrCounterLength(), |
| 4988 Encrypt(CreateAesCtrAlgorithm(counter, bad_counter_length_bits), |
| 4989 key, |
| 4990 CryptoData(input), |
| 4991 &output)); |
| 4992 |
| 4993 EXPECT_EQ(Status::ErrorInvalidAesCtrCounterLength(), |
| 4994 Decrypt(CreateAesCtrAlgorithm(counter, bad_counter_length_bits), |
| 4995 key, |
| 4996 CryptoData(input), |
| 4997 &output)); |
| 4998 } |
| 4999 } |
| 5000 |
| 5001 // Tests wrap-around using a 4-bit counter. |
| 5002 // |
| 5003 // Wrap-around is allowed, however if the counter repeats itself an error should |
| 5004 // be thrown. |
| 5005 // |
| 5006 // Using a 4-bit counter it is possible to encrypt 16 blocks. However the 17th |
| 5007 // block would end up wrapping back to the starting value. |
| 5008 TEST(WebCryptoAesCtrTest, OverflowAndRepeatCounter) { |
| 5009 if (!SupportsAesCtr()) { |
| 5010 LOG(WARNING) << "Skipping test because AES-CTR is not supported"; |
| 5011 return; |
| 5012 } |
| 5013 |
| 5014 const uint8_t kCounterLengthBits = 4; |
| 5015 const uint8_t kStartCounter[] = {0, 1, 15}; |
| 5016 |
| 5017 blink::WebCryptoKey key = ImportSecretKeyFromRaw( |
| 5018 std::vector<uint8>(16), // 128-bit key of all zeros. |
| 5019 CreateAlgorithm(blink::WebCryptoAlgorithmIdAesCtr), |
| 5020 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt); |
| 5021 |
| 5022 std::vector<uint8_t> buffer(272); |
| 5023 |
| 5024 // 16 and 17 AES blocks worth of data respectively (AES blocks are 16 bytes |
| 5025 // long). |
| 5026 CryptoData input_16(vector_as_array(&buffer), 256); |
| 5027 CryptoData input_17(vector_as_array(&buffer), 272); |
| 5028 |
| 5029 std::vector<uint8_t> output; |
| 5030 |
| 5031 for (size_t i = 0; i < arraysize(kStartCounter); ++i) { |
| 5032 std::vector<uint8_t> counter(16); |
| 5033 counter[15] = kStartCounter[i]; |
| 5034 |
| 5035 // Baseline test: Encrypting 16 blocks should work (don't bother to check |
| 5036 // output, the known answer tests already do that). |
| 5037 EXPECT_EQ(Status::Success(), |
| 5038 Encrypt(CreateAesCtrAlgorithm(counter, kCounterLengthBits), |
| 5039 key, |
| 5040 input_16, |
| 5041 &output)); |
| 5042 |
| 5043 // Encrypting/Decrypting 17 however should fail. |
| 5044 EXPECT_EQ(Status::ErrorAesCtrInputTooLongCounterRepeated(), |
| 5045 Encrypt(CreateAesCtrAlgorithm(counter, kCounterLengthBits), |
| 5046 key, |
| 5047 input_17, |
| 5048 &output)); |
| 5049 EXPECT_EQ(Status::ErrorAesCtrInputTooLongCounterRepeated(), |
| 5050 Decrypt(CreateAesCtrAlgorithm(counter, kCounterLengthBits), |
| 5051 key, |
| 5052 input_17, |
| 5053 &output)); |
| 5054 } |
| 5055 } |
| 5056 |
4863 } // namespace | 5057 } // namespace |
4864 | 5058 |
4865 } // namespace webcrypto | 5059 } // namespace webcrypto |
4866 | 5060 |
4867 } // namespace content | 5061 } // namespace content |
OLD | NEW |