summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/crypto/crypto.c93
1 files changed, 52 insertions, 41 deletions
diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index f287f76cc906..8c104e712bb2 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -147,9 +147,9 @@ typedef enum {
} fscrypt_direction_t;
static int do_page_crypto(const struct inode *inode,
- fscrypt_direction_t rw, pgoff_t index,
+ fscrypt_direction_t rw, u64 lblk_num,
struct page *src_page, struct page *dest_page,
- unsigned int src_len, unsigned int src_offset,
+ unsigned int len, unsigned int offs,
gfp_t gfp_flags)
{
struct {
@@ -163,6 +163,8 @@ static int do_page_crypto(const struct inode *inode,
struct crypto_skcipher *tfm = ci->ci_ctfm;
int res = 0;
+ BUG_ON(len == 0);
+
req = skcipher_request_alloc(tfm, gfp_flags);
if (!req) {
printk_ratelimited(KERN_ERR
@@ -176,14 +178,14 @@ static int do_page_crypto(const struct inode *inode,
page_crypt_complete, &ecr);
BUILD_BUG_ON(sizeof(xts_tweak) != FS_XTS_TWEAK_SIZE);
- xts_tweak.index = cpu_to_le64(index);
+ xts_tweak.index = cpu_to_le64(lblk_num);
memset(xts_tweak.padding, 0, sizeof(xts_tweak.padding));
sg_init_table(&dst, 1);
- sg_set_page(&dst, dest_page, src_len, src_offset);
+ sg_set_page(&dst, dest_page, len, offs);
sg_init_table(&src, 1);
- sg_set_page(&src, src_page, src_len, src_offset);
- skcipher_request_set_crypt(req, &src, &dst, src_len, &xts_tweak);
+ sg_set_page(&src, src_page, len, offs);
+ skcipher_request_set_crypt(req, &src, &dst, len, &xts_tweak);
if (rw == FS_DECRYPT)
res = crypto_skcipher_decrypt(req);
else
@@ -214,44 +216,53 @@ static struct page *alloc_bounce_page(struct fscrypt_ctx *ctx, gfp_t gfp_flags)
/**
* fscypt_encrypt_page() - Encrypts a page
- * @inode: The inode for which the encryption should take place
- * @plaintext_page: The page to encrypt. Must be locked.
- * @plaintext_len: Length of plaintext within page
- * @plaintext_offset: Offset of plaintext within page
- * @index: Index for encryption. This is mainly the page index, but
- * but might be different for multiple calls on same page.
- * @gfp_flags: The gfp flag for memory allocation
+ * @inode: The inode for which the encryption should take place
+ * @page: The page to encrypt. Must be locked for bounce-page
+ * encryption.
+ * @len: Length of data to encrypt in @page and encrypted
+ * data in returned page.
+ * @offs: Offset of data within @page and returned
+ * page holding encrypted data.
+ * @lblk_num: Logical block number. This must be unique for multiple
+ * calls with same inode, except when overwriting
+ * previously written data.
+ * @gfp_flags: The gfp flag for memory allocation
*
- * Encrypts plaintext_page using the ctx encryption context. If
- * the filesystem supports it, encryption is performed in-place, otherwise a
- * new ciphertext_page is allocated and returned.
+ * Encrypts @page using the ctx encryption context. Performs encryption
+ * either in-place or into a newly allocated bounce page.
+ * Called on the page write path.
*
- * Called on the page write path. The caller must call
+ * Bounce page allocation is the default.
+ * In this case, the contents of @page are encrypted and stored in an
+ * allocated bounce page. @page has to be locked and the caller must call
* fscrypt_restore_control_page() on the returned ciphertext page to
* release the bounce buffer and the encryption context.
*
- * Return: An allocated page with the encrypted content on success. Else, an
+ * In-place encryption is used by setting the FS_CFLG_INPLACE_ENCRYPTION flag in
+ * fscrypt_operations. Here, the input-page is returned with its content
+ * encrypted.
+ *
+ * Return: A page with the encrypted content on success. Else, an
* error value or NULL.
*/
struct page *fscrypt_encrypt_page(const struct inode *inode,
- struct page *plaintext_page,
- unsigned int plaintext_len,
- unsigned int plaintext_offset,
- pgoff_t index, gfp_t gfp_flags)
+ struct page *page,
+ unsigned int len,
+ unsigned int offs,
+ u64 lblk_num, gfp_t gfp_flags)
{
struct fscrypt_ctx *ctx;
- struct page *ciphertext_page = plaintext_page;
+ struct page *ciphertext_page = page;
int err;
- BUG_ON(plaintext_len % FS_CRYPTO_BLOCK_SIZE != 0);
+ BUG_ON(len % FS_CRYPTO_BLOCK_SIZE != 0);
if (inode->i_sb->s_cop->flags & FS_CFLG_INPLACE_ENCRYPTION) {
/* with inplace-encryption we just encrypt the page */
- err = do_page_crypto(inode, FS_ENCRYPT, index,
- plaintext_page, ciphertext_page,
- plaintext_len, plaintext_offset,
- gfp_flags);
+ err = do_page_crypto(inode, FS_ENCRYPT, lblk_num,
+ page, ciphertext_page,
+ len, offs, gfp_flags);
if (err)
return ERR_PTR(err);
@@ -267,11 +278,10 @@ struct page *fscrypt_encrypt_page(const struct inode *inode,
if (IS_ERR(ciphertext_page))
goto errout;
- ctx->w.control_page = plaintext_page;
- err = do_page_crypto(inode, FS_ENCRYPT, index,
- plaintext_page, ciphertext_page,
- plaintext_len, plaintext_offset,
- gfp_flags);
+ ctx->w.control_page = page;
+ err = do_page_crypto(inode, FS_ENCRYPT, lblk_num,
+ page, ciphertext_page,
+ len, offs, gfp_flags);
if (err) {
ciphertext_page = ERR_PTR(err);
goto errout;
@@ -289,11 +299,12 @@ EXPORT_SYMBOL(fscrypt_encrypt_page);
/**
* fscrypt_decrypt_page() - Decrypts a page in-place
- * @inode: Encrypted inode to decrypt.
- * @page: The page to decrypt. Must be locked.
- * @len: Number of bytes in @page to be decrypted.
- * @offs: Start of data in @page.
- * @index: Index for encryption.
+ * @inode: The corresponding inode for the page to decrypt.
+ * @page: The page to decrypt. Must be locked in case
+ * it is a writeback page.
+ * @len: Number of bytes in @page to be decrypted.
+ * @offs: Start of data in @page.
+ * @lblk_num: Logical block number.
*
* Decrypts page in-place using the ctx encryption context.
*
@@ -302,10 +313,10 @@ EXPORT_SYMBOL(fscrypt_encrypt_page);
* Return: Zero on success, non-zero otherwise.
*/
int fscrypt_decrypt_page(const struct inode *inode, struct page *page,
- unsigned int len, unsigned int offs, pgoff_t index)
+ unsigned int len, unsigned int offs, u64 lblk_num)
{
- return do_page_crypto(inode, FS_DECRYPT, index, page, page, len, offs,
- GFP_NOFS);
+ return do_page_crypto(inode, FS_DECRYPT, lblk_num, page, page, len,
+ offs, GFP_NOFS);
}
EXPORT_SYMBOL(fscrypt_decrypt_page);