Compare commits

...

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
54c4e85845
!49 [sync] PR-46: fix potential null pointer dereference
From: @openeuler-sync-bot 
Reviewed-by: @liuzhiqiang26 
Signed-off-by: @liuzhiqiang26
2023-03-23 01:10:17 +00:00
wangzhiqiang
65bfc32da2 fix potential null pointer dereference.
Signed-off-by: wangzhiqiang <wangzhiqiang95@huawei.com>
(cherry picked from commit 128a1b9499f62969a190e5d0dc4a13915dff131a)
2023-03-22 16:29:24 +08:00
openeuler-ci-bot
22958e39d4
!44 [sync] PR-43: Fix OpenSSL < 2 crypto backend PBKDF2 possible iteration count overflow
From: @openeuler-sync-bot 
Reviewed-by: @liuzhiqiang26 
Signed-off-by: @liuzhiqiang26
2023-02-28 07:17:25 +00:00
volcanodragon
6dad584d3d -Fix-OpenSSL-2-crypto-backend-PBKDF2-possible-iterati
(cherry picked from commit d450a9c21f0ad9f59394e7432180aeaab65f48aa)
2023-02-28 11:00:13 +08:00
openeuler-ci-bot
15ecf7d4ad
!42 [sync] PR-40: add testcase for sm4-xts-plain64, fix CVE-2021-4122, add out of range check
From: @openeuler-sync-bot 
Reviewed-by: @liuzhiqiang26 
Signed-off-by: @liuzhiqiang26
2023-02-23 09:00:08 +00:00
volcanodragon
fdc5d74f1a add patches
(cherry picked from commit 81c0fc48b6a6bcc22f8d58b0f3a6e6766071327c)
2023-02-23 16:04:56 +08:00
openeuler-ci-bot
adbafcf2c7
!36 [sync] PR-34: add CC0-1.0 license
From: @openeuler-sync-bot 
Reviewed-by: @liuzhiqiang26 
Signed-off-by: @liuzhiqiang26
2022-10-17 12:53:43 +00:00
wguanghao
b948251c4c add CC0-1.0 license
(cherry picked from commit 163d15fa5df744ad86a2cd8e417db01ca668abc5)
2022-10-17 20:26:59 +08:00
openeuler-ci-bot
1595978a35 !24 [sync] PR-23: Update to cryptsetup-2.4.1
From: @openeuler-sync-bot
Reviewed-by: @liuzhiqiang26
Signed-off-by: @liuzhiqiang26
2021-11-29 02:38:44 +00:00
Wenchao Hao
da927ab5b8 Update to 2.4.1 version
Signed-off-by: Wenchao Hao <haowenchao@huawei.com>
(cherry picked from commit 09991739ac91cb0b1f5e908ac193f1668ea5efad)
2021-11-29 09:34:27 +08:00
11 changed files with 3269 additions and 142 deletions

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View 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

View File

@ -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

View 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

View File

@ -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

View 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

View 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

View File

@ -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