Whamcloud - gitweb
LU-17138 enc: prefer specific crypto engines 77/52477/4
authorSebastien Buisson <sbuisson@ddn.com>
Fri, 22 Sep 2023 16:19:34 +0000 (18:19 +0200)
committerOleg Drokin <green@whamcloud.com>
Wed, 25 Oct 2023 18:07:35 +0000 (18:07 +0000)
Some ciphers provided by external accelerators might register under
the generic cipher name. To avoid using them with Lustre, prefer the
AES-NI variant implemented directly in the CPU. And fallback to the
generic cipher if AES-NI is not available.

Introduce a new libcfs kernel module parameter named
'client_encryption_engine' to give the ability to choose the cipher.
By default its value is 'aes-ni', which makes Lustre look for the
AES-NI cipher first. This parameter can be set to 'system-default'
whic makes Lustre pick the generic cipher.

Signed-off-by: Sebastien Buisson <sbuisson@ddn.com>
Change-Id: I8b00f1c3c8dcf11c58e9f40a410b57b2f255e642
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/52477
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Tested-by: Shuichi Ihara <sihara@ddn.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Patrick Farrell <pfarrell@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
libcfs/libcfs/crypto/crypto.c
libcfs/libcfs/crypto/keysetup.c
libcfs/libcfs/crypto/llcrypt_private.h
libcfs/libcfs/module.c

index 3d18715..e06a160 100644 (file)
@@ -51,6 +51,12 @@ module_param(num_prealloc_crypto_ctxs, uint, 0444);
 MODULE_PARM_DESC(num_prealloc_crypto_ctxs,
                "Number of crypto contexts to preallocate");
 
+static char *client_encryption_engine = "aes-ni";
+module_param(client_encryption_engine, charp, 0444);
+MODULE_PARM_DESC(client_encryption_engine, "Client encryption engine");
+
+enum llcrypt_crypto_engine_type llcrypt_crypto_engine = LLCRYPT_ENGINE_AES_NI;
+
 static mempool_t *llcrypt_bounce_page_pool = NULL;
 
 static LIST_HEAD(llcrypt_free_ctxs);
@@ -494,6 +500,21 @@ void llcrypt_msg(const struct inode *inode, int mask,
        va_end(args);
 }
 
+static inline int set_llcrypt_crypto_engine_type(void)
+{
+       if (strcmp(client_encryption_engine, "system-default") == 0)
+               llcrypt_crypto_engine = LLCRYPT_ENGINE_SYSTEM_DEFAULT;
+       else if (strcmp(client_encryption_engine, "aes-ni") == 0)
+               llcrypt_crypto_engine = LLCRYPT_ENGINE_AES_NI;
+       else
+               llcrypt_crypto_engine = LLCRYPT_ENGINE_INVALID;
+
+       if (llcrypt_crypto_engine == LLCRYPT_ENGINE_INVALID)
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
  * llcrypt_init() - Set up for fs encryption.
  */
@@ -523,6 +544,13 @@ int __init llcrypt_init(void)
        if (!llcrypt_info_cachep)
                goto fail_free_ctx;
 
+       err = set_llcrypt_crypto_engine_type();
+       if (err) {
+               CERROR("libcfs: bad crypto engine provided via 'client_encryption_engine': rc = %d\n",
+                      err);
+               goto fail_free_info;
+       }
+
        err = llcrypt_init_keyring();
        if (err)
                goto fail_free_info;
index 67fe888..6b3641e 100644 (file)
@@ -41,18 +41,21 @@ static struct llcrypt_mode available_modes[] = {
        [LLCRYPT_MODE_AES_256_XTS] = {
                .friendly_name = "AES-256-XTS",
                .cipher_str = "xts(aes)",
+               .engine_aesni_str = "xts-aes-aesni",
                .keysize = 64,
                .ivsize = 16,
        },
        [LLCRYPT_MODE_AES_256_CTS] = {
                .friendly_name = "AES-256-CTS-CBC",
                .cipher_str = "cts(cbc(aes))",
+               .engine_aesni_str = "cts-cbc-aes-aesni",
                .keysize = 32,
                .ivsize = 16,
        },
        [LLCRYPT_MODE_AES_128_CBC] = {
                .friendly_name = "AES-128-CBC",
                .cipher_str = "cbc(aes)",
+               .engine_aesni_str = "cbc-aes-aesni",
                .keysize = 16,
                .ivsize = 16,
                .needs_essiv = true,
@@ -60,6 +63,7 @@ static struct llcrypt_mode available_modes[] = {
        [LLCRYPT_MODE_AES_128_CTS] = {
                .friendly_name = "AES-128-CTS-CBC",
                .cipher_str = "cts(cbc(aes))",
+               .engine_aesni_str = "cts-cbc-aes-aesni",
                .keysize = 16,
                .ivsize = 16,
        },
@@ -86,20 +90,42 @@ select_encryption_mode(const union llcrypt_policy *policy,
        return ERR_PTR(-EINVAL);
 }
 
+static inline char *crypto_engine_to_use(struct llcrypt_mode *mode)
+{
+       switch (llcrypt_crypto_engine) {
+       case LLCRYPT_ENGINE_SYSTEM_DEFAULT:
+               return (char *)mode->cipher_str;
+       case LLCRYPT_ENGINE_AES_NI:
+               return (char *)mode->engine_aesni_str;
+       default:
+               return NULL;
+       }
+}
+
 /* Create a symmetric cipher object for the given encryption mode and key */
 struct crypto_skcipher *llcrypt_allocate_skcipher(struct llcrypt_mode *mode,
                                                  const u8 *raw_key,
                                                  const struct inode *inode)
 {
        struct crypto_skcipher *tfm;
+       char *cipher;
        int err;
 
        if (!strcmp(mode->cipher_str, "null"))
                return NULL;
 
-       tfm = crypto_alloc_skcipher(mode->cipher_str, 0, 0);
+       cipher = crypto_engine_to_use(mode);
+       if (!cipher)
+               return ERR_PTR(-EINVAL);
+
+alloc:
+       tfm = crypto_alloc_skcipher(cipher, 0, 0);
        if (IS_ERR(tfm)) {
                if (PTR_ERR(tfm) == -ENOENT) {
+                       if (cipher != mode->cipher_str) {
+                               cipher = (char *)mode->cipher_str;
+                               goto alloc;
+                       }
                        llcrypt_warn(inode,
                                     "Missing crypto API support for %s (API name: \"%s\")",
                                     mode->friendly_name, mode->cipher_str);
index 14d494e..c2e7596 100644 (file)
@@ -246,6 +246,12 @@ static inline bool llcrypt_valid_enc_modes(u32 contents_mode,
 }
 
 /* crypto.c */
+enum llcrypt_crypto_engine_type {
+       LLCRYPT_ENGINE_INVALID          = 0,
+       LLCRYPT_ENGINE_SYSTEM_DEFAULT   = 1,
+       LLCRYPT_ENGINE_AES_NI           = 2,
+};
+extern enum llcrypt_crypto_engine_type llcrypt_crypto_engine;
 extern struct kmem_cache *llcrypt_info_cachep;
 extern int llcrypt_initialize(unsigned int cop_flags);
 extern int llcrypt_crypt_block(const struct inode *inode,
@@ -459,6 +465,7 @@ extern void __exit llcrypt_exit_keyring(void);
 struct llcrypt_mode {
        const char *friendly_name;
        const char *cipher_str;
+       const char *engine_aesni_str;
        int keysize;
        int ivsize;
        bool logged_impl_name;
index 5fdac4a..201b5e3 100644 (file)
@@ -688,7 +688,7 @@ static int __init libcfs_init(void)
        rc = cfs_crypto_register();
        if (rc) {
                CERROR("cfs_crypto_regster: error %d\n", rc);
-               goto cleanup_cpu;
+               goto cleanup_wq;
        }
 
        lnet_insert_debugfs(lnet_table, THIS_MODULE, &debugfs_state);
@@ -698,13 +698,22 @@ static int __init libcfs_init(void)
        rc = llcrypt_init();
        if (rc) {
                CERROR("llcrypt_init: error %d\n", rc);
-               goto cleanup_crypto;
+               goto cleanup_lnet;
        }
 
        CDEBUG(D_OTHER, "portals setup OK\n");
        return 0;
-cleanup_crypto:
+
+cleanup_lnet:
+       if (!IS_ERR_OR_NULL(lnet_debugfs_root)) {
+               debugfs_remove_recursive(lnet_debugfs_root);
+               lnet_debugfs_root = NULL;
+               lnet_debugfs_fini(&debugfs_state);
+       }
        cfs_crypto_unregister();
+cleanup_wq:
+       destroy_workqueue(cfs_rehash_wq);
+       cfs_rehash_wq = NULL;
 cleanup_cpu:
        cfs_cpu_fini();
 cleanup_debug: