1 //**********************************************************************************
2 //EncryptPad Copyright 2015 Evgeny Pokhilko
3 //<evpomail@gmail.com> <http://www.evpo.net/encryptpad>
4 //
5 //This file is part of EncryptPad
6 //
7 //EncryptPad is free software: you can redistribute it and/or modify
8 //it under the terms of the GNU General Public License as published by
9 //the Free Software Foundation, either version 2 of the License, or
10 //(at your option) any later version.
11 //
12 //EncryptPad is distributed in the hope that it will be useful,
13 //but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 //GNU General Public License for more details.
16 //
17 //You should have received a copy of the GNU General Public License
18 //along with EncryptPad. If not, see <http://www.gnu.org/licenses/>.
19 //**********************************************************************************
20 #include <string>
21 #include <cstdio>
22 #include <iostream>
23 #include <fstream>
24 #include <utility>
25 #include <tuple>
26 #include "gtest/gtest.h"
27 #include "encryptor.h"
28
29
30 using namespace std;
31 using namespace EncryptPadEncryptor;
32 using namespace Botan;
33 using namespace EncryptPad;
34
35 class EncryptorFixtureBase
36 {
37 protected:
38 Encryptor encryptor_; // encryptor should go first because it has Botan library initializer
39 SecureVector<byte> initial_string_;
40 SecureVector<byte> buffer_;
41 PacketMetadata metadata_;
42 static const string text_to_encrypt_;
43 static const string temp_file_;
44 static const string x2_key_file_;
45
SetUpBase()46 void SetUpBase()
47 {
48 initial_string_ = SecureVector<byte>(text_to_encrypt_.begin(),
49 text_to_encrypt_.end());
50 metadata_= PacketMetadata();
51 metadata_.cipher_algo = kDefaultCipherAlgo;
52 metadata_.hash_algo = kDefaultHashAlgo;
53 metadata_.compression = kDefaultCompression;
54 metadata_.iterations = kDefaultIterations;
55 metadata_.persist_key_path = false;
56 metadata_.is_binary = true;
57 metadata_.file_name = "_CONSOLE";
58 }
59
TearDownBase()60 void TearDownBase()
61 {
62 encryptor_.SetIsPlainText();
63 buffer_.clear();
64 remove(temp_file_.c_str());
65 }
66 };
67
68
69 const string EncryptorFixtureBase::text_to_encrypt_ = "Hello World";
70 const string EncryptorFixtureBase::temp_file_ = "file.epad";
71 const string EncryptorFixtureBase::x2_key_file_ = "x2.key";
72
73 class EncryptorFixture : public EncryptorFixtureBase, public ::testing::Test
74 {
75 protected:
SetUp()76 virtual void SetUp()
77 {
78 SetUpBase();
79 }
80
TearDown()81 virtual void TearDown()
82 {
83 TearDownBase();
84 }
85
86 };
87
88 namespace {
FromSecureVectorToString(const SecureVector<byte> & sec_vec)89 string FromSecureVectorToString(const SecureVector<byte> &sec_vec)
90 {
91 const char *sec_vec_buf = reinterpret_cast<const char *>(sec_vec.data());
92 return string(sec_vec_buf, sec_vec_buf + sec_vec.size());
93 }
94
CopyFile(string file_from,string file_to)95 bool CopyFile(string file_from, string file_to)
96 {
97 ifstream src_stm(file_from, ifstream::binary);
98 if(src_stm.fail())
99 return false;
100 ofstream dst_stm(file_to, ofstream::binary);
101 if(dst_stm.fail())
102 return false;
103 if(dst_stm << src_stm.rdbuf())
104 return true;
105 else
106 return false;
107 }
108
CreateFile(string fileName,string content)109 void CreateFile(string fileName, string content)
110 {
111 remove(fileName.c_str());
112 ofstream stm(fileName);
113 stm << content;
114 }
115 }
116
TEST_F(EncryptorFixture,When_plain_text_without_X2_File_is_saved_in_plain_text)117 TEST_F(EncryptorFixture, When_plain_text_without_X2_File_is_saved_in_plain_text)
118 {
119 // Arrange
120
121 // Act
122 EpadResult save_result = encryptor_.Save(temp_file_, initial_string_,
123 "", false, &metadata_);
124
125 // Assert
126 ifstream stm(temp_file_);
127 string str;
128 getline(stm, str, '\0');
129
130 ASSERT_EQ(EpadResult::Success, save_result);
131 ASSERT_EQ(text_to_encrypt_, str);
132 }
133
TEST_F(EncryptorFixture,When_file_is_plain_text_File_is_loaded_without_passphrase_and_X2)134 TEST_F(EncryptorFixture, When_file_is_plain_text_File_is_loaded_without_passphrase_and_X2)
135 {
136 // Arrange
137 ofstream stm(temp_file_);
138 stm << text_to_encrypt_;
139 stm.close();
140
141 // Act
142 EpadResult load_result = encryptor_.Load(temp_file_, buffer_);
143
144 // Assert
145 ASSERT_EQ(EpadResult::Success, load_result);
146 ASSERT_EQ(text_to_encrypt_, FromSecureVectorToString(buffer_));
147 }
148
149
150 // Exceptions
151
TEST_F(EncryptorFixture,When_passphrase_is_wrong_and_without_X2_Encryption_error)152 TEST_F(EncryptorFixture, When_passphrase_is_wrong_and_without_X2_Encryption_error)
153 {
154 // Arrange
155 encryptor_.SetPassphrase("123", &metadata_);
156 // encryptor_.Save(temp_file_, initial_string_);
157 // encryptor_.SetPassphrase("321", &metadata_);
158 //
159 // // Act
160 // EpadResult load_result = encryptor_.Load(temp_file_, buffer_);
161 //
162 // // Assert
163 // ASSERT_EQ(EpadResult::EncryptionError, load_result);
164 }
165
TEST_F(EncryptorFixture,When_passphrase_is_correct_and_X2_file_does_not_exist_X2_key_IO_error)166 TEST_F(EncryptorFixture, When_passphrase_is_correct_and_X2_file_does_not_exist_X2_key_IO_error)
167 {
168 // Arrange
169 encryptor_.SetPassphrase("123", &metadata_);
170 bool persist_x2_location = false;
171 encryptor_.Save(temp_file_, initial_string_, x2_key_file_, persist_x2_location,
172 &metadata_);
173
174 // Act
175 EpadResult load_result = encryptor_.Load(temp_file_, buffer_, "i_dont_exist.key",
176 nullptr, &metadata_);
177
178 // Assert
179 ASSERT_EQ(EpadResult::IOErrorKeyFile, load_result);
180 }
181
TEST_F(EncryptorFixture,When_passphrase_is_correct_and_X2_file_persisted_and_does_not_exist_X2_IO_error)182 TEST_F(EncryptorFixture, When_passphrase_is_correct_and_X2_file_persisted_and_does_not_exist_X2_IO_error)
183 {
184 // Arrange
185 encryptor_.SetPassphrase("123", &metadata_);
186 bool persist_x2_location = true;
187 remove("x2_copy.key");
188 CopyFile(x2_key_file_, "x2_copy.key");
189 encryptor_.Save(temp_file_, initial_string_, "x2_copy.key", persist_x2_location, &metadata_);
190 remove("x2_copy.key");
191
192 // Act
193 EpadResult load_result = encryptor_.Load(temp_file_, buffer_,
194 "", nullptr, &metadata_);
195
196 // Assert
197 ASSERT_EQ(EpadResult::IOErrorKeyFile, load_result);
198 }
199
TEST_F(EncryptorFixture,When_passphrase_is_correct_and_X2_file_is_wrong_Encryption_error)200 TEST_F(EncryptorFixture, When_passphrase_is_correct_and_X2_file_is_wrong_Encryption_error)
201 {
202 // Arrange
203 encryptor_.SetPassphrase("123", &metadata_);
204 CreateFile("x2-invalid.key", "FKeYEq3z3S8krxeWX+gFRnmkTzRTjwyjRxgOFw+eP3s=");
205
206
207 bool persist_x2_location = true;
208 encryptor_.Save(temp_file_, initial_string_, x2_key_file_, persist_x2_location, &metadata_);
209
210
211 // Act
212 EpadResult load_result = encryptor_.Load(temp_file_, buffer_, "x2-invalid.key", nullptr,
213 &metadata_);
214 remove("x2-invalid.key");
215
216 // Assert
217 ASSERT_EQ(EpadResult::InvalidKeyFile, load_result);
218 }
219
TEST_F(EncryptorFixture,When_invalid_X2_file_Save_result_is_invalid_X2_file)220 TEST_F(EncryptorFixture, When_invalid_X2_file_Save_result_is_invalid_X2_file)
221 {
222 // Arrange
223 encryptor_.SetPassphrase("123", &metadata_);
224 // CreateFile("x2-invalid.key", "ICANTBEAKEY DFSFSDFSDF\t\r\n^*&%*&^*&^*(&^");
225 CreateFile("x2-invalid.key", "");
226 bool persist_x2_location = false;
227
228 // Act
229 EpadResult save_result = encryptor_.Save(temp_file_, initial_string_, "x2-invalid.key", persist_x2_location, &metadata_);
230 remove("x2-invalid.key");
231
232 // Assert
233 ASSERT_EQ(EpadResult::InvalidKeyFile, save_result);
234 }
235
TEST_F(EncryptorFixture,When_passphrase_is_correct_and_X2_file_is_invalid_Invalid_X2_file)236 TEST_F(EncryptorFixture, When_passphrase_is_correct_and_X2_file_is_invalid_Invalid_X2_file)
237 {
238 // Arrange
239
240 encryptor_.SetPassphrase("123", &metadata_);
241 CreateFile("x2-invalid.key", "ICANTBEAKEY DFSFSDFSDF\t\r\n^*&%*&^*&^*(&^");
242 bool persist_x2_location = false;
243 encryptor_.Save(temp_file_, initial_string_, x2_key_file_, persist_x2_location, &metadata_);
244
245 // Act
246 EpadResult load_result = encryptor_.Load(temp_file_, buffer_, "x2-invalid.key", nullptr,
247 &metadata_);
248 remove("x2-invalid.key");
249
250 // Assert
251 ASSERT_EQ(EpadResult::InvalidKeyFile, load_result);
252 }
253
TEST_F(EncryptorFixture,When_plain_text_and_invalid_X2_file_Load_result_is_invalid_X2_file)254 TEST_F(EncryptorFixture, When_plain_text_and_invalid_X2_file_Load_result_is_invalid_X2_file)
255 {
256 // Arrange
257 encryptor_.SetIsPlainText();
258 CreateFile("x2-invalid.key", "ICANTBEAKEY DFSFSDFSDF\t\r\n^*&%*&^*&^*(&^");
259 bool persist_x2_location = false;
260 encryptor_.Save(temp_file_, initial_string_, x2_key_file_, persist_x2_location,
261 &metadata_);
262
263 // Act
264 EpadResult load_result = encryptor_.Load(temp_file_, buffer_, "x2-invalid.key",
265 nullptr, &metadata_);
266 remove("x2-invalid.key");
267
268 // Assert
269 ASSERT_EQ(EpadResult::InvalidKeyFile, load_result);
270 }
271
TEST_F(EncryptorFixture,When_passphrase_and_X2_and_X2_not_persisted_and_loaded_without_X2_Result_is_X2_required)272 TEST_F(EncryptorFixture, When_passphrase_and_X2_and_X2_not_persisted_and_loaded_without_X2_Result_is_X2_required)
273 {
274 // Arrange
275 encryptor_.SetPassphrase("123", &metadata_);
276 bool persiste_x2_location = false;
277 encryptor_.Save(temp_file_, initial_string_, x2_key_file_, persiste_x2_location,
278 &metadata_);
279
280 // Act
281 EpadResult load_result = encryptor_.Load(temp_file_, buffer_, "", nullptr,
282 &metadata_);
283
284 // Assert
285 ASSERT_EQ(EpadResult::KeyFileNotSpecified, load_result);
286 }
287
288 // Disable the test because this test is done in loadFile before coming to Load. However, we leave the test
289 // because this logic may need to move to Encryptor::Load
290 // TEST_F(EncryptorFixture, When_plain_text_and_X2_and_X2_not_persisted_and_loaded_without_X2_Result_is_X2_required)
291 // {
292 // // Arrange
293 // encryptor_.SetIsPlainText();
294 // bool persiste_x2_location = false;
295 // encryptor_.Save(temp_file_, initial_string_, x2_key_file_, persiste_x2_location,
296 // &metadata_);
297 //
298 // // Act
299 // EpadResult load_result = encryptor_.Load(temp_file_, buffer_, "", nullptr,
300 // &metadata_);
301 //
302 // // Assert
303 // ASSERT_EQ(EpadResult::KeyFileNotSpecified, load_result);
304 // }
305
TEST_F(EncryptorFixture,When_passphrase_used_and_saved_without_key_The_result_of_load_with_key_and_passphrase_is_OK)306 TEST_F(EncryptorFixture, When_passphrase_used_and_saved_without_key_The_result_of_load_with_key_and_passphrase_is_OK)
307 {
308 // Arrange
309 encryptor_.SetPassphrase("123", &metadata_);
310 encryptor_.Save(temp_file_, initial_string_, "", false, &metadata_);
311
312 // Act
313 EpadResult load_result = encryptor_.Load(temp_file_, buffer_, x2_key_file_,
314 nullptr, &metadata_);
315
316 // Assert
317 ASSERT_EQ(EpadResult::Success, load_result);
318 }
319
TEST_F(EncryptorFixture,When_passphrase_used_with_persisted_key_Key_information_is_available_after_load)320 TEST_F(EncryptorFixture, When_passphrase_used_with_persisted_key_Key_information_is_available_after_load)
321 {
322 // Arrange
323 encryptor_.SetPassphrase("123", &metadata_);
324 bool persistX2KeyLocation = true;
325 encryptor_.Save(temp_file_, initial_string_, x2_key_file_, persistX2KeyLocation,
326 &metadata_);
327
328 // Act
329 EpadResult load_result = encryptor_.Load(temp_file_, buffer_,
330 "", nullptr, &metadata_);
331
332 // Assert
333 ASSERT_EQ(EpadResult::Success, load_result);
334 ASSERT_EQ(x2_key_file_, encryptor_.GetX2KeyLocation());
335 }
336
337 // Test different combinations saving with key
338
339 struct TestParam
340 {
341 string passphrase;
342 bool usePassphrase;
343 bool useX2;
344 bool persistX2;
345 bool useX2ParameterInLoad;
346 };
347
348 class EncryptorFixtureWithParam : public EncryptorFixtureBase, public ::testing::TestWithParam<TestParam>
349 {
350 public:
351 static TestParam ParameterCombination[];
352
353 protected:
SetUp()354 virtual void SetUp()
355 {
356 SetUpBase();
357 }
358
TearDown()359 virtual void TearDown()
360 {
361 TearDownBase();
362 }
363 };
364
365 TestParam EncryptorFixtureWithParam::ParameterCombination[] =
366 {
367 //pwd usePassphrase useX2 persistX2 useX2ParameterInLoad
368 {"123", true, false, false, false},
369 {"123", true, true, false, true},
370 {"123", true, true, true, false},
371 {"123", true, true, true, true},
372 {"", false, false, false, false},
373 {"", false, true, false, true},
374 // File type identification happens before calling Load
375 // see the comment in
376 // When_plain_text_and_X2_and_X2_not_persisted_and_loaded_without_X2_Result_is_X2_required
377 // {"", false, true, true, false},
378 {"", false, true, true, true}
379 };
380
TEST_P(EncryptorFixtureWithParam,When_combination_of_pwd_X2_persist_File_is_saved_and_loaded)381 TEST_P(EncryptorFixtureWithParam, When_combination_of_pwd_X2_persist_File_is_saved_and_loaded)
382 {
383 // Arrange
384 const TestParam &testParam = GetParam();
385 if(!testParam.passphrase.empty())
386 encryptor_.SetPassphrase(testParam.passphrase.c_str(), &metadata_);
387 else
388 encryptor_.SetIsPlainText();
389
390 // Act
391 EpadResult save_result = encryptor_.Save(
392 temp_file_,
393 initial_string_,
394 testParam.useX2 ? x2_key_file_ : "",
395 testParam.persistX2,
396 &metadata_);
397
398 EpadResult load_result = encryptor_.Load(
399 temp_file_,
400 buffer_,
401 testParam.useX2ParameterInLoad ? x2_key_file_ : "",
402 nullptr,
403 &metadata_);
404
405 string str = FromSecureVectorToString(buffer_);
406
407 // Assert
408 ASSERT_EQ(EpadResult::Success, save_result);
409 ASSERT_EQ(EpadResult::Success, load_result);
410 ASSERT_EQ(text_to_encrypt_, str);
411 }
412
413 INSTANTIATE_TEST_CASE_P(Common, EncryptorFixtureWithParam,
414 ::testing::ValuesIn(EncryptorFixtureWithParam::ParameterCombination));
415