mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-11 19:00:02 +01:00
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:
@@ -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>
|
2010-10-17 Milan Broz <mbroz@redhat.com>
|
||||||
* Add crypt_get_device_name() to API (get underlying device name).
|
* Add crypt_get_device_name() to API (get underlying device name).
|
||||||
* Change detection for static libraries.
|
* Change detection for static libraries.
|
||||||
|
|||||||
232
src/cryptsetup.c
232
src/cryptsetup.c
@@ -295,30 +295,11 @@ static int action_status(int arg)
|
|||||||
return r;
|
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)
|
static int _read_mk(const char *file, char **key, int keysize)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
*key = malloc(keysize);
|
*key = crypt_safe_alloc(keysize);
|
||||||
if (!*key)
|
if (!*key)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@@ -330,106 +311,153 @@ static int _read_mk(const char *file, char **key, int keysize)
|
|||||||
if ((read(fd, *key, keysize) != keysize)) {
|
if ((read(fd, *key, keysize) != keysize)) {
|
||||||
log_err("Cannot read %d bytes from keyfile %s.\n", keysize, file);
|
log_err("Cannot read %d bytes from keyfile %s.\n", keysize, file);
|
||||||
close(fd);
|
close(fd);
|
||||||
memset(*key, 0, keysize);
|
crypt_safe_free(*key);
|
||||||
free(*key);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _action_luksFormat_useMK()
|
static int action_luksFormat(int arg)
|
||||||
{
|
{
|
||||||
int r = -EINVAL, keysize;
|
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_device *cd = NULL;
|
||||||
struct crypt_params_luks1 params = {
|
struct crypt_params_luks1 params = {
|
||||||
.hash = opt_hash ?: DEFAULT_LUKS1_HASH,
|
.hash = opt_hash ?: DEFAULT_LUKS1_HASH,
|
||||||
.data_alignment = opt_align_payload,
|
.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),
|
r = crypt_parse_name_and_mode(opt_cipher ?: DEFAULT_CIPHER(LUKS1),
|
||||||
cipher, cipher_mode);
|
cipher, cipher_mode);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_err("No known cipher specification pattern detected.\n");
|
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])))
|
if ((r = crypt_init(&cd, action_argv[0])))
|
||||||
goto out;
|
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_password_verify(cd, 1);
|
||||||
crypt_set_timeout(cd, opt_timeout);
|
crypt_set_timeout(cd, opt_timeout);
|
||||||
if (opt_iteration_time)
|
if (opt_iteration_time)
|
||||||
crypt_set_iterarion_time(cd, opt_iteration_time);
|
crypt_set_iterarion_time(cd, opt_iteration_time);
|
||||||
|
|
||||||
if ((r = crypt_format(cd, CRYPT_LUKS1, cipher, cipher_mode, NULL, key, keysize, ¶ms)))
|
if (opt_master_key_file) {
|
||||||
|
r = _read_mk(opt_master_key_file, &key, keysize);
|
||||||
|
if (r < 0)
|
||||||
goto out;
|
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, ¶ms);
|
||||||
|
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, ¶ms);
|
||||||
|
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:
|
out:
|
||||||
|
|
||||||
crypt_free(cd);
|
crypt_free(cd);
|
||||||
if (key) {
|
crypt_safe_free(key);
|
||||||
memset(key, 0, keysize);
|
crypt_safe_free(password);
|
||||||
free(key);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int action_luksFormat(int arg)
|
return (r < 0) ? r : 0;
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int action_luksOpen(int arg)
|
static int action_luksOpen(int arg)
|
||||||
{
|
{
|
||||||
struct crypt_options options = {
|
struct crypt_device *cd = NULL;
|
||||||
.name = action_argv[1],
|
uint32_t flags = 0;
|
||||||
.device = action_argv[0],
|
int r;
|
||||||
.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,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
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)
|
if (opt_readonly)
|
||||||
options.flags |= CRYPT_FLAG_READONLY;
|
flags |= CRYPT_ACTIVATE_READONLY;
|
||||||
|
|
||||||
if (opt_non_exclusive)
|
if (opt_non_exclusive)
|
||||||
log_err(_("Obsolete option --non-exclusive is ignored.\n"));
|
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)
|
static int action_luksDelKey(int arg)
|
||||||
{
|
{
|
||||||
log_err("luksDelKey is a deprecated action name.\nPlease use luksKillSlot.\n");
|
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);
|
return crypt_luksRemoveKey(&options);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _action_luksAddKey_useMK()
|
static int action_luksAddKey(int arg)
|
||||||
{
|
{
|
||||||
int r = -EINVAL, keysize = 0;
|
int r = -EINVAL, keysize = 0;
|
||||||
char *key = NULL;
|
char *key = NULL;
|
||||||
|
const char *opt_new_key_file = (action_argc > 1 ? action_argv[1] : NULL);
|
||||||
struct crypt_device *cd = NULL;
|
struct crypt_device *cd = NULL;
|
||||||
|
|
||||||
if ((r = crypt_init(&cd, action_argv[0])))
|
if ((r = crypt_init(&cd, action_argv[0])))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
crypt_set_log_callback(cd, _log, NULL);
|
||||||
|
crypt_set_confirm_callback(cd, _yesDialog, NULL);
|
||||||
|
|
||||||
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
|
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
keysize = crypt_get_volume_key_size(cd);
|
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);
|
crypt_set_timeout(cd, opt_timeout);
|
||||||
if (opt_iteration_time)
|
if (opt_iteration_time)
|
||||||
crypt_set_iterarion_time(cd, 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)
|
if (_read_mk(opt_master_key_file, &key, keysize) < 0)
|
||||||
goto out;
|
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:
|
out:
|
||||||
crypt_free(cd);
|
crypt_free(cd);
|
||||||
if (key) {
|
crypt_safe_free(key);
|
||||||
memset(key, 0, keysize);
|
|
||||||
free(key);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int action_luksAddKey(int arg)
|
return (r < 0) ? r : 0;
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int action_isLuks(int arg)
|
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"),
|
_("Key size must be a multiple of 8 bits"),
|
||||||
poptGetInvocationName(popt_context));
|
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)))
|
if (!(aname = (char *)poptGetArg(popt_context)))
|
||||||
usage(popt_context, 1, _("Argument <action> missing."),
|
usage(popt_context, 1, _("Argument <action> missing."),
|
||||||
poptGetInvocationName(popt_context));
|
poptGetInvocationName(popt_context));
|
||||||
|
|||||||
Reference in New Issue
Block a user