cryptsetup  2.3.5
About: cryptsetup is a utility used to conveniently setup disk encryption based on the dm-crypt kernel module. These include plain dm-crypt volumes, LUKS volumes, loop-AES and TrueCrypt compatible format.
  Fossies Dox: cryptsetup-2.3.5.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

Cryptsetup API

The documentation covers public parts of cryptsetup API. In the following sections you'll find the examples that describe some features of cryptsetup API. For more info about libcryptsetup API versions see API Tracker.

  1. Cryptsetup API examples
    1. crypt_luks_usage - cryptsetup LUKS device type usage examples
    2. crypt_log_usage - cryptsetup logging API examples

Cryptsetup API examples

crypt_luks_usage - cryptsetup LUKS device type usage

crypt_init()

Every time you need to do something with cryptsetup or dmcrypt device you need a valid context. The first step to start your work is crypt_init call. You can call it either with path to the block device or path to the regular file. If you don't supply the path, empty context is initialized.

crypt_format() - header and payload on mutual device

This section covers basic use cases for formatting LUKS devices. Format operation sets device type in context and in case of LUKS header is written at the beginning of block device. In the example below we use the scenario where LUKS header and data are both stored on the same device. There's also a possibility to store header and data separately.

Bear in mind that crypt_format() is destructive operation and it overwrites part of the backing block device.

Keyslot operations examples

After successful crypt_format of LUKS device, volume key is not stored in a persistent way on the device. Keyslot area is an array beyond LUKS header, where volume key is stored in the encrypted form using user input passphrase. For more info about LUKS keyslots and how it's actually protected, please look at LUKS specification. There are two basic methods to create a new keyslot:

crypt_keyslot_add_by_volume_key()

Creates a new keyslot directly by encrypting volume_key stored in the device context. Passphrase should be supplied or user is prompted if passphrase param is NULL.

crypt_keyslot_add_by_passphrase()

Creates a new keyslot for the volume key by opening existing active keyslot, extracting volume key from it and storing it into a new keyslot protected by a new passphrase

crypt_load()

Function loads header from backing block device into device context.

crypt_activate_by_passphrase()

Activates crypt device by user supplied password for keyslot containing the volume_key. If keyslot parameter is set to CRYPT_ANY_SLOT then all active keyslots are tried one by one until the volume key is found.

crypt_get_active_device()

This call returns structure containing runtime attributes of active device.

crypt_init_by_name()

In case you need to do operations with active device (device which already has its corresponding mapping) and you miss valid device context stored in *crypt_device reference, you should use this call. Function tries to get path to backing device from DM, initializes context for it and loads LUKS header.

crypt_deactivate()

Deactivates crypt device (removes DM mapping and safely erases volume key from kernel).

crypt_luks_usage.c - Complex example

To compile and run use following commands in examples directory:

make
./crypt_luks_usage _path_to_[block_device]_file

Note that you need to have the cryptsetup library compiled.

/*
* libcryptsetup API - using LUKS device example
*
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <inttypes.h>
#include <sys/types.h>
#include <libcryptsetup.h>
static int format_and_add_keyslots(const char *path)
{
struct crypt_device *cd;
int r;
/*
* The crypt_init() call is used to initialize crypt_device context,
* The path parameter specifies a device path.
*
* For path, you can use either link to a file or block device.
* The loopback device will be detached automatically.
*/
r = crypt_init(&cd, path);
if (r < 0) {
printf("crypt_init() failed for %s.\n", path);
return r;
}
printf("Context is attached to block device %s.\n", crypt_get_device_name(cd));
/*
* So far, no data were written to the device.
*/
printf("Device %s will be formatted as a LUKS device after 5 seconds.\n"
"Press CTRL+C now if you want to cancel this operation.\n", path);
sleep(5);
/*
* NULLs for uuid and volume_key means that these attributes will be
* generated during crypt_format().
*/
r = crypt_format(cd, /* crypt context */
CRYPT_LUKS2, /* LUKS2 is a new LUKS format; use CRYPT_LUKS1 for LUKS1 */
"aes", /* used cipher */
"xts-plain64", /* used block mode and IV */
NULL, /* generate UUID */
NULL, /* generate volume key from RNG */
512 / 8, /* 512bit key - here AES-256 in XTS mode, size is in bytes */
NULL); /* default parameters */
if (r < 0) {
printf("crypt_format() failed on device %s\n", crypt_get_device_name(cd));
return r;
}
/*
* The device now contains a LUKS header, but there is no active keyslot.
*
* crypt_keyslot_add_* call stores the volume_key in the encrypted form into the keyslot.
*
* After format, the volume key is stored internally.
*/
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");
return r;
}
printf("The first keyslot is initialized.\n");
/*
* Add another keyslot, now authenticating with the first keyslot.
* It decrypts the volume key from the first keyslot and creates a new one with the specified passphrase.
*/
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");
return r;
}
printf("The second keyslot is initialized.\n");
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;
/*
* LUKS device activation example.
*/
r = crypt_init(&cd, path);
if (r < 0) {
printf("crypt_init() failed for %s.\n", path);
return r;
}
/*
* crypt_load() is used to load existing LUKS header from a block device
*/
r = crypt_load(cd, /* crypt context */
CRYPT_LUKS, /* requested type - here LUKS of any type */
NULL); /* additional parameters (not used) */
if (r < 0) {
printf("crypt_load() failed on device %s.\n", crypt_get_device_name(cd));
return r;
}
/*
* Device activation creates a device-mapper device with the specified name.
*/
r = crypt_activate_by_passphrase(cd, /* crypt context */
device_name, /* device name to activate */
CRYPT_ANY_SLOT,/* the keyslot use (try all here) */
"foo", 3, /* passphrase */
if (r < 0) {
printf("Device %s activation failed.\n", device_name);
return r;
}
printf("%s device %s/%s is active.\n", crypt_get_type(cd), 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 the active device.
*/
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);
return r;
}
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");
return 0;
}
static int handle_active_device(const char *device_name)
{
struct crypt_device *cd;
int r;
/*
* crypt_init_by_name() initializes context by an active device-mapper name
*/
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);
return -1;
}
/*
* crypt_deactivate() is used to deactivate a device
*/
r = crypt_deactivate(cd, device_name);
if (r < 0) {
printf("crypt_deactivate() failed.\n");
return r;
}
printf("Device %s is now deactivated.\n", device_name);
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;
}
int main(int argc, char *argv[])
Definition: crypt_dict.c:98
int crypt_format(struct crypt_device *cd, const char *type, const char *cipher, const char *cipher_mode, const char *uuid, const char *volume_key, size_t volume_key_size, void *params)
Definition: setup.c:2243
int crypt_load(struct crypt_device *cd, const char *requested_type, void *params)
Definition: setup.c:1004
int crypt_activate_by_passphrase(struct crypt_device *cd, const char *name, int keyslot, const char *passphrase, size_t passphrase_size, uint32_t flags)
Definition: setup.c:4197
int crypt_deactivate(struct crypt_device *cd, const char *name)
Definition: setup.c:4547
#define CRYPT_ACTIVATE_READONLY
int crypt_get_active_device(struct crypt_device *cd, const char *name, struct crypt_active_device *cad)
Definition: setup.c:4552
const char * crypt_get_uuid(struct crypt_device *cd)
Definition: setup.c:5030
crypt_status_info crypt_status(struct crypt_device *cd, const char *name)
Definition: setup.c:4766
const char * crypt_get_cipher(struct crypt_device *cd)
Definition: setup.c:4910
const char * crypt_get_cipher_mode(struct crypt_device *cd)
Definition: setup.c:4943
const char * crypt_get_device_name(struct crypt_device *cd)
Definition: setup.c:5050
@ CRYPT_ACTIVE
int crypt_init_by_name(struct crypt_device **cd, const char *name)
Definition: setup.c:1505
void crypt_free(struct crypt_device *cd)
Definition: setup.c:2995
int crypt_init(struct crypt_device **cd, const char *device)
Definition: setup.c:577
#define CRYPT_ANY_SLOT
int crypt_keyslot_add_by_passphrase(struct crypt_device *cd, int keyslot, const char *passphrase, size_t passphrase_size, const char *new_passphrase, size_t new_passphrase_size)
Definition: setup.c:3309
const char * crypt_get_dir(void)
Definition: setup.c:572
int crypt_keyslot_add_by_volume_key(struct crypt_device *cd, int keyslot, const char *volume_key, size_t volume_key_size, const char *passphrase, size_t passphrase_size)
Definition: setup.c:3615
#define CRYPT_LUKS
const char * crypt_get_type(struct crypt_device *cd)
Definition: setup.c:5384
#define CRYPT_LUKS2
Public cryptsetup API.

crypt_log_usage - cryptsetup logging API example

Example describes basic use case for cryptsetup logging. To compile and run use following commands in examples directory:

make
./crypt_log_usage

Note that you need to have the cryptsetup library compiled.

/*
* libcryptsetup API log example
*
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <sys/types.h>
#include <syslog.h>
#include <unistd.h>
#include <libcryptsetup.h>
/*
* This is an example of crypt_set_log_callback API callback.
*
*/
static void simple_syslog_wrapper(int level, const char *msg, void *usrptr)
{
const char *prefix = (const char *)usrptr;
int priority;
switch(level) {
case CRYPT_LOG_NORMAL: priority = LOG_NOTICE; break;
case CRYPT_LOG_ERROR: priority = LOG_ERR; break;
case CRYPT_LOG_VERBOSE: priority = LOG_INFO; break;
case CRYPT_LOG_DEBUG: priority = LOG_DEBUG; break;
default:
fprintf(stderr, "Unsupported log level requested!\n");
return;
}
if (prefix)
syslog(priority, "%s:%s", prefix, msg);
else
syslog(priority, "%s", msg);
}
int main(void)
{
struct crypt_device *cd;
char usrprefix[] = "cslog_example";
int r;
if (geteuid()) {
printf("Using of libcryptsetup requires super user privileges.\n");
return 1;
}
openlog("cryptsetup", LOG_CONS | LOG_PID, LOG_USER);
/* Initialize empty crypt device context */
r = crypt_init(&cd, NULL);
if (r < 0) {
printf("crypt_init() failed.\n");
return 2;
}
/* crypt_set_log_callback() - register a log callback for crypt context */
crypt_set_log_callback(cd, &simple_syslog_wrapper, (void *)usrprefix);
/* send messages ithrough the crypt_log() interface */
crypt_log(cd, CRYPT_LOG_NORMAL, "This is normal log message");
crypt_log(cd, CRYPT_LOG_ERROR, "This is error log message");
crypt_log(cd, CRYPT_LOG_VERBOSE, "This is verbose log message");
crypt_log(cd, CRYPT_LOG_DEBUG, "This is debug message");
/* release crypt context */
/* Initialize default (global) log callback */
crypt_set_log_callback(NULL, &simple_syslog_wrapper, NULL);
crypt_log(NULL, CRYPT_LOG_NORMAL, "This is normal log message");
crypt_log(NULL, CRYPT_LOG_ERROR, "This is error log message");
crypt_log(NULL, CRYPT_LOG_VERBOSE, "This is verbose log message");
crypt_log(NULL, CRYPT_LOG_DEBUG, "This is debug message");
closelog();
return 0;
}
#define CRYPT_LOG_ERROR
#define CRYPT_LOG_DEBUG
#define CRYPT_LOG_VERBOSE
#define CRYPT_LOG_NORMAL
void crypt_set_log_callback(struct crypt_device *cd, void(*log)(int level, const char *msg, void *usrptr), void *usrptr)
Definition: setup.c:550
void crypt_log(struct crypt_device *cd, int level, const char *msg)
Definition: setup.c:161