mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-02-26 09:57:26 +03:00
cryptenroll: support listing and wiping tokens
This commit is contained in:
parent
5e521624f2
commit
d2fafc423d
@ -2434,13 +2434,18 @@ if conf.get('HAVE_LIBCRYPTSETUP') == 1
|
|||||||
|
|
||||||
systemd_cryptenroll_sources = files('''
|
systemd_cryptenroll_sources = files('''
|
||||||
src/cryptenroll/cryptenroll-fido2.h
|
src/cryptenroll/cryptenroll-fido2.h
|
||||||
|
src/cryptenroll/cryptenroll-list.c
|
||||||
|
src/cryptenroll/cryptenroll-list.h
|
||||||
src/cryptenroll/cryptenroll-password.c
|
src/cryptenroll/cryptenroll-password.c
|
||||||
src/cryptenroll/cryptenroll-password.h
|
src/cryptenroll/cryptenroll-password.h
|
||||||
src/cryptenroll/cryptenroll-pkcs11.h
|
src/cryptenroll/cryptenroll-pkcs11.h
|
||||||
src/cryptenroll/cryptenroll-recovery.c
|
src/cryptenroll/cryptenroll-recovery.c
|
||||||
src/cryptenroll/cryptenroll-recovery.h
|
src/cryptenroll/cryptenroll-recovery.h
|
||||||
src/cryptenroll/cryptenroll-tpm2.h
|
src/cryptenroll/cryptenroll-tpm2.h
|
||||||
|
src/cryptenroll/cryptenroll-wipe.c
|
||||||
|
src/cryptenroll/cryptenroll-wipe.h
|
||||||
src/cryptenroll/cryptenroll.c
|
src/cryptenroll/cryptenroll.c
|
||||||
|
src/cryptenroll/cryptenroll.h
|
||||||
'''.split())
|
'''.split())
|
||||||
|
|
||||||
if conf.get('HAVE_P11KIT') == 1 and conf.get('HAVE_OPENSSL') == 1
|
if conf.get('HAVE_P11KIT') == 1 and conf.get('HAVE_OPENSSL') == 1
|
||||||
|
126
src/cryptenroll/cryptenroll-list.c
Normal file
126
src/cryptenroll/cryptenroll-list.c
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include "cryptenroll-list.h"
|
||||||
|
#include "cryptenroll.h"
|
||||||
|
#include "format-table.h"
|
||||||
|
#include "parse-util.h"
|
||||||
|
|
||||||
|
int list_enrolled(struct crypt_device *cd) {
|
||||||
|
|
||||||
|
struct keyslot_metadata {
|
||||||
|
int slot;
|
||||||
|
const char *type;
|
||||||
|
} *keyslot_metadata = NULL;
|
||||||
|
size_t n_keyslot_metadata = 0, n_keyslot_metadata_allocated = 0;
|
||||||
|
_cleanup_(table_unrefp) Table *t = NULL;
|
||||||
|
int slot_max, r;
|
||||||
|
TableCell *cell;
|
||||||
|
|
||||||
|
assert(cd);
|
||||||
|
|
||||||
|
/* First step, find out all currently used slots */
|
||||||
|
assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
|
||||||
|
for (int slot = 0; slot < slot_max; slot++) {
|
||||||
|
crypt_keyslot_info status;
|
||||||
|
|
||||||
|
status = crypt_keyslot_status(cd, slot);
|
||||||
|
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!GREEDY_REALLOC(keyslot_metadata, n_keyslot_metadata_allocated, n_keyslot_metadata+1))
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
keyslot_metadata[n_keyslot_metadata++] = (struct keyslot_metadata) {
|
||||||
|
.slot = slot,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Second step, enumerate through all tokens, and update the slot table, indicating what kind of
|
||||||
|
* token they are assigned to */
|
||||||
|
for (int token = 0; token < LUKS2_TOKENS_MAX; token++) {
|
||||||
|
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||||
|
const char *type;
|
||||||
|
JsonVariant *w, *z;
|
||||||
|
EnrollType et;
|
||||||
|
|
||||||
|
r = cryptsetup_get_token_as_json(cd, token, NULL, &v);
|
||||||
|
if (IN_SET(r, -ENOENT, -EINVAL))
|
||||||
|
continue;
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning_errno(r, "Failed to read JSON token data off disk, ignoring: %m");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
w = json_variant_by_key(v, "type");
|
||||||
|
if (!w || !json_variant_is_string(w)) {
|
||||||
|
log_warning("Token JSON data lacks type field, ignoring.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
et = luks2_token_type_from_string(json_variant_string(w));
|
||||||
|
if (et < 0)
|
||||||
|
type = "other";
|
||||||
|
else
|
||||||
|
type = enroll_type_to_string(et);
|
||||||
|
|
||||||
|
w = json_variant_by_key(v, "keyslots");
|
||||||
|
if (!w || !json_variant_is_array(w)) {
|
||||||
|
log_warning("Token JSON data lacks keyslots field, ignoring.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_VARIANT_ARRAY_FOREACH(z, w) {
|
||||||
|
unsigned u;
|
||||||
|
|
||||||
|
if (!json_variant_is_string(z)) {
|
||||||
|
log_warning("Token JSON data's keyslot field is not an array of strings, ignoring.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = safe_atou(json_variant_string(z), &u);
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning_errno(r, "Token JSON data's keyslot filed is not an integer formatted as string, ignoring.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n_keyslot_metadata; i++) {
|
||||||
|
if ((unsigned) keyslot_metadata[i].slot != u)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (keyslot_metadata[i].type) /* Slot claimed multiple times? */
|
||||||
|
keyslot_metadata[i].type = POINTER_MAX;
|
||||||
|
else
|
||||||
|
keyslot_metadata[i].type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally, create a table out of it all */
|
||||||
|
t = table_new("slot", "type");
|
||||||
|
if (!t)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
assert_se(cell = table_get_cell(t, 0, 0));
|
||||||
|
(void) table_set_align_percent(t, cell, 100);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n_keyslot_metadata; i++) {
|
||||||
|
r = table_add_many(
|
||||||
|
t,
|
||||||
|
TABLE_INT, keyslot_metadata[i].slot,
|
||||||
|
TABLE_STRING, keyslot_metadata[i].type == POINTER_MAX ? "conflict" :
|
||||||
|
keyslot_metadata[i].type ?: "password");
|
||||||
|
if (r < 0)
|
||||||
|
return table_log_add_error(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (table_get_rows(t) <= 1) {
|
||||||
|
log_info("No slots found.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = table_print(t, stdout);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to show slot table: %m");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
6
src/cryptenroll/cryptenroll-list.h
Normal file
6
src/cryptenroll/cryptenroll-list.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cryptsetup-util.h"
|
||||||
|
|
||||||
|
int list_enrolled(struct crypt_device *cd);
|
445
src/cryptenroll/cryptenroll-wipe.c
Normal file
445
src/cryptenroll/cryptenroll-wipe.c
Normal file
@ -0,0 +1,445 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
|
||||||
|
#include "cryptenroll-wipe.h"
|
||||||
|
#include "cryptenroll.h"
|
||||||
|
#include "json.h"
|
||||||
|
#include "memory-util.h"
|
||||||
|
#include "parse-util.h"
|
||||||
|
#include "set.h"
|
||||||
|
#include "sort-util.h"
|
||||||
|
|
||||||
|
static int find_all_slots(struct crypt_device *cd, Set *wipe_slots, Set *keep_slots) {
|
||||||
|
int slot_max;
|
||||||
|
|
||||||
|
assert(cd);
|
||||||
|
assert(wipe_slots);
|
||||||
|
assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
|
||||||
|
|
||||||
|
/* Finds all currently assigned slots, and adds them to 'wipe_slots', except if listed already in 'keep_slots' */
|
||||||
|
|
||||||
|
for (int slot = 0; slot < slot_max; slot++) {
|
||||||
|
crypt_keyslot_info status;
|
||||||
|
|
||||||
|
/* No need to check this slot if we already know we want to wipe it or definitely keep it. */
|
||||||
|
if (set_contains(keep_slots, INT_TO_PTR(slot)) ||
|
||||||
|
set_contains(wipe_slots, INT_TO_PTR(slot)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
status = crypt_keyslot_status(cd, slot);
|
||||||
|
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (set_put(wipe_slots, INT_TO_PTR(slot)) < 0)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_empty_passphrase_slots(struct crypt_device *cd, Set *wipe_slots, Set *keep_slots) {
|
||||||
|
size_t vks;
|
||||||
|
int r, slot_max;
|
||||||
|
|
||||||
|
assert(cd);
|
||||||
|
assert(wipe_slots);
|
||||||
|
assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
|
||||||
|
|
||||||
|
/* Finds all slots with an empty passphrase assigned (i.e. "") and adds them to 'wipe_slots', except
|
||||||
|
* if listed already in 'keep_slots' */
|
||||||
|
|
||||||
|
r = crypt_get_volume_key_size(cd);
|
||||||
|
if (r <= 0)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to determine LUKS volume key size");
|
||||||
|
vks = (size_t) r;
|
||||||
|
|
||||||
|
for (int slot = 0; slot < slot_max; slot++) {
|
||||||
|
_cleanup_(erase_and_freep) char *vk = NULL;
|
||||||
|
crypt_keyslot_info status;
|
||||||
|
|
||||||
|
/* No need to check this slot if we already know we want to wipe it or definitely keep it. */
|
||||||
|
if (set_contains(keep_slots, INT_TO_PTR(slot)) ||
|
||||||
|
set_contains(wipe_slots, INT_TO_PTR(slot)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
status = crypt_keyslot_status(cd, slot);
|
||||||
|
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
vk = malloc(vks);
|
||||||
|
if (!vk)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
r = crypt_volume_key_get(cd, slot, vk, &vks, "", 0);
|
||||||
|
if (r < 0) {
|
||||||
|
log_debug_errno(r, "Failed to acquire volume key from slot %i with empty password, ignoring: %m", slot);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set_put(wipe_slots, INT_TO_PTR(r)) < 0)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_slots_by_mask(
|
||||||
|
struct crypt_device *cd,
|
||||||
|
Set *wipe_slots,
|
||||||
|
Set *keep_slots,
|
||||||
|
unsigned by_mask) {
|
||||||
|
|
||||||
|
_cleanup_(set_freep) Set *listed_slots = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(cd);
|
||||||
|
assert(wipe_slots);
|
||||||
|
|
||||||
|
if (by_mask == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Find all slots that are associated with a token of a type in the specified token type mask */
|
||||||
|
|
||||||
|
for (int token = 0; token < LUKS2_TOKENS_MAX; token++) {
|
||||||
|
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||||
|
JsonVariant *w, *z;
|
||||||
|
EnrollType t;
|
||||||
|
|
||||||
|
r = cryptsetup_get_token_as_json(cd, token, NULL, &v);
|
||||||
|
if (IN_SET(r, -ENOENT, -EINVAL))
|
||||||
|
continue;
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning_errno(r, "Failed to read JSON token data off disk, ignoring: %m");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
w = json_variant_by_key(v, "type");
|
||||||
|
if (!w || !json_variant_is_string(w)) {
|
||||||
|
log_warning("Token JSON data lacks type field, ignoring.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
t = luks2_token_type_from_string(json_variant_string(w));
|
||||||
|
|
||||||
|
w = json_variant_by_key(v, "keyslots");
|
||||||
|
if (!w || !json_variant_is_array(w)) {
|
||||||
|
log_warning("Token JSON data lacks keyslots field, ignoring.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSON_VARIANT_ARRAY_FOREACH(z, w) {
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
if (!json_variant_is_string(z)) {
|
||||||
|
log_warning("Token JSON data's keyslot field is not an array of strings, ignoring.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = safe_atoi(json_variant_string(z), &slot);
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning_errno(r, "Token JSON data's keyslot filed is not an integer formatted as string, ignoring.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t >= 0 && (by_mask & (1U << t)) != 0) {
|
||||||
|
/* Selected by token type */
|
||||||
|
if (set_put(wipe_slots, INT_TO_PTR(slot)) < 0)
|
||||||
|
return log_oom();
|
||||||
|
} else if ((by_mask & (1U << ENROLL_PASSWORD)) != 0) {
|
||||||
|
/* If we shall remove all plain password slots, let's maintain a list of
|
||||||
|
* slots that are listed in any tokens, since those are *NOT* plain
|
||||||
|
* passwords */
|
||||||
|
if (set_ensure_allocated(&listed_slots, NULL) < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
if (set_put(listed_slots, INT_TO_PTR(slot)) < 0)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "password" slots are those which have no token assigned. If we shall remove those, iterate through
|
||||||
|
* all slots and mark those for wiping that weren't listed in any token */
|
||||||
|
if ((by_mask & (1U << ENROLL_PASSWORD)) != 0) {
|
||||||
|
int slot_max;
|
||||||
|
|
||||||
|
assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
|
||||||
|
|
||||||
|
for (int slot = 0; slot < slot_max; slot++) {
|
||||||
|
crypt_keyslot_info status;
|
||||||
|
|
||||||
|
/* No need to check this slot if we already know we want to wipe it or definitely keep it. */
|
||||||
|
if (set_contains(keep_slots, INT_TO_PTR(slot)) ||
|
||||||
|
set_contains(wipe_slots, INT_TO_PTR(slot)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (set_contains(listed_slots, INT_TO_PTR(slot))) /* This has a token, hence is not a password. */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
status = crypt_keyslot_status(cd, slot);
|
||||||
|
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST)) /* Not actually assigned? */
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Finally, we found a password, add it to the list of slots to wipe */
|
||||||
|
if (set_put(wipe_slots, INT_TO_PTR(slot)) < 0)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_slot_tokens(struct crypt_device *cd, Set *wipe_slots, Set *keep_slots, Set *wipe_tokens) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(cd);
|
||||||
|
assert(wipe_slots);
|
||||||
|
assert(keep_slots);
|
||||||
|
assert(wipe_tokens);
|
||||||
|
|
||||||
|
/* Find all tokens matching the slots we want to wipe, so that we can wipe them too. Also, for update
|
||||||
|
* the slots sets according to the token data: add any other slots listed in the tokens we act on. */
|
||||||
|
|
||||||
|
for (int token = 0; token < LUKS2_TOKENS_MAX; token++) {
|
||||||
|
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
|
||||||
|
bool shall_wipe = false;
|
||||||
|
JsonVariant *w, *z;
|
||||||
|
|
||||||
|
r = cryptsetup_get_token_as_json(cd, token, NULL, &v);
|
||||||
|
if (IN_SET(r, -ENOENT, -EINVAL))
|
||||||
|
continue;
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning_errno(r, "Failed to read JSON token data off disk, ignoring: %m");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
w = json_variant_by_key(v, "keyslots");
|
||||||
|
if (!w || !json_variant_is_array(w)) {
|
||||||
|
log_warning("Token JSON data lacks keyslots field, ignoring.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Go through the slots associated with this token: if we shall keep any slot of them, the token shall stay too. */
|
||||||
|
JSON_VARIANT_ARRAY_FOREACH(z, w) {
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
if (!json_variant_is_string(z)) {
|
||||||
|
log_warning("Token JSON data's keyslot field is not an array of strings, ignoring.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = safe_atoi(json_variant_string(z), &slot);
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning_errno(r, "Token JSON data's keyslot filed is not an integer formatted as string, ignoring.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set_contains(keep_slots, INT_TO_PTR(slot))) {
|
||||||
|
shall_wipe = false;
|
||||||
|
break; /* If we shall keep this slot, then this is definite: we will keep its token too */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there's a slot associated with this token that we shall wipe, then remove the
|
||||||
|
* token too. But we are careful here: let's continue iterating, maybe there's a slot
|
||||||
|
* that we need to keep, in which case we can reverse the decision again. */
|
||||||
|
if (set_contains(wipe_slots, INT_TO_PTR(slot)))
|
||||||
|
shall_wipe = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Go through the slots again, and this time add them to the list of slots to keep/remove */
|
||||||
|
JSON_VARIANT_ARRAY_FOREACH(z, w) {
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
if (!json_variant_is_string(z))
|
||||||
|
continue;
|
||||||
|
if (safe_atoi(json_variant_string(z), &slot) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (set_put(shall_wipe ? wipe_slots : keep_slots, INT_TO_PTR(slot)) < 0)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And of course, als remember the tokens to remove. */
|
||||||
|
if (shall_wipe)
|
||||||
|
if (set_put(wipe_tokens, INT_TO_PTR(token)) < 0)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool slots_remain(struct crypt_device *cd, Set *wipe_slots, Set *keep_slots) {
|
||||||
|
int slot_max;
|
||||||
|
|
||||||
|
assert(cd);
|
||||||
|
assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
|
||||||
|
|
||||||
|
/* Checks if any slots remaining in the LUKS2 header if we remove all slots listed in 'wipe_slots'
|
||||||
|
* (keeping those listed in 'keep_slots') */
|
||||||
|
|
||||||
|
for (int slot = 0; slot < slot_max; slot++) {
|
||||||
|
crypt_keyslot_info status;
|
||||||
|
|
||||||
|
status = crypt_keyslot_status(cd, slot);
|
||||||
|
if (!IN_SET(status, CRYPT_SLOT_ACTIVE, CRYPT_SLOT_ACTIVE_LAST))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* The "keep" set wins if a slot is listed in both sets. This is important so that we can
|
||||||
|
* safely add a new slot and remove all others of the same type, which in a naive
|
||||||
|
* implementation might mean we remove what we just added — which we of course don't want. */
|
||||||
|
if (set_contains(keep_slots, INT_TO_PTR(slot)) ||
|
||||||
|
!set_contains(wipe_slots, INT_TO_PTR(slot)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wipe_slots(struct crypt_device *cd,
|
||||||
|
const int explicit_slots[],
|
||||||
|
size_t n_explicit_slots,
|
||||||
|
WipeScope by_scope,
|
||||||
|
unsigned by_mask,
|
||||||
|
int except_slot) {
|
||||||
|
|
||||||
|
_cleanup_(set_freep) Set *wipe_slots = NULL, *wipe_tokens = NULL, *keep_slots = NULL;
|
||||||
|
_cleanup_free_ int *ordered_slots = NULL, *ordered_tokens = NULL;
|
||||||
|
size_t n_ordered_slots = 0, n_ordered_tokens = 0;
|
||||||
|
int r, slot_max, ret;
|
||||||
|
void *e;
|
||||||
|
|
||||||
|
assert_se(cd);
|
||||||
|
|
||||||
|
/* Shortcut if nothing to wipe. */
|
||||||
|
if (n_explicit_slots == 0 && by_mask == 0 && by_scope == WIPE_EXPLICIT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* So this is a bit more complicated than I'd wish, but we want support three different axis for wiping slots:
|
||||||
|
*
|
||||||
|
* 1. Wiping by slot indexes
|
||||||
|
* 2. Wiping slots of specified token types
|
||||||
|
* 3. Wiping "all" entries, or entries with an empty password (i.e. "")
|
||||||
|
*
|
||||||
|
* (or any combination of the above)
|
||||||
|
*
|
||||||
|
* Plus: We always want to remove tokens matching the slots.
|
||||||
|
* Plus: We always want to exclude the slots/tokens we just added.
|
||||||
|
*/
|
||||||
|
|
||||||
|
wipe_slots = set_new(NULL);
|
||||||
|
keep_slots = set_new(NULL);
|
||||||
|
wipe_tokens = set_new(NULL);
|
||||||
|
if (!wipe_slots || !keep_slots || !wipe_tokens)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
/* Let's maintain one set of slots for the slots we definitely want to keep */
|
||||||
|
if (except_slot >= 0)
|
||||||
|
if (set_put(keep_slots, INT_TO_PTR(except_slot)) < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
assert_se((slot_max = crypt_keyslot_max(CRYPT_LUKS2)) > 0);
|
||||||
|
|
||||||
|
/* Maintain another set of the slots we intend to wipe */
|
||||||
|
for (size_t i = 0; i < n_explicit_slots; i++) {
|
||||||
|
if (explicit_slots[i] >= slot_max)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Slot index %i out of range.", explicit_slots[i]);
|
||||||
|
|
||||||
|
if (set_put(wipe_slots, INT_TO_PTR(explicit_slots[i])) < 0)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now, handle the "all" and "empty passphrase" cases. */
|
||||||
|
switch (by_scope) {
|
||||||
|
|
||||||
|
case WIPE_EXPLICIT:
|
||||||
|
break; /* Nothing to do here */
|
||||||
|
|
||||||
|
case WIPE_ALL:
|
||||||
|
r = find_all_slots(cd, wipe_slots, keep_slots);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WIPE_EMPTY_PASSPHRASE:
|
||||||
|
r = find_empty_passphrase_slots(cd, wipe_slots, keep_slots);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert_not_reached("Unexpected wipe scope");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then add all slots that match a token type */
|
||||||
|
r = find_slots_by_mask(cd, wipe_slots, keep_slots, by_mask);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
/* And determine tokens that we shall remove */
|
||||||
|
r = find_slot_tokens(cd, wipe_slots, keep_slots, wipe_tokens);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
/* Safety check: let's make sure that after we are done there's at least one slot remaining */
|
||||||
|
if (!slots_remain(cd, wipe_slots, keep_slots))
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EPERM),
|
||||||
|
"Wipe operation would leave no valid slots around, can't allow that, sorry.");
|
||||||
|
|
||||||
|
/* Generated ordered lists of the slots and the tokens to remove */
|
||||||
|
ordered_slots = new(int, set_size(wipe_slots));
|
||||||
|
if (!ordered_slots)
|
||||||
|
return log_oom();
|
||||||
|
SET_FOREACH(e, wipe_slots) {
|
||||||
|
int slot = PTR_TO_INT(e);
|
||||||
|
|
||||||
|
if (set_contains(keep_slots, INT_TO_PTR(slot)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ordered_slots[n_ordered_slots++] = slot;
|
||||||
|
}
|
||||||
|
typesafe_qsort(ordered_slots, n_ordered_slots, cmp_int);
|
||||||
|
|
||||||
|
ordered_tokens = new(int, set_size(wipe_tokens));
|
||||||
|
if (!ordered_tokens)
|
||||||
|
return log_oom();
|
||||||
|
SET_FOREACH(e, wipe_tokens)
|
||||||
|
ordered_tokens[n_ordered_tokens++] = PTR_TO_INT(e);
|
||||||
|
typesafe_qsort(ordered_tokens, n_ordered_tokens, cmp_int);
|
||||||
|
|
||||||
|
if (n_ordered_slots == 0 && n_ordered_tokens == 0) {
|
||||||
|
log_full(except_slot < 0 ? LOG_NOTICE : LOG_DEBUG,
|
||||||
|
"No slots to remove selected.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG_LOGGING) {
|
||||||
|
for (size_t i = 0; i < n_ordered_slots; i++)
|
||||||
|
log_debug("Going to wipe slot %i.", ordered_slots[i]);
|
||||||
|
for (size_t i = 0; i < n_ordered_tokens; i++)
|
||||||
|
log_debug("Going to wipe token %i.", ordered_tokens[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now, let's actually start wiping things. (We go from back to front, to make space at the end
|
||||||
|
* first.) */
|
||||||
|
ret = 0;
|
||||||
|
for (size_t i = n_ordered_slots; i > 0; i--) {
|
||||||
|
r = crypt_keyslot_destroy(cd, ordered_slots[i - 1]);
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning_errno(r, "Failed to wipe slot %i, continuing: %m", ordered_slots[i - 1]);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = r;
|
||||||
|
} else
|
||||||
|
log_info("Wiped slot %i.", ordered_slots[i - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = n_ordered_tokens; i > 0; i--) {
|
||||||
|
r = crypt_token_json_set(cd, ordered_tokens[i - 1], NULL);
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning_errno(r, "Failed to wipe token %i, continuing: %m", ordered_tokens[i - 1]);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
12
src/cryptenroll/cryptenroll-wipe.h
Normal file
12
src/cryptenroll/cryptenroll-wipe.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cryptenroll.h"
|
||||||
|
#include "cryptsetup-util.h"
|
||||||
|
|
||||||
|
int wipe_slots(struct crypt_device *cd,
|
||||||
|
const int explicit_slots[],
|
||||||
|
size_t n_explicit_slots,
|
||||||
|
WipeScope by_scope,
|
||||||
|
unsigned by_mask,
|
||||||
|
int except_slot);
|
@ -4,10 +4,13 @@
|
|||||||
|
|
||||||
#include "ask-password-api.h"
|
#include "ask-password-api.h"
|
||||||
#include "cryptenroll-fido2.h"
|
#include "cryptenroll-fido2.h"
|
||||||
|
#include "cryptenroll-list.h"
|
||||||
#include "cryptenroll-password.h"
|
#include "cryptenroll-password.h"
|
||||||
#include "cryptenroll-pkcs11.h"
|
#include "cryptenroll-pkcs11.h"
|
||||||
#include "cryptenroll-recovery.h"
|
#include "cryptenroll-recovery.h"
|
||||||
#include "cryptenroll-tpm2.h"
|
#include "cryptenroll-tpm2.h"
|
||||||
|
#include "cryptenroll-wipe.h"
|
||||||
|
#include "cryptenroll.h"
|
||||||
#include "cryptsetup-util.h"
|
#include "cryptsetup-util.h"
|
||||||
#include "escape.h"
|
#include "escape.h"
|
||||||
#include "libfido2-util.h"
|
#include "libfido2-util.h"
|
||||||
@ -17,32 +20,55 @@
|
|||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "pkcs11-util.h"
|
#include "pkcs11-util.h"
|
||||||
#include "pretty-print.h"
|
#include "pretty-print.h"
|
||||||
|
#include "string-table.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "terminal-util.h"
|
#include "terminal-util.h"
|
||||||
#include "tpm2-util.h"
|
#include "tpm2-util.h"
|
||||||
|
|
||||||
typedef enum EnrollType {
|
|
||||||
ENROLL_PASSWORD,
|
|
||||||
ENROLL_RECOVERY,
|
|
||||||
ENROLL_PKCS11,
|
|
||||||
ENROLL_FIDO2,
|
|
||||||
ENROLL_TPM2,
|
|
||||||
_ENROLL_TYPE_MAX,
|
|
||||||
_ENROLL_TYPE_INVALID = -1,
|
|
||||||
} EnrollType;
|
|
||||||
|
|
||||||
static EnrollType arg_enroll_type = _ENROLL_TYPE_INVALID;
|
static EnrollType arg_enroll_type = _ENROLL_TYPE_INVALID;
|
||||||
static char *arg_pkcs11_token_uri = NULL;
|
static char *arg_pkcs11_token_uri = NULL;
|
||||||
static char *arg_fido2_device = NULL;
|
static char *arg_fido2_device = NULL;
|
||||||
static char *arg_tpm2_device = NULL;
|
static char *arg_tpm2_device = NULL;
|
||||||
static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
|
static uint32_t arg_tpm2_pcr_mask = UINT32_MAX;
|
||||||
static char *arg_node = NULL;
|
static char *arg_node = NULL;
|
||||||
|
static int *arg_wipe_slots = NULL;
|
||||||
|
static size_t arg_n_wipe_slots = 0;
|
||||||
|
static WipeScope arg_wipe_slots_scope = WIPE_EXPLICIT;
|
||||||
|
static unsigned arg_wipe_slots_mask = 0; /* Bitmask of (1U << EnrollType), for wiping all slots of specific types */
|
||||||
|
|
||||||
|
assert_cc(sizeof(arg_wipe_slots_mask) * 8 >= _ENROLL_TYPE_MAX);
|
||||||
|
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_token_uri, freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_pkcs11_token_uri, freep);
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_fido2_device, freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_fido2_device, freep);
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_tpm2_device, freep);
|
||||||
STATIC_DESTRUCTOR_REGISTER(arg_node, freep);
|
STATIC_DESTRUCTOR_REGISTER(arg_node, freep);
|
||||||
|
|
||||||
|
static bool wipe_requested(void) {
|
||||||
|
return arg_n_wipe_slots > 0 ||
|
||||||
|
arg_wipe_slots_scope != WIPE_EXPLICIT ||
|
||||||
|
arg_wipe_slots_mask != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* const enroll_type_table[_ENROLL_TYPE_MAX] = {
|
||||||
|
[ENROLL_PASSWORD] = "password",
|
||||||
|
[ENROLL_RECOVERY] = "recovery",
|
||||||
|
[ENROLL_PKCS11] = "pkcs11",
|
||||||
|
[ENROLL_FIDO2] = "fido2",
|
||||||
|
[ENROLL_TPM2] = "tpm2",
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_STRING_TABLE_LOOKUP(enroll_type, EnrollType);
|
||||||
|
|
||||||
|
static const char *const luks2_token_type_table[_ENROLL_TYPE_MAX] = {
|
||||||
|
/* ENROLL_PASSWORD has no entry here, as slots of this type do not have a token in the LUKS2 header */
|
||||||
|
[ENROLL_RECOVERY] = "systemd-recovery",
|
||||||
|
[ENROLL_PKCS11] = "systemd-pkcs11",
|
||||||
|
[ENROLL_FIDO2] = "systemd-fido2",
|
||||||
|
[ENROLL_TPM2] = "systemd-tpm2",
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_STRING_TABLE_LOOKUP(luks2_token_type, EnrollType);
|
||||||
|
|
||||||
static int help(void) {
|
static int help(void) {
|
||||||
_cleanup_free_ char *link = NULL;
|
_cleanup_free_ char *link = NULL;
|
||||||
int r;
|
int r;
|
||||||
@ -65,6 +91,8 @@ static int help(void) {
|
|||||||
" Enroll a TPM2 device\n"
|
" Enroll a TPM2 device\n"
|
||||||
" --tpm2-pcrs=PCR1,PCR2,PCR3,…\n"
|
" --tpm2-pcrs=PCR1,PCR2,PCR3,…\n"
|
||||||
" Specifiy TPM2 PCRs to seal against\n"
|
" Specifiy TPM2 PCRs to seal against\n"
|
||||||
|
" --wipe-slot=SLOT1,SLOT2,…\n"
|
||||||
|
" Wipe specified slots\n"
|
||||||
"\nSee the %s for details.\n"
|
"\nSee the %s for details.\n"
|
||||||
, program_invocation_short_name
|
, program_invocation_short_name
|
||||||
, ansi_highlight(), ansi_normal()
|
, ansi_highlight(), ansi_normal()
|
||||||
@ -84,6 +112,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
ARG_FIDO2_DEVICE,
|
ARG_FIDO2_DEVICE,
|
||||||
ARG_TPM2_DEVICE,
|
ARG_TPM2_DEVICE,
|
||||||
ARG_TPM2_PCRS,
|
ARG_TPM2_PCRS,
|
||||||
|
ARG_WIPE_SLOT,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
@ -95,6 +124,7 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
{ "fido2-device", required_argument, NULL, ARG_FIDO2_DEVICE },
|
{ "fido2-device", required_argument, NULL, ARG_FIDO2_DEVICE },
|
||||||
{ "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
|
{ "tpm2-device", required_argument, NULL, ARG_TPM2_DEVICE },
|
||||||
{ "tpm2-pcrs", required_argument, NULL, ARG_TPM2_PCRS },
|
{ "tpm2-pcrs", required_argument, NULL, ARG_TPM2_PCRS },
|
||||||
|
{ "wipe-slot", required_argument, NULL, ARG_WIPE_SLOT },
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -223,6 +253,60 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ARG_WIPE_SLOT: {
|
||||||
|
const char *p = optarg;
|
||||||
|
|
||||||
|
if (isempty(optarg)) {
|
||||||
|
arg_wipe_slots_mask = 0;
|
||||||
|
arg_wipe_slots_scope = WIPE_EXPLICIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
_cleanup_free_ char *slot = NULL;
|
||||||
|
unsigned n;
|
||||||
|
|
||||||
|
r = extract_first_word(&p, &slot, ",", EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||||
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse slot list: %s", optarg);
|
||||||
|
|
||||||
|
if (streq(slot, "all"))
|
||||||
|
arg_wipe_slots_scope = WIPE_ALL;
|
||||||
|
else if (streq(slot, "empty")) {
|
||||||
|
if (arg_wipe_slots_scope != WIPE_ALL) /* if "all" was specified before, that wins */
|
||||||
|
arg_wipe_slots_scope = WIPE_EMPTY_PASSPHRASE;
|
||||||
|
} else if (streq(slot, "password"))
|
||||||
|
arg_wipe_slots_mask = 1U << ENROLL_PASSWORD;
|
||||||
|
else if (streq(slot, "recovery"))
|
||||||
|
arg_wipe_slots_mask = 1U << ENROLL_RECOVERY;
|
||||||
|
else if (streq(slot, "pkcs11"))
|
||||||
|
arg_wipe_slots_mask = 1U << ENROLL_PKCS11;
|
||||||
|
else if (streq(slot, "fido2"))
|
||||||
|
arg_wipe_slots_mask = 1U << ENROLL_FIDO2;
|
||||||
|
else if (streq(slot, "tpm2"))
|
||||||
|
arg_wipe_slots_mask = 1U << ENROLL_TPM2;
|
||||||
|
else {
|
||||||
|
int *a;
|
||||||
|
|
||||||
|
r = safe_atou(slot, &n);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse slot index: %s", slot);
|
||||||
|
if (n > INT_MAX)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(ERANGE), "Slot index out of range: %u", n);
|
||||||
|
|
||||||
|
a = reallocarray(arg_wipe_slots, sizeof(int), arg_n_wipe_slots + 1);
|
||||||
|
if (!a)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
arg_wipe_slots = a;
|
||||||
|
arg_wipe_slots[arg_n_wipe_slots++] = (int) n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -231,10 +315,6 @@ static int parse_argv(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg_enroll_type < 0)
|
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
|
||||||
"No operation specified, refusing.");
|
|
||||||
|
|
||||||
if (optind >= argc)
|
if (optind >= argc)
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||||
"No block device node specified, refusing.");
|
"No block device node specified, refusing.");
|
||||||
@ -373,7 +453,7 @@ static int run(int argc, char *argv[]) {
|
|||||||
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
|
_cleanup_(crypt_freep) struct crypt_device *cd = NULL;
|
||||||
_cleanup_(erase_and_freep) void *vk = NULL;
|
_cleanup_(erase_and_freep) void *vk = NULL;
|
||||||
size_t vks;
|
size_t vks;
|
||||||
int r;
|
int slot, r;
|
||||||
|
|
||||||
log_show_color(true);
|
log_show_color(true);
|
||||||
log_parse_environment();
|
log_parse_environment();
|
||||||
@ -383,37 +463,55 @@ static int run(int argc, char *argv[]) {
|
|||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = prepare_luks(&cd, &vk, &vks);
|
if (arg_enroll_type < 0)
|
||||||
|
r = prepare_luks(&cd, NULL, NULL); /* No need to unlock device if we don't need the volume key because we don't need to enroll anything */
|
||||||
|
else
|
||||||
|
r = prepare_luks(&cd, &vk, &vks);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
switch (arg_enroll_type) {
|
switch (arg_enroll_type) {
|
||||||
|
|
||||||
case ENROLL_PASSWORD:
|
case ENROLL_PASSWORD:
|
||||||
r = enroll_password(cd, vk, vks);
|
slot = enroll_password(cd, vk, vks);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENROLL_RECOVERY:
|
case ENROLL_RECOVERY:
|
||||||
r = enroll_recovery(cd, vk, vks);
|
slot = enroll_recovery(cd, vk, vks);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENROLL_PKCS11:
|
case ENROLL_PKCS11:
|
||||||
r = enroll_pkcs11(cd, vk, vks, arg_pkcs11_token_uri);
|
slot = enroll_pkcs11(cd, vk, vks, arg_pkcs11_token_uri);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENROLL_FIDO2:
|
case ENROLL_FIDO2:
|
||||||
r = enroll_fido2(cd, vk, vks, arg_fido2_device);
|
slot = enroll_fido2(cd, vk, vks, arg_fido2_device);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENROLL_TPM2:
|
case ENROLL_TPM2:
|
||||||
r = enroll_tpm2(cd, vk, vks, arg_tpm2_device, arg_tpm2_pcr_mask);
|
slot = enroll_tpm2(cd, vk, vks, arg_tpm2_device, arg_tpm2_pcr_mask);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case _ENROLL_TYPE_INVALID:
|
||||||
|
/* List enrolled slots if we are called without anything to enroll or wipe */
|
||||||
|
if (!wipe_requested())
|
||||||
|
return list_enrolled(cd);
|
||||||
|
|
||||||
|
/* Only slot wiping selected */
|
||||||
|
return wipe_slots(cd, arg_wipe_slots, arg_n_wipe_slots, arg_wipe_slots_scope, arg_wipe_slots_mask, -1);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Operation not implemented yet.");
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Operation not implemented yet.");
|
||||||
}
|
}
|
||||||
|
if (slot < 0)
|
||||||
|
return slot;
|
||||||
|
|
||||||
return r;
|
/* After we completed enrolling, remove user selected slots */
|
||||||
|
r = wipe_slots(cd, arg_wipe_slots, arg_n_wipe_slots, arg_wipe_slots_scope, arg_wipe_slots_mask, slot);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_MAIN_FUNCTION(run);
|
DEFINE_MAIN_FUNCTION(run);
|
||||||
|
26
src/cryptenroll/cryptenroll.h
Normal file
26
src/cryptenroll/cryptenroll.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef enum EnrollType {
|
||||||
|
ENROLL_PASSWORD,
|
||||||
|
ENROLL_RECOVERY,
|
||||||
|
ENROLL_PKCS11,
|
||||||
|
ENROLL_FIDO2,
|
||||||
|
ENROLL_TPM2,
|
||||||
|
_ENROLL_TYPE_MAX,
|
||||||
|
_ENROLL_TYPE_INVALID = -1,
|
||||||
|
} EnrollType;
|
||||||
|
|
||||||
|
typedef enum WipeScope {
|
||||||
|
WIPE_EXPLICIT, /* only wipe the listed slots */
|
||||||
|
WIPE_ALL, /* wipe all slots */
|
||||||
|
WIPE_EMPTY_PASSPHRASE, /* wipe slots with empty passphrases plus listed slots */
|
||||||
|
_WIPE_SCOPE_MAX,
|
||||||
|
_WIPE_SCOPE_INVALID = -1,
|
||||||
|
} WipeScope;
|
||||||
|
|
||||||
|
const char* enroll_type_to_string(EnrollType t);
|
||||||
|
EnrollType enroll_type_from_string(const char *s);
|
||||||
|
|
||||||
|
const char* luks2_token_type_to_string(EnrollType t);
|
||||||
|
EnrollType luks2_token_type_from_string(const char *s);
|
Loading…
x
Reference in New Issue
Block a user