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);
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.
*/
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;
[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,
[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,
},
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);
}
/* 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,
struct llcrypt_mode {
const char *friendly_name;
const char *cipher_str;
+ const char *engine_aesni_str;
int keysize;
int ivsize;
bool logged_impl_name;
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);
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: