From 20cc99feb7ec1638fcee1f2f48bb0cd3dae35e7d Mon Sep 17 00:00:00 2001 From: Ingo Franzki Date: Fri, 15 Mar 2024 10:32:01 +0100 Subject: [PATCH] zkey-cryptsetup: Add support for integrity verification pattern in token MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In case the volume is integrity protected, and the integrity algorithm is PHMAC, then the verification-pattern token as well as the reencipher-token contain the verification pattern of the integrity key as well. Signed-off-by: Ingo Franzki Reviewed-by: Finn Callies Signed-off-by: Jan Höppner --- zkey/zkey-cryptsetup.c | 68 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/zkey/zkey-cryptsetup.c b/zkey/zkey-cryptsetup.c index 29cde5c9..5b41471c 100644 --- a/zkey/zkey-cryptsetup.c +++ b/zkey/zkey-cryptsetup.c @@ -48,20 +48,24 @@ #define PAES_VP_TOKEN_NAME "paes-verification-pattern" #define PAES_VP_TOKEN_VP "verification-pattern" +#define PAES_VP_TOKEN_INT_VP "integrity-verification-pattern" #define PAES_REENC_TOKEN_NAME "paes-reencipher" #define PAES_REENC_TOKEN_VP "verification-pattern" +#define PAES_REENC_TOKEN_INT_VP "integrity-verification-pattern" #define PAES_REENC_TOKEN_ORG_SLOT "original-keyslot" #define PAES_REENC_TOKEN_UNB_SLOT "unbound-keyslot" struct reencipher_token { char verification_pattern[VERIFICATION_PATTERN_LEN]; + char int_verification_pattern[VERIFICATION_PATTERN_LEN]; unsigned int original_keyslot; unsigned int unbound_keyslot; }; struct vp_token { char verification_pattern[VERIFICATION_PATTERN_LEN]; + char int_verification_pattern[VERIFICATION_PATTERN_LEN]; }; __attribute__ ((unused)) @@ -998,11 +1002,14 @@ static int get_reencipher_token(struct crypt_device *cd, int token, { json_object *jobj_org_keyslot = NULL; json_object *jobj_unb_keyslot = NULL; + json_object *jobj_int_vp = NULL; json_object *json_token = NULL; json_object *jobj_vp = NULL; const char *temp; int rc; + memset(info, 0, sizeof(*info)); + rc = get_token(cd, token, &json_token); if (rc != 0) return rc; @@ -1026,6 +1033,22 @@ static int get_reencipher_token(struct crypt_device *cd, int token, info->verification_pattern[ sizeof(info->verification_pattern) - 1] = '\0'; + /* integrity-verification-pattern is optional */ + if (json_object_object_get_ex(json_token, PAES_REENC_TOKEN_INT_VP, + &jobj_int_vp)) { + temp = json_object_get_string(jobj_int_vp); + if (temp == NULL) { + warnx("The re-encipher token is incomplete, '%s' is " + "missing", PAES_REENC_TOKEN_INT_VP); + rc = -EINVAL; + goto out; + } + strncpy(info->int_verification_pattern, temp, + sizeof(info->int_verification_pattern)); + info->int_verification_pattern[ + sizeof(info->int_verification_pattern) - 1] = '\0'; + } + if (!json_object_object_get_ex(json_token, PAES_REENC_TOKEN_ORG_SLOT, &jobj_org_keyslot)) { warnx("The re-encipher token is incomplete, '%s' is missing", @@ -1059,8 +1082,10 @@ static int get_reencipher_token(struct crypt_device *cd, int token, } pr_verbose("Re-encipher token: original-keyslot: %d, unbound-keyslot: " - "%d, verification-pattern: %s", info->original_keyslot, - info->unbound_keyslot, info->verification_pattern); + "%d, verification-pattern: %s, " + "integrity-verification-pattern: %s", info->original_keyslot, + info->unbound_keyslot, info->verification_pattern, + info->int_verification_pattern); rc = 0; @@ -1085,8 +1110,10 @@ static int put_reencipher_token(struct crypt_device *cd, int token, int rc; pr_verbose("Re-encipher token: original-keyslot: %d, unbound-keyslot: " - "%d, verification-pattern: %s", info->original_keyslot, - info->unbound_keyslot, info->verification_pattern); + "%d, verification-pattern: %s, " + "integrity-verification-pattern: %s", info->original_keyslot, + info->unbound_keyslot, info->verification_pattern, + info->int_verification_pattern); jobj = json_object_new_object(); json_object_object_add(jobj, "type", @@ -1100,6 +1127,10 @@ static int put_reencipher_token(struct crypt_device *cd, int token, json_object_object_add(jobj, PAES_REENC_TOKEN_VP, json_object_new_string( info->verification_pattern)); + if (strlen(info->int_verification_pattern) > 0) + json_object_object_add(jobj, PAES_REENC_TOKEN_INT_VP, + json_object_new_string( + info->int_verification_pattern)); json_object_object_add(jobj, PAES_REENC_TOKEN_ORG_SLOT, json_object_new_int64(info->original_keyslot)); json_object_object_add(jobj, PAES_REENC_TOKEN_UNB_SLOT, @@ -1128,11 +1159,14 @@ static int put_reencipher_token(struct crypt_device *cd, int token, static int get_vp_token(struct crypt_device *cd, int token, struct vp_token *info) { + json_object *jobj_int_vp = NULL; json_object *json_token = NULL; json_object *jobj_vp = NULL; const char *temp; int rc; + memset(info, 0, sizeof(*info)); + rc = get_token(cd, token, &json_token); if (rc != 0) return rc; @@ -1158,6 +1192,25 @@ static int get_vp_token(struct crypt_device *cd, int token, pr_verbose("Verification-pattern: %s", info->verification_pattern); + /* integrity-verification-pattern is optional */ + if (json_object_object_get_ex(json_token, PAES_VP_TOKEN_INT_VP, + &jobj_int_vp)) { + temp = json_object_get_string(jobj_int_vp); + if (temp == NULL) { + warnx("The verification-pattern token is incomplete, " + "'%s' is missing", PAES_VP_TOKEN_INT_VP); + rc = -EINVAL; + goto out; + } + strncpy(info->int_verification_pattern, temp, + sizeof(info->int_verification_pattern)); + info->int_verification_pattern[ + sizeof(info->int_verification_pattern) - 1] = '\0'; + + pr_verbose("Integrity-verification-pattern: %s", + info->int_verification_pattern); + } + out: if (json_token != NULL) json_object_put(json_token); @@ -1175,6 +1228,8 @@ static int put_vp_token(struct crypt_device *cd, int token, int rc; pr_verbose("Verification-pattern: %s", info->verification_pattern); + pr_verbose("Integrity-verification-pattern: %s", + info->int_verification_pattern); jobj = json_object_new_object(); json_object_object_add(jobj, "type", @@ -1187,6 +1242,11 @@ static int put_vp_token(struct crypt_device *cd, int token, json_object_new_string( info->verification_pattern)); + if (strlen(info->int_verification_pattern) > 0) + json_object_object_add(jobj, PAES_VP_TOKEN_INT_VP, + json_object_new_string( + info->int_verification_pattern)); + rc = crypt_token_json_set(cd, token >= 0 ? token : CRYPT_ANY_TOKEN, json_object_to_json_string_ext(jobj, JSON_C_TO_STRING_PLAIN));