1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * Ceph fscrypt functionality |
4 | */ |
5 | |
6 | #ifndef _CEPH_CRYPTO_H |
7 | #define _CEPH_CRYPTO_H |
8 | |
9 | #include <crypto/sha2.h> |
10 | #include <linux/fscrypt.h> |
11 | |
12 | #define CEPH_FSCRYPT_BLOCK_SHIFT 12 |
13 | #define CEPH_FSCRYPT_BLOCK_SIZE (_AC(1, UL) << CEPH_FSCRYPT_BLOCK_SHIFT) |
14 | #define CEPH_FSCRYPT_BLOCK_MASK (~(CEPH_FSCRYPT_BLOCK_SIZE-1)) |
15 | |
16 | struct ceph_fs_client; |
17 | struct ceph_acl_sec_ctx; |
18 | struct ceph_mds_request; |
19 | |
20 | struct ceph_fname { |
21 | struct inode *dir; |
22 | char *name; // b64 encoded, possibly hashed |
23 | unsigned char *ctext; // binary crypttext (if any) |
24 | u32 name_len; // length of name buffer |
25 | u32 ctext_len; // length of crypttext |
26 | bool no_copy; |
27 | }; |
28 | |
29 | /* |
30 | * Header for the crypted file when truncating the size, this |
31 | * will be sent to MDS, and the MDS will update the encrypted |
32 | * last block and then truncate the size. |
33 | */ |
34 | struct { |
35 | __u8 ; |
36 | __u8 ; |
37 | |
38 | /* |
39 | * It will be sizeof(assert_ver + file_offset + block_size) |
40 | * if the last block is empty when it's located in a file |
41 | * hole. Or the data_len will plus CEPH_FSCRYPT_BLOCK_SIZE. |
42 | */ |
43 | __le32 ; |
44 | |
45 | __le64 ; |
46 | __le64 ; |
47 | __le32 ; |
48 | } __packed; |
49 | |
50 | struct ceph_fscrypt_auth { |
51 | __le32 cfa_version; |
52 | __le32 cfa_blob_len; |
53 | u8 cfa_blob[FSCRYPT_SET_CONTEXT_MAX_SIZE]; |
54 | } __packed; |
55 | |
56 | #define CEPH_FSCRYPT_AUTH_VERSION 1 |
57 | static inline u32 ceph_fscrypt_auth_len(struct ceph_fscrypt_auth *fa) |
58 | { |
59 | u32 ctxsize = le32_to_cpu(fa->cfa_blob_len); |
60 | |
61 | return offsetof(struct ceph_fscrypt_auth, cfa_blob) + ctxsize; |
62 | } |
63 | |
64 | #ifdef CONFIG_FS_ENCRYPTION |
65 | /* |
66 | * We want to encrypt filenames when creating them, but the encrypted |
67 | * versions of those names may have illegal characters in them. To mitigate |
68 | * that, we base64 encode them, but that gives us a result that can exceed |
69 | * NAME_MAX. |
70 | * |
71 | * Follow a similar scheme to fscrypt itself, and cap the filename to a |
72 | * smaller size. If the ciphertext name is longer than the value below, then |
73 | * sha256 hash the remaining bytes. |
74 | * |
75 | * For the fscrypt_nokey_name struct the dirhash[2] member is useless in ceph |
76 | * so the corresponding struct will be: |
77 | * |
78 | * struct fscrypt_ceph_nokey_name { |
79 | * u8 bytes[157]; |
80 | * u8 sha256[SHA256_DIGEST_SIZE]; |
81 | * }; // 180 bytes => 240 bytes base64-encoded, which is <= NAME_MAX (255) |
82 | * |
83 | * (240 bytes is the maximum size allowed for snapshot names to take into |
84 | * account the format: '_<SNAPSHOT-NAME>_<INODE-NUMBER>'.) |
85 | * |
86 | * Note that for long names that end up having their tail portion hashed, we |
87 | * must also store the full encrypted name (in the dentry's alternate_name |
88 | * field). |
89 | */ |
90 | #define CEPH_NOHASH_NAME_MAX (180 - SHA256_DIGEST_SIZE) |
91 | |
92 | #define CEPH_BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3) |
93 | |
94 | int ceph_base64_encode(const u8 *src, int srclen, char *dst); |
95 | int ceph_base64_decode(const char *src, int srclen, u8 *dst); |
96 | |
97 | void ceph_fscrypt_set_ops(struct super_block *sb); |
98 | |
99 | void ceph_fscrypt_free_dummy_policy(struct ceph_fs_client *fsc); |
100 | |
101 | int ceph_fscrypt_prepare_context(struct inode *dir, struct inode *inode, |
102 | struct ceph_acl_sec_ctx *as); |
103 | void ceph_fscrypt_as_ctx_to_req(struct ceph_mds_request *req, |
104 | struct ceph_acl_sec_ctx *as); |
105 | int ceph_encode_encrypted_dname(struct inode *parent, struct qstr *d_name, |
106 | char *buf); |
107 | int ceph_encode_encrypted_fname(struct inode *parent, struct dentry *dentry, |
108 | char *buf); |
109 | |
110 | static inline int ceph_fname_alloc_buffer(struct inode *parent, |
111 | struct fscrypt_str *fname) |
112 | { |
113 | if (!IS_ENCRYPTED(parent)) |
114 | return 0; |
115 | return fscrypt_fname_alloc_buffer(NAME_MAX, crypto_str: fname); |
116 | } |
117 | |
118 | static inline void ceph_fname_free_buffer(struct inode *parent, |
119 | struct fscrypt_str *fname) |
120 | { |
121 | if (IS_ENCRYPTED(parent)) |
122 | fscrypt_fname_free_buffer(crypto_str: fname); |
123 | } |
124 | |
125 | int ceph_fname_to_usr(const struct ceph_fname *fname, struct fscrypt_str *tname, |
126 | struct fscrypt_str *oname, bool *is_nokey); |
127 | int ceph_fscrypt_prepare_readdir(struct inode *dir); |
128 | |
129 | static inline unsigned int ceph_fscrypt_blocks(u64 off, u64 len) |
130 | { |
131 | /* crypto blocks cannot span more than one page */ |
132 | BUILD_BUG_ON(CEPH_FSCRYPT_BLOCK_SHIFT > PAGE_SHIFT); |
133 | |
134 | return ((off+len+CEPH_FSCRYPT_BLOCK_SIZE-1) >> CEPH_FSCRYPT_BLOCK_SHIFT) - |
135 | (off >> CEPH_FSCRYPT_BLOCK_SHIFT); |
136 | } |
137 | |
138 | /* |
139 | * If we have an encrypted inode then we must adjust the offset and |
140 | * range of the on-the-wire read to cover an entire encryption block. |
141 | * The copy will be done using the original offset and length, after |
142 | * we've decrypted the result. |
143 | */ |
144 | static inline void ceph_fscrypt_adjust_off_and_len(struct inode *inode, |
145 | u64 *off, u64 *len) |
146 | { |
147 | if (IS_ENCRYPTED(inode)) { |
148 | *len = ceph_fscrypt_blocks(off: *off, len: *len) * CEPH_FSCRYPT_BLOCK_SIZE; |
149 | *off &= CEPH_FSCRYPT_BLOCK_MASK; |
150 | } |
151 | } |
152 | |
153 | int ceph_fscrypt_decrypt_block_inplace(const struct inode *inode, |
154 | struct page *page, unsigned int len, |
155 | unsigned int offs, u64 lblk_num); |
156 | int ceph_fscrypt_encrypt_block_inplace(const struct inode *inode, |
157 | struct page *page, unsigned int len, |
158 | unsigned int offs, u64 lblk_num, |
159 | gfp_t gfp_flags); |
160 | int ceph_fscrypt_decrypt_pages(struct inode *inode, struct page **page, |
161 | u64 off, int len); |
162 | int ceph_fscrypt_decrypt_extents(struct inode *inode, struct page **page, |
163 | u64 off, struct ceph_sparse_extent *map, |
164 | u32 ext_cnt); |
165 | int ceph_fscrypt_encrypt_pages(struct inode *inode, struct page **page, u64 off, |
166 | int len, gfp_t gfp); |
167 | |
168 | static inline struct page *ceph_fscrypt_pagecache_page(struct page *page) |
169 | { |
170 | return fscrypt_is_bounce_page(page) ? fscrypt_pagecache_page(bounce_page: page) : page; |
171 | } |
172 | |
173 | #else /* CONFIG_FS_ENCRYPTION */ |
174 | |
175 | static inline void ceph_fscrypt_set_ops(struct super_block *sb) |
176 | { |
177 | } |
178 | |
179 | static inline void ceph_fscrypt_free_dummy_policy(struct ceph_fs_client *fsc) |
180 | { |
181 | } |
182 | |
183 | static inline int ceph_fscrypt_prepare_context(struct inode *dir, |
184 | struct inode *inode, |
185 | struct ceph_acl_sec_ctx *as) |
186 | { |
187 | if (IS_ENCRYPTED(dir)) |
188 | return -EOPNOTSUPP; |
189 | return 0; |
190 | } |
191 | |
192 | static inline void ceph_fscrypt_as_ctx_to_req(struct ceph_mds_request *req, |
193 | struct ceph_acl_sec_ctx *as_ctx) |
194 | { |
195 | } |
196 | |
197 | static inline int ceph_encode_encrypted_dname(struct inode *parent, |
198 | struct qstr *d_name, char *buf) |
199 | { |
200 | memcpy(buf, d_name->name, d_name->len); |
201 | return d_name->len; |
202 | } |
203 | |
204 | static inline int ceph_encode_encrypted_fname(struct inode *parent, |
205 | struct dentry *dentry, char *buf) |
206 | { |
207 | return -EOPNOTSUPP; |
208 | } |
209 | |
210 | static inline int ceph_fname_alloc_buffer(struct inode *parent, |
211 | struct fscrypt_str *fname) |
212 | { |
213 | return 0; |
214 | } |
215 | |
216 | static inline void ceph_fname_free_buffer(struct inode *parent, |
217 | struct fscrypt_str *fname) |
218 | { |
219 | } |
220 | |
221 | static inline int ceph_fname_to_usr(const struct ceph_fname *fname, |
222 | struct fscrypt_str *tname, |
223 | struct fscrypt_str *oname, bool *is_nokey) |
224 | { |
225 | oname->name = fname->name; |
226 | oname->len = fname->name_len; |
227 | return 0; |
228 | } |
229 | |
230 | static inline int ceph_fscrypt_prepare_readdir(struct inode *dir) |
231 | { |
232 | return 0; |
233 | } |
234 | |
235 | static inline void ceph_fscrypt_adjust_off_and_len(struct inode *inode, |
236 | u64 *off, u64 *len) |
237 | { |
238 | } |
239 | |
240 | static inline int ceph_fscrypt_decrypt_block_inplace(const struct inode *inode, |
241 | struct page *page, unsigned int len, |
242 | unsigned int offs, u64 lblk_num) |
243 | { |
244 | return 0; |
245 | } |
246 | |
247 | static inline int ceph_fscrypt_encrypt_block_inplace(const struct inode *inode, |
248 | struct page *page, unsigned int len, |
249 | unsigned int offs, u64 lblk_num, |
250 | gfp_t gfp_flags) |
251 | { |
252 | return 0; |
253 | } |
254 | |
255 | static inline int ceph_fscrypt_decrypt_pages(struct inode *inode, |
256 | struct page **page, u64 off, |
257 | int len) |
258 | { |
259 | return 0; |
260 | } |
261 | |
262 | static inline int ceph_fscrypt_decrypt_extents(struct inode *inode, |
263 | struct page **page, u64 off, |
264 | struct ceph_sparse_extent *map, |
265 | u32 ext_cnt) |
266 | { |
267 | return 0; |
268 | } |
269 | |
270 | static inline int ceph_fscrypt_encrypt_pages(struct inode *inode, |
271 | struct page **page, u64 off, |
272 | int len, gfp_t gfp) |
273 | { |
274 | return 0; |
275 | } |
276 | |
277 | static inline struct page *ceph_fscrypt_pagecache_page(struct page *page) |
278 | { |
279 | return page; |
280 | } |
281 | #endif /* CONFIG_FS_ENCRYPTION */ |
282 | |
283 | static inline loff_t ceph_fscrypt_page_offset(struct page *page) |
284 | { |
285 | return page_offset(page: ceph_fscrypt_pagecache_page(page)); |
286 | } |
287 | |
288 | #endif /* _CEPH_CRYPTO_H */ |
289 | |