Rewrite luksFormat, luksOpen, liksAddKey in crypsetup for new API.

With new API is possible to add ne features (old API calls are frozen
and deprecated).

FIXME: add more regression tests here.

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@353 36d66b0a-2a48-0410-832c-cd162a569da5
This commit is contained in:
Milan Broz
2010-10-27 10:55:11 +00:00
parent 3ae161df5d
commit c3f3865485
2 changed files with 137 additions and 105 deletions

View File

@@ -1,3 +1,7 @@
2010-10-27 Milan Broz <mbroz@redhat.com>
* Rewrite cryptsetup luksFormat, luksOpen, luksAddKey to use new API
to allow adding new features.
2010-10-17 Milan Broz <mbroz@redhat.com>
* Add crypt_get_device_name() to API (get underlying device name).
* Change detection for static libraries.

View File

@@ -295,30 +295,11 @@ static int action_status(int arg)
return r;
}
static int _action_luksFormat_generateMK()
{
struct crypt_options options = {
.key_size = (opt_key_size ?: DEFAULT_LUKS1_KEYBITS) / 8,
.key_slot = opt_key_slot,
.device = action_argv[0],
.cipher = opt_cipher ?: DEFAULT_CIPHER(LUKS1),
.hash = opt_hash ?: DEFAULT_LUKS1_HASH,
.new_key_file = opt_key_file ?: (action_argc > 1 ? action_argv[1] : NULL),
.flags = opt_verify_passphrase ? CRYPT_FLAG_VERIFY : (!opt_batch_mode?CRYPT_FLAG_VERIFY_IF_POSSIBLE : 0),
.iteration_time = opt_iteration_time,
.timeout = opt_timeout,
.align_payload = opt_align_payload,
.icb = &cmd_icb,
};
return crypt_luksFormat(&options);
}
static int _read_mk(const char *file, char **key, int keysize)
{
int fd;
*key = malloc(keysize);
*key = crypt_safe_alloc(keysize);
if (!*key)
return -ENOMEM;
@@ -330,106 +311,153 @@ static int _read_mk(const char *file, char **key, int keysize)
if ((read(fd, *key, keysize) != keysize)) {
log_err("Cannot read %d bytes from keyfile %s.\n", keysize, file);
close(fd);
memset(*key, 0, keysize);
free(*key);
crypt_safe_free(*key);
return -EINVAL;
}
close(fd);
return 0;
}
static int _action_luksFormat_useMK()
static int action_luksFormat(int arg)
{
int r = -EINVAL, keysize;
char *key = NULL, cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
char *msg = NULL, *key = NULL, cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
const char *key_file = NULL;
char *password = NULL;
unsigned int passwordLen;
struct crypt_device *cd = NULL;
struct crypt_params_luks1 params = {
.hash = opt_hash ?: DEFAULT_LUKS1_HASH,
.data_alignment = opt_align_payload,
};
/* Avoid overwriting possibly wrong part of device than user requested by rejecting these options */
if (opt_offset || opt_skip) {
log_err("Options --offset and --skip are not supported for luksFormat.\n");
r = -EINVAL;
goto out;;
}
if (action_argc > 1) {
key_file = action_argv[1];
if (opt_key_file)
log_err(_("Option --key-file takes precedence over specified key file argument.\n"));
} else
key_file = opt_key_file;
if(asprintf(&msg, _("This will overwrite data on %s irrevocably."), action_argv[0]) == -1) {
log_err(_("memory allocation error in action_luksFormat"));
r = -ENOMEM;
goto out;
}
r = yesDialog(msg);
free(msg);
if (!r) {
r = -EINVAL;
goto out;
}
r = crypt_parse_name_and_mode(opt_cipher ?: DEFAULT_CIPHER(LUKS1),
cipher, cipher_mode);
if (r < 0) {
log_err("No known cipher specification pattern detected.\n");
return r;
goto out;
}
keysize = (opt_key_size ?: DEFAULT_LUKS1_KEYBITS) / 8;
if (_read_mk(opt_master_key_file, &key, keysize) < 0)
return -EINVAL;
if ((r = crypt_init(&cd, action_argv[0])))
goto out;
crypt_set_log_callback(cd, _log, NULL);
keysize = (opt_key_size ?: DEFAULT_LUKS1_KEYBITS) / 8;
crypt_set_password_verify(cd, 1);
crypt_set_timeout(cd, opt_timeout);
if (opt_iteration_time)
crypt_set_iterarion_time(cd, opt_iteration_time);
if ((r = crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, keysize, &params)))
if (opt_master_key_file) {
r = _read_mk(opt_master_key_file, &key, keysize);
if (r < 0)
goto out;
r = crypt_keyslot_add_by_volume_key(cd, opt_key_slot, key, keysize, NULL, 0);
r = crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode,
NULL, key, keysize, &params);
if (r < 0)
goto out;
r = crypt_keyslot_add_by_volume_key(cd, opt_key_slot,
key, keysize, NULL, 0);
} else {
crypt_get_key(_("Enter LUKS passphrase: "),
&password, &passwordLen, 0,
key_file, opt_timeout,
opt_verify_passphrase && !opt_batch_mode,
cd);
if(!password) {
r = -EINVAL;
goto out;
}
r = crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode,
NULL, NULL, keysize, &params);
if (r < 0)
goto out;
/* Add keyslot using internally stored volume key generated during format */
r = crypt_keyslot_add_by_volume_key(cd, opt_key_slot,
NULL, 0, password, passwordLen);
}
out:
crypt_free(cd);
if (key) {
memset(key, 0, keysize);
free(key);
}
return r;
}
crypt_safe_free(key);
crypt_safe_free(password);
static int action_luksFormat(int arg)
{
int r = 0; char *msg = NULL;
/* Avoid overwriting possibly wrong part of device than user requested by rejecting these options */
if (opt_offset || opt_skip) {
log_err("Options --offset and --skip are not supported for luksFormat.\n");
return -EINVAL;
}
if (action_argc > 1 && opt_key_file)
log_err(_("Option --key-file takes precedence over specified key file argument.\n"));
if(asprintf(&msg, _("This will overwrite data on %s irrevocably."), action_argv[0]) == -1) {
log_err(_("memory allocation error in action_luksFormat"));
return -ENOMEM;
}
r = yesDialog(msg);
free(msg);
if (!r)
return -EINVAL;
if (opt_master_key_file)
return _action_luksFormat_useMK();
else
return _action_luksFormat_generateMK();
return (r < 0) ? r : 0;
}
static int action_luksOpen(int arg)
{
struct crypt_options options = {
.name = action_argv[1],
.device = action_argv[0],
.key_file = opt_key_file,
.key_size = opt_key_file ? (opt_key_size / 8) : 0, /* limit bytes read from keyfile */
.timeout = opt_timeout,
.tries = opt_key_file ? 1 : opt_tries, /* verify is usefull only for tty */
.icb = &cmd_icb,
};
struct crypt_device *cd = NULL;
uint32_t flags = 0;
int r;
if ((r = crypt_init(&cd, action_argv[0])))
goto out;
crypt_set_log_callback(cd, _log, NULL);
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
goto out;
crypt_set_timeout(cd, opt_timeout);
crypt_set_password_retry(cd, opt_tries);
if (opt_iteration_time)
crypt_set_iterarion_time(cd, opt_iteration_time);
if (opt_readonly)
options.flags |= CRYPT_FLAG_READONLY;
flags |= CRYPT_ACTIVATE_READONLY;
if (opt_non_exclusive)
log_err(_("Obsolete option --non-exclusive is ignored.\n"));
return crypt_luksOpen(&options);
if (opt_key_file) {
crypt_set_password_retry(cd, 1);
/* limit bytes read from keyfile using opt_key_size*/
r = crypt_activate_by_keyfile(cd, action_argv[1],
CRYPT_ANY_SLOT, opt_key_file, opt_key_size / 8,
flags);
} else
r = crypt_activate_by_passphrase(cd, action_argv[1],
CRYPT_ANY_SLOT, NULL, 0, flags);
out:
crypt_free(cd);
return (r < 0) ? r : 0;
}
/* FIXME: keyslot operation needs better get_key() implementation. Use old API for now */
static int action_luksDelKey(int arg)
{
log_err("luksDelKey is a deprecated action name.\nPlease use luksKillSlot.\n");
@@ -464,54 +492,47 @@ static int action_luksRemoveKey(int arg)
return crypt_luksRemoveKey(&options);
}
static int _action_luksAddKey_useMK()
static int action_luksAddKey(int arg)
{
int r = -EINVAL, keysize = 0;
char *key = NULL;
const char *opt_new_key_file = (action_argc > 1 ? action_argv[1] : NULL);
struct crypt_device *cd = NULL;
if ((r = crypt_init(&cd, action_argv[0])))
goto out;
crypt_set_log_callback(cd, _log, NULL);
crypt_set_confirm_callback(cd, _yesDialog, NULL);
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
goto out;
keysize = crypt_get_volume_key_size(cd);
crypt_set_password_verify(cd, 1);
crypt_set_password_verify(cd, opt_verify_passphrase ? 1 : 0);
crypt_set_timeout(cd, opt_timeout);
if (opt_iteration_time)
crypt_set_iterarion_time(cd, opt_iteration_time);
if (opt_master_key_file) {
if (_read_mk(opt_master_key_file, &key, keysize) < 0)
goto out;
r = crypt_keyslot_add_by_volume_key(cd, opt_key_slot, key, keysize, NULL, 0);
r = crypt_keyslot_add_by_volume_key(cd, opt_key_slot,
key, keysize, NULL, 0);
} else if (opt_key_file || opt_new_key_file) {
r = crypt_keyslot_add_by_keyfile(cd, opt_key_slot,
opt_key_file, 0,
opt_new_key_file, 0);
} else {
r = crypt_keyslot_add_by_passphrase(cd, opt_key_slot,
NULL, 0, NULL, 0);
}
out:
crypt_free(cd);
if (key) {
memset(key, 0, keysize);
free(key);
}
return r;
}
crypt_safe_free(key);
static int action_luksAddKey(int arg)
{
struct crypt_options options = {
.device = action_argv[0],
.new_key_file = action_argc>1?action_argv[1]:NULL,
.key_file = opt_key_file,
.key_slot = opt_key_slot,
.flags = opt_verify_passphrase ? CRYPT_FLAG_VERIFY : (!opt_batch_mode?CRYPT_FLAG_VERIFY_IF_POSSIBLE : 0),
.iteration_time = opt_iteration_time,
.timeout = opt_timeout,
.icb = &cmd_icb,
};
if (opt_master_key_file)
return _action_luksAddKey_useMK();
else
return crypt_luksAddKey(&options);
return (r < 0) ? r : 0;
}
static int action_isLuks(int arg)
@@ -784,6 +805,13 @@ int main(int argc, char **argv)
_("Key size must be a multiple of 8 bits"),
poptGetInvocationName(popt_context));
/* FIXME: use per format define here */
if (opt_key_slot != CRYPT_ANY_SLOT &&
(opt_key_slot < 0 || opt_key_slot > 8)) {
usage(popt_context, 1, _("Key slot is invalid."),
poptGetInvocationName(popt_context));
}
if (!(aname = (char *)poptGetArg(popt_context)))
usage(popt_context, 1, _("Argument <action> missing."),
poptGetInvocationName(popt_context));