Imported Upstream version 2.6.1
[platform/upstream/cryptsetup.git] / lib / luks1 / keymanage.c
index 180407e..fe49a00 100644 (file)
@@ -2,8 +2,8 @@
  * LUKS - Linux Unified Key Setup
  *
  * Copyright (C) 2004-2006 Clemens Fruhwirth <clemens@endorphin.org>
- * Copyright (C) 2009-2021 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2013-2021 Milan Broz
+ * Copyright (C) 2009-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2013-2023 Milan Broz
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <netinet/in.h>
 #include <errno.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include <assert.h>
 #include <uuid/uuid.h>
+#include <limits.h>
 
 #include "luks.h"
 #include "af.h"
@@ -66,6 +65,27 @@ static void LUKS_sort_keyslots(const struct luks_phdr *hdr, int *array)
        }
 }
 
+static int _is_not_lower(char *str, unsigned max_len)
+{
+       for(; *str && max_len; str++, max_len--)
+               if (isupper(*str))
+                       return 1;
+       return 0;
+}
+
+static int _to_lower(char *str, unsigned max_len)
+{
+       int r = 0;
+
+       for(; *str && max_len; str++, max_len--)
+               if (isupper(*str)) {
+                       *str = tolower(*str);
+                       r = 1;
+               }
+
+       return r;
+}
+
 size_t LUKS_device_sectors(const struct luks_phdr *hdr)
 {
        int sorted_areas[LUKS_NUMKEYS] = { 0, 1, 2, 3, 4, 5, 6, 7 };
@@ -212,11 +232,12 @@ int LUKS_hdr_backup(const char *backup_file, struct crypt_device *ctx)
        hdr_size = LUKS_device_sectors(&hdr) << SECTOR_SHIFT;
        buffer_size = size_round_up(hdr_size, crypt_getpagesize());
 
-       buffer = crypt_safe_alloc(buffer_size);
+       buffer = malloc(buffer_size);
        if (!buffer || hdr_size < LUKS_ALIGN_KEYSLOTS || hdr_size > buffer_size) {
                r = -ENOMEM;
                goto out;
        }
+       memset(buffer, 0, buffer_size);
 
        log_dbg(ctx, "Storing backup of header (%zu bytes) and keyslot area (%zu bytes).",
                sizeof(hdr), hdr_size - LUKS_ALIGN_KEYSLOTS);
@@ -260,7 +281,8 @@ int LUKS_hdr_backup(const char *backup_file, struct crypt_device *ctx)
        r = 0;
 out:
        crypt_safe_memzero(&hdr, sizeof(hdr));
-       crypt_safe_free(buffer);
+       crypt_safe_memzero(buffer, buffer_size);
+       free(buffer);
        return r;
 }
 
@@ -288,7 +310,7 @@ int LUKS_hdr_restore(
                goto out;
        }
 
-       buffer = crypt_safe_alloc(buffer_size);
+       buffer = malloc(buffer_size);
        if (!buffer) {
                r = -ENOMEM;
                goto out;
@@ -359,7 +381,8 @@ int LUKS_hdr_restore(
        r = LUKS_read_phdr(hdr, 1, 0, ctx);
 out:
        device_sync(ctx, device);
-       crypt_safe_free(buffer);
+       crypt_safe_memzero(buffer, buffer_size);
+       free(buffer);
        return r;
 }
 
@@ -379,13 +402,37 @@ static int _keyslot_repair(struct luks_phdr *phdr, struct crypt_device *ctx)
        /*
         * cryptsetup 1.0 did not align keyslots to 4k, cannot repair this one
         * Also we cannot trust possibly broken keyslots metadata here through LUKS_keyslots_offset().
-        * Expect first keyslot is aligned, if not, then manual repair is neccessary.
+        * Expect first keyslot is aligned, if not, then manual repair is necessary.
         */
        if (phdr->keyblock[0].keyMaterialOffset < (LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE)) {
                log_err(ctx, _("Non standard keyslots alignment, manual repair required."));
                return -EINVAL;
        }
 
+       /*
+        * ECB mode does not use IV but legacy dmcrypt silently allows it.
+        * Today device cannot be activated anyway, so we need to fix it here.
+        */
+       if (!strncmp(phdr->cipherMode, "ecb-", 4)) {
+               log_err(ctx, _("Cipher mode repaired (%s -> %s)."), phdr->cipherMode, "ecb");
+               memset(phdr->cipherMode, 0, LUKS_CIPHERMODE_L);
+               strcpy(phdr->cipherMode, "ecb");
+               need_write = 1;
+       }
+
+       /*
+        * Old cryptsetup expects "sha1", gcrypt allows case insensitive names,
+        * so always convert hash to lower case in header
+        */
+       if (_to_lower(phdr->hashSpec, LUKS_HASHSPEC_L)) {
+               log_err(ctx, _("Cipher hash repaired to lowercase (%s)."), phdr->hashSpec);
+               if (crypt_hmac_size(phdr->hashSpec) < LUKS_DIGESTSIZE) {
+                       log_err(ctx, _("Requested LUKS hash %s is not supported."), phdr->hashSpec);
+                       return -EINVAL;
+               }
+               need_write = 1;
+       }
+
        r = LUKS_check_cipher(ctx, phdr->keyBytes, phdr->cipherName, phdr->cipherMode);
        if (r < 0)
                return -EINVAL;
@@ -473,12 +520,13 @@ static int _check_and_convert_hdr(const char *device,
        unsigned int i;
        char luksMagic[] = LUKS_MAGIC;
 
-       if(memcmp(hdr->magic, luksMagic, LUKS_MAGIC_L)) { /* Check magic */
+       hdr->version = be16_to_cpu(hdr->version);
+       if (memcmp(hdr->magic, luksMagic, LUKS_MAGIC_L)) { /* Check magic */
                log_dbg(ctx, "LUKS header not detected.");
                if (require_luks_device)
                        log_err(ctx, _("Device %s is not a valid LUKS device."), device);
                return -EINVAL;
-       } else if((hdr->version = ntohs(hdr->version)) != 1) {  /* Convert every uint16/32_t item from network byte order */
+       } else if (hdr->version != 1) {
                log_err(ctx, _("Unsupported LUKS version %d."), hdr->version);
                return -EINVAL;
        }
@@ -486,19 +534,19 @@ static int _check_and_convert_hdr(const char *device,
        hdr->hashSpec[LUKS_HASHSPEC_L - 1] = '\0';
        if (crypt_hmac_size(hdr->hashSpec) < LUKS_DIGESTSIZE) {
                log_err(ctx, _("Requested LUKS hash %s is not supported."), hdr->hashSpec);
-               return -EINVAL;
+               r = -EINVAL;
        }
 
        /* Header detected */
-       hdr->payloadOffset      = ntohl(hdr->payloadOffset);
-       hdr->keyBytes           = ntohl(hdr->keyBytes);
-       hdr->mkDigestIterations = ntohl(hdr->mkDigestIterations);
-
-       for(i = 0; i < LUKS_NUMKEYS; ++i) {
-               hdr->keyblock[i].active             = ntohl(hdr->keyblock[i].active);
-               hdr->keyblock[i].passwordIterations = ntohl(hdr->keyblock[i].passwordIterations);
-               hdr->keyblock[i].keyMaterialOffset  = ntohl(hdr->keyblock[i].keyMaterialOffset);
-               hdr->keyblock[i].stripes            = ntohl(hdr->keyblock[i].stripes);
+       hdr->payloadOffset      = be32_to_cpu(hdr->payloadOffset);
+       hdr->keyBytes           = be32_to_cpu(hdr->keyBytes);
+       hdr->mkDigestIterations = be32_to_cpu(hdr->mkDigestIterations);
+
+       for (i = 0; i < LUKS_NUMKEYS; ++i) {
+               hdr->keyblock[i].active             = be32_to_cpu(hdr->keyblock[i].active);
+               hdr->keyblock[i].passwordIterations = be32_to_cpu(hdr->keyblock[i].passwordIterations);
+               hdr->keyblock[i].keyMaterialOffset  = be32_to_cpu(hdr->keyblock[i].keyMaterialOffset);
+               hdr->keyblock[i].stripes            = be32_to_cpu(hdr->keyblock[i].stripes);
        }
 
        if (LUKS_check_keyslots(ctx, hdr))
@@ -510,6 +558,16 @@ static int _check_and_convert_hdr(const char *device,
        hdr->uuid[UUID_STRING_L - 1] = '\0';
 
        if (repair) {
+               if (!strncmp(hdr->cipherMode, "ecb-", 4)) {
+                       log_err(ctx, _("LUKS cipher mode %s is invalid."), hdr->cipherMode);
+                       r = -EINVAL;
+               }
+
+               if (_is_not_lower(hdr->hashSpec, LUKS_HASHSPEC_L)) {
+                       log_err(ctx, _("LUKS hash %s is invalid."), hdr->hashSpec);
+                       r = -EINVAL;
+               }
+
                if (r == -EINVAL)
                        r = _keyslot_repair(hdr, ctx);
                else
@@ -519,27 +577,6 @@ static int _check_and_convert_hdr(const char *device,
        return r;
 }
 
-static void _to_lower(char *str, unsigned max_len)
-{
-       for(; *str && max_len; str++, max_len--)
-               if (isupper(*str))
-                       *str = tolower(*str);
-}
-
-static void LUKS_fix_header_compatible(struct luks_phdr *header)
-{
-       /* Old cryptsetup expects "sha1", gcrypt allows case insensitive names,
-        * so always convert hash to lower case in header */
-       _to_lower(header->hashSpec, LUKS_HASHSPEC_L);
-
-       /* ECB mode does not use IV but dmcrypt silently allows it.
-        * Drop any IV here if ECB is used (that is not secure anyway).*/
-       if (!strncmp(header->cipherMode, "ecb-", 4)) {
-               memset(header->cipherMode, 0, LUKS_CIPHERMODE_L);
-               strcpy(header->cipherMode, "ecb");
-       }
-}
-
 int LUKS_read_phdr_backup(const char *backup_file,
                          struct luks_phdr *hdr,
                          int require_luks_device,
@@ -559,11 +596,9 @@ int LUKS_read_phdr_backup(const char *backup_file,
 
        if (read_buffer(devfd, hdr, hdr_size) < hdr_size)
                r = -EIO;
-       else {
-               LUKS_fix_header_compatible(hdr);
+       else
                r = _check_and_convert_hdr(backup_file, hdr,
                                           require_luks_device, 0, ctx);
-       }
 
        close(devfd);
        return r;
@@ -650,15 +685,15 @@ int LUKS_write_phdr(struct luks_phdr *hdr,
        memset(&convHdr._padding, 0, sizeof(convHdr._padding));
 
        /* Convert every uint16/32_t item to network byte order */
-       convHdr.version            = htons(hdr->version);
-       convHdr.payloadOffset      = htonl(hdr->payloadOffset);
-       convHdr.keyBytes           = htonl(hdr->keyBytes);
-       convHdr.mkDigestIterations = htonl(hdr->mkDigestIterations);
+       convHdr.version            = cpu_to_be16(hdr->version);
+       convHdr.payloadOffset      = cpu_to_be32(hdr->payloadOffset);
+       convHdr.keyBytes           = cpu_to_be32(hdr->keyBytes);
+       convHdr.mkDigestIterations = cpu_to_be32(hdr->mkDigestIterations);
        for(i = 0; i < LUKS_NUMKEYS; ++i) {
-               convHdr.keyblock[i].active             = htonl(hdr->keyblock[i].active);
-               convHdr.keyblock[i].passwordIterations = htonl(hdr->keyblock[i].passwordIterations);
-               convHdr.keyblock[i].keyMaterialOffset  = htonl(hdr->keyblock[i].keyMaterialOffset);
-               convHdr.keyblock[i].stripes            = htonl(hdr->keyblock[i].stripes);
+               convHdr.keyblock[i].active             = cpu_to_be32(hdr->keyblock[i].active);
+               convHdr.keyblock[i].passwordIterations = cpu_to_be32(hdr->keyblock[i].passwordIterations);
+               convHdr.keyblock[i].keyMaterialOffset  = cpu_to_be32(hdr->keyblock[i].keyMaterialOffset);
+               convHdr.keyblock[i].stripes            = cpu_to_be32(hdr->keyblock[i].stripes);
        }
 
        r = write_lseek_blockwise(devfd, device_block_size(ctx, device), device_alignment(device),
@@ -771,11 +806,10 @@ int LUKS_generate_phdr(struct luks_phdr *header,
        strncpy(header->cipherName,cipherName,LUKS_CIPHERNAME_L-1);
        strncpy(header->cipherMode,cipherMode,LUKS_CIPHERMODE_L-1);
        strncpy(header->hashSpec,hashSpec,LUKS_HASHSPEC_L-1);
+       _to_lower(header->hashSpec, LUKS_HASHSPEC_L);
 
        header->keyBytes=vk->keylength;
 
-       LUKS_fix_header_compatible(header);
-
        log_dbg(ctx, "Generating LUKS header version %d using hash %s, %s, %s, MK %d bytes",
                header->version, header->hashSpec ,header->cipherName, header->cipherMode,
                header->keyBytes);
@@ -786,7 +820,7 @@ int LUKS_generate_phdr(struct luks_phdr *header,
                return r;
        }
 
-       /* Compute master key digest */
+       /* Compute volume key digest */
        pbkdf = crypt_get_pbkdf(ctx);
        r = crypt_benchmark_pbkdf_internal(ctx, pbkdf, vk->keylength);
        if (r < 0)
@@ -800,7 +834,7 @@ int LUKS_generate_phdr(struct luks_phdr *header,
 
        if (PBKDF2_temp > (double)UINT32_MAX)
                return -EINVAL;
-       header->mkDigestIterations = at_least((uint32_t)PBKDF2_temp, LUKS_MKD_ITERATIONS_MIN);
+       header->mkDigestIterations = AT_LEAST((uint32_t)PBKDF2_temp, LUKS_MKD_ITERATIONS_MIN);
        assert(header->mkDigestIterations);
 
        r = crypt_pbkdf(CRYPT_KDF_PBKDF2, header->hashSpec, vk->key,vk->keylength,
@@ -874,7 +908,7 @@ int LUKS_set_key(unsigned int keyIndex,
         * Final iteration count is at least LUKS_SLOT_ITERATIONS_MIN
         */
        hdr->keyblock[keyIndex].passwordIterations =
-               at_least(pbkdf->iterations, LUKS_SLOT_ITERATIONS_MIN);
+               AT_LEAST(pbkdf->iterations, LUKS_SLOT_ITERATIONS_MIN);
        log_dbg(ctx, "Key slot %d use %" PRIu32 " password iterations.", keyIndex,
                hdr->keyblock[keyIndex].passwordIterations);
 
@@ -891,11 +925,15 @@ int LUKS_set_key(unsigned int keyIndex,
                        hdr->keyblock[keyIndex].passwordSalt, LUKS_SALTSIZE,
                        derived_key->key, hdr->keyBytes,
                        hdr->keyblock[keyIndex].passwordIterations, 0, 0);
-       if (r < 0)
+       if (r < 0) {
+               if ((crypt_backend_flags() & CRYPT_BACKEND_PBKDF2_INT) &&
+                    hdr->keyblock[keyIndex].passwordIterations > INT_MAX)
+                       log_err(ctx, _("PBKDF2 iteration value overflow."));
                goto out;
+       }
 
        /*
-        * AF splitting, the masterkey stored in vk->key is split to AfKey
+        * AF splitting, the volume key stored in vk->key is split to AfKey
         */
        assert(vk->keylength == hdr->keyBytes);
        AFEKSize = AF_split_sectors(vk->keylength, hdr->keyblock[keyIndex].stripes) * SECTOR_SIZE;
@@ -951,7 +989,7 @@ int LUKS_verify_volume_key(const struct luks_phdr *hdr,
                        hdr->mkDigestIterations, 0, 0) < 0)
                return -EINVAL;
 
-       if (memcmp(checkHashBuf, hdr->mkDigest, LUKS_DIGESTSIZE))
+       if (crypt_backend_memeq(checkHashBuf, hdr->mkDigest, LUKS_DIGESTSIZE))
                return -EPERM;
 
        return 0;
@@ -1013,7 +1051,7 @@ static int LUKS_open_key(unsigned int keyIndex,
        if (r < 0)
                goto out;
 
-       r = AF_merge(ctx, AfKey, (*vk)->key, (*vk)->keylength, hdr->keyblock[keyIndex].stripes, hdr->hashSpec);
+       r = AF_merge(AfKey, (*vk)->key, (*vk)->keylength, hdr->keyblock[keyIndex].stripes, hdr->hashSpec);
        if (r < 0)
                goto out;
 
@@ -1196,6 +1234,10 @@ int LUKS_wipe_header_areas(struct luks_phdr *hdr,
        uint64_t offset, length;
        size_t wipe_block;
 
+       r = LUKS_check_device_size(ctx, hdr, 1);
+       if (r)
+               return r;
+
        /* Wipe complete header, keyslots and padding areas with zeroes. */
        offset = 0;
        length = (uint64_t)hdr->payloadOffset * SECTOR_SIZE;