xref: /openbmc/linux/fs/ubifs/crypto.c (revision 7799953b34d1838b30e3d69fd36aa3288ac1e89d)
1d475a507SRichard Weinberger #include "ubifs.h"
2d475a507SRichard Weinberger 
3d475a507SRichard Weinberger static int ubifs_crypt_get_context(struct inode *inode, void *ctx, size_t len)
4d475a507SRichard Weinberger {
5d475a507SRichard Weinberger 	return ubifs_xattr_get(inode, UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT,
6d475a507SRichard Weinberger 			       ctx, len);
7d475a507SRichard Weinberger }
8d475a507SRichard Weinberger 
9d475a507SRichard Weinberger static int ubifs_crypt_set_context(struct inode *inode, const void *ctx,
10d475a507SRichard Weinberger 				   size_t len, void *fs_data)
11d475a507SRichard Weinberger {
12d475a507SRichard Weinberger 	return ubifs_xattr_set(inode, UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT,
13d475a507SRichard Weinberger 			       ctx, len, 0);
14d475a507SRichard Weinberger }
15d475a507SRichard Weinberger 
16d475a507SRichard Weinberger static bool ubifs_crypt_empty_dir(struct inode *inode)
17d475a507SRichard Weinberger {
18d475a507SRichard Weinberger 	return ubifs_check_dir_empty(inode) == 0;
19d475a507SRichard Weinberger }
20d475a507SRichard Weinberger 
21d475a507SRichard Weinberger static unsigned int ubifs_crypt_max_namelen(struct inode *inode)
22d475a507SRichard Weinberger {
23d475a507SRichard Weinberger 	if (S_ISLNK(inode->i_mode))
24d475a507SRichard Weinberger 		return UBIFS_MAX_INO_DATA;
25d475a507SRichard Weinberger 	else
26d475a507SRichard Weinberger 		return UBIFS_MAX_NLEN;
27d475a507SRichard Weinberger }
28d475a507SRichard Weinberger 
29d475a507SRichard Weinberger static int ubifs_key_prefix(struct inode *inode, u8 **key)
30d475a507SRichard Weinberger {
31d475a507SRichard Weinberger 	static char prefix[] = "ubifs:";
32d475a507SRichard Weinberger 
33d475a507SRichard Weinberger 	*key = prefix;
34d475a507SRichard Weinberger 
35d475a507SRichard Weinberger 	return sizeof(prefix) - 1;
36d475a507SRichard Weinberger }
37d475a507SRichard Weinberger 
38*7799953bSRichard Weinberger int ubifs_encrypt(const struct inode *inode, struct ubifs_data_node *dn,
39*7799953bSRichard Weinberger 		  unsigned int in_len, unsigned int *out_len, int block)
40*7799953bSRichard Weinberger {
41*7799953bSRichard Weinberger 	struct ubifs_info *c = inode->i_sb->s_fs_info;
42*7799953bSRichard Weinberger 	void *p = &dn->data;
43*7799953bSRichard Weinberger 	struct page *ret;
44*7799953bSRichard Weinberger 	unsigned int pad_len = round_up(in_len, UBIFS_CIPHER_BLOCK_SIZE);
45*7799953bSRichard Weinberger 
46*7799953bSRichard Weinberger 	ubifs_assert(pad_len <= *out_len);
47*7799953bSRichard Weinberger 	dn->compr_size = cpu_to_le16(in_len);
48*7799953bSRichard Weinberger 
49*7799953bSRichard Weinberger 	/* pad to full block cipher length */
50*7799953bSRichard Weinberger 	if (pad_len != in_len)
51*7799953bSRichard Weinberger 		memset(p + in_len, 0, pad_len - in_len);
52*7799953bSRichard Weinberger 
53*7799953bSRichard Weinberger 	ret = fscrypt_encrypt_page(inode, virt_to_page(&dn->data), pad_len,
54*7799953bSRichard Weinberger 			offset_in_page(&dn->data), block, GFP_NOFS);
55*7799953bSRichard Weinberger 	if (IS_ERR(ret)) {
56*7799953bSRichard Weinberger 		ubifs_err(c, "fscrypt_encrypt_page failed: %ld", PTR_ERR(ret));
57*7799953bSRichard Weinberger 		return PTR_ERR(ret);
58*7799953bSRichard Weinberger 	}
59*7799953bSRichard Weinberger 	*out_len = pad_len;
60*7799953bSRichard Weinberger 
61*7799953bSRichard Weinberger 	return 0;
62*7799953bSRichard Weinberger }
63*7799953bSRichard Weinberger 
64*7799953bSRichard Weinberger int ubifs_decrypt(const struct inode *inode, struct ubifs_data_node *dn,
65*7799953bSRichard Weinberger 		  unsigned int *out_len, int block)
66*7799953bSRichard Weinberger {
67*7799953bSRichard Weinberger 	struct ubifs_info *c = inode->i_sb->s_fs_info;
68*7799953bSRichard Weinberger 	int err;
69*7799953bSRichard Weinberger 	unsigned int clen = le16_to_cpu(dn->compr_size);
70*7799953bSRichard Weinberger 	unsigned int dlen = *out_len;
71*7799953bSRichard Weinberger 
72*7799953bSRichard Weinberger 	if (clen <= 0 || clen > UBIFS_BLOCK_SIZE || clen > dlen) {
73*7799953bSRichard Weinberger 		ubifs_err(c, "bad compr_size: %i", clen);
74*7799953bSRichard Weinberger 		return -EINVAL;
75*7799953bSRichard Weinberger 	}
76*7799953bSRichard Weinberger 
77*7799953bSRichard Weinberger 	ubifs_assert(dlen <= UBIFS_BLOCK_SIZE);
78*7799953bSRichard Weinberger 	err = fscrypt_decrypt_page(inode, virt_to_page(&dn->data), dlen,
79*7799953bSRichard Weinberger 			offset_in_page(&dn->data), block);
80*7799953bSRichard Weinberger 	if (err) {
81*7799953bSRichard Weinberger 		ubifs_err(c, "fscrypt_decrypt_page failed: %i", err);
82*7799953bSRichard Weinberger 		return err;
83*7799953bSRichard Weinberger 	}
84*7799953bSRichard Weinberger 	*out_len = clen;
85*7799953bSRichard Weinberger 
86*7799953bSRichard Weinberger 	return 0;
87*7799953bSRichard Weinberger }
88*7799953bSRichard Weinberger 
89d475a507SRichard Weinberger struct fscrypt_operations ubifs_crypt_operations = {
90d475a507SRichard Weinberger 	.flags			= FS_CFLG_INPLACE_ENCRYPTION,
91d475a507SRichard Weinberger 	.get_context		= ubifs_crypt_get_context,
92d475a507SRichard Weinberger 	.set_context		= ubifs_crypt_set_context,
931ee77870SRichard Weinberger 	.is_encrypted		= __ubifs_crypt_is_encrypted,
94d475a507SRichard Weinberger 	.empty_dir		= ubifs_crypt_empty_dir,
95d475a507SRichard Weinberger 	.max_namelen		= ubifs_crypt_max_namelen,
96d475a507SRichard Weinberger 	.key_prefix		= ubifs_key_prefix,
97d475a507SRichard Weinberger };
98