Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/fs/ceph/crypto.c
26283 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* The base64 encode/decode code was copied from fscrypt:
4
* Copyright (C) 2015, Google, Inc.
5
* Copyright (C) 2015, Motorola Mobility
6
* Written by Uday Savagaonkar, 2014.
7
* Modified by Jaegeuk Kim, 2015.
8
*/
9
#include <linux/ceph/ceph_debug.h>
10
#include <linux/xattr.h>
11
#include <linux/fscrypt.h>
12
#include <linux/ceph/striper.h>
13
14
#include "super.h"
15
#include "mds_client.h"
16
#include "crypto.h"
17
18
/*
19
* The base64url encoding used by fscrypt includes the '_' character, which may
20
* cause problems in snapshot names (which can not start with '_'). Thus, we
21
* used the base64 encoding defined for IMAP mailbox names (RFC 3501) instead,
22
* which replaces '-' and '_' by '+' and ','.
23
*/
24
static const char base64_table[65] =
25
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
26
27
int ceph_base64_encode(const u8 *src, int srclen, char *dst)
28
{
29
u32 ac = 0;
30
int bits = 0;
31
int i;
32
char *cp = dst;
33
34
for (i = 0; i < srclen; i++) {
35
ac = (ac << 8) | src[i];
36
bits += 8;
37
do {
38
bits -= 6;
39
*cp++ = base64_table[(ac >> bits) & 0x3f];
40
} while (bits >= 6);
41
}
42
if (bits)
43
*cp++ = base64_table[(ac << (6 - bits)) & 0x3f];
44
return cp - dst;
45
}
46
47
int ceph_base64_decode(const char *src, int srclen, u8 *dst)
48
{
49
u32 ac = 0;
50
int bits = 0;
51
int i;
52
u8 *bp = dst;
53
54
for (i = 0; i < srclen; i++) {
55
const char *p = strchr(base64_table, src[i]);
56
57
if (p == NULL || src[i] == 0)
58
return -1;
59
ac = (ac << 6) | (p - base64_table);
60
bits += 6;
61
if (bits >= 8) {
62
bits -= 8;
63
*bp++ = (u8)(ac >> bits);
64
}
65
}
66
if (ac & ((1 << bits) - 1))
67
return -1;
68
return bp - dst;
69
}
70
71
static int ceph_crypt_get_context(struct inode *inode, void *ctx, size_t len)
72
{
73
struct ceph_inode_info *ci = ceph_inode(inode);
74
struct ceph_fscrypt_auth *cfa = (struct ceph_fscrypt_auth *)ci->fscrypt_auth;
75
u32 ctxlen;
76
77
/* Non existent or too short? */
78
if (!cfa || (ci->fscrypt_auth_len < (offsetof(struct ceph_fscrypt_auth, cfa_blob) + 1)))
79
return -ENOBUFS;
80
81
/* Some format we don't recognize? */
82
if (le32_to_cpu(cfa->cfa_version) != CEPH_FSCRYPT_AUTH_VERSION)
83
return -ENOBUFS;
84
85
ctxlen = le32_to_cpu(cfa->cfa_blob_len);
86
if (len < ctxlen)
87
return -ERANGE;
88
89
memcpy(ctx, cfa->cfa_blob, ctxlen);
90
return ctxlen;
91
}
92
93
static int ceph_crypt_set_context(struct inode *inode, const void *ctx,
94
size_t len, void *fs_data)
95
{
96
int ret;
97
struct iattr attr = { };
98
struct ceph_iattr cia = { };
99
struct ceph_fscrypt_auth *cfa;
100
101
WARN_ON_ONCE(fs_data);
102
103
if (len > FSCRYPT_SET_CONTEXT_MAX_SIZE)
104
return -EINVAL;
105
106
cfa = kzalloc(sizeof(*cfa), GFP_KERNEL);
107
if (!cfa)
108
return -ENOMEM;
109
110
cfa->cfa_version = cpu_to_le32(CEPH_FSCRYPT_AUTH_VERSION);
111
cfa->cfa_blob_len = cpu_to_le32(len);
112
memcpy(cfa->cfa_blob, ctx, len);
113
114
cia.fscrypt_auth = cfa;
115
116
ret = __ceph_setattr(&nop_mnt_idmap, inode, &attr, &cia);
117
if (ret == 0)
118
inode_set_flags(inode, S_ENCRYPTED, S_ENCRYPTED);
119
kfree(cia.fscrypt_auth);
120
return ret;
121
}
122
123
static bool ceph_crypt_empty_dir(struct inode *inode)
124
{
125
struct ceph_inode_info *ci = ceph_inode(inode);
126
127
return ci->i_rsubdirs + ci->i_rfiles == 1;
128
}
129
130
static const union fscrypt_policy *ceph_get_dummy_policy(struct super_block *sb)
131
{
132
return ceph_sb_to_fs_client(sb)->fsc_dummy_enc_policy.policy;
133
}
134
135
static struct fscrypt_operations ceph_fscrypt_ops = {
136
.needs_bounce_pages = 1,
137
.get_context = ceph_crypt_get_context,
138
.set_context = ceph_crypt_set_context,
139
.get_dummy_policy = ceph_get_dummy_policy,
140
.empty_dir = ceph_crypt_empty_dir,
141
};
142
143
void ceph_fscrypt_set_ops(struct super_block *sb)
144
{
145
fscrypt_set_ops(sb, &ceph_fscrypt_ops);
146
}
147
148
void ceph_fscrypt_free_dummy_policy(struct ceph_fs_client *fsc)
149
{
150
fscrypt_free_dummy_policy(&fsc->fsc_dummy_enc_policy);
151
}
152
153
int ceph_fscrypt_prepare_context(struct inode *dir, struct inode *inode,
154
struct ceph_acl_sec_ctx *as)
155
{
156
int ret, ctxsize;
157
bool encrypted = false;
158
struct ceph_inode_info *ci = ceph_inode(inode);
159
160
ret = fscrypt_prepare_new_inode(dir, inode, &encrypted);
161
if (ret)
162
return ret;
163
if (!encrypted)
164
return 0;
165
166
as->fscrypt_auth = kzalloc(sizeof(*as->fscrypt_auth), GFP_KERNEL);
167
if (!as->fscrypt_auth)
168
return -ENOMEM;
169
170
ctxsize = fscrypt_context_for_new_inode(as->fscrypt_auth->cfa_blob,
171
inode);
172
if (ctxsize < 0)
173
return ctxsize;
174
175
as->fscrypt_auth->cfa_version = cpu_to_le32(CEPH_FSCRYPT_AUTH_VERSION);
176
as->fscrypt_auth->cfa_blob_len = cpu_to_le32(ctxsize);
177
178
WARN_ON_ONCE(ci->fscrypt_auth);
179
kfree(ci->fscrypt_auth);
180
ci->fscrypt_auth_len = ceph_fscrypt_auth_len(as->fscrypt_auth);
181
ci->fscrypt_auth = kmemdup(as->fscrypt_auth, ci->fscrypt_auth_len,
182
GFP_KERNEL);
183
if (!ci->fscrypt_auth)
184
return -ENOMEM;
185
186
inode->i_flags |= S_ENCRYPTED;
187
188
return 0;
189
}
190
191
void ceph_fscrypt_as_ctx_to_req(struct ceph_mds_request *req,
192
struct ceph_acl_sec_ctx *as)
193
{
194
swap(req->r_fscrypt_auth, as->fscrypt_auth);
195
}
196
197
/*
198
* User-created snapshots can't start with '_'. Snapshots that start with this
199
* character are special (hint: there aren't real snapshots) and use the
200
* following format:
201
*
202
* _<SNAPSHOT-NAME>_<INODE-NUMBER>
203
*
204
* where:
205
* - <SNAPSHOT-NAME> - the real snapshot name that may need to be decrypted,
206
* - <INODE-NUMBER> - the inode number (in decimal) for the actual snapshot
207
*
208
* This function parses these snapshot names and returns the inode
209
* <INODE-NUMBER>. 'name_len' will also bet set with the <SNAPSHOT-NAME>
210
* length.
211
*/
212
static struct inode *parse_longname(const struct inode *parent,
213
const char *name, int *name_len)
214
{
215
struct ceph_client *cl = ceph_inode_to_client(parent);
216
struct inode *dir = NULL;
217
struct ceph_vino vino = { .snap = CEPH_NOSNAP };
218
char *name_end, *inode_number;
219
int ret = -EIO;
220
/* NUL-terminate */
221
char *str __free(kfree) = kmemdup_nul(name, *name_len, GFP_KERNEL);
222
if (!str)
223
return ERR_PTR(-ENOMEM);
224
/* Skip initial '_' */
225
str++;
226
name_end = strrchr(str, '_');
227
if (!name_end) {
228
doutc(cl, "failed to parse long snapshot name: %s\n", str);
229
return ERR_PTR(-EIO);
230
}
231
*name_len = (name_end - str);
232
if (*name_len <= 0) {
233
pr_err_client(cl, "failed to parse long snapshot name\n");
234
return ERR_PTR(-EIO);
235
}
236
237
/* Get the inode number */
238
inode_number = name_end + 1;
239
ret = kstrtou64(inode_number, 10, &vino.ino);
240
if (ret) {
241
doutc(cl, "failed to parse inode number: %s\n", str);
242
return ERR_PTR(ret);
243
}
244
245
/* And finally the inode */
246
dir = ceph_find_inode(parent->i_sb, vino);
247
if (!dir) {
248
/* This can happen if we're not mounting cephfs on the root */
249
dir = ceph_get_inode(parent->i_sb, vino, NULL);
250
if (IS_ERR(dir))
251
doutc(cl, "can't find inode %s (%s)\n", inode_number, name);
252
}
253
return dir;
254
}
255
256
int ceph_encode_encrypted_dname(struct inode *parent, char *buf, int elen)
257
{
258
struct ceph_client *cl = ceph_inode_to_client(parent);
259
struct inode *dir = parent;
260
char *p = buf;
261
u32 len;
262
int name_len = elen;
263
int ret;
264
u8 *cryptbuf = NULL;
265
266
/* Handle the special case of snapshot names that start with '_' */
267
if (ceph_snap(dir) == CEPH_SNAPDIR && *p == '_') {
268
dir = parse_longname(parent, p, &name_len);
269
if (IS_ERR(dir))
270
return PTR_ERR(dir);
271
p++; /* skip initial '_' */
272
}
273
274
if (!fscrypt_has_encryption_key(dir))
275
goto out;
276
277
/*
278
* Convert cleartext d_name to ciphertext. If result is longer than
279
* CEPH_NOHASH_NAME_MAX, sha256 the remaining bytes
280
*
281
* See: fscrypt_setup_filename
282
*/
283
if (!fscrypt_fname_encrypted_size(dir, name_len, NAME_MAX, &len)) {
284
elen = -ENAMETOOLONG;
285
goto out;
286
}
287
288
/* Allocate a buffer appropriate to hold the result */
289
cryptbuf = kmalloc(len > CEPH_NOHASH_NAME_MAX ? NAME_MAX : len,
290
GFP_KERNEL);
291
if (!cryptbuf) {
292
elen = -ENOMEM;
293
goto out;
294
}
295
296
ret = fscrypt_fname_encrypt(dir,
297
&(struct qstr)QSTR_INIT(p, name_len),
298
cryptbuf, len);
299
if (ret) {
300
elen = ret;
301
goto out;
302
}
303
304
/* hash the end if the name is long enough */
305
if (len > CEPH_NOHASH_NAME_MAX) {
306
u8 hash[SHA256_DIGEST_SIZE];
307
u8 *extra = cryptbuf + CEPH_NOHASH_NAME_MAX;
308
309
/*
310
* hash the extra bytes and overwrite crypttext beyond that
311
* point with it
312
*/
313
sha256(extra, len - CEPH_NOHASH_NAME_MAX, hash);
314
memcpy(extra, hash, SHA256_DIGEST_SIZE);
315
len = CEPH_NOHASH_NAME_MAX + SHA256_DIGEST_SIZE;
316
}
317
318
/* base64 encode the encrypted name */
319
elen = ceph_base64_encode(cryptbuf, len, p);
320
doutc(cl, "base64-encoded ciphertext name = %.*s\n", elen, p);
321
322
/* To understand the 240 limit, see CEPH_NOHASH_NAME_MAX comments */
323
WARN_ON(elen > 240);
324
if (dir != parent) // leading _ is already there; append _<inum>
325
elen += 1 + sprintf(p + elen, "_%ld", dir->i_ino);
326
327
out:
328
kfree(cryptbuf);
329
if (dir != parent) {
330
if ((dir->i_state & I_NEW))
331
discard_new_inode(dir);
332
else
333
iput(dir);
334
}
335
return elen;
336
}
337
338
/**
339
* ceph_fname_to_usr - convert a filename for userland presentation
340
* @fname: ceph_fname to be converted
341
* @tname: temporary name buffer to use for conversion (may be NULL)
342
* @oname: where converted name should be placed
343
* @is_nokey: set to true if key wasn't available during conversion (may be NULL)
344
*
345
* Given a filename (usually from the MDS), format it for presentation to
346
* userland. If @parent is not encrypted, just pass it back as-is.
347
*
348
* Otherwise, base64 decode the string, and then ask fscrypt to format it
349
* for userland presentation.
350
*
351
* Returns 0 on success or negative error code on error.
352
*/
353
int ceph_fname_to_usr(const struct ceph_fname *fname, struct fscrypt_str *tname,
354
struct fscrypt_str *oname, bool *is_nokey)
355
{
356
struct inode *dir = fname->dir;
357
struct fscrypt_str _tname = FSTR_INIT(NULL, 0);
358
struct fscrypt_str iname;
359
char *name = fname->name;
360
int name_len = fname->name_len;
361
int ret;
362
363
/* Sanity check that the resulting name will fit in the buffer */
364
if (fname->name_len > NAME_MAX || fname->ctext_len > NAME_MAX)
365
return -EIO;
366
367
/* Handle the special case of snapshot names that start with '_' */
368
if ((ceph_snap(dir) == CEPH_SNAPDIR) && (name_len > 0) &&
369
(name[0] == '_')) {
370
dir = parse_longname(dir, name, &name_len);
371
if (IS_ERR(dir))
372
return PTR_ERR(dir);
373
name++; /* skip initial '_' */
374
}
375
376
if (!IS_ENCRYPTED(dir)) {
377
oname->name = fname->name;
378
oname->len = fname->name_len;
379
ret = 0;
380
goto out_inode;
381
}
382
383
ret = ceph_fscrypt_prepare_readdir(dir);
384
if (ret)
385
goto out_inode;
386
387
/*
388
* Use the raw dentry name as sent by the MDS instead of
389
* generating a nokey name via fscrypt.
390
*/
391
if (!fscrypt_has_encryption_key(dir)) {
392
if (fname->no_copy)
393
oname->name = fname->name;
394
else
395
memcpy(oname->name, fname->name, fname->name_len);
396
oname->len = fname->name_len;
397
if (is_nokey)
398
*is_nokey = true;
399
ret = 0;
400
goto out_inode;
401
}
402
403
if (fname->ctext_len == 0) {
404
int declen;
405
406
if (!tname) {
407
ret = fscrypt_fname_alloc_buffer(NAME_MAX, &_tname);
408
if (ret)
409
goto out_inode;
410
tname = &_tname;
411
}
412
413
declen = ceph_base64_decode(name, name_len, tname->name);
414
if (declen <= 0) {
415
ret = -EIO;
416
goto out;
417
}
418
iname.name = tname->name;
419
iname.len = declen;
420
} else {
421
iname.name = fname->ctext;
422
iname.len = fname->ctext_len;
423
}
424
425
ret = fscrypt_fname_disk_to_usr(dir, 0, 0, &iname, oname);
426
if (!ret && (dir != fname->dir)) {
427
char tmp_buf[CEPH_BASE64_CHARS(NAME_MAX)];
428
429
name_len = snprintf(tmp_buf, sizeof(tmp_buf), "_%.*s_%ld",
430
oname->len, oname->name, dir->i_ino);
431
memcpy(oname->name, tmp_buf, name_len);
432
oname->len = name_len;
433
}
434
435
out:
436
fscrypt_fname_free_buffer(&_tname);
437
out_inode:
438
if (dir != fname->dir) {
439
if ((dir->i_state & I_NEW))
440
discard_new_inode(dir);
441
else
442
iput(dir);
443
}
444
return ret;
445
}
446
447
/**
448
* ceph_fscrypt_prepare_readdir - simple __fscrypt_prepare_readdir() wrapper
449
* @dir: directory inode for readdir prep
450
*
451
* Simple wrapper around __fscrypt_prepare_readdir() that will mark directory as
452
* non-complete if this call results in having the directory unlocked.
453
*
454
* Returns:
455
* 1 - if directory was locked and key is now loaded (i.e. dir is unlocked)
456
* 0 - if directory is still locked
457
* < 0 - if __fscrypt_prepare_readdir() fails
458
*/
459
int ceph_fscrypt_prepare_readdir(struct inode *dir)
460
{
461
bool had_key = fscrypt_has_encryption_key(dir);
462
int err;
463
464
if (!IS_ENCRYPTED(dir))
465
return 0;
466
467
err = __fscrypt_prepare_readdir(dir);
468
if (err)
469
return err;
470
if (!had_key && fscrypt_has_encryption_key(dir)) {
471
/* directory just got unlocked, mark it as not complete */
472
ceph_dir_clear_complete(dir);
473
return 1;
474
}
475
return 0;
476
}
477
478
int ceph_fscrypt_decrypt_block_inplace(const struct inode *inode,
479
struct page *page, unsigned int len,
480
unsigned int offs, u64 lblk_num)
481
{
482
struct ceph_client *cl = ceph_inode_to_client(inode);
483
484
doutc(cl, "%p %llx.%llx len %u offs %u blk %llu\n", inode,
485
ceph_vinop(inode), len, offs, lblk_num);
486
return fscrypt_decrypt_block_inplace(inode, page, len, offs, lblk_num);
487
}
488
489
int ceph_fscrypt_encrypt_block_inplace(const struct inode *inode,
490
struct page *page, unsigned int len,
491
unsigned int offs, u64 lblk_num)
492
{
493
struct ceph_client *cl = ceph_inode_to_client(inode);
494
495
doutc(cl, "%p %llx.%llx len %u offs %u blk %llu\n", inode,
496
ceph_vinop(inode), len, offs, lblk_num);
497
return fscrypt_encrypt_block_inplace(inode, page, len, offs, lblk_num);
498
}
499
500
/**
501
* ceph_fscrypt_decrypt_pages - decrypt an array of pages
502
* @inode: pointer to inode associated with these pages
503
* @page: pointer to page array
504
* @off: offset into the file that the read data starts
505
* @len: max length to decrypt
506
*
507
* Decrypt an array of fscrypt'ed pages and return the amount of
508
* data decrypted. Any data in the page prior to the start of the
509
* first complete block in the read is ignored. Any incomplete
510
* crypto blocks at the end of the array are ignored (and should
511
* probably be zeroed by the caller).
512
*
513
* Returns the length of the decrypted data or a negative errno.
514
*/
515
int ceph_fscrypt_decrypt_pages(struct inode *inode, struct page **page,
516
u64 off, int len)
517
{
518
int i, num_blocks;
519
u64 baseblk = off >> CEPH_FSCRYPT_BLOCK_SHIFT;
520
int ret = 0;
521
522
/*
523
* We can't deal with partial blocks on an encrypted file, so mask off
524
* the last bit.
525
*/
526
num_blocks = ceph_fscrypt_blocks(off, len & CEPH_FSCRYPT_BLOCK_MASK);
527
528
/* Decrypt each block */
529
for (i = 0; i < num_blocks; ++i) {
530
int blkoff = i << CEPH_FSCRYPT_BLOCK_SHIFT;
531
int pgidx = blkoff >> PAGE_SHIFT;
532
unsigned int pgoffs = offset_in_page(blkoff);
533
int fret;
534
535
fret = ceph_fscrypt_decrypt_block_inplace(inode, page[pgidx],
536
CEPH_FSCRYPT_BLOCK_SIZE, pgoffs,
537
baseblk + i);
538
if (fret < 0) {
539
if (ret == 0)
540
ret = fret;
541
break;
542
}
543
ret += CEPH_FSCRYPT_BLOCK_SIZE;
544
}
545
return ret;
546
}
547
548
/**
549
* ceph_fscrypt_decrypt_extents: decrypt received extents in given buffer
550
* @inode: inode associated with pages being decrypted
551
* @page: pointer to page array
552
* @off: offset into the file that the data in page[0] starts
553
* @map: pointer to extent array
554
* @ext_cnt: length of extent array
555
*
556
* Given an extent map and a page array, decrypt the received data in-place,
557
* skipping holes. Returns the offset into buffer of end of last decrypted
558
* block.
559
*/
560
int ceph_fscrypt_decrypt_extents(struct inode *inode, struct page **page,
561
u64 off, struct ceph_sparse_extent *map,
562
u32 ext_cnt)
563
{
564
struct ceph_client *cl = ceph_inode_to_client(inode);
565
int i, ret = 0;
566
struct ceph_inode_info *ci = ceph_inode(inode);
567
u64 objno, objoff;
568
u32 xlen;
569
570
/* Nothing to do for empty array */
571
if (ext_cnt == 0) {
572
doutc(cl, "%p %llx.%llx empty array, ret 0\n", inode,
573
ceph_vinop(inode));
574
return 0;
575
}
576
577
ceph_calc_file_object_mapping(&ci->i_layout, off, map[0].len,
578
&objno, &objoff, &xlen);
579
580
for (i = 0; i < ext_cnt; ++i) {
581
struct ceph_sparse_extent *ext = &map[i];
582
int pgsoff = ext->off - objoff;
583
int pgidx = pgsoff >> PAGE_SHIFT;
584
int fret;
585
586
if ((ext->off | ext->len) & ~CEPH_FSCRYPT_BLOCK_MASK) {
587
pr_warn_client(cl,
588
"%p %llx.%llx bad encrypted sparse extent "
589
"idx %d off %llx len %llx\n",
590
inode, ceph_vinop(inode), i, ext->off,
591
ext->len);
592
return -EIO;
593
}
594
fret = ceph_fscrypt_decrypt_pages(inode, &page[pgidx],
595
off + pgsoff, ext->len);
596
doutc(cl, "%p %llx.%llx [%d] 0x%llx~0x%llx fret %d\n", inode,
597
ceph_vinop(inode), i, ext->off, ext->len, fret);
598
if (fret < 0) {
599
if (ret == 0)
600
ret = fret;
601
break;
602
}
603
ret = pgsoff + fret;
604
}
605
doutc(cl, "ret %d\n", ret);
606
return ret;
607
}
608
609
/**
610
* ceph_fscrypt_encrypt_pages - encrypt an array of pages
611
* @inode: pointer to inode associated with these pages
612
* @page: pointer to page array
613
* @off: offset into the file that the data starts
614
* @len: max length to encrypt
615
*
616
* Encrypt an array of cleartext pages and return the amount of
617
* data encrypted. Any data in the page prior to the start of the
618
* first complete block in the read is ignored. Any incomplete
619
* crypto blocks at the end of the array are ignored.
620
*
621
* Returns the length of the encrypted data or a negative errno.
622
*/
623
int ceph_fscrypt_encrypt_pages(struct inode *inode, struct page **page, u64 off,
624
int len)
625
{
626
int i, num_blocks;
627
u64 baseblk = off >> CEPH_FSCRYPT_BLOCK_SHIFT;
628
int ret = 0;
629
630
/*
631
* We can't deal with partial blocks on an encrypted file, so mask off
632
* the last bit.
633
*/
634
num_blocks = ceph_fscrypt_blocks(off, len & CEPH_FSCRYPT_BLOCK_MASK);
635
636
/* Encrypt each block */
637
for (i = 0; i < num_blocks; ++i) {
638
int blkoff = i << CEPH_FSCRYPT_BLOCK_SHIFT;
639
int pgidx = blkoff >> PAGE_SHIFT;
640
unsigned int pgoffs = offset_in_page(blkoff);
641
int fret;
642
643
fret = ceph_fscrypt_encrypt_block_inplace(inode, page[pgidx],
644
CEPH_FSCRYPT_BLOCK_SIZE, pgoffs,
645
baseblk + i);
646
if (fret < 0) {
647
if (ret == 0)
648
ret = fret;
649
break;
650
}
651
ret += CEPH_FSCRYPT_BLOCK_SIZE;
652
}
653
return ret;
654
}
655
656