#include <crypto/skcipher.h>
#include "llcrypt_private.h"
+#ifdef HAVE_CIPHER_H
+#include <crypto/internal/cipher.h>
+
+MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+#endif
+
static unsigned int num_prealloc_crypto_pages = 32;
static unsigned int num_prealloc_crypto_ctxs = 128;
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);
EXPORT_SYMBOL(llcrypt_encrypt_pagecache_blocks);
/**
- * llcrypt_encrypt_block_inplace() - Encrypt a filesystem block in-place
+ * llcrypt_encrypt_block() - Encrypt a filesystem block in a page
* @inode: The inode to which this block belongs
- * @page: The page containing the block to encrypt
+ * @src: The page containing the block to encrypt
+ * @dst: The page which will contain the encrypted data
* @len: Size of block to encrypt. Doesn't need to be a multiple of the
* fs block size, but must be a multiple of LL_CRYPTO_BLOCK_SIZE.
* @offs: Byte offset within @page at which the block to encrypt begins
* Encrypt a possibly-compressed filesystem block that is located in an
* arbitrary page, not necessarily in the original pagecache page. The @inode
* and @lblk_num must be specified, as they can't be determined from @page.
+ * The decrypted data will be stored in @dst.
*
* Return: 0 on success; -errno on failure
*/
-int llcrypt_encrypt_block_inplace(const struct inode *inode, struct page *page,
- unsigned int len, unsigned int offs,
- u64 lblk_num, gfp_t gfp_flags)
+int llcrypt_encrypt_block(const struct inode *inode, struct page *src,
+ struct page *dst, unsigned int len, unsigned int offs,
+ u64 lblk_num, gfp_t gfp_flags)
{
- return llcrypt_crypt_block(inode, FS_ENCRYPT, lblk_num, page, page,
+ return llcrypt_crypt_block(inode, FS_ENCRYPT, lblk_num, src, dst,
len, offs, gfp_flags);
}
-EXPORT_SYMBOL(llcrypt_encrypt_block_inplace);
+EXPORT_SYMBOL(llcrypt_encrypt_block);
/**
* llcrypt_decrypt_pagecache_blocks() - Decrypt filesystem blocks in a pagecache page
EXPORT_SYMBOL(llcrypt_decrypt_pagecache_blocks);
/**
- * llcrypt_decrypt_block_inplace() - Decrypt a filesystem block in-place
+ * llcrypt_decrypt_block() - Cache a decrypted filesystem block in a page
* @inode: The inode to which this block belongs
- * @page: The page containing the block to decrypt
+ * @src: The page containing the block to decrypt
+ * @dst: The page which will contain the plain data
* @len: Size of block to decrypt. Doesn't need to be a multiple of the
* fs block size, but must be a multiple of LL_CRYPTO_BLOCK_SIZE.
* @offs: Byte offset within @page at which the block to decrypt begins
* Decrypt a possibly-compressed filesystem block that is located in an
* arbitrary page, not necessarily in the original pagecache page. The @inode
* and @lblk_num must be specified, as they can't be determined from @page.
+ * The encrypted data will be stored in @dst.
*
* Return: 0 on success; -errno on failure
*/
-int llcrypt_decrypt_block_inplace(const struct inode *inode, struct page *page,
- unsigned int len, unsigned int offs,
- u64 lblk_num)
+int llcrypt_decrypt_block(const struct inode *inode, struct page *src,
+ struct page *dst, unsigned int len, unsigned int offs,
+ u64 lblk_num, gfp_t gfp_flags)
{
- return llcrypt_crypt_block(inode, FS_DECRYPT, lblk_num, page, page,
- len, offs, GFP_NOFS);
+ return llcrypt_crypt_block(inode, FS_DECRYPT, lblk_num, src, dst,
+ len, offs, gfp_flags);
}
-EXPORT_SYMBOL(llcrypt_decrypt_block_inplace);
+EXPORT_SYMBOL(llcrypt_decrypt_block);
/*
* Validate dentries in encrypted directories to make sure we aren't potentially
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;