mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-11 19:00:02 +01:00
Rewrite examples to more simple format.
git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@631 36d66b0a-2a48-0410-832c-cd162a569da5
This commit is contained in:
@@ -6,56 +6,13 @@
|
||||
#include <sys/types.h>
|
||||
#include <libcryptsetup.h>
|
||||
|
||||
#include "crypt_examples.h"
|
||||
|
||||
#define KEY_SIZE 32
|
||||
#define EX_DEV_NAME "ex_crypt_dev"
|
||||
#define DMDIR "/dev/mapper/"
|
||||
#define SECTOR_SIZE 512
|
||||
|
||||
/*
|
||||
* You can use this example with command line parameters as follows,
|
||||
* but please note, that this example will not do any sophisticated parameters
|
||||
* checking at all.
|
||||
*
|
||||
* ./crypt_luks_usage <path>
|
||||
*
|
||||
* where:
|
||||
* <path> is either regular file or block device. DO NOT use your physical HDD
|
||||
* with running system or another device containing valuable data otherwise you risk
|
||||
* partial or complete loss of it.
|
||||
*/
|
||||
static void usage(const char *msg)
|
||||
static int format_and_add_keyslots(const char *path)
|
||||
{
|
||||
fprintf(stderr, "ERROR: %s\nusage: ./crypt_luks_usage <path>\n"
|
||||
"The <path> can refer to either a regular file or a block device.\n",
|
||||
msg ?: "");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *answer = NULL, *cipher, *cipher_mode, *dev;
|
||||
int step = 0, r;
|
||||
size_t size = 0;
|
||||
/* crypt device handle */
|
||||
struct crypt_active_device cad;
|
||||
struct crypt_device *cd;
|
||||
struct crypt_params_luks1 params;
|
||||
|
||||
if (geteuid())
|
||||
fprintf(stderr, "WARN: Process doesn't have super user privileges. "
|
||||
"Most of examples will fail because of that.\n");
|
||||
|
||||
if (argc != 2) {
|
||||
usage("Wrong number of cmd line parameters.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dev = argv[1];
|
||||
int r;
|
||||
|
||||
/*
|
||||
* __STEP_01__
|
||||
*
|
||||
* crypt_init() call precedes most of operations of cryptsetup API. The call is used
|
||||
* to initialize crypt device context stored in structure referenced by _cd_ in
|
||||
* the example. Second parameter is used to pass underlaying device path.
|
||||
@@ -63,244 +20,255 @@ int main(int argc, char **argv)
|
||||
* Note:
|
||||
* If path refers to a regular file it'll be attached to a first free loop device.
|
||||
* crypt_init() operation fails in case there's no more loop device available.
|
||||
* Also, loop device will have the AUTOCLEAR flag set, so the file will be
|
||||
* detached after crypt_free() call on the concerned context.
|
||||
* Also, loop device will have the AUTOCLEAR flag set, so the file loopback will
|
||||
* be detached automatically.
|
||||
*/
|
||||
EX_STEP(++step, "crypt_init()");
|
||||
if ((r = crypt_init(&cd, dev))) {
|
||||
EX_FAIL("crypt_init() failed for '%s'\n", dev ?: "(not set)");
|
||||
|
||||
r = crypt_init(&cd, path);
|
||||
if (r < 0 ) {
|
||||
printf("crypt_init() failed for %s.\n", path);
|
||||
return r;
|
||||
}
|
||||
EX_SUCCESS("crypt_init() on '%s' has been successful", dev);
|
||||
if (strcmp(dev, crypt_get_device_name(cd)))
|
||||
printf("\tFile '%s' has been attached to %s\n", dev, crypt_get_device_name(cd));
|
||||
|
||||
EX_DELIM;
|
||||
printf("Context is attached to block device %s.\n", crypt_get_device_name(cd));
|
||||
|
||||
/*
|
||||
* So far no data were written on your device. This will change with call of
|
||||
* crypt_format() only if you specify CRYPT_LUKS1 as device type.
|
||||
*/
|
||||
printf("8 initial sectors of the device will be overwritten\n"
|
||||
"Are you sure you want to call crypt_format() over '%s'?\n"
|
||||
"If you're absolutely sure the device doesn't contain any valuable data,\n"
|
||||
"approve the operation by typing 'yes' in upper case: ", crypt_get_device_name(cd));
|
||||
printf("Device %s will be formatted to LUKS device after 5 seconds.\n"
|
||||
"Press CTRL+C now if you want to cancel this operation.\n", path);
|
||||
sleep(5);
|
||||
|
||||
if ((r = getline(&answer, &size, stdin)) == -1) {
|
||||
perror("getline");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp(answer, "YES\n"))
|
||||
goto out;
|
||||
|
||||
/* Example of crypt_format() follows: */
|
||||
|
||||
/*
|
||||
* cipher and cipher_mode:
|
||||
* Prepare LUKS format parameters
|
||||
*
|
||||
* you'll get more on _cipher_ and _cipher_mode_ in man page
|
||||
* for cryptsetup userspace utility or at cryptsetup project
|
||||
* documentation.
|
||||
* hash parameter defines PBKDF2 hash algorithm used in LUKS header.
|
||||
* For compatibility reason we use SHA1 here.
|
||||
*/
|
||||
cipher = "aes";
|
||||
cipher_mode = "cbc-essiv:sha256";
|
||||
params.hash = "sha1";
|
||||
|
||||
/*
|
||||
* This parameter is relevant only in case of the luks header
|
||||
* data_alignment parameter is relevant only in case of the luks header
|
||||
* and the payload are both stored on same device.
|
||||
*
|
||||
* In this particular case, payload offset (which is
|
||||
* computed internaly, according to volume key size)
|
||||
* is aligned to 2048 sectors
|
||||
*
|
||||
* if you set data_alignment = 0, cryptsetup will autodetect
|
||||
* data_alignment from underlaying device topology.
|
||||
* data_alignment according to underlaying device topology.
|
||||
*/
|
||||
params.data_alignment = 2048;
|
||||
params.data_alignment = 0;
|
||||
|
||||
/*
|
||||
* this parameter defines that no external device
|
||||
* data_device parameter defines that no external device
|
||||
* for luks header will be used
|
||||
*/
|
||||
params.data_device = NULL;
|
||||
|
||||
/*
|
||||
* __STEP_02__
|
||||
*
|
||||
* NULLs for uuid and volume_key means that these attributes will be
|
||||
* generated during crypt_format(). Volume key is generated with respect
|
||||
* to key size parameter passed to function.
|
||||
*
|
||||
* Note that in crypt_format() device is checked wheter it's large enough to
|
||||
* store the luks header only.
|
||||
* crypt_format() checks device size (LUKS header must fit there).
|
||||
*/
|
||||
EX_STEP(++step, "crypt_format()");
|
||||
if((r = crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, NULL, KEY_SIZE, ¶ms))) {
|
||||
EX_FAIL("crypt_format() failed on device %s\n", crypt_get_device_name(cd));
|
||||
goto out;
|
||||
r = crypt_format(cd, /* crypt context */
|
||||
CRYPT_LUKS1, /* LUKS1 is standard LUKS header */
|
||||
"aes", /* used cipher */
|
||||
"xts-plain64", /* used block mode and IV generator*/
|
||||
NULL, /* generate UUID */
|
||||
NULL, /* generate volume key from RNG */
|
||||
256 / 8, /* 256bit key - here AES-128 in XTS mode, size is in bytes */
|
||||
¶ms); /* parameters above */
|
||||
|
||||
if(r < 0) {
|
||||
printf("crypt_format() failed on device %s\n", crypt_get_device_name(cd));
|
||||
crypt_free(cd);
|
||||
return r;
|
||||
}
|
||||
EX_SUCCESS("crypt_format() on device %s formated successfully. "
|
||||
"The device now contains LUKS1 header, but there is no active keyslot with encrypted "
|
||||
"volume key.", crypt_get_device_name(cd));
|
||||
EX_DELIM;
|
||||
|
||||
/*
|
||||
* __STEP_03__
|
||||
*
|
||||
* This call is intended to store volume_key in encrypted form into structure called keyslot.
|
||||
* The device now contains LUKS1 header, but there is
|
||||
* no active keyslot with encrypted volume key yet.
|
||||
*/
|
||||
|
||||
/*
|
||||
* cryptt_kesylot_add_* call stores volume_key in encrypted form into keyslot.
|
||||
* Without keyslot you can't manipulate with LUKS device after the context will be freed.
|
||||
*
|
||||
* To create a new keyslot you need to supply the existing one (to get the volume key from) or
|
||||
* you need to supply the volume key. Now we have volume key stored internally and we have no active
|
||||
* keyslot so this the only option.
|
||||
* you need to supply the volume key.
|
||||
*
|
||||
* After format, we have volume key stored internally in context so add new keyslot
|
||||
* using this internal volume key.
|
||||
*/
|
||||
printf("Going to create a new keyslot...\n");
|
||||
EX_STEP(++step, "crypt_keyslot_add_by_volume_key()");
|
||||
if ((r = crypt_keyslot_add_by_volume_key(cd, CRYPT_ANY_SLOT, NULL, 0, NULL, 0)) < 0) {
|
||||
EX_FAIL("Adding keyslot failed.");
|
||||
goto out;
|
||||
r = crypt_keyslot_add_by_volume_key(cd, /* crypt context */
|
||||
CRYPT_ANY_SLOT, /* just use first free slot */
|
||||
NULL, /* use internal volume key */
|
||||
0, /* unused (size of volume key) */
|
||||
"foo", /* passphrase - NULL means query*/
|
||||
3); /* size of passphrase */
|
||||
|
||||
if (r < 0) {
|
||||
printf("Adding keyslot failed.\n");
|
||||
crypt_free(cd);
|
||||
return r;
|
||||
}
|
||||
EX_SUCCESS("Keyslot nr. %d created successfully on device %s.", r, crypt_get_device_name(cd));
|
||||
EX_DELIM;
|
||||
|
||||
printf("The first keyslot is initialized.\n");
|
||||
|
||||
/*
|
||||
* __STEP_04__
|
||||
*
|
||||
* This is the example of the second method mentioned in STEP 03. By supplying passphrase for
|
||||
* the active keyslot you can create a new one.
|
||||
* Add another keyslot, now using the first keyslot.
|
||||
* It will decrypt volume key from the first keyslot and creates new one with another passphrase.
|
||||
*/
|
||||
printf("Now let's try to add a keyslot using the existing active keyslot\n");
|
||||
EX_STEP(++step, "crypt_keyslot_add_by_passphrase()");
|
||||
if ((r = crypt_keyslot_add_by_passphrase(cd, CRYPT_ANY_SLOT, NULL, 0, NULL, 0)) < 0) {
|
||||
EX_FAIL("Adding keyslot failed\n");
|
||||
goto out;
|
||||
r = crypt_keyslot_add_by_passphrase(cd, /* crypt context */
|
||||
CRYPT_ANY_SLOT, /* just use first free slot */
|
||||
"foo", 3, /* passphrase for the old keyslot */
|
||||
"bar", 3); /* passphrase for the new kesylot */
|
||||
if (r < 0) {
|
||||
printf("Adding keyslot failed.\n");
|
||||
crypt_free(cd);
|
||||
return r;
|
||||
}
|
||||
EX_SUCCESS("Keyslot nr. %d created successfully and written on device %s.", r, crypt_get_device_name(cd));
|
||||
EX_DELIM;
|
||||
|
||||
printf("The second keyslot is initialized.\n");
|
||||
|
||||
crypt_free(cd);
|
||||
cd = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int activate_and_check_status(const char *path, const char *device_name)
|
||||
{
|
||||
struct crypt_device *cd;
|
||||
struct crypt_active_device cad;
|
||||
int r;
|
||||
|
||||
/*
|
||||
* __STEP_05__
|
||||
*
|
||||
* In previous steps the device was formatted (LUKS header was written to backing device)
|
||||
* and keyslots were activated (volume key was written in two separate structures encrypted
|
||||
* by two user supplied passwords).
|
||||
*
|
||||
* This example demonstrates typical use case for LUKS device activation.
|
||||
* It's sequence of sub-steps: device initialization (crypt_init), LUKS header load (crypt_load())
|
||||
* and finally the device activation itself
|
||||
* LUKS device activation example.
|
||||
* It's sequence of sub-steps: device initialization, LUKS header load
|
||||
* and the device activation itself.
|
||||
*/
|
||||
EX_PRESS_ENTER("Device context going to be freed. New one will initialized to demonstrate activation process.");
|
||||
EX_STEP(++step, "crypt_init()");
|
||||
if ((r = crypt_init(&cd, dev))) {
|
||||
EX_FAIL("crypt_init() failed for '%s'!", dev);
|
||||
goto out;
|
||||
r = crypt_init(&cd, path);
|
||||
if (r < 0 ) {
|
||||
printf("crypt_init() failed for %s.\n", path);
|
||||
return r;
|
||||
}
|
||||
EX_SUCCESS("crypt_init() on '%s' has been successful.", dev);
|
||||
if (strcmp(dev, crypt_get_device_name(cd)))
|
||||
printf("\tFile '%s' has been attached to %s\n", dev, crypt_get_device_name(cd));
|
||||
EX_DELIM;
|
||||
/* __STEP_05__
|
||||
*
|
||||
* crypt_load() is used to load the LUKS header from backing block device
|
||||
* into crypt_device context
|
||||
*/
|
||||
EX_PRESS_ENTER("Going to load LUKS header.");
|
||||
EX_STEP(step, "crypt_load()");
|
||||
if ((r = crypt_load(cd, CRYPT_LUKS1, ¶ms))) {
|
||||
EX_FAIL("crypt_load() failed on device '%s'!", crypt_get_device_name(cd));
|
||||
goto out;
|
||||
}
|
||||
EX_SUCCESS("crypt_load() successful. The header has been read from %s.", crypt_get_device_name(cd));
|
||||
EX_DELIM;
|
||||
|
||||
/*
|
||||
* __STEP_05__
|
||||
*
|
||||
* Device activation creates mapping in device-mapper with name EX_DEV_NAME.
|
||||
* The volume key is stored into kernel mem. space and the encryption of backing
|
||||
* device is now set in motion.
|
||||
* crypt_load() is used to load the LUKS header from block device
|
||||
* into crypt_device context.
|
||||
*/
|
||||
printf("Going to activate LUKS device\n");
|
||||
EX_STEP(step, "crypt_activate_by_passphrase()");
|
||||
if ((r = crypt_activate_by_passphrase(cd, EX_DEV_NAME, CRYPT_ANY_SLOT, NULL, 0, 0)) < 0) {
|
||||
EX_FAIL("Device activation failed!");
|
||||
goto out;
|
||||
r = crypt_load(cd, /* crypt context */
|
||||
CRYPT_LUKS1, /* requested type */
|
||||
NULL); /* additional parameters (not used) */
|
||||
|
||||
if (r < 0) {
|
||||
printf("crypt_load() failed on device %s.\n", crypt_get_device_name(cd));
|
||||
crypt_free(cd);
|
||||
return r;
|
||||
}
|
||||
EX_SUCCESS("Encrypted device is active on " DMDIR EX_DEV_NAME ".");
|
||||
printf("\tThe cipher used in device context: '%s'\n", crypt_get_cipher(cd) ?: "(not set) !");
|
||||
printf("\tThe cipher mode used in device context: '%s'\n", crypt_get_cipher_mode(cd) ?: "(not set) !");
|
||||
printf("\tThe device UUID '%s'\n", crypt_get_uuid(cd) ?: "(not set) !");
|
||||
EX_DELIM;
|
||||
|
||||
/*
|
||||
* __STEP_06__
|
||||
*
|
||||
* Device activation creates device-mapper devie mapping with name device_name.
|
||||
*/
|
||||
r = crypt_activate_by_passphrase(cd, /* crypt context */
|
||||
device_name, /* device name to activate */
|
||||
CRYPT_ANY_SLOT,/* which slot use (ANY - try all) */
|
||||
"foo", 3, /* passphrase */
|
||||
CRYPT_ACTIVATE_READONLY); /* flags */
|
||||
if (r < 0) {
|
||||
printf("Device %s activation failed.\n", device_name);
|
||||
crypt_free(cd);
|
||||
return r;
|
||||
}
|
||||
|
||||
printf("LUKS device %s/%s is active.\n", crypt_get_dir(), device_name);
|
||||
printf("\tcipher used: %s\n", crypt_get_cipher(cd));
|
||||
printf("\tcipher mode: %s\n", crypt_get_cipher_mode(cd));
|
||||
printf("\tdevice UUID: %s\n", crypt_get_uuid(cd));
|
||||
|
||||
/*
|
||||
* Get info about active device (query DM backend)
|
||||
*/
|
||||
EX_PRESS_ENTER("Going to get active active device parameters.");
|
||||
EX_STEP(++step, "crypt_get_active_device()");
|
||||
if ((r = crypt_get_active_device(cd, EX_DEV_NAME, &cad))) {
|
||||
EX_FAIL("Get info about active device '%s' failed!", EX_DEV_NAME);
|
||||
goto out;
|
||||
r = crypt_get_active_device(cd, device_name, &cad);
|
||||
if (r < 0) {
|
||||
printf("Get info about active device %s failed.\n", device_name);
|
||||
crypt_deactivate(cd, device_name);
|
||||
crypt_free(cd);
|
||||
return r;
|
||||
}
|
||||
EX_SUCCESS("Active device parameters for " EX_DEV_NAME ":\n"
|
||||
"\tPayload offset (in sectors): %" PRIu64 "\n"
|
||||
"\tEncrypted payload area size in sectors: %" PRIu64 " and bytes: %" PRIu64 "\n"
|
||||
"\tThe device has a read-only flag %sset",
|
||||
cad.offset, cad.size, cad.size * SECTOR_SIZE,
|
||||
cad.flags & CRYPT_ACTIVATE_READONLY ? "" : "not ");
|
||||
EX_DELIM;
|
||||
|
||||
printf("Active device parameters for %s:\n"
|
||||
"\tDevice offset (in sectors): %" PRIu64 "\n"
|
||||
"\tIV offset (in sectors) : %" PRIu64 "\n"
|
||||
"\tdevice size (in sectors) : %" PRIu64 "\n"
|
||||
"\tread-only flag : %s\n",
|
||||
device_name, cad.offset, cad.iv_offset, cad.size,
|
||||
cad.flags & CRYPT_ACTIVATE_READONLY ? "1" : "0");
|
||||
|
||||
crypt_free(cd);
|
||||
cd = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_active_device(const char *device_name)
|
||||
{
|
||||
struct crypt_device *cd;
|
||||
int r;
|
||||
|
||||
/*
|
||||
* __STEP_07__
|
||||
*
|
||||
* crypt_init_by_name() initializes device context and loads LUKS header from backing device
|
||||
*/
|
||||
EX_PRESS_ENTER("The context used in previous examples is going to be freed to demonstrate "
|
||||
"how to initialize a device context from the active device.");
|
||||
EX_STEP(++step, "crypt_init_by_name()");
|
||||
if ((r = crypt_init_by_name(&cd, EX_DEV_NAME))) {
|
||||
EX_FAIL("crypt_init_by_name() failed for the device name: " EX_DEV_NAME);
|
||||
goto out;
|
||||
r = crypt_init_by_name(&cd, device_name);
|
||||
if (r < 0) {
|
||||
printf("crypt_init_by_name() failed for %s.\n", device_name);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (crypt_status(cd, device_name) == CRYPT_ACTIVE)
|
||||
printf("Device %s is still active.\n", device_name);
|
||||
else {
|
||||
printf("Something failed perhaps, device %s is not active.\n", device_name);
|
||||
crypt_free(cd);
|
||||
return -1;
|
||||
}
|
||||
EX_SUCCESS("A new context has been initialized, LUKS header has been restored"
|
||||
"\n\tDevice UUID is '%s'", crypt_get_uuid(cd));
|
||||
|
||||
/*
|
||||
* __STEP_08__
|
||||
*
|
||||
* crypt_deactivate() is used to remove the volume_key from kernel mem. space and to remove the
|
||||
* device nod associated with decrypted backing device.
|
||||
*
|
||||
* crypt_deactivate() is used to deactivate device
|
||||
*/
|
||||
EX_PRESS_ENTER("\n\tGoing to deactivate the crypt device. Note that the device "
|
||||
"won't be deactivated while it's opened with O_EXCL flag (e.g. mounted).");
|
||||
EX_STEP(++step, "crypt_deactivate()");
|
||||
//printf("\nPress <ENTER> to continue to device deactivation of the test device.\n"
|
||||
// "Note that mounted device won't be deactivated. First unmount the device!");
|
||||
//getc(stdin);
|
||||
while ((r = crypt_deactivate(cd, EX_DEV_NAME))) {
|
||||
EX_FAIL("crypt_deactivate() failed. Most propably the device is still busy!");
|
||||
EX_PRESS_ENTER("Going to retry device deactivation");
|
||||
}
|
||||
EX_SUCCESS("crypt_deactivate() successful. Device " DMDIR EX_DEV_NAME " is now deactivated");
|
||||
|
||||
out:
|
||||
if (crypt_status(cd, EX_DEV_NAME) == CRYPT_ACTIVE)
|
||||
crypt_deactivate(cd, EX_DEV_NAME);
|
||||
if (answer)
|
||||
free(answer);
|
||||
/* always free context which is no longer used */
|
||||
if (cd)
|
||||
r = crypt_deactivate(cd, device_name);
|
||||
if (r < 0) {
|
||||
printf("crypt_deactivate() failed.\n");
|
||||
crypt_free(cd);
|
||||
return r;
|
||||
}
|
||||
|
||||
return r;
|
||||
printf("Device %s is now deactivated.\n", device_name);
|
||||
|
||||
crypt_free(cd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (geteuid()) {
|
||||
printf("Using of libcryptsetup requires super user privileges.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc != 2) {
|
||||
printf("usage: ./crypt_luks_usage <path>\n"
|
||||
"<path> refers to either a regular file or a block device.\n"
|
||||
" WARNING: the file or device will be wiped.\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (format_and_add_keyslots(argv[1]))
|
||||
return 3;
|
||||
|
||||
if (activate_and_check_status(argv[1], "example_device"))
|
||||
return 4;
|
||||
|
||||
if (handle_active_device("example_device"))
|
||||
return 5;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user