2 * An example of using LUKS device through libcryptsetup API
4 * Copyright (C) 2011, Red Hat, Inc. All rights reserved.
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.
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.
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.
26 #include <sys/types.h>
27 #include <libcryptsetup.h>
29 static int format_and_add_keyslots(const char *path)
31 struct crypt_device *cd;
32 struct crypt_params_luks1 params;
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.
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.
47 r = crypt_init(&cd, path);
49 printf("crypt_init() failed for %s.\n", path);
53 printf("Context is attached to block device %s.\n", crypt_get_device_name(cd));
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.
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);
65 * Prepare LUKS format parameters
67 * hash parameter defines PBKDF2 hash algorithm used in LUKS header.
68 * For compatibility reason we use SHA1 here.
73 * data_alignment parameter is relevant only in case of the luks header
74 * and the payload are both stored on same device.
76 * if you set data_alignment = 0, cryptsetup will autodetect
77 * data_alignment according to underlaying device topology.
79 params.data_alignment = 0;
82 * data_device parameter defines that no external device
83 * for luks header will be used
85 params.data_device = NULL;
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.
92 * crypt_format() checks device size (LUKS header must fit there).
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 ¶ms); /* parameters above */
104 printf("crypt_format() failed on device %s\n", crypt_get_device_name(cd));
110 * The device now contains LUKS1 header, but there is
111 * no active keyslot with encrypted volume key yet.
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.
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.
121 * After format, we have volume key stored internally in context so add new keyslot
122 * using this internal volume key.
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 */
132 printf("Adding keyslot failed.\n");
137 printf("The first keyslot is initialized.\n");
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.
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 */
148 printf("Adding keyslot failed.\n");
153 printf("The second keyslot is initialized.\n");
159 static int activate_and_check_status(const char *path, const char *device_name)
161 struct crypt_device *cd;
162 struct crypt_active_device cad;
166 * LUKS device activation example.
167 * It's sequence of sub-steps: device initialization, LUKS header load
168 * and the device activation itself.
170 r = crypt_init(&cd, path);
172 printf("crypt_init() failed for %s.\n", path);
177 * crypt_load() is used to load the LUKS header from block device
178 * into crypt_device context.
180 r = crypt_load(cd, /* crypt context */
181 CRYPT_LUKS1, /* requested type */
182 NULL); /* additional parameters (not used) */
185 printf("crypt_load() failed on device %s.\n", crypt_get_device_name(cd));
191 * Device activation creates device-mapper devie mapping with name device_name.
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 */
199 printf("Device %s activation failed.\n", device_name);
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));
210 * Get info about active device (query DM backend)
212 r = crypt_get_active_device(cd, device_name, &cad);
214 printf("Get info about active device %s failed.\n", device_name);
215 crypt_deactivate(cd, device_name);
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");
232 static int handle_active_device(const char *device_name)
234 struct crypt_device *cd;
238 * crypt_init_by_name() initializes device context and loads LUKS header from backing device
240 r = crypt_init_by_name(&cd, device_name);
242 printf("crypt_init_by_name() failed for %s.\n", device_name);
246 if (crypt_status(cd, device_name) == CRYPT_ACTIVE)
247 printf("Device %s is still active.\n", device_name);
249 printf("Something failed perhaps, device %s is not active.\n", device_name);
255 * crypt_deactivate() is used to deactivate device
257 r = crypt_deactivate(cd, device_name);
259 printf("crypt_deactivate() failed.\n");
264 printf("Device %s is now deactivated.\n", device_name);
270 int main(int argc, char **argv)
273 printf("Using of libcryptsetup requires super user privileges.\n");
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");
284 if (format_and_add_keyslots(argv[1]))
287 if (activate_and_check_status(argv[1], "example_device"))
290 if (handle_active_device("example_device"))