blob: bf4b457cd585b54ee36d532cd57e596264ab7361 [file] [log] [blame]
/*
* Copyright (C) 2018 Samsung Electronics Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Functions related to inline encryption handling
*
* NOTE :
* blkcrypt implementation depends on a inline encryption hardware.
* Refactoring is needed to remove any dependency on specified hardwae.
*/
#include <linux/pagemap.h>
#include <linux/module.h>
#include <linux/buffer_head.h>
#include <linux/bio.h>
#include <linux/namei.h>
#include "fscrypt_private.h"
#include <linux/blk-crypt.h>
int fscrypt_inline_encrypted(const struct inode *inode)
{
return __fscrypt_inline_encrypted(inode);
}
EXPORT_SYMBOL(fscrypt_inline_encrypted);
static inline void *__fscrypt_get_bio_cryptd(const struct inode *inode)
{
return blk_crypt_get_data(inode->i_crypt_info->ci_private);
}
void *fscrypt_get_bio_cryptd(const struct inode *inode)
{
if (!__fscrypt_inline_encrypted(inode))
return NULL;
return __fscrypt_get_bio_cryptd(inode);
}
EXPORT_SYMBOL(fscrypt_get_bio_cryptd);
unsigned long long fscrypt_get_dun(const struct inode *inode, pgoff_t pg_idx)
{
struct super_block *sb = inode->i_sb;
if (sb->s_cop && sb->s_cop->get_dun)
return sb->s_cop->get_dun(inode, pg_idx);
return 0;
}
EXPORT_SYMBOL(fscrypt_get_dun);
void fscrypt_set_bio_cryptd_dun(const struct inode *inode, struct bio *bio, u64 dun)
{
BUG_ON(!__fscrypt_inline_encrypted(inode));
BUG_ON(!S_ISREG(inode->i_mode));
bio->bi_opf |= REQ_CRYPT;
bio->bi_cryptd = __fscrypt_get_bio_cryptd(inode);
#ifdef CONFIG_BLK_DEV_CRYPT_DUN
if (dun)
bio->bi_iter.bi_dun = dun;
#endif
#if defined(CONFIG_CRYPTO_DISKCIPHER_DEBUG)
//crypto_diskcipher_set(bio, inode->i_crypt_info->ci_dtfm);
crypto_diskcipher_debug(DISKC_API_SET, 0);
#endif
}
EXPORT_SYMBOL(fscrypt_set_bio_cryptd_dun);
int fscrypt_submit_bh(int op, int op_flags, struct buffer_head *bh, struct inode *inode)
{
void *bi_cryptd = NULL;
/*
* Inline-encrypted also means S_ISREG() is true.
* And ll_rw_block does not use bh->b_private for end_io.
* So, we use it temporarily while ll_rw_block is doing
* in order to pass blk_crypt data, if REQ_CRYPT is set.
*/
if (!__fscrypt_inline_encrypted(inode))
return -EOPNOTSUPP;
BUG_ON(!S_ISREG(inode->i_mode));
BUG_ON(op_flags & REQ_CRYPT);
op_flags |= REQ_CRYPT;
bi_cryptd = __fscrypt_get_bio_cryptd(inode);
/* Attach blk-crypt data to bh->b_private */
BUG_ON(!bi_cryptd);
BUG_ON(bh->b_private);
bh->b_private = bi_cryptd;
ll_rw_block(op, op_flags, 1, &bh);
/* Restore bh->b_private */
bh->b_private = NULL;
return 0;
}
EXPORT_SYMBOL(fscrypt_submit_bh);