From c60b7d9f571748fb055d29cd019709f9e965a84d Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Tue, 9 Jun 2020 15:11:42 +0000 Subject: [PATCH] LU-12275 sec: introduce null algo for filename encryption 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 Change-Id: I3470f89f227b3a03e56766fe1ba5e36ae92ec27b Reviewed-on: https://review.whamcloud.com/38881 Reviewed-by: Andreas Dilger Tested-by: jenkins Tested-by: Maloo Reviewed-by: Yingjin Qian Reviewed-by: Oleg Drokin --- libcfs/include/uapi/linux/llcrypt.h | 1 + libcfs/libcfs/crypto/crypto.c | 7 ++++++ libcfs/libcfs/crypto/fname.c | 10 ++++++++ libcfs/libcfs/crypto/keysetup.c | 12 +++++++++- libcfs/libcfs/crypto/llcrypt_private.h | 9 +++++--- libcfs/libcfs/crypto/policy.c | 42 ++++++++++++++++++++++++++++++++++ 6 files changed, 77 insertions(+), 4 deletions(-) diff --git a/libcfs/include/uapi/linux/llcrypt.h b/libcfs/include/uapi/linux/llcrypt.h index dac16c0..c133859 100644 --- a/libcfs/include/uapi/linux/llcrypt.h +++ b/libcfs/include/uapi/linux/llcrypt.h @@ -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 diff --git a/libcfs/libcfs/crypto/crypto.c b/libcfs/libcfs/crypto/crypto.c index 379affb..bc888cc 100644 --- a/libcfs/libcfs/crypto/crypto.c +++ b/libcfs/libcfs/crypto/crypto.c @@ -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)) diff --git a/libcfs/libcfs/crypto/fname.c b/libcfs/libcfs/crypto/fname.c index 08accf8..d3f5832 100644 --- a/libcfs/libcfs/crypto/fname.c +++ b/libcfs/libcfs/crypto/fname.c @@ -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) diff --git a/libcfs/libcfs/crypto/keysetup.c b/libcfs/libcfs/crypto/keysetup.c index c9ca537..c28add0 100644 --- a/libcfs/libcfs/crypto/keysetup.c +++ b/libcfs/libcfs/crypto/keysetup.c @@ -22,6 +22,12 @@ 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); } diff --git a/libcfs/libcfs/crypto/llcrypt_private.h b/libcfs/libcfs/crypto/llcrypt_private.h index fbf7c73..06eafaf 100644 --- a/libcfs/libcfs/crypto/llcrypt_private.h +++ b/libcfs/libcfs/crypto/llcrypt_private.h @@ -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; diff --git a/libcfs/libcfs/crypto/policy.c b/libcfs/libcfs/crypto/policy.c index bdfc683..8d209e2 100644 --- a/libcfs/libcfs/crypto/policy.c +++ b/libcfs/libcfs/crypto/policy.c @@ -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; -- 1.8.3.1