"Fossies" - the Fresh Open Source Software Archive

Member "cryptsetup-2.4.3/docs/examples/crypt_luks_usage.c" (13 Jan 2022, 7001 Bytes) of package /linux/misc/cryptsetup-2.4.3.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2  *  libcryptsetup API - using LUKS device example
    3  *
    4  * Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
    5  *
    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.
   10  *
   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.
   15  *
   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.
   19  */
   20 
   21 #include <stdio.h>
   22 #include <stdlib.h>
   23 #include <string.h>
   24 #include <unistd.h>
   25 #include <inttypes.h>
   26 #include <sys/types.h>
   27 #include <libcryptsetup.h>
   28 
   29 static int format_and_add_keyslots(const char *path)
   30 {
   31     struct crypt_device *cd;
   32     int r;
   33 
   34     /*
   35      * The crypt_init() call is used  to initialize crypt_device context,
   36      * The path parameter specifies a device path.
   37      *
   38      * For path, you can use either link to a file or block device.
   39      * The loopback device will be detached automatically.
   40      */
   41 
   42     r = crypt_init(&cd, path);
   43     if (r < 0) {
   44         printf("crypt_init() failed for %s.\n", path);
   45         return r;
   46     }
   47 
   48     printf("Context is attached to block device %s.\n", crypt_get_device_name(cd));
   49 
   50     /*
   51      * So far, no data were written to the device.
   52      */
   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);
   55     sleep(5);
   56 
   57     /*
   58      * NULLs for uuid and volume_key means that these attributes will be
   59      * generated during crypt_format().
   60      */
   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 */
   69 
   70     if (r < 0) {
   71         printf("crypt_format() failed on device %s\n", crypt_get_device_name(cd));
   72         crypt_free(cd);
   73         return r;
   74     }
   75 
   76     /*
   77      * The device now contains a LUKS header, but there is no active keyslot.
   78      *
   79      * crypt_keyslot_add_* call stores the volume_key in the encrypted form into the keyslot.
   80      *
   81      * After format, the volume key is stored internally.
   82      */
   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 */
   89 
   90     if (r < 0) {
   91         printf("Adding keyslot failed.\n");
   92         crypt_free(cd);
   93         return r;
   94     }
   95 
   96     printf("The first keyslot is initialized.\n");
   97 
   98     /*
   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.
  101      */
  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 */
  106     if (r < 0) {
  107         printf("Adding keyslot failed.\n");
  108         crypt_free(cd);
  109         return r;
  110     }
  111 
  112     printf("The second keyslot is initialized.\n");
  113 
  114     crypt_free(cd);
  115     return 0;
  116 }
  117 
  118 static int activate_and_check_status(const char *path, const char *device_name)
  119 {
  120     struct crypt_device *cd;
  121     struct crypt_active_device cad;
  122     int r;
  123 
  124     /*
  125      * LUKS device activation example.
  126      */
  127     r = crypt_init(&cd, path);
  128     if (r < 0) {
  129         printf("crypt_init() failed for %s.\n", path);
  130         return r;
  131     }
  132 
  133     /*
  134      * crypt_load() is used to load existing LUKS header from a block device
  135      */
  136     r = crypt_load(cd,      /* crypt context */
  137                CRYPT_LUKS,  /* requested type - here LUKS of any type */
  138                NULL);       /* additional parameters (not used) */
  139 
  140     if (r < 0) {
  141         printf("crypt_load() failed on device %s.\n", crypt_get_device_name(cd));
  142         crypt_free(cd);
  143         return r;
  144     }
  145 
  146     /*
  147      * Device activation creates a device-mapper device with the specified name.
  148      */
  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 */
  154     if (r < 0) {
  155         printf("Device %s activation failed.\n", device_name);
  156         crypt_free(cd);
  157         return r;
  158     }
  159 
  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));
  164 
  165     /*
  166      * Get info about the active device.
  167      */
  168     r = crypt_get_active_device(cd, device_name, &cad);
  169     if (r < 0) {
  170         printf("Get info about active device %s failed.\n", device_name);
  171         crypt_deactivate(cd, device_name);
  172         crypt_free(cd);
  173         return r;
  174     }
  175 
  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");
  183 
  184     crypt_free(cd);
  185     return 0;
  186 }
  187 
  188 static int handle_active_device(const char *device_name)
  189 {
  190     struct crypt_device *cd;
  191     int r;
  192 
  193     /*
  194      * crypt_init_by_name() initializes context by an active device-mapper name
  195      */
  196     r = crypt_init_by_name(&cd, device_name);
  197     if (r < 0) {
  198         printf("crypt_init_by_name() failed for %s.\n", device_name);
  199         return r;
  200     }
  201 
  202     if (crypt_status(cd, device_name) == CRYPT_ACTIVE)
  203         printf("Device %s is still active.\n", device_name);
  204     else {
  205         printf("Something failed perhaps, device %s is not active.\n", device_name);
  206         crypt_free(cd);
  207         return -1;
  208     }
  209 
  210     /*
  211      * crypt_deactivate() is used to deactivate a device
  212      */
  213     r = crypt_deactivate(cd, device_name);
  214     if (r < 0) {
  215         printf("crypt_deactivate() failed.\n");
  216         crypt_free(cd);
  217         return r;
  218     }
  219 
  220     printf("Device %s is now deactivated.\n", device_name);
  221 
  222     crypt_free(cd);
  223     return 0;
  224 }
  225 
  226 int main(int argc, char **argv)
  227 {
  228     if (geteuid()) {
  229         printf("Using of libcryptsetup requires super user privileges.\n");
  230         return 1;
  231     }
  232 
  233     if (argc != 2) {
  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");
  237         return 2;
  238     }
  239 
  240     if (format_and_add_keyslots(argv[1]))
  241         return 3;
  242 
  243     if (activate_and_check_status(argv[1], "example_device"))
  244         return 4;
  245 
  246     if (handle_active_device("example_device"))
  247         return 5;
  248 
  249     return 0;
  250 }