From 056eb9dcc0d5f80451c400342d54037f6de24bd9 Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Fri, 22 Sep 2023 18:19:34 +0200 Subject: [PATCH] LU-17138 enc: prefer specific crypto engines 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 Change-Id: I8b00f1c3c8dcf11c58e9f40a410b57b2f255e642 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/52477 Tested-by: jenkins Tested-by: Maloo Tested-by: Shuichi Ihara Reviewed-by: Andreas Dilger Reviewed-by: Patrick Farrell Reviewed-by: Oleg Drokin --- libcfs/libcfs/crypto/crypto.c | 28 ++++++++++++++++++++++++++++ libcfs/libcfs/crypto/keysetup.c | 28 +++++++++++++++++++++++++++- libcfs/libcfs/crypto/llcrypt_private.h | 7 +++++++ libcfs/libcfs/module.c | 15 ++++++++++++--- 4 files changed, 74 insertions(+), 4 deletions(-) diff --git a/libcfs/libcfs/crypto/crypto.c b/libcfs/libcfs/crypto/crypto.c index 3d18715..e06a160 100644 --- a/libcfs/libcfs/crypto/crypto.c +++ b/libcfs/libcfs/crypto/crypto.c @@ -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; diff --git a/libcfs/libcfs/crypto/keysetup.c b/libcfs/libcfs/crypto/keysetup.c index 67fe888..6b3641e 100644 --- a/libcfs/libcfs/crypto/keysetup.c +++ b/libcfs/libcfs/crypto/keysetup.c @@ -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); diff --git a/libcfs/libcfs/crypto/llcrypt_private.h b/libcfs/libcfs/crypto/llcrypt_private.h index 14d494e..c2e7596 100644 --- a/libcfs/libcfs/crypto/llcrypt_private.h +++ b/libcfs/libcfs/crypto/llcrypt_private.h @@ -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; diff --git a/libcfs/libcfs/module.c b/libcfs/libcfs/module.c index 5fdac4a..201b5e3 100644 --- a/libcfs/libcfs/module.c +++ b/libcfs/libcfs/module.c @@ -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: -- 1.8.3.1