Skip to content

Commit

Permalink
cryptsetup: handle more gracefully if "keyslots" LUKS2 JSON header fi…
Browse files Browse the repository at this point in the history
…eld 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
  • Loading branch information
poettering committed Sep 28, 2021
1 parent 5918a93 commit 1641c2b
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 17 deletions.
8 changes: 6 additions & 2 deletions src/cryptenroll/cryptenroll-tpm2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
17 changes: 12 additions & 5 deletions src/cryptsetup/cryptsetup-fido2.c
Original file line number Diff line number Diff line change
Expand Up @@ -133,17 +133,29 @@ 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))
continue;
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),
Expand All @@ -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. */
Expand Down
17 changes: 12 additions & 5 deletions src/cryptsetup/cryptsetup-pkcs11.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,17 +111,29 @@ 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))
continue;
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),
Expand All @@ -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)
Expand Down
17 changes: 12 additions & 5 deletions src/cryptsetup/cryptsetup-tpm2.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,22 @@ 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))
continue;
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),
Expand All @@ -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);

Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit 1641c2b

Please sign in to comment.