Skip to content

Commit 095fff1

Browse files
committed
Add fallback to dmcrypt in LUKS21 keyslot processing
Basically just use existing storage wrapper. The change need locked access to device.
1 parent a830691 commit 095fff1

3 files changed

Lines changed: 52 additions & 80 deletions

File tree

lib/luks2/luks2_keyslot_luks2.c

Lines changed: 47 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <limits.h>
1010
#include "luks2_internal.h"
11+
#include "utils_storage_wrappers.h"
1112

1213
/* FIXME: move keyslot encryption to crypto backend */
1314
#include "../luks1/af.h"
@@ -20,100 +21,73 @@
2021

2122
/* coverity[ -taint_source : arg-0 ] */
2223
static int luks2_encrypt_to_storage(char *src, size_t srcLength,
23-
const char *cipher, const char *cipher_mode,
24-
struct volume_key *vk, unsigned int sector,
24+
const char *cipher,
25+
struct volume_key *vk, uint64_t offset,
2526
struct crypt_device *cd)
2627
{
27-
struct crypt_storage *s;
28-
int devfd, r;
2928
struct device *device = crypt_metadata_device(cd);
29+
struct crypt_storage_wrapper *csw;
30+
uint32_t csw_flags = CSW_OPEN_LOCKED;
31+
ssize_t written;
32+
int r;
3033

31-
/* Only whole sector writes supported */
32-
if (MISALIGNED_512(srcLength))
33-
return -EINVAL;
34-
35-
/* Encrypt buffer */
36-
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode,
37-
crypt_volume_key_get_key(vk), crypt_volume_key_length(vk), false);
38-
if (r) {
39-
log_err(cd, _("Cannot use %s-%s cipher for keyslot encryption."), cipher, cipher_mode);
40-
return r;
41-
}
34+
/* dm-crypt backend requires root access */
35+
if (getuid() || geteuid())
36+
csw_flags |= CSW_DISABLE_DMCRYPT;
4237

43-
r = crypt_storage_encrypt(s, 0, srcLength, src);
44-
crypt_storage_destroy(s);
38+
r = crypt_storage_wrapper_init(cd, &csw, device, offset, 0, SECTOR_SIZE, cipher, vk, csw_flags);
4539
if (r) {
46-
log_err(cd, _("IO error while encrypting keyslot."));
40+
log_err(cd, _("Cannot use %s cipher for keyslot encryption."), cipher);
4741
return r;
4842
}
4943

50-
devfd = device_open_locked(cd, device, O_RDWR);
51-
if (devfd >= 0) {
52-
if (write_lseek_blockwise(devfd, device_block_size(cd, device),
53-
device_alignment(device), src,
54-
srcLength, sector * SECTOR_SIZE) < 0)
55-
r = -EIO;
56-
else
57-
r = 0;
58-
59-
device_sync(cd, device);
60-
} else
44+
written = crypt_storage_wrapper_encrypt_write(csw, 0, src, srcLength);
45+
if (written < 0 || (size_t)written != srcLength) {
6146
r = -EIO;
62-
63-
if (r)
6447
log_err(cd, _("IO error while encrypting keyslot."));
48+
} else
49+
r = 0;
6550

51+
crypt_storage_wrapper_destroy(csw);
6652
return r;
6753
}
6854

6955
static int luks2_decrypt_from_storage(char *dst, size_t dstLength,
70-
const char *cipher, const char *cipher_mode, struct volume_key *vk,
71-
unsigned int sector, struct crypt_device *cd)
56+
const char *cipher, struct volume_key *vk,
57+
uint64_t offset, struct crypt_device *cd)
7258
{
7359
struct device *device = crypt_metadata_device(cd);
74-
struct crypt_storage *s;
75-
int devfd, r;
60+
struct crypt_storage_wrapper *csw;
61+
uint32_t csw_flags = CSW_OPEN_LOCKED | CSW_OPEN_READONLY;
62+
ssize_t read;
63+
int r;
7664

77-
/* Only whole sector writes supported */
78-
if (MISALIGNED_512(dstLength))
79-
return -EINVAL;
65+
/* dm-crypt backend requires root access */
66+
if (getuid() || geteuid())
67+
csw_flags |= CSW_DISABLE_DMCRYPT;
8068

81-
r = crypt_storage_init(&s, SECTOR_SIZE, cipher, cipher_mode,
82-
crypt_volume_key_get_key(vk),
83-
crypt_volume_key_length(vk), false);
69+
r = device_read_lock(cd, device);
8470
if (r) {
85-
log_err(cd, _("Cannot use %s-%s cipher for keyslot encryption."), cipher, cipher_mode);
71+
log_err(cd, _("Failed to acquire read lock on device %s."), device_path(device));
8672
return r;
8773
}
8874

89-
r = device_read_lock(cd, device);
75+
r = crypt_storage_wrapper_init(cd, &csw, device, offset, 0, SECTOR_SIZE, cipher, vk, csw_flags);
9076
if (r) {
91-
log_err(cd, _("Failed to acquire read lock on device %s."),
92-
device_path(device));
93-
crypt_storage_destroy(s);
77+
log_err(cd, _("Cannot use %s cipher for keyslot encryption."), cipher);
78+
device_read_unlock(cd, device);
9479
return r;
9580
}
9681

97-
devfd = device_open_locked(cd, device, O_RDONLY);
98-
if (devfd >= 0) {
99-
if (read_lseek_blockwise(devfd, device_block_size(cd, device),
100-
device_alignment(device), dst,
101-
dstLength, sector * SECTOR_SIZE) < 0)
102-
r = -EIO;
103-
else
104-
r = 0;
105-
} else
82+
read = crypt_storage_wrapper_read_decrypt(csw, 0, dst, dstLength);
83+
if (read < 0 || (size_t)read != dstLength) {
10684
r = -EIO;
107-
108-
device_read_unlock(cd, device);
109-
110-
/* Decrypt buffer */
111-
if (!r)
112-
r = crypt_storage_decrypt(s, 0, dstLength, dst);
113-
else
11485
log_err(cd, _("IO error while decrypting keyslot."));
86+
} else
87+
r = 0;
11588

116-
crypt_storage_destroy(s);
89+
device_read_unlock(cd, device);
90+
crypt_storage_wrapper_destroy(csw);
11791
return r;
11892
}
11993

@@ -177,9 +151,9 @@ static int luks2_keyslot_set_key(struct crypt_device *cd,
177151
const char *password, size_t passwordLen,
178152
const char *volume_key, size_t volume_key_len)
179153
{
180-
char *salt = NULL, cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
154+
char *salt = NULL;
181155
char *AfKey = NULL;
182-
const char *af_hash = NULL;
156+
const char *af_hash = NULL, *cipher;
183157
size_t AFEKSize, keyslot_key_len;
184158
json_object *jobj2, *jobj_kdf, *jobj_af, *jobj_area;
185159
uint64_t area_offset;
@@ -205,9 +179,7 @@ static int luks2_keyslot_set_key(struct crypt_device *cd,
205179

206180
if (!json_object_object_get_ex(jobj_area, "encryption", &jobj2))
207181
return -EINVAL;
208-
r = crypt_parse_name_and_mode(json_object_get_string(jobj2), cipher, NULL, cipher_mode);
209-
if (r < 0)
210-
return r;
182+
cipher = json_object_get_string(jobj2);
211183

212184
if (!json_object_object_get_ex(jobj_area, "key_size", &jobj2))
213185
return -EINVAL;
@@ -272,9 +244,8 @@ static int luks2_keyslot_set_key(struct crypt_device *cd,
272244
}
273245

274246
log_dbg(cd, "Updating keyslot area [0x%04" PRIx64 "].", area_offset);
275-
/* FIXME: sector_offset should be size_t, fix LUKS_encrypt... accordingly */
276-
r = luks2_encrypt_to_storage(AfKey, AFEKSize, cipher, cipher_mode,
277-
derived_vk, (unsigned)(area_offset / SECTOR_SIZE), cd);
247+
248+
r = luks2_encrypt_to_storage(AfKey, AFEKSize, cipher, derived_vk, area_offset, cd);
278249
out:
279250
crypt_safe_free(AfKey);
280251
crypt_safe_free(derived_key);
@@ -293,8 +264,8 @@ static int luks2_keyslot_get_key(struct crypt_device *cd,
293264
struct crypt_pbkdf_type pbkdf;
294265
char *AfKey = NULL;
295266
size_t AFEKSize;
296-
const char *af_hash = NULL;
297-
char *salt = NULL, cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
267+
const char *af_hash = NULL, *cipher;
268+
char *salt = NULL;
298269
json_object *jobj2, *jobj_af, *jobj_area;
299270
uint64_t area_offset;
300271
size_t keyslot_key_len;
@@ -317,9 +288,8 @@ static int luks2_keyslot_get_key(struct crypt_device *cd,
317288

318289
if (!json_object_object_get_ex(jobj_area, "encryption", &jobj2))
319290
return -EINVAL;
320-
r = crypt_parse_name_and_mode(json_object_get_string(jobj2), cipher, NULL, cipher_mode);
321-
if (r < 0)
322-
return r;
291+
292+
cipher = json_object_get_string(jobj2);
323293

324294
/* Allow only empty passphrase with null cipher */
325295
if (crypt_is_cipher_null(cipher) && passwordLen)
@@ -380,10 +350,8 @@ static int luks2_keyslot_get_key(struct crypt_device *cd,
380350
}
381351

382352
log_dbg(cd, "Reading keyslot area [0x%04" PRIx64 "].", area_offset);
383-
/* FIXME: sector_offset should be size_t, fix LUKS_decrypt... accordingly */
384-
r = luks2_decrypt_from_storage(AfKey, AFEKSize, cipher, cipher_mode,
385-
derived_vk, (unsigned)(area_offset / SECTOR_SIZE), cd);
386353

354+
r = luks2_decrypt_from_storage(AfKey, AFEKSize, cipher, derived_vk, area_offset, cd);
387355
if (r == 0) {
388356
r = crypt_hash_size(af_hash);
389357
if (r < 0)

lib/utils_storage_wrappers.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,10 @@ int crypt_storage_wrapper_init(struct crypt_device *cd,
175175
goto err;
176176
}
177177

178-
w->dev_fd = device_open(cd, device, open_flags);
178+
if (flags & CSW_OPEN_LOCKED)
179+
w->dev_fd = device_open_locked(cd, device, open_flags);
180+
else
181+
w->dev_fd = device_open(cd, device, open_flags);
179182
if (w->dev_fd < 0) {
180183
r = -EINVAL;
181184
goto err;

lib/utils_storage_wrappers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct crypt_device;
2121
#define CSW_DISABLE_DMCRYPT (1 << 1)
2222
#define CSW_OPEN_READONLY (1 << 2)
2323
#define CSW_LARGE_IV (1 << 3)
24+
#define CSW_OPEN_LOCKED (1 << 4)
2425

2526
typedef enum {
2627
NONE = 0,

0 commit comments

Comments
 (0)