From: Lennart Poettering Date: Tue, 28 Sep 2021 10:11:53 +0000 (+0200) Subject: cryptsetup: handle more gracefully if "keyslots" LUKS2 JSON header field is invalid X-Git-Tag: v250-rc1~607 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1641c2b1123617f7be249bb7f2b2c408defb3b96;p=thirdparty%2Fsystemd.git cryptsetup: handle more gracefully if "keyslots" LUKS2 JSON header field is invalid The field is not owned by us (even though is in our JSON objects) but by the LUKS2 spec. Hence let's handle this a bit more gracefully: let's not get confused by it, just warn and skip over it. Fixes: #20847 --- diff --git a/src/cryptenroll/cryptenroll-tpm2.c b/src/cryptenroll/cryptenroll-tpm2.c index 23deeed272d..801014af11d 100644 --- a/src/cryptenroll/cryptenroll-tpm2.c +++ b/src/cryptenroll/cryptenroll-tpm2.c @@ -34,8 +34,12 @@ static int search_policy_hash( return log_error_errno(r, "Failed to read JSON token data off disk: %m"); keyslot = cryptsetup_get_keyslot_from_token(v); - if (keyslot < 0) - return log_error_errno(keyslot, "Failed to determine keyslot of JSON token: %m"); + if (keyslot < 0) { + /* Handle parsing errors of the keyslots field gracefully, since it's not 'owned' by + * us, but by the LUKS2 spec */ + log_warning_errno(keyslot, "Failed to determine keyslot of JSON token %i, skipping: %m", token); + continue; + } w = json_variant_by_key(v, "tpm2-policy-hash"); if (!w || !json_variant_is_string(w)) diff --git a/src/cryptsetup/cryptsetup-fido2.c b/src/cryptsetup/cryptsetup-fido2.c index 74b6bff1aa0..3a870016d31 100644 --- a/src/cryptsetup/cryptsetup-fido2.c +++ b/src/cryptsetup/cryptsetup-fido2.c @@ -133,6 +133,7 @@ int find_fido2_auto_data( for (int token = 0; token < sym_crypt_token_max(CRYPT_LUKS2); token ++) { _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; JsonVariant *w; + int ks; r = cryptsetup_get_token_as_json(cd, token, "systemd-fido2", &v); if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE)) @@ -140,10 +141,21 @@ int find_fido2_auto_data( if (r < 0) return log_error_errno(r, "Failed to read JSON token data off disk: %m"); + ks = cryptsetup_get_keyslot_from_token(v); + if (ks < 0) { + /* Handle parsing errors of the keyslots field gracefully, since it's not 'owned' by + * us, but by the LUKS2 spec */ + log_warning_errno(ks, "Failed to extract keyslot index from FIDO2 JSON data token %i, skipping: %m", token); + continue; + } + if (cid) return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ), "Multiple FIDO2 tokens enrolled, cannot automatically determine token."); + assert(keyslot < 0); + keyslot = ks; + w = json_variant_by_key(v, "fido2-credential"); if (!w || !json_variant_is_string(w)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), @@ -165,11 +177,6 @@ int find_fido2_auto_data( if (r < 0) return log_error_errno(r, "Failed to decode base64 encoded salt."); - assert(keyslot < 0); - keyslot = cryptsetup_get_keyslot_from_token(v); - if (keyslot < 0) - return log_error_errno(keyslot, "Failed to extract keyslot index from FIDO2 JSON data: %m"); - w = json_variant_by_key(v, "fido2-rp"); if (w) { /* The "rp" field is optional. */ diff --git a/src/cryptsetup/cryptsetup-pkcs11.c b/src/cryptsetup/cryptsetup-pkcs11.c index 31960de5970..f991389aa5b 100644 --- a/src/cryptsetup/cryptsetup-pkcs11.c +++ b/src/cryptsetup/cryptsetup-pkcs11.c @@ -111,6 +111,7 @@ int find_pkcs11_auto_data( for (int token = 0; token < sym_crypt_token_max(CRYPT_LUKS2); token++) { _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; JsonVariant *w; + int ks; r = cryptsetup_get_token_as_json(cd, token, "systemd-pkcs11", &v); if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE)) @@ -118,10 +119,21 @@ int find_pkcs11_auto_data( if (r < 0) return log_error_errno(r, "Failed to read JSON token data off disk: %m"); + ks = cryptsetup_get_keyslot_from_token(v); + if (ks < 0) { + /* Handle parsing errors of the keyslots field gracefully, since it's not 'owned' by + * us, but by the LUKS2 spec */ + log_warning_errno(ks, "Failed to extract keyslot index from PKCS#11 JSON data token %i, skipping: %m", token); + continue; + } + if (uri) return log_error_errno(SYNTHETIC_ERRNO(ENOTUNIQ), "Multiple PKCS#11 tokens enrolled, cannot automatically determine token."); + assert(keyslot < 0); + keyslot = ks; + w = json_variant_by_key(v, "pkcs11-uri"); if (!w || !json_variant_is_string(w)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), @@ -145,11 +157,6 @@ int find_pkcs11_auto_data( r = unbase64mem(json_variant_string(w), SIZE_MAX, &key, &key_size); if (r < 0) return log_error_errno(r, "Failed to decode base64 encoded key."); - - assert(keyslot < 0); - keyslot = cryptsetup_get_keyslot_from_token(v); - if (keyslot < 0) - return log_error_errno(keyslot, "Failed to extract keyslot index from PKCS#11 JSON data: %m"); } if (!uri) diff --git a/src/cryptsetup/cryptsetup-tpm2.c b/src/cryptsetup/cryptsetup-tpm2.c index 4d95dacca5a..87572129691 100644 --- a/src/cryptsetup/cryptsetup-tpm2.c +++ b/src/cryptsetup/cryptsetup-tpm2.c @@ -93,6 +93,7 @@ int find_tpm2_auto_data( for (token = start_token; token < sym_crypt_token_max(CRYPT_LUKS2); token++) { _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; JsonVariant *w, *e; + int ks; r = cryptsetup_get_token_as_json(cd, token, "systemd-tpm2", &v); if (IN_SET(r, -ENOENT, -EINVAL, -EMEDIUMTYPE)) @@ -100,6 +101,14 @@ int find_tpm2_auto_data( if (r < 0) return log_error_errno(r, "Failed to read JSON token data off disk: %m"); + ks = cryptsetup_get_keyslot_from_token(v); + if (ks < 0) { + /* Handle parsing errors of the keyslots field gracefully, since it's not 'owned' by + * us, but by the LUKS2 spec */ + log_warning_errno(ks, "Failed to extract keyslot index from TPM2 JSON data token %i, skipping: %m", token); + continue; + } + w = json_variant_by_key(v, "tpm2-pcrs"); if (!w || !json_variant_is_array(w)) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), @@ -125,6 +134,9 @@ int find_tpm2_auto_data( search_pcr_mask != pcr_mask) /* PCR mask doesn't match what is configured, ignore this entry */ continue; + assert(keyslot < 0); + keyslot = ks; + assert(pcr_bank == UINT16_MAX); assert(primary_alg == TPM2_ALG_ECC); @@ -184,11 +196,6 @@ int find_tpm2_auto_data( return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid base64 data in 'tpm2-policy-hash' field."); - assert(keyslot < 0); - keyslot = cryptsetup_get_keyslot_from_token(v); - if (keyslot < 0) - return log_error_errno(keyslot, "Failed to extract keyslot index from TPM2 JSON data: %m"); - break; }