Skip to content

Commit c538f6e

Browse files
onikosnitm
authored andcommitted
dm crypt: add ability to use keys from the kernel key retention service
The kernel key service is a generic way to store keys for the use of other subsystems. Currently there is no way to use kernel keys in dm-crypt. This patch aims to fix that. Instead of key userspace may pass a key description with preceding ':'. So message that constructs encryption mapping now looks like this: <cipher> [<key>|:<key_string>] <iv_offset> <dev_path> <start> [<#opt_params> <opt_params>] where <key_string> is in format: <key_size>:<key_type>:<key_description> Currently we only support two elementary key types: 'user' and 'logon'. Keys may be loaded in dm-crypt either via <key_string> or using classical method and pass the key in hex representation directly. dm-crypt device initialised with a key passed in hex representation may be replaced with key passed in key_string format and vice versa. (Based on original work by Andrey Ryabinin) Signed-off-by: Ondrej Kozina <[email protected]> Reviewed-by: David Howells <[email protected]> Signed-off-by: Mike Snitzer <[email protected]>
1 parent 0637018 commit c538f6e

File tree

2 files changed

+170
-14
lines changed

2 files changed

+170
-14
lines changed

Documentation/device-mapper/dm-crypt.txt

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,30 @@ Parameters: <cipher> <key> <iv_offset> <device path> \
2121
/proc/crypto contains supported crypto modes
2222

2323
<key>
24-
Key used for encryption. It is encoded as a hexadecimal number.
24+
Key used for encryption. It is encoded either as a hexadecimal number
25+
or it can be passed as <key_string> prefixed with single colon
26+
character (':') for keys residing in kernel keyring service.
2527
You can only use key sizes that are valid for the selected cipher
2628
in combination with the selected iv mode.
2729
Note that for some iv modes the key string can contain additional
2830
keys (for example IV seed) so the key contains more parts concatenated
2931
into a single string.
3032

33+
<key_string>
34+
The kernel keyring key is identified by string in following format:
35+
<key_size>:<key_type>:<key_description>.
36+
37+
<key_size>
38+
The encryption key size in bytes. The kernel key payload size must match
39+
the value passed in <key_size>.
40+
41+
<key_type>
42+
Either 'logon' or 'user' kernel key type.
43+
44+
<key_description>
45+
The kernel keyring key description crypt target should look for
46+
when loading key of <key_type>.
47+
3148
<keycount>
3249
Multi-key compatibility mode. You can define <keycount> keys and
3350
then sectors are encrypted according to their offsets (sector 0 uses key0;
@@ -88,6 +105,12 @@ https://gitlab.com/cryptsetup/cryptsetup
88105
dmsetup create crypt1 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0"
89106
]]
90107

108+
[[
109+
#!/bin/sh
110+
# Create a crypt device using dmsetup when encryption key is stored in keyring service
111+
dmsetup create crypt2 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 :32:logon:my_prefix:my_key 0 $1 0"
112+
]]
113+
91114
[[
92115
#!/bin/sh
93116
# Create a crypt device using cryptsetup and LUKS header with default cipher

drivers/md/dm-crypt.c

Lines changed: 146 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/module.h>
1313
#include <linux/init.h>
1414
#include <linux/kernel.h>
15+
#include <linux/key.h>
1516
#include <linux/bio.h>
1617
#include <linux/blkdev.h>
1718
#include <linux/mempool.h>
@@ -29,6 +30,7 @@
2930
#include <crypto/md5.h>
3031
#include <crypto/algapi.h>
3132
#include <crypto/skcipher.h>
33+
#include <keys/user-type.h>
3234

3335
#include <linux/device-mapper.h>
3436

@@ -140,6 +142,7 @@ struct crypt_config {
140142

141143
char *cipher;
142144
char *cipher_string;
145+
char *key_string;
143146

144147
const struct crypt_iv_operations *iv_gen_ops;
145148
union {
@@ -1484,22 +1487,134 @@ static int crypt_setkey(struct crypt_config *cc)
14841487
return err;
14851488
}
14861489

1490+
#ifdef CONFIG_KEYS
1491+
1492+
static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string)
1493+
{
1494+
char *new_key_string, *key_desc;
1495+
int ret;
1496+
struct key *key;
1497+
const struct user_key_payload *ukp;
1498+
1499+
/* look for next ':' separating key_type from key_description */
1500+
key_desc = strpbrk(key_string, ":");
1501+
if (!key_desc || key_desc == key_string || !strlen(key_desc + 1))
1502+
return -EINVAL;
1503+
1504+
if (strncmp(key_string, "logon:", key_desc - key_string + 1) &&
1505+
strncmp(key_string, "user:", key_desc - key_string + 1))
1506+
return -EINVAL;
1507+
1508+
new_key_string = kstrdup(key_string, GFP_KERNEL);
1509+
if (!new_key_string)
1510+
return -ENOMEM;
1511+
1512+
key = request_key(key_string[0] == 'l' ? &key_type_logon : &key_type_user,
1513+
key_desc + 1, NULL);
1514+
if (IS_ERR(key)) {
1515+
kzfree(new_key_string);
1516+
return PTR_ERR(key);
1517+
}
1518+
1519+
rcu_read_lock();
1520+
1521+
ukp = user_key_payload(key);
1522+
if (!ukp) {
1523+
rcu_read_unlock();
1524+
key_put(key);
1525+
kzfree(new_key_string);
1526+
return -EKEYREVOKED;
1527+
}
1528+
1529+
if (cc->key_size != ukp->datalen) {
1530+
rcu_read_unlock();
1531+
key_put(key);
1532+
kzfree(new_key_string);
1533+
return -EINVAL;
1534+
}
1535+
1536+
memcpy(cc->key, ukp->data, cc->key_size);
1537+
1538+
rcu_read_unlock();
1539+
key_put(key);
1540+
1541+
/* clear the flag since following operations may invalidate previously valid key */
1542+
clear_bit(DM_CRYPT_KEY_VALID, &cc->flags);
1543+
1544+
ret = crypt_setkey(cc);
1545+
1546+
/* wipe the kernel key payload copy in each case */
1547+
memset(cc->key, 0, cc->key_size * sizeof(u8));
1548+
1549+
if (!ret) {
1550+
set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
1551+
kzfree(cc->key_string);
1552+
cc->key_string = new_key_string;
1553+
} else
1554+
kzfree(new_key_string);
1555+
1556+
return ret;
1557+
}
1558+
1559+
static int get_key_size(char **key_string)
1560+
{
1561+
char *colon, dummy;
1562+
int ret;
1563+
1564+
if (*key_string[0] != ':')
1565+
return strlen(*key_string) >> 1;
1566+
1567+
/* look for next ':' in key string */
1568+
colon = strpbrk(*key_string + 1, ":");
1569+
if (!colon)
1570+
return -EINVAL;
1571+
1572+
if (sscanf(*key_string + 1, "%u%c", &ret, &dummy) != 2 || dummy != ':')
1573+
return -EINVAL;
1574+
1575+
*key_string = colon;
1576+
1577+
/* remaining key string should be :<logon|user>:<key_desc> */
1578+
1579+
return ret;
1580+
}
1581+
1582+
#else
1583+
1584+
static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string)
1585+
{
1586+
return -EINVAL;
1587+
}
1588+
1589+
static int get_key_size(char **key_string)
1590+
{
1591+
return (*key_string[0] == ':') ? -EINVAL : strlen(*key_string) >> 1;
1592+
}
1593+
1594+
#endif
1595+
14871596
static int crypt_set_key(struct crypt_config *cc, char *key)
14881597
{
14891598
int r = -EINVAL;
14901599
int key_string_len = strlen(key);
14911600

1492-
/* The key size may not be changed. */
1493-
if (cc->key_size != (key_string_len >> 1))
1494-
goto out;
1495-
14961601
/* Hyphen (which gives a key_size of zero) means there is no key. */
14971602
if (!cc->key_size && strcmp(key, "-"))
14981603
goto out;
14991604

1605+
/* ':' means the key is in kernel keyring, short-circuit normal key processing */
1606+
if (key[0] == ':') {
1607+
r = crypt_set_keyring_key(cc, key + 1);
1608+
goto out;
1609+
}
1610+
15001611
/* clear the flag since following operations may invalidate previously valid key */
15011612
clear_bit(DM_CRYPT_KEY_VALID, &cc->flags);
15021613

1614+
/* wipe references to any kernel keyring key */
1615+
kzfree(cc->key_string);
1616+
cc->key_string = NULL;
1617+
15031618
if (cc->key_size && crypt_decode_key(cc->key, key, cc->key_size) < 0)
15041619
goto out;
15051620

@@ -1518,6 +1633,8 @@ static int crypt_wipe_key(struct crypt_config *cc)
15181633
{
15191634
clear_bit(DM_CRYPT_KEY_VALID, &cc->flags);
15201635
memset(&cc->key, 0, cc->key_size * sizeof(u8));
1636+
kzfree(cc->key_string);
1637+
cc->key_string = NULL;
15211638

15221639
return crypt_setkey(cc);
15231640
}
@@ -1555,6 +1672,7 @@ static void crypt_dtr(struct dm_target *ti)
15551672

15561673
kzfree(cc->cipher);
15571674
kzfree(cc->cipher_string);
1675+
kzfree(cc->key_string);
15581676

15591677
/* Must zero key material before freeing */
15601678
kzfree(cc);
@@ -1723,12 +1841,13 @@ static int crypt_ctr_cipher(struct dm_target *ti,
17231841

17241842
/*
17251843
* Construct an encryption mapping:
1726-
* <cipher> <key> <iv_offset> <dev_path> <start>
1844+
* <cipher> [<key>|:<key_size>:<user|logon>:<key_description>] <iv_offset> <dev_path> <start>
17271845
*/
17281846
static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
17291847
{
17301848
struct crypt_config *cc;
1731-
unsigned int key_size, opt_params;
1849+
int key_size;
1850+
unsigned int opt_params;
17321851
unsigned long long tmpll;
17331852
int ret;
17341853
size_t iv_size_padding;
@@ -1745,7 +1864,11 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
17451864
return -EINVAL;
17461865
}
17471866

1748-
key_size = strlen(argv[1]) >> 1;
1867+
key_size = get_key_size(&argv[1]);
1868+
if (key_size < 0) {
1869+
ti->error = "Cannot parse key size";
1870+
return -EINVAL;
1871+
}
17491872

17501873
cc = kzalloc(sizeof(*cc) + key_size * sizeof(u8), GFP_KERNEL);
17511874
if (!cc) {
@@ -1952,10 +2075,13 @@ static void crypt_status(struct dm_target *ti, status_type_t type,
19522075
case STATUSTYPE_TABLE:
19532076
DMEMIT("%s ", cc->cipher_string);
19542077

1955-
if (cc->key_size > 0)
1956-
for (i = 0; i < cc->key_size; i++)
1957-
DMEMIT("%02x", cc->key[i]);
1958-
else
2078+
if (cc->key_size > 0) {
2079+
if (cc->key_string)
2080+
DMEMIT(":%u:%s", cc->key_size, cc->key_string);
2081+
else
2082+
for (i = 0; i < cc->key_size; i++)
2083+
DMEMIT("%02x", cc->key[i]);
2084+
} else
19592085
DMEMIT("-");
19602086

19612087
DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset,
@@ -2011,7 +2137,7 @@ static void crypt_resume(struct dm_target *ti)
20112137
static int crypt_message(struct dm_target *ti, unsigned argc, char **argv)
20122138
{
20132139
struct crypt_config *cc = ti->private;
2014-
int ret = -EINVAL;
2140+
int key_size, ret = -EINVAL;
20152141

20162142
if (argc < 2)
20172143
goto error;
@@ -2022,6 +2148,13 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv)
20222148
return -EINVAL;
20232149
}
20242150
if (argc == 3 && !strcasecmp(argv[1], "set")) {
2151+
/* The key size may not be changed. */
2152+
key_size = get_key_size(&argv[2]);
2153+
if (key_size < 0 || cc->key_size != key_size) {
2154+
memset(argv[2], '0', strlen(argv[2]));
2155+
return -EINVAL;
2156+
}
2157+
20252158
ret = crypt_set_key(cc, argv[2]);
20262159
if (ret)
20272160
return ret;
@@ -2065,7 +2198,7 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
20652198

20662199
static struct target_type crypt_target = {
20672200
.name = "crypt",
2068-
.version = {1, 14, 1},
2201+
.version = {1, 15, 0},
20692202
.module = THIS_MODULE,
20702203
.ctr = crypt_ctr,
20712204
.dtr = crypt_dtr,

0 commit comments

Comments
 (0)