Whamcloud - gitweb
LU-12275 sec: introduce null algo for filename encryption 81/38881/8
authorSebastien Buisson <sbuisson@ddn.com>
Tue, 9 Jun 2020 15:11:42 +0000 (15:11 +0000)
committerOleg Drokin <green@whamcloud.com>
Fri, 17 Jul 2020 19:30:23 +0000 (19:30 +0000)
Introduce a "null" algorithm for client side filename encryption,
which is basically a no-op.
This is needed because first implementation step only supports
content encryption, and not names. So give the ability to support
encryption policies that have a 'filenames_encryption_mode' property
internally set to LLCRYPT_MODE_NULL.

Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: I3470f89f227b3a03e56766fe1ba5e36ae92ec27b
Reviewed-on: https://review.whamcloud.com/38881
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Yingjin Qian <qian@ddn.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
libcfs/include/uapi/linux/llcrypt.h
libcfs/libcfs/crypto/crypto.c
libcfs/libcfs/crypto/fname.c
libcfs/libcfs/crypto/keysetup.c
libcfs/libcfs/crypto/llcrypt_private.h
libcfs/libcfs/crypto/policy.c

index dac16c0..c133859 100644 (file)
@@ -24,6 +24,7 @@
 #define LLCRYPT_POLICY_FLAGS_VALID             0x07
 
 /* Encryption algorithms */
+#define LLCRYPT_MODE_NULL                      0
 #define LLCRYPT_MODE_AES_256_XTS               1
 #define LLCRYPT_MODE_AES_256_CTS               4
 #define LLCRYPT_MODE_AES_128_CBC               5
index 379affb..bc888cc 100644 (file)
@@ -166,6 +166,13 @@ int llcrypt_crypt_block(const struct inode *inode, llcrypt_direction_t rw,
        struct crypto_skcipher *tfm = ci->ci_ctfm;
        int res = 0;
 
+       if (tfm == NULL) {
+               if (dest_page != src_page)
+                       memcpy(page_address(dest_page), page_address(src_page),
+                              PAGE_SIZE);
+               return 0;
+       }
+
        if (WARN_ON_ONCE(len <= 0))
                return -EINVAL;
        if (WARN_ON_ONCE(len % LL_CRYPTO_BLOCK_SIZE != 0))
index 08accf8..d3f5832 100644 (file)
@@ -58,6 +58,9 @@ int fname_encrypt(struct inode *inode, const struct qstr *iname,
        memcpy(out, iname->name, iname->len);
        memset(out + iname->len, 0, olen - iname->len);
 
+       if (tfm == NULL)
+               return 0;
+
        /* Initialize the IV */
        llcrypt_generate_iv(&iv, 0, ci);
 
@@ -101,6 +104,13 @@ static int fname_decrypt(struct inode *inode,
        union llcrypt_iv iv;
        int res;
 
+       if (tfm == NULL) {
+               memcpy(oname->name, iname->name, iname->len);
+               oname->name[iname->len] = '\0';
+               oname->len = iname->len;
+               return 0;
+       }
+
        /* Allocate request */
        req = skcipher_request_alloc(tfm, GFP_NOFS);
        if (!req)
index c9ca537..c28add0 100644 (file)
 static struct crypto_shash *essiv_hash_tfm;
 
 static struct llcrypt_mode available_modes[] = {
+       [LLCRYPT_MODE_NULL] = {
+               .friendly_name = "NULL",
+               .cipher_str = "null",
+               .keysize = 0,
+               .ivsize = 0,
+       },
        [LLCRYPT_MODE_AES_256_XTS] = {
                .friendly_name = "AES-256-XTS",
                .cipher_str = "xts(aes)",
@@ -78,6 +84,9 @@ struct crypto_skcipher *llcrypt_allocate_skcipher(struct llcrypt_mode *mode,
        struct crypto_skcipher *tfm;
        int err;
 
+       if (!strcmp(mode->cipher_str, "null"))
+               return NULL;
+
        tfm = crypto_alloc_skcipher(mode->cipher_str, 0, 0);
        if (IS_ERR(tfm)) {
                if (PTR_ERR(tfm) == -ENOENT) {
@@ -396,7 +405,8 @@ static void put_crypt_info(struct llcrypt_info *ci)
                llcrypt_put_direct_key(ci->ci_direct_key);
        } else if ((ci->ci_ctfm != NULL || ci->ci_essiv_tfm != NULL) &&
                   !llcrypt_is_direct_key_policy(&ci->ci_policy)) {
-               crypto_free_skcipher(ci->ci_ctfm);
+               if (ci->ci_ctfm)
+                       crypto_free_skcipher(ci->ci_ctfm);
                crypto_free_cipher(ci->ci_essiv_tfm);
        }
 
index fbf7c73..06eafaf 100644 (file)
@@ -227,15 +227,18 @@ static inline bool llcrypt_valid_enc_modes(u32 contents_mode,
                                           u32 filenames_mode)
 {
        if (contents_mode == LLCRYPT_MODE_AES_128_CBC &&
-           filenames_mode == LLCRYPT_MODE_AES_128_CTS)
+           (filenames_mode == LLCRYPT_MODE_AES_128_CTS ||
+            filenames_mode == LLCRYPT_MODE_NULL))
                return true;
 
        if (contents_mode == LLCRYPT_MODE_AES_256_XTS &&
-           filenames_mode == LLCRYPT_MODE_AES_256_CTS)
+           (filenames_mode == LLCRYPT_MODE_AES_256_CTS ||
+            filenames_mode == LLCRYPT_MODE_NULL))
                return true;
 
        if (contents_mode == LLCRYPT_MODE_ADIANTUM &&
-           filenames_mode == LLCRYPT_MODE_ADIANTUM)
+           (filenames_mode == LLCRYPT_MODE_ADIANTUM ||
+            filenames_mode == LLCRYPT_MODE_NULL))
                return true;
 
        return false;
index bdfc683..8d209e2 100644 (file)
@@ -368,12 +368,27 @@ int llcrypt_ioctl_get_policy(struct file *filp, void __user *arg)
 }
 EXPORT_SYMBOL(llcrypt_ioctl_get_policy);
 
+/* Valid filenames_encryption_mode associated with contents_encryption_mode,
+ * as imposed by llcrypt_valid_enc_modes()
+ */
+static inline u8 contents2filenames_encmode(u8 contents_encryption_mode)
+{
+       if (contents_encryption_mode == LLCRYPT_MODE_AES_128_CBC)
+               return LLCRYPT_MODE_AES_128_CTS;
+       if (contents_encryption_mode == LLCRYPT_MODE_AES_256_XTS)
+               return LLCRYPT_MODE_AES_256_CTS;
+       if (contents_encryption_mode == LLCRYPT_MODE_ADIANTUM)
+               return LLCRYPT_MODE_ADIANTUM;
+       return LLCRYPT_MODE_NULL;
+}
+
 /* Extended ioctl version; can get policies of any version */
 int llcrypt_ioctl_get_policy_ex(struct file *filp, void __user *uarg)
 {
        struct llcrypt_get_policy_ex_arg arg;
        union llcrypt_policy *policy = (union llcrypt_policy *)&arg.policy;
        size_t policy_size;
+       struct inode *inode = file_inode(filp);
        int err;
 
        /* arg is policy_size, then policy */
@@ -394,6 +409,33 @@ int llcrypt_ioctl_get_policy_ex(struct file *filp, void __user *uarg)
                return -EOVERFLOW;
        arg.policy_size = policy_size;
 
+       /* Do not return null filenames_encryption_mode to userspace, as it is
+        * unknown. Instead, return valid mode associated with
+        * contents_encryption_mode, as imposed by llcrypt_valid_enc_modes().
+        */
+       switch (policy->version) {
+       case LLCRYPT_POLICY_V1:
+               if (policy->v1.filenames_encryption_mode == LLCRYPT_MODE_NULL) {
+                       policy->v1.filenames_encryption_mode =
+                               contents2filenames_encmode(
+                                       policy->v1.contents_encryption_mode);
+                       CWARN("inode %lu: returning policy filenames_encryption_mode as %d, but is in fact null\n",
+                             inode->i_ino,
+                             policy->v1.filenames_encryption_mode);
+               }
+               break;
+       case LLCRYPT_POLICY_V2:
+               if (policy->v2.filenames_encryption_mode == LLCRYPT_MODE_NULL) {
+                       policy->v2.filenames_encryption_mode =
+                               contents2filenames_encmode(
+                                       policy->v2.contents_encryption_mode);
+                       CWARN("inode %lu: returning policy filenames_encryption_mode as %d, but is in fact null\n",
+                             inode->i_ino,
+                             policy->v2.filenames_encryption_mode);
+               }
+               break;
+       }
+
        if (copy_to_user(uarg, &arg, sizeof(arg.policy_size) + policy_size))
                return -EFAULT;
        return 0;