12d332d5bSJeff Layton /* SPDX-License-Identifier: GPL-2.0 */ 22d332d5bSJeff Layton /* 32d332d5bSJeff Layton * Ceph fscrypt functionality 42d332d5bSJeff Layton */ 52d332d5bSJeff Layton 62d332d5bSJeff Layton #ifndef _CEPH_CRYPTO_H 72d332d5bSJeff Layton #define _CEPH_CRYPTO_H 82d332d5bSJeff Layton 93fd945a7SJeff Layton #include <crypto/sha2.h> 102d332d5bSJeff Layton #include <linux/fscrypt.h> 112d332d5bSJeff Layton 1294af0470SJeff Layton #define CEPH_FSCRYPT_BLOCK_SHIFT 12 1394af0470SJeff Layton #define CEPH_FSCRYPT_BLOCK_SIZE (_AC(1, UL) << CEPH_FSCRYPT_BLOCK_SHIFT) 1494af0470SJeff Layton #define CEPH_FSCRYPT_BLOCK_MASK (~(CEPH_FSCRYPT_BLOCK_SIZE-1)) 1594af0470SJeff Layton 166b5717bdSJeff Layton struct ceph_fs_client; 176b5717bdSJeff Layton struct ceph_acl_sec_ctx; 186b5717bdSJeff Layton struct ceph_mds_request; 196b5717bdSJeff Layton 20457117f0SJeff Layton struct ceph_fname { 21457117f0SJeff Layton struct inode *dir; 22457117f0SJeff Layton char *name; // b64 encoded, possibly hashed 23457117f0SJeff Layton unsigned char *ctext; // binary crypttext (if any) 24457117f0SJeff Layton u32 name_len; // length of name buffer 25457117f0SJeff Layton u32 ctext_len; // length of crypttext 26af9ffa6dSXiubo Li bool no_copy; 27457117f0SJeff Layton }; 28457117f0SJeff Layton 295c64737dSXiubo Li /* 305c64737dSXiubo Li * Header for the crypted file when truncating the size, this 315c64737dSXiubo Li * will be sent to MDS, and the MDS will update the encrypted 325c64737dSXiubo Li * last block and then truncate the size. 335c64737dSXiubo Li */ 345c64737dSXiubo Li struct ceph_fscrypt_truncate_size_header { 355c64737dSXiubo Li __u8 ver; 365c64737dSXiubo Li __u8 compat; 375c64737dSXiubo Li 385c64737dSXiubo Li /* 395c64737dSXiubo Li * It will be sizeof(assert_ver + file_offset + block_size) 405c64737dSXiubo Li * if the last block is empty when it's located in a file 415c64737dSXiubo Li * hole. Or the data_len will plus CEPH_FSCRYPT_BLOCK_SIZE. 425c64737dSXiubo Li */ 435c64737dSXiubo Li __le32 data_len; 445c64737dSXiubo Li 455c64737dSXiubo Li __le64 change_attr; 465c64737dSXiubo Li __le64 file_offset; 475c64737dSXiubo Li __le32 block_size; 485c64737dSXiubo Li } __packed; 495c64737dSXiubo Li 502d332d5bSJeff Layton struct ceph_fscrypt_auth { 512d332d5bSJeff Layton __le32 cfa_version; 522d332d5bSJeff Layton __le32 cfa_blob_len; 532d332d5bSJeff Layton u8 cfa_blob[FSCRYPT_SET_CONTEXT_MAX_SIZE]; 542d332d5bSJeff Layton } __packed; 552d332d5bSJeff Layton 562d332d5bSJeff Layton #define CEPH_FSCRYPT_AUTH_VERSION 1 572d332d5bSJeff Layton static inline u32 ceph_fscrypt_auth_len(struct ceph_fscrypt_auth *fa) 582d332d5bSJeff Layton { 592d332d5bSJeff Layton u32 ctxsize = le32_to_cpu(fa->cfa_blob_len); 602d332d5bSJeff Layton 612d332d5bSJeff Layton return offsetof(struct ceph_fscrypt_auth, cfa_blob) + ctxsize; 622d332d5bSJeff Layton } 632d332d5bSJeff Layton 642d332d5bSJeff Layton #ifdef CONFIG_FS_ENCRYPTION 6564e86f63SLuís Henriques /* 6664e86f63SLuís Henriques * We want to encrypt filenames when creating them, but the encrypted 6764e86f63SLuís Henriques * versions of those names may have illegal characters in them. To mitigate 6864e86f63SLuís Henriques * that, we base64 encode them, but that gives us a result that can exceed 6964e86f63SLuís Henriques * NAME_MAX. 7064e86f63SLuís Henriques * 7164e86f63SLuís Henriques * Follow a similar scheme to fscrypt itself, and cap the filename to a 7264e86f63SLuís Henriques * smaller size. If the ciphertext name is longer than the value below, then 7364e86f63SLuís Henriques * sha256 hash the remaining bytes. 7464e86f63SLuís Henriques * 7564e86f63SLuís Henriques * For the fscrypt_nokey_name struct the dirhash[2] member is useless in ceph 7664e86f63SLuís Henriques * so the corresponding struct will be: 7764e86f63SLuís Henriques * 7864e86f63SLuís Henriques * struct fscrypt_ceph_nokey_name { 7964e86f63SLuís Henriques * u8 bytes[157]; 8064e86f63SLuís Henriques * u8 sha256[SHA256_DIGEST_SIZE]; 8164e86f63SLuís Henriques * }; // 180 bytes => 240 bytes base64-encoded, which is <= NAME_MAX (255) 8264e86f63SLuís Henriques * 8364e86f63SLuís Henriques * (240 bytes is the maximum size allowed for snapshot names to take into 8464e86f63SLuís Henriques * account the format: '_<SNAPSHOT-NAME>_<INODE-NUMBER>'.) 8564e86f63SLuís Henriques * 8664e86f63SLuís Henriques * Note that for long names that end up having their tail portion hashed, we 8764e86f63SLuís Henriques * must also store the full encrypted name (in the dentry's alternate_name 8864e86f63SLuís Henriques * field). 8964e86f63SLuís Henriques */ 9064e86f63SLuís Henriques #define CEPH_NOHASH_NAME_MAX (180 - SHA256_DIGEST_SIZE) 9164e86f63SLuís Henriques 9264e86f63SLuís Henriques #define CEPH_BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3) 9364e86f63SLuís Henriques 9464e86f63SLuís Henriques int ceph_base64_encode(const u8 *src, int srclen, char *dst); 9564e86f63SLuís Henriques int ceph_base64_decode(const char *src, int srclen, u8 *dst); 9664e86f63SLuís Henriques 972d332d5bSJeff Layton void ceph_fscrypt_set_ops(struct super_block *sb); 982d332d5bSJeff Layton 996b5717bdSJeff Layton void ceph_fscrypt_free_dummy_policy(struct ceph_fs_client *fsc); 1006b5717bdSJeff Layton 1016b5717bdSJeff Layton int ceph_fscrypt_prepare_context(struct inode *dir, struct inode *inode, 1026b5717bdSJeff Layton struct ceph_acl_sec_ctx *as); 1036b5717bdSJeff Layton void ceph_fscrypt_as_ctx_to_req(struct ceph_mds_request *req, 1046b5717bdSJeff Layton struct ceph_acl_sec_ctx *as); 105*dd66df00SLuís Henriques int ceph_encode_encrypted_dname(struct inode *parent, struct qstr *d_name, 106*dd66df00SLuís Henriques char *buf); 107*dd66df00SLuís Henriques int ceph_encode_encrypted_fname(struct inode *parent, struct dentry *dentry, 108*dd66df00SLuís Henriques char *buf); 1096b5717bdSJeff Layton 110457117f0SJeff Layton static inline int ceph_fname_alloc_buffer(struct inode *parent, 111457117f0SJeff Layton struct fscrypt_str *fname) 112457117f0SJeff Layton { 113457117f0SJeff Layton if (!IS_ENCRYPTED(parent)) 114457117f0SJeff Layton return 0; 115457117f0SJeff Layton return fscrypt_fname_alloc_buffer(NAME_MAX, fname); 116457117f0SJeff Layton } 117457117f0SJeff Layton 118457117f0SJeff Layton static inline void ceph_fname_free_buffer(struct inode *parent, 119457117f0SJeff Layton struct fscrypt_str *fname) 120457117f0SJeff Layton { 121457117f0SJeff Layton if (IS_ENCRYPTED(parent)) 122457117f0SJeff Layton fscrypt_fname_free_buffer(fname); 123457117f0SJeff Layton } 124457117f0SJeff Layton 125457117f0SJeff Layton int ceph_fname_to_usr(const struct ceph_fname *fname, struct fscrypt_str *tname, 126457117f0SJeff Layton struct fscrypt_str *oname, bool *is_nokey); 12714e034a6SLuís Henriques int ceph_fscrypt_prepare_readdir(struct inode *dir); 128457117f0SJeff Layton 12977cdb7e1SJeff Layton static inline unsigned int ceph_fscrypt_blocks(u64 off, u64 len) 13077cdb7e1SJeff Layton { 13177cdb7e1SJeff Layton /* crypto blocks cannot span more than one page */ 13277cdb7e1SJeff Layton BUILD_BUG_ON(CEPH_FSCRYPT_BLOCK_SHIFT > PAGE_SHIFT); 13377cdb7e1SJeff Layton 13477cdb7e1SJeff Layton return ((off+len+CEPH_FSCRYPT_BLOCK_SIZE-1) >> CEPH_FSCRYPT_BLOCK_SHIFT) - 13577cdb7e1SJeff Layton (off >> CEPH_FSCRYPT_BLOCK_SHIFT); 13677cdb7e1SJeff Layton } 13777cdb7e1SJeff Layton 13877cdb7e1SJeff Layton /* 13977cdb7e1SJeff Layton * If we have an encrypted inode then we must adjust the offset and 14077cdb7e1SJeff Layton * range of the on-the-wire read to cover an entire encryption block. 14177cdb7e1SJeff Layton * The copy will be done using the original offset and length, after 14277cdb7e1SJeff Layton * we've decrypted the result. 14377cdb7e1SJeff Layton */ 14477cdb7e1SJeff Layton static inline void ceph_fscrypt_adjust_off_and_len(struct inode *inode, 14577cdb7e1SJeff Layton u64 *off, u64 *len) 14677cdb7e1SJeff Layton { 14777cdb7e1SJeff Layton if (IS_ENCRYPTED(inode)) { 14877cdb7e1SJeff Layton *len = ceph_fscrypt_blocks(*off, *len) * CEPH_FSCRYPT_BLOCK_SIZE; 14977cdb7e1SJeff Layton *off &= CEPH_FSCRYPT_BLOCK_MASK; 15077cdb7e1SJeff Layton } 15177cdb7e1SJeff Layton } 15277cdb7e1SJeff Layton 15377cdb7e1SJeff Layton int ceph_fscrypt_decrypt_block_inplace(const struct inode *inode, 15477cdb7e1SJeff Layton struct page *page, unsigned int len, 15577cdb7e1SJeff Layton unsigned int offs, u64 lblk_num); 15677cdb7e1SJeff Layton int ceph_fscrypt_encrypt_block_inplace(const struct inode *inode, 15777cdb7e1SJeff Layton struct page *page, unsigned int len, 15877cdb7e1SJeff Layton unsigned int offs, u64 lblk_num, 15977cdb7e1SJeff Layton gfp_t gfp_flags); 16077cdb7e1SJeff Layton int ceph_fscrypt_decrypt_pages(struct inode *inode, struct page **page, 16177cdb7e1SJeff Layton u64 off, int len); 16277cdb7e1SJeff Layton int ceph_fscrypt_decrypt_extents(struct inode *inode, struct page **page, 16377cdb7e1SJeff Layton u64 off, struct ceph_sparse_extent *map, 16477cdb7e1SJeff Layton u32 ext_cnt); 16577cdb7e1SJeff Layton int ceph_fscrypt_encrypt_pages(struct inode *inode, struct page **page, u64 off, 16677cdb7e1SJeff Layton int len, gfp_t gfp); 167d5520771SJeff Layton 168d5520771SJeff Layton static inline struct page *ceph_fscrypt_pagecache_page(struct page *page) 169d5520771SJeff Layton { 170d5520771SJeff Layton return fscrypt_is_bounce_page(page) ? fscrypt_pagecache_page(page) : page; 171d5520771SJeff Layton } 172d5520771SJeff Layton 1732d332d5bSJeff Layton #else /* CONFIG_FS_ENCRYPTION */ 1742d332d5bSJeff Layton 1752d332d5bSJeff Layton static inline void ceph_fscrypt_set_ops(struct super_block *sb) 1762d332d5bSJeff Layton { 1772d332d5bSJeff Layton } 1782d332d5bSJeff Layton 1796b5717bdSJeff Layton static inline void ceph_fscrypt_free_dummy_policy(struct ceph_fs_client *fsc) 1806b5717bdSJeff Layton { 1816b5717bdSJeff Layton } 1826b5717bdSJeff Layton 1836b5717bdSJeff Layton static inline int ceph_fscrypt_prepare_context(struct inode *dir, 1846b5717bdSJeff Layton struct inode *inode, 1856b5717bdSJeff Layton struct ceph_acl_sec_ctx *as) 1866b5717bdSJeff Layton { 1876b5717bdSJeff Layton if (IS_ENCRYPTED(dir)) 1886b5717bdSJeff Layton return -EOPNOTSUPP; 1896b5717bdSJeff Layton return 0; 1906b5717bdSJeff Layton } 1916b5717bdSJeff Layton 1926b5717bdSJeff Layton static inline void ceph_fscrypt_as_ctx_to_req(struct ceph_mds_request *req, 1936b5717bdSJeff Layton struct ceph_acl_sec_ctx *as_ctx) 1946b5717bdSJeff Layton { 1956b5717bdSJeff Layton } 1963fd945a7SJeff Layton 197*dd66df00SLuís Henriques static inline int ceph_encode_encrypted_dname(struct inode *parent, 198af9ffa6dSXiubo Li struct qstr *d_name, char *buf) 199af9ffa6dSXiubo Li { 200af9ffa6dSXiubo Li memcpy(buf, d_name->name, d_name->len); 201af9ffa6dSXiubo Li return d_name->len; 202af9ffa6dSXiubo Li } 203af9ffa6dSXiubo Li 204*dd66df00SLuís Henriques static inline int ceph_encode_encrypted_fname(struct inode *parent, 2053fd945a7SJeff Layton struct dentry *dentry, char *buf) 2063fd945a7SJeff Layton { 2073fd945a7SJeff Layton return -EOPNOTSUPP; 2083fd945a7SJeff Layton } 209457117f0SJeff Layton 210457117f0SJeff Layton static inline int ceph_fname_alloc_buffer(struct inode *parent, 211457117f0SJeff Layton struct fscrypt_str *fname) 212457117f0SJeff Layton { 213457117f0SJeff Layton return 0; 214457117f0SJeff Layton } 215457117f0SJeff Layton 216457117f0SJeff Layton static inline void ceph_fname_free_buffer(struct inode *parent, 217457117f0SJeff Layton struct fscrypt_str *fname) 218457117f0SJeff Layton { 219457117f0SJeff Layton } 220457117f0SJeff Layton 221457117f0SJeff Layton static inline int ceph_fname_to_usr(const struct ceph_fname *fname, 222457117f0SJeff Layton struct fscrypt_str *tname, 223457117f0SJeff Layton struct fscrypt_str *oname, bool *is_nokey) 224457117f0SJeff Layton { 225457117f0SJeff Layton oname->name = fname->name; 226457117f0SJeff Layton oname->len = fname->name_len; 227457117f0SJeff Layton return 0; 228457117f0SJeff Layton } 22914e034a6SLuís Henriques 23014e034a6SLuís Henriques static inline int ceph_fscrypt_prepare_readdir(struct inode *dir) 23114e034a6SLuís Henriques { 23214e034a6SLuís Henriques return 0; 23314e034a6SLuís Henriques } 23477cdb7e1SJeff Layton 23577cdb7e1SJeff Layton static inline void ceph_fscrypt_adjust_off_and_len(struct inode *inode, 23677cdb7e1SJeff Layton u64 *off, u64 *len) 23777cdb7e1SJeff Layton { 23877cdb7e1SJeff Layton } 23977cdb7e1SJeff Layton 24077cdb7e1SJeff Layton static inline int ceph_fscrypt_decrypt_block_inplace(const struct inode *inode, 24177cdb7e1SJeff Layton struct page *page, unsigned int len, 24277cdb7e1SJeff Layton unsigned int offs, u64 lblk_num) 24377cdb7e1SJeff Layton { 24477cdb7e1SJeff Layton return 0; 24577cdb7e1SJeff Layton } 24677cdb7e1SJeff Layton 24777cdb7e1SJeff Layton static inline int ceph_fscrypt_encrypt_block_inplace(const struct inode *inode, 24877cdb7e1SJeff Layton struct page *page, unsigned int len, 24977cdb7e1SJeff Layton unsigned int offs, u64 lblk_num, 25077cdb7e1SJeff Layton gfp_t gfp_flags) 25177cdb7e1SJeff Layton { 25277cdb7e1SJeff Layton return 0; 25377cdb7e1SJeff Layton } 25477cdb7e1SJeff Layton 25577cdb7e1SJeff Layton static inline int ceph_fscrypt_decrypt_pages(struct inode *inode, 25677cdb7e1SJeff Layton struct page **page, u64 off, 25777cdb7e1SJeff Layton int len) 25877cdb7e1SJeff Layton { 25977cdb7e1SJeff Layton return 0; 26077cdb7e1SJeff Layton } 26177cdb7e1SJeff Layton 26277cdb7e1SJeff Layton static inline int ceph_fscrypt_decrypt_extents(struct inode *inode, 26377cdb7e1SJeff Layton struct page **page, u64 off, 26477cdb7e1SJeff Layton struct ceph_sparse_extent *map, 26577cdb7e1SJeff Layton u32 ext_cnt) 26677cdb7e1SJeff Layton { 26777cdb7e1SJeff Layton return 0; 26877cdb7e1SJeff Layton } 26977cdb7e1SJeff Layton 27077cdb7e1SJeff Layton static inline int ceph_fscrypt_encrypt_pages(struct inode *inode, 27177cdb7e1SJeff Layton struct page **page, u64 off, 27277cdb7e1SJeff Layton int len, gfp_t gfp) 27377cdb7e1SJeff Layton { 27477cdb7e1SJeff Layton return 0; 27577cdb7e1SJeff Layton } 276d5520771SJeff Layton 277d5520771SJeff Layton static inline struct page *ceph_fscrypt_pagecache_page(struct page *page) 278d5520771SJeff Layton { 279d5520771SJeff Layton return page; 280d5520771SJeff Layton } 2812d332d5bSJeff Layton #endif /* CONFIG_FS_ENCRYPTION */ 2822d332d5bSJeff Layton 283d5520771SJeff Layton static inline loff_t ceph_fscrypt_page_offset(struct page *page) 284d5520771SJeff Layton { 285d5520771SJeff Layton return page_offset(ceph_fscrypt_pagecache_page(page)); 286d5520771SJeff Layton } 287d5520771SJeff Layton 288d5520771SJeff Layton #endif /* _CEPH_CRYPTO_H */ 289