Commit a551d7c8 authored by Theodore Ts'o's avatar Theodore Ts'o

Merge branch 'fscrypt' into dev

parents 0cb80b48 6a34e4d2
...@@ -5138,6 +5138,7 @@ F: include/linux/fscache*.h ...@@ -5138,6 +5138,7 @@ F: include/linux/fscache*.h
FS-CRYPTO: FILE SYSTEM LEVEL ENCRYPTION SUPPORT FS-CRYPTO: FILE SYSTEM LEVEL ENCRYPTION SUPPORT
M: Theodore Y. Ts'o <tytso@mit.edu> M: Theodore Y. Ts'o <tytso@mit.edu>
M: Jaegeuk Kim <jaegeuk@kernel.org> M: Jaegeuk Kim <jaegeuk@kernel.org>
L: linux-fsdevel@vger.kernel.org
S: Supported S: Supported
F: fs/crypto/ F: fs/crypto/
F: include/linux/fscrypto.h F: include/linux/fscrypto.h
......
...@@ -8,9 +8,7 @@ config FS_ENCRYPTION ...@@ -8,9 +8,7 @@ config FS_ENCRYPTION
select CRYPTO_XTS select CRYPTO_XTS
select CRYPTO_CTS select CRYPTO_CTS
select CRYPTO_CTR select CRYPTO_CTR
select CRYPTO_SHA256
select KEYS select KEYS
select ENCRYPTED_KEYS
help help
Enable encryption of files and directories. This Enable encryption of files and directories. This
feature is similar to ecryptfs, but it is more memory feature is similar to ecryptfs, but it is more memory
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/dcache.h> #include <linux/dcache.h>
#include <linux/namei.h> #include <linux/namei.h>
#include <linux/fscrypto.h> #include "fscrypt_private.h"
static unsigned int num_prealloc_crypto_pages = 32; static unsigned int num_prealloc_crypto_pages = 32;
static unsigned int num_prealloc_crypto_ctxs = 128; static unsigned int num_prealloc_crypto_ctxs = 128;
...@@ -63,7 +63,7 @@ void fscrypt_release_ctx(struct fscrypt_ctx *ctx) ...@@ -63,7 +63,7 @@ void fscrypt_release_ctx(struct fscrypt_ctx *ctx)
{ {
unsigned long flags; unsigned long flags;
if (ctx->flags & FS_WRITE_PATH_FL && ctx->w.bounce_page) { if (ctx->flags & FS_CTX_HAS_BOUNCE_BUFFER_FL && ctx->w.bounce_page) {
mempool_free(ctx->w.bounce_page, fscrypt_bounce_page_pool); mempool_free(ctx->w.bounce_page, fscrypt_bounce_page_pool);
ctx->w.bounce_page = NULL; ctx->w.bounce_page = NULL;
} }
...@@ -121,7 +121,7 @@ struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode, gfp_t gfp_flags) ...@@ -121,7 +121,7 @@ struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode, gfp_t gfp_flags)
} else { } else {
ctx->flags &= ~FS_CTX_REQUIRES_FREE_ENCRYPT_FL; ctx->flags &= ~FS_CTX_REQUIRES_FREE_ENCRYPT_FL;
} }
ctx->flags &= ~FS_WRITE_PATH_FL; ctx->flags &= ~FS_CTX_HAS_BOUNCE_BUFFER_FL;
return ctx; return ctx;
} }
EXPORT_SYMBOL(fscrypt_get_ctx); EXPORT_SYMBOL(fscrypt_get_ctx);
...@@ -147,9 +147,9 @@ typedef enum { ...@@ -147,9 +147,9 @@ typedef enum {
} fscrypt_direction_t; } fscrypt_direction_t;
static int do_page_crypto(const struct inode *inode, 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, 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) gfp_t gfp_flags)
{ {
struct { struct {
...@@ -163,6 +163,8 @@ static int do_page_crypto(const struct inode *inode, ...@@ -163,6 +163,8 @@ static int do_page_crypto(const struct inode *inode,
struct crypto_skcipher *tfm = ci->ci_ctfm; struct crypto_skcipher *tfm = ci->ci_ctfm;
int res = 0; int res = 0;
BUG_ON(len == 0);
req = skcipher_request_alloc(tfm, gfp_flags); req = skcipher_request_alloc(tfm, gfp_flags);
if (!req) { if (!req) {
printk_ratelimited(KERN_ERR printk_ratelimited(KERN_ERR
...@@ -176,14 +178,14 @@ static int do_page_crypto(const struct inode *inode, ...@@ -176,14 +178,14 @@ static int do_page_crypto(const struct inode *inode,
page_crypt_complete, &ecr); page_crypt_complete, &ecr);
BUILD_BUG_ON(sizeof(xts_tweak) != FS_XTS_TWEAK_SIZE); 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)); memset(xts_tweak.padding, 0, sizeof(xts_tweak.padding));
sg_init_table(&dst, 1); 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_init_table(&src, 1);
sg_set_page(&src, src_page, src_len, src_offset); sg_set_page(&src, src_page, len, offs);
skcipher_request_set_crypt(req, &src, &dst, src_len, &xts_tweak); skcipher_request_set_crypt(req, &src, &dst, len, &xts_tweak);
if (rw == FS_DECRYPT) if (rw == FS_DECRYPT)
res = crypto_skcipher_decrypt(req); res = crypto_skcipher_decrypt(req);
else else
...@@ -208,69 +210,87 @@ static struct page *alloc_bounce_page(struct fscrypt_ctx *ctx, gfp_t gfp_flags) ...@@ -208,69 +210,87 @@ static struct page *alloc_bounce_page(struct fscrypt_ctx *ctx, gfp_t gfp_flags)
ctx->w.bounce_page = mempool_alloc(fscrypt_bounce_page_pool, gfp_flags); ctx->w.bounce_page = mempool_alloc(fscrypt_bounce_page_pool, gfp_flags);
if (ctx->w.bounce_page == NULL) if (ctx->w.bounce_page == NULL)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
ctx->flags |= FS_WRITE_PATH_FL; ctx->flags |= FS_CTX_HAS_BOUNCE_BUFFER_FL;
return ctx->w.bounce_page; return ctx->w.bounce_page;
} }
/** /**
* fscypt_encrypt_page() - Encrypts a page * fscypt_encrypt_page() - Encrypts a page
* @inode: The inode for which the encryption should take place * @inode: The inode for which the encryption should take place
* @plaintext_page: The page to encrypt. Must be locked. * @page: The page to encrypt. Must be locked for bounce-page
* @plaintext_len: Length of plaintext within page * encryption.
* @plaintext_offset: Offset of plaintext within page * @len: Length of data to encrypt in @page and encrypted
* @index: Index for encryption. This is mainly the page index, but * data in returned page.
* but might be different for multiple calls on same page. * @offs: Offset of data within @page and returned
* @gfp_flags: The gfp flag for memory allocation * 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 * Encrypts @page using the ctx encryption context. Performs encryption
* the filesystem supports it, encryption is performed in-place, otherwise a * either in-place or into a newly allocated bounce page.
* new ciphertext_page is allocated and returned. * 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 * fscrypt_restore_control_page() on the returned ciphertext page to
* release the bounce buffer and the encryption context. * 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_OWN_PAGES 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. * error value or NULL.
*/ */
struct page *fscrypt_encrypt_page(const struct inode *inode, struct page *fscrypt_encrypt_page(const struct inode *inode,
struct page *plaintext_page, struct page *page,
unsigned int plaintext_len, unsigned int len,
unsigned int plaintext_offset, unsigned int offs,
pgoff_t index, gfp_t gfp_flags) u64 lblk_num, gfp_t gfp_flags)
{ {
struct fscrypt_ctx *ctx; struct fscrypt_ctx *ctx;
struct page *ciphertext_page = plaintext_page; struct page *ciphertext_page = page;
int err; 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_OWN_PAGES) {
/* with inplace-encryption we just encrypt the page */
err = do_page_crypto(inode, FS_ENCRYPT, lblk_num,
page, ciphertext_page,
len, offs, gfp_flags);
if (err)
return ERR_PTR(err);
return ciphertext_page;
}
BUG_ON(!PageLocked(page));
ctx = fscrypt_get_ctx(inode, gfp_flags); ctx = fscrypt_get_ctx(inode, gfp_flags);
if (IS_ERR(ctx)) if (IS_ERR(ctx))
return (struct page *)ctx; return (struct page *)ctx;
if (!(inode->i_sb->s_cop->flags & FS_CFLG_INPLACE_ENCRYPTION)) { /* The encryption operation will require a bounce page. */
/* The encryption operation will require a bounce page. */ ciphertext_page = alloc_bounce_page(ctx, gfp_flags);
ciphertext_page = alloc_bounce_page(ctx, gfp_flags); if (IS_ERR(ciphertext_page))
if (IS_ERR(ciphertext_page)) goto errout;
goto errout;
}
ctx->w.control_page = plaintext_page; ctx->w.control_page = page;
err = do_page_crypto(inode, FS_ENCRYPT, index, err = do_page_crypto(inode, FS_ENCRYPT, lblk_num,
plaintext_page, ciphertext_page, page, ciphertext_page,
plaintext_len, plaintext_offset, len, offs, gfp_flags);
gfp_flags);
if (err) { if (err) {
ciphertext_page = ERR_PTR(err); ciphertext_page = ERR_PTR(err);
goto errout; goto errout;
} }
if (!(inode->i_sb->s_cop->flags & FS_CFLG_INPLACE_ENCRYPTION)) { SetPagePrivate(ciphertext_page);
SetPagePrivate(ciphertext_page); set_page_private(ciphertext_page, (unsigned long)ctx);
set_page_private(ciphertext_page, (unsigned long)ctx); lock_page(ciphertext_page);
lock_page(ciphertext_page);
}
return ciphertext_page; return ciphertext_page;
errout: errout:
...@@ -281,11 +301,12 @@ EXPORT_SYMBOL(fscrypt_encrypt_page); ...@@ -281,11 +301,12 @@ EXPORT_SYMBOL(fscrypt_encrypt_page);
/** /**
* fscrypt_decrypt_page() - Decrypts a page in-place * fscrypt_decrypt_page() - Decrypts a page in-place
* @inode: Encrypted inode to decrypt. * @inode: The corresponding inode for the page to decrypt.
* @page: The page to decrypt. Must be locked. * @page: The page to decrypt. Must be locked in case
* @len: Number of bytes in @page to be decrypted. * it is a writeback page (FS_CFLG_OWN_PAGES unset).
* @offs: Start of data in @page. * @len: Number of bytes in @page to be decrypted.
* @index: Index for encryption. * @offs: Start of data in @page.
* @lblk_num: Logical block number.
* *
* Decrypts page in-place using the ctx encryption context. * Decrypts page in-place using the ctx encryption context.
* *
...@@ -294,10 +315,13 @@ EXPORT_SYMBOL(fscrypt_encrypt_page); ...@@ -294,10 +315,13 @@ EXPORT_SYMBOL(fscrypt_encrypt_page);
* Return: Zero on success, non-zero otherwise. * Return: Zero on success, non-zero otherwise.
*/ */
int fscrypt_decrypt_page(const struct inode *inode, struct page *page, 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, page->index, page, page, len, offs, if (!(inode->i_sb->s_cop->flags & FS_CFLG_OWN_PAGES))
GFP_NOFS); BUG_ON(!PageLocked(page));
return do_page_crypto(inode, FS_DECRYPT, lblk_num, page, page, len,
offs, GFP_NOFS);
} }
EXPORT_SYMBOL(fscrypt_decrypt_page); EXPORT_SYMBOL(fscrypt_decrypt_page);
...@@ -501,17 +525,22 @@ static void fscrypt_destroy(void) ...@@ -501,17 +525,22 @@ static void fscrypt_destroy(void)
/** /**
* fscrypt_initialize() - allocate major buffers for fs encryption. * fscrypt_initialize() - allocate major buffers for fs encryption.
* @cop_flags: fscrypt operations flags
* *
* We only call this when we start accessing encrypted files, since it * We only call this when we start accessing encrypted files, since it
* results in memory getting allocated that wouldn't otherwise be used. * results in memory getting allocated that wouldn't otherwise be used.
* *
* Return: Zero on success, non-zero otherwise. * Return: Zero on success, non-zero otherwise.
*/ */
int fscrypt_initialize(void) int fscrypt_initialize(unsigned int cop_flags)
{ {
int i, res = -ENOMEM; int i, res = -ENOMEM;
if (fscrypt_bounce_page_pool) /*
* No need to allocate a bounce page pool if there already is one or
* this FS won't use it.
*/
if (cop_flags & FS_CFLG_OWN_PAGES || fscrypt_bounce_page_pool)
return 0; return 0;
mutex_lock(&fscrypt_init_mutex); mutex_lock(&fscrypt_init_mutex);
...@@ -540,7 +569,6 @@ int fscrypt_initialize(void) ...@@ -540,7 +569,6 @@ int fscrypt_initialize(void)
mutex_unlock(&fscrypt_init_mutex); mutex_unlock(&fscrypt_init_mutex);
return res; return res;
} }
EXPORT_SYMBOL(fscrypt_initialize);
/** /**
* fscrypt_init() - Set up for fs encryption. * fscrypt_init() - Set up for fs encryption.
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/fscrypto.h> #include "fscrypt_private.h"
/** /**
* fname_crypt_complete() - completion callback for filename crypto * fname_crypt_complete() - completion callback for filename crypto
...@@ -350,7 +350,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, ...@@ -350,7 +350,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname,
fname->disk_name.len = iname->len; fname->disk_name.len = iname->len;
return 0; return 0;
} }
ret = get_crypt_info(dir); ret = fscrypt_get_crypt_info(dir);
if (ret && ret != -EOPNOTSUPP) if (ret && ret != -EOPNOTSUPP)
return ret; return ret;
......
/*
* fscrypt_private.h
*
* Copyright (C) 2015, Google, Inc.
*
* This contains encryption key functions.
*
* Written by Michael Halcrow, Ildar Muslukhov, and Uday Savagaonkar, 2015.
*/
#ifndef _FSCRYPT_PRIVATE_H
#define _FSCRYPT_PRIVATE_H
#include <linux/fscrypto.h>
#define FS_FNAME_CRYPTO_DIGEST_SIZE 32
/* Encryption parameters */
#define FS_XTS_TWEAK_SIZE 16
#define FS_AES_128_ECB_KEY_SIZE 16
#define FS_AES_256_GCM_KEY_SIZE 32
#define FS_AES_256_CBC_KEY_SIZE 32
#define FS_AES_256_CTS_KEY_SIZE 32
#define FS_AES_256_XTS_KEY_SIZE 64
#define FS_MAX_KEY_SIZE 64
#define FS_KEY_DESC_PREFIX "fscrypt:"
#define FS_KEY_DESC_PREFIX_SIZE 8
#define FS_KEY_DERIVATION_NONCE_SIZE 16
/**
* Encryption context for inode
*
* Protector format:
* 1 byte: Protector format (1 = this version)
* 1 byte: File contents encryption mode
* 1 byte: File names encryption mode
* 1 byte: Flags
* 8 bytes: Master Key descriptor
* 16 bytes: Encryption Key derivation nonce
*/
struct fscrypt_context {
u8 format;
u8 contents_encryption_mode;
u8 filenames_encryption_mode;
u8 flags;
u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
} __packed;
#define FS_ENCRYPTION_CONTEXT_FORMAT_V1 1
/* This is passed in from userspace into the kernel keyring */
struct fscrypt_key {
u32 mode;
u8 raw[FS_MAX_KEY_SIZE];
u32 size;
} __packed;
/*
* A pointer to this structure is stored in the file system's in-core
* representation of an inode.
*/
struct fscrypt_info {
u8 ci_data_mode;
u8 ci_filename_mode;
u8 ci_flags;
struct crypto_skcipher *ci_ctfm;
struct key *ci_keyring_key;
u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE];
};
#define FS_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001
#define FS_CTX_HAS_BOUNCE_BUFFER_FL 0x00000002
struct fscrypt_completion_result {
struct completion completion;
int res;
};
#define DECLARE_FS_COMPLETION_RESULT(ecr) \
struct fscrypt_completion_result ecr = { \
COMPLETION_INITIALIZER((ecr).completion), 0 }
/* crypto.c */
int fscrypt_initialize(unsigned int cop_flags);
/* keyinfo.c */
extern int fscrypt_get_crypt_info(struct inode *);
#endif /* _FSCRYPT_PRIVATE_H */
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#include <keys/user-type.h> #include <keys/user-type.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/fscrypto.h> #include "fscrypt_private.h"
static void derive_crypt_complete(struct crypto_async_request *req, int rc) static void derive_crypt_complete(struct crypto_async_request *req, int rc)
{ {
...@@ -178,7 +178,7 @@ static void put_crypt_info(struct fscrypt_info *ci) ...@@ -178,7 +178,7 @@ static void put_crypt_info(struct fscrypt_info *ci)
kmem_cache_free(fscrypt_info_cachep, ci); kmem_cache_free(fscrypt_info_cachep, ci);
} }
int get_crypt_info(struct inode *inode) int fscrypt_get_crypt_info(struct inode *inode)
{ {
struct fscrypt_info *crypt_info; struct fscrypt_info *crypt_info;
struct fscrypt_context ctx; struct fscrypt_context ctx;
...@@ -188,7 +188,7 @@ int get_crypt_info(struct inode *inode) ...@@ -188,7 +188,7 @@ int get_crypt_info(struct inode *inode)
u8 *raw_key = NULL; u8 *raw_key = NULL;
int res; int res;
res = fscrypt_initialize(); res = fscrypt_initialize(inode->i_sb->s_cop->flags);
if (res) if (res)
return res; return res;
...@@ -327,7 +327,7 @@ int fscrypt_get_encryption_info(struct inode *inode) ...@@ -327,7 +327,7 @@ int fscrypt_get_encryption_info(struct inode *inode)
(ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) | (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
(1 << KEY_FLAG_REVOKED) | (1 << KEY_FLAG_REVOKED) |
(1 << KEY_FLAG_DEAD))))) (1 << KEY_FLAG_DEAD)))))
return get_crypt_info(inode); return fscrypt_get_crypt_info(inode);
return 0; return 0;
} }
EXPORT_SYMBOL(fscrypt_get_encryption_info); EXPORT_SYMBOL(fscrypt_get_encryption_info);
...@@ -10,8 +10,8 @@ ...@@ -10,8 +10,8 @@
#include <linux/random.h> #include <linux/random.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/fscrypto.h>
#include <linux/mount.h> #include <linux/mount.h>
#include "fscrypt_private.h"
static int inode_has_encryption_context(struct inode *inode) static int inode_has_encryption_context(struct inode *inode)
{ {
...@@ -93,16 +93,19 @@ static int create_encryption_context_from_policy(struct inode *inode, ...@@ -93,16 +93,19 @@ static int create_encryption_context_from_policy(struct inode *inode,
return inode->i_sb->s_cop->set_context(inode, &ctx, sizeof(ctx), NULL); return inode->i_sb->s_cop->set_context(inode, &ctx, sizeof(ctx), NULL);
} }
int fscrypt_process_policy(struct file *filp, int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg)
const struct fscrypt_policy *policy)
{ {
struct fscrypt_policy policy;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
int ret; int ret;
if (copy_from_user(&policy, arg, sizeof(policy)))
return -EFAULT;
if (!inode_owner_or_capable(inode)) if (!inode_owner_or_capable(inode))
return -EACCES; return -EACCES;
if (policy->version != 0) if (policy.version != 0)
return -EINVAL; return -EINVAL;
ret = mnt_want_write_file(filp); ret = mnt_want_write_file(filp);
...@@ -120,9 +123,9 @@ int fscrypt_process_policy(struct file *filp, ...@@ -120,9 +123,9 @@ int fscrypt_process_policy(struct file *filp,
ret = -ENOTEMPTY; ret = -ENOTEMPTY;
else else
ret = create_encryption_context_from_policy(inode, ret = create_encryption_context_from_policy(inode,
policy); &policy);
} else if (!is_encryption_context_consistent_with_policy(inode, } else if (!is_encryption_context_consistent_with_policy(inode,
policy)) { &policy)) {
printk(KERN_WARNING printk(KERN_WARNING
"%s: Policy inconsistent with encryption context\n", "%s: Policy inconsistent with encryption context\n",
__func__); __func__);
...@@ -134,11 +137,13 @@ int fscrypt_process_policy(struct file *filp, ...@@ -134,11 +137,13 @@ int fscrypt_process_policy(struct file *filp,
mnt_drop_write_file(filp); mnt_drop_write_file(filp);
return ret; return ret;
} }
EXPORT_SYMBOL(fscrypt_process_policy); EXPORT_SYMBOL(fscrypt_ioctl_set_policy);
int fscrypt_get_policy(struct inode *inode, struct fscrypt_policy *policy) int fscrypt_ioctl_get_policy(struct file *filp, void __user *arg)
{ {
struct inode *inode = file_inode(filp);
struct fscrypt_context ctx; struct fscrypt_context ctx;
struct fscrypt_policy policy;
int res; int res;
if (!inode->i_sb->s_cop->get_context || if (!inode->i_sb->s_cop->get_context ||
...@@ -151,15 +156,18 @@ int fscrypt_get_policy(struct inode *inode, struct fscrypt_policy *policy) ...@@ -151,15 +156,18 @@ int fscrypt_get_policy(struct inode *inode, struct fscrypt_policy *policy)
if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1) if (ctx.format != FS_ENCRYPTION_CONTEXT_FORMAT_V1)
return -EINVAL; return -EINVAL;
policy->version = 0; policy.version = 0;
policy->contents_encryption_mode = ctx.contents_encryption_mode; policy.contents_encryption_mode = ctx.contents_encryption_mode;
policy->filenames_encryption_mode = ctx.filenames_encryption_mode; policy.filenames_encryption_mode = ctx.filenames_encryption_mode;
policy->flags = ctx.flags; policy.flags = ctx.flags;
memcpy(&policy->master_key_descriptor, ctx.master_key_descriptor, memcpy(policy.master_key_descriptor, ctx.master_key_descriptor,
FS_KEY_DESCRIPTOR_SIZE); FS_KEY_DESCRIPTOR_SIZE);
if (copy_to_user(arg, &policy, sizeof(policy)))
return -EFAULT;
return 0; return 0;
} }
EXPORT_SYMBOL(fscrypt_get_policy); EXPORT_SYMBOL(fscrypt_ioctl_get_policy);
int fscrypt_has_permitted_context(struct inode *parent, struct inode *child) int fscrypt_has_permitted_context(struct inode *parent, struct inode *child)
{ {
......
...@@ -2329,8 +2329,8 @@ static inline void ext4_fname_free_filename(struct ext4_filename *fname) { } ...@@ -2329,8 +2329,8 @@ static inline void ext4_fname_free_filename(struct ext4_filename *fname) { }
#define fscrypt_pullback_bio_page fscrypt_notsupp_pullback_bio_page #define fscrypt_pullback_bio_page fscrypt_notsupp_pullback_bio_page
#define fscrypt_restore_control_page fscrypt_notsupp_restore_control_page #define fscrypt_restore_control_page fscrypt_notsupp_restore_control_page
#define fscrypt_zeroout_range fscrypt_notsupp_zeroout_range #define fscrypt_zeroout_range fscrypt_notsupp_zeroout_range
#define fscrypt_process_policy fscrypt_notsupp_process_policy #define fscrypt_ioctl_set_policy fscrypt_notsupp_ioctl_set_policy
#define fscrypt_get_policy fscrypt_notsupp_get_policy #define fscrypt_ioctl_get_policy fscrypt_notsupp_ioctl_get_policy
#define fscrypt_has_permitted_context fscrypt_notsupp_has_permitted_context #define fscrypt_has_permitted_context fscrypt_notsupp_has_permitted_context
#define fscrypt_inherit_context fscrypt_notsupp_inherit_context #define fscrypt_inherit_context fscrypt_notsupp_inherit_context
#define fscrypt_get_encryption_info fscrypt_notsupp_get_encryption_info #define fscrypt_get_encryption_info fscrypt_notsupp_get_encryption_info
......
...@@ -3851,7 +3851,6 @@ static int __ext4_block_zero_page_range(handle_t *handle, ...@@ -3851,7 +3851,6 @@ static int __ext4_block_zero_page_range(handle_t *handle,
/* We expect the key to be set. */ /* We expect the key to be set. */
BUG_ON(!fscrypt_has_encryption_key(inode)); BUG_ON(!fscrypt_has_encryption_key(inode));
BUG_ON(blocksize != PAGE_SIZE); BUG_ON(blocksize != PAGE_SIZE);
BUG_ON(!PageLocked(page));
WARN_ON_ONCE(fscrypt_decrypt_page(page->mapping->host, WARN_ON_ONCE(fscrypt_decrypt_page(page->mapping->host,
page, PAGE_SIZE, 0, page->index)); page, PAGE_SIZE, 0, page->index));
} }
......
...@@ -787,22 +787,12 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -787,22 +787,12 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
} }
case EXT4_IOC_PRECACHE_EXTENTS: case EXT4_IOC_PRECACHE_EXTENTS:
return ext4_ext_precache(inode); return ext4_ext_precache(inode);
case EXT4_IOC_SET_ENCRYPTION_POLICY: {
#ifdef CONFIG_EXT4_FS_ENCRYPTION
struct fscrypt_policy policy;
case EXT4_IOC_SET_ENCRYPTION_POLICY:
if (!ext4_has_feature_encrypt(sb)) if (!ext4_has_feature_encrypt(sb))
return -EOPNOTSUPP; return -EOPNOTSUPP;
return fscrypt_ioctl_set_policy(filp, (const void __user *)arg);
if (copy_from_user(&policy,
(struct fscrypt_policy __user *)arg,
sizeof(policy)))
return -EFAULT;
return fscrypt_process_policy(filp, &policy);
#else
return -EOPNOTSUPP;
#endif
}
case EXT4_IOC_GET_ENCRYPTION_PWSALT: { case EXT4_IOC_GET_ENCRYPTION_PWSALT: {
#ifdef CONFIG_EXT4_FS_ENCRYPTION #ifdef CONFIG_EXT4_FS_ENCRYPTION
int err, err2; int err, err2;
...@@ -843,23 +833,9 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ...@@ -843,23 +833,9 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return -EOPNOTSUPP; return -EOPNOTSUPP;
#endif #endif
} }
case EXT4_IOC_GET_ENCRYPTION_POLICY: { case EXT4_IOC_GET_ENCRYPTION_POLICY:
#ifdef CONFIG_EXT4_FS_ENCRYPTION return fscrypt_ioctl_get_policy(filp, (void __user *)arg);
struct fscrypt_policy policy;
int err = 0;
if (!ext4_encrypted_inode(inode))
return -ENOENT;
err = fscrypt_get_policy(inode, &policy);
if (err)
return err;
if (copy_to_user((void __user *)arg, &policy, sizeof(policy)))
return -EFAULT;
return 0;
#else
return -EOPNOTSUPP;
#endif
}
case EXT4_IOC_FSGETXATTR: case EXT4_IOC_FSGETXATTR:
{ {
struct fsxattr fa; struct fsxattr fa;
......
...@@ -1194,7 +1194,6 @@ int do_write_data_page(struct f2fs_io_info *fio) ...@@ -1194,7 +1194,6 @@ int do_write_data_page(struct f2fs_io_info *fio)
f2fs_wait_on_encrypted_page_writeback(F2FS_I_SB(inode), f2fs_wait_on_encrypted_page_writeback(F2FS_I_SB(inode),
fio->old_blkaddr); fio->old_blkaddr);
retry_encrypt: retry_encrypt:
BUG_ON(!PageLocked(fio->page));
fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page, fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page,
PAGE_SIZE, 0, PAGE_SIZE, 0,
fio->page->index, fio->page->index,
......
...@@ -2453,8 +2453,8 @@ static inline bool f2fs_may_encrypt(struct inode *inode) ...@@ -2453,8 +2453,8 @@ static inline bool f2fs_may_encrypt(struct inode *inode)
#define fscrypt_pullback_bio_page fscrypt_notsupp_pullback_bio_page #define fscrypt_pullback_bio_page fscrypt_notsupp_pullback_bio_page
#define fscrypt_restore_control_page fscrypt_notsupp_restore_control_page #define fscrypt_restore_control_page fscrypt_notsupp_restore_control_page
#define fscrypt_zeroout_range fscrypt_notsupp_zeroout_range #define fscrypt_zeroout_range fscrypt_notsupp_zeroout_range
#define fscrypt_process_policy fscrypt_notsupp_process_policy #define fscrypt_ioctl_set_policy fscrypt_notsupp_ioctl_set_policy
#define fscrypt_get_policy fscrypt_notsupp_get_policy #define fscrypt_ioctl_get_policy fscrypt_notsupp_ioctl_get_policy
#define fscrypt_has_permitted_context fscrypt_notsupp_has_permitted_context #define fscrypt_has_permitted_context fscrypt_notsupp_has_permitted_context
#define fscrypt_inherit_context fscrypt_notsupp_inherit_context #define fscrypt_inherit_context fscrypt_notsupp_inherit_context
#define fscrypt_get_encryption_info fscrypt_notsupp_get_encryption_info #define fscrypt_get_encryption_info fscrypt_notsupp_get_encryption_info
......
...@@ -1752,31 +1752,16 @@ static bool uuid_is_nonzero(__u8 u[16]) ...@@ -1752,31 +1752,16 @@ static bool uuid_is_nonzero(__u8 u[16])
static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg) static int f2fs_ioc_set_encryption_policy(struct file *filp, unsigned long arg)
{ {
struct fscrypt_policy policy;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(filp);
if (copy_from_user(&policy, (struct fscrypt_policy __user *)arg,
sizeof(policy)))
return -EFAULT;
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
return fscrypt_process_policy(filp, &policy); return fscrypt_ioctl_set_policy(filp, (const void __user *)arg);
} }
static int f2fs_ioc_get_encryption_policy(struct file *filp, unsigned long arg) static int f2fs_ioc_get_encryption_policy(struct file *filp, unsigned long arg)
{ {
struct fscrypt_policy policy; return fscrypt_ioctl_get_policy(filp, (void __user *)arg);
struct inode *inode = file_inode(filp);
int err;
err = fscrypt_get_policy(inode, &policy);
if (err)
return err;
if (copy_to_user((struct fscrypt_policy __user *)arg, &policy, sizeof(policy)))
return -EFAULT;
return 0;
} }
static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg) static int f2fs_ioc_get_encryption_pwsalt(struct file *filp, unsigned long arg)
......
...@@ -18,73 +18,9 @@ ...@@ -18,73 +18,9 @@
#include <crypto/skcipher.h> #include <crypto/skcipher.h>
#include <uapi/linux/fs.h> #include <uapi/linux/fs.h>
#define FS_KEY_DERIVATION_NONCE_SIZE 16 #define FS_CRYPTO_BLOCK_SIZE 16
#define FS_ENCRYPTION_CONTEXT_FORMAT_V1 1
#define FS_POLICY_FLAGS_PAD_4 0x00
#define FS_POLICY_FLAGS_PAD_8 0x01
#define FS_POLICY_FLAGS_PAD_16 0x02
#define FS_POLICY_FLAGS_PAD_32 0x03
#define FS_POLICY_FLAGS_PAD_MASK 0x03
#define FS_POLICY_FLAGS_VALID 0x03
/* Encryption algorithms */
#define FS_ENCRYPTION_MODE_INVALID 0
#define FS_ENCRYPTION_MODE_AES_256_XTS 1
#define FS_ENCRYPTION_MODE_AES_256_GCM 2
#define FS_ENCRYPTION_MODE_AES_256_CBC 3
#define FS_ENCRYPTION_MODE_AES_256_CTS 4
/**
* Encryption context for inode
*
* Protector format:
* 1 byte: Protector format (1 = this version)
* 1 byte: File contents encryption mode
* 1 byte: File names encryption mode
* 1 byte: Flags
* 8 bytes: Master Key descriptor
* 16 bytes: Encryption Key derivation nonce
*/
struct fscrypt_context {
u8 format;
u8 contents_encryption_mode;
u8 filenames_encryption_mode;
u8 flags;
u8 master_key_descriptor[FS_KEY_DESCRIPTOR_SIZE];
u8 nonce[FS_KEY_DERIVATION_NONCE_SIZE];
} __packed;
/* Encryption parameters */
#define FS_XTS_TWEAK_SIZE 16
#define FS_AES_128_ECB_KEY_SIZE 16
#define FS_AES_256_GCM_KEY_SIZE 32
#define FS_AES_256_CBC_KEY_SIZE 32
#define FS_AES_256_CTS_KEY_SIZE 32
#define FS_AES_256_XTS_KEY_SIZE 64
#define FS_MAX_KEY_SIZE 64
#define FS_KEY_DESC_PREFIX "fscrypt:"
#define FS_KEY_DESC_PREFIX_SIZE 8
/* This is passed in from userspace into the kernel keyring */
struct fscrypt_key {
u32 mode;
u8 raw[FS_MAX_KEY_SIZE];
u32 size;
} __packed;
struct fscrypt_info {
u8 ci_data_mode;
u8 ci_filename_mode;
u8 ci_flags;
struct crypto_skcipher *ci_ctfm;
struct key *ci_keyring_key;
u8 ci_master_key[FS_KEY_DESCRIPTOR_SIZE];
};
#define FS_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001 struct fscrypt_info;
#define FS_WRITE_PATH_FL 0x00000002
struct fscrypt_ctx { struct fscrypt_ctx {
union { union {
...@@ -102,19 +38,6 @@ struct fscrypt_ctx { ...@@ -102,19 +38,6 @@ struct fscrypt_ctx {
u8 mode; /* Encryption mode for tfm */ u8 mode; /* Encryption mode for tfm */
}; };
struct fscrypt_completion_result {
struct completion completion;
int res;
};
#define DECLARE_FS_COMPLETION_RESULT(ecr) \
struct fscrypt_completion_result ecr = { \
COMPLETION_INITIALIZER((ecr).completion), 0 }
#define FS_FNAME_NUM_SCATTER_ENTRIES 4
#define FS_CRYPTO_BLOCK_SIZE 16
#define FS_FNAME_CRYPTO_DIGEST_SIZE 32
/** /**
* For encrypted symlinks, the ciphertext length is stored at the beginning * For encrypted symlinks, the ciphertext length is stored at the beginning
* of the string in little-endian format. * of the string in little-endian format.
...@@ -156,7 +79,7 @@ struct fscrypt_name { ...@@ -156,7 +79,7 @@ struct fscrypt_name {
/* /*
* fscrypt superblock flags * fscrypt superblock flags
*/ */
#define FS_CFLG_INPLACE_ENCRYPTION (1U << 1) #define FS_CFLG_OWN_PAGES (1U << 1)
/* /*
* crypto opertions for filesystems * crypto opertions for filesystems
...@@ -244,28 +167,25 @@ static inline void fscrypt_set_d_op(struct dentry *dentry) ...@@ -244,28 +167,25 @@ static inline void fscrypt_set_d_op(struct dentry *dentry)
#if IS_ENABLED(CONFIG_FS_ENCRYPTION) #if IS_ENABLED(CONFIG_FS_ENCRYPTION)
/* crypto.c */ /* crypto.c */
extern struct kmem_cache *fscrypt_info_cachep; extern struct kmem_cache *fscrypt_info_cachep;
int fscrypt_initialize(void);
extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t); extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t);
extern void fscrypt_release_ctx(struct fscrypt_ctx *); extern void fscrypt_release_ctx(struct fscrypt_ctx *);
extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *, extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *,
unsigned int, unsigned int, unsigned int, unsigned int,
pgoff_t, gfp_t); u64, gfp_t);
extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int, extern int fscrypt_decrypt_page(const struct inode *, struct page *, unsigned int,
unsigned int, pgoff_t); unsigned int, u64);
extern void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *, struct bio *); extern void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *, struct bio *);
extern void fscrypt_pullback_bio_page(struct page **, bool); extern void fscrypt_pullback_bio_page(struct page **, bool);
extern void fscrypt_restore_control_page(struct page *); extern void fscrypt_restore_control_page(struct page *);
extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t, extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
unsigned int); unsigned int);
/* policy.c */ /* policy.c */
extern int fscrypt_process_policy(struct file *, const struct fscrypt_policy *); extern int fscrypt_ioctl_set_policy(struct file *, const void __user *);
extern int fscrypt_get_policy(struct inode *, struct fscrypt_policy *); extern int fscrypt_ioctl_get_policy(struct file *, void __user *);
extern int fscrypt_has_permitted_context(struct inode *, struct inode *); extern int fscrypt_has_permitted_context(struct inode *, struct inode *);
extern int fscrypt_inherit_context(struct inode *, struct inode *, extern int fscrypt_inherit_context(struct inode *, struct inode *,
void *, bool); void *, bool);
/* keyinfo.c */ /* keyinfo.c */
extern int get_crypt_info(struct inode *);
extern int fscrypt_get_encryption_info(struct inode *); extern int fscrypt_get_encryption_info(struct inode *);
extern void fscrypt_put_encryption_info(struct inode *, struct fscrypt_info *); extern void fscrypt_put_encryption_info(struct inode *, struct fscrypt_info *);
...@@ -299,14 +219,14 @@ static inline struct page *fscrypt_notsupp_encrypt_page(const struct inode *i, ...@@ -299,14 +219,14 @@ static inline struct page *fscrypt_notsupp_encrypt_page(const struct inode *i,
struct page *p, struct page *p,
unsigned int len, unsigned int len,
unsigned int offs, unsigned int offs,
pgoff_t index, gfp_t f) u64 lblk_num, gfp_t f)
{ {
return ERR_PTR(-EOPNOTSUPP); return ERR_PTR(-EOPNOTSUPP);
} }
static inline int fscrypt_notsupp_decrypt_page(const struct inode *i, struct page *p, static inline int fscrypt_notsupp_decrypt_page(const struct inode *i, struct page *p,
unsigned int len, unsigned int offs, unsigned int len, unsigned int offs,
pgoff_t index) u64 lblk_num)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
...@@ -334,14 +254,14 @@ static inline int fscrypt_notsupp_zeroout_range(const struct inode *i, pgoff_t p ...@@ -334,14 +254,14 @@ static inline int fscrypt_notsupp_zeroout_range(const struct inode *i, pgoff_t p
} }
/* policy.c */ /* policy.c */
static inline int fscrypt_notsupp_process_policy(struct file *f, static inline int fscrypt_notsupp_ioctl_set_policy(struct file *f,
const struct fscrypt_policy *p) const void __user *arg)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int fscrypt_notsupp_get_policy(struct inode *i, static inline int fscrypt_notsupp_ioctl_get_policy(struct file *f,
struct fscrypt_policy *p) void __user *arg)
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
......
...@@ -254,6 +254,20 @@ struct fsxattr { ...@@ -254,6 +254,20 @@ struct fsxattr {
/* Policy provided via an ioctl on the topmost directory */ /* Policy provided via an ioctl on the topmost directory */
#define FS_KEY_DESCRIPTOR_SIZE 8 #define FS_KEY_DESCRIPTOR_SIZE 8
#define FS_POLICY_FLAGS_PAD_4 0x00
#define FS_POLICY_FLAGS_PAD_8 0x01
#define FS_POLICY_FLAGS_PAD_16 0x02
#define FS_POLICY_FLAGS_PAD_32 0x03
#define FS_POLICY_FLAGS_PAD_MASK 0x03
#define FS_POLICY_FLAGS_VALID 0x03
/* Encryption algorithms */
#define FS_ENCRYPTION_MODE_INVALID 0
#define FS_ENCRYPTION_MODE_AES_256_XTS 1
#define FS_ENCRYPTION_MODE_AES_256_GCM 2
#define FS_ENCRYPTION_MODE_AES_256_CBC 3
#define FS_ENCRYPTION_MODE_AES_256_CTS 4
struct fscrypt_policy { struct fscrypt_policy {
__u8 version; __u8 version;
__u8 contents_encryption_mode; __u8 contents_encryption_mode;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment