Add separate tests directory, move LUKS tests, Add old library API tests.
[platform/upstream/cryptsetup.git] / tests / apitest.c
1 /*
2  * cryptsetup library API check functions
3  *
4  * Copyright (C) 2009 Red Hat, Inc. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * version 2 as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <fcntl.h>
24 #include <linux/fs.h>
25 #include <errno.h>
26 #include <sys/stat.h>
27
28 #include "libcryptsetup.h"
29
30 #define DMDIR "/dev/mapper/"
31
32 #define DEVICE_1 "/dev/loop5"
33 #define DEVICE_1_UUID "28632274-8c8a-493f-835b-da802e1c576b"
34 #define DEVICE_2 "/dev/loop6"
35 #define DEVICE_EMPTY_name "crypt_zero"
36 #define DEVICE_EMPTY DMDIR DEVICE_EMPTY_name
37 #define DEVICE_ERROR_name "crypt_error"
38 #define DEVICE_ERROR DMDIR DEVICE_ERROR_name
39
40 #define CDEVICE_1 "ctest1"
41 #define CDEVICE_2 "ctest2"
42 #define CDEVICE_WRONG "O_o"
43
44 #define IMAGE1 "compatimage.img"
45 #define IMAGE_EMPTY "empty.img"
46
47 #define KEYFILE1 "key1.file"
48 #define KEY1 "compatkey"
49
50 #define KEYFILE2 "key2.file"
51 #define KEY2 "0123456789abcdef"
52
53 static int _debug   = 0;
54 static int _verbose = 1;
55
56 static char global_log[4096];
57
58 // Helpers
59 static int _prepare_keyfile(const char *name, const char *passphrase)
60 {
61         int fd, r;
62
63         fd = open(name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR);
64         if (fd != -1) {
65                 r = write(fd, passphrase, strlen(passphrase));
66                 close(fd);
67         } else
68                 r = 0;
69
70         return r == strlen(passphrase) ? 0 : 1;
71 }
72
73 static void _remove_keyfiles(void)
74 {
75         remove(KEYFILE1);
76         remove(KEYFILE2);
77 }
78
79 static int yesDialog(char *msg)
80 {
81         return 1;
82 }
83
84 static void cmdLineLog(int class, char *msg)
85 {
86         strncat(global_log, msg, sizeof(global_log));
87 }
88
89 static void reset_log()
90 {
91         memset(global_log, 0, sizeof(global_log));
92 }
93
94 static struct interface_callbacks cmd_icb = {
95         .yesDialog = yesDialog,
96         .log = cmdLineLog,
97 };
98
99 static void _cleanup(void)
100 {
101         struct stat st;
102
103         //system("udevadm settle");
104
105         if (!stat(DMDIR CDEVICE_1, &st))
106                 system("dmsetup remove " CDEVICE_1);
107
108         if (!stat(DMDIR CDEVICE_2, &st))
109                 system("dmsetup remove " CDEVICE_2);
110
111         if (!stat(DEVICE_EMPTY, &st))
112                 system("dmsetup remove " DEVICE_EMPTY_name);
113
114         if (!stat(DEVICE_ERROR, &st))
115                 system("dmsetup remove " DEVICE_ERROR_name);
116
117         if (!strncmp("/dev/loop", DEVICE_1, 9))
118                 system("losetup -d " DEVICE_1);
119
120         if (!strncmp("/dev/loop", DEVICE_2, 9))
121                 system("losetup -d " DEVICE_2);
122
123         system("rm -f " IMAGE_EMPTY);
124         _remove_keyfiles();
125 }
126
127 static void _setup(void)
128 {
129         system("dmsetup create " DEVICE_EMPTY_name " --table \"0 10000 zero\"");
130         system("dmsetup create " DEVICE_ERROR_name " --table \"0 10000 error\"");
131         if (!strncmp("/dev/loop", DEVICE_1, 9))
132                 system("losetup " DEVICE_1 " " IMAGE1);
133         if (!strncmp("/dev/loop", DEVICE_2, 9)) {
134                 system("dd if=/dev/zero of=" IMAGE_EMPTY " bs=1M count=4");
135                 system("losetup " DEVICE_2 " " IMAGE_EMPTY);
136         }
137
138 }
139
140 void check_ok(int status, int line, const char *func)
141 {
142         char buf[256];
143
144         if (status) {
145                 crypt_get_error(buf, sizeof(buf));
146                 printf("FAIL line %d [%s]: code %d, %s\n", line, func, status, buf);
147                 _cleanup();
148                 exit(-1);
149         }
150 }
151
152 void check_ko(int status, int line, const char *func)
153 {
154         char buf[256];
155
156         memset(buf, 0, sizeof(buf));
157         crypt_get_error(buf, sizeof(buf));
158         if (status >= 0) {
159                 printf("FAIL line %d [%s]: code %d, %s\n", line, func, status, buf);
160                 _cleanup();
161                 exit(-1);
162         } else if (_verbose)
163                 printf("   => errno %d, errmsg: %s\n", status, buf);
164 }
165
166 void check_equal(int line, const char *func)
167 {
168         printf("FAIL line %d [%s]: expected equal values differs.\n", line, func);
169         _cleanup();
170         exit(-1);
171 }
172
173 void xlog(const char *msg, const char *tst, const char *func, int line, const char *txt)
174 {
175         if (_verbose) {
176                 if (txt)
177                         printf(" [%s,%s:%d] %s [%s]\n", msg, func, line, tst, txt);
178                 else
179                         printf(" [%s,%s:%d] %s\n", msg, func, line, tst);
180         }
181 }
182 #define OK_(x)          do { xlog("(success)", #x, __FUNCTION__, __LINE__, NULL); \
183                              check_ok((x), __LINE__, __FUNCTION__); \
184                         } while(0)
185 #define FAIL_(x, y)     do { xlog("(fail)   ", #x, __FUNCTION__, __LINE__, y); \
186                              check_ko((x), __LINE__, __FUNCTION__); \
187                         } while(0)
188 #define EQ_(x, y)       do { xlog("(equal)  ", #x " == " #y, __FUNCTION__, __LINE__, NULL); \
189                              if ((x) != (y)) check_equal(__LINE__, __FUNCTION__); \
190                         } while(0)
191
192 #define RUN_(x, y)              do { printf("%s: %s\n", #x, (y)); x(); } while (0)
193
194 // OLD API TESTS
195 static void LuksUUID(void)
196 {
197         struct crypt_options co = { .icb = &cmd_icb };
198
199         co.device = DEVICE_EMPTY;
200         EQ_(crypt_luksUUID(&co), -EINVAL);
201
202         co.device = DEVICE_ERROR;
203         EQ_(crypt_luksUUID(&co), -EINVAL);
204
205         reset_log();
206         co.device = DEVICE_1;
207         OK_(crypt_luksUUID(&co));
208         EQ_(strlen(global_log), 37); /* UUID + "\n" */
209         EQ_(strncmp(global_log, DEVICE_1_UUID, strlen(DEVICE_1_UUID)), 0);
210
211 }
212
213 static void IsLuks(void)
214 {
215         struct crypt_options co = {  .icb = &cmd_icb };
216
217         co.device = DEVICE_EMPTY;
218         EQ_(crypt_isLuks(&co), -EINVAL);
219
220         co.device = DEVICE_ERROR;
221         EQ_(crypt_isLuks(&co), -EINVAL);
222
223         co.device = DEVICE_1;
224         OK_(crypt_isLuks(&co));
225 }
226
227 static void LuksOpen(void)
228 {
229         struct crypt_options co = {
230                 .name = CDEVICE_1,
231                 //.passphrase = "blabla",
232                 .icb = &cmd_icb,
233         };
234
235         OK_(_prepare_keyfile(KEYFILE1, KEY1));
236         co.key_file = KEYFILE1;
237
238         co.device = DEVICE_EMPTY;
239         EQ_(crypt_luksOpen(&co), -EINVAL);
240
241         co.device = DEVICE_ERROR;
242         EQ_(crypt_luksOpen(&co), -EINVAL);
243
244         co.device = DEVICE_1;
245         OK_(crypt_luksOpen(&co));
246         FAIL_(crypt_luksOpen(&co), "already open");
247
248         _remove_keyfiles();
249 }
250
251 static void query_device(void)
252 {
253         struct crypt_options co = {. icb = &cmd_icb };
254
255         co.name = CDEVICE_WRONG;
256         EQ_(crypt_query_device(&co), 0);
257
258         co.name = CDEVICE_1;
259         EQ_(crypt_query_device(&co), 1);
260
261         OK_(strncmp(crypt_get_dir(), DMDIR, 11));
262         OK_(strcmp(co.cipher, "aes-cbc-essiv:sha256"));
263         EQ_(co.key_size, 16);
264         EQ_(co.offset, 1032);
265         EQ_(co.flags & CRYPT_FLAG_READONLY, 0);
266         EQ_(co.skip, 0);
267         crypt_put_options(&co);
268 }
269
270 static void remove_device(void)
271 {
272         int fd;
273         struct crypt_options co = {. icb = &cmd_icb };
274
275         co.name = CDEVICE_WRONG;
276         EQ_(crypt_remove_device(&co), -ENODEV);
277
278         fd = open(DMDIR CDEVICE_1, O_RDONLY);
279         co.name = CDEVICE_1;
280         FAIL_(crypt_remove_device(&co), "device busy");
281         close(fd);
282
283         OK_(crypt_remove_device(&co));
284 }
285
286 static void LuksFormat(void)
287 {
288         struct crypt_options co = {
289                 .device = DEVICE_2,
290                 .key_size = 256 / 8,
291                 .key_slot = -1,
292                 .cipher = "aes-cbc-essiv:sha256",
293                 .hash = "sha1",
294                 .flags = 0,
295                 .iteration_time = 10,
296                 .align_payload = 0,
297                 .icb = &cmd_icb,
298         };
299
300         OK_(_prepare_keyfile(KEYFILE1, KEY1));
301
302         co.new_key_file = KEYFILE1;
303         co.device = DEVICE_ERROR;
304         FAIL_(crypt_luksFormat(&co), "error device");
305
306         co.device = DEVICE_2;
307         OK_(crypt_luksFormat(&co));
308
309         co.new_key_file = NULL;
310         co.key_file = KEYFILE1;
311         co.name = CDEVICE_2;
312         OK_(crypt_luksOpen(&co));
313         OK_(crypt_remove_device(&co));
314         _remove_keyfiles();
315 }
316
317 static void LuksKeyGame(void)
318 {
319         int i;
320         struct crypt_options co = {
321                 .device = DEVICE_2,
322                 .key_size = 256 / 8,
323                 .key_slot = -1,
324                 .cipher = "aes-cbc-essiv:sha256",
325                 .hash = "sha1",
326                 .flags = 0,
327                 .iteration_time = 10,
328                 .align_payload = 0,
329                 .icb = &cmd_icb,
330         };
331
332         OK_(_prepare_keyfile(KEYFILE1, KEY1));
333         OK_(_prepare_keyfile(KEYFILE2, KEY2));
334
335         co.new_key_file = KEYFILE1;
336         co.device = DEVICE_2;
337         co.key_slot = 8;
338         FAIL_(crypt_luksFormat(&co), "wrong slot #");
339
340         co.key_slot = 7; // last slot
341         OK_(crypt_luksFormat(&co));
342
343         co.new_key_file = KEYFILE1;
344         co.key_file = KEYFILE1;
345         co.key_slot = 8;
346         FAIL_(crypt_luksAddKey(&co), "wrong slot #");
347         co.key_slot = 7;
348         FAIL_(crypt_luksAddKey(&co), "slot already used");
349
350         co.key_slot = 6;
351         OK_(crypt_luksAddKey(&co));
352
353         co.key_file = KEYFILE2 "blah";
354         co.key_slot = 5;
355         FAIL_(crypt_luksAddKey(&co), "keyfile not found");
356
357         co.new_key_file = KEYFILE2; // key to add
358         co.key_file = KEYFILE1;
359         co.key_slot = -1;
360         for (i = 0; i < 6; i++)
361                 OK_(crypt_luksAddKey(&co)); //FIXME: EQ_(i)?
362
363         FAIL_(crypt_luksAddKey(&co), "all slots full");
364
365         // REMOVE KEY
366         co.new_key_file = KEYFILE1; // key to remove
367         co.key_file = NULL;
368         co.key_slot = 8; // should be ignored
369          // only 2 slots should use KEYFILE1
370         OK_(crypt_luksRemoveKey(&co));
371         OK_(crypt_luksRemoveKey(&co));
372         FAIL_(crypt_luksRemoveKey(&co), "no slot with this passphrase");
373
374         co.new_key_file = KEYFILE2 "blah";
375         co.key_file = NULL;
376         FAIL_(crypt_luksRemoveKey(&co), "keyfile not found");
377
378         // KILL SLOT
379         co.new_key_file = NULL;
380         co.key_file = NULL;
381         co.key_slot = 8;
382         FAIL_(crypt_luksKillSlot(&co), "wrong slot #");
383         co.key_slot = 7;
384         FAIL_(crypt_luksKillSlot(&co), "slot already wiped");
385
386         co.key_slot = 5;
387         OK_(crypt_luksKillSlot(&co));
388
389         _remove_keyfiles();
390 }
391
392 size_t _get_device_size(const char *device)
393 {
394         unsigned long size = 0;
395         int fd;
396
397         fd = open(device, O_RDONLY);
398         if (fd == -1)
399                 return 0;
400         (void)ioctl(fd, BLKGETSIZE, &size);
401         close(fd);
402
403         return size;
404 }
405
406 void DeviceResizeGame(void)
407 {
408         size_t orig_size;
409         struct crypt_options co = {
410                 .name = CDEVICE_2,
411                 .device = DEVICE_2,
412                 .key_size = 128 / 8,
413                 .cipher = "aes-cbc-plain",
414                 .hash = "sha1",
415                 .offset = 333,
416                 .skip = 0,
417                 .icb = &cmd_icb,
418         };
419
420         orig_size = _get_device_size(DEVICE_2);
421
422         OK_(_prepare_keyfile(KEYFILE2, KEY2));
423
424         co.key_file = KEYFILE2;
425         co.size = 1000;
426         OK_(crypt_create_device(&co));
427         EQ_(_get_device_size(DMDIR CDEVICE_2), 1000);
428
429         co.size = 2000;
430         OK_(crypt_resize_device(&co));
431         EQ_(_get_device_size(DMDIR CDEVICE_2), 2000);
432
433         co.size = 0;
434         OK_(crypt_resize_device(&co));
435         EQ_(_get_device_size(DMDIR CDEVICE_2), (orig_size - 333));
436
437         co.size = 0;
438         co.offset = 444;
439         co.skip = 555;
440         co.cipher = "aes-cbc-benbi";
441         OK_(crypt_update_device(&co));
442         EQ_(_get_device_size(DMDIR CDEVICE_2), (orig_size - 444));
443
444         memset(&co, 0, sizeof(co));
445         co.icb = &cmd_icb,
446         co.name = CDEVICE_2;
447         EQ_(crypt_query_device(&co), 1);
448         EQ_(strcmp(co.cipher, "aes-cbc-benbi"), 0);
449         EQ_(co.key_size, 128 / 8);
450         EQ_(co.offset, 444);
451         EQ_(co.skip, 555);
452         OK_(crypt_remove_device(&co));
453
454         crypt_put_options(&co);
455
456         _remove_keyfiles();
457 }
458
459 int main (int argc, char *argv[])
460 {
461         int i;
462
463         for (i = 1; i < argc; i++) {
464                 if (!strcmp("-v", argv[i]) || !strcmp("--verbose", argv[i]))
465                         _verbose = 1;
466                 else if (!strcmp("--debug", argv[i]))
467                         _debug = _verbose = 1;
468         }
469
470         _cleanup();
471         _setup();
472
473 #ifdef CRYPT_DEBUG_ALL
474         crypt_set_debug_level(_debug ? CRYPT_DEBUG_ALL : CRYPT_DEBUG_NONE);
475 #endif
476
477         RUN_(LuksUUID, "luksUUID API call");
478         RUN_(IsLuks, "isLuks API call");
479         RUN_(LuksOpen, "luksOpen API call");
480         RUN_(query_device, "crypt_query_device API call");
481         RUN_(remove_device, "crypt_remove_device API call");
482         RUN_(LuksFormat, "luksFormat API call");
483         RUN_(LuksKeyGame, "luksAddKey, RemoveKey, KillSlot API calls");
484         RUN_(DeviceResizeGame, "regular crypto, resize calls");
485
486         _cleanup();
487         return 0;
488 }