Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/fs/ceph/crypto.h
26282 views
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 encrypted 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 ceph_fscrypt_truncate_size_header {
35
__u8 ver;
36
__u8 compat;
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 data_len;
44
45
__le64 change_attr;
46
__le64 file_offset;
47
__le32 block_size;
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, char *buf, int len);
106
107
static inline int ceph_fname_alloc_buffer(struct inode *parent,
108
struct fscrypt_str *fname)
109
{
110
if (!IS_ENCRYPTED(parent))
111
return 0;
112
return fscrypt_fname_alloc_buffer(NAME_MAX, fname);
113
}
114
115
static inline void ceph_fname_free_buffer(struct inode *parent,
116
struct fscrypt_str *fname)
117
{
118
if (IS_ENCRYPTED(parent))
119
fscrypt_fname_free_buffer(fname);
120
}
121
122
int ceph_fname_to_usr(const struct ceph_fname *fname, struct fscrypt_str *tname,
123
struct fscrypt_str *oname, bool *is_nokey);
124
int ceph_fscrypt_prepare_readdir(struct inode *dir);
125
126
static inline unsigned int ceph_fscrypt_blocks(u64 off, u64 len)
127
{
128
/* crypto blocks cannot span more than one page */
129
BUILD_BUG_ON(CEPH_FSCRYPT_BLOCK_SHIFT > PAGE_SHIFT);
130
131
return ((off+len+CEPH_FSCRYPT_BLOCK_SIZE-1) >> CEPH_FSCRYPT_BLOCK_SHIFT) -
132
(off >> CEPH_FSCRYPT_BLOCK_SHIFT);
133
}
134
135
/*
136
* If we have an encrypted inode then we must adjust the offset and
137
* range of the on-the-wire read to cover an entire encryption block.
138
* The copy will be done using the original offset and length, after
139
* we've decrypted the result.
140
*/
141
static inline void ceph_fscrypt_adjust_off_and_len(struct inode *inode,
142
u64 *off, u64 *len)
143
{
144
if (IS_ENCRYPTED(inode)) {
145
*len = ceph_fscrypt_blocks(*off, *len) * CEPH_FSCRYPT_BLOCK_SIZE;
146
*off &= CEPH_FSCRYPT_BLOCK_MASK;
147
}
148
}
149
150
int ceph_fscrypt_decrypt_block_inplace(const struct inode *inode,
151
struct page *page, unsigned int len,
152
unsigned int offs, u64 lblk_num);
153
int ceph_fscrypt_encrypt_block_inplace(const struct inode *inode,
154
struct page *page, unsigned int len,
155
unsigned int offs, u64 lblk_num);
156
int ceph_fscrypt_decrypt_pages(struct inode *inode, struct page **page,
157
u64 off, int len);
158
int ceph_fscrypt_decrypt_extents(struct inode *inode, struct page **page,
159
u64 off, struct ceph_sparse_extent *map,
160
u32 ext_cnt);
161
int ceph_fscrypt_encrypt_pages(struct inode *inode, struct page **page, u64 off,
162
int len);
163
164
static inline struct page *ceph_fscrypt_pagecache_page(struct page *page)
165
{
166
return fscrypt_is_bounce_page(page) ? fscrypt_pagecache_page(page) : page;
167
}
168
169
#else /* CONFIG_FS_ENCRYPTION */
170
171
static inline void ceph_fscrypt_set_ops(struct super_block *sb)
172
{
173
}
174
175
static inline void ceph_fscrypt_free_dummy_policy(struct ceph_fs_client *fsc)
176
{
177
}
178
179
static inline int ceph_fscrypt_prepare_context(struct inode *dir,
180
struct inode *inode,
181
struct ceph_acl_sec_ctx *as)
182
{
183
if (IS_ENCRYPTED(dir))
184
return -EOPNOTSUPP;
185
return 0;
186
}
187
188
static inline void ceph_fscrypt_as_ctx_to_req(struct ceph_mds_request *req,
189
struct ceph_acl_sec_ctx *as_ctx)
190
{
191
}
192
193
static inline int ceph_encode_encrypted_dname(struct inode *parent, char *buf,
194
int len)
195
{
196
return len;
197
}
198
199
static inline int ceph_fname_alloc_buffer(struct inode *parent,
200
struct fscrypt_str *fname)
201
{
202
return 0;
203
}
204
205
static inline void ceph_fname_free_buffer(struct inode *parent,
206
struct fscrypt_str *fname)
207
{
208
}
209
210
static inline int ceph_fname_to_usr(const struct ceph_fname *fname,
211
struct fscrypt_str *tname,
212
struct fscrypt_str *oname, bool *is_nokey)
213
{
214
oname->name = fname->name;
215
oname->len = fname->name_len;
216
return 0;
217
}
218
219
static inline int ceph_fscrypt_prepare_readdir(struct inode *dir)
220
{
221
return 0;
222
}
223
224
static inline void ceph_fscrypt_adjust_off_and_len(struct inode *inode,
225
u64 *off, u64 *len)
226
{
227
}
228
229
static inline int ceph_fscrypt_decrypt_block_inplace(const struct inode *inode,
230
struct page *page, unsigned int len,
231
unsigned int offs, u64 lblk_num)
232
{
233
return 0;
234
}
235
236
static inline int ceph_fscrypt_encrypt_block_inplace(const struct inode *inode,
237
struct page *page, unsigned int len,
238
unsigned int offs, u64 lblk_num)
239
{
240
return 0;
241
}
242
243
static inline int ceph_fscrypt_decrypt_pages(struct inode *inode,
244
struct page **page, u64 off,
245
int len)
246
{
247
return 0;
248
}
249
250
static inline int ceph_fscrypt_decrypt_extents(struct inode *inode,
251
struct page **page, u64 off,
252
struct ceph_sparse_extent *map,
253
u32 ext_cnt)
254
{
255
return 0;
256
}
257
258
static inline int ceph_fscrypt_encrypt_pages(struct inode *inode,
259
struct page **page, u64 off,
260
int len)
261
{
262
return 0;
263
}
264
265
static inline struct page *ceph_fscrypt_pagecache_page(struct page *page)
266
{
267
return page;
268
}
269
#endif /* CONFIG_FS_ENCRYPTION */
270
271
static inline loff_t ceph_fscrypt_page_offset(struct page *page)
272
{
273
return page_offset(ceph_fscrypt_pagecache_page(page));
274
}
275
276
#endif /* _CEPH_CRYPTO_H */
277
278