1 /*===========================================================================
2  *
3  *                            PUBLIC DOMAIN NOTICE
4  *               National Center for Biotechnology Information
5  *
6  *  This software/database is a "United States Government Work" under the
7  *  terms of the United States Copyright Act.  It was written as part of
8  *  the author's official duties as a United States Government employee and
9  *  thus cannot be copyrighted.  This software/database is freely available
10  *  to the public for use. The National Library of Medicine and the U.S.
11  *  Government have not placed any restriction on its use or reproduction.
12  *
13  *  Although all reasonable efforts have been taken to ensure the accuracy
14  *  and reliability of the software and data, the NLM and the U.S.
15  *  Government do not and cannot warrant the performance or results that
16  *  may be obtained by using this software or data. The NLM and the U.S.
17  *  Government disclaim all warranties, express or implied, including
18  *  warranties of performance, merchantability or fitness for any particular
19  *  purpose.
20  *
21  *  Please cite the author in any work or product based on this material.
22  *
23  * ===========================================================================
24  *
25  */
26 
27 /**
28  * Unit tests for KEncDecTestSuite
29  */
30 
31 #include <ktst/unit_test.hpp>
32 #include <krypto/key.h>
33 #include <krypto/encfile.h>
34 #include <krypto/encfile-priv.h>
35 #include <krypto/reencfile.h>
36 #include <kfs/impl.h>
37 #include <klib/rc.h>
38 #include <klib/log.h>
39 #include <kapp/args.h>
40 #include <kfg/config.h>
41 
42 #include "test-cmn.hpp"
43 
44 #include <string.h>
45 #include <stdio.h>
46 
47 TEST_SUITE(KEncDecTestSuite);
48 
TEST_CASE(KEncryptDecrypt)49 TEST_CASE(KEncryptDecrypt)
50 {
51     const char pw [] = "first pw";
52     KKey key;
53     REQUIRE_RC (KKeyInitUpdate (&key, kkeyAES128, pw, strlen (pw)));
54 
55     const char enc_file_path_fmt [] = TMP_FOLDER "/enc_file%llu";
56 
57     KFile * enc_file, * pt_file;
58 
59     struct KDirectory * current_dir;
60     REQUIRE_RC ( KDirectoryNativeDir ( &current_dir ) );
61 
62     // just in case if it still there
63     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
64 
65     uint64_t file_sizes_n_32k[] = { 0, 1, 2, 10, 46, 51 };
66     int8_t file_size_variants[] = { -2, -1, 0, 1, 2 };
67 
68     const uint8_t* file_fillers[] = { (const uint8_t *)"\0", (const uint8_t *)"\1\2\3\0" };
69     size_t file_fillers_sizes[] = { 1, 4 };
70 
71     assert( sizeof file_fillers / sizeof file_fillers[0] == sizeof file_fillers_sizes / sizeof file_fillers_sizes[0] );
72 
73     for (size_t filler_index = 0; filler_index < sizeof file_fillers / sizeof file_fillers[0]; ++filler_index )
74     {
75         printf("filler pattern: ");
76         for (size_t i = 0; i < file_fillers_sizes[filler_index]; ++i)
77         {
78             printf("0x%X ", file_fillers[filler_index][i]);
79         }
80         printf("\n");
81         for (size_t i = 0; i < sizeof file_sizes_n_32k / sizeof file_sizes_n_32k[0]; ++i)
82         {
83             for (size_t j = 0; j < sizeof file_size_variants / sizeof file_size_variants[0]; ++j)
84             {
85                 if (file_sizes_n_32k[i] == 0 && file_size_variants[j] <= 0)
86                 {
87                     continue;
88                 }
89 
90                 uint64_t file_size = file_sizes_n_32k[i] * BLOCK_32K_SIZE + file_size_variants[j];
91 
92                 char file_path[1024];
93                 sprintf(file_path, enc_file_path_fmt, ( long long unsigned int ) file_size);
94 
95                 printf("encrypting/decrypting file %s, size: %llu, i: %zu, j: %zu\n", file_path, ( long long unsigned int ) file_size, i, j);
96 
97                 // create file
98                 REQUIRE_RC ( TCreateEncFile( current_dir, file_path, TFileOpenMode_ReadWrite, &key, &enc_file ) );
99 
100                 // write file
101                 REQUIRE_RC ( TFillFile( enc_file, file_fillers[filler_index], file_fillers_sizes[filler_index], file_size ) );
102 
103                 uint64_t size_data_actual;
104                 REQUIRE_RC ( KFileSize ( enc_file, &size_data_actual ) );
105 
106                 // check content size
107                 REQUIRE ( file_size == size_data_actual );
108 
109                 REQUIRE_RC ( KFileRelease ( enc_file ) );
110 
111                 // check raw file size and checksums
112                 REQUIRE_RC ( TOpenPtFile ( current_dir, file_path, TFileOpenMode_Read, &pt_file ) );
113 
114                 uint64_t size_raw;
115                 REQUIRE_RC ( KFileSize ( pt_file, &size_raw ) );
116                 REQUIRE ( size_raw == TEncSizeFromPtSize(size_data_actual) );
117 
118                 REQUIRE_RC ( KEncFileValidate( pt_file ) );
119 
120                 REQUIRE_RC ( KFileRelease ( pt_file ) );
121 
122                 // check file content
123                 REQUIRE_RC ( TOpenEncFile( current_dir, file_path, TFileOpenMode_Read, &key, &enc_file ) );
124 
125                 REQUIRE_RC ( TCheckFileContent( enc_file, file_fillers[filler_index], file_fillers_sizes[filler_index] ) );
126 
127                 REQUIRE_RC ( KFileRelease ( enc_file ) );
128             }
129         }
130     }
131 
132     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
133     REQUIRE_RC ( KDirectoryRelease ( current_dir ) );
134 }
135 
TEST_CASE(KDecryptZeroRawSize)136 TEST_CASE(KDecryptZeroRawSize)
137 {
138     const char pw [] = "first pw";
139     KKey key;
140     REQUIRE_RC (KKeyInitUpdate (&key, kkeyAES128, pw, strlen (pw)));
141 
142     const char file_path [] = TMP_FOLDER "/zero_size_file_to_dec";
143 
144     KFile * enc_file, * pt_file;
145 
146     uint64_t file_size;
147 
148     struct KDirectory * current_dir;
149     REQUIRE_RC ( KDirectoryNativeDir ( &current_dir ) );
150 
151     // just in case if it still there
152     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
153     // create file
154     REQUIRE_RC ( TCreatePtFile( current_dir, file_path, TFileOpenMode_ReadWrite, &pt_file ) );
155     REQUIRE_RC ( KFileSize ( pt_file, &file_size ) );
156     REQUIRE ( file_size == 0 );
157     REQUIRE_RC ( KFileRelease ( pt_file ) );
158 
159     LOGMSG ( klogWarn, "Expect errors after this line:" );
160     REQUIRE ( TOpenEncFile( current_dir, file_path, TFileOpenMode_Read, &key, &enc_file ) == RC( rcKrypto, rcFile, rcConstructing, rcSize, rcIncorrect ) );
161     LOGMSG ( klogWarn, "No more errors are expected" );
162 
163     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
164     REQUIRE_RC ( KDirectoryRelease ( current_dir ) );
165 }
166 
TEST_CASE(KDecryptZeroContentSizeRW)167 TEST_CASE(KDecryptZeroContentSizeRW)
168 {
169     const char pw [] = "first pw";
170     KKey key;
171     REQUIRE_RC (KKeyInitUpdate (&key, kkeyAES128, pw, strlen (pw)));
172 
173     const char file_path [] = TMP_FOLDER "/zero_content_rw_file_to_dec";
174 
175     KFile * enc_file, * pt_file;
176 
177     uint64_t file_size;
178 
179     struct KDirectory * current_dir;
180     REQUIRE_RC ( KDirectoryNativeDir ( &current_dir ) );
181 
182     // just in case if it still there
183     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
184     // create file
185     REQUIRE_RC ( TCreateEncFile( current_dir, file_path, TFileOpenMode_ReadWrite, &key, &enc_file ) );
186     REQUIRE_RC ( KFileRelease ( enc_file ) );
187 
188     // check raw size
189     REQUIRE_RC ( TOpenPtFile( current_dir, file_path, TFileOpenMode_Read, &pt_file ) );
190     REQUIRE_RC ( KFileSize ( pt_file, &file_size ) );
191     REQUIRE ( file_size == sizeof(KEncFileHeader) + sizeof(KEncFileFooter) );
192     REQUIRE_RC ( KEncFileValidate( pt_file ) );
193     REQUIRE_RC ( KFileRelease ( pt_file ) );
194 
195     // check enc open
196     REQUIRE_RC ( TOpenEncFile( current_dir, file_path, TFileOpenMode_Read, &key, &enc_file ) );
197     REQUIRE_RC ( KFileRelease ( enc_file ) );
198 
199     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
200     REQUIRE_RC ( KDirectoryRelease ( current_dir ) );
201 }
202 
TEST_CASE(KDecryptZeroContentSizeWOnly)203 TEST_CASE(KDecryptZeroContentSizeWOnly)
204 {
205     const char pw [] = "first pw";
206     KKey key;
207     REQUIRE_RC (KKeyInitUpdate (&key, kkeyAES128, pw, strlen (pw)));
208 
209     const char file_path [] = TMP_FOLDER "/zero_content_w_file_to_dec";
210 
211     KFile * enc_file, * pt_file;
212 
213     uint64_t file_size;
214 
215     struct KDirectory * current_dir;
216     REQUIRE_RC ( KDirectoryNativeDir ( &current_dir ) );
217 
218     // just in case if it still there
219     KDirectoryRemove ( current_dir, true, "temp"
220 #if defined(__APPLE__)
221         "mac");
222 #else
223         "linux");
224 #endif
225 
226     // create file
227     REQUIRE_RC ( TCreateEncFile( current_dir, file_path, TFileOpenMode_Write, &key, &enc_file ) );
228     REQUIRE_RC ( KFileRelease ( enc_file ) );
229 
230     // check raw size
231     REQUIRE_RC ( TOpenPtFile( current_dir, file_path, TFileOpenMode_Read, &pt_file ) );
232     REQUIRE_RC ( KFileSize ( pt_file, &file_size ) );
233     REQUIRE ( file_size == sizeof(KEncFileHeader) + sizeof(KEncFileFooter) );
234     REQUIRE_RC ( KEncFileValidate( pt_file ) );
235     REQUIRE_RC ( KFileRelease ( pt_file ) );
236 
237     // check enc open
238     REQUIRE_RC ( TOpenEncFile( current_dir, file_path, TFileOpenMode_Read, &key, &enc_file ) );
239     REQUIRE_RC ( KFileRelease ( enc_file ) );
240 
241     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
242     REQUIRE_RC ( KDirectoryRelease ( current_dir ) );
243 }
244 
245 
TEST_CASE(KDectryptOnlyHeader)246 TEST_CASE(KDectryptOnlyHeader)
247 {
248     const char pw [] = "first pw";
249     KKey key;
250     REQUIRE_RC (KKeyInitUpdate (&key, kkeyAES128, pw, strlen (pw)));
251 
252     const char file_path [] = TMP_FOLDER "/file_only_header";
253 
254     KFile * enc_file, * pt_file;
255 
256     struct KDirectory * current_dir;
257     REQUIRE_RC ( KDirectoryNativeDir ( &current_dir ) );
258 
259     // just in case if it still there
260     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
261     // create file
262     REQUIRE_RC ( TCreateEncFile( current_dir, file_path, TFileOpenMode_Write, &key, &enc_file ) );
263     REQUIRE_RC ( TFillFile( enc_file, (const uint8_t *)"\0\1", 2, 500 ) );
264     REQUIRE_RC ( KFileRelease ( enc_file ) );
265 
266     // truncate it to header size
267     REQUIRE_RC ( TOpenPtFile ( current_dir, file_path, TFileOpenMode_ReadWrite, &pt_file ) );
268     REQUIRE_RC ( KFileSetSize ( pt_file, sizeof(KEncFileHeader) ) );
269     REQUIRE_RC ( KFileRelease ( pt_file ) );
270 
271     LOGMSG ( klogWarn, "Expect errors after this line:" );
272     REQUIRE ( TOpenEncFile( current_dir, file_path, TFileOpenMode_Read, &key, &enc_file ) == RC( rcKrypto, rcFile, rcConstructing, rcSize, rcIncorrect ) );
273     LOGMSG ( klogWarn, "No more errors are expected" );
274 
275     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
276     REQUIRE_RC ( KDirectoryRelease ( current_dir ) );
277 }
278 
TEST_CASE(KDectryptWithoutFooter)279 TEST_CASE(KDectryptWithoutFooter)
280 {
281     const char pw [] = "first pw";
282     KKey key;
283     REQUIRE_RC (KKeyInitUpdate (&key, kkeyAES128, pw, strlen (pw)));
284 
285     const char file_path [] = TMP_FOLDER "/file_no_footer";
286     KFile * enc_file, * pt_file;
287 
288     uint64_t file_size;
289 
290     struct KDirectory * current_dir;
291     REQUIRE_RC ( KDirectoryNativeDir ( &current_dir ) );
292 
293     // just in case if it still there
294     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
295     // create file
296     REQUIRE_RC ( TCreateEncFile( current_dir, file_path, TFileOpenMode_Write, &key, &enc_file ) );
297     REQUIRE_RC ( TFillFile( enc_file, (const uint8_t *)"\0\1", 2, 500 ) );
298     REQUIRE_RC ( KFileRelease ( enc_file ) );
299 
300     // truncate footer
301     REQUIRE_RC ( TOpenPtFile ( current_dir, file_path, TFileOpenMode_ReadWrite, &pt_file ) );
302     REQUIRE_RC ( KFileSize ( pt_file, &file_size ) );
303     REQUIRE_RC ( KFileSetSize ( pt_file, file_size - sizeof(KEncFileFooter) ) );
304     REQUIRE_RC ( KFileRelease ( pt_file ) );
305 
306     LOGMSG ( klogWarn, "Expect errors after this line:" );
307     REQUIRE ( TOpenEncFile( current_dir, file_path, TFileOpenMode_Read, &key, &enc_file ) == RC( rcKrypto, rcFile, rcConstructing, rcSize, rcIncorrect ) );
308     LOGMSG ( klogWarn, "No more errors are expected" );
309 
310     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
311     REQUIRE_RC ( KDirectoryRelease ( current_dir ) );
312 }
313 
TEST_CASE(KDectryptCorruptHeader)314 TEST_CASE(KDectryptCorruptHeader)
315 {
316     const char pw [] = "first pw";
317     KKey key;
318     REQUIRE_RC (KKeyInitUpdate (&key, kkeyAES128, pw, strlen (pw)));
319 
320     const char file_path [] = TMP_FOLDER "/file_corrupt_header";
321 
322     KFile * enc_file, * pt_file;
323 
324     const size_t buffer_size = sizeof(KEncFileHeader);
325     size_t num_written;
326     uint8_t buffer[buffer_size];
327 
328     struct KDirectory * current_dir;
329     REQUIRE_RC ( KDirectoryNativeDir ( &current_dir ) );
330 
331     // just in case if it still there
332     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
333 
334     // create file
335     REQUIRE_RC ( TCreateEncFile( current_dir, file_path, TFileOpenMode_Write, &key, &enc_file ) );
336     REQUIRE_RC ( TFillFile( enc_file, (const uint8_t *)"\0\1", 2, 500 ) );
337     REQUIRE_RC ( KFileRelease ( enc_file ) );
338 
339     // corrupt header
340     REQUIRE_RC ( TOpenPtFile ( current_dir, file_path, TFileOpenMode_ReadWrite, &pt_file ) );
341     REQUIRE_RC ( KFileReadAll ( pt_file, 0, buffer, buffer_size, &num_written ) );
342     buffer[0] ^= 4;
343     REQUIRE_RC ( KFileWriteAll ( pt_file, 0, buffer, buffer_size, &num_written ) );
344     assert(buffer_size == num_written);
345     REQUIRE_RC ( KFileRelease ( pt_file ) );
346 
347     LOGMSG ( klogWarn, "Expect errors after this line:" );
348     REQUIRE ( TOpenEncFile( current_dir, file_path, TFileOpenMode_Read, &key, &enc_file ) == RC( rcFS, rcFile, rcConstructing, rcHeader, rcInvalid ) );
349     LOGMSG ( klogWarn, "No more errors are expected" );
350 
351     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
352     REQUIRE_RC ( KDirectoryRelease ( current_dir ) );
353 }
354 
TEST_CASE(KDectryptCorruptFooterCrc)355 TEST_CASE(KDectryptCorruptFooterCrc)
356 {
357     const char pw [] = "first pw";
358     KKey key;
359     REQUIRE_RC (KKeyInitUpdate (&key, kkeyAES128, pw, strlen (pw)));
360 
361     const char file_path [] = TMP_FOLDER "/file_corrupt_footer_crc";
362 
363     KFile * enc_file, * pt_file;
364 
365     uint64_t file_size;
366     const size_t buffer_size = sizeof(KEncFileFooter);
367     size_t num_written, num_read;
368     uint8_t buffer[buffer_size];
369 
370     struct KDirectory * current_dir;
371     REQUIRE_RC ( KDirectoryNativeDir ( &current_dir ) );
372 
373     // just in case if it still there
374     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
375 
376     // create file
377     REQUIRE_RC ( TCreateEncFile( current_dir, file_path, TFileOpenMode_Write, &key, &enc_file ) );
378     REQUIRE_RC ( TFillFile( enc_file, (const uint8_t *)"\0\1", 2, 500 ) );
379     REQUIRE_RC ( KFileRelease ( enc_file ) );
380 
381     // corrupt footer
382     REQUIRE_RC ( TOpenPtFile ( current_dir, file_path, TFileOpenMode_ReadWrite, &pt_file ) );
383     REQUIRE_RC ( KFileSize ( pt_file, &file_size ) );
384     REQUIRE_RC ( KFileReadAll ( pt_file, file_size - buffer_size, buffer, buffer_size, &num_read ) );
385     assert(buffer_size == num_read);
386     ((KEncFileFooter*)&buffer)->crc_checksum ^= 4;
387     REQUIRE_RC ( KFileWriteAll ( pt_file, file_size - buffer_size, buffer, buffer_size, &num_written ) );
388     assert(buffer_size == num_written);
389     REQUIRE_RC ( KFileRelease ( pt_file ) );
390 
391     REQUIRE_RC ( TOpenPtFile( current_dir, file_path, TFileOpenMode_Read, &pt_file ) );
392     LOGMSG ( klogWarn, "Expect errors after this line:" );
393     REQUIRE ( KEncFileValidate( pt_file ) == RC(rcKrypto, rcFile, rcValidating, rcChecksum, rcCorrupt) );
394     LOGMSG ( klogWarn, "No more errors are expected" );
395     REQUIRE_RC ( KFileRelease ( pt_file ) );
396 
397     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
398 
399     REQUIRE_RC ( KDirectoryRelease ( current_dir ) );
400 }
401 
TEST_CASE(KDectryptCorruptFooterBlockCount)402 TEST_CASE(KDectryptCorruptFooterBlockCount)
403 {
404     const char pw [] = "first pw";
405     KKey key;
406     REQUIRE_RC (KKeyInitUpdate (&key, kkeyAES128, pw, strlen (pw)));
407 
408     const char file_path [] = TMP_FOLDER "/file_corrupt_footer_block_count";
409 
410     KFile * enc_file, * pt_file;
411 
412     uint64_t file_size;
413     const size_t buffer_size = sizeof(KEncFileFooter);
414     size_t num_written, num_read;
415     uint8_t buffer[buffer_size];
416 
417     struct KDirectory * current_dir;
418     REQUIRE_RC ( KDirectoryNativeDir ( &current_dir ) );
419 
420     // just in case if it still there
421     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
422 
423     // create file
424     REQUIRE_RC ( TCreateEncFile( current_dir, file_path, TFileOpenMode_Write, &key, &enc_file ) );
425     REQUIRE_RC ( TFillFile( enc_file, (const uint8_t *)"\0\1", 2, 500 ) );
426     REQUIRE_RC ( KFileRelease ( enc_file ) );
427 
428     // corrupt footer
429     REQUIRE_RC ( TOpenPtFile ( current_dir, file_path, TFileOpenMode_ReadWrite, &pt_file ) );
430     REQUIRE_RC ( KFileSize ( pt_file, &file_size ) );
431     REQUIRE_RC ( KFileReadAll ( pt_file, file_size - buffer_size, buffer, buffer_size, &num_read ) );
432     assert(buffer_size == num_read);
433     ((KEncFileFooter*)&buffer)->block_count ^= 4;
434     REQUIRE_RC ( KFileWriteAll ( pt_file, file_size - buffer_size, buffer, buffer_size, &num_written ) );
435     assert(buffer_size == num_written);
436     REQUIRE_RC ( KFileRelease ( pt_file ) );
437 
438     REQUIRE_RC ( TOpenPtFile( current_dir, file_path, TFileOpenMode_Read, &pt_file ) );
439     LOGMSG ( klogWarn, "Expect errors after this line:" );
440     REQUIRE ( KEncFileValidate( pt_file ) == RC(rcKrypto, rcFile, rcValidating, rcSize, rcIncorrect) );
441     LOGMSG ( klogWarn, "No more errors are expected" );
442     REQUIRE_RC ( KFileRelease ( pt_file ) );
443 
444     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
445 
446     REQUIRE_RC ( KDirectoryRelease ( current_dir ) );
447 }
448 
TEST_CASE(KDectryptCorruptBlockStruct)449 TEST_CASE(KDectryptCorruptBlockStruct)
450 {
451     const char pw [] = "first pw";
452     KKey key;
453     REQUIRE_RC (KKeyInitUpdate (&key, kkeyAES128, pw, strlen (pw)));
454 
455     const char file_path [] = TMP_FOLDER "/file_corrupt_block_struct";
456 
457     KFile * enc_file, * pt_file;
458 
459     uint64_t file_size;
460     const size_t buffer_size = sizeof(KEncFileBlock);
461     size_t num_written, num_read;
462     uint8_t buffer[buffer_size];
463 
464     struct KDirectory * current_dir;
465     REQUIRE_RC ( KDirectoryNativeDir ( &current_dir ) );
466 
467     // just in case if it still there
468     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
469 
470     // create file
471     REQUIRE_RC ( TCreateEncFile( current_dir, file_path, TFileOpenMode_Write, &key, &enc_file ) );
472     REQUIRE_RC ( TFillFile( enc_file, (const uint8_t *)"\0\1", 2, 500 ) );
473     REQUIRE_RC ( KFileRelease ( enc_file ) );
474 
475     // corrupt block struct
476     REQUIRE_RC ( TOpenPtFile ( current_dir, file_path, TFileOpenMode_ReadWrite, &pt_file ) );
477     REQUIRE_RC ( KFileSize ( pt_file, &file_size ) );
478     REQUIRE_RC ( KFileReadAll ( pt_file, file_size - sizeof(KEncFileFooter) - buffer_size, buffer, buffer_size, &num_read ) );
479     assert(buffer_size == num_read);
480     buffer[0] ^= 4;
481     REQUIRE_RC ( KFileWriteAll ( pt_file, file_size - sizeof(KEncFileFooter) - buffer_size, buffer, buffer_size, &num_written ) );
482     assert(buffer_size == num_written);
483     REQUIRE_RC ( KFileRelease ( pt_file ) );
484 
485     REQUIRE_RC ( TOpenPtFile( current_dir, file_path, TFileOpenMode_Read, &pt_file ) );
486     LOGMSG ( klogWarn, "Expect errors after this line:" );
487     REQUIRE ( KEncFileValidate( pt_file ) == RC(rcKrypto, rcFile, rcValidating, rcChecksum, rcCorrupt) );
488     LOGMSG ( klogWarn, "No more errors are expected" );
489     REQUIRE_RC ( KFileRelease ( pt_file ) );
490 
491     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
492 
493     REQUIRE_RC ( KDirectoryRelease ( current_dir ) );
494 }
495 
TEST_CASE(KDectryptCorruptBlockData)496 TEST_CASE(KDectryptCorruptBlockData)
497 {
498     const char pw [] = "first pw";
499     KKey key;
500     REQUIRE_RC (KKeyInitUpdate (&key, kkeyAES128, pw, strlen (pw)));
501 
502     const char file_path [] = TMP_FOLDER "/file_corrupt_block_data";
503 
504     KFile * enc_file, * pt_file;
505 
506     uint64_t file_size;
507     const size_t buffer_size = sizeof(KEncFileBlock);
508     size_t num_written, num_read;
509     uint8_t buffer[buffer_size];
510 
511     struct KDirectory * current_dir;
512     REQUIRE_RC ( KDirectoryNativeDir ( &current_dir ) );
513 
514     // just in case if it still there
515     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
516 
517     // create file
518     REQUIRE_RC ( TCreateEncFile( current_dir, file_path, TFileOpenMode_Write, &key, &enc_file ) );
519     REQUIRE_RC ( TFillFile( enc_file, (const uint8_t *)"\0\1", 2, 500 ) );
520     REQUIRE_RC ( KFileRelease ( enc_file ) );
521 
522     // corrupt block struct
523     REQUIRE_RC ( TOpenPtFile ( current_dir, file_path, TFileOpenMode_ReadWrite, &pt_file ) );
524     REQUIRE_RC ( KFileSize ( pt_file, &file_size ) );
525     REQUIRE_RC ( KFileReadAll ( pt_file, file_size - sizeof(KEncFileFooter) - buffer_size, buffer, buffer_size, &num_read ) );
526     assert(buffer_size == num_read);
527     ((KEncFileBlock*)&buffer)->data[0] ^= 4;
528     REQUIRE_RC ( KFileWriteAll ( pt_file, file_size - sizeof(KEncFileFooter) - buffer_size, buffer, buffer_size, &num_written ) );
529     assert(buffer_size == num_written);
530     REQUIRE_RC ( KFileRelease ( pt_file ) );
531 
532     REQUIRE_RC ( TOpenPtFile( current_dir, file_path, TFileOpenMode_Read, &pt_file ) );
533     LOGMSG ( klogWarn, "Expect errors after this line:" );
534     REQUIRE ( KEncFileValidate( pt_file ) == RC(rcKrypto, rcFile, rcValidating, rcChecksum, rcCorrupt) );
535     LOGMSG ( klogWarn, "No more errors are expected" );
536     REQUIRE_RC ( KFileRelease ( pt_file ) );
537 
538     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
539 
540     REQUIRE_RC ( KDirectoryRelease ( current_dir ) );
541 }
542 
543 
TEST_CASE(KDectryptInvalidKey)544 TEST_CASE(KDectryptInvalidKey)
545 {
546     const char pw1 [] = "first pw";
547     const char pw2 [] = "second pw";
548     KKey key1, key2;
549     REQUIRE_RC (KKeyInitUpdate (&key1, kkeyAES128, pw1, strlen (pw1)));
550     REQUIRE_RC (KKeyInitUpdate (&key2, kkeyAES128, pw2, strlen (pw2)));
551 
552     const char file_path [] = TMP_FOLDER "/enc_file_invalid_key";
553 
554     KFile * enc_file;
555 
556     struct KDirectory * current_dir;
557     REQUIRE_RC ( KDirectoryNativeDir ( &current_dir ) );
558 
559     // just in case if it still there
560     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
561 
562     // create file
563     REQUIRE_RC ( TCreateEncFile( current_dir, file_path, TFileOpenMode_Write, &key1, &enc_file ) );
564     REQUIRE_RC ( TFillFile( enc_file, (const uint8_t *)"\0\1", 2, 500 ) );
565     REQUIRE_RC ( KFileRelease ( enc_file ) );
566 
567     REQUIRE_RC ( TOpenEncFile( current_dir, file_path, TFileOpenMode_Read, &key2, &enc_file ) );
568     LOGMSG ( klogWarn, "Expect errors after this line:" );
569     REQUIRE ( TCheckFileContent( enc_file, (const uint8_t *)"\0\1", 2 ) == RC( rcKrypto, rcFile, rcValidating, rcEncryption, rcCorrupt ) );
570     LOGMSG ( klogWarn, "No more errors are expected" );
571     REQUIRE_RC ( KFileRelease ( enc_file ) );
572 
573     KDirectoryRemove ( current_dir, true, TMP_FOLDER );
574 
575     REQUIRE_RC ( KDirectoryRelease ( current_dir ) );
576 }
577 
578 //////////////////////////////////////////// Main
579 
580 extern "C"
581 {
582 
KAppVersion(void)583     ver_t CC KAppVersion ( void )
584     {
585         return 0x1000000;
586     }
587 
UsageSummary(const char * prog_name)588     rc_t CC UsageSummary (const char * prog_name)
589     {
590         return 0;
591     }
592 
Usage(const Args * args)593     rc_t CC Usage ( const Args * args)
594     {
595         return 0;
596     }
597 
598     const char UsageDefaultName[] = "test-encdec";
599 
KMain(int argc,char * argv[])600     rc_t CC KMain ( int argc, char *argv [] )
601     {
602         KConfigDisableUserSettings();
603         rc_t rc=KEncDecTestSuite(argc, argv);
604         return rc;
605     }
606 
607 }
608