2 * libcryptsetup API - using LUKS device example
4 * Copyright (C) 2011-2020 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;
35 * The crypt_init() call is used to initialize crypt_device context,
36 * The path parameter specifies a device path.
38 * For path, you can use either link to a file or block device.
39 * The loopback device will be detached automatically.
42 r = crypt_init(&cd, path);
44 printf("crypt_init() failed for %s.\n", path);
48 printf("Context is attached to block device %s.\n", crypt_get_device_name(cd));
51 * So far, no data were written to the device.
53 printf("Device %s will be formatted as a LUKS device after 5 seconds.\n"
54 "Press CTRL+C now if you want to cancel this operation.\n", path);
58 * NULLs for uuid and volume_key means that these attributes will be
59 * generated during crypt_format().
61 r = crypt_format(cd, /* crypt context */
62 CRYPT_LUKS2, /* LUKS2 is a new LUKS format; use CRYPT_LUKS1 for LUKS1 */
63 "aes", /* used cipher */
64 "xts-plain64", /* used block mode and IV */
65 NULL, /* generate UUID */
66 NULL, /* generate volume key from RNG */
67 512 / 8, /* 512bit key - here AES-256 in XTS mode, size is in bytes */
68 NULL); /* default parameters */
71 printf("crypt_format() failed on device %s\n", crypt_get_device_name(cd));
77 * The device now contains a LUKS header, but there is no active keyslot.
79 * crypt_keyslot_add_* call stores the volume_key in the encrypted form into the keyslot.
81 * After format, the volume key is stored internally.
83 r = crypt_keyslot_add_by_volume_key(cd, /* crypt context */
84 CRYPT_ANY_SLOT, /* just use first free slot */
85 NULL, /* use internal volume key */
86 0, /* unused (size of volume key) */
87 "foo", /* passphrase - NULL means query*/
88 3); /* size of passphrase */
91 printf("Adding keyslot failed.\n");
96 printf("The first keyslot is initialized.\n");
99 * Add another keyslot, now authenticating with the first keyslot.
100 * It decrypts the volume key from the first keyslot and creates a new one with the specified passphrase.
102 r = crypt_keyslot_add_by_passphrase(cd, /* crypt context */
103 CRYPT_ANY_SLOT, /* just use first free slot */
104 "foo", 3, /* passphrase for the old keyslot */
105 "bar", 3); /* passphrase for the new kesylot */
107 printf("Adding keyslot failed.\n");
112 printf("The second keyslot is initialized.\n");
118 static int activate_and_check_status(const char *path, const char *device_name)
120 struct crypt_device *cd;
121 struct crypt_active_device cad;
125 * LUKS device activation example.
127 r = crypt_init(&cd, path);
129 printf("crypt_init() failed for %s.\n", path);
134 * crypt_load() is used to load existing LUKS header from a block device
136 r = crypt_load(cd, /* crypt context */
137 CRYPT_LUKS, /* requested type - here LUKS of any type */
138 NULL); /* additional parameters (not used) */
141 printf("crypt_load() failed on device %s.\n", crypt_get_device_name(cd));
147 * Device activation creates a device-mapper device with the specified name.
149 r = crypt_activate_by_passphrase(cd, /* crypt context */
150 device_name, /* device name to activate */
151 CRYPT_ANY_SLOT,/* the keyslot use (try all here) */
152 "foo", 3, /* passphrase */
153 CRYPT_ACTIVATE_READONLY); /* flags */
155 printf("Device %s activation failed.\n", device_name);
160 printf("%s device %s/%s is active.\n", crypt_get_type(cd), crypt_get_dir(), device_name);
161 printf("\tcipher used: %s\n", crypt_get_cipher(cd));
162 printf("\tcipher mode: %s\n", crypt_get_cipher_mode(cd));
163 printf("\tdevice UUID: %s\n", crypt_get_uuid(cd));
166 * Get info about the active device.
168 r = crypt_get_active_device(cd, device_name, &cad);
170 printf("Get info about active device %s failed.\n", device_name);
171 crypt_deactivate(cd, device_name);
176 printf("Active device parameters for %s:\n"
177 "\tDevice offset (in sectors): %" PRIu64 "\n"
178 "\tIV offset (in sectors) : %" PRIu64 "\n"
179 "\tdevice size (in sectors) : %" PRIu64 "\n"
180 "\tread-only flag : %s\n",
181 device_name, cad.offset, cad.iv_offset, cad.size,
182 cad.flags & CRYPT_ACTIVATE_READONLY ? "1" : "0");
188 static int handle_active_device(const char *device_name)
190 struct crypt_device *cd;
194 * crypt_init_by_name() initializes context by an active device-mapper name
196 r = crypt_init_by_name(&cd, device_name);
198 printf("crypt_init_by_name() failed for %s.\n", device_name);
202 if (crypt_status(cd, device_name) == CRYPT_ACTIVE)
203 printf("Device %s is still active.\n", device_name);
205 printf("Something failed perhaps, device %s is not active.\n", device_name);
211 * crypt_deactivate() is used to deactivate a device
213 r = crypt_deactivate(cd, device_name);
215 printf("crypt_deactivate() failed.\n");
220 printf("Device %s is now deactivated.\n", device_name);
226 int main(int argc, char **argv)
229 printf("Using of libcryptsetup requires super user privileges.\n");
234 printf("usage: ./crypt_luks_usage <path>\n"
235 "<path> refers to either a regular file or a block device.\n"
236 " WARNING: the file or device will be wiped.\n");
240 if (format_and_add_keyslots(argv[1]))
243 if (activate_and_check_status(argv[1], "example_device"))
246 if (handle_active_device("example_device"))