]> Git Repo - linux.git/commitdiff
dm crypt: support using encrypted keys
authorDmitry Baryshkov <[email protected]>
Mon, 20 Apr 2020 13:46:59 +0000 (16:46 +0300)
committerMike Snitzer <[email protected]>
Fri, 15 May 2020 14:29:34 +0000 (10:29 -0400)
Allow one to use "encrypted" in addition to "user" and "logon" key
types for device encryption.

Signed-off-by: Dmitry Baryshkov <[email protected]>
Signed-off-by: Mike Snitzer <[email protected]>
drivers/md/Kconfig
drivers/md/dm-crypt.c

index d6d5ab23c0883497d4663f24eb33b9474281f66d..8b0c646d2f596f68619e7686cd5545f9390ac586 100644 (file)
@@ -269,6 +269,7 @@ config DM_UNSTRIPED
 config DM_CRYPT
        tristate "Crypt target support"
        depends on BLK_DEV_DM
+       depends on (ENCRYPTED_KEYS || ENCRYPTED_KEYS=n)
        select CRYPTO
        select CRYPTO_CBC
        select CRYPTO_ESSIV
index 3df90daba89eed000b563a84fd1aee09f69587ea..91787cde369bf387a479bf7a3091fbe5bc3fc883 100644 (file)
@@ -34,7 +34,9 @@
 #include <crypto/aead.h>
 #include <crypto/authenc.h>
 #include <linux/rtnetlink.h> /* for struct rtattr and RTA macros only */
+#include <linux/key-type.h>
 #include <keys/user-type.h>
+#include <keys/encrypted-type.h>
 
 #include <linux/device-mapper.h>
 
@@ -2215,12 +2217,47 @@ static bool contains_whitespace(const char *str)
        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)
 {
        char *new_key_string, *key_desc;
        int ret;
+       struct key_type *type;
        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
@@ -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))
                return -EINVAL;
 
-       if (strncmp(key_string, "logon:", key_desc - key_string + 1) &&
-           strncmp(key_string, "user:", key_desc - key_string + 1))
+       if (!strncmp(key_string, "logon:", 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;
+       }
 
        new_key_string = kstrdup(key_string, GFP_KERNEL);
        if (!new_key_string)
                return -ENOMEM;
 
-       key = request_key(key_string[0] == 'l' ? &key_type_logon : &key_type_user,
-                         key_desc + 1, NULL);
+       key = request_key(type, key_desc + 1, NULL);
        if (IS_ERR(key)) {
                kzfree(new_key_string);
                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);
 
-       ukp = user_key_payload_locked(key);
-       if (!ukp) {
-               up_read(&key->sem);
-               key_put(key);
-               kzfree(new_key_string);
-               return -EKEYREVOKED;
-       }
-
-       if (cc->key_size != ukp->datalen) {
+       ret = set_key(cc, key);
+       if (ret < 0) {
                up_read(&key->sem);
                key_put(key);
                kzfree(new_key_string);
-               return -EINVAL;
+               return ret;
        }
 
-       memcpy(cc->key, ukp->data, cc->key_size);
-
        up_read(&key->sem);
        key_put(key);
 
@@ -2323,7 +2361,7 @@ static int get_key_size(char **key_string)
        return (*key_string[0] == ':') ? -EINVAL : strlen(*key_string) >> 1;
 }
 
-#endif
+#endif /* CONFIG_KEYS */
 
 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 = {
        .name   = "crypt",
-       .version = {1, 20, 0},
+       .version = {1, 21, 0},
        .module = THIS_MODULE,
        .ctr    = crypt_ctr,
        .dtr    = crypt_dtr,
This page took 0.068092 seconds and 4 git commands to generate.