mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-15 21:00:05 +01:00
Add repair command and API for repairing known LUKS header problems.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
2012-03-16 Milan Broz <gmazyland@gmail.com>
|
2012-03-16 Milan Broz <gmazyland@gmail.com>
|
||||||
* Add --keyfile-offset and --new-keyfile-offset parameters to API and CLI.
|
* Add --keyfile-offset and --new-keyfile-offset parameters to API and CLI.
|
||||||
|
* Add repair command and crypt_repair() for known LUKS metadata problems repair.
|
||||||
|
|
||||||
2012-03-16 Milan Broz <mbroz@redhat.com>
|
2012-03-16 Milan Broz <mbroz@redhat.com>
|
||||||
* Unify password verification option.
|
* Unify password verification option.
|
||||||
|
|||||||
@@ -391,6 +391,20 @@ int crypt_load(struct crypt_device *cd,
|
|||||||
const char *requested_type,
|
const char *requested_type,
|
||||||
void *params);
|
void *params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to repair crypt device on-disk header if invalid
|
||||||
|
*
|
||||||
|
* @param cd crypt device handle
|
||||||
|
* @param requested_type - use @e NULL for all known
|
||||||
|
* @param params crypt type specific parameters (see @link crypt_type @endlink)
|
||||||
|
*
|
||||||
|
* @returns 0 on success or negative errno value otherwise.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int crypt_repair(struct crypt_device *cd,
|
||||||
|
const char *requested_type,
|
||||||
|
void *params __attribute__((unused)));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resize crypt device
|
* Resize crypt device
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ CRYPTSETUP_1.0 {
|
|||||||
crypt_memory_lock;
|
crypt_memory_lock;
|
||||||
crypt_format;
|
crypt_format;
|
||||||
crypt_load;
|
crypt_load;
|
||||||
|
crypt_repair;
|
||||||
crypt_resize;
|
crypt_resize;
|
||||||
crypt_suspend;
|
crypt_suspend;
|
||||||
crypt_resume_by_passphrase;
|
crypt_resume_by_passphrase;
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ int LUKS_hdr_backup(
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = LUKS_read_phdr(device, hdr, 1, ctx);
|
r = LUKS_read_phdr(device, hdr, 1, 0, ctx);
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@@ -245,7 +245,7 @@ int LUKS_hdr_restore(
|
|||||||
}
|
}
|
||||||
close(devfd);
|
close(devfd);
|
||||||
|
|
||||||
r = LUKS_read_phdr(device, hdr, 0, ctx);
|
r = LUKS_read_phdr(device, hdr, 0, 0, ctx);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
log_dbg("Device %s already contains LUKS header, checking UUID and offset.", device);
|
log_dbg("Device %s already contains LUKS header, checking UUID and offset.", device);
|
||||||
if(hdr->payloadOffset != hdr_file.payloadOffset ||
|
if(hdr->payloadOffset != hdr_file.payloadOffset ||
|
||||||
@@ -288,7 +288,7 @@ int LUKS_hdr_restore(
|
|||||||
close(devfd);
|
close(devfd);
|
||||||
|
|
||||||
/* Be sure to reload new data */
|
/* Be sure to reload new data */
|
||||||
r = LUKS_read_phdr(device, hdr, 1, ctx);
|
r = LUKS_read_phdr(device, hdr, 1, 0, ctx);
|
||||||
out:
|
out:
|
||||||
if (devfd != -1)
|
if (devfd != -1)
|
||||||
close(devfd);
|
close(devfd);
|
||||||
@@ -296,23 +296,35 @@ out:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This routine should do some just basic recovery for known problems. */
|
||||||
static int _keyslot_repair(const char *device, struct luks_phdr *phdr, struct crypt_device *ctx)
|
static int _keyslot_repair(const char *device, struct luks_phdr *phdr, struct crypt_device *ctx)
|
||||||
{
|
{
|
||||||
struct luks_phdr temp_phdr;
|
struct luks_phdr temp_phdr;
|
||||||
const unsigned char *sector = (const unsigned char*)phdr;
|
const unsigned char *sector = (const unsigned char*)phdr;
|
||||||
struct volume_key *vk;
|
struct volume_key *vk;
|
||||||
uint64_t PBKDF2_per_sec = 1;
|
uint64_t PBKDF2_per_sec = 1;
|
||||||
int i, bad;
|
int i, bad, r, need_write = 0;
|
||||||
|
|
||||||
// FIXME check keyBytes
|
if (phdr->keyBytes != 16 && phdr->keyBytes != 32) {
|
||||||
|
log_err(ctx, _("Non standard key size, manual repair required.\n"));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
vk = crypt_alloc_volume_key(phdr->keyBytes, NULL);
|
vk = crypt_alloc_volume_key(phdr->keyBytes, NULL);
|
||||||
|
|
||||||
// FIXME check cipher, cipher_mode, hash, uuid, payloadOffset
|
log_verbose(ctx, _("Repairing keyslots.\n"));
|
||||||
LUKS_generate_phdr(&temp_phdr, vk, phdr->cipherName, phdr->cipherMode,
|
|
||||||
|
log_dbg("Generating second header with the same parameters for check.");
|
||||||
|
/* cipherName, cipherMode, hashSpec, uuid are already null terminated */
|
||||||
|
/* payloadOffset - cannot check */
|
||||||
|
r = LUKS_generate_phdr(&temp_phdr, vk, phdr->cipherName, phdr->cipherMode,
|
||||||
phdr->hashSpec,phdr->uuid, LUKS_STRIPES,
|
phdr->hashSpec,phdr->uuid, LUKS_STRIPES,
|
||||||
phdr->payloadOffset, 0,
|
phdr->payloadOffset, 0,
|
||||||
1, &PBKDF2_per_sec,
|
1, &PBKDF2_per_sec,
|
||||||
"/dev/null", ctx);
|
"/dev/null", ctx);
|
||||||
|
if (r < 0) {
|
||||||
|
log_err(ctx, _("Repair failed."));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
for(i = 0; i < LUKS_NUMKEYS; ++i) {
|
for(i = 0; i < LUKS_NUMKEYS; ++i) {
|
||||||
bad = 0;
|
bad = 0;
|
||||||
@@ -332,7 +344,7 @@ static int _keyslot_repair(const char *device, struct luks_phdr *phdr, struct cr
|
|||||||
bad = 1;
|
bad = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if enabled, do not try to fix it */
|
/* if enabled, do not try to wipe salt */
|
||||||
if (phdr->keyblock[i].active != LUKS_KEY_ENABLED) {
|
if (phdr->keyblock[i].active != LUKS_KEY_ENABLED) {
|
||||||
/* Known case - MSDOS partition table signature */
|
/* Known case - MSDOS partition table signature */
|
||||||
if (i == 6 && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa) {
|
if (i == 6 && sector[0x1fe] == 0x55 && sector[0x1ff] == 0xaa) {
|
||||||
@@ -347,17 +359,25 @@ static int _keyslot_repair(const char *device, struct luks_phdr *phdr, struct cr
|
|||||||
phdr->keyblock[i].passwordIterations = 0;
|
phdr->keyblock[i].passwordIterations = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bad)
|
||||||
|
need_write = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (need_write) {
|
||||||
|
log_verbose(ctx, _("Writing LUKS header to disk.\n"));
|
||||||
|
r = LUKS_write_phdr(device, phdr, ctx);
|
||||||
|
}
|
||||||
|
out:
|
||||||
crypt_free_volume_key(vk);
|
crypt_free_volume_key(vk);
|
||||||
memset(&temp_phdr, 0, sizeof(temp_phdr));
|
memset(&temp_phdr, 0, sizeof(temp_phdr));
|
||||||
|
return r;
|
||||||
return LUKS_write_phdr(device, phdr, ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _check_and_convert_hdr(const char *device,
|
static int _check_and_convert_hdr(const char *device,
|
||||||
struct luks_phdr *hdr,
|
struct luks_phdr *hdr,
|
||||||
int require_luks_device,
|
int require_luks_device,
|
||||||
|
int repair,
|
||||||
struct crypt_device *ctx)
|
struct crypt_device *ctx)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
@@ -368,39 +388,44 @@ static int _check_and_convert_hdr(const char *device,
|
|||||||
log_dbg("LUKS header not detected.");
|
log_dbg("LUKS header not detected.");
|
||||||
if (require_luks_device)
|
if (require_luks_device)
|
||||||
log_err(ctx, _("Device %s is not a valid LUKS device.\n"), device);
|
log_err(ctx, _("Device %s is not a valid LUKS device.\n"), device);
|
||||||
r = -EINVAL;
|
return -EINVAL;
|
||||||
} else if((hdr->version = ntohs(hdr->version)) != 1) { /* Convert every uint16/32_t item from network byte order */
|
} else if((hdr->version = ntohs(hdr->version)) != 1) { /* Convert every uint16/32_t item from network byte order */
|
||||||
log_err(ctx, _("Unsupported LUKS version %d.\n"), hdr->version);
|
log_err(ctx, _("Unsupported LUKS version %d.\n"), hdr->version);
|
||||||
r = -EINVAL;
|
return -EINVAL;
|
||||||
} else if (PBKDF2_HMAC_ready(hdr->hashSpec) < 0) {
|
}
|
||||||
|
|
||||||
|
hdr->hashSpec[LUKS_HASHSPEC_L - 1] = '\0';
|
||||||
|
if (PBKDF2_HMAC_ready(hdr->hashSpec) < 0) {
|
||||||
log_err(ctx, _("Requested LUKS hash %s is not supported.\n"), hdr->hashSpec);
|
log_err(ctx, _("Requested LUKS hash %s is not supported.\n"), hdr->hashSpec);
|
||||||
r = -EINVAL;
|
return -EINVAL;
|
||||||
} else {
|
}
|
||||||
hdr->payloadOffset = ntohl(hdr->payloadOffset);
|
|
||||||
hdr->keyBytes = ntohl(hdr->keyBytes);
|
|
||||||
hdr->mkDigestIterations = ntohl(hdr->mkDigestIterations);
|
|
||||||
|
|
||||||
for(i = 0; i < LUKS_NUMKEYS; ++i) {
|
/* Header detected */
|
||||||
hdr->keyblock[i].active = ntohl(hdr->keyblock[i].active);
|
hdr->payloadOffset = ntohl(hdr->payloadOffset);
|
||||||
hdr->keyblock[i].passwordIterations = ntohl(hdr->keyblock[i].passwordIterations);
|
hdr->keyBytes = ntohl(hdr->keyBytes);
|
||||||
hdr->keyblock[i].keyMaterialOffset = ntohl(hdr->keyblock[i].keyMaterialOffset);
|
hdr->mkDigestIterations = ntohl(hdr->mkDigestIterations);
|
||||||
hdr->keyblock[i].stripes = ntohl(hdr->keyblock[i].stripes);
|
|
||||||
if (LUKS_check_keyslot_size(hdr, i)) {
|
for(i = 0; i < LUKS_NUMKEYS; ++i) {
|
||||||
log_err(ctx, _("LUKS keyslot %u is invalid.\n"), i);
|
hdr->keyblock[i].active = ntohl(hdr->keyblock[i].active);
|
||||||
r = -EINVAL;
|
hdr->keyblock[i].passwordIterations = ntohl(hdr->keyblock[i].passwordIterations);
|
||||||
}
|
hdr->keyblock[i].keyMaterialOffset = ntohl(hdr->keyblock[i].keyMaterialOffset);
|
||||||
|
hdr->keyblock[i].stripes = ntohl(hdr->keyblock[i].stripes);
|
||||||
|
if (LUKS_check_keyslot_size(hdr, i)) {
|
||||||
|
log_err(ctx, _("LUKS keyslot %u is invalid.\n"), i);
|
||||||
|
r = -EINVAL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Avoid unterminated strings */
|
/* Avoid unterminated strings */
|
||||||
hdr->cipherName[LUKS_CIPHERNAME_L - 1] = '\0';
|
hdr->cipherName[LUKS_CIPHERNAME_L - 1] = '\0';
|
||||||
hdr->cipherMode[LUKS_CIPHERMODE_L - 1] = '\0';
|
hdr->cipherMode[LUKS_CIPHERMODE_L - 1] = '\0';
|
||||||
hdr->uuid[UUID_STRING_L - 1] = '\0';
|
hdr->uuid[UUID_STRING_L - 1] = '\0';
|
||||||
#if 0
|
|
||||||
if (r == -EINVAL) {
|
if (repair) {
|
||||||
log_err(ctx, _("Repairing keyslots.\n"));
|
if (r == -EINVAL)
|
||||||
r = _keyslot_repair(device, hdr, ctx);
|
r = _keyslot_repair(device, hdr, ctx);
|
||||||
}
|
else
|
||||||
#endif
|
log_verbose(ctx, _("No known problems detected for LUKS header.\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
@@ -442,7 +467,8 @@ int LUKS_read_phdr_backup(const char *backup_file,
|
|||||||
r = -EIO;
|
r = -EIO;
|
||||||
else {
|
else {
|
||||||
LUKS_fix_header_compatible(hdr);
|
LUKS_fix_header_compatible(hdr);
|
||||||
r = _check_and_convert_hdr(backup_file, hdr, require_luks_device, ctx);
|
r = _check_and_convert_hdr(backup_file, hdr,
|
||||||
|
require_luks_device, 0, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(devfd);
|
close(devfd);
|
||||||
@@ -452,11 +478,15 @@ int LUKS_read_phdr_backup(const char *backup_file,
|
|||||||
int LUKS_read_phdr(const char *device,
|
int LUKS_read_phdr(const char *device,
|
||||||
struct luks_phdr *hdr,
|
struct luks_phdr *hdr,
|
||||||
int require_luks_device,
|
int require_luks_device,
|
||||||
|
int repair,
|
||||||
struct crypt_device *ctx)
|
struct crypt_device *ctx)
|
||||||
{
|
{
|
||||||
ssize_t hdr_size = sizeof(struct luks_phdr);
|
ssize_t hdr_size = sizeof(struct luks_phdr);
|
||||||
int devfd = 0, r = 0;
|
int devfd = 0, r = 0;
|
||||||
|
|
||||||
|
if (repair && !require_luks_device)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
log_dbg("Reading LUKS header of size %d from device %s",
|
log_dbg("Reading LUKS header of size %d from device %s",
|
||||||
hdr_size, device);
|
hdr_size, device);
|
||||||
|
|
||||||
@@ -469,7 +499,8 @@ int LUKS_read_phdr(const char *device,
|
|||||||
if (read_blockwise(devfd, hdr, hdr_size) < hdr_size)
|
if (read_blockwise(devfd, hdr, hdr_size) < hdr_size)
|
||||||
r = -EIO;
|
r = -EIO;
|
||||||
else
|
else
|
||||||
r = _check_and_convert_hdr(device, hdr, require_luks_device, ctx);
|
r = _check_and_convert_hdr(device, hdr, require_luks_device,
|
||||||
|
repair, ctx);
|
||||||
|
|
||||||
close(devfd);
|
close(devfd);
|
||||||
return r;
|
return r;
|
||||||
@@ -521,7 +552,7 @@ int LUKS_write_phdr(const char *device,
|
|||||||
|
|
||||||
/* Re-read header from disk to be sure that in-memory and on-disk data are the same. */
|
/* Re-read header from disk to be sure that in-memory and on-disk data are the same. */
|
||||||
if (!r) {
|
if (!r) {
|
||||||
r = LUKS_read_phdr(device, hdr, 1, ctx);
|
r = LUKS_read_phdr(device, hdr, 1, 0, ctx);
|
||||||
if (r)
|
if (r)
|
||||||
log_err(ctx, _("Error re-reading LUKS header after update on device %s.\n"), device);
|
log_err(ctx, _("Error re-reading LUKS header after update on device %s.\n"), device);
|
||||||
}
|
}
|
||||||
@@ -894,7 +925,7 @@ int LUKS_del_key(const char *device,
|
|||||||
unsigned int startOffset, endOffset, stripesLen;
|
unsigned int startOffset, endOffset, stripesLen;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = LUKS_read_phdr(device, hdr, 1, ctx);
|
r = LUKS_read_phdr(device, hdr, 1, 0, ctx);
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ int LUKS_read_phdr(
|
|||||||
const char *device,
|
const char *device,
|
||||||
struct luks_phdr *hdr,
|
struct luks_phdr *hdr,
|
||||||
int require_luks_device,
|
int require_luks_device,
|
||||||
|
int repair,
|
||||||
struct crypt_device *ctx);
|
struct crypt_device *ctx);
|
||||||
|
|
||||||
int LUKS_read_phdr_backup(
|
int LUKS_read_phdr_backup(
|
||||||
|
|||||||
39
lib/setup.c
39
lib/setup.c
@@ -602,7 +602,7 @@ int crypt_set_data_device(struct crypt_device *cd, const char *device)
|
|||||||
return crypt_check_data_device_size(cd);
|
return crypt_check_data_device_size(cd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _crypt_load_luks1(struct crypt_device *cd, int require_header)
|
static int _crypt_load_luks1(struct crypt_device *cd, int require_header, int repair)
|
||||||
{
|
{
|
||||||
struct luks_phdr hdr;
|
struct luks_phdr hdr;
|
||||||
int r;
|
int r;
|
||||||
@@ -611,7 +611,7 @@ static int _crypt_load_luks1(struct crypt_device *cd, int require_header)
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = LUKS_read_phdr(mdata_device(cd), &hdr, require_header, cd);
|
r = LUKS_read_phdr(mdata_device(cd), &hdr, require_header, repair, cd);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@@ -726,7 +726,7 @@ int crypt_init_by_name_and_header(struct crypt_device **cd,
|
|||||||
}
|
}
|
||||||
} else if (isLUKS((*cd)->type)) {
|
} else if (isLUKS((*cd)->type)) {
|
||||||
if (mdata_device(*cd)) {
|
if (mdata_device(*cd)) {
|
||||||
r = _crypt_load_luks1(*cd, 0);
|
r = _crypt_load_luks1(*cd, 0, 0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_dbg("LUKS device header does not match active device.");
|
log_dbg("LUKS device header does not match active device.");
|
||||||
free((*cd)->type);
|
free((*cd)->type);
|
||||||
@@ -972,7 +972,38 @@ int crypt_load(struct crypt_device *cd,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = _crypt_load_luks1(cd, 1);
|
r = _crypt_load_luks1(cd, 1, 0);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
/* cd->type and header must be set in context */
|
||||||
|
r = crypt_check_data_device_size(cd);
|
||||||
|
if (r < 0) {
|
||||||
|
free(cd->type);
|
||||||
|
cd->type = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int crypt_repair(struct crypt_device *cd,
|
||||||
|
const char *requested_type,
|
||||||
|
void *params __attribute__((unused)))
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
log_dbg("Trying to repair %s crypt type from device %s.",
|
||||||
|
requested_type ?: "any", mdata_device(cd) ?: "(none)");
|
||||||
|
|
||||||
|
if (!mdata_device(cd))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (requested_type && !isLUKS(requested_type))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
|
||||||
|
/* Load with repair */
|
||||||
|
r = _crypt_load_luks1(cd, 1, 1);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|||||||
@@ -175,6 +175,18 @@ form backup file are available after issuing this command.
|
|||||||
This command allows restoring header if device do not contain LUKS header
|
This command allows restoring header if device do not contain LUKS header
|
||||||
or if the master key size and data offset in LUKS header on device match the backup file.
|
or if the master key size and data offset in LUKS header on device match the backup file.
|
||||||
.PP
|
.PP
|
||||||
|
\fIrepair\fR <device>
|
||||||
|
.IP
|
||||||
|
Tries to repair (LUKS) device metadata if possible.
|
||||||
|
|
||||||
|
This command is useful to fix known benign LUKS metadata header corruptions.
|
||||||
|
Only basic corruptions of unused keyslot are fixable, any rewrite
|
||||||
|
of keyslot data or used keyslot or header metadata means lost of device.
|
||||||
|
|
||||||
|
\fBWARNING:\fR Always store binary copy of the original header, for
|
||||||
|
LUKS, \fIrepair\fR will not touch more than 4kB from the start of device
|
||||||
|
(visible LUKS header).
|
||||||
|
.PP
|
||||||
For more information about LUKS, see
|
For more information about LUKS, see
|
||||||
\fBhttp://code.google.com/p/cryptsetup/wiki/Specification\fR
|
\fBhttp://code.google.com/p/cryptsetup/wiki/Specification\fR
|
||||||
.SH loop-AES EXTENSION
|
.SH loop-AES EXTENSION
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ static int action_luksResume(int arg);
|
|||||||
static int action_luksBackup(int arg);
|
static int action_luksBackup(int arg);
|
||||||
static int action_luksRestore(int arg);
|
static int action_luksRestore(int arg);
|
||||||
static int action_loopaesOpen(int arg);
|
static int action_loopaesOpen(int arg);
|
||||||
|
static int action_luksRepair(int arg);
|
||||||
|
|
||||||
static struct action_type {
|
static struct action_type {
|
||||||
const char *type;
|
const char *type;
|
||||||
@@ -105,6 +106,7 @@ static struct action_type {
|
|||||||
{ "remove", action_remove, 0, 1, 1, N_("<name>"), N_("remove device") },
|
{ "remove", action_remove, 0, 1, 1, N_("<name>"), N_("remove device") },
|
||||||
{ "resize", action_resize, 0, 1, 1, N_("<name>"), N_("resize active device") },
|
{ "resize", action_resize, 0, 1, 1, N_("<name>"), N_("resize active device") },
|
||||||
{ "status", action_status, 0, 1, 0, N_("<name>"), N_("show device status") },
|
{ "status", action_status, 0, 1, 0, N_("<name>"), N_("show device status") },
|
||||||
|
{ "repair", action_luksRepair, 0, 1, 1, N_("<device>"), N_("try to repair on-disk metadata") },
|
||||||
{ "luksFormat", action_luksFormat, 0, 1, 1, N_("<device> [<new key file>]"), N_("formats a LUKS device") },
|
{ "luksFormat", action_luksFormat, 0, 1, 1, N_("<device> [<new key file>]"), N_("formats a LUKS device") },
|
||||||
{ "luksOpen", action_luksOpen, 0, 2, 1, N_("<device> <name> "), N_("open LUKS device as mapping <name>") },
|
{ "luksOpen", action_luksOpen, 0, 2, 1, N_("<device> <name> "), N_("open LUKS device as mapping <name>") },
|
||||||
{ "luksAddKey", action_luksAddKey, 0, 1, 1, N_("<device> [<new key file>]"), N_("add key to LUKS device") },
|
{ "luksAddKey", action_luksAddKey, 0, 1, 1, N_("<device> [<new key file>]"), N_("add key to LUKS device") },
|
||||||
@@ -517,6 +519,32 @@ fail:
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int action_luksRepair(int arg __attribute__((unused)))
|
||||||
|
{
|
||||||
|
struct crypt_device *cd = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if ((r = crypt_init(&cd, action_argv[0])))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Currently only LUKS1 allows repair */
|
||||||
|
crypt_set_log_callback(cd, _quiet_log, NULL);
|
||||||
|
r = crypt_load(cd, CRYPT_LUKS1, NULL);
|
||||||
|
crypt_set_log_callback(cd, _log, NULL);
|
||||||
|
if (r == 0) {
|
||||||
|
log_verbose( _("No known problems detected for LUKS header.\n"));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = _yesDialog(_("Really try to repair LUKS device header?"),
|
||||||
|
NULL) ? 0 : -EINVAL;
|
||||||
|
if (r == 0)
|
||||||
|
r = crypt_repair(cd, CRYPT_LUKS1, NULL);
|
||||||
|
out:
|
||||||
|
crypt_free(cd);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static int action_luksFormat(int arg __attribute__((unused)))
|
static int action_luksFormat(int arg __attribute__((unused)))
|
||||||
{
|
{
|
||||||
int r = -EINVAL, keysize;
|
int r = -EINVAL, keysize;
|
||||||
|
|||||||
@@ -495,5 +495,14 @@ $CRYPTSETUP luksSuspend $DEV_NAME --header $HEADER_IMG || fail
|
|||||||
echo "key0" | $CRYPTSETUP luksResume $DEV_NAME --header $HEADER_IMG || fail
|
echo "key0" | $CRYPTSETUP luksResume $DEV_NAME --header $HEADER_IMG || fail
|
||||||
$CRYPTSETUP luksClose $DEV_NAME || fail
|
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||||
|
|
||||||
|
prepare "[29] Repair metadata" wipe
|
||||||
|
$CRYPTSETUP -q luksFormat -i1 $LOOPDEV $KEY1 --key-slot 0 || fail
|
||||||
|
# second sector overwrite should corrupt keyslot 6+7
|
||||||
|
dd if=/dev/urandom of=$LOOPDEV bs=512 seek=1 count=1 >/dev/null 2>&1
|
||||||
|
$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME >/dev/null 2>&1 && fail
|
||||||
|
$CRYPTSETUP -q repair $LOOPDEV >/dev/null 2>&1 || fail
|
||||||
|
$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME || fail
|
||||||
|
$CRYPTSETUP luksClose $DEV_NAME || fail
|
||||||
|
|
||||||
remove_mapping
|
remove_mapping
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
Reference in New Issue
Block a user