"Fossies" - the Fresh Open Source Software Archive

Member "cryptsetup-2.4.3/lib/luks1/keyencryption.c" (13 Jan 2022, 7817 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. For more information about "keyencryption.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * LUKS - Linux Unified Key Setup
    3  *
    4  * Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
    5  * Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
    6  * Copyright (C) 2012-2021 Milan Broz
    7  *
    8  * This program is free software; you can redistribute it and/or
    9  * modify it under the terms of the GNU General Public License
   10  * as published by the Free Software Foundation; either version 2
   11  * of the License, or (at your option) any later version.
   12  *
   13  * This program is distributed in the hope that it will be useful,
   14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16  * GNU General Public License for more details.
   17  *
   18  * You should have received a copy of the GNU General Public License
   19  * along with this program; if not, write to the Free Software
   20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   21  */
   22 
   23 #include <stdio.h>
   24 #include <string.h>
   25 #include <errno.h>
   26 #include <sys/stat.h>
   27 #include "luks.h"
   28 #include "af.h"
   29 #include "internal.h"
   30 
   31 static void _error_hint(struct crypt_device *ctx, const char *device,
   32             const char *cipher, const char *mode, size_t keyLength)
   33 {
   34     char *c, cipher_spec[MAX_CIPHER_LEN * 3];
   35 
   36     if (snprintf(cipher_spec, sizeof(cipher_spec), "%s-%s", cipher, mode) < 0)
   37         return;
   38 
   39     log_err(ctx, _("Failed to setup dm-crypt key mapping for device %s.\n"
   40             "Check that kernel supports %s cipher (check syslog for more info)."),
   41             device, cipher_spec);
   42 
   43     if (!strncmp(mode, "xts", 3) && (keyLength != 256 && keyLength != 512))
   44         log_err(ctx, _("Key size in XTS mode must be 256 or 512 bits."));
   45     else if (!(c = strchr(mode, '-')) || strlen(c) < 4)
   46         log_err(ctx, _("Cipher specification should be in [cipher]-[mode]-[iv] format."));
   47 }
   48 
   49 static int LUKS_endec_template(char *src, size_t srcLength,
   50                    const char *cipher, const char *cipher_mode,
   51                    struct volume_key *vk,
   52                    unsigned int sector,
   53                    ssize_t (*func)(int, size_t, size_t, void *, size_t),
   54                    int mode,
   55                    struct crypt_device *ctx)
   56 {
   57     char name[PATH_MAX], path[PATH_MAX];
   58     char cipher_spec[MAX_CIPHER_LEN * 3];
   59     struct crypt_dm_active_device dmd = {
   60         .flags = CRYPT_ACTIVATE_PRIVATE,
   61     };
   62     int r, devfd = -1, remove_dev = 0;
   63     size_t bsize, keyslot_alignment, alignment;
   64 
   65     log_dbg(ctx, "Using dmcrypt to access keyslot area.");
   66 
   67     bsize = device_block_size(ctx, crypt_metadata_device(ctx));
   68     alignment = device_alignment(crypt_metadata_device(ctx));
   69     if (!bsize || !alignment)
   70         return -EINVAL;
   71 
   72     if (bsize > LUKS_ALIGN_KEYSLOTS)
   73         keyslot_alignment = LUKS_ALIGN_KEYSLOTS;
   74     else
   75         keyslot_alignment = bsize;
   76     dmd.size = size_round_up(srcLength, keyslot_alignment) / SECTOR_SIZE;
   77 
   78     if (mode == O_RDONLY)
   79         dmd.flags |= CRYPT_ACTIVATE_READONLY;
   80 
   81     if (snprintf(name, sizeof(name), "temporary-cryptsetup-%d", getpid()) < 0)
   82         return -ENOMEM;
   83     if (snprintf(path, sizeof(path), "%s/%s", dm_get_dir(), name) < 0)
   84         return -ENOMEM;
   85     if (snprintf(cipher_spec, sizeof(cipher_spec), "%s-%s", cipher, cipher_mode) < 0)
   86         return -ENOMEM;
   87 
   88     r = device_block_adjust(ctx, crypt_metadata_device(ctx), DEV_OK,
   89                 sector, &dmd.size, &dmd.flags);
   90     if (r < 0) {
   91         log_err(ctx, _("Device %s does not exist or access denied."),
   92             device_path(crypt_metadata_device(ctx)));
   93         return -EIO;
   94     }
   95 
   96     if (mode != O_RDONLY && dmd.flags & CRYPT_ACTIVATE_READONLY) {
   97         log_err(ctx, _("Cannot write to device %s, permission denied."),
   98             device_path(crypt_metadata_device(ctx)));
   99         return -EACCES;
  100     }
  101 
  102     r = dm_crypt_target_set(&dmd.segment, 0, dmd.size,
  103             crypt_metadata_device(ctx), vk, cipher_spec, 0, sector,
  104             NULL, 0, SECTOR_SIZE);
  105     if (r)
  106         goto out;
  107 
  108     r = dm_create_device(ctx, name, "TEMP", &dmd);
  109     if (r < 0) {
  110         if (r != -EACCES && r != -ENOTSUP)
  111             _error_hint(ctx, device_path(crypt_metadata_device(ctx)),
  112                     cipher, cipher_mode, vk->keylength * 8);
  113         r = -EIO;
  114         goto out;
  115     }
  116     remove_dev = 1;
  117 
  118     devfd = open(path, mode | O_DIRECT | O_SYNC);
  119     if (devfd == -1) {
  120         log_err(ctx, _("Failed to open temporary keystore device."));
  121         r = -EIO;
  122         goto out;
  123     }
  124 
  125     r = func(devfd, bsize, alignment, src, srcLength);
  126     if (r < 0) {
  127         log_err(ctx, _("Failed to access temporary keystore device."));
  128         r = -EIO;
  129     } else
  130         r = 0;
  131  out:
  132     dm_targets_free(ctx, &dmd);
  133     if (devfd != -1)
  134         close(devfd);
  135     if (remove_dev)
  136         dm_remove_device(ctx, name, CRYPT_DEACTIVATE_FORCE);
  137     return r;
  138 }
  139 
  140 int LUKS_encrypt_to_storage(char *src, size_t srcLength,
  141                 const char *cipher,
  142                 const char *cipher_mode,
  143                 struct volume_key *vk,
  144                 unsigned int sector,
  145                 struct crypt_device *ctx)
  146 {
  147     struct device *device = crypt_metadata_device(ctx);
  148     struct crypt_storage *s;
  149     int devfd, r = 0;
  150 
  151     /* Only whole sector writes supported */
  152     if (MISALIGNED_512(srcLength))
  153         return -EINVAL;
  154 
  155     /* Encrypt buffer */
  156     r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength, false);
  157 
  158     if (r)
  159         log_dbg(ctx, "Userspace crypto wrapper cannot use %s-%s (%d).",
  160             cipher, cipher_mode, r);
  161 
  162     /* Fallback to old temporary dmcrypt device */
  163     if (r == -ENOTSUP || r == -ENOENT)
  164         return LUKS_endec_template(src, srcLength, cipher, cipher_mode,
  165                        vk, sector, write_blockwise, O_RDWR, ctx);
  166 
  167     if (r) {
  168         _error_hint(ctx, device_path(device), cipher, cipher_mode,
  169                 vk->keylength * 8);
  170         return r;
  171     }
  172 
  173     log_dbg(ctx, "Using userspace crypto wrapper to access keyslot area.");
  174 
  175     r = crypt_storage_encrypt(s, 0, srcLength, src);
  176     crypt_storage_destroy(s);
  177 
  178     if (r)
  179         return r;
  180 
  181     r = -EIO;
  182 
  183     /* Write buffer to device */
  184     if (device_is_locked(device))
  185         devfd = device_open_locked(ctx, device, O_RDWR);
  186     else
  187         devfd = device_open(ctx, device, O_RDWR);
  188     if (devfd < 0)
  189         goto out;
  190 
  191     if (write_lseek_blockwise(devfd, device_block_size(ctx, device),
  192                   device_alignment(device), src, srcLength,
  193                   sector * SECTOR_SIZE) < 0)
  194         goto out;
  195 
  196     r = 0;
  197 out:
  198     device_sync(ctx, device);
  199     if (r)
  200         log_err(ctx, _("IO error while encrypting keyslot."));
  201 
  202     return r;
  203 }
  204 
  205 int LUKS_decrypt_from_storage(char *dst, size_t dstLength,
  206                   const char *cipher,
  207                   const char *cipher_mode,
  208                   struct volume_key *vk,
  209                   unsigned int sector,
  210                   struct crypt_device *ctx)
  211 {
  212     struct device *device = crypt_metadata_device(ctx);
  213     struct crypt_storage *s;
  214     struct stat st;
  215     int devfd, r = 0;
  216 
  217     /* Only whole sector reads supported */
  218     if (MISALIGNED_512(dstLength))
  219         return -EINVAL;
  220 
  221     r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode, vk->key, vk->keylength, false);
  222 
  223     if (r)
  224         log_dbg(ctx, "Userspace crypto wrapper cannot use %s-%s (%d).",
  225             cipher, cipher_mode, r);
  226 
  227     /* Fallback to old temporary dmcrypt device */
  228     if (r == -ENOTSUP || r == -ENOENT)
  229         return LUKS_endec_template(dst, dstLength, cipher, cipher_mode,
  230                        vk, sector, read_blockwise, O_RDONLY, ctx);
  231 
  232     if (r) {
  233         _error_hint(ctx, device_path(device), cipher, cipher_mode,
  234                 vk->keylength * 8);
  235         return r;
  236     }
  237 
  238     log_dbg(ctx, "Using userspace crypto wrapper to access keyslot area.");
  239 
  240     /* Read buffer from device */
  241     if (device_is_locked(device))
  242         devfd = device_open_locked(ctx, device, O_RDONLY);
  243     else
  244         devfd = device_open(ctx, device, O_RDONLY);
  245     if (devfd < 0) {
  246         log_err(ctx, _("Cannot open device %s."), device_path(device));
  247         crypt_storage_destroy(s);
  248         return -EIO;
  249     }
  250 
  251     if (read_lseek_blockwise(devfd, device_block_size(ctx, device),
  252                  device_alignment(device), dst, dstLength,
  253                  sector * SECTOR_SIZE) < 0) {
  254         if (!fstat(devfd, &st) && (st.st_size < (off_t)dstLength))
  255             log_err(ctx, _("Device %s is too small."), device_path(device));
  256         else
  257             log_err(ctx, _("IO error while decrypting keyslot."));
  258 
  259         crypt_storage_destroy(s);
  260         return -EIO;
  261     }
  262 
  263     /* Decrypt buffer */
  264     r = crypt_storage_decrypt(s, 0, dstLength, dst);
  265     crypt_storage_destroy(s);
  266 
  267     return r;
  268 }