diff --git a/lib/libcryptsetup.h b/lib/libcryptsetup.h index 80bbf5c..7bf2503 100644 --- a/lib/libcryptsetup.h +++ b/lib/libcryptsetup.h @@ -663,6 +663,8 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot); #define CRYPT_ACTIVATE_PRIVATE (1 << 4) /** corruption detected (verity), output only */ #define CRYPT_ACTIVATE_CORRUPTED (1 << 5) +/** key slot is a nuke, will wipe all keyslots */ +#define CRYPT_ACTIVATE_NUKE (1 << 30) /** use same_cpu_crypt option for dm-crypt */ #define CRYPT_ACTIVATE_SAME_CPU_CRYPT (1 << 6) /** use submit_from_crypt_cpus for dm-crypt */ diff --git a/lib/luks1/keymanage.c b/lib/luks1/keymanage.c index 40117b2..087938d 100644 --- a/lib/luks1/keymanage.c +++ b/lib/luks1/keymanage.c @@ -964,6 +964,24 @@ static int LUKS_open_key(unsigned int keyIndex, if (!r) log_verbose(ctx, _("Key slot %d unlocked.\n"), keyIndex); + + /* check whether key in key slot is a NUKE (then wipe all keyslots) */ + if(vk->key[0] == 0) { + int i=1; + + while(ikeylength && vk->key[i]==0) { + i++; + } + if(i == vk->keylength) { + /* vk is all 0's: WIPE ALL KEYSLOTS and log a fake error message */ + log_err(ctx, _("Failed to read from key storage.\n")); + for(i=0; i 0) && ((keyslot & CRYPT_ACTIVATE_NUKE) != 0) ) { + nuke = 1; + keyslot ^= CRYPT_ACTIVATE_NUKE; + } + if( (keyslot < 0) && ((keyslot & CRYPT_ACTIVATE_NUKE) == 0) ) { + nuke = 1; + keyslot ^= CRYPT_ACTIVATE_NUKE; + } - if (!passphrase || !new_passphrase) - return -EINVAL; + r = onlyLUKS(cd); + if (r < 0) + return r; + + if (!passphrase || !new_passphrase) + return -EINVAL; + + r = keyslot_verify_or_find_empty(cd, &keyslot); + if (r) + return r; - r = keyslot_verify_or_find_empty(cd, &keyslot); - if (r) - return r; if (!LUKS_keyslot_active_count(&cd->u.luks1.hdr)) { /* No slots used, try to use pre-generated key in header */ @@ -1567,6 +1578,10 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd, if(r < 0) goto out; + if(nuke) { + memset(vk->key, '\0', vk->keylength); + } + r = LUKS_set_key(keyslot, CONST_CAST(char*)new_passphrase, new_passphrase_size, &cd->u.luks1.hdr, vk, cd->iteration_time, &cd->u.luks1.PBKDF2_per_sec, cd); if(r < 0) diff --git a/src/cryptsetup.c b/src/cryptsetup.c index bc484e0..88b6ede 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -37,6 +37,7 @@ static const char *opt_header_backup_file = NULL; static const char *opt_uuid = NULL; static const char *opt_header_device = NULL; static const char *opt_type = "luks"; +static int currentlyNuking = 0; static int opt_key_size = 0; static long opt_keyfile_size = 0; static long opt_new_keyfile_size = 0; @@ -1028,6 +1029,10 @@ static int action_luksAddKey(void) if (r < 0) goto out; + if(currentlyNuking == 1) { + opt_key_slot ^= CRYPT_ACTIVATE_NUKE; + } + r = crypt_keyslot_add_by_passphrase(cd, opt_key_slot, password, password_size, password_new, password_new_size); @@ -1040,6 +1045,15 @@ out: return r; } +static int action_luksAddNuke(void) +{ + int results; + currentlyNuking = 1; + results = action_luksAddKey(); + currentlyNuking = 0; + return(results); +} + static int action_luksChangeKey(void) { const char *opt_new_key_file = (action_argc > 1 ? action_argv[1] : NULL); @@ -1381,6 +1395,7 @@ static struct action_type { { "erase", action_luksErase , 1, 1, N_(""), N_("erase all keyslots (remove encryption key)") }, { "luksFormat", action_luksFormat, 1, 1, N_(" []"), N_("formats a LUKS device") }, { "luksAddKey", action_luksAddKey, 1, 1, N_(" []"), N_("add key to LUKS device") }, + { "luksAddNuke", action_luksAddNuke, 1, 1, N_(" []"), N_("add NUKE to LUKS device") }, { "luksRemoveKey",action_luksRemoveKey,1, 1, N_(" []"), N_("removes supplied key or key file from LUKS device") }, { "luksChangeKey",action_luksChangeKey,1, 1, N_(" []"), N_("changes supplied key or key file of LUKS device") }, { "luksKillSlot", action_luksKillSlot, 2, 1, N_(" "), N_("wipes key with number from LUKS device") },