Whamcloud - gitweb
LU-17138 enc: prefer specific crypto engines
[fs/lustre-release.git] / libcfs / libcfs / crypto / crypto.c
index bc888cc..e06a160 100644 (file)
 #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;
 
@@ -45,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);
@@ -266,9 +278,10 @@ struct page *llcrypt_encrypt_pagecache_blocks(struct page *page,
 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
@@ -279,17 +292,18 @@ EXPORT_SYMBOL(llcrypt_encrypt_pagecache_blocks);
  * 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
@@ -335,9 +349,10 @@ int llcrypt_decrypt_pagecache_blocks(struct page *page, unsigned int len,
 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
@@ -347,17 +362,18 @@ EXPORT_SYMBOL(llcrypt_decrypt_pagecache_blocks);
  * 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
@@ -484,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.
  */
@@ -513,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;