mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-28 20:02:17 +00:00
dm crypt: support using encrypted keys
Allow one to use "encrypted" in addition to "user" and "logon" key types for device encryption. Signed-off-by: Dmitry Baryshkov <dmitry_baryshkov@mentor.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
This commit is contained in:
parent
2ef96a5bb1
commit
27f5411a71
2 changed files with 58 additions and 19 deletions
|
@ -269,6 +269,7 @@ config DM_UNSTRIPED
|
||||||
config DM_CRYPT
|
config DM_CRYPT
|
||||||
tristate "Crypt target support"
|
tristate "Crypt target support"
|
||||||
depends on BLK_DEV_DM
|
depends on BLK_DEV_DM
|
||||||
|
depends on (ENCRYPTED_KEYS || ENCRYPTED_KEYS=n)
|
||||||
select CRYPTO
|
select CRYPTO
|
||||||
select CRYPTO_CBC
|
select CRYPTO_CBC
|
||||||
select CRYPTO_ESSIV
|
select CRYPTO_ESSIV
|
||||||
|
|
|
@ -34,7 +34,9 @@
|
||||||
#include <crypto/aead.h>
|
#include <crypto/aead.h>
|
||||||
#include <crypto/authenc.h>
|
#include <crypto/authenc.h>
|
||||||
#include <linux/rtnetlink.h> /* for struct rtattr and RTA macros only */
|
#include <linux/rtnetlink.h> /* for struct rtattr and RTA macros only */
|
||||||
|
#include <linux/key-type.h>
|
||||||
#include <keys/user-type.h>
|
#include <keys/user-type.h>
|
||||||
|
#include <keys/encrypted-type.h>
|
||||||
|
|
||||||
#include <linux/device-mapper.h>
|
#include <linux/device-mapper.h>
|
||||||
|
|
||||||
|
@ -2215,12 +2217,47 @@ static bool contains_whitespace(const char *str)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int set_key_user(struct crypt_config *cc, struct key *key)
|
||||||
|
{
|
||||||
|
const struct user_key_payload *ukp;
|
||||||
|
|
||||||
|
ukp = user_key_payload_locked(key);
|
||||||
|
if (!ukp)
|
||||||
|
return -EKEYREVOKED;
|
||||||
|
|
||||||
|
if (cc->key_size != ukp->datalen)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
memcpy(cc->key, ukp->data, cc->key_size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_ENCRYPTED_KEYS) || defined(CONFIG_ENCRYPTED_KEYS_MODULE)
|
||||||
|
static int set_key_encrypted(struct crypt_config *cc, struct key *key)
|
||||||
|
{
|
||||||
|
const struct encrypted_key_payload *ekp;
|
||||||
|
|
||||||
|
ekp = key->payload.data[0];
|
||||||
|
if (!ekp)
|
||||||
|
return -EKEYREVOKED;
|
||||||
|
|
||||||
|
if (cc->key_size != ekp->decrypted_datalen)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
memcpy(cc->key, ekp->decrypted_data, cc->key_size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_ENCRYPTED_KEYS */
|
||||||
|
|
||||||
static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string)
|
static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string)
|
||||||
{
|
{
|
||||||
char *new_key_string, *key_desc;
|
char *new_key_string, *key_desc;
|
||||||
int ret;
|
int ret;
|
||||||
|
struct key_type *type;
|
||||||
struct key *key;
|
struct key *key;
|
||||||
const struct user_key_payload *ukp;
|
int (*set_key)(struct crypt_config *cc, struct key *key);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reject key_string with whitespace. dm core currently lacks code for
|
* Reject key_string with whitespace. dm core currently lacks code for
|
||||||
|
@ -2236,16 +2273,26 @@ static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string
|
||||||
if (!key_desc || key_desc == key_string || !strlen(key_desc + 1))
|
if (!key_desc || key_desc == key_string || !strlen(key_desc + 1))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (strncmp(key_string, "logon:", key_desc - key_string + 1) &&
|
if (!strncmp(key_string, "logon:", key_desc - key_string + 1)) {
|
||||||
strncmp(key_string, "user:", key_desc - key_string + 1))
|
type = &key_type_logon;
|
||||||
|
set_key = set_key_user;
|
||||||
|
} else if (!strncmp(key_string, "user:", key_desc - key_string + 1)) {
|
||||||
|
type = &key_type_user;
|
||||||
|
set_key = set_key_user;
|
||||||
|
#if defined(CONFIG_ENCRYPTED_KEYS) || defined(CONFIG_ENCRYPTED_KEYS_MODULE)
|
||||||
|
} else if (!strncmp(key_string, "encrypted:", key_desc - key_string + 1)) {
|
||||||
|
type = &key_type_encrypted;
|
||||||
|
set_key = set_key_encrypted;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
new_key_string = kstrdup(key_string, GFP_KERNEL);
|
new_key_string = kstrdup(key_string, GFP_KERNEL);
|
||||||
if (!new_key_string)
|
if (!new_key_string)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
key = request_key(key_string[0] == 'l' ? &key_type_logon : &key_type_user,
|
key = request_key(type, key_desc + 1, NULL);
|
||||||
key_desc + 1, NULL);
|
|
||||||
if (IS_ERR(key)) {
|
if (IS_ERR(key)) {
|
||||||
kzfree(new_key_string);
|
kzfree(new_key_string);
|
||||||
return PTR_ERR(key);
|
return PTR_ERR(key);
|
||||||
|
@ -2253,23 +2300,14 @@ static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string
|
||||||
|
|
||||||
down_read(&key->sem);
|
down_read(&key->sem);
|
||||||
|
|
||||||
ukp = user_key_payload_locked(key);
|
ret = set_key(cc, key);
|
||||||
if (!ukp) {
|
if (ret < 0) {
|
||||||
up_read(&key->sem);
|
up_read(&key->sem);
|
||||||
key_put(key);
|
key_put(key);
|
||||||
kzfree(new_key_string);
|
kzfree(new_key_string);
|
||||||
return -EKEYREVOKED;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cc->key_size != ukp->datalen) {
|
|
||||||
up_read(&key->sem);
|
|
||||||
key_put(key);
|
|
||||||
kzfree(new_key_string);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(cc->key, ukp->data, cc->key_size);
|
|
||||||
|
|
||||||
up_read(&key->sem);
|
up_read(&key->sem);
|
||||||
key_put(key);
|
key_put(key);
|
||||||
|
|
||||||
|
@ -2323,7 +2361,7 @@ static int get_key_size(char **key_string)
|
||||||
return (*key_string[0] == ':') ? -EINVAL : strlen(*key_string) >> 1;
|
return (*key_string[0] == ':') ? -EINVAL : strlen(*key_string) >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif /* CONFIG_KEYS */
|
||||||
|
|
||||||
static int crypt_set_key(struct crypt_config *cc, char *key)
|
static int crypt_set_key(struct crypt_config *cc, char *key)
|
||||||
{
|
{
|
||||||
|
@ -3282,7 +3320,7 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
|
||||||
|
|
||||||
static struct target_type crypt_target = {
|
static struct target_type crypt_target = {
|
||||||
.name = "crypt",
|
.name = "crypt",
|
||||||
.version = {1, 20, 0},
|
.version = {1, 21, 0},
|
||||||
.module = THIS_MODULE,
|
.module = THIS_MODULE,
|
||||||
.ctr = crypt_ctr,
|
.ctr = crypt_ctr,
|
||||||
.dtr = crypt_dtr,
|
.dtr = crypt_dtr,
|
||||||
|
|
Loading…
Reference in a new issue