7 #include <libcryptsetup.h>
9 #include "crypt_examples.h"
12 #define EX_DEV_NAME "ex_crypt_dev"
13 #define DMDIR "/dev/mapper/"
14 #define SECTOR_SIZE 512
17 * You can use this example with command line parameters as follows,
18 * but please note, that this example will not do any sophisticated parameters
21 * ./crypt_luks_usage <path>
24 * <path> is either regular file or block device. DO NOT use your physical HDD
25 * with running system or another device containing valuable data otherwise you risk
26 * partial or complete loss of it.
28 static void usage(const char *msg)
30 fprintf(stderr, "ERROR: %s\nusage: ./crypt_luks_usage <path>\n"
31 "The <path> can refer to either a regular file or a block device.\n",
35 int main(int argc, char **argv)
37 char *answer = NULL, *cipher, *cipher_mode, *dev;
40 /* crypt device handle */
41 struct crypt_active_device cad;
42 struct crypt_device *cd;
43 struct crypt_params_luks1 params;
46 fprintf(stderr, "WARN: Process doesn't have super user privileges. "
47 "Most of examples will fail because of that.\n");
50 usage("Wrong number of cmd line parameters.");
59 * crypt_init() call precedes most of operations of cryptsetup API. The call is used
60 * to initialize crypt device context stored in structure referenced by _cd_ in
61 * the example. Second parameter is used to pass underlaying device path.
64 * If path refers to a regular file it'll be attached to a first free loop device.
65 * crypt_init() operation fails in case there's no more loop device available.
66 * Also, loop device will have the AUTOCLEAR flag set, so the file will be
67 * detached after crypt_free() call on the concerned context.
69 EX_STEP(++step, "crypt_init()");
70 if ((r = crypt_init(&cd, dev))) {
71 EX_FAIL("crypt_init() failed for '%s'\n", dev ?: "(not set)");
74 EX_SUCCESS("crypt_init() on '%s' has been successful", dev);
75 if (strcmp(dev, crypt_get_device_name(cd)))
76 printf("\tFile '%s' has been attached to %s\n", dev, crypt_get_device_name(cd));
80 * So far no data were written on your device. This will change with call of
81 * crypt_format() only if you specify CRYPT_LUKS1 as device type.
83 printf("8 initial sectors of the device will be overwritten\n"
84 "Are you sure you want to call crypt_format() over '%s'?\n"
85 "If you're absolutely sure the device doesn't contain any valuable data,\n"
86 "approve the operation by typing 'yes' in upper case: ", crypt_get_device_name(cd));
88 if ((r = getline(&answer, &size, stdin)) == -1) {
93 if (strcmp(answer, "YES\n"))
96 /* Example of crypt_format() follows: */
99 * cipher and cipher_mode:
101 * you'll get more on _cipher_ and _cipher_mode_ in man page
102 * for cryptsetup userspace utility or at cryptsetup project
106 cipher_mode = "cbc-essiv:sha256";
107 params.hash = "sha1";
110 * This parameter is relevant only in case of the luks header
111 * and the payload are both stored on same device.
113 * In this particular case, payload offset (which is
114 * computed internaly, according to volume key size)
115 * is aligned to 2048 sectors
117 * if you set data_alignment = 0, cryptsetup will autodetect
118 * data_alignment from underlaying device topology.
120 params.data_alignment = 2048;
123 * this parameter defines that no external device
124 * for luks header will be used
126 params.data_device = NULL;
131 * NULLs for uuid and volume_key means that these attributes will be
132 * generated during crypt_format(). Volume key is generated with respect
133 * to key size parameter passed to function.
135 * Note that in crypt_format() device is checked wheter it's large enough to
136 * store the luks header only.
138 EX_STEP(++step, "crypt_format()");
139 if((r = crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, NULL, KEY_SIZE, ¶ms))) {
140 EX_FAIL("crypt_format() failed on device %s\n", crypt_get_device_name(cd));
143 EX_SUCCESS("crypt_format() on device %s formated successfully. "
144 "The device now contains LUKS1 header, but there is no active keyslot with encrypted "
145 "volume key.", crypt_get_device_name(cd));
151 * This call is intended to store volume_key in encrypted form into structure called keyslot.
152 * Without keyslot you can't manipulate with LUKS device after the context will be freed.
154 * To create a new keyslot you need to supply the existing one (to get the volume key from) or
155 * you need to supply the volume key. Now we have volume key stored internally and we have no active
156 * keyslot so this the only option.
159 printf("Going to create a new keyslot...\n");
160 EX_STEP(++step, "crypt_keyslot_add_by_volume_key()");
161 if ((r = crypt_keyslot_add_by_volume_key(cd, CRYPT_ANY_SLOT, NULL, 0, NULL, 0)) < 0) {
162 EX_FAIL("Adding keyslot failed.");
165 EX_SUCCESS("Keyslot nr. %d created successfully on device %s.", r, crypt_get_device_name(cd));
171 * This is the example of the second method mentioned in STEP 03. By supplying passphrase for
172 * the active keyslot you can create a new one.
174 printf("Now let's try to add a keyslot using the existing active keyslot\n");
175 EX_STEP(++step, "crypt_keyslot_add_by_passphrase()");
176 if ((r = crypt_keyslot_add_by_passphrase(cd, CRYPT_ANY_SLOT, NULL, 0, NULL, 0)) < 0) {
177 EX_FAIL("Adding keyslot failed\n");
180 EX_SUCCESS("Keyslot nr. %d created successfully and written on device %s.", r, crypt_get_device_name(cd));
189 * In previous steps the device was formatted (LUKS header was written to backing device)
190 * and keyslots were activated (volume key was written in two separate structures encrypted
191 * by two user supplied passwords).
193 * This example demonstrates typical use case for LUKS device activation.
194 * It's sequence of sub-steps: device initialization (crypt_init), LUKS header load (crypt_load())
195 * and finally the device activation itself
197 EX_PRESS_ENTER("Device context going to be freed. New one will initialized to demonstrate activation process.");
198 EX_STEP(++step, "crypt_init()");
199 if ((r = crypt_init(&cd, dev))) {
200 EX_FAIL("crypt_init() failed for '%s'!", dev);
203 EX_SUCCESS("crypt_init() on '%s' has been successful.", dev);
204 if (strcmp(dev, crypt_get_device_name(cd)))
205 printf("\tFile '%s' has been attached to %s\n", dev, crypt_get_device_name(cd));
209 * crypt_load() is used to load the LUKS header from backing block device
210 * into crypt_device context
212 EX_PRESS_ENTER("Going to load LUKS header.");
213 EX_STEP(step, "crypt_load()");
214 if ((r = crypt_load(cd, CRYPT_LUKS1, ¶ms))) {
215 EX_FAIL("crypt_load() failed on device '%s'!", crypt_get_device_name(cd));
218 EX_SUCCESS("crypt_load() successful. The header has been read from %s.", crypt_get_device_name(cd));
224 * Device activation creates mapping in device-mapper with name EX_DEV_NAME.
225 * The volume key is stored into kernel mem. space and the encryption of backing
226 * device is now set in motion.
228 printf("Going to activate LUKS device\n");
229 EX_STEP(step, "crypt_activate_by_passphrase()");
230 if ((r = crypt_activate_by_passphrase(cd, EX_DEV_NAME, CRYPT_ANY_SLOT, NULL, 0, 0)) < 0) {
231 EX_FAIL("Device activation failed!");
234 EX_SUCCESS("Encrypted device is active on " DMDIR EX_DEV_NAME ".");
235 printf("\tThe cipher used in device context: '%s'\n", crypt_get_cipher(cd) ?: "(not set) !");
236 printf("\tThe cipher mode used in device context: '%s'\n", crypt_get_cipher_mode(cd) ?: "(not set) !");
237 printf("\tThe device UUID '%s'\n", crypt_get_uuid(cd) ?: "(not set) !");
243 * Get info about active device (query DM backend)
245 EX_PRESS_ENTER("Going to get active active device parameters.");
246 EX_STEP(++step, "crypt_get_active_device()");
247 if ((r = crypt_get_active_device(cd, EX_DEV_NAME, &cad))) {
248 EX_FAIL("Get info about active device '%s' failed!", EX_DEV_NAME);
251 EX_SUCCESS("Active device parameters for " EX_DEV_NAME ":\n"
252 "\tPayload offset (in sectors): %" PRIu64 "\n"
253 "\tEncrypted payload area size in sectors: %" PRIu64 " and bytes: %" PRIu64 "\n"
254 "\tThe device has a read-only flag %sset",
255 cad.offset, cad.size, cad.size * SECTOR_SIZE,
256 cad.flags & CRYPT_ACTIVATE_READONLY ? "" : "not ");
265 * crypt_init_by_name() initializes device context and loads LUKS header from backing device
267 EX_PRESS_ENTER("The context used in previous examples is going to be freed to demonstrate "
268 "how to initialize a device context from the active device.");
269 EX_STEP(++step, "crypt_init_by_name()");
270 if ((r = crypt_init_by_name(&cd, EX_DEV_NAME))) {
271 EX_FAIL("crypt_init_by_name() failed for the device name: " EX_DEV_NAME);
274 EX_SUCCESS("A new context has been initialized, LUKS header has been restored"
275 "\n\tDevice UUID is '%s'", crypt_get_uuid(cd));
280 * crypt_deactivate() is used to remove the volume_key from kernel mem. space and to remove the
281 * device nod associated with decrypted backing device.
284 EX_PRESS_ENTER("\n\tGoing to deactivate the crypt device. Note that the device "
285 "won't be deactivated while it's opened with O_EXCL flag (e.g. mounted).");
286 EX_STEP(++step, "crypt_deactivate()");
287 //printf("\nPress <ENTER> to continue to device deactivation of the test device.\n"
288 // "Note that mounted device won't be deactivated. First unmount the device!");
290 while ((r = crypt_deactivate(cd, EX_DEV_NAME))) {
291 EX_FAIL("crypt_deactivate() failed. Most propably the device is still busy!");
292 EX_PRESS_ENTER("Going to retry device deactivation");
294 EX_SUCCESS("crypt_deactivate() successful. Device " DMDIR EX_DEV_NAME " is now deactivated");
297 if (crypt_status(cd, EX_DEV_NAME) == CRYPT_ACTIVE)
298 crypt_deactivate(cd, EX_DEV_NAME);
301 /* always free context which is no longer used */