162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Ceph fscrypt functionality 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#ifndef _CEPH_CRYPTO_H 762306a36Sopenharmony_ci#define _CEPH_CRYPTO_H 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <crypto/sha2.h> 1062306a36Sopenharmony_ci#include <linux/fscrypt.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#define CEPH_FSCRYPT_BLOCK_SHIFT 12 1362306a36Sopenharmony_ci#define CEPH_FSCRYPT_BLOCK_SIZE (_AC(1, UL) << CEPH_FSCRYPT_BLOCK_SHIFT) 1462306a36Sopenharmony_ci#define CEPH_FSCRYPT_BLOCK_MASK (~(CEPH_FSCRYPT_BLOCK_SIZE-1)) 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistruct ceph_fs_client; 1762306a36Sopenharmony_cistruct ceph_acl_sec_ctx; 1862306a36Sopenharmony_cistruct ceph_mds_request; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistruct ceph_fname { 2162306a36Sopenharmony_ci struct inode *dir; 2262306a36Sopenharmony_ci char *name; // b64 encoded, possibly hashed 2362306a36Sopenharmony_ci unsigned char *ctext; // binary crypttext (if any) 2462306a36Sopenharmony_ci u32 name_len; // length of name buffer 2562306a36Sopenharmony_ci u32 ctext_len; // length of crypttext 2662306a36Sopenharmony_ci bool no_copy; 2762306a36Sopenharmony_ci}; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* 3062306a36Sopenharmony_ci * Header for the crypted file when truncating the size, this 3162306a36Sopenharmony_ci * will be sent to MDS, and the MDS will update the encrypted 3262306a36Sopenharmony_ci * last block and then truncate the size. 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_cistruct ceph_fscrypt_truncate_size_header { 3562306a36Sopenharmony_ci __u8 ver; 3662306a36Sopenharmony_ci __u8 compat; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci /* 3962306a36Sopenharmony_ci * It will be sizeof(assert_ver + file_offset + block_size) 4062306a36Sopenharmony_ci * if the last block is empty when it's located in a file 4162306a36Sopenharmony_ci * hole. Or the data_len will plus CEPH_FSCRYPT_BLOCK_SIZE. 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci __le32 data_len; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci __le64 change_attr; 4662306a36Sopenharmony_ci __le64 file_offset; 4762306a36Sopenharmony_ci __le32 block_size; 4862306a36Sopenharmony_ci} __packed; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistruct ceph_fscrypt_auth { 5162306a36Sopenharmony_ci __le32 cfa_version; 5262306a36Sopenharmony_ci __le32 cfa_blob_len; 5362306a36Sopenharmony_ci u8 cfa_blob[FSCRYPT_SET_CONTEXT_MAX_SIZE]; 5462306a36Sopenharmony_ci} __packed; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci#define CEPH_FSCRYPT_AUTH_VERSION 1 5762306a36Sopenharmony_cistatic inline u32 ceph_fscrypt_auth_len(struct ceph_fscrypt_auth *fa) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci u32 ctxsize = le32_to_cpu(fa->cfa_blob_len); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci return offsetof(struct ceph_fscrypt_auth, cfa_blob) + ctxsize; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#ifdef CONFIG_FS_ENCRYPTION 6562306a36Sopenharmony_ci/* 6662306a36Sopenharmony_ci * We want to encrypt filenames when creating them, but the encrypted 6762306a36Sopenharmony_ci * versions of those names may have illegal characters in them. To mitigate 6862306a36Sopenharmony_ci * that, we base64 encode them, but that gives us a result that can exceed 6962306a36Sopenharmony_ci * NAME_MAX. 7062306a36Sopenharmony_ci * 7162306a36Sopenharmony_ci * Follow a similar scheme to fscrypt itself, and cap the filename to a 7262306a36Sopenharmony_ci * smaller size. If the ciphertext name is longer than the value below, then 7362306a36Sopenharmony_ci * sha256 hash the remaining bytes. 7462306a36Sopenharmony_ci * 7562306a36Sopenharmony_ci * For the fscrypt_nokey_name struct the dirhash[2] member is useless in ceph 7662306a36Sopenharmony_ci * so the corresponding struct will be: 7762306a36Sopenharmony_ci * 7862306a36Sopenharmony_ci * struct fscrypt_ceph_nokey_name { 7962306a36Sopenharmony_ci * u8 bytes[157]; 8062306a36Sopenharmony_ci * u8 sha256[SHA256_DIGEST_SIZE]; 8162306a36Sopenharmony_ci * }; // 180 bytes => 240 bytes base64-encoded, which is <= NAME_MAX (255) 8262306a36Sopenharmony_ci * 8362306a36Sopenharmony_ci * (240 bytes is the maximum size allowed for snapshot names to take into 8462306a36Sopenharmony_ci * account the format: '_<SNAPSHOT-NAME>_<INODE-NUMBER>'.) 8562306a36Sopenharmony_ci * 8662306a36Sopenharmony_ci * Note that for long names that end up having their tail portion hashed, we 8762306a36Sopenharmony_ci * must also store the full encrypted name (in the dentry's alternate_name 8862306a36Sopenharmony_ci * field). 8962306a36Sopenharmony_ci */ 9062306a36Sopenharmony_ci#define CEPH_NOHASH_NAME_MAX (180 - SHA256_DIGEST_SIZE) 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#define CEPH_BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3) 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ciint ceph_base64_encode(const u8 *src, int srclen, char *dst); 9562306a36Sopenharmony_ciint ceph_base64_decode(const char *src, int srclen, u8 *dst); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_civoid ceph_fscrypt_set_ops(struct super_block *sb); 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_civoid ceph_fscrypt_free_dummy_policy(struct ceph_fs_client *fsc); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ciint ceph_fscrypt_prepare_context(struct inode *dir, struct inode *inode, 10262306a36Sopenharmony_ci struct ceph_acl_sec_ctx *as); 10362306a36Sopenharmony_civoid ceph_fscrypt_as_ctx_to_req(struct ceph_mds_request *req, 10462306a36Sopenharmony_ci struct ceph_acl_sec_ctx *as); 10562306a36Sopenharmony_ciint ceph_encode_encrypted_dname(struct inode *parent, struct qstr *d_name, 10662306a36Sopenharmony_ci char *buf); 10762306a36Sopenharmony_ciint ceph_encode_encrypted_fname(struct inode *parent, struct dentry *dentry, 10862306a36Sopenharmony_ci char *buf); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic inline int ceph_fname_alloc_buffer(struct inode *parent, 11162306a36Sopenharmony_ci struct fscrypt_str *fname) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci if (!IS_ENCRYPTED(parent)) 11462306a36Sopenharmony_ci return 0; 11562306a36Sopenharmony_ci return fscrypt_fname_alloc_buffer(NAME_MAX, fname); 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cistatic inline void ceph_fname_free_buffer(struct inode *parent, 11962306a36Sopenharmony_ci struct fscrypt_str *fname) 12062306a36Sopenharmony_ci{ 12162306a36Sopenharmony_ci if (IS_ENCRYPTED(parent)) 12262306a36Sopenharmony_ci fscrypt_fname_free_buffer(fname); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ciint ceph_fname_to_usr(const struct ceph_fname *fname, struct fscrypt_str *tname, 12662306a36Sopenharmony_ci struct fscrypt_str *oname, bool *is_nokey); 12762306a36Sopenharmony_ciint ceph_fscrypt_prepare_readdir(struct inode *dir); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic inline unsigned int ceph_fscrypt_blocks(u64 off, u64 len) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci /* crypto blocks cannot span more than one page */ 13262306a36Sopenharmony_ci BUILD_BUG_ON(CEPH_FSCRYPT_BLOCK_SHIFT > PAGE_SHIFT); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci return ((off+len+CEPH_FSCRYPT_BLOCK_SIZE-1) >> CEPH_FSCRYPT_BLOCK_SHIFT) - 13562306a36Sopenharmony_ci (off >> CEPH_FSCRYPT_BLOCK_SHIFT); 13662306a36Sopenharmony_ci} 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci/* 13962306a36Sopenharmony_ci * If we have an encrypted inode then we must adjust the offset and 14062306a36Sopenharmony_ci * range of the on-the-wire read to cover an entire encryption block. 14162306a36Sopenharmony_ci * The copy will be done using the original offset and length, after 14262306a36Sopenharmony_ci * we've decrypted the result. 14362306a36Sopenharmony_ci */ 14462306a36Sopenharmony_cistatic inline void ceph_fscrypt_adjust_off_and_len(struct inode *inode, 14562306a36Sopenharmony_ci u64 *off, u64 *len) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci if (IS_ENCRYPTED(inode)) { 14862306a36Sopenharmony_ci *len = ceph_fscrypt_blocks(*off, *len) * CEPH_FSCRYPT_BLOCK_SIZE; 14962306a36Sopenharmony_ci *off &= CEPH_FSCRYPT_BLOCK_MASK; 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ciint ceph_fscrypt_decrypt_block_inplace(const struct inode *inode, 15462306a36Sopenharmony_ci struct page *page, unsigned int len, 15562306a36Sopenharmony_ci unsigned int offs, u64 lblk_num); 15662306a36Sopenharmony_ciint ceph_fscrypt_encrypt_block_inplace(const struct inode *inode, 15762306a36Sopenharmony_ci struct page *page, unsigned int len, 15862306a36Sopenharmony_ci unsigned int offs, u64 lblk_num, 15962306a36Sopenharmony_ci gfp_t gfp_flags); 16062306a36Sopenharmony_ciint ceph_fscrypt_decrypt_pages(struct inode *inode, struct page **page, 16162306a36Sopenharmony_ci u64 off, int len); 16262306a36Sopenharmony_ciint ceph_fscrypt_decrypt_extents(struct inode *inode, struct page **page, 16362306a36Sopenharmony_ci u64 off, struct ceph_sparse_extent *map, 16462306a36Sopenharmony_ci u32 ext_cnt); 16562306a36Sopenharmony_ciint ceph_fscrypt_encrypt_pages(struct inode *inode, struct page **page, u64 off, 16662306a36Sopenharmony_ci int len, gfp_t gfp); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic inline struct page *ceph_fscrypt_pagecache_page(struct page *page) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci return fscrypt_is_bounce_page(page) ? fscrypt_pagecache_page(page) : page; 17162306a36Sopenharmony_ci} 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci#else /* CONFIG_FS_ENCRYPTION */ 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistatic inline void ceph_fscrypt_set_ops(struct super_block *sb) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistatic inline void ceph_fscrypt_free_dummy_policy(struct ceph_fs_client *fsc) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic inline int ceph_fscrypt_prepare_context(struct inode *dir, 18462306a36Sopenharmony_ci struct inode *inode, 18562306a36Sopenharmony_ci struct ceph_acl_sec_ctx *as) 18662306a36Sopenharmony_ci{ 18762306a36Sopenharmony_ci if (IS_ENCRYPTED(dir)) 18862306a36Sopenharmony_ci return -EOPNOTSUPP; 18962306a36Sopenharmony_ci return 0; 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic inline void ceph_fscrypt_as_ctx_to_req(struct ceph_mds_request *req, 19362306a36Sopenharmony_ci struct ceph_acl_sec_ctx *as_ctx) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci} 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistatic inline int ceph_encode_encrypted_dname(struct inode *parent, 19862306a36Sopenharmony_ci struct qstr *d_name, char *buf) 19962306a36Sopenharmony_ci{ 20062306a36Sopenharmony_ci memcpy(buf, d_name->name, d_name->len); 20162306a36Sopenharmony_ci return d_name->len; 20262306a36Sopenharmony_ci} 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic inline int ceph_encode_encrypted_fname(struct inode *parent, 20562306a36Sopenharmony_ci struct dentry *dentry, char *buf) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci return -EOPNOTSUPP; 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistatic inline int ceph_fname_alloc_buffer(struct inode *parent, 21162306a36Sopenharmony_ci struct fscrypt_str *fname) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci return 0; 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic inline void ceph_fname_free_buffer(struct inode *parent, 21762306a36Sopenharmony_ci struct fscrypt_str *fname) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_cistatic inline int ceph_fname_to_usr(const struct ceph_fname *fname, 22262306a36Sopenharmony_ci struct fscrypt_str *tname, 22362306a36Sopenharmony_ci struct fscrypt_str *oname, bool *is_nokey) 22462306a36Sopenharmony_ci{ 22562306a36Sopenharmony_ci oname->name = fname->name; 22662306a36Sopenharmony_ci oname->len = fname->name_len; 22762306a36Sopenharmony_ci return 0; 22862306a36Sopenharmony_ci} 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_cistatic inline int ceph_fscrypt_prepare_readdir(struct inode *dir) 23162306a36Sopenharmony_ci{ 23262306a36Sopenharmony_ci return 0; 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic inline void ceph_fscrypt_adjust_off_and_len(struct inode *inode, 23662306a36Sopenharmony_ci u64 *off, u64 *len) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_cistatic inline int ceph_fscrypt_decrypt_block_inplace(const struct inode *inode, 24162306a36Sopenharmony_ci struct page *page, unsigned int len, 24262306a36Sopenharmony_ci unsigned int offs, u64 lblk_num) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci return 0; 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic inline int ceph_fscrypt_encrypt_block_inplace(const struct inode *inode, 24862306a36Sopenharmony_ci struct page *page, unsigned int len, 24962306a36Sopenharmony_ci unsigned int offs, u64 lblk_num, 25062306a36Sopenharmony_ci gfp_t gfp_flags) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci return 0; 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic inline int ceph_fscrypt_decrypt_pages(struct inode *inode, 25662306a36Sopenharmony_ci struct page **page, u64 off, 25762306a36Sopenharmony_ci int len) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci return 0; 26062306a36Sopenharmony_ci} 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cistatic inline int ceph_fscrypt_decrypt_extents(struct inode *inode, 26362306a36Sopenharmony_ci struct page **page, u64 off, 26462306a36Sopenharmony_ci struct ceph_sparse_extent *map, 26562306a36Sopenharmony_ci u32 ext_cnt) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci return 0; 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic inline int ceph_fscrypt_encrypt_pages(struct inode *inode, 27162306a36Sopenharmony_ci struct page **page, u64 off, 27262306a36Sopenharmony_ci int len, gfp_t gfp) 27362306a36Sopenharmony_ci{ 27462306a36Sopenharmony_ci return 0; 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_cistatic inline struct page *ceph_fscrypt_pagecache_page(struct page *page) 27862306a36Sopenharmony_ci{ 27962306a36Sopenharmony_ci return page; 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci#endif /* CONFIG_FS_ENCRYPTION */ 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic inline loff_t ceph_fscrypt_page_offset(struct page *page) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci return page_offset(ceph_fscrypt_pagecache_page(page)); 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci#endif /* _CEPH_CRYPTO_H */ 289