2016-10-20 16:47:56 +02:00
# include "ubifs.h"
static int ubifs_crypt_get_context ( struct inode * inode , void * ctx , size_t len )
{
return ubifs_xattr_get ( inode , UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT ,
ctx , len ) ;
}
static int ubifs_crypt_set_context ( struct inode * inode , const void * ctx ,
size_t len , void * fs_data )
{
2017-06-23 10:37:23 +08:00
/*
* Creating an encryption context is done unlocked since we
* operate on a new inode which is not visible to other users
* at this point . So , no need to check whether inode is locked .
*/
2016-10-20 16:47:56 +02:00
return ubifs_xattr_set ( inode , UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT ,
2017-06-23 10:37:23 +08:00
ctx , len , 0 , false ) ;
2016-10-20 16:47:56 +02:00
}
static bool ubifs_crypt_empty_dir ( struct inode * inode )
{
return ubifs_check_dir_empty ( inode ) = = 0 ;
}
static unsigned int ubifs_crypt_max_namelen ( struct inode * inode )
{
if ( S_ISLNK ( inode - > i_mode ) )
return UBIFS_MAX_INO_DATA ;
else
return UBIFS_MAX_NLEN ;
}
2016-09-29 22:20:19 +02:00
int ubifs_encrypt ( const struct inode * inode , struct ubifs_data_node * dn ,
unsigned int in_len , unsigned int * out_len , int block )
{
struct ubifs_info * c = inode - > i_sb - > s_fs_info ;
void * p = & dn - > data ;
struct page * ret ;
unsigned int pad_len = round_up ( in_len , UBIFS_CIPHER_BLOCK_SIZE ) ;
ubifs_assert ( pad_len < = * out_len ) ;
dn - > compr_size = cpu_to_le16 ( in_len ) ;
/* pad to full block cipher length */
if ( pad_len ! = in_len )
memset ( p + in_len , 0 , pad_len - in_len ) ;
ret = fscrypt_encrypt_page ( inode , virt_to_page ( & dn - > data ) , pad_len ,
offset_in_page ( & dn - > data ) , block , GFP_NOFS ) ;
if ( IS_ERR ( ret ) ) {
ubifs_err ( c , " fscrypt_encrypt_page failed: %ld " , PTR_ERR ( ret ) ) ;
return PTR_ERR ( ret ) ;
}
* out_len = pad_len ;
return 0 ;
}
int ubifs_decrypt ( const struct inode * inode , struct ubifs_data_node * dn ,
unsigned int * out_len , int block )
{
struct ubifs_info * c = inode - > i_sb - > s_fs_info ;
int err ;
unsigned int clen = le16_to_cpu ( dn - > compr_size ) ;
unsigned int dlen = * out_len ;
if ( clen < = 0 | | clen > UBIFS_BLOCK_SIZE | | clen > dlen ) {
ubifs_err ( c , " bad compr_size: %i " , clen ) ;
return - EINVAL ;
}
ubifs_assert ( dlen < = UBIFS_BLOCK_SIZE ) ;
err = fscrypt_decrypt_page ( inode , virt_to_page ( & dn - > data ) , dlen ,
offset_in_page ( & dn - > data ) , block ) ;
if ( err ) {
ubifs_err ( c , " fscrypt_decrypt_page failed: %i " , err ) ;
return err ;
}
* out_len = clen ;
return 0 ;
}
2017-02-07 12:42:10 -08:00
const struct fscrypt_operations ubifs_crypt_operations = {
2016-12-13 00:27:58 +01:00
. flags = FS_CFLG_OWN_PAGES ,
2017-01-05 13:51:18 -08:00
. key_prefix = " ubifs: " ,
2016-10-20 16:47:56 +02:00
. get_context = ubifs_crypt_get_context ,
. set_context = ubifs_crypt_set_context ,
2016-10-21 14:03:19 +02:00
. is_encrypted = __ubifs_crypt_is_encrypted ,
2016-10-20 16:47:56 +02:00
. empty_dir = ubifs_crypt_empty_dir ,
. max_namelen = ubifs_crypt_max_namelen ,
} ;