Parse compat values from LUKS2 default segment encryption.

We used to preset compat cipher and cipher_mode values during
crypt_format() or crypt_load(). Since we can change 'default segment'
dynamically during reencryption (encryption, decryption included) we
need to parse those values from default segment json encryption field
each time crypt_get_cipher() or crypt_get_cipher_mode() is called.
This commit is contained in:
Ondrej Kozina
2018-10-22 13:53:13 +02:00
committed by Milan Broz
parent 493e8580d6
commit 9e7f9f3471

View File

@@ -63,8 +63,8 @@ struct crypt_device {
} luks1; } luks1;
struct { /* used in CRYPT_LUKS2 */ struct { /* used in CRYPT_LUKS2 */
struct luks2_hdr hdr; struct luks2_hdr hdr;
char *cipher; /* only for compatibility, segment 0 */ char cipher[MAX_CIPHER_LEN]; /* only for compatibility */
char *cipher_mode; /* only for compatibility, segment 0 */ char cipher_mode[MAX_CIPHER_LEN]; /* only for compatibility */
} luks2; } luks2;
struct { /* used in CRYPT_PLAIN */ struct { /* used in CRYPT_PLAIN */
struct crypt_params_plain hdr; struct crypt_params_plain hdr;
@@ -649,8 +649,7 @@ struct crypt_pbkdf_type *crypt_get_pbkdf(struct crypt_device *cd)
static int _crypt_load_luks2(struct crypt_device *cd, int reload, int repair) static int _crypt_load_luks2(struct crypt_device *cd, int reload, int repair)
{ {
int r; int r;
char tmp_cipher[MAX_CIPHER_LEN], tmp_cipher_mode[MAX_CIPHER_LEN], char *type = NULL;
*cipher = NULL, *cipher_mode = NULL, *type = NULL;
struct luks2_hdr hdr2 = {}; struct luks2_hdr hdr2 = {};
log_dbg("%soading LUKS2 header (repair %sabled).", reload ? "Rel" : "L", repair ? "en" : "dis"); log_dbg("%soading LUKS2 header (repair %sabled).", reload ? "Rel" : "L", repair ? "en" : "dis");
@@ -664,43 +663,22 @@ static int _crypt_load_luks2(struct crypt_device *cd, int reload, int repair)
goto out; goto out;
} }
r = crypt_parse_name_and_mode(LUKS2_get_cipher(&hdr2, CRYPT_DEFAULT_SEGMENT),
tmp_cipher, NULL, tmp_cipher_mode);
if (r < 0) {
log_dbg("Cannot parse cipher and mode from loaded device.");
goto out;
}
cipher = strdup(tmp_cipher);
cipher_mode = strdup(tmp_cipher_mode);
if (!cipher || !cipher_mode) {
r = -ENOMEM;
goto out;
}
if (verify_pbkdf_params(cd, &cd->pbkdf)) { if (verify_pbkdf_params(cd, &cd->pbkdf)) {
r = init_pbkdf_type(cd, NULL, CRYPT_LUKS2); r = init_pbkdf_type(cd, NULL, CRYPT_LUKS2);
if (r) if (r)
goto out; goto out;
} }
if (reload) { if (reload)
LUKS2_hdr_free(&cd->u.luks2.hdr); LUKS2_hdr_free(&cd->u.luks2.hdr);
free(cd->u.luks2.cipher); else
free(cd->u.luks2.cipher_mode);
} else
cd->type = type; cd->type = type;
r = 0; r = 0;
memcpy(&cd->u.luks2.hdr, &hdr2, sizeof(hdr2)); memcpy(&cd->u.luks2.hdr, &hdr2, sizeof(hdr2));
/* Save cipher and mode, compatibility only. */
cd->u.luks2.cipher = cipher;
cd->u.luks2.cipher_mode = cipher_mode;
out: out:
if (r) { if (r) {
free(cipher);
free(cipher_mode);
free(type); free(type);
LUKS2_hdr_free(&hdr2); LUKS2_hdr_free(&hdr2);
} }
@@ -1019,8 +997,6 @@ static void crypt_free_type(struct crypt_device *cd)
free(cd->u.plain.cipher_mode); free(cd->u.plain.cipher_mode);
} else if (isLUKS2(cd->type)) { } else if (isLUKS2(cd->type)) {
LUKS2_hdr_free(&cd->u.luks2.hdr); LUKS2_hdr_free(&cd->u.luks2.hdr);
free(cd->u.luks2.cipher);
free(cd->u.luks2.cipher_mode);
} else if (isLOOPAES(cd->type)) { } else if (isLOOPAES(cd->type)) {
free(CONST_CAST(void*)cd->u.loopaes.hdr.hash); free(CONST_CAST(void*)cd->u.loopaes.hdr.hash);
free(cd->u.loopaes.cipher); free(cd->u.loopaes.cipher);
@@ -1574,17 +1550,10 @@ static int _crypt_format_luks2(struct crypt_device *cd,
&required_alignment, &required_alignment,
&alignment_offset, DEFAULT_DISK_ALIGNMENT); &alignment_offset, DEFAULT_DISK_ALIGNMENT);
/* Save cipher and mode, compatibility only. */
cd->u.luks2.cipher = strdup(cipher);
cd->u.luks2.cipher_mode = strdup(cipher_mode);
if (!cd->u.luks2.cipher || !cd->u.luks2.cipher_mode) {
r = -ENOMEM;
goto out;
}
/* FIXME: we have no way how to check AEAD ciphers, /* FIXME: we have no way how to check AEAD ciphers,
* only length preserving mode or authenc() composed modes */ * only length preserving mode or authenc() composed modes */
if ((!integrity || integrity_key_size) && !LUKS2_keyslot_cipher_incompatible(cd)) { if ((!integrity || integrity_key_size) && !crypt_cipher_wrapped_key(cipher) &&
!INTEGRITY_tag_size(cd, NULL, cipher, cipher_mode)) {
r = LUKS_check_cipher(cd, volume_key_size - integrity_key_size, r = LUKS_check_cipher(cd, volume_key_size - integrity_key_size,
cipher, cipher_mode); cipher, cipher_mode);
if (r < 0) if (r < 0)
@@ -1659,13 +1628,8 @@ static int _crypt_format_luks2(struct crypt_device *cd,
} }
out: out:
if (r) { if (r)
LUKS2_hdr_free(&cd->u.luks2.hdr); LUKS2_hdr_free(&cd->u.luks2.hdr);
free(cd->u.luks2.cipher);
free(cd->u.luks2.cipher_mode);
cd->u.luks2.cipher = NULL;
cd->u.luks2.cipher_mode = NULL;
}
return r; return r;
} }
@@ -3647,8 +3611,12 @@ const char *crypt_get_cipher(struct crypt_device *cd)
if (isLUKS1(cd->type)) if (isLUKS1(cd->type))
return cd->u.luks1.hdr.cipherName; return cd->u.luks1.hdr.cipherName;
if (isLUKS2(cd->type)) if (isLUKS2(cd->type)) {
if (crypt_parse_name_and_mode(LUKS2_get_cipher(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT),
cd->u.luks2.cipher, NULL, cd->u.luks2.cipher_mode))
return NULL;
return cd->u.luks2.cipher; return cd->u.luks2.cipher;
}
if (isLOOPAES(cd->type)) if (isLOOPAES(cd->type))
return cd->u.loopaes.cipher; return cd->u.loopaes.cipher;
@@ -3673,8 +3641,12 @@ const char *crypt_get_cipher_mode(struct crypt_device *cd)
if (isLUKS1(cd->type)) if (isLUKS1(cd->type))
return cd->u.luks1.hdr.cipherMode; return cd->u.luks1.hdr.cipherMode;
if (isLUKS2(cd->type)) if (isLUKS2(cd->type)) {
if (crypt_parse_name_and_mode(LUKS2_get_cipher(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT),
cd->u.luks2.cipher, NULL, cd->u.luks2.cipher_mode))
return NULL;
return cd->u.luks2.cipher_mode; return cd->u.luks2.cipher_mode;
}
if (isLOOPAES(cd->type)) if (isLOOPAES(cd->type))
return cd->u.loopaes.cipher_mode; return cd->u.loopaes.cipher_mode;