Add --integrity-key-size option to cryptsetup.

This patch adds support for --integrity-key-size option that can be used
to setup non-standard HMAC integrity key size.
This commit is contained in:
Milan Broz
2024-11-24 14:39:22 +01:00
parent 7b5ac650e5
commit 491f31c4d4
7 changed files with 43 additions and 12 deletions

View File

@@ -594,7 +594,7 @@ struct crypt_params_integrity {
uint32_t sector_size; /**< sector size in bytes */ uint32_t sector_size; /**< sector size in bytes */
uint32_t buffer_sectors; /**< number of sectors in one buffer */ uint32_t buffer_sectors; /**< number of sectors in one buffer */
const char *integrity; /**< integrity algorithm, NULL for LUKS2 */ const char *integrity; /**< integrity algorithm, NULL for LUKS2 */
uint32_t integrity_key_size; /**< integrity key size in bytes, info only, 0 for LUKS2 */ uint32_t integrity_key_size; /**< integrity key size in bytes, info only */
const char *journal_integrity; /**< journal integrity algorithm */ const char *journal_integrity; /**< journal integrity algorithm */
const char *journal_integrity_key; /**< journal integrity key, only for crypt_load */ const char *journal_integrity_key; /**< journal integrity key, only for crypt_load */

View File

@@ -1892,8 +1892,7 @@ static int LUKS2_check_encryption_params(struct crypt_device *cd,
const char **ret_integrity, const char **ret_integrity,
size_t *ret_integrity_key_size) size_t *ret_integrity_key_size)
{ {
int r; int r, integrity_key_size = 0;
size_t integrity_key_size = 0;
assert(cipher); assert(cipher);
assert(cipher_mode); assert(cipher_mode);

View File

@@ -95,7 +95,7 @@ int crypt_parse_hash_integrity_mode(const char *s, char *integrity)
} }
int crypt_parse_integrity_mode(const char *s, char *integrity, int crypt_parse_integrity_mode(const char *s, char *integrity,
int *integrity_key_size) int *integrity_key_size, int required_key_size)
{ {
int ks = 0, r = 0; int ks = 0, r = 0;
@@ -108,18 +108,22 @@ int crypt_parse_integrity_mode(const char *s, char *integrity,
!strcmp(s, "none")) { !strcmp(s, "none")) {
strncpy(integrity, s, MAX_CIPHER_LEN); strncpy(integrity, s, MAX_CIPHER_LEN);
ks = 0; ks = 0;
if (required_key_size != ks)
r = -EINVAL;
} else if (!strcmp(s, "hmac-sha1")) { } else if (!strcmp(s, "hmac-sha1")) {
strncpy(integrity, "hmac(sha1)", MAX_CIPHER_LEN); strncpy(integrity, "hmac(sha1)", MAX_CIPHER_LEN);
ks = 20; ks = required_key_size ?: 20;
} else if (!strcmp(s, "hmac-sha256")) { } else if (!strcmp(s, "hmac-sha256")) {
strncpy(integrity, "hmac(sha256)", MAX_CIPHER_LEN); strncpy(integrity, "hmac(sha256)", MAX_CIPHER_LEN);
ks = 32; ks = required_key_size ?: 32;
} else if (!strcmp(s, "hmac-sha512")) { } else if (!strcmp(s, "hmac-sha512")) {
ks = 64;
strncpy(integrity, "hmac(sha512)", MAX_CIPHER_LEN); strncpy(integrity, "hmac(sha512)", MAX_CIPHER_LEN);
ks = required_key_size ?: 64;
} else if (!strcmp(s, "cmac-aes")) { } else if (!strcmp(s, "cmac-aes")) {
ks = 16;
strncpy(integrity, "cmac(aes)", MAX_CIPHER_LEN); strncpy(integrity, "cmac(aes)", MAX_CIPHER_LEN);
ks = 16;
if (required_key_size && required_key_size != ks)
r = -EINVAL;
} else } else
r = -EINVAL; r = -EINVAL;

View File

@@ -28,7 +28,7 @@ int crypt_parse_name_and_mode(const char *s, char *cipher,
int *key_nums, char *cipher_mode); int *key_nums, char *cipher_mode);
int crypt_parse_hash_integrity_mode(const char *s, char *integrity); int crypt_parse_hash_integrity_mode(const char *s, char *integrity);
int crypt_parse_integrity_mode(const char *s, char *integrity, int crypt_parse_integrity_mode(const char *s, char *integrity,
int *integrity_key_size); int *integrity_key_size, int required_key_size);
int crypt_parse_pbkdf(const char *s, const char **pbkdf); int crypt_parse_pbkdf(const char *s, const char **pbkdf);
ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc); ssize_t crypt_hex_to_bytes(const char *hex, char **result, int safe_alloc);

View File

@@ -376,6 +376,12 @@ option).
For more info, see _AUTHENTICATED DISK ENCRYPTION_ section in *cryptsetup*(8). For more info, see _AUTHENTICATED DISK ENCRYPTION_ section in *cryptsetup*(8).
endif::[] endif::[]
ifdef::ACTION_LUKSFORMAT[]
*--integrity-key-size BYTES*::
The size of the data integrity key. Configurable only for HMAC integrity.
Default integrity key size is set to the same as hash output length.
endif::[]
ifdef::ACTION_LUKSFORMAT[] ifdef::ACTION_LUKSFORMAT[]
*--integrity-legacy-padding*:: *--integrity-legacy-padding*::
Use inefficient legacy padding. Use inefficient legacy padding.

View File

@@ -1522,7 +1522,7 @@ static int strcmp_or_null(const char *str, const char *expected)
int luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_passwordLen) int luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_passwordLen)
{ {
bool wipe_signatures = false; bool wipe_signatures = false;
int encrypt_type, r = -EINVAL, keysize, integrity_keysize = 0, fd, created = 0; int encrypt_type, r = -EINVAL, keysize, integrity_keysize = 0, required_integrity_key_size = 0, fd, created = 0;
struct stat st; struct stat st;
const char *header_device, *type; const char *header_device, *type;
char *msg = NULL, *key = NULL, *password = NULL; char *msg = NULL, *key = NULL, *password = NULL;
@@ -1544,6 +1544,7 @@ int luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_password
struct crypt_params_hw_opal opal_params = { struct crypt_params_hw_opal opal_params = {
.user_key_size = DEFAULT_LUKS1_KEYBITS / 8 .user_key_size = DEFAULT_LUKS1_KEYBITS / 8
}; };
struct crypt_params_integrity integrity_params = {};
void *params; void *params;
struct crypt_keyslot_context *kc = NULL, *new_kc = NULL; struct crypt_keyslot_context *kc = NULL, *new_kc = NULL;
@@ -1614,13 +1615,23 @@ int luksFormat(struct crypt_device **r_cd, char **r_password, size_t *r_password
} }
if (ARG_SET(OPT_INTEGRITY_ID)) { if (ARG_SET(OPT_INTEGRITY_ID)) {
r = crypt_parse_integrity_mode(ARG_STR(OPT_INTEGRITY_ID), integrity, &integrity_keysize); if (ARG_SET(OPT_INTEGRITY_KEY_SIZE_ID))
required_integrity_key_size = ARG_UINT32(OPT_INTEGRITY_KEY_SIZE_ID) / 8;
r = crypt_parse_integrity_mode(ARG_STR(OPT_INTEGRITY_ID), integrity,
&integrity_keysize, required_integrity_key_size);
if (r < 0) { if (r < 0) {
log_err(_("No known integrity specification pattern detected.")); log_err(_("No known integrity specification pattern detected."));
if (ARG_SET(OPT_INTEGRITY_KEY_SIZE_ID) && required_integrity_key_size != integrity_keysize)
log_err(_("Cannot use specified integrity key size."));
goto out; goto out;
} }
params2.integrity = integrity; params2.integrity = integrity;
/* FIXME: we use default integrity_params (set to NULL) */ /* FIXME: we use default integrity_params except key size */
if (required_integrity_key_size) {
params2.integrity_params = &integrity_params;
integrity_params.integrity_key_size = integrity_keysize;
}
} }
/* Never call pwquality if using null cipher */ /* Never call pwquality if using null cipher */
@@ -3715,6 +3726,15 @@ static void basic_options_cb(poptContext popt_context,
_("Key size must be a multiple of 8 bits"), _("Key size must be a multiple of 8 bits"),
poptGetInvocationName(popt_context)); poptGetInvocationName(popt_context));
break; break;
case OPT_INTEGRITY_KEY_SIZE_ID:
if (ARG_UINT32(OPT_INTEGRITY_KEY_SIZE_ID) == 0)
usage(popt_context, EXIT_FAILURE, poptStrerror(POPT_ERROR_BADNUMBER),
poptGetInvocationName(popt_context));
if (ARG_UINT32(OPT_INTEGRITY_KEY_SIZE_ID) % 8)
usage(popt_context, EXIT_FAILURE,
_("Key size must be a multiple of 8 bits"),
poptGetInvocationName(popt_context));
break;
case OPT_KEY_SLOT_ID: case OPT_KEY_SLOT_ID:
check_key_slot_value(popt_context); check_key_slot_value(popt_context);
break; break;

View File

@@ -70,6 +70,8 @@ ARG(OPT_INIT_ONLY, '\0', POPT_ARG_NONE, N_("Initialize LUKS2 reencryption in met
ARG(OPT_INTEGRITY, 'I', POPT_ARG_STRING, N_("Data integrity algorithm (LUKS2 only)"), NULL, CRYPT_ARG_STRING, {}, OPT_INTEGRITY_ACTIONS) ARG(OPT_INTEGRITY, 'I', POPT_ARG_STRING, N_("Data integrity algorithm (LUKS2 only)"), NULL, CRYPT_ARG_STRING, {}, OPT_INTEGRITY_ACTIONS)
ARG(OPT_INTEGRITY_KEY_SIZE, '\0', POPT_ARG_STRING, N_("The size of the data integrity key"), N_("BITS"), CRYPT_ARG_UINT32, {}, {})
ARG(OPT_INTEGRITY_LEGACY_PADDING,'\0', POPT_ARG_NONE, N_("Use inefficient legacy padding (old kernels)"), NULL, CRYPT_ARG_BOOL, {}, {}) ARG(OPT_INTEGRITY_LEGACY_PADDING,'\0', POPT_ARG_NONE, N_("Use inefficient legacy padding (old kernels)"), NULL, CRYPT_ARG_BOOL, {}, {})
ARG(OPT_INTEGRITY_NO_JOURNAL, '\0', POPT_ARG_NONE, N_("Disable journal for integrity device"), NULL, CRYPT_ARG_BOOL, {}, {}) ARG(OPT_INTEGRITY_NO_JOURNAL, '\0', POPT_ARG_NONE, N_("Disable journal for integrity device"), NULL, CRYPT_ARG_BOOL, {}, {})