Merge branch 'upstream' into tizen
[platform/upstream/cryptsetup.git] / lib / luks2 / luks2_json_format.c
index 1416766..4456358 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * LUKS - Linux Unified Key Setup v2, LUKS2 header format code
  *
- * Copyright (C) 2015-2020 Red Hat, Inc. All rights reserved.
- * Copyright (C) 2015-2020 Milan Broz
+ * Copyright (C) 2015-2023 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2015-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
@@ -21,7 +21,6 @@
 
 #include "luks2_internal.h"
 #include <uuid/uuid.h>
-#include <assert.h>
 
 struct area {
        uint64_t offset;
@@ -30,7 +29,7 @@ struct area {
 
 static size_t get_area_size(size_t keylength)
 {
-       //FIXME: calculate this properly, for now it is AF_split_sectors
+       /* for now it is AF_split_sectors */
        return size_round_up(keylength * 4000, 4096);
 }
 
@@ -41,7 +40,7 @@ static size_t get_min_offset(struct luks2_hdr *hdr)
 
 static size_t get_max_offset(struct luks2_hdr *hdr)
 {
-       return LUKS2_hdr_and_areas_size(hdr->jobj);
+       return LUKS2_hdr_and_areas_size(hdr);
 }
 
 int LUKS2_find_area_max_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
@@ -177,8 +176,11 @@ int LUKS2_find_area_gap(struct crypt_device *cd, struct luks2_hdr *hdr,
 
        log_dbg(cd, "Found area %zu -> %zu", offset, length + offset);
 
-       *area_offset = offset;
-       *area_length = length;
+       if (area_offset)
+               *area_offset = offset;
+       if (area_length)
+               *area_length = length;
+
        return 0;
 }
 
@@ -216,7 +218,7 @@ int LUKS2_generate_hdr(
        struct json_object *jobj_segment, *jobj_integrity, *jobj_keyslots, *jobj_segments, *jobj_config;
        char cipher[128];
        uuid_t partitionUuid;
-       int digest;
+       int r, digest;
        uint64_t mdev_size;
 
        if (!metadata_size)
@@ -244,7 +246,8 @@ int LUKS2_generate_hdr(
                /* Decrease keyslots_size due to metadata device being too small */
                if (!device_size(crypt_metadata_device(cd), &mdev_size) &&
                    ((keyslots_size + get_min_offset(hdr)) > mdev_size) &&
-                   device_fallocate(crypt_metadata_device(cd), keyslots_size + get_min_offset(hdr)))
+                   device_fallocate(crypt_metadata_device(cd), keyslots_size + get_min_offset(hdr)) &&
+                   (get_min_offset(hdr) <= mdev_size))
                        keyslots_size = mdev_size - get_min_offset(hdr);
        }
 
@@ -289,9 +292,11 @@ int LUKS2_generate_hdr(
        uuid_unparse(partitionUuid, hdr->uuid);
 
        if (*cipherMode != '\0')
-               snprintf(cipher, sizeof(cipher), "%s-%s", cipherName, cipherMode);
+               r = snprintf(cipher, sizeof(cipher), "%s-%s", cipherName, cipherMode);
        else
-               snprintf(cipher, sizeof(cipher), "%s", cipherName);
+               r = snprintf(cipher, sizeof(cipher), "%s", cipherName);
+       if (r < 0 || (size_t)r >= sizeof(cipher))
+               return -EINVAL;
 
        hdr->jobj = json_object_new_object();
 
@@ -337,7 +342,7 @@ err:
 }
 
 int LUKS2_wipe_header_areas(struct crypt_device *cd,
-       struct luks2_hdr *hdr)
+       struct luks2_hdr *hdr, bool detached_header)
 {
        int r;
        uint64_t offset, length;
@@ -352,11 +357,15 @@ int LUKS2_wipe_header_areas(struct crypt_device *cd,
                return -EINVAL;
 
        /* On detached header wipe at least the first 4k */
-       if (length == 0) {
+       if (detached_header) {
                length = 4096;
                wipe_block = 4096;
        }
 
+       r = device_check_size(cd, crypt_metadata_device(cd), length, 1);
+       if (r)
+               return r;
+
        log_dbg(cd, "Wiping LUKS areas (0x%06" PRIx64 " - 0x%06" PRIx64") with zeroes.",
                offset, length + offset);
 
@@ -368,7 +377,7 @@ int LUKS2_wipe_header_areas(struct crypt_device *cd,
        /* Wipe keyslot area */
        wipe_block = 1024 * 1024;
        offset = get_min_offset(hdr);
-       length = LUKS2_keyslots_size(hdr->jobj);
+       length = LUKS2_keyslots_size(hdr);
 
        log_dbg(cd, "Wiping keyslots area (0x%06" PRIx64 " - 0x%06" PRIx64") with random data.",
                offset, length + offset);
@@ -377,10 +386,7 @@ int LUKS2_wipe_header_areas(struct crypt_device *cd,
                                 offset, length, wipe_block, NULL, NULL);
 }
 
-/* FIXME: what if user wanted to keep original keyslots size? */
-int LUKS2_set_keyslots_size(struct crypt_device *cd,
-               struct luks2_hdr *hdr,
-               uint64_t data_offset)
+int LUKS2_set_keyslots_size(struct luks2_hdr *hdr, uint64_t data_offset)
 {
        json_object *jobj_config;
        uint64_t keyslots_size;