crypto.c (14e034a61c908d4479be1a7ee9fe5b8d3d1f09b8) | crypto.c (77cdb7e17e39ebb986f60bbd3c2b3507687bf475) |
---|---|
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> | 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> |
|
12 13#include "super.h" 14#include "mds_client.h" 15#include "crypto.h" 16 17/* 18 * The base64url encoding used by fscrypt includes the '_' character, which may 19 * cause problems in snapshot names (which can not start with '_'). Thus, we --- 340 unchanged lines hidden (view full) --- 360 return err; 361 if (!had_key && fscrypt_has_encryption_key(dir)) { 362 /* directory just got unlocked, mark it as not complete */ 363 ceph_dir_clear_complete(dir); 364 return 1; 365 } 366 return 0; 367} | 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 --- 340 unchanged lines hidden (view full) --- 361 return err; 362 if (!had_key && fscrypt_has_encryption_key(dir)) { 363 /* directory just got unlocked, mark it as not complete */ 364 ceph_dir_clear_complete(dir); 365 return 1; 366 } 367 return 0; 368} |
369 370int ceph_fscrypt_decrypt_block_inplace(const struct inode *inode, 371 struct page *page, unsigned int len, 372 unsigned int offs, u64 lblk_num) 373{ 374 dout("%s: len %u offs %u blk %llu\n", __func__, len, offs, lblk_num); 375 return fscrypt_decrypt_block_inplace(inode, page, len, offs, lblk_num); 376} 377 378int ceph_fscrypt_encrypt_block_inplace(const struct inode *inode, 379 struct page *page, unsigned int len, 380 unsigned int offs, u64 lblk_num, 381 gfp_t gfp_flags) 382{ 383 dout("%s: len %u offs %u blk %llu\n", __func__, len, offs, lblk_num); 384 return fscrypt_encrypt_block_inplace(inode, page, len, offs, lblk_num, 385 gfp_flags); 386} 387 388/** 389 * ceph_fscrypt_decrypt_pages - decrypt an array of pages 390 * @inode: pointer to inode associated with these pages 391 * @page: pointer to page array 392 * @off: offset into the file that the read data starts 393 * @len: max length to decrypt 394 * 395 * Decrypt an array of fscrypt'ed pages and return the amount of 396 * data decrypted. Any data in the page prior to the start of the 397 * first complete block in the read is ignored. Any incomplete 398 * crypto blocks at the end of the array are ignored (and should 399 * probably be zeroed by the caller). 400 * 401 * Returns the length of the decrypted data or a negative errno. 402 */ 403int ceph_fscrypt_decrypt_pages(struct inode *inode, struct page **page, 404 u64 off, int len) 405{ 406 int i, num_blocks; 407 u64 baseblk = off >> CEPH_FSCRYPT_BLOCK_SHIFT; 408 int ret = 0; 409 410 /* 411 * We can't deal with partial blocks on an encrypted file, so mask off 412 * the last bit. 413 */ 414 num_blocks = ceph_fscrypt_blocks(off, len & CEPH_FSCRYPT_BLOCK_MASK); 415 416 /* Decrypt each block */ 417 for (i = 0; i < num_blocks; ++i) { 418 int blkoff = i << CEPH_FSCRYPT_BLOCK_SHIFT; 419 int pgidx = blkoff >> PAGE_SHIFT; 420 unsigned int pgoffs = offset_in_page(blkoff); 421 int fret; 422 423 fret = ceph_fscrypt_decrypt_block_inplace(inode, page[pgidx], 424 CEPH_FSCRYPT_BLOCK_SIZE, pgoffs, 425 baseblk + i); 426 if (fret < 0) { 427 if (ret == 0) 428 ret = fret; 429 break; 430 } 431 ret += CEPH_FSCRYPT_BLOCK_SIZE; 432 } 433 return ret; 434} 435 436/** 437 * ceph_fscrypt_decrypt_extents: decrypt received extents in given buffer 438 * @inode: inode associated with pages being decrypted 439 * @page: pointer to page array 440 * @off: offset into the file that the data in page[0] starts 441 * @map: pointer to extent array 442 * @ext_cnt: length of extent array 443 * 444 * Given an extent map and a page array, decrypt the received data in-place, 445 * skipping holes. Returns the offset into buffer of end of last decrypted 446 * block. 447 */ 448int ceph_fscrypt_decrypt_extents(struct inode *inode, struct page **page, 449 u64 off, struct ceph_sparse_extent *map, 450 u32 ext_cnt) 451{ 452 int i, ret = 0; 453 struct ceph_inode_info *ci = ceph_inode(inode); 454 u64 objno, objoff; 455 u32 xlen; 456 457 /* Nothing to do for empty array */ 458 if (ext_cnt == 0) { 459 dout("%s: empty array, ret 0\n", __func__); 460 return 0; 461 } 462 463 ceph_calc_file_object_mapping(&ci->i_layout, off, map[0].len, 464 &objno, &objoff, &xlen); 465 466 for (i = 0; i < ext_cnt; ++i) { 467 struct ceph_sparse_extent *ext = &map[i]; 468 int pgsoff = ext->off - objoff; 469 int pgidx = pgsoff >> PAGE_SHIFT; 470 int fret; 471 472 if ((ext->off | ext->len) & ~CEPH_FSCRYPT_BLOCK_MASK) { 473 pr_warn("%s: bad encrypted sparse extent idx %d off %llx len %llx\n", 474 __func__, i, ext->off, ext->len); 475 return -EIO; 476 } 477 fret = ceph_fscrypt_decrypt_pages(inode, &page[pgidx], 478 off + pgsoff, ext->len); 479 dout("%s: [%d] 0x%llx~0x%llx fret %d\n", __func__, i, 480 ext->off, ext->len, fret); 481 if (fret < 0) { 482 if (ret == 0) 483 ret = fret; 484 break; 485 } 486 ret = pgsoff + fret; 487 } 488 dout("%s: ret %d\n", __func__, ret); 489 return ret; 490} 491 492/** 493 * ceph_fscrypt_encrypt_pages - encrypt an array of pages 494 * @inode: pointer to inode associated with these pages 495 * @page: pointer to page array 496 * @off: offset into the file that the data starts 497 * @len: max length to encrypt 498 * @gfp: gfp flags to use for allocation 499 * 500 * Decrypt an array of cleartext pages and return the amount of 501 * data encrypted. Any data in the page prior to the start of the 502 * first complete block in the read is ignored. Any incomplete 503 * crypto blocks at the end of the array are ignored. 504 * 505 * Returns the length of the encrypted data or a negative errno. 506 */ 507int ceph_fscrypt_encrypt_pages(struct inode *inode, struct page **page, u64 off, 508 int len, gfp_t gfp) 509{ 510 int i, num_blocks; 511 u64 baseblk = off >> CEPH_FSCRYPT_BLOCK_SHIFT; 512 int ret = 0; 513 514 /* 515 * We can't deal with partial blocks on an encrypted file, so mask off 516 * the last bit. 517 */ 518 num_blocks = ceph_fscrypt_blocks(off, len & CEPH_FSCRYPT_BLOCK_MASK); 519 520 /* Encrypt each block */ 521 for (i = 0; i < num_blocks; ++i) { 522 int blkoff = i << CEPH_FSCRYPT_BLOCK_SHIFT; 523 int pgidx = blkoff >> PAGE_SHIFT; 524 unsigned int pgoffs = offset_in_page(blkoff); 525 int fret; 526 527 fret = ceph_fscrypt_encrypt_block_inplace(inode, page[pgidx], 528 CEPH_FSCRYPT_BLOCK_SIZE, pgoffs, 529 baseblk + i, gfp); 530 if (fret < 0) { 531 if (ret == 0) 532 ret = fret; 533 break; 534 } 535 ret += CEPH_FSCRYPT_BLOCK_SIZE; 536 } 537 return ret; 538} |
|