Fix FSF address in license text according to
[platform/upstream/cryptsetup.git] / docs / examples / crypt_luks_usage.c
1 /*
2  * An example of using LUKS device through libcryptsetup API
3  *
4  * Copyright (C) 2011, Red Hat, Inc. All rights reserved.
5  *
6  * This file is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This file is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <inttypes.h>
26 #include <sys/types.h>
27 #include <libcryptsetup.h>
28
29 static int format_and_add_keyslots(const char *path)
30 {
31         struct crypt_device *cd;
32         struct crypt_params_luks1 params;
33         int r;
34
35         /*
36          * crypt_init() call precedes most of operations of cryptsetup API. The call is used
37          * to initialize crypt device context stored in structure referenced by _cd_ in
38          * the example. Second parameter is used to pass underlaying device path.
39          *
40          * Note:
41          * If path refers to a regular file it'll be attached to a first free loop device.
42          * crypt_init() operation fails in case there's no more loop device available.
43          * Also, loop device will have the AUTOCLEAR flag set, so the file loopback will
44          * be detached automatically.
45          */
46
47         r = crypt_init(&cd, path);
48         if (r < 0 ) {
49                 printf("crypt_init() failed for %s.\n", path);
50                 return r;
51         }
52
53         printf("Context is attached to block device %s.\n", crypt_get_device_name(cd));
54
55         /*
56          * So far no data were written on your device. This will change with call of
57          * crypt_format() only if you specify CRYPT_LUKS1 as device type.
58          */
59         printf("Device %s will be formatted to LUKS device after 5 seconds.\n"
60                "Press CTRL+C now if you want to cancel this operation.\n", path);
61         sleep(5);
62
63
64         /*
65          * Prepare LUKS format parameters
66          *
67          * hash parameter defines PBKDF2 hash algorithm used in LUKS header.
68          * For compatibility reason we use SHA1 here.
69          */
70         params.hash = "sha1";
71
72         /*
73          * data_alignment parameter is relevant only in case of the luks header
74          * and the payload are both stored on same device.
75          *
76          * if you set data_alignment = 0, cryptsetup will autodetect
77          * data_alignment according to underlaying device topology.
78          */
79         params.data_alignment = 0;
80
81         /*
82          * data_device parameter defines that no external device
83          * for luks header will be used
84          */
85         params.data_device = NULL;
86
87         /*
88          * NULLs for uuid and volume_key means that these attributes will be
89          * generated during crypt_format(). Volume key is generated with respect
90          * to key size parameter passed to function.
91          *
92          * crypt_format() checks device size (LUKS header must fit there).
93          */
94         r = crypt_format(cd,            /* crypt context */
95                          CRYPT_LUKS1,   /* LUKS1 is standard LUKS header */
96                          "aes",         /* used cipher */
97                          "xts-plain64", /* used block mode and IV generator*/
98                          NULL,          /* generate UUID */
99                          NULL,          /* generate volume key from RNG */
100                          256 / 8,       /* 256bit key - here AES-128 in XTS mode, size is in bytes */
101                          &params);      /* parameters above */
102
103         if(r < 0) {
104                 printf("crypt_format() failed on device %s\n", crypt_get_device_name(cd));
105                 crypt_free(cd);
106                 return r;
107         }
108
109         /*
110          * The device now contains LUKS1 header, but there is
111          * no active keyslot with encrypted volume key yet.
112          */
113
114         /*
115          * cryptt_kesylot_add_* call stores volume_key in encrypted form into keyslot.
116          * Without keyslot you can't manipulate with LUKS device after the context will be freed.
117          *
118          * To create a new keyslot you need to supply the existing one (to get the volume key from) or
119          * you need to supply the volume key.
120          *
121          * After format, we have volume key stored internally in context so add new keyslot
122          * using this internal volume key.
123          */
124         r = crypt_keyslot_add_by_volume_key(cd,                 /* crypt context */
125                                             CRYPT_ANY_SLOT,     /* just use first free slot */
126                                             NULL,               /* use internal volume key */
127                                             0,                  /* unused (size of volume key) */
128                                             "foo",              /* passphrase - NULL means query*/
129                                             3);                 /* size of passphrase */
130
131         if (r < 0) {
132                 printf("Adding keyslot failed.\n");
133                 crypt_free(cd);
134                 return r;
135         }
136
137         printf("The first keyslot is initialized.\n");
138
139         /*
140          * Add another keyslot, now using the first keyslot.
141          * It will decrypt volume key from the first keyslot and creates new one with another passphrase.
142          */
143         r = crypt_keyslot_add_by_passphrase(cd,                 /* crypt context */
144                                             CRYPT_ANY_SLOT,     /* just use first free slot */
145                                             "foo", 3,           /* passphrase for the old keyslot */
146                                             "bar", 3);          /* passphrase for the new kesylot */
147         if (r < 0) {
148                 printf("Adding keyslot failed.\n");
149                 crypt_free(cd);
150                 return r;
151         }
152
153         printf("The second keyslot is initialized.\n");
154
155         crypt_free(cd);
156         return 0;
157 }
158
159 static int activate_and_check_status(const char *path, const char *device_name)
160 {
161         struct crypt_device *cd;
162         struct crypt_active_device cad;
163         int r;
164
165         /*
166          * LUKS device activation example.
167          * It's sequence of sub-steps: device initialization, LUKS header load
168          * and the device activation itself.
169          */
170         r = crypt_init(&cd, path);
171         if (r < 0 ) {
172                 printf("crypt_init() failed for %s.\n", path);
173                 return r;
174         }
175
176         /*
177          * crypt_load() is used to load the LUKS header from block device
178          * into crypt_device context.
179          */
180         r = crypt_load(cd,              /* crypt context */
181                        CRYPT_LUKS1,     /* requested type */
182                        NULL);           /* additional parameters (not used) */
183
184         if (r < 0) {
185                 printf("crypt_load() failed on device %s.\n", crypt_get_device_name(cd));
186                 crypt_free(cd);
187                 return r;
188         }
189
190         /*
191          * Device activation creates device-mapper devie mapping with name device_name.
192          */
193         r = crypt_activate_by_passphrase(cd,            /* crypt context */
194                                          device_name,   /* device name to activate */
195                                          CRYPT_ANY_SLOT,/* which slot use (ANY - try all) */
196                                          "foo", 3,      /* passphrase */
197                                          CRYPT_ACTIVATE_READONLY); /* flags */
198         if (r < 0) {
199                 printf("Device %s activation failed.\n", device_name);
200                 crypt_free(cd);
201                 return r;
202         }
203
204         printf("LUKS device %s/%s is active.\n", crypt_get_dir(), device_name);
205         printf("\tcipher used: %s\n", crypt_get_cipher(cd));
206         printf("\tcipher mode: %s\n", crypt_get_cipher_mode(cd));
207         printf("\tdevice UUID: %s\n", crypt_get_uuid(cd));
208
209         /*
210          * Get info about active device (query DM backend)
211          */
212         r = crypt_get_active_device(cd, device_name, &cad);
213         if (r < 0) {
214                 printf("Get info about active device %s failed.\n", device_name);
215                 crypt_deactivate(cd, device_name);
216                 crypt_free(cd);
217                 return r;
218         }
219
220         printf("Active device parameters for %s:\n"
221                 "\tDevice offset (in sectors): %" PRIu64 "\n"
222                 "\tIV offset (in sectors)    : %" PRIu64 "\n"
223                 "\tdevice size (in sectors)  : %" PRIu64 "\n"
224                 "\tread-only flag            : %s\n",
225                 device_name, cad.offset, cad.iv_offset, cad.size,
226                 cad.flags & CRYPT_ACTIVATE_READONLY ? "1" : "0");
227
228         crypt_free(cd);
229         return 0;
230 }
231
232 static int handle_active_device(const char *device_name)
233 {
234         struct crypt_device *cd;
235         int r;
236
237         /*
238          * crypt_init_by_name() initializes device context and loads LUKS header from backing device
239          */
240         r = crypt_init_by_name(&cd, device_name);
241         if (r < 0) {
242                 printf("crypt_init_by_name() failed for %s.\n", device_name);
243                 return r;
244         }
245
246         if (crypt_status(cd, device_name) == CRYPT_ACTIVE)
247                 printf("Device %s is still active.\n", device_name);
248         else {
249                 printf("Something failed perhaps, device %s is not active.\n", device_name);
250                 crypt_free(cd);
251                 return -1;
252         }
253
254         /*
255          * crypt_deactivate() is used to deactivate device
256          */
257         r = crypt_deactivate(cd, device_name);
258         if (r < 0) {
259                 printf("crypt_deactivate() failed.\n");
260                 crypt_free(cd);
261                 return r;
262         }
263
264         printf("Device %s is now deactivated.\n", device_name);
265
266         crypt_free(cd);
267         return 0;
268 }
269
270 int main(int argc, char **argv)
271 {
272         if (geteuid()) {
273                 printf("Using of libcryptsetup requires super user privileges.\n");
274                 return 1;
275         }
276
277         if (argc != 2) {
278                 printf("usage: ./crypt_luks_usage <path>\n"
279                         "<path> refers to either a regular file or a block device.\n"
280                         "       WARNING: the file or device will be wiped.\n");
281                 return 2;
282         }
283
284         if (format_and_add_keyslots(argv[1]))
285                 return 3;
286
287         if (activate_and_check_status(argv[1], "example_device"))
288                 return 4;
289
290         if (handle_active_device("example_device"))
291                 return 5;
292
293         return 0;
294 }