Rename apitest -> api-test.
[platform/upstream/cryptsetup.git] / tests / api-test.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 <unistd.h>
24 #include <fcntl.h>
25 #include <linux/fs.h>
26 #include <errno.h>
27 #include <sys/stat.h>
28 #include <sys/ioctl.h>
29
30 #include "libcryptsetup.h"
31
32 #define DMDIR "/dev/mapper/"
33
34 #define DEVICE_1 "/dev/loop5"
35 #define DEVICE_1_UUID "28632274-8c8a-493f-835b-da802e1c576b"
36 #define DEVICE_2 "/dev/loop6"
37 #define DEVICE_EMPTY_name "crypt_zero"
38 #define DEVICE_EMPTY DMDIR DEVICE_EMPTY_name
39 #define DEVICE_ERROR_name "crypt_error"
40 #define DEVICE_ERROR DMDIR DEVICE_ERROR_name
41
42 #define CDEVICE_1 "ctest1"
43 #define CDEVICE_2 "ctest2"
44 #define CDEVICE_WRONG "O_o"
45
46 #define IMAGE1 "compatimage.img"
47 #define IMAGE_EMPTY "empty.img"
48
49 #define KEYFILE1 "key1.file"
50 #define KEY1 "compatkey"
51
52 #define KEYFILE2 "key2.file"
53 #define KEY2 "0123456789abcdef"
54
55 static int _debug   = 0;
56 static int _verbose = 1;
57
58 static char global_log[4096];
59 static int global_lines = 0;
60
61 static int gcrypt_compatible = 0;
62
63 // Helpers
64 static int _prepare_keyfile(const char *name, const char *passphrase)
65 {
66         int fd, r;
67
68         fd = open(name, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR);
69         if (fd != -1) {
70                 r = write(fd, passphrase, strlen(passphrase));
71                 close(fd);
72         } else
73                 r = 0;
74
75         return r == strlen(passphrase) ? 0 : 1;
76 }
77
78 static void _remove_keyfiles(void)
79 {
80         remove(KEYFILE1);
81         remove(KEYFILE2);
82 }
83
84 // Decode key from its hex representation
85 static int crypt_decode_key(char *key, char *hex, unsigned int size)
86 {
87         char buffer[3];
88         char *endp;
89         unsigned int i;
90
91         buffer[2] = '\0';
92
93         for (i = 0; i < size; i++) {
94                 buffer[0] = *hex++;
95                 buffer[1] = *hex++;
96
97                 key[i] = (unsigned char)strtoul(buffer, &endp, 16);
98
99                 if (endp != &buffer[2])
100                         return -1;
101         }
102
103         if (*hex != '\0')
104                 return -1;
105
106         return 0;
107 }
108
109 static int yesDialog(char *msg)
110 {
111         return 1;
112 }
113
114 static void cmdLineLog(int level, char *msg)
115 {
116         strncat(global_log, msg, sizeof(global_log) - strlen(global_log));
117         global_lines++;
118 }
119
120 static void new_log(int level, const char *msg, void *usrptr)
121 {
122         cmdLineLog(level, (char*)msg);
123 }
124
125
126 static void reset_log()
127 {
128         memset(global_log, 0, sizeof(global_log));
129         global_lines = 0;
130 }
131
132 static struct interface_callbacks cmd_icb = {
133         .yesDialog = yesDialog,
134         .log = cmdLineLog,
135 };
136
137 static void _cleanup(void)
138 {
139         int r;
140         struct stat st;
141
142         //r = system("udevadm settle");
143
144         if (!stat(DMDIR CDEVICE_1, &st))
145                 r = system("dmsetup remove " CDEVICE_1);
146
147         if (!stat(DMDIR CDEVICE_2, &st))
148                 r = system("dmsetup remove " CDEVICE_2);
149
150         if (!stat(DEVICE_EMPTY, &st))
151                 r = system("dmsetup remove " DEVICE_EMPTY_name);
152
153         if (!stat(DEVICE_ERROR, &st))
154                 r = system("dmsetup remove " DEVICE_ERROR_name);
155
156         if (!strncmp("/dev/loop", DEVICE_1, 9))
157                 r = system("losetup -d " DEVICE_1);
158
159         if (!strncmp("/dev/loop", DEVICE_2, 9))
160                 r = system("losetup -d " DEVICE_2);
161
162         r = system("rm -f " IMAGE_EMPTY);
163         _remove_keyfiles();
164 }
165
166 static void _setup(void)
167 {
168         int r;
169
170         r = system("dmsetup create " DEVICE_EMPTY_name " --table \"0 10000 zero\"");
171         r = system("dmsetup create " DEVICE_ERROR_name " --table \"0 10000 error\"");
172         if (!strncmp("/dev/loop", DEVICE_1, 9))
173                 r = system("losetup " DEVICE_1 " " IMAGE1);
174         if (!strncmp("/dev/loop", DEVICE_2, 9)) {
175                 r = system("dd if=/dev/zero of=" IMAGE_EMPTY " bs=1M count=4");
176                 r = system("losetup " DEVICE_2 " " IMAGE_EMPTY);
177         }
178
179 }
180
181 void check_ok(int status, int line, const char *func)
182 {
183         char buf[256];
184
185         if (status) {
186                 crypt_get_error(buf, sizeof(buf));
187                 printf("FAIL line %d [%s]: code %d, %s\n", line, func, status, buf);
188                 _cleanup();
189                 exit(-1);
190         }
191 }
192
193 void check_ko(int status, int line, const char *func)
194 {
195         char buf[256];
196
197         memset(buf, 0, sizeof(buf));
198         crypt_get_error(buf, sizeof(buf));
199         if (status >= 0) {
200                 printf("FAIL line %d [%s]: code %d, %s\n", line, func, status, buf);
201                 _cleanup();
202                 exit(-1);
203         } else if (_verbose)
204                 printf("   => errno %d, errmsg: %s\n", status, buf);
205 }
206
207 void check_equal(int line, const char *func)
208 {
209         printf("FAIL line %d [%s]: expected equal values differs.\n", line, func);
210         _cleanup();
211         exit(-1);
212 }
213
214 void xlog(const char *msg, const char *tst, const char *func, int line, const char *txt)
215 {
216         if (_verbose) {
217                 if (txt)
218                         printf(" [%s,%s:%d] %s [%s]\n", msg, func, line, tst, txt);
219                 else
220                         printf(" [%s,%s:%d] %s\n", msg, func, line, tst);
221         }
222 }
223 #define OK_(x)          do { xlog("(success)", #x, __FUNCTION__, __LINE__, NULL); \
224                              check_ok((x), __LINE__, __FUNCTION__); \
225                         } while(0)
226 #define FAIL_(x, y)     do { xlog("(fail)   ", #x, __FUNCTION__, __LINE__, y); \
227                              check_ko((x), __LINE__, __FUNCTION__); \
228                         } while(0)
229 #define EQ_(x, y)       do { xlog("(equal)  ", #x " == " #y, __FUNCTION__, __LINE__, NULL); \
230                              if ((x) != (y)) check_equal(__LINE__, __FUNCTION__); \
231                         } while(0)
232
233 #define RUN_(x, y)              do { printf("%s: %s\n", #x, (y)); x(); } while (0)
234
235 // OLD API TESTS
236 static void LuksUUID(void)
237 {
238         struct crypt_options co = { .icb = &cmd_icb };
239
240         co.device = DEVICE_EMPTY;
241         EQ_(crypt_luksUUID(&co), -EINVAL);
242
243         co.device = DEVICE_ERROR;
244         EQ_(crypt_luksUUID(&co), -EINVAL);
245
246         reset_log();
247         co.device = DEVICE_1;
248         OK_(crypt_luksUUID(&co));
249         EQ_(strlen(global_log), 37); /* UUID + "\n" */
250         EQ_(strncmp(global_log, DEVICE_1_UUID, strlen(DEVICE_1_UUID)), 0);
251
252 }
253
254 static void IsLuks(void)
255 {
256         struct crypt_options co = {  .icb = &cmd_icb };
257
258         co.device = DEVICE_EMPTY;
259         EQ_(crypt_isLuks(&co), -EINVAL);
260
261         co.device = DEVICE_ERROR;
262         EQ_(crypt_isLuks(&co), -EINVAL);
263
264         co.device = DEVICE_1;
265         OK_(crypt_isLuks(&co));
266 }
267
268 static void LuksOpen(void)
269 {
270         struct crypt_options co = {
271                 .name = CDEVICE_1,
272                 //.passphrase = "blabla",
273                 .icb = &cmd_icb,
274         };
275
276         OK_(_prepare_keyfile(KEYFILE1, KEY1));
277         co.key_file = KEYFILE1;
278
279         co.device = DEVICE_EMPTY;
280         EQ_(crypt_luksOpen(&co), -EINVAL);
281
282         co.device = DEVICE_ERROR;
283         EQ_(crypt_luksOpen(&co), -EINVAL);
284
285         co.device = DEVICE_1;
286         OK_(crypt_luksOpen(&co));
287         FAIL_(crypt_luksOpen(&co), "already open");
288
289         _remove_keyfiles();
290 }
291
292 static void query_device(void)
293 {
294         struct crypt_options co = {. icb = &cmd_icb };
295
296         co.name = CDEVICE_WRONG;
297         EQ_(crypt_query_device(&co), 0);
298
299         co.name = CDEVICE_1;
300         EQ_(crypt_query_device(&co), 1);
301
302         OK_(strncmp(crypt_get_dir(), DMDIR, 11));
303         OK_(strcmp(co.cipher, "aes-cbc-essiv:sha256"));
304         EQ_(co.key_size, 16);
305         EQ_(co.offset, 1032);
306         EQ_(co.flags & CRYPT_FLAG_READONLY, 0);
307         EQ_(co.skip, 0);
308         crypt_put_options(&co);
309 }
310
311 static void remove_device(void)
312 {
313         int fd;
314         struct crypt_options co = {. icb = &cmd_icb };
315
316         co.name = CDEVICE_WRONG;
317         EQ_(crypt_remove_device(&co), -ENODEV);
318
319         fd = open(DMDIR CDEVICE_1, O_RDONLY);
320         co.name = CDEVICE_1;
321         FAIL_(crypt_remove_device(&co), "device busy");
322         close(fd);
323
324         OK_(crypt_remove_device(&co));
325 }
326
327 static void LuksFormat(void)
328 {
329         struct crypt_options co = {
330                 .device = DEVICE_2,
331                 .key_size = 256 / 8,
332                 .key_slot = -1,
333                 .cipher = "aes-cbc-essiv:sha256",
334                 .hash = "sha1",
335                 .flags = 0,
336                 .iteration_time = 10,
337                 .align_payload = 0,
338                 .icb = &cmd_icb,
339         };
340
341         OK_(_prepare_keyfile(KEYFILE1, KEY1));
342
343         co.new_key_file = KEYFILE1;
344         co.device = DEVICE_ERROR;
345         FAIL_(crypt_luksFormat(&co), "error device");
346
347         co.device = DEVICE_2;
348         OK_(crypt_luksFormat(&co));
349
350         co.new_key_file = NULL;
351         co.key_file = KEYFILE1;
352         co.name = CDEVICE_2;
353         OK_(crypt_luksOpen(&co));
354         OK_(crypt_remove_device(&co));
355         _remove_keyfiles();
356 }
357
358 static void LuksKeyGame(void)
359 {
360         int i;
361         struct crypt_options co = {
362                 .device = DEVICE_2,
363                 .key_size = 256 / 8,
364                 .key_slot = -1,
365                 .cipher = "aes-cbc-essiv:sha256",
366                 .hash = "sha1",
367                 .flags = 0,
368                 .iteration_time = 10,
369                 .align_payload = 0,
370                 .icb = &cmd_icb,
371         };
372
373         OK_(_prepare_keyfile(KEYFILE1, KEY1));
374         OK_(_prepare_keyfile(KEYFILE2, KEY2));
375
376         co.new_key_file = KEYFILE1;
377         co.device = DEVICE_2;
378         co.key_slot = 8;
379         FAIL_(crypt_luksFormat(&co), "wrong slot #");
380
381         co.key_slot = 7; // last slot
382         OK_(crypt_luksFormat(&co));
383
384         co.new_key_file = KEYFILE1;
385         co.key_file = KEYFILE1;
386         co.key_slot = 8;
387         FAIL_(crypt_luksAddKey(&co), "wrong slot #");
388         co.key_slot = 7;
389         FAIL_(crypt_luksAddKey(&co), "slot already used");
390
391         co.key_slot = 6;
392         OK_(crypt_luksAddKey(&co));
393
394         co.key_file = KEYFILE2 "blah";
395         co.key_slot = 5;
396         FAIL_(crypt_luksAddKey(&co), "keyfile not found");
397
398         co.new_key_file = KEYFILE2; // key to add
399         co.key_file = KEYFILE1;
400         co.key_slot = -1;
401         for (i = 0; i < 6; i++)
402                 OK_(crypt_luksAddKey(&co)); //FIXME: EQ_(i)?
403
404         FAIL_(crypt_luksAddKey(&co), "all slots full");
405
406         // REMOVE KEY
407         co.new_key_file = KEYFILE1; // key to remove
408         co.key_file = NULL;
409         co.key_slot = 8; // should be ignored
410          // only 2 slots should use KEYFILE1
411         OK_(crypt_luksRemoveKey(&co));
412         OK_(crypt_luksRemoveKey(&co));
413         FAIL_(crypt_luksRemoveKey(&co), "no slot with this passphrase");
414
415         co.new_key_file = KEYFILE2 "blah";
416         co.key_file = NULL;
417         FAIL_(crypt_luksRemoveKey(&co), "keyfile not found");
418
419         // KILL SLOT
420         co.new_key_file = NULL;
421         co.key_file = NULL;
422         co.key_slot = 8;
423         FAIL_(crypt_luksKillSlot(&co), "wrong slot #");
424         co.key_slot = 7;
425         FAIL_(crypt_luksKillSlot(&co), "slot already wiped");
426
427         co.key_slot = 5;
428         OK_(crypt_luksKillSlot(&co));
429
430         _remove_keyfiles();
431 }
432
433 size_t _get_device_size(const char *device)
434 {
435         unsigned long size = 0;
436         int fd;
437
438         fd = open(device, O_RDONLY);
439         if (fd == -1)
440                 return 0;
441         (void)ioctl(fd, BLKGETSIZE, &size);
442         close(fd);
443
444         return size;
445 }
446
447 void DeviceResizeGame(void)
448 {
449         size_t orig_size;
450         struct crypt_options co = {
451                 .name = CDEVICE_2,
452                 .device = DEVICE_2,
453                 .key_size = 128 / 8,
454                 .cipher = "aes-cbc-plain",
455                 .hash = "sha1",
456                 .offset = 333,
457                 .skip = 0,
458                 .icb = &cmd_icb,
459         };
460
461         orig_size = _get_device_size(DEVICE_2);
462
463         OK_(_prepare_keyfile(KEYFILE2, KEY2));
464
465         co.key_file = KEYFILE2;
466         co.size = 1000;
467         OK_(crypt_create_device(&co));
468         EQ_(_get_device_size(DMDIR CDEVICE_2), 1000);
469
470         co.size = 2000;
471         OK_(crypt_resize_device(&co));
472         EQ_(_get_device_size(DMDIR CDEVICE_2), 2000);
473
474         co.size = 0;
475         OK_(crypt_resize_device(&co));
476         EQ_(_get_device_size(DMDIR CDEVICE_2), (orig_size - 333));
477
478         co.size = 0;
479         co.offset = 444;
480         co.skip = 555;
481         co.cipher = "aes-cbc-essiv:sha256";
482         OK_(crypt_update_device(&co));
483         EQ_(_get_device_size(DMDIR CDEVICE_2), (orig_size - 444));
484
485         memset(&co, 0, sizeof(co));
486         co.icb = &cmd_icb,
487         co.name = CDEVICE_2;
488         EQ_(crypt_query_device(&co), 1);
489         EQ_(strcmp(co.cipher, "aes-cbc-essiv:sha256"), 0);
490         EQ_(co.key_size, 128 / 8);
491         EQ_(co.offset, 444);
492         EQ_(co.skip, 555);
493         OK_(crypt_remove_device(&co));
494
495         crypt_put_options(&co);
496
497         _remove_keyfiles();
498 }
499
500 // NEW API tests
501
502 static void AddDevicePlain(void)
503 {
504         struct crypt_device *cd;
505         struct crypt_params_plain params = {
506                 .hash = "sha1",
507                 .skip = 0,
508                 .offset = 0,
509         };
510         int fd;
511         char key[128], key2[128], path[128];
512
513         char *passphrase = "blabla";
514         char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
515         size_t key_size = strlen(mk_hex) / 2;
516         char *cipher = "aes";
517         char *cipher_mode = "cbc-essiv:sha256";
518
519         crypt_decode_key(key, mk_hex, key_size);
520
521         FAIL_(crypt_init(&cd, ""), "empty device string");
522
523         // default is "plain" hash - no password hash
524         OK_(crypt_init(&cd, DEVICE_1));
525         OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, NULL));
526         OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
527         EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
528         // FIXME: this should get key from active device?
529         //OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase)));
530         //OK_(memcmp(key, key2, key_size));
531         OK_(crypt_deactivate(cd, CDEVICE_1));
532         crypt_free(cd);
533
534         // Now use hashed password
535         OK_(crypt_init(&cd, DEVICE_1));
536         OK_(crypt_format(cd, CRYPT_PLAIN, cipher, cipher_mode, NULL, NULL, key_size, &params));
537         OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0));
538
539         // device status check
540         EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
541         snprintf(path, sizeof(path), "%s/%s", crypt_get_dir(), CDEVICE_1);
542         fd = open(path, O_RDONLY);
543         EQ_(crypt_status(cd, CDEVICE_1), CRYPT_BUSY);
544         FAIL_(crypt_deactivate(cd, CDEVICE_1), "Device is busy");
545         close(fd);
546         OK_(crypt_deactivate(cd, CDEVICE_1));
547         EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
548
549         OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
550         EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
551
552         // retrieve volume key check
553         memset(key2, 0, key_size);
554         key_size--;
555         // small buffer
556         FAIL_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase)), "small buffer");
557         key_size++;
558         OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase)));
559
560         OK_(memcmp(key, key2, key_size));
561         OK_(strcmp(cipher, crypt_get_cipher(cd)));
562         OK_(strcmp(cipher_mode, crypt_get_cipher_mode(cd)));
563         EQ_(key_size, crypt_get_volume_key_size(cd));
564         EQ_(0, crypt_get_data_offset(cd));
565         OK_(crypt_deactivate(cd, CDEVICE_1));
566         crypt_free(cd);
567 }
568
569 static void UseLuksDevice(void)
570 {
571         struct crypt_device *cd;
572         char key[128];
573         size_t key_size;
574
575         OK_(crypt_init(&cd, DEVICE_1));
576         OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
577         EQ_(crypt_status(cd, CDEVICE_1), CRYPT_INACTIVE);
578         OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
579         FAIL_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0), "already open");
580         EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
581         OK_(crypt_deactivate(cd, CDEVICE_1));
582         FAIL_(crypt_deactivate(cd, CDEVICE_1), "no such device");
583
584         key_size = 16;
585         OK_(strcmp("aes", crypt_get_cipher(cd)));
586         OK_(strcmp("cbc-essiv:sha256", crypt_get_cipher_mode(cd)));
587         OK_(strcmp(DEVICE_1_UUID, crypt_get_uuid(cd)));
588         EQ_(key_size, crypt_get_volume_key_size(cd));
589         EQ_(1032, crypt_get_data_offset(cd));
590
591         EQ_(0, crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key, &key_size, KEY1, strlen(KEY1)));
592         OK_(crypt_volume_key_verify(cd, key, key_size));
593         OK_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0));
594         EQ_(crypt_status(cd, CDEVICE_1), CRYPT_ACTIVE);
595         OK_(crypt_deactivate(cd, CDEVICE_1));
596
597         key[1] = ~key[1];
598         FAIL_(crypt_volume_key_verify(cd, key, key_size), "key mismatch");
599         FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_1, key, key_size, 0), "key mismatch");
600         crypt_free(cd);
601 }
602
603 static void SuspendDevice(void)
604 {
605         int suspend_status;
606         struct crypt_device *cd;
607
608         OK_(crypt_init(&cd, DEVICE_1));
609         OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
610         OK_(crypt_activate_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1), 0));
611
612         suspend_status = crypt_suspend(cd, CDEVICE_1);
613         if (suspend_status == -ENOTSUP) {
614                 printf("WARNING: Suspend/Resume not supported, skipping test.\n");
615                 goto out;
616         }
617         OK_(suspend_status);
618         FAIL_(crypt_suspend(cd, CDEVICE_1), "already suspended");
619
620         FAIL_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)-1), "wrong key");
621         OK_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)));
622         FAIL_(crypt_resume_by_passphrase(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEY1, strlen(KEY1)), "not suspended");
623
624         OK_(_prepare_keyfile(KEYFILE1, KEY1));
625         OK_(crypt_suspend(cd, CDEVICE_1));
626         FAIL_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1 "blah", 0), "wrong keyfile");
627         OK_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0));
628         FAIL_(crypt_resume_by_keyfile(cd, CDEVICE_1, CRYPT_ANY_SLOT, KEYFILE1, 0), "not suspended");
629         _remove_keyfiles();
630 out:
631         OK_(crypt_deactivate(cd, CDEVICE_1));
632         crypt_free(cd);
633 }
634
635 static void AddDeviceLuks(void)
636 {
637         struct crypt_device *cd;
638         struct crypt_params_luks1 params = {
639                 .hash = "sha512",
640                 .data_alignment = 2048, // 4M, data offset will be 4096
641         };
642         char key[128], key2[128];
643
644         char *passphrase = "blabla";
645         char *mk_hex = "bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
646         size_t key_size = strlen(mk_hex) / 2;
647         char *cipher = "aes";
648         char *cipher_mode = "cbc-essiv:sha256";
649
650         crypt_decode_key(key, mk_hex, key_size);
651
652         OK_(crypt_init(&cd, DEVICE_2));
653         OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
654
655         // even with no keyslots defined it can be activated by volume key
656         OK_(crypt_volume_key_verify(cd, key, key_size));
657         OK_(crypt_activate_by_volume_key(cd, CDEVICE_2, key, key_size, 0));
658         EQ_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE);
659         OK_(crypt_deactivate(cd, CDEVICE_2));
660
661         // now with keyslot
662         EQ_(7, crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)));
663         EQ_(CRYPT_SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 7));
664         EQ_(7, crypt_activate_by_passphrase(cd, CDEVICE_2, CRYPT_ANY_SLOT, passphrase, strlen(passphrase), 0));
665         EQ_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE);
666         OK_(crypt_deactivate(cd, CDEVICE_2));
667
668         FAIL_(crypt_keyslot_add_by_volume_key(cd, 7, key, key_size, passphrase, strlen(passphrase)), "slot used");
669         key[1] = ~key[1];
670         FAIL_(crypt_keyslot_add_by_volume_key(cd, 6, key, key_size, passphrase, strlen(passphrase)), "key mismatch");
671         key[1] = ~key[1];
672         EQ_(6, crypt_keyslot_add_by_volume_key(cd, 6, key, key_size, passphrase, strlen(passphrase)));
673         EQ_(CRYPT_SLOT_ACTIVE, crypt_keyslot_status(cd, 6));
674
675         FAIL_(crypt_keyslot_destroy(cd, 8), "invalid keyslot");
676         FAIL_(crypt_keyslot_destroy(cd, CRYPT_ANY_SLOT), "invalid keyslot");
677         FAIL_(crypt_keyslot_destroy(cd, 0), "keyslot not used");
678         OK_(crypt_keyslot_destroy(cd, 7));
679         EQ_(CRYPT_SLOT_INACTIVE, crypt_keyslot_status(cd, 7));
680         EQ_(CRYPT_SLOT_ACTIVE_LAST, crypt_keyslot_status(cd, 6));
681
682         EQ_(6, crypt_volume_key_get(cd, CRYPT_ANY_SLOT, key2, &key_size, passphrase, strlen(passphrase)));
683         OK_(crypt_volume_key_verify(cd, key2, key_size));
684
685         OK_(memcmp(key, key2, key_size));
686         OK_(strcmp(cipher, crypt_get_cipher(cd)));
687         OK_(strcmp(cipher_mode, crypt_get_cipher_mode(cd)));
688         EQ_(key_size, crypt_get_volume_key_size(cd));
689         EQ_(4096, crypt_get_data_offset(cd));
690
691         reset_log();
692         crypt_set_log_callback(cd, &new_log, NULL);
693         OK_(crypt_dump(cd));
694         OK_(!(global_lines != 0));
695         crypt_set_log_callback(cd, NULL, NULL);
696         reset_log();
697
698         FAIL_(crypt_deactivate(cd, CDEVICE_2), "not active");
699         crypt_free(cd);
700 }
701
702 // Check that gcrypt is properly initialised in format
703 static void NonFIPSAlg(void)
704 {
705         struct crypt_device *cd;
706         struct crypt_params_luks1 params = {
707                 .hash = "whirlpool",
708         };
709         char key[128] = "";
710         size_t key_size = 128;
711         char *cipher = "aes";
712         char *cipher_mode = "cbc-essiv:sha256";
713
714         if (!gcrypt_compatible) {
715                 printf("WARNING: old libgcrypt, skipping test.\n");
716                 return;
717         }
718         OK_(crypt_init(&cd, DEVICE_2));
719         OK_(crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, key_size, &params));
720         crypt_free(cd);
721 }
722
723
724 static void _gcrypt_compatible()
725 {
726         int maj, min, patch;
727         FILE *f;
728
729         if (!(f = popen("libgcrypt-config --version", "r")))
730                 return;
731
732         if (fscanf(f, "%d.%d.%d", &maj, &min, &patch) == 2 &&
733             maj >= 1 && min >= 4)
734                 gcrypt_compatible = 1;
735         if (_debug)
736                 printf("libgcrypt version %d.%d.%d detected.\n", maj, min, patch);
737
738         (void)fclose(f);
739         return;
740 }
741
742 int main (int argc, char *argv[])
743 {
744         int i;
745
746         if (getuid() != 0) {
747                 printf("You must be root to run this test.\n");
748                 exit(0);
749         }
750
751         for (i = 1; i < argc; i++) {
752                 if (!strcmp("-v", argv[i]) || !strcmp("--verbose", argv[i]))
753                         _verbose = 1;
754                 else if (!strcmp("--debug", argv[i]))
755                         _debug = _verbose = 1;
756         }
757
758         _cleanup();
759         _setup();
760         _gcrypt_compatible();
761
762         crypt_set_debug_level(_debug ? CRYPT_DEBUG_ALL : CRYPT_DEBUG_NONE);
763
764         RUN_(NonFIPSAlg, "Crypto is properly initialised in format"); //must be the first!
765         RUN_(LuksUUID, "luksUUID API call");
766         RUN_(IsLuks, "isLuks API call");
767         RUN_(LuksOpen, "luksOpen API call");
768         RUN_(query_device, "crypt_query_device API call");
769         RUN_(remove_device, "crypt_remove_device API call");
770         RUN_(LuksFormat, "luksFormat API call");
771         RUN_(LuksKeyGame, "luksAddKey, RemoveKey, KillSlot API calls");
772         RUN_(DeviceResizeGame, "regular crypto, resize calls");
773
774         RUN_(AddDevicePlain, "plain device API creation exercise");
775         RUN_(AddDeviceLuks, "Format and use LUKS device");
776         RUN_(UseLuksDevice, "Use pre-formated LUKS device");
777         RUN_(SuspendDevice, "Suspend/Resume test");
778
779         _cleanup();
780         return 0;
781 }