Compare commits
10 Commits
56273f8a4d
...
54c4e85845
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54c4e85845 | ||
|
|
65bfc32da2 | ||
|
|
22958e39d4 | ||
|
|
6dad584d3d | ||
|
|
15ecf7d4ad | ||
|
|
fdc5d74f1a | ||
|
|
adbafcf2c7 | ||
|
|
b948251c4c | ||
|
|
1595978a35 | ||
|
|
da927ab5b8 |
@ -8,10 +8,10 @@ Subject: [PATCH 2/2] fix compat test
|
||||
1 file changed, 8 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/tests/compat-test b/tests/compat-test
|
||||
index a61453e..7ee946e 100755
|
||||
index a71b247..9e395b1 100755
|
||||
--- a/tests/compat-test
|
||||
+++ b/tests/compat-test
|
||||
@@ -22,6 +22,7 @@ PWD0="compatkey"
|
||||
@@ -23,6 +23,7 @@ PWD0="compatkey"
|
||||
PWD1="93R4P4pIqAH8"
|
||||
PWD2="mymJeD8ivEhE"
|
||||
PWD3="ocMakf3fAcQO"
|
||||
@ -19,7 +19,7 @@ index a61453e..7ee946e 100755
|
||||
PWDW="rUkL4RUryBom"
|
||||
VK_FILE="compattest_vkfile"
|
||||
|
||||
@@ -225,17 +226,17 @@ echo $PWD1 | $CRYPTSETUP luksAddKey $IMG $FAST_PBKDF_OPT 2>/dev/null && fail
|
||||
@@ -239,17 +240,17 @@ echo $PWD1 | $CRYPTSETUP luksAddKey $IMG $FAST_PBKDF_OPT 2>/dev/null && fail
|
||||
echo -e "$PWD1\n$PWD2" | $CRYPTSETUP luksAddKey $IMG $FAST_PBKDF_OPT || fail
|
||||
echo -e "$PWD0\n$PWD1" | $CRYPTSETUP luksAddKey $IMG $FAST_PBKDF_OPT 2>/dev/null && fail
|
||||
echo "[4] change key"
|
||||
@ -41,26 +41,29 @@ index a61453e..7ee946e 100755
|
||||
[ $? -ne 1 ] && fail "luksOpen should return ENOENT exit code"
|
||||
echo $PWD2 | $CRYPTSETUP luksOpen $IMG --test-passphrase 2>/dev/null && fail
|
||||
[ $? -ne 1 ] && fail "luksOpen should return ENOENT exit code"
|
||||
@@ -867,16 +868,16 @@ expect timeout abort "Are you sure? (Type 'yes' in capital letters):"
|
||||
send "YES\n"
|
||||
@@ -866,11 +867,11 @@ set timeout $EXPECT_TIMEOUT
|
||||
eval spawn $CRYPTSETUP_RAW luksOpen -v -T 2 $LOOPDEV $DEV_NAME
|
||||
expect timeout abort "Enter passphrase for $EXPECT_DEV:"
|
||||
sleep 0.1
|
||||
-send "$PWD0\n"
|
||||
+send "$PWD4\n"
|
||||
expect timeout abort "Verify passphrase:"
|
||||
sleep 0.1
|
||||
-send "$PWD0\n"
|
||||
+send "$PWD4\n"
|
||||
expect timeout abort "Command successful."
|
||||
expect timeout abort eof
|
||||
eval spawn $CRYPTSETUP luksOpen -v $LOOPDEV --test-passphrase
|
||||
-send "$PWD0 x\n"
|
||||
+send "$PWD4 x\n"
|
||||
expect timeout abort "No key available with this passphrase."
|
||||
expect timeout abort "Enter passphrase for $EXPECT_DEV:"
|
||||
sleep 0.1
|
||||
-send "$PWD0\n"
|
||||
+send "$PWD4\n"
|
||||
expect timeout abort "Command successful."
|
||||
-send "$PWD0 y\n"
|
||||
+send "$PWD4 y\n"
|
||||
expect timeout abort "No key available with this passphrase."
|
||||
expect timeout abort eof
|
||||
exit
|
||||
@@ -886,7 +887,7 @@ expect timeout abort "Are you sure? (Type 'yes' in capital letters):"
|
||||
send "YES\n"
|
||||
expect timeout abort "Enter any remaining passphrase:"
|
||||
sleep 0.1
|
||||
-send "$PWD0\n"
|
||||
+send "$PWD4\n"
|
||||
expect timeout abort "Command successful."
|
||||
expect timeout abort eof
|
||||
eval spawn $CRYPTSETUP_RAW luksKillSlot -v $LOOPDEV 0
|
||||
--
|
||||
1.8.3.1
|
||||
2.30.0
|
||||
|
||||
|
||||
@ -1,61 +0,0 @@
|
||||
From e8e71e43c3ff2dca951d30af48708bcb411e47d2 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Stoeckmann <tobias@stoeckmann.org>
|
||||
Date: Mon, 24 Aug 2020 19:21:43 +0200
|
||||
Subject: [PATCH 3/5] Check segment gaps regardless of heap space.
|
||||
|
||||
Segments are validated in hdr_validate_segments. Gaps in segment keys
|
||||
are detected when collecting offsets. But if an invalid segment is very
|
||||
large, larger than count, it could happen that cryptsetup is unable to
|
||||
allocate enough memory, not giving a clue about what actually is the
|
||||
problem.
|
||||
|
||||
Therefore check for gaps even if not enough memory is available. This
|
||||
gives much more information with debug output enabled.
|
||||
|
||||
Obviously cryptsetup still fails if segments are perfectly fine but not
|
||||
enough RAM available. But at that stage, the user knows that it's the
|
||||
fault of the system, not of an invalid segment.
|
||||
---
|
||||
lib/luks2/luks2_json_metadata.c | 19 ++++++++++++-------
|
||||
1 file changed, 12 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c
|
||||
index e346067..e4e1424 100644
|
||||
--- a/lib/luks2/luks2_json_metadata.c
|
||||
+++ b/lib/luks2/luks2_json_metadata.c
|
||||
@@ -679,11 +679,10 @@ static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
|
||||
if (first_backup < 0)
|
||||
first_backup = count;
|
||||
|
||||
- intervals = malloc(first_backup * sizeof(*intervals));
|
||||
- if (!intervals) {
|
||||
- log_dbg(cd, "Not enough memory.");
|
||||
- return 1;
|
||||
- }
|
||||
+ if (first_backup <= count && (size_t)first_backup < SIZE_MAX / sizeof(*intervals))
|
||||
+ intervals = malloc(first_backup * sizeof(*intervals));
|
||||
+ else
|
||||
+ intervals = NULL;
|
||||
|
||||
for (i = 0; i < first_backup; i++) {
|
||||
jobj = json_segments_get_segment(jobj_segments, i);
|
||||
@@ -692,8 +691,14 @@ static int hdr_validate_segments(struct crypt_device *cd, json_object *hdr_jobj)
|
||||
free(intervals);
|
||||
return 1;
|
||||
}
|
||||
- intervals[i].offset = json_segment_get_offset(jobj, 0);
|
||||
- intervals[i].length = json_segment_get_size(jobj, 0) ?: UINT64_MAX;
|
||||
+ if (intervals != NULL) {
|
||||
+ intervals[i].offset = json_segment_get_offset(jobj, 0);
|
||||
+ intervals[i].length = json_segment_get_size(jobj, 0) ?: UINT64_MAX;
|
||||
+ }
|
||||
+ }
|
||||
+ if (intervals == NULL) {
|
||||
+ log_dbg(cd, "Not enough memory.");
|
||||
+ return 1;
|
||||
}
|
||||
|
||||
r = !validate_segment_intervals(cd, first_backup, intervals);
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
1854
0003-add-test-case-for-sm4.patch
Normal file
1854
0003-add-test-case-for-sm4.patch
Normal file
File diff suppressed because it is too large
Load Diff
863
0004-Fix-CVE-2021-4122-LUKS2-reencryption-crash-recovery-.patch
Normal file
863
0004-Fix-CVE-2021-4122-LUKS2-reencryption-crash-recovery-.patch
Normal file
@ -0,0 +1,863 @@
|
||||
From 0113ac2d889c5322659ad0596d4cfc6da53e356c Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Kozina <okozina@redhat.com>
|
||||
Date: Sun, 2 Jan 2022 16:57:31 +0100
|
||||
Subject: [PATCH] Fix CVE-2021-4122 - LUKS2 reencryption crash recovery attack
|
||||
|
||||
Conflict:NA
|
||||
Reference:https://gitlab.com/cryptsetup/cryptsetup/-/commit/0113ac2d889c5322659ad0596d4cfc6da53e356c
|
||||
|
||||
Fix possible attacks against data confidentiality through LUKS2 online
|
||||
reencryption extension crash recovery.
|
||||
|
||||
An attacker can modify on-disk metadata to simulate decryption in
|
||||
progress with crashed (unfinished) reencryption step and persistently
|
||||
decrypt part of the LUKS device.
|
||||
|
||||
This attack requires repeated physical access to the LUKS device but
|
||||
no knowledge of user passphrases.
|
||||
|
||||
The decryption step is performed after a valid user activates
|
||||
the device with a correct passphrase and modified metadata.
|
||||
There are no visible warnings for the user that such recovery happened
|
||||
(except using the luksDump command). The attack can also be reversed
|
||||
afterward (simulating crashed encryption from a plaintext) with
|
||||
possible modification of revealed plaintext.
|
||||
|
||||
The problem was caused by reusing a mechanism designed for actual
|
||||
reencryption operation without reassessing the security impact for new
|
||||
encryption and decryption operations. While the reencryption requires
|
||||
calculating and verifying both key digests, no digest was needed to
|
||||
initiate decryption recovery if the destination is plaintext (no
|
||||
encryption key). Also, some metadata (like encryption cipher) is not
|
||||
protected, and an attacker could change it. Note that LUKS2 protects
|
||||
visible metadata only when a random change occurs. It does not protect
|
||||
against intentional modification but such modification must not cause
|
||||
a violation of data confidentiality.
|
||||
|
||||
The fix introduces additional digest protection of reencryption
|
||||
metadata. The digest is calculated from known keys and critical
|
||||
reencryption metadata. Now an attacker cannot create correct metadata
|
||||
digest without knowledge of a passphrase for used keyslots.
|
||||
For more details, see LUKS2 On-Disk Format Specification version 1.1.0.
|
||||
---
|
||||
lib/Makemodule.am | 1 +
|
||||
lib/luks2/luks2.h | 4 +
|
||||
lib/luks2/luks2_internal.h | 6 +
|
||||
lib/luks2/luks2_json_metadata.c | 73 +++++-
|
||||
lib/luks2/luks2_keyslot.c | 31 ++-
|
||||
lib/luks2/luks2_keyslot_reenc.c | 12 +-
|
||||
lib/luks2/luks2_reencrypt.c | 47 ++--
|
||||
lib/luks2/luks2_reencrypt_digest.c | 381 +++++++++++++++++++++++++++++
|
||||
lib/setup.c | 21 +-
|
||||
po/POTFILES.in | 1 +
|
||||
10 files changed, 533 insertions(+), 44 deletions(-)
|
||||
create mode 100644 lib/luks2/luks2_reencrypt_digest.c
|
||||
|
||||
diff --git a/lib/Makemodule.am b/lib/Makemodule.am
|
||||
index 5b12eae8..351dbbd3 100644
|
||||
--- a/lib/Makemodule.am
|
||||
+++ b/lib/Makemodule.am
|
||||
@@ -100,6 +100,7 @@ libcryptsetup_la_SOURCES = \
|
||||
lib/luks2/luks2_keyslot_luks2.c \
|
||||
lib/luks2/luks2_keyslot_reenc.c \
|
||||
lib/luks2/luks2_reencrypt.c \
|
||||
+ lib/luks2/luks2_reencrypt_digest.c \
|
||||
lib/luks2/luks2_segment.c \
|
||||
lib/luks2/luks2_token_keyring.c \
|
||||
lib/luks2/luks2_token.c \
|
||||
diff --git a/lib/luks2/luks2.h b/lib/luks2/luks2.h
|
||||
index fe99579d..2275cde6 100644
|
||||
--- a/lib/luks2/luks2.h
|
||||
+++ b/lib/luks2/luks2.h
|
||||
@@ -453,4 +453,8 @@ int LUKS2_reencrypt_check_device_size(struct crypt_device *cd,
|
||||
bool activation,
|
||||
bool dynamic);
|
||||
|
||||
+int LUKS2_reencrypt_digest_verify(struct crypt_device *cd,
|
||||
+ struct luks2_hdr *hdr,
|
||||
+ struct volume_key *vks);
|
||||
+
|
||||
#endif
|
||||
diff --git a/lib/luks2/luks2_internal.h b/lib/luks2/luks2_internal.h
|
||||
index ae6ddd51..740ba038 100644
|
||||
--- a/lib/luks2/luks2_internal.h
|
||||
+++ b/lib/luks2/luks2_internal.h
|
||||
@@ -239,9 +239,15 @@ int LUKS2_keyslot_reencrypt_create(struct crypt_device *cd,
|
||||
int keyslot,
|
||||
const struct crypt_params_reencrypt *params);
|
||||
|
||||
+int LUKS2_keyslot_reencrypt_digest_create(struct crypt_device *cd,
|
||||
+ struct luks2_hdr *hdr,
|
||||
+ struct volume_key *vks);
|
||||
+
|
||||
int LUKS2_keyslot_dump(struct crypt_device *cd,
|
||||
int keyslot);
|
||||
|
||||
+int LUKS2_keyslot_jobj_area(json_object *jobj_keyslot, uint64_t *offset, uint64_t *length);
|
||||
+
|
||||
/* JSON helpers */
|
||||
uint64_t json_segment_get_offset(json_object *jobj_segment, unsigned blockwise);
|
||||
const char *json_segment_type(json_object *jobj_segment);
|
||||
diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c
|
||||
index d527f54f..0c449ee5 100644
|
||||
--- a/lib/luks2/luks2_json_metadata.c
|
||||
+++ b/lib/luks2/luks2_json_metadata.c
|
||||
@@ -1389,24 +1389,63 @@ int LUKS2_config_set_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint3
|
||||
*/
|
||||
|
||||
/* LUKS2 library requirements */
|
||||
-static const struct {
|
||||
+struct requirement_flag {
|
||||
uint32_t flag;
|
||||
+ uint32_t version;
|
||||
const char *description;
|
||||
-} requirements_flags[] = {
|
||||
- { CRYPT_REQUIREMENT_OFFLINE_REENCRYPT, "offline-reencrypt" },
|
||||
- { CRYPT_REQUIREMENT_ONLINE_REENCRYPT, "online-reencrypt" },
|
||||
- { 0, NULL }
|
||||
};
|
||||
|
||||
-static uint32_t get_requirement_by_name(const char *requirement)
|
||||
+static const struct requirement_flag unknown_requirement_flag = { CRYPT_REQUIREMENT_UNKNOWN, 0, NULL };
|
||||
+
|
||||
+static const struct requirement_flag requirements_flags[] = {
|
||||
+ { CRYPT_REQUIREMENT_OFFLINE_REENCRYPT,1, "offline-reencrypt" },
|
||||
+ { CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 2, "online-reencrypt-v2" },
|
||||
+ { CRYPT_REQUIREMENT_ONLINE_REENCRYPT, 1, "online-reencrypt" },
|
||||
+ { 0, 0, NULL }
|
||||
+};
|
||||
+
|
||||
+static const struct requirement_flag *get_requirement_by_name(const char *requirement)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; requirements_flags[i].description; i++)
|
||||
if (!strcmp(requirement, requirements_flags[i].description))
|
||||
- return requirements_flags[i].flag;
|
||||
+ return requirements_flags + i;
|
||||
|
||||
- return CRYPT_REQUIREMENT_UNKNOWN;
|
||||
+ return &unknown_requirement_flag;
|
||||
+}
|
||||
+
|
||||
+static const struct requirement_flag *stored_requirement_name_by_id(struct crypt_device *cd, struct luks2_hdr *hdr, uint32_t req_id)
|
||||
+{
|
||||
+ json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
|
||||
+ int i, len;
|
||||
+ const struct requirement_flag *req;
|
||||
+
|
||||
+ assert(hdr);
|
||||
+ if (!hdr)
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (!json_object_object_get_ex(hdr->jobj, "config", &jobj_config))
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (!json_object_object_get_ex(jobj_config, "requirements", &jobj_requirements))
|
||||
+ return NULL;
|
||||
+
|
||||
+ if (!json_object_object_get_ex(jobj_requirements, "mandatory", &jobj_mandatory))
|
||||
+ return NULL;
|
||||
+
|
||||
+ len = (int) json_object_array_length(jobj_mandatory);
|
||||
+ if (len <= 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ for (i = 0; i < len; i++) {
|
||||
+ jobj = json_object_array_get_idx(jobj_mandatory, i);
|
||||
+ req = get_requirement_by_name(json_object_get_string(jobj));
|
||||
+ if (req->flag == req_id)
|
||||
+ return req;
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1416,7 +1455,7 @@ int LUKS2_config_get_requirements(struct crypt_device *cd, struct luks2_hdr *hdr
|
||||
{
|
||||
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
|
||||
int i, len;
|
||||
- uint32_t req;
|
||||
+ const struct requirement_flag *req;
|
||||
|
||||
assert(hdr);
|
||||
if (!hdr || !reqs)
|
||||
@@ -1443,8 +1482,8 @@ int LUKS2_config_get_requirements(struct crypt_device *cd, struct luks2_hdr *hdr
|
||||
jobj = json_object_array_get_idx(jobj_mandatory, i);
|
||||
req = get_requirement_by_name(json_object_get_string(jobj));
|
||||
log_dbg(cd, "%s - %sknown", json_object_get_string(jobj),
|
||||
- reqs_unknown(req) ? "un" : "");
|
||||
- *reqs |= req;
|
||||
+ reqs_unknown(req->flag) ? "un" : "");
|
||||
+ *reqs |= req->flag;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1454,6 +1493,8 @@ int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr
|
||||
{
|
||||
json_object *jobj_config, *jobj_requirements, *jobj_mandatory, *jobj;
|
||||
int i, r = -EINVAL;
|
||||
+ const struct requirement_flag *req;
|
||||
+ uint32_t req_id;
|
||||
|
||||
if (!hdr)
|
||||
return -EINVAL;
|
||||
@@ -1463,8 +1504,14 @@ int LUKS2_config_set_requirements(struct crypt_device *cd, struct luks2_hdr *hdr
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; requirements_flags[i].description; i++) {
|
||||
- if (reqs & requirements_flags[i].flag) {
|
||||
- jobj = json_object_new_string(requirements_flags[i].description);
|
||||
+ req_id = reqs & requirements_flags[i].flag;
|
||||
+ if (req_id) {
|
||||
+ /* retain already stored version of requirement flag */
|
||||
+ req = stored_requirement_name_by_id(cd, hdr, req_id);
|
||||
+ if (req)
|
||||
+ jobj = json_object_new_string(req->description);
|
||||
+ else
|
||||
+ jobj = json_object_new_string(requirements_flags[i].description);
|
||||
if (!jobj) {
|
||||
r = -ENOMEM;
|
||||
goto err;
|
||||
diff --git a/lib/luks2/luks2_keyslot.c b/lib/luks2/luks2_keyslot.c
|
||||
index 8534a850..3d701868 100644
|
||||
--- a/lib/luks2/luks2_keyslot.c
|
||||
+++ b/lib/luks2/luks2_keyslot.c
|
||||
@@ -288,19 +288,9 @@ crypt_keyslot_info LUKS2_keyslot_info(struct luks2_hdr *hdr, int keyslot)
|
||||
return CRYPT_SLOT_ACTIVE;
|
||||
}
|
||||
|
||||
-int LUKS2_keyslot_area(struct luks2_hdr *hdr,
|
||||
- int keyslot,
|
||||
- uint64_t *offset,
|
||||
- uint64_t *length)
|
||||
+int LUKS2_keyslot_jobj_area(json_object *jobj_keyslot, uint64_t *offset, uint64_t *length)
|
||||
{
|
||||
- json_object *jobj_keyslot, *jobj_area, *jobj;
|
||||
-
|
||||
- if(LUKS2_keyslot_info(hdr, keyslot) == CRYPT_SLOT_INVALID)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
|
||||
- if (!jobj_keyslot)
|
||||
- return -ENOENT;
|
||||
+ json_object *jobj_area, *jobj;
|
||||
|
||||
if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
|
||||
return -EINVAL;
|
||||
@@ -316,6 +306,23 @@ int LUKS2_keyslot_area(struct luks2_hdr *hdr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int LUKS2_keyslot_area(struct luks2_hdr *hdr,
|
||||
+ int keyslot,
|
||||
+ uint64_t *offset,
|
||||
+ uint64_t *length)
|
||||
+{
|
||||
+ json_object *jobj_keyslot;
|
||||
+
|
||||
+ if (LUKS2_keyslot_info(hdr, keyslot) == CRYPT_SLOT_INVALID)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot);
|
||||
+ if (!jobj_keyslot)
|
||||
+ return -ENOENT;
|
||||
+
|
||||
+ return LUKS2_keyslot_jobj_area(jobj_keyslot, offset, length);
|
||||
+}
|
||||
+
|
||||
static int _open_and_verify(struct crypt_device *cd,
|
||||
struct luks2_hdr *hdr,
|
||||
const keyslot_handler *h,
|
||||
diff --git a/lib/luks2/luks2_keyslot_reenc.c b/lib/luks2/luks2_keyslot_reenc.c
|
||||
index 34eefbf8..adec5734 100644
|
||||
--- a/lib/luks2/luks2_keyslot_reenc.c
|
||||
+++ b/lib/luks2/luks2_keyslot_reenc.c
|
||||
@@ -176,9 +176,17 @@ static int reenc_keyslot_store(struct crypt_device *cd,
|
||||
return r < 0 ? r : keyslot;
|
||||
}
|
||||
|
||||
-static int reenc_keyslot_wipe(struct crypt_device *cd __attribute__((unused)),
|
||||
- int keyslot __attribute__((unused)))
|
||||
+static int reenc_keyslot_wipe(struct crypt_device *cd,
|
||||
+ int keyslot)
|
||||
{
|
||||
+ struct luks2_hdr *hdr;
|
||||
+
|
||||
+ if (!(hdr = crypt_get_hdr(cd, CRYPT_LUKS2)))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* remove reencryption verification data */
|
||||
+ LUKS2_digest_assign(cd, hdr, keyslot, CRYPT_ANY_DIGEST, 0, 0);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/lib/luks2/luks2_reencrypt.c b/lib/luks2/luks2_reencrypt.c
|
||||
index d0e0dc40..f75ff825 100644
|
||||
--- a/lib/luks2/luks2_reencrypt.c
|
||||
+++ b/lib/luks2/luks2_reencrypt.c
|
||||
@@ -95,6 +95,7 @@ struct luks2_reencrypt {
|
||||
static int reencrypt_keyslot_update(struct crypt_device *cd,
|
||||
const struct luks2_reencrypt *rh)
|
||||
{
|
||||
+ int r;
|
||||
json_object *jobj_keyslot, *jobj_area, *jobj_area_type;
|
||||
struct luks2_hdr *hdr;
|
||||
|
||||
@@ -124,7 +125,11 @@ static int reencrypt_keyslot_update(struct crypt_device *cd,
|
||||
} else
|
||||
log_dbg(cd, "No update of reencrypt keyslot needed.");
|
||||
|
||||
- return 0;
|
||||
+ r = LUKS2_keyslot_reencrypt_digest_create(cd, hdr, rh->vks);
|
||||
+ if (r < 0)
|
||||
+ log_err(cd, "Failed to refresh reencryption verification digest.");
|
||||
+
|
||||
+ return r;
|
||||
}
|
||||
|
||||
static json_object *reencrypt_segment(struct luks2_hdr *hdr, unsigned new)
|
||||
@@ -2484,6 +2489,10 @@ static int reencrypt_init(struct crypt_device *cd,
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
+ r = LUKS2_keyslot_reencrypt_digest_create(cd, hdr, *vks);
|
||||
+ if (r < 0)
|
||||
+ goto out;
|
||||
+
|
||||
if (name && params->mode != CRYPT_REENCRYPT_ENCRYPT) {
|
||||
r = reencrypt_verify_and_upload_keys(cd, hdr, LUKS2_reencrypt_digest_old(hdr), LUKS2_reencrypt_digest_new(hdr), *vks);
|
||||
if (r)
|
||||
@@ -2614,20 +2623,28 @@ static int reencrypt_context_update(struct crypt_device *cd,
|
||||
static int reencrypt_load(struct crypt_device *cd, struct luks2_hdr *hdr,
|
||||
uint64_t device_size,
|
||||
const struct crypt_params_reencrypt *params,
|
||||
+ struct volume_key *vks,
|
||||
struct luks2_reencrypt **rh)
|
||||
{
|
||||
int r;
|
||||
struct luks2_reencrypt *tmp = NULL;
|
||||
crypt_reencrypt_info ri = LUKS2_reencrypt_status(hdr);
|
||||
|
||||
+ if (ri == CRYPT_REENCRYPT_NONE) {
|
||||
+ log_err(cd, _("Device not marked for LUKS2 reencryption."));
|
||||
+ return -EINVAL;
|
||||
+ } else if (ri == CRYPT_REENCRYPT_INVALID)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ r = LUKS2_reencrypt_digest_verify(cd, hdr, vks);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
if (ri == CRYPT_REENCRYPT_CLEAN)
|
||||
r = reencrypt_load_clean(cd, hdr, device_size, &tmp, params);
|
||||
else if (ri == CRYPT_REENCRYPT_CRASH)
|
||||
r = reencrypt_load_crashed(cd, hdr, device_size, &tmp);
|
||||
- else if (ri == CRYPT_REENCRYPT_NONE) {
|
||||
- log_err(cd, _("Device not marked for LUKS2 reencryption."));
|
||||
- return -EINVAL;
|
||||
- } else
|
||||
+ else
|
||||
r = -EINVAL;
|
||||
|
||||
if (r < 0 || !tmp) {
|
||||
@@ -2876,7 +2893,7 @@ static int reencrypt_load_by_passphrase(struct crypt_device *cd,
|
||||
rparams.device_size = required_size;
|
||||
}
|
||||
|
||||
- r = reencrypt_load(cd, hdr, device_size, &rparams, &rh);
|
||||
+ r = reencrypt_load(cd, hdr, device_size, &rparams, *vks, &rh);
|
||||
if (r < 0 || !rh)
|
||||
goto err;
|
||||
|
||||
@@ -3096,13 +3113,6 @@ static reenc_status_t reencrypt_step(struct crypt_device *cd,
|
||||
{
|
||||
int r;
|
||||
|
||||
- /* update reencrypt keyslot protection parameters in memory only */
|
||||
- r = reencrypt_keyslot_update(cd, rh);
|
||||
- if (r < 0) {
|
||||
- log_dbg(cd, "Keyslot update failed.");
|
||||
- return REENC_ERR;
|
||||
- }
|
||||
-
|
||||
/* in memory only */
|
||||
r = reencrypt_make_segments(cd, hdr, rh, device_size);
|
||||
if (r)
|
||||
@@ -3370,6 +3380,15 @@ int crypt_reencrypt_run(
|
||||
|
||||
rs = REENC_OK;
|
||||
|
||||
+ /* update reencrypt keyslot protection parameters in memory only */
|
||||
+ if (!quit && (rh->device_size > rh->progress)) {
|
||||
+ r = reencrypt_keyslot_update(cd, rh);
|
||||
+ if (r < 0) {
|
||||
+ log_dbg(cd, "Keyslot update failed.");
|
||||
+ return reencrypt_teardown(cd, hdr, rh, REENC_ERR, quit, progress, usrptr);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
while (!quit && (rh->device_size > rh->progress)) {
|
||||
rs = reencrypt_step(cd, hdr, rh, rh->device_size, rh->online);
|
||||
if (rs != REENC_OK)
|
||||
@@ -3409,7 +3428,7 @@ static int reencrypt_recovery(struct crypt_device *cd,
|
||||
int r;
|
||||
struct luks2_reencrypt *rh = NULL;
|
||||
|
||||
- r = reencrypt_load(cd, hdr, device_size, NULL, &rh);
|
||||
+ r = reencrypt_load(cd, hdr, device_size, NULL, vks, &rh);
|
||||
if (r < 0) {
|
||||
log_err(cd, _("Failed to load LUKS2 reencryption context."));
|
||||
return r;
|
||||
diff --git a/lib/luks2/luks2_reencrypt_digest.c b/lib/luks2/luks2_reencrypt_digest.c
|
||||
new file mode 100644
|
||||
index 00000000..7ee277cb
|
||||
--- /dev/null
|
||||
+++ b/lib/luks2/luks2_reencrypt_digest.c
|
||||
@@ -0,0 +1,381 @@
|
||||
+/*
|
||||
+ * LUKS - Linux Unified Key Setup v2, reencryption digest helpers
|
||||
+ *
|
||||
+ * Copyright (C) 2022, Red Hat, Inc. All rights reserved.
|
||||
+ * Copyright (C) 2022, Ondrej Kozina
|
||||
+ * Copyright (C) 2022, Milan Broz
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License
|
||||
+ * as published by the Free Software Foundation; either version 2
|
||||
+ * of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program 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 General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public License
|
||||
+ * along with this program; if not, write to the Free Software
|
||||
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
+ */
|
||||
+
|
||||
+#include "luks2_internal.h"
|
||||
+#include <assert.h>
|
||||
+
|
||||
+#define MAX_STR 64
|
||||
+
|
||||
+struct jtype {
|
||||
+ enum { JNONE = 0, JSTR, JU64, JX64, JU32 } type;
|
||||
+ json_object *jobj;
|
||||
+ const char *id;
|
||||
+};
|
||||
+
|
||||
+static size_t sr(struct jtype *j, uint8_t *ptr)
|
||||
+{
|
||||
+ json_object *jobj;
|
||||
+ size_t len = 0;
|
||||
+ uint64_t u64;
|
||||
+ uint32_t u32;
|
||||
+
|
||||
+ if (!json_object_is_type(j->jobj, json_type_object))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!json_object_object_get_ex(j->jobj, j->id, &jobj))
|
||||
+ return 0;
|
||||
+
|
||||
+ switch(j->type) {
|
||||
+ case JSTR: /* JSON string */
|
||||
+ if (!json_object_is_type(jobj, json_type_string))
|
||||
+ return 0;
|
||||
+ len = strlen(json_object_get_string(jobj));
|
||||
+ if (len > MAX_STR)
|
||||
+ return 0;
|
||||
+ if (ptr)
|
||||
+ memcpy(ptr, json_object_get_string(jobj), len);
|
||||
+ break;
|
||||
+ case JU64: /* Unsigned 64bit integer stored as string */
|
||||
+ if (!json_object_is_type(jobj, json_type_string))
|
||||
+ break;
|
||||
+ len = sizeof(u64);
|
||||
+ if (ptr) {
|
||||
+ u64 = cpu_to_be64(crypt_jobj_get_uint64(jobj));
|
||||
+ memcpy(ptr, &u64, len);
|
||||
+ }
|
||||
+ break;
|
||||
+ case JX64: /* Unsigned 64bit segment size (allows "dynamic") */
|
||||
+ if (!json_object_is_type(jobj, json_type_string))
|
||||
+ break;
|
||||
+ if (!strcmp(json_object_get_string(jobj), "dynamic")) {
|
||||
+ len = strlen("dynamic");
|
||||
+ if (ptr)
|
||||
+ memcpy(ptr, json_object_get_string(jobj), len);
|
||||
+ } else {
|
||||
+ len = sizeof(u64);
|
||||
+ u64 = cpu_to_be64(crypt_jobj_get_uint64(jobj));
|
||||
+ if (ptr)
|
||||
+ memcpy(ptr, &u64, len);
|
||||
+ }
|
||||
+ break;
|
||||
+ case JU32: /* Unsigned 32bit integer, stored as JSON int */
|
||||
+ if (!json_object_is_type(jobj, json_type_int))
|
||||
+ return 0;
|
||||
+ len = sizeof(u32);
|
||||
+ if (ptr) {
|
||||
+ u32 = cpu_to_be32(crypt_jobj_get_uint32(jobj));
|
||||
+ memcpy(ptr, &u32, len);
|
||||
+ }
|
||||
+ break;
|
||||
+ case JNONE:
|
||||
+ return 0;
|
||||
+ };
|
||||
+
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+static size_t srs(struct jtype j[], uint8_t *ptr)
|
||||
+{
|
||||
+ size_t l, len = 0;
|
||||
+
|
||||
+ while(j->jobj) {
|
||||
+ l = sr(j, ptr);
|
||||
+ if (!l)
|
||||
+ return 0;
|
||||
+ len += l;
|
||||
+ if (ptr)
|
||||
+ ptr += l;
|
||||
+ j++;
|
||||
+ }
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+static size_t segment_linear_serialize(json_object *jobj_segment, uint8_t *buffer)
|
||||
+{
|
||||
+ struct jtype j[] = {
|
||||
+ { JSTR, jobj_segment, "type" },
|
||||
+ { JU64, jobj_segment, "offset" },
|
||||
+ { JX64, jobj_segment, "size" },
|
||||
+ {}
|
||||
+ };
|
||||
+ return srs(j, buffer);
|
||||
+}
|
||||
+
|
||||
+static size_t segment_crypt_serialize(json_object *jobj_segment, uint8_t *buffer)
|
||||
+{
|
||||
+ struct jtype j[] = {
|
||||
+ { JSTR, jobj_segment, "type" },
|
||||
+ { JU64, jobj_segment, "offset" },
|
||||
+ { JX64, jobj_segment, "size" },
|
||||
+ { JU64, jobj_segment, "iv_tweak" },
|
||||
+ { JSTR, jobj_segment, "encryption" },
|
||||
+ { JU32, jobj_segment, "sector_size" },
|
||||
+ {}
|
||||
+ };
|
||||
+ return srs(j, buffer);
|
||||
+}
|
||||
+
|
||||
+static size_t segment_serialize(json_object *jobj_segment, uint8_t *buffer)
|
||||
+{
|
||||
+ json_object *jobj_type;
|
||||
+ const char *segment_type;
|
||||
+
|
||||
+ if (!json_object_object_get_ex(jobj_segment, "type", &jobj_type))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!(segment_type = json_object_get_string(jobj_type)))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!strcmp(segment_type, "crypt"))
|
||||
+ return segment_crypt_serialize(jobj_segment, buffer);
|
||||
+ else if (!strcmp(segment_type, "linear"))
|
||||
+ return segment_linear_serialize(jobj_segment, buffer);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static size_t backup_segments_serialize(struct luks2_hdr *hdr, uint8_t *buffer)
|
||||
+{
|
||||
+ json_object *jobj_segment;
|
||||
+ size_t l, len = 0;
|
||||
+
|
||||
+ jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-previous");
|
||||
+ if (!jobj_segment || !(l = segment_serialize(jobj_segment, buffer)))
|
||||
+ return 0;
|
||||
+ len += l;
|
||||
+ if (buffer)
|
||||
+ buffer += l;
|
||||
+
|
||||
+ jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-final");
|
||||
+ if (!jobj_segment || !(l = segment_serialize(jobj_segment, buffer)))
|
||||
+ return 0;
|
||||
+ len += l;
|
||||
+ if (buffer)
|
||||
+ buffer += l;
|
||||
+
|
||||
+ jobj_segment = LUKS2_get_segment_by_flag(hdr, "backup-moved-segment");
|
||||
+ if (jobj_segment) {
|
||||
+ if (!(l = segment_serialize(jobj_segment, buffer)))
|
||||
+ return 0;
|
||||
+ len += l;
|
||||
+ }
|
||||
+
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+static size_t reenc_keyslot_serialize(struct luks2_hdr *hdr, uint8_t *buffer)
|
||||
+{
|
||||
+ json_object *jobj_keyslot, *jobj_area, *jobj_type;
|
||||
+ const char *area_type;
|
||||
+ int keyslot_reencrypt;
|
||||
+
|
||||
+ keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
|
||||
+ if (keyslot_reencrypt < 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!(jobj_keyslot = LUKS2_get_keyslot_jobj(hdr, keyslot_reencrypt)))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!json_object_object_get_ex(jobj_keyslot, "area", &jobj_area))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!json_object_object_get_ex(jobj_area, "type", &jobj_type))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (!(area_type = json_object_get_string(jobj_type)))
|
||||
+ return 0;
|
||||
+
|
||||
+ struct jtype j[] = {
|
||||
+ { JSTR, jobj_keyslot, "mode" },
|
||||
+ { JSTR, jobj_keyslot, "direction" },
|
||||
+ { JSTR, jobj_area, "type" },
|
||||
+ { JU64, jobj_area, "offset" },
|
||||
+ { JU64, jobj_area, "size" },
|
||||
+ {}
|
||||
+ };
|
||||
+ struct jtype j_datashift[] = {
|
||||
+ { JSTR, jobj_keyslot, "mode" },
|
||||
+ { JSTR, jobj_keyslot, "direction" },
|
||||
+ { JSTR, jobj_area, "type" },
|
||||
+ { JU64, jobj_area, "offset" },
|
||||
+ { JU64, jobj_area, "size" },
|
||||
+ { JU64, jobj_area, "shift_size" },
|
||||
+ {}
|
||||
+ };
|
||||
+ struct jtype j_checksum[] = {
|
||||
+ { JSTR, jobj_keyslot, "mode" },
|
||||
+ { JSTR, jobj_keyslot, "direction" },
|
||||
+ { JSTR, jobj_area, "type" },
|
||||
+ { JU64, jobj_area, "offset" },
|
||||
+ { JU64, jobj_area, "size" },
|
||||
+ { JSTR, jobj_area, "hash" },
|
||||
+ { JU32, jobj_area, "sector_size" },
|
||||
+ {}
|
||||
+ };
|
||||
+
|
||||
+ if (!strcmp(area_type, "datashift"))
|
||||
+ return srs(j_datashift, buffer);
|
||||
+ else if (!strcmp(area_type, "checksum"))
|
||||
+ return srs(j_checksum, buffer);
|
||||
+
|
||||
+ return srs(j, buffer);
|
||||
+}
|
||||
+
|
||||
+static size_t blob_serialize(void *blob, size_t length, uint8_t *buffer)
|
||||
+{
|
||||
+ if (buffer)
|
||||
+ memcpy(buffer, blob, length);
|
||||
+
|
||||
+ return length;
|
||||
+}
|
||||
+
|
||||
+static int reencrypt_assembly_verification_data(struct crypt_device *cd,
|
||||
+ struct luks2_hdr *hdr,
|
||||
+ struct volume_key *vks,
|
||||
+ struct volume_key **verification_data)
|
||||
+{
|
||||
+ uint8_t *ptr;
|
||||
+ int digest_new, digest_old;
|
||||
+ struct volume_key *data = NULL, *vk_old = NULL, *vk_new = NULL;
|
||||
+ size_t keyslot_data_len, segments_data_len, data_len = 2;
|
||||
+
|
||||
+ /* Keys - calculate length */
|
||||
+ digest_new = LUKS2_reencrypt_digest_new(hdr);
|
||||
+ digest_old = LUKS2_reencrypt_digest_old(hdr);
|
||||
+
|
||||
+ if (digest_old >= 0) {
|
||||
+ vk_old = crypt_volume_key_by_id(vks, digest_old);
|
||||
+ if (!vk_old)
|
||||
+ return -EINVAL;
|
||||
+ data_len += blob_serialize(vk_old->key, vk_old->keylength, NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (digest_new >= 0 && digest_old != digest_new) {
|
||||
+ vk_new = crypt_volume_key_by_id(vks, digest_new);
|
||||
+ if (!vk_new)
|
||||
+ return -EINVAL;
|
||||
+ data_len += blob_serialize(vk_new->key, vk_new->keylength, NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (data_len == 2)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* Metadata - calculate length */
|
||||
+ if (!(keyslot_data_len = reenc_keyslot_serialize(hdr, NULL)))
|
||||
+ return -EINVAL;
|
||||
+ data_len += keyslot_data_len;
|
||||
+
|
||||
+ if (!(segments_data_len = backup_segments_serialize(hdr, NULL)))
|
||||
+ return -EINVAL;
|
||||
+ data_len += segments_data_len;
|
||||
+
|
||||
+ /* Alloc and fill serialization data */
|
||||
+ data = crypt_alloc_volume_key(data_len, NULL);
|
||||
+ if (!data)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ ptr = (uint8_t*)data->key;
|
||||
+
|
||||
+ /* v2 */
|
||||
+ *ptr++ = 0x76;
|
||||
+ *ptr++ = 0x32;
|
||||
+
|
||||
+ if (vk_old)
|
||||
+ ptr += blob_serialize(vk_old->key, vk_old->keylength, ptr);
|
||||
+
|
||||
+ if (vk_new)
|
||||
+ ptr += blob_serialize(vk_new->key, vk_new->keylength, ptr);
|
||||
+
|
||||
+ if (!reenc_keyslot_serialize(hdr, ptr))
|
||||
+ goto bad;
|
||||
+ ptr += keyslot_data_len;
|
||||
+
|
||||
+ if (!backup_segments_serialize(hdr, ptr))
|
||||
+ goto bad;
|
||||
+ ptr += segments_data_len;
|
||||
+
|
||||
+ assert((size_t)(ptr - (uint8_t*)data->key) == data_len);
|
||||
+
|
||||
+ *verification_data = data;
|
||||
+
|
||||
+ return 0;
|
||||
+bad:
|
||||
+ crypt_free_volume_key(data);
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
+int LUKS2_keyslot_reencrypt_digest_create(struct crypt_device *cd,
|
||||
+ struct luks2_hdr *hdr,
|
||||
+ struct volume_key *vks)
|
||||
+{
|
||||
+ int digest_reencrypt, keyslot_reencrypt, r;
|
||||
+ struct volume_key *data;
|
||||
+
|
||||
+ keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
|
||||
+ if (keyslot_reencrypt < 0)
|
||||
+ return keyslot_reencrypt;
|
||||
+
|
||||
+ r = reencrypt_assembly_verification_data(cd, hdr, vks, &data);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = LUKS2_digest_create(cd, "pbkdf2", hdr, data);
|
||||
+ crypt_free_volume_key(data);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ digest_reencrypt = r;
|
||||
+
|
||||
+ r = LUKS2_digest_assign(cd, hdr, keyslot_reencrypt, CRYPT_ANY_DIGEST, 0, 0);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ return LUKS2_digest_assign(cd, hdr, keyslot_reencrypt, digest_reencrypt, 1, 0);
|
||||
+}
|
||||
+
|
||||
+int LUKS2_reencrypt_digest_verify(struct crypt_device *cd,
|
||||
+ struct luks2_hdr *hdr,
|
||||
+ struct volume_key *vks)
|
||||
+{
|
||||
+ int r, keyslot_reencrypt;
|
||||
+ struct volume_key *data;
|
||||
+
|
||||
+ keyslot_reencrypt = LUKS2_find_keyslot(hdr, "reencrypt");
|
||||
+ if (keyslot_reencrypt < 0)
|
||||
+ return keyslot_reencrypt;
|
||||
+
|
||||
+ r = reencrypt_assembly_verification_data(cd, hdr, vks, &data);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ r = LUKS2_digest_verify(cd, hdr, data, keyslot_reencrypt);
|
||||
+ crypt_free_volume_key(data);
|
||||
+
|
||||
+ if (r < 0) {
|
||||
+ if (r == -ENOENT)
|
||||
+ log_dbg(cd, "Reencryption digest is missing.");
|
||||
+ log_err(cd, _("Reencryption metadata is invalid."));
|
||||
+ } else
|
||||
+ log_dbg(cd, "Reencryption metadata verified.");
|
||||
+
|
||||
+ return r;
|
||||
+}
|
||||
diff --git a/lib/setup.c b/lib/setup.c
|
||||
index a5dfd843..86a932da 100644
|
||||
--- a/lib/setup.c
|
||||
+++ b/lib/setup.c
|
||||
@@ -4131,6 +4131,12 @@ static int _open_and_activate_reencrypt_device(struct crypt_device *cd,
|
||||
keyslot = r;
|
||||
}
|
||||
|
||||
+ if (r >= 0) {
|
||||
+ r = LUKS2_reencrypt_digest_verify(cd, hdr, vks);
|
||||
+ if (r < 0)
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
log_dbg(cd, "Entering clean reencryption state mode.");
|
||||
|
||||
if (r >= 0)
|
||||
@@ -4158,8 +4164,9 @@ static int _open_and_activate_luks2(struct crypt_device *cd,
|
||||
uint32_t flags)
|
||||
{
|
||||
crypt_reencrypt_info ri;
|
||||
- int r;
|
||||
+ int r, rv;
|
||||
struct luks2_hdr *hdr = &cd->u.luks2.hdr;
|
||||
+ struct volume_key *vks = NULL;
|
||||
|
||||
ri = LUKS2_reencrypt_status(hdr);
|
||||
if (ri == CRYPT_REENCRYPT_INVALID)
|
||||
@@ -4169,9 +4176,17 @@ static int _open_and_activate_luks2(struct crypt_device *cd,
|
||||
if (name)
|
||||
r = _open_and_activate_reencrypt_device(cd, hdr, keyslot, name, passphrase,
|
||||
passphrase_size, flags);
|
||||
- else
|
||||
+ else {
|
||||
r = _open_all_keys(cd, hdr, keyslot, passphrase,
|
||||
- passphrase_size, flags, NULL);
|
||||
+ passphrase_size, flags, &vks);
|
||||
+ if (r < 0)
|
||||
+ return r;
|
||||
+
|
||||
+ rv = LUKS2_reencrypt_digest_verify(cd, hdr, vks);
|
||||
+ crypt_free_volume_key(vks);
|
||||
+ if (rv < 0)
|
||||
+ return rv;
|
||||
+ }
|
||||
} else
|
||||
r = _open_and_activate(cd, keyslot, name, passphrase,
|
||||
passphrase_size, flags);
|
||||
diff --git a/po/POTFILES.in b/po/POTFILES.in
|
||||
index 867d879d..dac9a31f 100644
|
||||
--- a/po/POTFILES.in
|
||||
+++ b/po/POTFILES.in
|
||||
@@ -37,6 +37,7 @@ lib/luks2/luks2_keyslot_luks2.c
|
||||
lib/luks2/luks2_keyslot_reenc.c
|
||||
lib/luks2/luks2_luks1_convert.c
|
||||
lib/luks2/luks2_reencrypt.c
|
||||
+lib/luks2/luks2_reencrypt_digest.c
|
||||
lib/luks2/luks2_segment.c
|
||||
lib/luks2/luks2_token.c
|
||||
lib/luks2/luks2_token_keyring.c
|
||||
--
|
||||
2.27.0
|
||||
|
||||
@ -1,31 +0,0 @@
|
||||
From 88b2d1af10922e0defb3eeacac6bb03aab9cbd60 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Kozina <okozina@redhat.com>
|
||||
Date: Thu, 27 Aug 2020 12:12:13 +0200
|
||||
Subject: [PATCH 4/5] Fix posible buffer overflows in LUKS conversion.
|
||||
|
||||
cipher[31] and cipher_mode[31] buffers were passed to
|
||||
crypt_parse_name_and_mode() routine where sscanf(s, "%31[^-]-%31s",
|
||||
cipher, cipher_mode) was called.
|
||||
|
||||
In corner case it could cause terminating 0 byte written beyond
|
||||
respective arrays.
|
||||
---
|
||||
lib/luks2/luks2_luks1_convert.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/lib/luks2/luks2_luks1_convert.c b/lib/luks2/luks2_luks1_convert.c
|
||||
index 603c44d..9b70df1 100644
|
||||
--- a/lib/luks2/luks2_luks1_convert.c
|
||||
+++ b/lib/luks2/luks2_luks1_convert.c
|
||||
@@ -675,7 +675,7 @@ static int keyslot_LUKS1_compatible(struct crypt_device *cd, struct luks2_hdr *h
|
||||
int LUKS2_luks2_to_luks1(struct crypt_device *cd, struct luks2_hdr *hdr2, struct luks_phdr *hdr1)
|
||||
{
|
||||
size_t buf_size, buf_offset;
|
||||
- char cipher[LUKS_CIPHERNAME_L-1], cipher_mode[LUKS_CIPHERMODE_L-1];
|
||||
+ char cipher[LUKS_CIPHERNAME_L], cipher_mode[LUKS_CIPHERMODE_L];
|
||||
char digest[LUKS_DIGESTSIZE], digest_salt[LUKS_SALTSIZE];
|
||||
const char *hash;
|
||||
size_t len;
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
131
0005-Fix-OpenSSL-2-crypto-backend-PBKDF2-possible-iterati.patch
Normal file
131
0005-Fix-OpenSSL-2-crypto-backend-PBKDF2-possible-iterati.patch
Normal file
@ -0,0 +1,131 @@
|
||||
From ace015a3e5d0940ae00c309ed53097f5a695dee5 Mon Sep 17 00:00:00 2001
|
||||
From: Milan Broz <gmazyland@gmail.com>
|
||||
Date: Tue, 31 Jan 2023 20:15:58 +0100
|
||||
Subject: [PATCH] Fix OpenSSL < 2 crypto backend PBKDF2 possible
|
||||
iteration
|
||||
count overflow.
|
||||
|
||||
For OpenSSL2, we use PKCS5_PBKDF2_HMAC() function.
|
||||
Unfortunately, the iteration count is defined as signed integer
|
||||
(unlike unsigned in OpenSSL3 PARAMS KDF API).
|
||||
|
||||
This can lead to overflow and decreasing of actual iterations count.
|
||||
In reality this can happen only if pbkdf-force-iterations is used.
|
||||
|
||||
This patch add check to INT_MAX if linked to older OpenSSL and
|
||||
disallows such setting.
|
||||
|
||||
Note, this is misconception in OpenSSL2 API, cryptsetup internally
|
||||
use uint32_t for iterations count.
|
||||
|
||||
Reported by wangzhiqiang <wangzhiqiang95@huawei.com> in cryptsetup list.
|
||||
|
||||
Conflict: context adaptation
|
||||
---
|
||||
lib/crypto_backend/crypto_backend.h | 3 ++-
|
||||
lib/crypto_backend/crypto_openssl.c | 10 ++++++++++
|
||||
lib/luks1/keymanage.c | 7 ++++++-
|
||||
lib/luks2/luks2_keyslot_luks2.c | 4 ++++
|
||||
4 files changed, 22 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/lib/crypto_backend/crypto_backend.h b/lib/crypto_backend/crypto_backend.h
|
||||
index 88cc2d5..47e5186 100644
|
||||
--- a/lib/crypto_backend/crypto_backend.h
|
||||
+++ b/lib/crypto_backend/crypto_backend.h
|
||||
@@ -34,7 +34,8 @@ struct crypt_storage;
|
||||
int crypt_backend_init(bool fips);
|
||||
void crypt_backend_destroy(void);
|
||||
|
||||
-#define CRYPT_BACKEND_KERNEL (1 << 0) /* Crypto uses kernel part, for benchmark */
|
||||
+#define CRYPT_BACKEND_KERNEL (1 << 0) /* Crypto uses kernel part, for benchmark */
|
||||
+#define CRYPT_BACKEND_PBKDF2_INT (1 << 1) /* Iteration in PBKDF2 is signed int and can overflow */
|
||||
|
||||
uint32_t crypt_backend_flags(void);
|
||||
const char *crypt_backend_version(void);
|
||||
diff --git a/lib/crypto_backend/crypto_openssl.c b/lib/crypto_backend/crypto_openssl.c
|
||||
index 0dbcb75..3a58dcd 100644
|
||||
--- a/lib/crypto_backend/crypto_openssl.c
|
||||
+++ b/lib/crypto_backend/crypto_openssl.c
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
+#include <limits.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/rand.h>
|
||||
@@ -228,7 +229,11 @@ void crypt_backend_destroy(void)
|
||||
|
||||
uint32_t crypt_backend_flags(void)
|
||||
{
|
||||
+#if OPENSSL_VERSION_MAJOR >= 3
|
||||
return 0;
|
||||
+#else
|
||||
+ return CRYPT_BACKEND_PBKDF2_INT;
|
||||
+#endif
|
||||
}
|
||||
|
||||
const char *crypt_backend_version(void)
|
||||
@@ -527,6 +532,11 @@ static int pbkdf2(const char *password, size_t password_length,
|
||||
if (!hash_id)
|
||||
return 0;
|
||||
|
||||
+ /* OpenSSL2 has iteration as signed int, avoid overflow */
|
||||
+ if (iterations > INT_MAX)
|
||||
+ return 0;
|
||||
+
|
||||
+
|
||||
return PKCS5_PBKDF2_HMAC(password, (int)password_length, (const unsigned char *)salt,
|
||||
(int)salt_length, iterations, hash_id,
|
||||
(int)key_length, key);
|
||||
diff --git a/lib/luks1/keymanage.c b/lib/luks1/keymanage.c
|
||||
index 244b0d5..792088c 100644
|
||||
--- a/lib/luks1/keymanage.c
|
||||
+++ b/lib/luks1/keymanage.c
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include <uuid/uuid.h>
|
||||
+#include <limits.h>
|
||||
|
||||
#include "luks.h"
|
||||
#include "af.h"
|
||||
@@ -922,8 +923,12 @@ 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
|
||||
diff --git a/lib/luks2/luks2_keyslot_luks2.c b/lib/luks2/luks2_keyslot_luks2.c
|
||||
index ea58112..098f6c6 100644
|
||||
--- a/lib/luks2/luks2_keyslot_luks2.c
|
||||
+++ b/lib/luks2/luks2_keyslot_luks2.c
|
||||
@@ -19,6 +19,7 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
+#include <limits.h>
|
||||
#include "luks2_internal.h"
|
||||
|
||||
/* FIXME: move keyslot encryption to crypto backend */
|
||||
@@ -254,6 +255,9 @@ static int luks2_keyslot_set_key(struct crypt_device *cd,
|
||||
pbkdf.iterations, pbkdf.max_memory_kb,
|
||||
pbkdf.parallel_threads);
|
||||
if (r < 0) {
|
||||
+ if ((crypt_backend_flags() & CRYPT_BACKEND_PBKDF2_INT) &&
|
||||
+ pbkdf.iterations > INT_MAX)
|
||||
+ log_err(cd, _("PBKDF2 iteration value overflow."));
|
||||
crypt_free_volume_key(derived_key);
|
||||
return r;
|
||||
}
|
||||
--
|
||||
2.33.0
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
From fa57d76de233e22afd79e81c98a741c23dae3498 Mon Sep 17 00:00:00 2001
|
||||
From: Milan Broz <gmazyland@gmail.com>
|
||||
Date: Sat, 29 Aug 2020 12:21:32 +0200
|
||||
Subject: [PATCH 5/5] Fix a memleak in blockwise test.
|
||||
|
||||
---
|
||||
tests/unit-utils-io.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tests/unit-utils-io.c b/tests/unit-utils-io.c
|
||||
index ff5be52..9e59234 100644
|
||||
--- a/tests/unit-utils-io.c
|
||||
+++ b/tests/unit-utils-io.c
|
||||
@@ -99,7 +99,7 @@ static int test_write_buffer(void)
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
- return (size_t) ret == test_length ? 0 : -EIO;
|
||||
+ ret = (size_t) ret == test_length ? 0 : -EIO;
|
||||
out:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
--
|
||||
1.8.3.1
|
||||
|
||||
348
0006-fix-potential-null-pointer-dereference.patch
Normal file
348
0006-fix-potential-null-pointer-dereference.patch
Normal file
@ -0,0 +1,348 @@
|
||||
From 5dd515878f23610e541ab761f9c45c6dab1c9700 Mon Sep 17 00:00:00 2001
|
||||
From: wangzhiqiang <wangzhiqiang95@huawei.com>
|
||||
Date: Fri, 10 Feb 2023 15:02:23 +0800
|
||||
Subject: [PATCH 1/2] fix potential null pointer dereference.
|
||||
|
||||
Signed-off-by: wangzhiqiang <wangzhiqiang95@huawei.com>
|
||||
---
|
||||
lib/luks2/luks2_digest_pbkdf2.c | 3 +++
|
||||
lib/luks2/luks2_json_format.c | 38 +++++++++++++++++++++++++++++----
|
||||
lib/luks2/luks2_json_metadata.c | 8 +++++++
|
||||
lib/luks2/luks2_keyslot.c | 8 +++++++
|
||||
lib/luks2/luks2_keyslot_luks2.c | 18 ++++++++++++++++
|
||||
lib/luks2/luks2_luks1_convert.c | 24 +++++++++++++++++++++
|
||||
src/cryptsetup.c | 3 +++
|
||||
src/integritysetup.c | 3 +++
|
||||
src/veritysetup.c | 3 +++
|
||||
tokens/ssh/cryptsetup-ssh.c | 8 ++++++-
|
||||
10 files changed, 111 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/lib/luks2/luks2_digest_pbkdf2.c b/lib/luks2/luks2_digest_pbkdf2.c
|
||||
index 03c6f49..003d86d 100644
|
||||
--- a/lib/luks2/luks2_digest_pbkdf2.c
|
||||
+++ b/lib/luks2/luks2_digest_pbkdf2.c
|
||||
@@ -148,6 +148,9 @@ static int PBKDF2_digest_store(struct crypt_device *cd,
|
||||
json_object_object_get_ex(hdr->jobj, "digests", &jobj_digests);
|
||||
}
|
||||
|
||||
+ if (!jobj_digest)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
json_object_object_add(jobj_digest, "type", json_object_new_string("pbkdf2"));
|
||||
json_object_object_add(jobj_digest, "keyslots", json_object_new_array());
|
||||
json_object_object_add(jobj_digest, "segments", json_object_new_array());
|
||||
diff --git a/lib/luks2/luks2_json_format.c b/lib/luks2/luks2_json_format.c
|
||||
index 350ebf4..45541c3 100644
|
||||
--- a/lib/luks2/luks2_json_format.c
|
||||
+++ b/lib/luks2/luks2_json_format.c
|
||||
@@ -300,29 +300,59 @@ int LUKS2_generate_hdr(
|
||||
return -EINVAL;
|
||||
|
||||
hdr->jobj = json_object_new_object();
|
||||
+ if (!hdr->jobj) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
|
||||
jobj_keyslots = json_object_new_object();
|
||||
+ if (!jobj_keyslots) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
json_object_object_add(hdr->jobj, "keyslots", jobj_keyslots);
|
||||
json_object_object_add(hdr->jobj, "tokens", json_object_new_object());
|
||||
jobj_segments = json_object_new_object();
|
||||
+ if (!jobj_segments) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
json_object_object_add(hdr->jobj, "segments", jobj_segments);
|
||||
json_object_object_add(hdr->jobj, "digests", json_object_new_object());
|
||||
jobj_config = json_object_new_object();
|
||||
+ if (!jobj_config) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
json_object_object_add(hdr->jobj, "config", jobj_config);
|
||||
|
||||
digest = LUKS2_digest_create(cd, "pbkdf2", hdr, vk);
|
||||
- if (digest < 0)
|
||||
+ if (digest < 0) {
|
||||
+ r = -EINVAL;
|
||||
goto err;
|
||||
+ }
|
||||
|
||||
- if (LUKS2_digest_segment_assign(cd, hdr, 0, digest, 1, 0) < 0)
|
||||
+ if (LUKS2_digest_segment_assign(cd, hdr, 0, digest, 1, 0) < 0) {
|
||||
+ r = -EINVAL;
|
||||
goto err;
|
||||
+ }
|
||||
|
||||
jobj_segment = json_segment_create_crypt(data_offset, 0, NULL, cipher, sector_size, 0);
|
||||
- if (!jobj_segment)
|
||||
+ if (!jobj_segment) {
|
||||
+ r = -EINVAL;
|
||||
goto err;
|
||||
+ }
|
||||
|
||||
if (integrity) {
|
||||
jobj_integrity = json_object_new_object();
|
||||
+ if (!jobj_integrity) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
json_object_object_add(jobj_integrity, "type", json_object_new_string(integrity));
|
||||
json_object_object_add(jobj_integrity, "journal_encryption", json_object_new_string("none"));
|
||||
json_object_object_add(jobj_integrity, "journal_integrity", json_object_new_string("none"));
|
||||
@@ -339,7 +369,7 @@ int LUKS2_generate_hdr(
|
||||
err:
|
||||
json_object_put(hdr->jobj);
|
||||
hdr->jobj = NULL;
|
||||
- return -EINVAL;
|
||||
+ return r;
|
||||
}
|
||||
|
||||
int LUKS2_wipe_header_areas(struct crypt_device *cd,
|
||||
diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c
|
||||
index 0c449ee..e12b3c7 100644
|
||||
--- a/lib/luks2/luks2_json_metadata.c
|
||||
+++ b/lib/luks2/luks2_json_metadata.c
|
||||
@@ -90,6 +90,9 @@ struct json_object *LUKS2_array_remove(struct json_object *array, const char *nu
|
||||
|
||||
/* Create new array without jobj_removing. */
|
||||
array_new = json_object_new_array();
|
||||
+ if (!array_new)
|
||||
+ return NULL;
|
||||
+
|
||||
for (i = 0; i < (int) json_object_array_length(array); i++) {
|
||||
jobj1 = json_object_array_get_idx(array, i);
|
||||
if (jobj1 != jobj_removing)
|
||||
@@ -456,6 +459,9 @@ static int hdr_validate_json_size(struct crypt_device *cd, json_object *hdr_jobj
|
||||
|
||||
json = json_object_to_json_string_ext(hdr_jobj,
|
||||
JSON_C_TO_STRING_PLAIN | JSON_C_TO_STRING_NOSLASHESCAPE);
|
||||
+ if (!json)
|
||||
+ return 1;
|
||||
+
|
||||
json_area_size = crypt_jobj_get_uint64(jobj1);
|
||||
json_size = (uint64_t)strlen(json);
|
||||
|
||||
@@ -1362,6 +1368,8 @@ int LUKS2_config_set_flags(struct crypt_device *cd, struct luks2_hdr *hdr, uint3
|
||||
return 0;
|
||||
|
||||
jobj_flags = json_object_new_array();
|
||||
+ if (!jobj_flags)
|
||||
+ return -ENOMEM;
|
||||
|
||||
for (i = 0; persistent_flags[i].description; i++) {
|
||||
if (flags & persistent_flags[i].flag) {
|
||||
diff --git a/lib/luks2/luks2_keyslot.c b/lib/luks2/luks2_keyslot.c
|
||||
index 3d70186..c2a4088 100644
|
||||
--- a/lib/luks2/luks2_keyslot.c
|
||||
+++ b/lib/luks2/luks2_keyslot.c
|
||||
@@ -838,6 +838,9 @@ int placeholder_keyslot_alloc(struct crypt_device *cd,
|
||||
return -EINVAL;
|
||||
|
||||
jobj_keyslot = json_object_new_object();
|
||||
+ if (!jobj_keyslot)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
json_object_object_add(jobj_keyslot, "type", json_object_new_string("placeholder"));
|
||||
/*
|
||||
* key_size = -1 makes placeholder keyslot impossible to pass validation.
|
||||
@@ -848,6 +851,11 @@ int placeholder_keyslot_alloc(struct crypt_device *cd,
|
||||
|
||||
/* Area object */
|
||||
jobj_area = json_object_new_object();
|
||||
+ if (!jobj_area) {
|
||||
+ json_object_put(jobj_keyslot);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(area_offset));
|
||||
json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_length));
|
||||
json_object_object_add(jobj_keyslot, "area", jobj_area);
|
||||
diff --git a/lib/luks2/luks2_keyslot_luks2.c b/lib/luks2/luks2_keyslot_luks2.c
|
||||
index 49b3a75..1513d25 100644
|
||||
--- a/lib/luks2/luks2_keyslot_luks2.c
|
||||
+++ b/lib/luks2/luks2_keyslot_luks2.c
|
||||
@@ -489,17 +489,32 @@ static int luks2_keyslot_alloc(struct crypt_device *cd,
|
||||
}
|
||||
|
||||
jobj_keyslot = json_object_new_object();
|
||||
+ if (!jobj_keyslot) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
json_object_object_add(jobj_keyslot, "type", json_object_new_string("luks2"));
|
||||
json_object_object_add(jobj_keyslot, "key_size", json_object_new_int(volume_key_len));
|
||||
|
||||
/* AF object */
|
||||
jobj_af = json_object_new_object();
|
||||
+ if (!jobj_af) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
json_object_object_add(jobj_af, "type", json_object_new_string("luks1"));
|
||||
json_object_object_add(jobj_af, "stripes", json_object_new_int(params->af.luks1.stripes));
|
||||
json_object_object_add(jobj_keyslot, "af", jobj_af);
|
||||
|
||||
/* Area object */
|
||||
jobj_area = json_object_new_object();
|
||||
+ if (!jobj_area) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
json_object_object_add(jobj_area, "type", json_object_new_string("raw"));
|
||||
json_object_object_add(jobj_area, "offset", crypt_jobj_new_uint64(area_offset));
|
||||
json_object_object_add(jobj_area, "size", crypt_jobj_new_uint64(area_length));
|
||||
@@ -518,6 +533,9 @@ static int luks2_keyslot_alloc(struct crypt_device *cd,
|
||||
json_object_object_del_by_uint(jobj_keyslots, keyslot);
|
||||
|
||||
return r;
|
||||
+err:
|
||||
+ json_object_put(jobj_keyslot);
|
||||
+ return r;
|
||||
}
|
||||
|
||||
static int luks2_keyslot_open(struct crypt_device *cd,
|
||||
diff --git a/lib/luks2/luks2_luks1_convert.c b/lib/luks2/luks2_luks1_convert.c
|
||||
index 84fd44f..8350dba 100644
|
||||
--- a/lib/luks2/luks2_luks1_convert.c
|
||||
+++ b/lib/luks2/luks2_luks1_convert.c
|
||||
@@ -38,13 +38,24 @@ static int json_luks1_keyslot(const struct luks_phdr *hdr_v1, int keyslot, struc
|
||||
size_t base64_len;
|
||||
struct json_object *keyslot_obj, *field, *jobj_kdf, *jobj_af, *jobj_area;
|
||||
uint64_t offset, area_size, offs_a, offs_b, length;
|
||||
+ int r;
|
||||
|
||||
keyslot_obj = json_object_new_object();
|
||||
+ if (!keyslot_obj) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
json_object_object_add(keyslot_obj, "type", json_object_new_string("luks2"));
|
||||
json_object_object_add(keyslot_obj, "key_size", json_object_new_int64(hdr_v1->keyBytes));
|
||||
|
||||
/* KDF */
|
||||
jobj_kdf = json_object_new_object();
|
||||
+ if (!jobj_kdf) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
json_object_object_add(jobj_kdf, "type", json_object_new_string(CRYPT_KDF_PBKDF2));
|
||||
json_object_object_add(jobj_kdf, "hash", json_object_new_string(hdr_v1->hashSpec));
|
||||
json_object_object_add(jobj_kdf, "iterations", json_object_new_int64(hdr_v1->keyblock[keyslot].passwordIterations));
|
||||
@@ -64,6 +75,11 @@ static int json_luks1_keyslot(const struct luks_phdr *hdr_v1, int keyslot, struc
|
||||
|
||||
/* AF */
|
||||
jobj_af = json_object_new_object();
|
||||
+ if (!jobj_af) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
json_object_object_add(jobj_af, "type", json_object_new_string("luks1"));
|
||||
json_object_object_add(jobj_af, "hash", json_object_new_string(hdr_v1->hashSpec));
|
||||
/* stripes field ignored, fixed to LUKS_STRIPES (4000) */
|
||||
@@ -72,6 +88,11 @@ static int json_luks1_keyslot(const struct luks_phdr *hdr_v1, int keyslot, struc
|
||||
|
||||
/* Area */
|
||||
jobj_area = json_object_new_object();
|
||||
+ if (!jobj_area) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
json_object_object_add(jobj_area, "type", json_object_new_string("raw"));
|
||||
|
||||
/* encryption algorithm field */
|
||||
@@ -97,6 +118,9 @@ static int json_luks1_keyslot(const struct luks_phdr *hdr_v1, int keyslot, struc
|
||||
|
||||
*keyslot_object = keyslot_obj;
|
||||
return 0;
|
||||
+err:
|
||||
+ json_object_put(keyslot_obj);
|
||||
+ return r;
|
||||
}
|
||||
|
||||
static int json_luks1_keyslots(const struct luks_phdr *hdr_v1, struct json_object **keyslots_object)
|
||||
diff --git a/src/cryptsetup.c b/src/cryptsetup.c
|
||||
index e785dc3..78421a6 100644
|
||||
--- a/src/cryptsetup.c
|
||||
+++ b/src/cryptsetup.c
|
||||
@@ -3767,6 +3767,9 @@ int main(int argc, const char **argv)
|
||||
textdomain(PACKAGE);
|
||||
|
||||
popt_context = poptGetContext(PACKAGE, argc, argv, popt_options, 0);
|
||||
+ if (!popt_context)
|
||||
+ exit(EXIT_FAILURE);
|
||||
+
|
||||
poptSetOtherOptionHelp(popt_context,
|
||||
_("[OPTION...] <action> <action-specific>"));
|
||||
|
||||
diff --git a/src/integritysetup.c b/src/integritysetup.c
|
||||
index 4604302..468a8cf 100644
|
||||
--- a/src/integritysetup.c
|
||||
+++ b/src/integritysetup.c
|
||||
@@ -569,6 +569,9 @@ int main(int argc, const char **argv)
|
||||
textdomain(PACKAGE);
|
||||
|
||||
popt_context = poptGetContext("integrity", argc, argv, popt_options, 0);
|
||||
+ if (!popt_context)
|
||||
+ exit(EXIT_FAILURE);
|
||||
+
|
||||
poptSetOtherOptionHelp(popt_context,
|
||||
_("[OPTION...] <action> <action-specific>"));
|
||||
|
||||
diff --git a/src/veritysetup.c b/src/veritysetup.c
|
||||
index 04fd996..2a701af 100644
|
||||
--- a/src/veritysetup.c
|
||||
+++ b/src/veritysetup.c
|
||||
@@ -588,6 +588,9 @@ int main(int argc, const char **argv)
|
||||
textdomain(PACKAGE);
|
||||
|
||||
popt_context = poptGetContext("verity", argc, argv, popt_options, 0);
|
||||
+ if (!popt_context)
|
||||
+ exit(EXIT_FAILURE);
|
||||
+
|
||||
poptSetOtherOptionHelp(popt_context,
|
||||
_("[OPTION...] <action> <action-specific>"));
|
||||
|
||||
diff --git a/tokens/ssh/cryptsetup-ssh.c b/tokens/ssh/cryptsetup-ssh.c
|
||||
index c1d0a60..87c55d5 100644
|
||||
--- a/tokens/ssh/cryptsetup-ssh.c
|
||||
+++ b/tokens/ssh/cryptsetup-ssh.c
|
||||
@@ -78,13 +78,19 @@ static int token_add(
|
||||
|
||||
r = -EINVAL;
|
||||
jobj = json_object_new_object();
|
||||
- if (!jobj)
|
||||
+ if (!jobj) {
|
||||
+ r = -ENOMEM;
|
||||
goto out;
|
||||
+ }
|
||||
|
||||
/* type is mandatory field in all tokens and must match handler name member */
|
||||
json_object_object_add(jobj, "type", json_object_new_string(TOKEN_NAME));
|
||||
|
||||
jobj_keyslots = json_object_new_array();
|
||||
+ if (!jobj_keyslots) {
|
||||
+ r = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
/* mandatory array field (may be empty and assigned later */
|
||||
json_object_object_add(jobj, "keyslots", jobj_keyslots);
|
||||
--
|
||||
2.33.0
|
||||
|
||||
24
0007-Update-file-cryptsetup-ssh.c.patch
Normal file
24
0007-Update-file-cryptsetup-ssh.c.patch
Normal file
@ -0,0 +1,24 @@
|
||||
From 7883cf7f2b8f2a37aea78aced53b7a445ec72c3b Mon Sep 17 00:00:00 2001
|
||||
From: wangzhiqiang <zhiqiangwang12_4@163.com>
|
||||
Date: Fri, 10 Feb 2023 16:48:19 +0000
|
||||
Subject: [PATCH 2/2] Update file cryptsetup-ssh.c
|
||||
|
||||
---
|
||||
tokens/ssh/cryptsetup-ssh.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/tokens/ssh/cryptsetup-ssh.c b/tokens/ssh/cryptsetup-ssh.c
|
||||
index 87c55d5..0d06000 100644
|
||||
--- a/tokens/ssh/cryptsetup-ssh.c
|
||||
+++ b/tokens/ssh/cryptsetup-ssh.c
|
||||
@@ -76,7 +76,6 @@ static int token_add(
|
||||
if (r)
|
||||
goto out;
|
||||
|
||||
- r = -EINVAL;
|
||||
jobj = json_object_new_object();
|
||||
if (!jobj) {
|
||||
r = -ENOMEM;
|
||||
--
|
||||
2.33.0
|
||||
|
||||
Binary file not shown.
@ -1,18 +1,20 @@
|
||||
Name: cryptsetup
|
||||
Version: 2.3.3
|
||||
Version: 2.4.1
|
||||
Release: 5
|
||||
Summary: Utility used to conveniently set up disk encryption
|
||||
License: GPLv2+ and LGPLv2+
|
||||
License: GPLv2+ and CC0-1.0 and LGPLv2+
|
||||
URL: https://gitlab.com/cryptsetup/cryptsetup
|
||||
Source0: https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-%{version}.tar.xz
|
||||
Source0: https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/cryptsetup-%{version}.tar.xz
|
||||
|
||||
Patch1: 0001-cryptsetup-add-system-library-paths.patch
|
||||
Patch2: 0002-fix-compat-test.patch
|
||||
Patch3: 0003-Check-segment-gaps-regardless-of-heap-space.patch
|
||||
Patch4: 0004-Fix-posible-buffer-overflows-in-LUKS-conversion.patch
|
||||
Patch5: 0005-Fix-a-memleak-in-blockwise-test.patch
|
||||
Patch3: 0003-add-test-case-for-sm4.patch
|
||||
Patch4: 0004-Fix-CVE-2021-4122-LUKS2-reencryption-crash-recovery-.patch
|
||||
Patch5: 0005-Fix-OpenSSL-2-crypto-backend-PBKDF2-possible-iterati.patch
|
||||
Patch6: 0006-fix-potential-null-pointer-dereference.patch
|
||||
Patch7: 0007-Update-file-cryptsetup-ssh.c.patch
|
||||
|
||||
BuildRequires: openssl-devel, popt-devel, device-mapper-devel, gcc
|
||||
BuildRequires: openssl-devel, popt-devel, device-mapper-devel, gcc, libssh-devel, gettext-devel libtool
|
||||
BuildRequires: libuuid-devel, json-c-devel, libargon2-devel, libpwquality-devel, libblkid-devel
|
||||
Requires: libpwquality >= 1.2.0
|
||||
|
||||
@ -70,6 +72,7 @@ This contains man files for the using of cryptsetup.
|
||||
%autosetup -n %{name}-%{version} -p1
|
||||
|
||||
%build
|
||||
./autogen.sh
|
||||
%configure --enable-fips --enable-pwquality --enable-libargon2 --with-crypto_backend=openssl
|
||||
%make_build
|
||||
|
||||
@ -88,10 +91,13 @@ make check
|
||||
%license COPYING COPYING.LGPL AUTHORS
|
||||
%doc docs/*
|
||||
%{_sbindir}/cryptsetup
|
||||
%{_sbindir}/cryptsetup-ssh
|
||||
%{_libdir}/libcryptsetup.so.*
|
||||
%{_libdir}/cryptsetup/*.so
|
||||
%{_tmpfilesdir}/cryptsetup.conf
|
||||
%ghost %dir /run/cryptsetup
|
||||
%exclude %{_libdir}/*.la
|
||||
%exclude %{_libdir}/cryptsetup/*.la
|
||||
|
||||
%files devel
|
||||
%doc docs/examples/*
|
||||
@ -113,6 +119,21 @@ make check
|
||||
%{_mandir}/man8/*
|
||||
|
||||
%changelog
|
||||
* Wed Mar 22 2023 wangzhiqiang <wangzhiqiang95@huawei.com> - 2.4.1-5
|
||||
- fix potential null pointer dereference
|
||||
|
||||
* Sat Feb 25 2023 volcanodragon <linfeilong@huawei.com> - 2.4.1-4
|
||||
- fix pbkdf-force-iterations in openssl
|
||||
|
||||
* Thu Feb 23 2023 volcanodragon <linfeilong@huawei.com> - 2.4.1-3
|
||||
- add testcase for sm4-xts-plain64, fix CVE-2021-4122, add out of range check
|
||||
|
||||
* Mon Oct 17 2022 wuguanghao <wuguanghao3@huawei.com> - 2.4.1-2
|
||||
- add CC0-1.0 license
|
||||
|
||||
* Wed Nov 17 2021 Wenchao Hao <haowenchao@huawei.com> - 2.4.1-1
|
||||
- Update to 2.4.1 version
|
||||
|
||||
* Fri Jul 30 2021 chenyanpanHW <chenyanpan@huawei.com> - 2.3.3-5
|
||||
- DESC: delete -S git from %autosetup, and delete BuildRequires git
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user