162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * eCryptfs: Linux filesystem encryption layer 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 1997-2004 Erez Zadok 662306a36Sopenharmony_ci * Copyright (C) 2001-2004 Stony Brook University 762306a36Sopenharmony_ci * Copyright (C) 2004-2007 International Business Machines Corp. 862306a36Sopenharmony_ci * Author(s): Michael A. Halcrow <mahalcro@us.ibm.com> 962306a36Sopenharmony_ci * Michael C. Thompson <mcthomps@us.ibm.com> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <crypto/hash.h> 1362306a36Sopenharmony_ci#include <crypto/skcipher.h> 1462306a36Sopenharmony_ci#include <linux/fs.h> 1562306a36Sopenharmony_ci#include <linux/mount.h> 1662306a36Sopenharmony_ci#include <linux/pagemap.h> 1762306a36Sopenharmony_ci#include <linux/random.h> 1862306a36Sopenharmony_ci#include <linux/compiler.h> 1962306a36Sopenharmony_ci#include <linux/key.h> 2062306a36Sopenharmony_ci#include <linux/namei.h> 2162306a36Sopenharmony_ci#include <linux/file.h> 2262306a36Sopenharmony_ci#include <linux/scatterlist.h> 2362306a36Sopenharmony_ci#include <linux/slab.h> 2462306a36Sopenharmony_ci#include <asm/unaligned.h> 2562306a36Sopenharmony_ci#include <linux/kernel.h> 2662306a36Sopenharmony_ci#include <linux/xattr.h> 2762306a36Sopenharmony_ci#include "ecryptfs_kernel.h" 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define DECRYPT 0 3062306a36Sopenharmony_ci#define ENCRYPT 1 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/** 3362306a36Sopenharmony_ci * ecryptfs_from_hex 3462306a36Sopenharmony_ci * @dst: Buffer to take the bytes from src hex; must be at least of 3562306a36Sopenharmony_ci * size (src_size / 2) 3662306a36Sopenharmony_ci * @src: Buffer to be converted from a hex string representation to raw value 3762306a36Sopenharmony_ci * @dst_size: size of dst buffer, or number of hex characters pairs to convert 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_civoid ecryptfs_from_hex(char *dst, char *src, int dst_size) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci int x; 4262306a36Sopenharmony_ci char tmp[3] = { 0, }; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci for (x = 0; x < dst_size; x++) { 4562306a36Sopenharmony_ci tmp[0] = src[x * 2]; 4662306a36Sopenharmony_ci tmp[1] = src[x * 2 + 1]; 4762306a36Sopenharmony_ci dst[x] = (unsigned char)simple_strtol(tmp, NULL, 16); 4862306a36Sopenharmony_ci } 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/** 5262306a36Sopenharmony_ci * ecryptfs_calculate_md5 - calculates the md5 of @src 5362306a36Sopenharmony_ci * @dst: Pointer to 16 bytes of allocated memory 5462306a36Sopenharmony_ci * @crypt_stat: Pointer to crypt_stat struct for the current inode 5562306a36Sopenharmony_ci * @src: Data to be md5'd 5662306a36Sopenharmony_ci * @len: Length of @src 5762306a36Sopenharmony_ci * 5862306a36Sopenharmony_ci * Uses the allocated crypto context that crypt_stat references to 5962306a36Sopenharmony_ci * generate the MD5 sum of the contents of src. 6062306a36Sopenharmony_ci */ 6162306a36Sopenharmony_cistatic int ecryptfs_calculate_md5(char *dst, 6262306a36Sopenharmony_ci struct ecryptfs_crypt_stat *crypt_stat, 6362306a36Sopenharmony_ci char *src, int len) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci int rc = crypto_shash_tfm_digest(crypt_stat->hash_tfm, src, len, dst); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci if (rc) { 6862306a36Sopenharmony_ci printk(KERN_ERR 6962306a36Sopenharmony_ci "%s: Error computing crypto hash; rc = [%d]\n", 7062306a36Sopenharmony_ci __func__, rc); 7162306a36Sopenharmony_ci goto out; 7262306a36Sopenharmony_ci } 7362306a36Sopenharmony_ciout: 7462306a36Sopenharmony_ci return rc; 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, 7862306a36Sopenharmony_ci char *cipher_name, 7962306a36Sopenharmony_ci char *chaining_modifier) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci int cipher_name_len = strlen(cipher_name); 8262306a36Sopenharmony_ci int chaining_modifier_len = strlen(chaining_modifier); 8362306a36Sopenharmony_ci int algified_name_len; 8462306a36Sopenharmony_ci int rc; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci algified_name_len = (chaining_modifier_len + cipher_name_len + 3); 8762306a36Sopenharmony_ci (*algified_name) = kmalloc(algified_name_len, GFP_KERNEL); 8862306a36Sopenharmony_ci if (!(*algified_name)) { 8962306a36Sopenharmony_ci rc = -ENOMEM; 9062306a36Sopenharmony_ci goto out; 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci snprintf((*algified_name), algified_name_len, "%s(%s)", 9362306a36Sopenharmony_ci chaining_modifier, cipher_name); 9462306a36Sopenharmony_ci rc = 0; 9562306a36Sopenharmony_ciout: 9662306a36Sopenharmony_ci return rc; 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci/** 10062306a36Sopenharmony_ci * ecryptfs_derive_iv 10162306a36Sopenharmony_ci * @iv: destination for the derived iv vale 10262306a36Sopenharmony_ci * @crypt_stat: Pointer to crypt_stat struct for the current inode 10362306a36Sopenharmony_ci * @offset: Offset of the extent whose IV we are to derive 10462306a36Sopenharmony_ci * 10562306a36Sopenharmony_ci * Generate the initialization vector from the given root IV and page 10662306a36Sopenharmony_ci * offset. 10762306a36Sopenharmony_ci * 10862306a36Sopenharmony_ci * Returns zero on success; non-zero on error. 10962306a36Sopenharmony_ci */ 11062306a36Sopenharmony_ciint ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat, 11162306a36Sopenharmony_ci loff_t offset) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci int rc = 0; 11462306a36Sopenharmony_ci char dst[MD5_DIGEST_SIZE]; 11562306a36Sopenharmony_ci char src[ECRYPTFS_MAX_IV_BYTES + 16]; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci if (unlikely(ecryptfs_verbosity > 0)) { 11862306a36Sopenharmony_ci ecryptfs_printk(KERN_DEBUG, "root iv:\n"); 11962306a36Sopenharmony_ci ecryptfs_dump_hex(crypt_stat->root_iv, crypt_stat->iv_bytes); 12062306a36Sopenharmony_ci } 12162306a36Sopenharmony_ci /* TODO: It is probably secure to just cast the least 12262306a36Sopenharmony_ci * significant bits of the root IV into an unsigned long and 12362306a36Sopenharmony_ci * add the offset to that rather than go through all this 12462306a36Sopenharmony_ci * hashing business. -Halcrow */ 12562306a36Sopenharmony_ci memcpy(src, crypt_stat->root_iv, crypt_stat->iv_bytes); 12662306a36Sopenharmony_ci memset((src + crypt_stat->iv_bytes), 0, 16); 12762306a36Sopenharmony_ci snprintf((src + crypt_stat->iv_bytes), 16, "%lld", offset); 12862306a36Sopenharmony_ci if (unlikely(ecryptfs_verbosity > 0)) { 12962306a36Sopenharmony_ci ecryptfs_printk(KERN_DEBUG, "source:\n"); 13062306a36Sopenharmony_ci ecryptfs_dump_hex(src, (crypt_stat->iv_bytes + 16)); 13162306a36Sopenharmony_ci } 13262306a36Sopenharmony_ci rc = ecryptfs_calculate_md5(dst, crypt_stat, src, 13362306a36Sopenharmony_ci (crypt_stat->iv_bytes + 16)); 13462306a36Sopenharmony_ci if (rc) { 13562306a36Sopenharmony_ci ecryptfs_printk(KERN_WARNING, "Error attempting to compute " 13662306a36Sopenharmony_ci "MD5 while generating IV for a page\n"); 13762306a36Sopenharmony_ci goto out; 13862306a36Sopenharmony_ci } 13962306a36Sopenharmony_ci memcpy(iv, dst, crypt_stat->iv_bytes); 14062306a36Sopenharmony_ci if (unlikely(ecryptfs_verbosity > 0)) { 14162306a36Sopenharmony_ci ecryptfs_printk(KERN_DEBUG, "derived iv:\n"); 14262306a36Sopenharmony_ci ecryptfs_dump_hex(iv, crypt_stat->iv_bytes); 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ciout: 14562306a36Sopenharmony_ci return rc; 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci/** 14962306a36Sopenharmony_ci * ecryptfs_init_crypt_stat 15062306a36Sopenharmony_ci * @crypt_stat: Pointer to the crypt_stat struct to initialize. 15162306a36Sopenharmony_ci * 15262306a36Sopenharmony_ci * Initialize the crypt_stat structure. 15362306a36Sopenharmony_ci */ 15462306a36Sopenharmony_ciint ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci struct crypto_shash *tfm; 15762306a36Sopenharmony_ci int rc; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci tfm = crypto_alloc_shash(ECRYPTFS_DEFAULT_HASH, 0, 0); 16062306a36Sopenharmony_ci if (IS_ERR(tfm)) { 16162306a36Sopenharmony_ci rc = PTR_ERR(tfm); 16262306a36Sopenharmony_ci ecryptfs_printk(KERN_ERR, "Error attempting to " 16362306a36Sopenharmony_ci "allocate crypto context; rc = [%d]\n", 16462306a36Sopenharmony_ci rc); 16562306a36Sopenharmony_ci return rc; 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci memset((void *)crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); 16962306a36Sopenharmony_ci INIT_LIST_HEAD(&crypt_stat->keysig_list); 17062306a36Sopenharmony_ci mutex_init(&crypt_stat->keysig_list_mutex); 17162306a36Sopenharmony_ci mutex_init(&crypt_stat->cs_mutex); 17262306a36Sopenharmony_ci mutex_init(&crypt_stat->cs_tfm_mutex); 17362306a36Sopenharmony_ci crypt_stat->hash_tfm = tfm; 17462306a36Sopenharmony_ci crypt_stat->flags |= ECRYPTFS_STRUCT_INITIALIZED; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci return 0; 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci/** 18062306a36Sopenharmony_ci * ecryptfs_destroy_crypt_stat 18162306a36Sopenharmony_ci * @crypt_stat: Pointer to the crypt_stat struct to initialize. 18262306a36Sopenharmony_ci * 18362306a36Sopenharmony_ci * Releases all memory associated with a crypt_stat struct. 18462306a36Sopenharmony_ci */ 18562306a36Sopenharmony_civoid ecryptfs_destroy_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) 18662306a36Sopenharmony_ci{ 18762306a36Sopenharmony_ci struct ecryptfs_key_sig *key_sig, *key_sig_tmp; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci crypto_free_skcipher(crypt_stat->tfm); 19062306a36Sopenharmony_ci crypto_free_shash(crypt_stat->hash_tfm); 19162306a36Sopenharmony_ci list_for_each_entry_safe(key_sig, key_sig_tmp, 19262306a36Sopenharmony_ci &crypt_stat->keysig_list, crypt_stat_list) { 19362306a36Sopenharmony_ci list_del(&key_sig->crypt_stat_list); 19462306a36Sopenharmony_ci kmem_cache_free(ecryptfs_key_sig_cache, key_sig); 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci memset(crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); 19762306a36Sopenharmony_ci} 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_civoid ecryptfs_destroy_mount_crypt_stat( 20062306a36Sopenharmony_ci struct ecryptfs_mount_crypt_stat *mount_crypt_stat) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci struct ecryptfs_global_auth_tok *auth_tok, *auth_tok_tmp; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci if (!(mount_crypt_stat->flags & ECRYPTFS_MOUNT_CRYPT_STAT_INITIALIZED)) 20562306a36Sopenharmony_ci return; 20662306a36Sopenharmony_ci mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); 20762306a36Sopenharmony_ci list_for_each_entry_safe(auth_tok, auth_tok_tmp, 20862306a36Sopenharmony_ci &mount_crypt_stat->global_auth_tok_list, 20962306a36Sopenharmony_ci mount_crypt_stat_list) { 21062306a36Sopenharmony_ci list_del(&auth_tok->mount_crypt_stat_list); 21162306a36Sopenharmony_ci if (!(auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID)) 21262306a36Sopenharmony_ci key_put(auth_tok->global_auth_tok_key); 21362306a36Sopenharmony_ci kmem_cache_free(ecryptfs_global_auth_tok_cache, auth_tok); 21462306a36Sopenharmony_ci } 21562306a36Sopenharmony_ci mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); 21662306a36Sopenharmony_ci memset(mount_crypt_stat, 0, sizeof(struct ecryptfs_mount_crypt_stat)); 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci/** 22062306a36Sopenharmony_ci * virt_to_scatterlist 22162306a36Sopenharmony_ci * @addr: Virtual address 22262306a36Sopenharmony_ci * @size: Size of data; should be an even multiple of the block size 22362306a36Sopenharmony_ci * @sg: Pointer to scatterlist array; set to NULL to obtain only 22462306a36Sopenharmony_ci * the number of scatterlist structs required in array 22562306a36Sopenharmony_ci * @sg_size: Max array size 22662306a36Sopenharmony_ci * 22762306a36Sopenharmony_ci * Fills in a scatterlist array with page references for a passed 22862306a36Sopenharmony_ci * virtual address. 22962306a36Sopenharmony_ci * 23062306a36Sopenharmony_ci * Returns the number of scatterlist structs in array used 23162306a36Sopenharmony_ci */ 23262306a36Sopenharmony_ciint virt_to_scatterlist(const void *addr, int size, struct scatterlist *sg, 23362306a36Sopenharmony_ci int sg_size) 23462306a36Sopenharmony_ci{ 23562306a36Sopenharmony_ci int i = 0; 23662306a36Sopenharmony_ci struct page *pg; 23762306a36Sopenharmony_ci int offset; 23862306a36Sopenharmony_ci int remainder_of_page; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci sg_init_table(sg, sg_size); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci while (size > 0 && i < sg_size) { 24362306a36Sopenharmony_ci pg = virt_to_page(addr); 24462306a36Sopenharmony_ci offset = offset_in_page(addr); 24562306a36Sopenharmony_ci sg_set_page(&sg[i], pg, 0, offset); 24662306a36Sopenharmony_ci remainder_of_page = PAGE_SIZE - offset; 24762306a36Sopenharmony_ci if (size >= remainder_of_page) { 24862306a36Sopenharmony_ci sg[i].length = remainder_of_page; 24962306a36Sopenharmony_ci addr += remainder_of_page; 25062306a36Sopenharmony_ci size -= remainder_of_page; 25162306a36Sopenharmony_ci } else { 25262306a36Sopenharmony_ci sg[i].length = size; 25362306a36Sopenharmony_ci addr += size; 25462306a36Sopenharmony_ci size = 0; 25562306a36Sopenharmony_ci } 25662306a36Sopenharmony_ci i++; 25762306a36Sopenharmony_ci } 25862306a36Sopenharmony_ci if (size > 0) 25962306a36Sopenharmony_ci return -ENOMEM; 26062306a36Sopenharmony_ci return i; 26162306a36Sopenharmony_ci} 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci/** 26462306a36Sopenharmony_ci * crypt_scatterlist 26562306a36Sopenharmony_ci * @crypt_stat: Pointer to the crypt_stat struct to initialize. 26662306a36Sopenharmony_ci * @dst_sg: Destination of the data after performing the crypto operation 26762306a36Sopenharmony_ci * @src_sg: Data to be encrypted or decrypted 26862306a36Sopenharmony_ci * @size: Length of data 26962306a36Sopenharmony_ci * @iv: IV to use 27062306a36Sopenharmony_ci * @op: ENCRYPT or DECRYPT to indicate the desired operation 27162306a36Sopenharmony_ci * 27262306a36Sopenharmony_ci * Returns the number of bytes encrypted or decrypted; negative value on error 27362306a36Sopenharmony_ci */ 27462306a36Sopenharmony_cistatic int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, 27562306a36Sopenharmony_ci struct scatterlist *dst_sg, 27662306a36Sopenharmony_ci struct scatterlist *src_sg, int size, 27762306a36Sopenharmony_ci unsigned char *iv, int op) 27862306a36Sopenharmony_ci{ 27962306a36Sopenharmony_ci struct skcipher_request *req = NULL; 28062306a36Sopenharmony_ci DECLARE_CRYPTO_WAIT(ecr); 28162306a36Sopenharmony_ci int rc = 0; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci if (unlikely(ecryptfs_verbosity > 0)) { 28462306a36Sopenharmony_ci ecryptfs_printk(KERN_DEBUG, "Key size [%zd]; key:\n", 28562306a36Sopenharmony_ci crypt_stat->key_size); 28662306a36Sopenharmony_ci ecryptfs_dump_hex(crypt_stat->key, 28762306a36Sopenharmony_ci crypt_stat->key_size); 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci mutex_lock(&crypt_stat->cs_tfm_mutex); 29162306a36Sopenharmony_ci req = skcipher_request_alloc(crypt_stat->tfm, GFP_NOFS); 29262306a36Sopenharmony_ci if (!req) { 29362306a36Sopenharmony_ci mutex_unlock(&crypt_stat->cs_tfm_mutex); 29462306a36Sopenharmony_ci rc = -ENOMEM; 29562306a36Sopenharmony_ci goto out; 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci skcipher_request_set_callback(req, 29962306a36Sopenharmony_ci CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, 30062306a36Sopenharmony_ci crypto_req_done, &ecr); 30162306a36Sopenharmony_ci /* Consider doing this once, when the file is opened */ 30262306a36Sopenharmony_ci if (!(crypt_stat->flags & ECRYPTFS_KEY_SET)) { 30362306a36Sopenharmony_ci rc = crypto_skcipher_setkey(crypt_stat->tfm, crypt_stat->key, 30462306a36Sopenharmony_ci crypt_stat->key_size); 30562306a36Sopenharmony_ci if (rc) { 30662306a36Sopenharmony_ci ecryptfs_printk(KERN_ERR, 30762306a36Sopenharmony_ci "Error setting key; rc = [%d]\n", 30862306a36Sopenharmony_ci rc); 30962306a36Sopenharmony_ci mutex_unlock(&crypt_stat->cs_tfm_mutex); 31062306a36Sopenharmony_ci rc = -EINVAL; 31162306a36Sopenharmony_ci goto out; 31262306a36Sopenharmony_ci } 31362306a36Sopenharmony_ci crypt_stat->flags |= ECRYPTFS_KEY_SET; 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci mutex_unlock(&crypt_stat->cs_tfm_mutex); 31662306a36Sopenharmony_ci skcipher_request_set_crypt(req, src_sg, dst_sg, size, iv); 31762306a36Sopenharmony_ci rc = op == ENCRYPT ? crypto_skcipher_encrypt(req) : 31862306a36Sopenharmony_ci crypto_skcipher_decrypt(req); 31962306a36Sopenharmony_ci rc = crypto_wait_req(rc, &ecr); 32062306a36Sopenharmony_ciout: 32162306a36Sopenharmony_ci skcipher_request_free(req); 32262306a36Sopenharmony_ci return rc; 32362306a36Sopenharmony_ci} 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci/* 32662306a36Sopenharmony_ci * lower_offset_for_page 32762306a36Sopenharmony_ci * 32862306a36Sopenharmony_ci * Convert an eCryptfs page index into a lower byte offset 32962306a36Sopenharmony_ci */ 33062306a36Sopenharmony_cistatic loff_t lower_offset_for_page(struct ecryptfs_crypt_stat *crypt_stat, 33162306a36Sopenharmony_ci struct page *page) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci return ecryptfs_lower_header_size(crypt_stat) + 33462306a36Sopenharmony_ci ((loff_t)page->index << PAGE_SHIFT); 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci/** 33862306a36Sopenharmony_ci * crypt_extent 33962306a36Sopenharmony_ci * @crypt_stat: crypt_stat containing cryptographic context for the 34062306a36Sopenharmony_ci * encryption operation 34162306a36Sopenharmony_ci * @dst_page: The page to write the result into 34262306a36Sopenharmony_ci * @src_page: The page to read from 34362306a36Sopenharmony_ci * @extent_offset: Page extent offset for use in generating IV 34462306a36Sopenharmony_ci * @op: ENCRYPT or DECRYPT to indicate the desired operation 34562306a36Sopenharmony_ci * 34662306a36Sopenharmony_ci * Encrypts or decrypts one extent of data. 34762306a36Sopenharmony_ci * 34862306a36Sopenharmony_ci * Return zero on success; non-zero otherwise 34962306a36Sopenharmony_ci */ 35062306a36Sopenharmony_cistatic int crypt_extent(struct ecryptfs_crypt_stat *crypt_stat, 35162306a36Sopenharmony_ci struct page *dst_page, 35262306a36Sopenharmony_ci struct page *src_page, 35362306a36Sopenharmony_ci unsigned long extent_offset, int op) 35462306a36Sopenharmony_ci{ 35562306a36Sopenharmony_ci pgoff_t page_index = op == ENCRYPT ? src_page->index : dst_page->index; 35662306a36Sopenharmony_ci loff_t extent_base; 35762306a36Sopenharmony_ci char extent_iv[ECRYPTFS_MAX_IV_BYTES]; 35862306a36Sopenharmony_ci struct scatterlist src_sg, dst_sg; 35962306a36Sopenharmony_ci size_t extent_size = crypt_stat->extent_size; 36062306a36Sopenharmony_ci int rc; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci extent_base = (((loff_t)page_index) * (PAGE_SIZE / extent_size)); 36362306a36Sopenharmony_ci rc = ecryptfs_derive_iv(extent_iv, crypt_stat, 36462306a36Sopenharmony_ci (extent_base + extent_offset)); 36562306a36Sopenharmony_ci if (rc) { 36662306a36Sopenharmony_ci ecryptfs_printk(KERN_ERR, "Error attempting to derive IV for " 36762306a36Sopenharmony_ci "extent [0x%.16llx]; rc = [%d]\n", 36862306a36Sopenharmony_ci (unsigned long long)(extent_base + extent_offset), rc); 36962306a36Sopenharmony_ci goto out; 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci sg_init_table(&src_sg, 1); 37362306a36Sopenharmony_ci sg_init_table(&dst_sg, 1); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci sg_set_page(&src_sg, src_page, extent_size, 37662306a36Sopenharmony_ci extent_offset * extent_size); 37762306a36Sopenharmony_ci sg_set_page(&dst_sg, dst_page, extent_size, 37862306a36Sopenharmony_ci extent_offset * extent_size); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci rc = crypt_scatterlist(crypt_stat, &dst_sg, &src_sg, extent_size, 38162306a36Sopenharmony_ci extent_iv, op); 38262306a36Sopenharmony_ci if (rc < 0) { 38362306a36Sopenharmony_ci printk(KERN_ERR "%s: Error attempting to crypt page with " 38462306a36Sopenharmony_ci "page_index = [%ld], extent_offset = [%ld]; " 38562306a36Sopenharmony_ci "rc = [%d]\n", __func__, page_index, extent_offset, rc); 38662306a36Sopenharmony_ci goto out; 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci rc = 0; 38962306a36Sopenharmony_ciout: 39062306a36Sopenharmony_ci return rc; 39162306a36Sopenharmony_ci} 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci/** 39462306a36Sopenharmony_ci * ecryptfs_encrypt_page 39562306a36Sopenharmony_ci * @page: Page mapped from the eCryptfs inode for the file; contains 39662306a36Sopenharmony_ci * decrypted content that needs to be encrypted (to a temporary 39762306a36Sopenharmony_ci * page; not in place) and written out to the lower file 39862306a36Sopenharmony_ci * 39962306a36Sopenharmony_ci * Encrypt an eCryptfs page. This is done on a per-extent basis. Note 40062306a36Sopenharmony_ci * that eCryptfs pages may straddle the lower pages -- for instance, 40162306a36Sopenharmony_ci * if the file was created on a machine with an 8K page size 40262306a36Sopenharmony_ci * (resulting in an 8K header), and then the file is copied onto a 40362306a36Sopenharmony_ci * host with a 32K page size, then when reading page 0 of the eCryptfs 40462306a36Sopenharmony_ci * file, 24K of page 0 of the lower file will be read and decrypted, 40562306a36Sopenharmony_ci * and then 8K of page 1 of the lower file will be read and decrypted. 40662306a36Sopenharmony_ci * 40762306a36Sopenharmony_ci * Returns zero on success; negative on error 40862306a36Sopenharmony_ci */ 40962306a36Sopenharmony_ciint ecryptfs_encrypt_page(struct page *page) 41062306a36Sopenharmony_ci{ 41162306a36Sopenharmony_ci struct inode *ecryptfs_inode; 41262306a36Sopenharmony_ci struct ecryptfs_crypt_stat *crypt_stat; 41362306a36Sopenharmony_ci char *enc_extent_virt; 41462306a36Sopenharmony_ci struct page *enc_extent_page = NULL; 41562306a36Sopenharmony_ci loff_t extent_offset; 41662306a36Sopenharmony_ci loff_t lower_offset; 41762306a36Sopenharmony_ci int rc = 0; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci ecryptfs_inode = page->mapping->host; 42062306a36Sopenharmony_ci crypt_stat = 42162306a36Sopenharmony_ci &(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat); 42262306a36Sopenharmony_ci BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)); 42362306a36Sopenharmony_ci enc_extent_page = alloc_page(GFP_USER); 42462306a36Sopenharmony_ci if (!enc_extent_page) { 42562306a36Sopenharmony_ci rc = -ENOMEM; 42662306a36Sopenharmony_ci ecryptfs_printk(KERN_ERR, "Error allocating memory for " 42762306a36Sopenharmony_ci "encrypted extent\n"); 42862306a36Sopenharmony_ci goto out; 42962306a36Sopenharmony_ci } 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci for (extent_offset = 0; 43262306a36Sopenharmony_ci extent_offset < (PAGE_SIZE / crypt_stat->extent_size); 43362306a36Sopenharmony_ci extent_offset++) { 43462306a36Sopenharmony_ci rc = crypt_extent(crypt_stat, enc_extent_page, page, 43562306a36Sopenharmony_ci extent_offset, ENCRYPT); 43662306a36Sopenharmony_ci if (rc) { 43762306a36Sopenharmony_ci printk(KERN_ERR "%s: Error encrypting extent; " 43862306a36Sopenharmony_ci "rc = [%d]\n", __func__, rc); 43962306a36Sopenharmony_ci goto out; 44062306a36Sopenharmony_ci } 44162306a36Sopenharmony_ci } 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci lower_offset = lower_offset_for_page(crypt_stat, page); 44462306a36Sopenharmony_ci enc_extent_virt = kmap_local_page(enc_extent_page); 44562306a36Sopenharmony_ci rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt, lower_offset, 44662306a36Sopenharmony_ci PAGE_SIZE); 44762306a36Sopenharmony_ci kunmap_local(enc_extent_virt); 44862306a36Sopenharmony_ci if (rc < 0) { 44962306a36Sopenharmony_ci ecryptfs_printk(KERN_ERR, 45062306a36Sopenharmony_ci "Error attempting to write lower page; rc = [%d]\n", 45162306a36Sopenharmony_ci rc); 45262306a36Sopenharmony_ci goto out; 45362306a36Sopenharmony_ci } 45462306a36Sopenharmony_ci rc = 0; 45562306a36Sopenharmony_ciout: 45662306a36Sopenharmony_ci if (enc_extent_page) { 45762306a36Sopenharmony_ci __free_page(enc_extent_page); 45862306a36Sopenharmony_ci } 45962306a36Sopenharmony_ci return rc; 46062306a36Sopenharmony_ci} 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci/** 46362306a36Sopenharmony_ci * ecryptfs_decrypt_page 46462306a36Sopenharmony_ci * @page: Page mapped from the eCryptfs inode for the file; data read 46562306a36Sopenharmony_ci * and decrypted from the lower file will be written into this 46662306a36Sopenharmony_ci * page 46762306a36Sopenharmony_ci * 46862306a36Sopenharmony_ci * Decrypt an eCryptfs page. This is done on a per-extent basis. Note 46962306a36Sopenharmony_ci * that eCryptfs pages may straddle the lower pages -- for instance, 47062306a36Sopenharmony_ci * if the file was created on a machine with an 8K page size 47162306a36Sopenharmony_ci * (resulting in an 8K header), and then the file is copied onto a 47262306a36Sopenharmony_ci * host with a 32K page size, then when reading page 0 of the eCryptfs 47362306a36Sopenharmony_ci * file, 24K of page 0 of the lower file will be read and decrypted, 47462306a36Sopenharmony_ci * and then 8K of page 1 of the lower file will be read and decrypted. 47562306a36Sopenharmony_ci * 47662306a36Sopenharmony_ci * Returns zero on success; negative on error 47762306a36Sopenharmony_ci */ 47862306a36Sopenharmony_ciint ecryptfs_decrypt_page(struct page *page) 47962306a36Sopenharmony_ci{ 48062306a36Sopenharmony_ci struct inode *ecryptfs_inode; 48162306a36Sopenharmony_ci struct ecryptfs_crypt_stat *crypt_stat; 48262306a36Sopenharmony_ci char *page_virt; 48362306a36Sopenharmony_ci unsigned long extent_offset; 48462306a36Sopenharmony_ci loff_t lower_offset; 48562306a36Sopenharmony_ci int rc = 0; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci ecryptfs_inode = page->mapping->host; 48862306a36Sopenharmony_ci crypt_stat = 48962306a36Sopenharmony_ci &(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat); 49062306a36Sopenharmony_ci BUG_ON(!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)); 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci lower_offset = lower_offset_for_page(crypt_stat, page); 49362306a36Sopenharmony_ci page_virt = kmap_local_page(page); 49462306a36Sopenharmony_ci rc = ecryptfs_read_lower(page_virt, lower_offset, PAGE_SIZE, 49562306a36Sopenharmony_ci ecryptfs_inode); 49662306a36Sopenharmony_ci kunmap_local(page_virt); 49762306a36Sopenharmony_ci if (rc < 0) { 49862306a36Sopenharmony_ci ecryptfs_printk(KERN_ERR, 49962306a36Sopenharmony_ci "Error attempting to read lower page; rc = [%d]\n", 50062306a36Sopenharmony_ci rc); 50162306a36Sopenharmony_ci goto out; 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci for (extent_offset = 0; 50562306a36Sopenharmony_ci extent_offset < (PAGE_SIZE / crypt_stat->extent_size); 50662306a36Sopenharmony_ci extent_offset++) { 50762306a36Sopenharmony_ci rc = crypt_extent(crypt_stat, page, page, 50862306a36Sopenharmony_ci extent_offset, DECRYPT); 50962306a36Sopenharmony_ci if (rc) { 51062306a36Sopenharmony_ci printk(KERN_ERR "%s: Error decrypting extent; " 51162306a36Sopenharmony_ci "rc = [%d]\n", __func__, rc); 51262306a36Sopenharmony_ci goto out; 51362306a36Sopenharmony_ci } 51462306a36Sopenharmony_ci } 51562306a36Sopenharmony_ciout: 51662306a36Sopenharmony_ci return rc; 51762306a36Sopenharmony_ci} 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci#define ECRYPTFS_MAX_SCATTERLIST_LEN 4 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci/** 52262306a36Sopenharmony_ci * ecryptfs_init_crypt_ctx 52362306a36Sopenharmony_ci * @crypt_stat: Uninitialized crypt stats structure 52462306a36Sopenharmony_ci * 52562306a36Sopenharmony_ci * Initialize the crypto context. 52662306a36Sopenharmony_ci * 52762306a36Sopenharmony_ci * TODO: Performance: Keep a cache of initialized cipher contexts; 52862306a36Sopenharmony_ci * only init if needed 52962306a36Sopenharmony_ci */ 53062306a36Sopenharmony_ciint ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) 53162306a36Sopenharmony_ci{ 53262306a36Sopenharmony_ci char *full_alg_name; 53362306a36Sopenharmony_ci int rc = -EINVAL; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci ecryptfs_printk(KERN_DEBUG, 53662306a36Sopenharmony_ci "Initializing cipher [%s]; strlen = [%d]; " 53762306a36Sopenharmony_ci "key_size_bits = [%zd]\n", 53862306a36Sopenharmony_ci crypt_stat->cipher, (int)strlen(crypt_stat->cipher), 53962306a36Sopenharmony_ci crypt_stat->key_size << 3); 54062306a36Sopenharmony_ci mutex_lock(&crypt_stat->cs_tfm_mutex); 54162306a36Sopenharmony_ci if (crypt_stat->tfm) { 54262306a36Sopenharmony_ci rc = 0; 54362306a36Sopenharmony_ci goto out_unlock; 54462306a36Sopenharmony_ci } 54562306a36Sopenharmony_ci rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, 54662306a36Sopenharmony_ci crypt_stat->cipher, "cbc"); 54762306a36Sopenharmony_ci if (rc) 54862306a36Sopenharmony_ci goto out_unlock; 54962306a36Sopenharmony_ci crypt_stat->tfm = crypto_alloc_skcipher(full_alg_name, 0, 0); 55062306a36Sopenharmony_ci if (IS_ERR(crypt_stat->tfm)) { 55162306a36Sopenharmony_ci rc = PTR_ERR(crypt_stat->tfm); 55262306a36Sopenharmony_ci crypt_stat->tfm = NULL; 55362306a36Sopenharmony_ci ecryptfs_printk(KERN_ERR, "cryptfs: init_crypt_ctx(): " 55462306a36Sopenharmony_ci "Error initializing cipher [%s]\n", 55562306a36Sopenharmony_ci full_alg_name); 55662306a36Sopenharmony_ci goto out_free; 55762306a36Sopenharmony_ci } 55862306a36Sopenharmony_ci crypto_skcipher_set_flags(crypt_stat->tfm, 55962306a36Sopenharmony_ci CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); 56062306a36Sopenharmony_ci rc = 0; 56162306a36Sopenharmony_ciout_free: 56262306a36Sopenharmony_ci kfree(full_alg_name); 56362306a36Sopenharmony_ciout_unlock: 56462306a36Sopenharmony_ci mutex_unlock(&crypt_stat->cs_tfm_mutex); 56562306a36Sopenharmony_ci return rc; 56662306a36Sopenharmony_ci} 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_cistatic void set_extent_mask_and_shift(struct ecryptfs_crypt_stat *crypt_stat) 56962306a36Sopenharmony_ci{ 57062306a36Sopenharmony_ci int extent_size_tmp; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci crypt_stat->extent_mask = 0xFFFFFFFF; 57362306a36Sopenharmony_ci crypt_stat->extent_shift = 0; 57462306a36Sopenharmony_ci if (crypt_stat->extent_size == 0) 57562306a36Sopenharmony_ci return; 57662306a36Sopenharmony_ci extent_size_tmp = crypt_stat->extent_size; 57762306a36Sopenharmony_ci while ((extent_size_tmp & 0x01) == 0) { 57862306a36Sopenharmony_ci extent_size_tmp >>= 1; 57962306a36Sopenharmony_ci crypt_stat->extent_mask <<= 1; 58062306a36Sopenharmony_ci crypt_stat->extent_shift++; 58162306a36Sopenharmony_ci } 58262306a36Sopenharmony_ci} 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_civoid ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat) 58562306a36Sopenharmony_ci{ 58662306a36Sopenharmony_ci /* Default values; may be overwritten as we are parsing the 58762306a36Sopenharmony_ci * packets. */ 58862306a36Sopenharmony_ci crypt_stat->extent_size = ECRYPTFS_DEFAULT_EXTENT_SIZE; 58962306a36Sopenharmony_ci set_extent_mask_and_shift(crypt_stat); 59062306a36Sopenharmony_ci crypt_stat->iv_bytes = ECRYPTFS_DEFAULT_IV_BYTES; 59162306a36Sopenharmony_ci if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) 59262306a36Sopenharmony_ci crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; 59362306a36Sopenharmony_ci else { 59462306a36Sopenharmony_ci if (PAGE_SIZE <= ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE) 59562306a36Sopenharmony_ci crypt_stat->metadata_size = 59662306a36Sopenharmony_ci ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; 59762306a36Sopenharmony_ci else 59862306a36Sopenharmony_ci crypt_stat->metadata_size = PAGE_SIZE; 59962306a36Sopenharmony_ci } 60062306a36Sopenharmony_ci} 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci/* 60362306a36Sopenharmony_ci * ecryptfs_compute_root_iv 60462306a36Sopenharmony_ci * 60562306a36Sopenharmony_ci * On error, sets the root IV to all 0's. 60662306a36Sopenharmony_ci */ 60762306a36Sopenharmony_ciint ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat) 60862306a36Sopenharmony_ci{ 60962306a36Sopenharmony_ci int rc = 0; 61062306a36Sopenharmony_ci char dst[MD5_DIGEST_SIZE]; 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci BUG_ON(crypt_stat->iv_bytes > MD5_DIGEST_SIZE); 61362306a36Sopenharmony_ci BUG_ON(crypt_stat->iv_bytes <= 0); 61462306a36Sopenharmony_ci if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { 61562306a36Sopenharmony_ci rc = -EINVAL; 61662306a36Sopenharmony_ci ecryptfs_printk(KERN_WARNING, "Session key not valid; " 61762306a36Sopenharmony_ci "cannot generate root IV\n"); 61862306a36Sopenharmony_ci goto out; 61962306a36Sopenharmony_ci } 62062306a36Sopenharmony_ci rc = ecryptfs_calculate_md5(dst, crypt_stat, crypt_stat->key, 62162306a36Sopenharmony_ci crypt_stat->key_size); 62262306a36Sopenharmony_ci if (rc) { 62362306a36Sopenharmony_ci ecryptfs_printk(KERN_WARNING, "Error attempting to compute " 62462306a36Sopenharmony_ci "MD5 while generating root IV\n"); 62562306a36Sopenharmony_ci goto out; 62662306a36Sopenharmony_ci } 62762306a36Sopenharmony_ci memcpy(crypt_stat->root_iv, dst, crypt_stat->iv_bytes); 62862306a36Sopenharmony_ciout: 62962306a36Sopenharmony_ci if (rc) { 63062306a36Sopenharmony_ci memset(crypt_stat->root_iv, 0, crypt_stat->iv_bytes); 63162306a36Sopenharmony_ci crypt_stat->flags |= ECRYPTFS_SECURITY_WARNING; 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci return rc; 63462306a36Sopenharmony_ci} 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_cistatic void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat) 63762306a36Sopenharmony_ci{ 63862306a36Sopenharmony_ci get_random_bytes(crypt_stat->key, crypt_stat->key_size); 63962306a36Sopenharmony_ci crypt_stat->flags |= ECRYPTFS_KEY_VALID; 64062306a36Sopenharmony_ci ecryptfs_compute_root_iv(crypt_stat); 64162306a36Sopenharmony_ci if (unlikely(ecryptfs_verbosity > 0)) { 64262306a36Sopenharmony_ci ecryptfs_printk(KERN_DEBUG, "Generated new session key:\n"); 64362306a36Sopenharmony_ci ecryptfs_dump_hex(crypt_stat->key, 64462306a36Sopenharmony_ci crypt_stat->key_size); 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci} 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci/** 64962306a36Sopenharmony_ci * ecryptfs_copy_mount_wide_flags_to_inode_flags 65062306a36Sopenharmony_ci * @crypt_stat: The inode's cryptographic context 65162306a36Sopenharmony_ci * @mount_crypt_stat: The mount point's cryptographic context 65262306a36Sopenharmony_ci * 65362306a36Sopenharmony_ci * This function propagates the mount-wide flags to individual inode 65462306a36Sopenharmony_ci * flags. 65562306a36Sopenharmony_ci */ 65662306a36Sopenharmony_cistatic void ecryptfs_copy_mount_wide_flags_to_inode_flags( 65762306a36Sopenharmony_ci struct ecryptfs_crypt_stat *crypt_stat, 65862306a36Sopenharmony_ci struct ecryptfs_mount_crypt_stat *mount_crypt_stat) 65962306a36Sopenharmony_ci{ 66062306a36Sopenharmony_ci if (mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED) 66162306a36Sopenharmony_ci crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; 66262306a36Sopenharmony_ci if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) 66362306a36Sopenharmony_ci crypt_stat->flags |= ECRYPTFS_VIEW_AS_ENCRYPTED; 66462306a36Sopenharmony_ci if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) { 66562306a36Sopenharmony_ci crypt_stat->flags |= ECRYPTFS_ENCRYPT_FILENAMES; 66662306a36Sopenharmony_ci if (mount_crypt_stat->flags 66762306a36Sopenharmony_ci & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK) 66862306a36Sopenharmony_ci crypt_stat->flags |= ECRYPTFS_ENCFN_USE_MOUNT_FNEK; 66962306a36Sopenharmony_ci else if (mount_crypt_stat->flags 67062306a36Sopenharmony_ci & ECRYPTFS_GLOBAL_ENCFN_USE_FEK) 67162306a36Sopenharmony_ci crypt_stat->flags |= ECRYPTFS_ENCFN_USE_FEK; 67262306a36Sopenharmony_ci } 67362306a36Sopenharmony_ci} 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_cistatic int ecryptfs_copy_mount_wide_sigs_to_inode_sigs( 67662306a36Sopenharmony_ci struct ecryptfs_crypt_stat *crypt_stat, 67762306a36Sopenharmony_ci struct ecryptfs_mount_crypt_stat *mount_crypt_stat) 67862306a36Sopenharmony_ci{ 67962306a36Sopenharmony_ci struct ecryptfs_global_auth_tok *global_auth_tok; 68062306a36Sopenharmony_ci int rc = 0; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci mutex_lock(&crypt_stat->keysig_list_mutex); 68362306a36Sopenharmony_ci mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci list_for_each_entry(global_auth_tok, 68662306a36Sopenharmony_ci &mount_crypt_stat->global_auth_tok_list, 68762306a36Sopenharmony_ci mount_crypt_stat_list) { 68862306a36Sopenharmony_ci if (global_auth_tok->flags & ECRYPTFS_AUTH_TOK_FNEK) 68962306a36Sopenharmony_ci continue; 69062306a36Sopenharmony_ci rc = ecryptfs_add_keysig(crypt_stat, global_auth_tok->sig); 69162306a36Sopenharmony_ci if (rc) { 69262306a36Sopenharmony_ci printk(KERN_ERR "Error adding keysig; rc = [%d]\n", rc); 69362306a36Sopenharmony_ci goto out; 69462306a36Sopenharmony_ci } 69562306a36Sopenharmony_ci } 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ciout: 69862306a36Sopenharmony_ci mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); 69962306a36Sopenharmony_ci mutex_unlock(&crypt_stat->keysig_list_mutex); 70062306a36Sopenharmony_ci return rc; 70162306a36Sopenharmony_ci} 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci/** 70462306a36Sopenharmony_ci * ecryptfs_set_default_crypt_stat_vals 70562306a36Sopenharmony_ci * @crypt_stat: The inode's cryptographic context 70662306a36Sopenharmony_ci * @mount_crypt_stat: The mount point's cryptographic context 70762306a36Sopenharmony_ci * 70862306a36Sopenharmony_ci * Default values in the event that policy does not override them. 70962306a36Sopenharmony_ci */ 71062306a36Sopenharmony_cistatic void ecryptfs_set_default_crypt_stat_vals( 71162306a36Sopenharmony_ci struct ecryptfs_crypt_stat *crypt_stat, 71262306a36Sopenharmony_ci struct ecryptfs_mount_crypt_stat *mount_crypt_stat) 71362306a36Sopenharmony_ci{ 71462306a36Sopenharmony_ci ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat, 71562306a36Sopenharmony_ci mount_crypt_stat); 71662306a36Sopenharmony_ci ecryptfs_set_default_sizes(crypt_stat); 71762306a36Sopenharmony_ci strcpy(crypt_stat->cipher, ECRYPTFS_DEFAULT_CIPHER); 71862306a36Sopenharmony_ci crypt_stat->key_size = ECRYPTFS_DEFAULT_KEY_BYTES; 71962306a36Sopenharmony_ci crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID); 72062306a36Sopenharmony_ci crypt_stat->file_version = ECRYPTFS_FILE_VERSION; 72162306a36Sopenharmony_ci crypt_stat->mount_crypt_stat = mount_crypt_stat; 72262306a36Sopenharmony_ci} 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci/** 72562306a36Sopenharmony_ci * ecryptfs_new_file_context 72662306a36Sopenharmony_ci * @ecryptfs_inode: The eCryptfs inode 72762306a36Sopenharmony_ci * 72862306a36Sopenharmony_ci * If the crypto context for the file has not yet been established, 72962306a36Sopenharmony_ci * this is where we do that. Establishing a new crypto context 73062306a36Sopenharmony_ci * involves the following decisions: 73162306a36Sopenharmony_ci * - What cipher to use? 73262306a36Sopenharmony_ci * - What set of authentication tokens to use? 73362306a36Sopenharmony_ci * Here we just worry about getting enough information into the 73462306a36Sopenharmony_ci * authentication tokens so that we know that they are available. 73562306a36Sopenharmony_ci * We associate the available authentication tokens with the new file 73662306a36Sopenharmony_ci * via the set of signatures in the crypt_stat struct. Later, when 73762306a36Sopenharmony_ci * the headers are actually written out, we may again defer to 73862306a36Sopenharmony_ci * userspace to perform the encryption of the session key; for the 73962306a36Sopenharmony_ci * foreseeable future, this will be the case with public key packets. 74062306a36Sopenharmony_ci * 74162306a36Sopenharmony_ci * Returns zero on success; non-zero otherwise 74262306a36Sopenharmony_ci */ 74362306a36Sopenharmony_ciint ecryptfs_new_file_context(struct inode *ecryptfs_inode) 74462306a36Sopenharmony_ci{ 74562306a36Sopenharmony_ci struct ecryptfs_crypt_stat *crypt_stat = 74662306a36Sopenharmony_ci &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; 74762306a36Sopenharmony_ci struct ecryptfs_mount_crypt_stat *mount_crypt_stat = 74862306a36Sopenharmony_ci &ecryptfs_superblock_to_private( 74962306a36Sopenharmony_ci ecryptfs_inode->i_sb)->mount_crypt_stat; 75062306a36Sopenharmony_ci int cipher_name_len; 75162306a36Sopenharmony_ci int rc = 0; 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci ecryptfs_set_default_crypt_stat_vals(crypt_stat, mount_crypt_stat); 75462306a36Sopenharmony_ci crypt_stat->flags |= (ECRYPTFS_ENCRYPTED | ECRYPTFS_KEY_VALID); 75562306a36Sopenharmony_ci ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat, 75662306a36Sopenharmony_ci mount_crypt_stat); 75762306a36Sopenharmony_ci rc = ecryptfs_copy_mount_wide_sigs_to_inode_sigs(crypt_stat, 75862306a36Sopenharmony_ci mount_crypt_stat); 75962306a36Sopenharmony_ci if (rc) { 76062306a36Sopenharmony_ci printk(KERN_ERR "Error attempting to copy mount-wide key sigs " 76162306a36Sopenharmony_ci "to the inode key sigs; rc = [%d]\n", rc); 76262306a36Sopenharmony_ci goto out; 76362306a36Sopenharmony_ci } 76462306a36Sopenharmony_ci cipher_name_len = 76562306a36Sopenharmony_ci strlen(mount_crypt_stat->global_default_cipher_name); 76662306a36Sopenharmony_ci memcpy(crypt_stat->cipher, 76762306a36Sopenharmony_ci mount_crypt_stat->global_default_cipher_name, 76862306a36Sopenharmony_ci cipher_name_len); 76962306a36Sopenharmony_ci crypt_stat->cipher[cipher_name_len] = '\0'; 77062306a36Sopenharmony_ci crypt_stat->key_size = 77162306a36Sopenharmony_ci mount_crypt_stat->global_default_cipher_key_size; 77262306a36Sopenharmony_ci ecryptfs_generate_new_key(crypt_stat); 77362306a36Sopenharmony_ci rc = ecryptfs_init_crypt_ctx(crypt_stat); 77462306a36Sopenharmony_ci if (rc) 77562306a36Sopenharmony_ci ecryptfs_printk(KERN_ERR, "Error initializing cryptographic " 77662306a36Sopenharmony_ci "context for cipher [%s]: rc = [%d]\n", 77762306a36Sopenharmony_ci crypt_stat->cipher, rc); 77862306a36Sopenharmony_ciout: 77962306a36Sopenharmony_ci return rc; 78062306a36Sopenharmony_ci} 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci/** 78362306a36Sopenharmony_ci * ecryptfs_validate_marker - check for the ecryptfs marker 78462306a36Sopenharmony_ci * @data: The data block in which to check 78562306a36Sopenharmony_ci * 78662306a36Sopenharmony_ci * Returns zero if marker found; -EINVAL if not found 78762306a36Sopenharmony_ci */ 78862306a36Sopenharmony_cistatic int ecryptfs_validate_marker(char *data) 78962306a36Sopenharmony_ci{ 79062306a36Sopenharmony_ci u32 m_1, m_2; 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci m_1 = get_unaligned_be32(data); 79362306a36Sopenharmony_ci m_2 = get_unaligned_be32(data + 4); 79462306a36Sopenharmony_ci if ((m_1 ^ MAGIC_ECRYPTFS_MARKER) == m_2) 79562306a36Sopenharmony_ci return 0; 79662306a36Sopenharmony_ci ecryptfs_printk(KERN_DEBUG, "m_1 = [0x%.8x]; m_2 = [0x%.8x]; " 79762306a36Sopenharmony_ci "MAGIC_ECRYPTFS_MARKER = [0x%.8x]\n", m_1, m_2, 79862306a36Sopenharmony_ci MAGIC_ECRYPTFS_MARKER); 79962306a36Sopenharmony_ci ecryptfs_printk(KERN_DEBUG, "(m_1 ^ MAGIC_ECRYPTFS_MARKER) = " 80062306a36Sopenharmony_ci "[0x%.8x]\n", (m_1 ^ MAGIC_ECRYPTFS_MARKER)); 80162306a36Sopenharmony_ci return -EINVAL; 80262306a36Sopenharmony_ci} 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_cistruct ecryptfs_flag_map_elem { 80562306a36Sopenharmony_ci u32 file_flag; 80662306a36Sopenharmony_ci u32 local_flag; 80762306a36Sopenharmony_ci}; 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci/* Add support for additional flags by adding elements here. */ 81062306a36Sopenharmony_cistatic struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = { 81162306a36Sopenharmony_ci {0x00000001, ECRYPTFS_ENABLE_HMAC}, 81262306a36Sopenharmony_ci {0x00000002, ECRYPTFS_ENCRYPTED}, 81362306a36Sopenharmony_ci {0x00000004, ECRYPTFS_METADATA_IN_XATTR}, 81462306a36Sopenharmony_ci {0x00000008, ECRYPTFS_ENCRYPT_FILENAMES} 81562306a36Sopenharmony_ci}; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci/** 81862306a36Sopenharmony_ci * ecryptfs_process_flags 81962306a36Sopenharmony_ci * @crypt_stat: The cryptographic context 82062306a36Sopenharmony_ci * @page_virt: Source data to be parsed 82162306a36Sopenharmony_ci * @bytes_read: Updated with the number of bytes read 82262306a36Sopenharmony_ci */ 82362306a36Sopenharmony_cistatic void ecryptfs_process_flags(struct ecryptfs_crypt_stat *crypt_stat, 82462306a36Sopenharmony_ci char *page_virt, int *bytes_read) 82562306a36Sopenharmony_ci{ 82662306a36Sopenharmony_ci int i; 82762306a36Sopenharmony_ci u32 flags; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci flags = get_unaligned_be32(page_virt); 83062306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ecryptfs_flag_map); i++) 83162306a36Sopenharmony_ci if (flags & ecryptfs_flag_map[i].file_flag) { 83262306a36Sopenharmony_ci crypt_stat->flags |= ecryptfs_flag_map[i].local_flag; 83362306a36Sopenharmony_ci } else 83462306a36Sopenharmony_ci crypt_stat->flags &= ~(ecryptfs_flag_map[i].local_flag); 83562306a36Sopenharmony_ci /* Version is in top 8 bits of the 32-bit flag vector */ 83662306a36Sopenharmony_ci crypt_stat->file_version = ((flags >> 24) & 0xFF); 83762306a36Sopenharmony_ci (*bytes_read) = 4; 83862306a36Sopenharmony_ci} 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci/** 84162306a36Sopenharmony_ci * write_ecryptfs_marker 84262306a36Sopenharmony_ci * @page_virt: The pointer to in a page to begin writing the marker 84362306a36Sopenharmony_ci * @written: Number of bytes written 84462306a36Sopenharmony_ci * 84562306a36Sopenharmony_ci * Marker = 0x3c81b7f5 84662306a36Sopenharmony_ci */ 84762306a36Sopenharmony_cistatic void write_ecryptfs_marker(char *page_virt, size_t *written) 84862306a36Sopenharmony_ci{ 84962306a36Sopenharmony_ci u32 m_1, m_2; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci get_random_bytes(&m_1, (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2)); 85262306a36Sopenharmony_ci m_2 = (m_1 ^ MAGIC_ECRYPTFS_MARKER); 85362306a36Sopenharmony_ci put_unaligned_be32(m_1, page_virt); 85462306a36Sopenharmony_ci page_virt += (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2); 85562306a36Sopenharmony_ci put_unaligned_be32(m_2, page_virt); 85662306a36Sopenharmony_ci (*written) = MAGIC_ECRYPTFS_MARKER_SIZE_BYTES; 85762306a36Sopenharmony_ci} 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_civoid ecryptfs_write_crypt_stat_flags(char *page_virt, 86062306a36Sopenharmony_ci struct ecryptfs_crypt_stat *crypt_stat, 86162306a36Sopenharmony_ci size_t *written) 86262306a36Sopenharmony_ci{ 86362306a36Sopenharmony_ci u32 flags = 0; 86462306a36Sopenharmony_ci int i; 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ecryptfs_flag_map); i++) 86762306a36Sopenharmony_ci if (crypt_stat->flags & ecryptfs_flag_map[i].local_flag) 86862306a36Sopenharmony_ci flags |= ecryptfs_flag_map[i].file_flag; 86962306a36Sopenharmony_ci /* Version is in top 8 bits of the 32-bit flag vector */ 87062306a36Sopenharmony_ci flags |= ((((u8)crypt_stat->file_version) << 24) & 0xFF000000); 87162306a36Sopenharmony_ci put_unaligned_be32(flags, page_virt); 87262306a36Sopenharmony_ci (*written) = 4; 87362306a36Sopenharmony_ci} 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_cistruct ecryptfs_cipher_code_str_map_elem { 87662306a36Sopenharmony_ci char cipher_str[16]; 87762306a36Sopenharmony_ci u8 cipher_code; 87862306a36Sopenharmony_ci}; 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci/* Add support for additional ciphers by adding elements here. The 88162306a36Sopenharmony_ci * cipher_code is whatever OpenPGP applications use to identify the 88262306a36Sopenharmony_ci * ciphers. List in order of probability. */ 88362306a36Sopenharmony_cistatic struct ecryptfs_cipher_code_str_map_elem 88462306a36Sopenharmony_ciecryptfs_cipher_code_str_map[] = { 88562306a36Sopenharmony_ci {"aes",RFC2440_CIPHER_AES_128 }, 88662306a36Sopenharmony_ci {"blowfish", RFC2440_CIPHER_BLOWFISH}, 88762306a36Sopenharmony_ci {"des3_ede", RFC2440_CIPHER_DES3_EDE}, 88862306a36Sopenharmony_ci {"cast5", RFC2440_CIPHER_CAST_5}, 88962306a36Sopenharmony_ci {"twofish", RFC2440_CIPHER_TWOFISH}, 89062306a36Sopenharmony_ci {"cast6", RFC2440_CIPHER_CAST_6}, 89162306a36Sopenharmony_ci {"aes", RFC2440_CIPHER_AES_192}, 89262306a36Sopenharmony_ci {"aes", RFC2440_CIPHER_AES_256} 89362306a36Sopenharmony_ci}; 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci/** 89662306a36Sopenharmony_ci * ecryptfs_code_for_cipher_string 89762306a36Sopenharmony_ci * @cipher_name: The string alias for the cipher 89862306a36Sopenharmony_ci * @key_bytes: Length of key in bytes; used for AES code selection 89962306a36Sopenharmony_ci * 90062306a36Sopenharmony_ci * Returns zero on no match, or the cipher code on match 90162306a36Sopenharmony_ci */ 90262306a36Sopenharmony_ciu8 ecryptfs_code_for_cipher_string(char *cipher_name, size_t key_bytes) 90362306a36Sopenharmony_ci{ 90462306a36Sopenharmony_ci int i; 90562306a36Sopenharmony_ci u8 code = 0; 90662306a36Sopenharmony_ci struct ecryptfs_cipher_code_str_map_elem *map = 90762306a36Sopenharmony_ci ecryptfs_cipher_code_str_map; 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci if (strcmp(cipher_name, "aes") == 0) { 91062306a36Sopenharmony_ci switch (key_bytes) { 91162306a36Sopenharmony_ci case 16: 91262306a36Sopenharmony_ci code = RFC2440_CIPHER_AES_128; 91362306a36Sopenharmony_ci break; 91462306a36Sopenharmony_ci case 24: 91562306a36Sopenharmony_ci code = RFC2440_CIPHER_AES_192; 91662306a36Sopenharmony_ci break; 91762306a36Sopenharmony_ci case 32: 91862306a36Sopenharmony_ci code = RFC2440_CIPHER_AES_256; 91962306a36Sopenharmony_ci } 92062306a36Sopenharmony_ci } else { 92162306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ecryptfs_cipher_code_str_map); i++) 92262306a36Sopenharmony_ci if (strcmp(cipher_name, map[i].cipher_str) == 0) { 92362306a36Sopenharmony_ci code = map[i].cipher_code; 92462306a36Sopenharmony_ci break; 92562306a36Sopenharmony_ci } 92662306a36Sopenharmony_ci } 92762306a36Sopenharmony_ci return code; 92862306a36Sopenharmony_ci} 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci/** 93162306a36Sopenharmony_ci * ecryptfs_cipher_code_to_string 93262306a36Sopenharmony_ci * @str: Destination to write out the cipher name 93362306a36Sopenharmony_ci * @cipher_code: The code to convert to cipher name string 93462306a36Sopenharmony_ci * 93562306a36Sopenharmony_ci * Returns zero on success 93662306a36Sopenharmony_ci */ 93762306a36Sopenharmony_ciint ecryptfs_cipher_code_to_string(char *str, u8 cipher_code) 93862306a36Sopenharmony_ci{ 93962306a36Sopenharmony_ci int rc = 0; 94062306a36Sopenharmony_ci int i; 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci str[0] = '\0'; 94362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(ecryptfs_cipher_code_str_map); i++) 94462306a36Sopenharmony_ci if (cipher_code == ecryptfs_cipher_code_str_map[i].cipher_code) 94562306a36Sopenharmony_ci strcpy(str, ecryptfs_cipher_code_str_map[i].cipher_str); 94662306a36Sopenharmony_ci if (str[0] == '\0') { 94762306a36Sopenharmony_ci ecryptfs_printk(KERN_WARNING, "Cipher code not recognized: " 94862306a36Sopenharmony_ci "[%d]\n", cipher_code); 94962306a36Sopenharmony_ci rc = -EINVAL; 95062306a36Sopenharmony_ci } 95162306a36Sopenharmony_ci return rc; 95262306a36Sopenharmony_ci} 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ciint ecryptfs_read_and_validate_header_region(struct inode *inode) 95562306a36Sopenharmony_ci{ 95662306a36Sopenharmony_ci u8 file_size[ECRYPTFS_SIZE_AND_MARKER_BYTES]; 95762306a36Sopenharmony_ci u8 *marker = file_size + ECRYPTFS_FILE_SIZE_BYTES; 95862306a36Sopenharmony_ci int rc; 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci rc = ecryptfs_read_lower(file_size, 0, ECRYPTFS_SIZE_AND_MARKER_BYTES, 96162306a36Sopenharmony_ci inode); 96262306a36Sopenharmony_ci if (rc < 0) 96362306a36Sopenharmony_ci return rc; 96462306a36Sopenharmony_ci else if (rc < ECRYPTFS_SIZE_AND_MARKER_BYTES) 96562306a36Sopenharmony_ci return -EINVAL; 96662306a36Sopenharmony_ci rc = ecryptfs_validate_marker(marker); 96762306a36Sopenharmony_ci if (!rc) 96862306a36Sopenharmony_ci ecryptfs_i_size_init(file_size, inode); 96962306a36Sopenharmony_ci return rc; 97062306a36Sopenharmony_ci} 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_civoid 97362306a36Sopenharmony_ciecryptfs_write_header_metadata(char *virt, 97462306a36Sopenharmony_ci struct ecryptfs_crypt_stat *crypt_stat, 97562306a36Sopenharmony_ci size_t *written) 97662306a36Sopenharmony_ci{ 97762306a36Sopenharmony_ci u32 header_extent_size; 97862306a36Sopenharmony_ci u16 num_header_extents_at_front; 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci header_extent_size = (u32)crypt_stat->extent_size; 98162306a36Sopenharmony_ci num_header_extents_at_front = 98262306a36Sopenharmony_ci (u16)(crypt_stat->metadata_size / crypt_stat->extent_size); 98362306a36Sopenharmony_ci put_unaligned_be32(header_extent_size, virt); 98462306a36Sopenharmony_ci virt += 4; 98562306a36Sopenharmony_ci put_unaligned_be16(num_header_extents_at_front, virt); 98662306a36Sopenharmony_ci (*written) = 6; 98762306a36Sopenharmony_ci} 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_cistruct kmem_cache *ecryptfs_header_cache; 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci/** 99262306a36Sopenharmony_ci * ecryptfs_write_headers_virt 99362306a36Sopenharmony_ci * @page_virt: The virtual address to write the headers to 99462306a36Sopenharmony_ci * @max: The size of memory allocated at page_virt 99562306a36Sopenharmony_ci * @size: Set to the number of bytes written by this function 99662306a36Sopenharmony_ci * @crypt_stat: The cryptographic context 99762306a36Sopenharmony_ci * @ecryptfs_dentry: The eCryptfs dentry 99862306a36Sopenharmony_ci * 99962306a36Sopenharmony_ci * Format version: 1 100062306a36Sopenharmony_ci * 100162306a36Sopenharmony_ci * Header Extent: 100262306a36Sopenharmony_ci * Octets 0-7: Unencrypted file size (big-endian) 100362306a36Sopenharmony_ci * Octets 8-15: eCryptfs special marker 100462306a36Sopenharmony_ci * Octets 16-19: Flags 100562306a36Sopenharmony_ci * Octet 16: File format version number (between 0 and 255) 100662306a36Sopenharmony_ci * Octets 17-18: Reserved 100762306a36Sopenharmony_ci * Octet 19: Bit 1 (lsb): Reserved 100862306a36Sopenharmony_ci * Bit 2: Encrypted? 100962306a36Sopenharmony_ci * Bits 3-8: Reserved 101062306a36Sopenharmony_ci * Octets 20-23: Header extent size (big-endian) 101162306a36Sopenharmony_ci * Octets 24-25: Number of header extents at front of file 101262306a36Sopenharmony_ci * (big-endian) 101362306a36Sopenharmony_ci * Octet 26: Begin RFC 2440 authentication token packet set 101462306a36Sopenharmony_ci * Data Extent 0: 101562306a36Sopenharmony_ci * Lower data (CBC encrypted) 101662306a36Sopenharmony_ci * Data Extent 1: 101762306a36Sopenharmony_ci * Lower data (CBC encrypted) 101862306a36Sopenharmony_ci * ... 101962306a36Sopenharmony_ci * 102062306a36Sopenharmony_ci * Returns zero on success 102162306a36Sopenharmony_ci */ 102262306a36Sopenharmony_cistatic int ecryptfs_write_headers_virt(char *page_virt, size_t max, 102362306a36Sopenharmony_ci size_t *size, 102462306a36Sopenharmony_ci struct ecryptfs_crypt_stat *crypt_stat, 102562306a36Sopenharmony_ci struct dentry *ecryptfs_dentry) 102662306a36Sopenharmony_ci{ 102762306a36Sopenharmony_ci int rc; 102862306a36Sopenharmony_ci size_t written; 102962306a36Sopenharmony_ci size_t offset; 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci offset = ECRYPTFS_FILE_SIZE_BYTES; 103262306a36Sopenharmony_ci write_ecryptfs_marker((page_virt + offset), &written); 103362306a36Sopenharmony_ci offset += written; 103462306a36Sopenharmony_ci ecryptfs_write_crypt_stat_flags((page_virt + offset), crypt_stat, 103562306a36Sopenharmony_ci &written); 103662306a36Sopenharmony_ci offset += written; 103762306a36Sopenharmony_ci ecryptfs_write_header_metadata((page_virt + offset), crypt_stat, 103862306a36Sopenharmony_ci &written); 103962306a36Sopenharmony_ci offset += written; 104062306a36Sopenharmony_ci rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat, 104162306a36Sopenharmony_ci ecryptfs_dentry, &written, 104262306a36Sopenharmony_ci max - offset); 104362306a36Sopenharmony_ci if (rc) 104462306a36Sopenharmony_ci ecryptfs_printk(KERN_WARNING, "Error generating key packet " 104562306a36Sopenharmony_ci "set; rc = [%d]\n", rc); 104662306a36Sopenharmony_ci if (size) { 104762306a36Sopenharmony_ci offset += written; 104862306a36Sopenharmony_ci *size = offset; 104962306a36Sopenharmony_ci } 105062306a36Sopenharmony_ci return rc; 105162306a36Sopenharmony_ci} 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_cistatic int 105462306a36Sopenharmony_ciecryptfs_write_metadata_to_contents(struct inode *ecryptfs_inode, 105562306a36Sopenharmony_ci char *virt, size_t virt_len) 105662306a36Sopenharmony_ci{ 105762306a36Sopenharmony_ci int rc; 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci rc = ecryptfs_write_lower(ecryptfs_inode, virt, 106062306a36Sopenharmony_ci 0, virt_len); 106162306a36Sopenharmony_ci if (rc < 0) 106262306a36Sopenharmony_ci printk(KERN_ERR "%s: Error attempting to write header " 106362306a36Sopenharmony_ci "information to lower file; rc = [%d]\n", __func__, rc); 106462306a36Sopenharmony_ci else 106562306a36Sopenharmony_ci rc = 0; 106662306a36Sopenharmony_ci return rc; 106762306a36Sopenharmony_ci} 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_cistatic int 107062306a36Sopenharmony_ciecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry, 107162306a36Sopenharmony_ci struct inode *ecryptfs_inode, 107262306a36Sopenharmony_ci char *page_virt, size_t size) 107362306a36Sopenharmony_ci{ 107462306a36Sopenharmony_ci int rc; 107562306a36Sopenharmony_ci struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); 107662306a36Sopenharmony_ci struct inode *lower_inode = d_inode(lower_dentry); 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci if (!(lower_inode->i_opflags & IOP_XATTR)) { 107962306a36Sopenharmony_ci rc = -EOPNOTSUPP; 108062306a36Sopenharmony_ci goto out; 108162306a36Sopenharmony_ci } 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci inode_lock(lower_inode); 108462306a36Sopenharmony_ci rc = __vfs_setxattr(&nop_mnt_idmap, lower_dentry, lower_inode, 108562306a36Sopenharmony_ci ECRYPTFS_XATTR_NAME, page_virt, size, 0); 108662306a36Sopenharmony_ci if (!rc && ecryptfs_inode) 108762306a36Sopenharmony_ci fsstack_copy_attr_all(ecryptfs_inode, lower_inode); 108862306a36Sopenharmony_ci inode_unlock(lower_inode); 108962306a36Sopenharmony_ciout: 109062306a36Sopenharmony_ci return rc; 109162306a36Sopenharmony_ci} 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_cistatic unsigned long ecryptfs_get_zeroed_pages(gfp_t gfp_mask, 109462306a36Sopenharmony_ci unsigned int order) 109562306a36Sopenharmony_ci{ 109662306a36Sopenharmony_ci struct page *page; 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci page = alloc_pages(gfp_mask | __GFP_ZERO, order); 109962306a36Sopenharmony_ci if (page) 110062306a36Sopenharmony_ci return (unsigned long) page_address(page); 110162306a36Sopenharmony_ci return 0; 110262306a36Sopenharmony_ci} 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci/** 110562306a36Sopenharmony_ci * ecryptfs_write_metadata 110662306a36Sopenharmony_ci * @ecryptfs_dentry: The eCryptfs dentry, which should be negative 110762306a36Sopenharmony_ci * @ecryptfs_inode: The newly created eCryptfs inode 110862306a36Sopenharmony_ci * 110962306a36Sopenharmony_ci * Write the file headers out. This will likely involve a userspace 111062306a36Sopenharmony_ci * callout, in which the session key is encrypted with one or more 111162306a36Sopenharmony_ci * public keys and/or the passphrase necessary to do the encryption is 111262306a36Sopenharmony_ci * retrieved via a prompt. Exactly what happens at this point should 111362306a36Sopenharmony_ci * be policy-dependent. 111462306a36Sopenharmony_ci * 111562306a36Sopenharmony_ci * Returns zero on success; non-zero on error 111662306a36Sopenharmony_ci */ 111762306a36Sopenharmony_ciint ecryptfs_write_metadata(struct dentry *ecryptfs_dentry, 111862306a36Sopenharmony_ci struct inode *ecryptfs_inode) 111962306a36Sopenharmony_ci{ 112062306a36Sopenharmony_ci struct ecryptfs_crypt_stat *crypt_stat = 112162306a36Sopenharmony_ci &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; 112262306a36Sopenharmony_ci unsigned int order; 112362306a36Sopenharmony_ci char *virt; 112462306a36Sopenharmony_ci size_t virt_len; 112562306a36Sopenharmony_ci size_t size = 0; 112662306a36Sopenharmony_ci int rc = 0; 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci if (likely(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) { 112962306a36Sopenharmony_ci if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) { 113062306a36Sopenharmony_ci printk(KERN_ERR "Key is invalid; bailing out\n"); 113162306a36Sopenharmony_ci rc = -EINVAL; 113262306a36Sopenharmony_ci goto out; 113362306a36Sopenharmony_ci } 113462306a36Sopenharmony_ci } else { 113562306a36Sopenharmony_ci printk(KERN_WARNING "%s: Encrypted flag not set\n", 113662306a36Sopenharmony_ci __func__); 113762306a36Sopenharmony_ci rc = -EINVAL; 113862306a36Sopenharmony_ci goto out; 113962306a36Sopenharmony_ci } 114062306a36Sopenharmony_ci virt_len = crypt_stat->metadata_size; 114162306a36Sopenharmony_ci order = get_order(virt_len); 114262306a36Sopenharmony_ci /* Released in this function */ 114362306a36Sopenharmony_ci virt = (char *)ecryptfs_get_zeroed_pages(GFP_KERNEL, order); 114462306a36Sopenharmony_ci if (!virt) { 114562306a36Sopenharmony_ci printk(KERN_ERR "%s: Out of memory\n", __func__); 114662306a36Sopenharmony_ci rc = -ENOMEM; 114762306a36Sopenharmony_ci goto out; 114862306a36Sopenharmony_ci } 114962306a36Sopenharmony_ci /* Zeroed page ensures the in-header unencrypted i_size is set to 0 */ 115062306a36Sopenharmony_ci rc = ecryptfs_write_headers_virt(virt, virt_len, &size, crypt_stat, 115162306a36Sopenharmony_ci ecryptfs_dentry); 115262306a36Sopenharmony_ci if (unlikely(rc)) { 115362306a36Sopenharmony_ci printk(KERN_ERR "%s: Error whilst writing headers; rc = [%d]\n", 115462306a36Sopenharmony_ci __func__, rc); 115562306a36Sopenharmony_ci goto out_free; 115662306a36Sopenharmony_ci } 115762306a36Sopenharmony_ci if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) 115862306a36Sopenharmony_ci rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, ecryptfs_inode, 115962306a36Sopenharmony_ci virt, size); 116062306a36Sopenharmony_ci else 116162306a36Sopenharmony_ci rc = ecryptfs_write_metadata_to_contents(ecryptfs_inode, virt, 116262306a36Sopenharmony_ci virt_len); 116362306a36Sopenharmony_ci if (rc) { 116462306a36Sopenharmony_ci printk(KERN_ERR "%s: Error writing metadata out to lower file; " 116562306a36Sopenharmony_ci "rc = [%d]\n", __func__, rc); 116662306a36Sopenharmony_ci goto out_free; 116762306a36Sopenharmony_ci } 116862306a36Sopenharmony_ciout_free: 116962306a36Sopenharmony_ci free_pages((unsigned long)virt, order); 117062306a36Sopenharmony_ciout: 117162306a36Sopenharmony_ci return rc; 117262306a36Sopenharmony_ci} 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci#define ECRYPTFS_DONT_VALIDATE_HEADER_SIZE 0 117562306a36Sopenharmony_ci#define ECRYPTFS_VALIDATE_HEADER_SIZE 1 117662306a36Sopenharmony_cistatic int parse_header_metadata(struct ecryptfs_crypt_stat *crypt_stat, 117762306a36Sopenharmony_ci char *virt, int *bytes_read, 117862306a36Sopenharmony_ci int validate_header_size) 117962306a36Sopenharmony_ci{ 118062306a36Sopenharmony_ci int rc = 0; 118162306a36Sopenharmony_ci u32 header_extent_size; 118262306a36Sopenharmony_ci u16 num_header_extents_at_front; 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci header_extent_size = get_unaligned_be32(virt); 118562306a36Sopenharmony_ci virt += sizeof(__be32); 118662306a36Sopenharmony_ci num_header_extents_at_front = get_unaligned_be16(virt); 118762306a36Sopenharmony_ci crypt_stat->metadata_size = (((size_t)num_header_extents_at_front 118862306a36Sopenharmony_ci * (size_t)header_extent_size)); 118962306a36Sopenharmony_ci (*bytes_read) = (sizeof(__be32) + sizeof(__be16)); 119062306a36Sopenharmony_ci if ((validate_header_size == ECRYPTFS_VALIDATE_HEADER_SIZE) 119162306a36Sopenharmony_ci && (crypt_stat->metadata_size 119262306a36Sopenharmony_ci < ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)) { 119362306a36Sopenharmony_ci rc = -EINVAL; 119462306a36Sopenharmony_ci printk(KERN_WARNING "Invalid header size: [%zd]\n", 119562306a36Sopenharmony_ci crypt_stat->metadata_size); 119662306a36Sopenharmony_ci } 119762306a36Sopenharmony_ci return rc; 119862306a36Sopenharmony_ci} 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci/** 120162306a36Sopenharmony_ci * set_default_header_data 120262306a36Sopenharmony_ci * @crypt_stat: The cryptographic context 120362306a36Sopenharmony_ci * 120462306a36Sopenharmony_ci * For version 0 file format; this function is only for backwards 120562306a36Sopenharmony_ci * compatibility for files created with the prior versions of 120662306a36Sopenharmony_ci * eCryptfs. 120762306a36Sopenharmony_ci */ 120862306a36Sopenharmony_cistatic void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat) 120962306a36Sopenharmony_ci{ 121062306a36Sopenharmony_ci crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE; 121162306a36Sopenharmony_ci} 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_civoid ecryptfs_i_size_init(const char *page_virt, struct inode *inode) 121462306a36Sopenharmony_ci{ 121562306a36Sopenharmony_ci struct ecryptfs_mount_crypt_stat *mount_crypt_stat; 121662306a36Sopenharmony_ci struct ecryptfs_crypt_stat *crypt_stat; 121762306a36Sopenharmony_ci u64 file_size; 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; 122062306a36Sopenharmony_ci mount_crypt_stat = 122162306a36Sopenharmony_ci &ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat; 122262306a36Sopenharmony_ci if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) { 122362306a36Sopenharmony_ci file_size = i_size_read(ecryptfs_inode_to_lower(inode)); 122462306a36Sopenharmony_ci if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR) 122562306a36Sopenharmony_ci file_size += crypt_stat->metadata_size; 122662306a36Sopenharmony_ci } else 122762306a36Sopenharmony_ci file_size = get_unaligned_be64(page_virt); 122862306a36Sopenharmony_ci i_size_write(inode, (loff_t)file_size); 122962306a36Sopenharmony_ci crypt_stat->flags |= ECRYPTFS_I_SIZE_INITIALIZED; 123062306a36Sopenharmony_ci} 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci/** 123362306a36Sopenharmony_ci * ecryptfs_read_headers_virt 123462306a36Sopenharmony_ci * @page_virt: The virtual address into which to read the headers 123562306a36Sopenharmony_ci * @crypt_stat: The cryptographic context 123662306a36Sopenharmony_ci * @ecryptfs_dentry: The eCryptfs dentry 123762306a36Sopenharmony_ci * @validate_header_size: Whether to validate the header size while reading 123862306a36Sopenharmony_ci * 123962306a36Sopenharmony_ci * Read/parse the header data. The header format is detailed in the 124062306a36Sopenharmony_ci * comment block for the ecryptfs_write_headers_virt() function. 124162306a36Sopenharmony_ci * 124262306a36Sopenharmony_ci * Returns zero on success 124362306a36Sopenharmony_ci */ 124462306a36Sopenharmony_cistatic int ecryptfs_read_headers_virt(char *page_virt, 124562306a36Sopenharmony_ci struct ecryptfs_crypt_stat *crypt_stat, 124662306a36Sopenharmony_ci struct dentry *ecryptfs_dentry, 124762306a36Sopenharmony_ci int validate_header_size) 124862306a36Sopenharmony_ci{ 124962306a36Sopenharmony_ci int rc = 0; 125062306a36Sopenharmony_ci int offset; 125162306a36Sopenharmony_ci int bytes_read; 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci ecryptfs_set_default_sizes(crypt_stat); 125462306a36Sopenharmony_ci crypt_stat->mount_crypt_stat = &ecryptfs_superblock_to_private( 125562306a36Sopenharmony_ci ecryptfs_dentry->d_sb)->mount_crypt_stat; 125662306a36Sopenharmony_ci offset = ECRYPTFS_FILE_SIZE_BYTES; 125762306a36Sopenharmony_ci rc = ecryptfs_validate_marker(page_virt + offset); 125862306a36Sopenharmony_ci if (rc) 125962306a36Sopenharmony_ci goto out; 126062306a36Sopenharmony_ci if (!(crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED)) 126162306a36Sopenharmony_ci ecryptfs_i_size_init(page_virt, d_inode(ecryptfs_dentry)); 126262306a36Sopenharmony_ci offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES; 126362306a36Sopenharmony_ci ecryptfs_process_flags(crypt_stat, (page_virt + offset), &bytes_read); 126462306a36Sopenharmony_ci if (crypt_stat->file_version > ECRYPTFS_SUPPORTED_FILE_VERSION) { 126562306a36Sopenharmony_ci ecryptfs_printk(KERN_WARNING, "File version is [%d]; only " 126662306a36Sopenharmony_ci "file version [%d] is supported by this " 126762306a36Sopenharmony_ci "version of eCryptfs\n", 126862306a36Sopenharmony_ci crypt_stat->file_version, 126962306a36Sopenharmony_ci ECRYPTFS_SUPPORTED_FILE_VERSION); 127062306a36Sopenharmony_ci rc = -EINVAL; 127162306a36Sopenharmony_ci goto out; 127262306a36Sopenharmony_ci } 127362306a36Sopenharmony_ci offset += bytes_read; 127462306a36Sopenharmony_ci if (crypt_stat->file_version >= 1) { 127562306a36Sopenharmony_ci rc = parse_header_metadata(crypt_stat, (page_virt + offset), 127662306a36Sopenharmony_ci &bytes_read, validate_header_size); 127762306a36Sopenharmony_ci if (rc) { 127862306a36Sopenharmony_ci ecryptfs_printk(KERN_WARNING, "Error reading header " 127962306a36Sopenharmony_ci "metadata; rc = [%d]\n", rc); 128062306a36Sopenharmony_ci } 128162306a36Sopenharmony_ci offset += bytes_read; 128262306a36Sopenharmony_ci } else 128362306a36Sopenharmony_ci set_default_header_data(crypt_stat); 128462306a36Sopenharmony_ci rc = ecryptfs_parse_packet_set(crypt_stat, (page_virt + offset), 128562306a36Sopenharmony_ci ecryptfs_dentry); 128662306a36Sopenharmony_ciout: 128762306a36Sopenharmony_ci return rc; 128862306a36Sopenharmony_ci} 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci/** 129162306a36Sopenharmony_ci * ecryptfs_read_xattr_region 129262306a36Sopenharmony_ci * @page_virt: The vitual address into which to read the xattr data 129362306a36Sopenharmony_ci * @ecryptfs_inode: The eCryptfs inode 129462306a36Sopenharmony_ci * 129562306a36Sopenharmony_ci * Attempts to read the crypto metadata from the extended attribute 129662306a36Sopenharmony_ci * region of the lower file. 129762306a36Sopenharmony_ci * 129862306a36Sopenharmony_ci * Returns zero on success; non-zero on error 129962306a36Sopenharmony_ci */ 130062306a36Sopenharmony_ciint ecryptfs_read_xattr_region(char *page_virt, struct inode *ecryptfs_inode) 130162306a36Sopenharmony_ci{ 130262306a36Sopenharmony_ci struct dentry *lower_dentry = 130362306a36Sopenharmony_ci ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_path.dentry; 130462306a36Sopenharmony_ci ssize_t size; 130562306a36Sopenharmony_ci int rc = 0; 130662306a36Sopenharmony_ci 130762306a36Sopenharmony_ci size = ecryptfs_getxattr_lower(lower_dentry, 130862306a36Sopenharmony_ci ecryptfs_inode_to_lower(ecryptfs_inode), 130962306a36Sopenharmony_ci ECRYPTFS_XATTR_NAME, 131062306a36Sopenharmony_ci page_virt, ECRYPTFS_DEFAULT_EXTENT_SIZE); 131162306a36Sopenharmony_ci if (size < 0) { 131262306a36Sopenharmony_ci if (unlikely(ecryptfs_verbosity > 0)) 131362306a36Sopenharmony_ci printk(KERN_INFO "Error attempting to read the [%s] " 131462306a36Sopenharmony_ci "xattr from the lower file; return value = " 131562306a36Sopenharmony_ci "[%zd]\n", ECRYPTFS_XATTR_NAME, size); 131662306a36Sopenharmony_ci rc = -EINVAL; 131762306a36Sopenharmony_ci goto out; 131862306a36Sopenharmony_ci } 131962306a36Sopenharmony_ciout: 132062306a36Sopenharmony_ci return rc; 132162306a36Sopenharmony_ci} 132262306a36Sopenharmony_ci 132362306a36Sopenharmony_ciint ecryptfs_read_and_validate_xattr_region(struct dentry *dentry, 132462306a36Sopenharmony_ci struct inode *inode) 132562306a36Sopenharmony_ci{ 132662306a36Sopenharmony_ci u8 file_size[ECRYPTFS_SIZE_AND_MARKER_BYTES]; 132762306a36Sopenharmony_ci u8 *marker = file_size + ECRYPTFS_FILE_SIZE_BYTES; 132862306a36Sopenharmony_ci int rc; 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_ci rc = ecryptfs_getxattr_lower(ecryptfs_dentry_to_lower(dentry), 133162306a36Sopenharmony_ci ecryptfs_inode_to_lower(inode), 133262306a36Sopenharmony_ci ECRYPTFS_XATTR_NAME, file_size, 133362306a36Sopenharmony_ci ECRYPTFS_SIZE_AND_MARKER_BYTES); 133462306a36Sopenharmony_ci if (rc < 0) 133562306a36Sopenharmony_ci return rc; 133662306a36Sopenharmony_ci else if (rc < ECRYPTFS_SIZE_AND_MARKER_BYTES) 133762306a36Sopenharmony_ci return -EINVAL; 133862306a36Sopenharmony_ci rc = ecryptfs_validate_marker(marker); 133962306a36Sopenharmony_ci if (!rc) 134062306a36Sopenharmony_ci ecryptfs_i_size_init(file_size, inode); 134162306a36Sopenharmony_ci return rc; 134262306a36Sopenharmony_ci} 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci/* 134562306a36Sopenharmony_ci * ecryptfs_read_metadata 134662306a36Sopenharmony_ci * 134762306a36Sopenharmony_ci * Common entry point for reading file metadata. From here, we could 134862306a36Sopenharmony_ci * retrieve the header information from the header region of the file, 134962306a36Sopenharmony_ci * the xattr region of the file, or some other repository that is 135062306a36Sopenharmony_ci * stored separately from the file itself. The current implementation 135162306a36Sopenharmony_ci * supports retrieving the metadata information from the file contents 135262306a36Sopenharmony_ci * and from the xattr region. 135362306a36Sopenharmony_ci * 135462306a36Sopenharmony_ci * Returns zero if valid headers found and parsed; non-zero otherwise 135562306a36Sopenharmony_ci */ 135662306a36Sopenharmony_ciint ecryptfs_read_metadata(struct dentry *ecryptfs_dentry) 135762306a36Sopenharmony_ci{ 135862306a36Sopenharmony_ci int rc; 135962306a36Sopenharmony_ci char *page_virt; 136062306a36Sopenharmony_ci struct inode *ecryptfs_inode = d_inode(ecryptfs_dentry); 136162306a36Sopenharmony_ci struct ecryptfs_crypt_stat *crypt_stat = 136262306a36Sopenharmony_ci &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat; 136362306a36Sopenharmony_ci struct ecryptfs_mount_crypt_stat *mount_crypt_stat = 136462306a36Sopenharmony_ci &ecryptfs_superblock_to_private( 136562306a36Sopenharmony_ci ecryptfs_dentry->d_sb)->mount_crypt_stat; 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat, 136862306a36Sopenharmony_ci mount_crypt_stat); 136962306a36Sopenharmony_ci /* Read the first page from the underlying file */ 137062306a36Sopenharmony_ci page_virt = kmem_cache_alloc(ecryptfs_header_cache, GFP_USER); 137162306a36Sopenharmony_ci if (!page_virt) { 137262306a36Sopenharmony_ci rc = -ENOMEM; 137362306a36Sopenharmony_ci goto out; 137462306a36Sopenharmony_ci } 137562306a36Sopenharmony_ci rc = ecryptfs_read_lower(page_virt, 0, crypt_stat->extent_size, 137662306a36Sopenharmony_ci ecryptfs_inode); 137762306a36Sopenharmony_ci if (rc >= 0) 137862306a36Sopenharmony_ci rc = ecryptfs_read_headers_virt(page_virt, crypt_stat, 137962306a36Sopenharmony_ci ecryptfs_dentry, 138062306a36Sopenharmony_ci ECRYPTFS_VALIDATE_HEADER_SIZE); 138162306a36Sopenharmony_ci if (rc) { 138262306a36Sopenharmony_ci /* metadata is not in the file header, so try xattrs */ 138362306a36Sopenharmony_ci memset(page_virt, 0, PAGE_SIZE); 138462306a36Sopenharmony_ci rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_inode); 138562306a36Sopenharmony_ci if (rc) { 138662306a36Sopenharmony_ci printk(KERN_DEBUG "Valid eCryptfs headers not found in " 138762306a36Sopenharmony_ci "file header region or xattr region, inode %lu\n", 138862306a36Sopenharmony_ci ecryptfs_inode->i_ino); 138962306a36Sopenharmony_ci rc = -EINVAL; 139062306a36Sopenharmony_ci goto out; 139162306a36Sopenharmony_ci } 139262306a36Sopenharmony_ci rc = ecryptfs_read_headers_virt(page_virt, crypt_stat, 139362306a36Sopenharmony_ci ecryptfs_dentry, 139462306a36Sopenharmony_ci ECRYPTFS_DONT_VALIDATE_HEADER_SIZE); 139562306a36Sopenharmony_ci if (rc) { 139662306a36Sopenharmony_ci printk(KERN_DEBUG "Valid eCryptfs headers not found in " 139762306a36Sopenharmony_ci "file xattr region either, inode %lu\n", 139862306a36Sopenharmony_ci ecryptfs_inode->i_ino); 139962306a36Sopenharmony_ci rc = -EINVAL; 140062306a36Sopenharmony_ci } 140162306a36Sopenharmony_ci if (crypt_stat->mount_crypt_stat->flags 140262306a36Sopenharmony_ci & ECRYPTFS_XATTR_METADATA_ENABLED) { 140362306a36Sopenharmony_ci crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR; 140462306a36Sopenharmony_ci } else { 140562306a36Sopenharmony_ci printk(KERN_WARNING "Attempt to access file with " 140662306a36Sopenharmony_ci "crypto metadata only in the extended attribute " 140762306a36Sopenharmony_ci "region, but eCryptfs was mounted without " 140862306a36Sopenharmony_ci "xattr support enabled. eCryptfs will not treat " 140962306a36Sopenharmony_ci "this like an encrypted file, inode %lu\n", 141062306a36Sopenharmony_ci ecryptfs_inode->i_ino); 141162306a36Sopenharmony_ci rc = -EINVAL; 141262306a36Sopenharmony_ci } 141362306a36Sopenharmony_ci } 141462306a36Sopenharmony_ciout: 141562306a36Sopenharmony_ci if (page_virt) { 141662306a36Sopenharmony_ci memset(page_virt, 0, PAGE_SIZE); 141762306a36Sopenharmony_ci kmem_cache_free(ecryptfs_header_cache, page_virt); 141862306a36Sopenharmony_ci } 141962306a36Sopenharmony_ci return rc; 142062306a36Sopenharmony_ci} 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci/* 142362306a36Sopenharmony_ci * ecryptfs_encrypt_filename - encrypt filename 142462306a36Sopenharmony_ci * 142562306a36Sopenharmony_ci * CBC-encrypts the filename. We do not want to encrypt the same 142662306a36Sopenharmony_ci * filename with the same key and IV, which may happen with hard 142762306a36Sopenharmony_ci * links, so we prepend random bits to each filename. 142862306a36Sopenharmony_ci * 142962306a36Sopenharmony_ci * Returns zero on success; non-zero otherwise 143062306a36Sopenharmony_ci */ 143162306a36Sopenharmony_cistatic int 143262306a36Sopenharmony_ciecryptfs_encrypt_filename(struct ecryptfs_filename *filename, 143362306a36Sopenharmony_ci struct ecryptfs_mount_crypt_stat *mount_crypt_stat) 143462306a36Sopenharmony_ci{ 143562306a36Sopenharmony_ci int rc = 0; 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci filename->encrypted_filename = NULL; 143862306a36Sopenharmony_ci filename->encrypted_filename_size = 0; 143962306a36Sopenharmony_ci if (mount_crypt_stat && (mount_crypt_stat->flags 144062306a36Sopenharmony_ci & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK)) { 144162306a36Sopenharmony_ci size_t packet_size; 144262306a36Sopenharmony_ci size_t remaining_bytes; 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci rc = ecryptfs_write_tag_70_packet( 144562306a36Sopenharmony_ci NULL, NULL, 144662306a36Sopenharmony_ci &filename->encrypted_filename_size, 144762306a36Sopenharmony_ci mount_crypt_stat, NULL, 144862306a36Sopenharmony_ci filename->filename_size); 144962306a36Sopenharmony_ci if (rc) { 145062306a36Sopenharmony_ci printk(KERN_ERR "%s: Error attempting to get packet " 145162306a36Sopenharmony_ci "size for tag 72; rc = [%d]\n", __func__, 145262306a36Sopenharmony_ci rc); 145362306a36Sopenharmony_ci filename->encrypted_filename_size = 0; 145462306a36Sopenharmony_ci goto out; 145562306a36Sopenharmony_ci } 145662306a36Sopenharmony_ci filename->encrypted_filename = 145762306a36Sopenharmony_ci kmalloc(filename->encrypted_filename_size, GFP_KERNEL); 145862306a36Sopenharmony_ci if (!filename->encrypted_filename) { 145962306a36Sopenharmony_ci rc = -ENOMEM; 146062306a36Sopenharmony_ci goto out; 146162306a36Sopenharmony_ci } 146262306a36Sopenharmony_ci remaining_bytes = filename->encrypted_filename_size; 146362306a36Sopenharmony_ci rc = ecryptfs_write_tag_70_packet(filename->encrypted_filename, 146462306a36Sopenharmony_ci &remaining_bytes, 146562306a36Sopenharmony_ci &packet_size, 146662306a36Sopenharmony_ci mount_crypt_stat, 146762306a36Sopenharmony_ci filename->filename, 146862306a36Sopenharmony_ci filename->filename_size); 146962306a36Sopenharmony_ci if (rc) { 147062306a36Sopenharmony_ci printk(KERN_ERR "%s: Error attempting to generate " 147162306a36Sopenharmony_ci "tag 70 packet; rc = [%d]\n", __func__, 147262306a36Sopenharmony_ci rc); 147362306a36Sopenharmony_ci kfree(filename->encrypted_filename); 147462306a36Sopenharmony_ci filename->encrypted_filename = NULL; 147562306a36Sopenharmony_ci filename->encrypted_filename_size = 0; 147662306a36Sopenharmony_ci goto out; 147762306a36Sopenharmony_ci } 147862306a36Sopenharmony_ci filename->encrypted_filename_size = packet_size; 147962306a36Sopenharmony_ci } else { 148062306a36Sopenharmony_ci printk(KERN_ERR "%s: No support for requested filename " 148162306a36Sopenharmony_ci "encryption method in this release\n", __func__); 148262306a36Sopenharmony_ci rc = -EOPNOTSUPP; 148362306a36Sopenharmony_ci goto out; 148462306a36Sopenharmony_ci } 148562306a36Sopenharmony_ciout: 148662306a36Sopenharmony_ci return rc; 148762306a36Sopenharmony_ci} 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_cistatic int ecryptfs_copy_filename(char **copied_name, size_t *copied_name_size, 149062306a36Sopenharmony_ci const char *name, size_t name_size) 149162306a36Sopenharmony_ci{ 149262306a36Sopenharmony_ci int rc = 0; 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ci (*copied_name) = kmalloc((name_size + 1), GFP_KERNEL); 149562306a36Sopenharmony_ci if (!(*copied_name)) { 149662306a36Sopenharmony_ci rc = -ENOMEM; 149762306a36Sopenharmony_ci goto out; 149862306a36Sopenharmony_ci } 149962306a36Sopenharmony_ci memcpy((void *)(*copied_name), (void *)name, name_size); 150062306a36Sopenharmony_ci (*copied_name)[(name_size)] = '\0'; /* Only for convenience 150162306a36Sopenharmony_ci * in printing out the 150262306a36Sopenharmony_ci * string in debug 150362306a36Sopenharmony_ci * messages */ 150462306a36Sopenharmony_ci (*copied_name_size) = name_size; 150562306a36Sopenharmony_ciout: 150662306a36Sopenharmony_ci return rc; 150762306a36Sopenharmony_ci} 150862306a36Sopenharmony_ci 150962306a36Sopenharmony_ci/** 151062306a36Sopenharmony_ci * ecryptfs_process_key_cipher - Perform key cipher initialization. 151162306a36Sopenharmony_ci * @key_tfm: Crypto context for key material, set by this function 151262306a36Sopenharmony_ci * @cipher_name: Name of the cipher 151362306a36Sopenharmony_ci * @key_size: Size of the key in bytes 151462306a36Sopenharmony_ci * 151562306a36Sopenharmony_ci * Returns zero on success. Any crypto_tfm structs allocated here 151662306a36Sopenharmony_ci * should be released by other functions, such as on a superblock put 151762306a36Sopenharmony_ci * event, regardless of whether this function succeeds for fails. 151862306a36Sopenharmony_ci */ 151962306a36Sopenharmony_cistatic int 152062306a36Sopenharmony_ciecryptfs_process_key_cipher(struct crypto_skcipher **key_tfm, 152162306a36Sopenharmony_ci char *cipher_name, size_t *key_size) 152262306a36Sopenharmony_ci{ 152362306a36Sopenharmony_ci char dummy_key[ECRYPTFS_MAX_KEY_BYTES]; 152462306a36Sopenharmony_ci char *full_alg_name = NULL; 152562306a36Sopenharmony_ci int rc; 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci *key_tfm = NULL; 152862306a36Sopenharmony_ci if (*key_size > ECRYPTFS_MAX_KEY_BYTES) { 152962306a36Sopenharmony_ci rc = -EINVAL; 153062306a36Sopenharmony_ci printk(KERN_ERR "Requested key size is [%zd] bytes; maximum " 153162306a36Sopenharmony_ci "allowable is [%d]\n", *key_size, ECRYPTFS_MAX_KEY_BYTES); 153262306a36Sopenharmony_ci goto out; 153362306a36Sopenharmony_ci } 153462306a36Sopenharmony_ci rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, cipher_name, 153562306a36Sopenharmony_ci "ecb"); 153662306a36Sopenharmony_ci if (rc) 153762306a36Sopenharmony_ci goto out; 153862306a36Sopenharmony_ci *key_tfm = crypto_alloc_skcipher(full_alg_name, 0, CRYPTO_ALG_ASYNC); 153962306a36Sopenharmony_ci if (IS_ERR(*key_tfm)) { 154062306a36Sopenharmony_ci rc = PTR_ERR(*key_tfm); 154162306a36Sopenharmony_ci printk(KERN_ERR "Unable to allocate crypto cipher with name " 154262306a36Sopenharmony_ci "[%s]; rc = [%d]\n", full_alg_name, rc); 154362306a36Sopenharmony_ci goto out; 154462306a36Sopenharmony_ci } 154562306a36Sopenharmony_ci crypto_skcipher_set_flags(*key_tfm, CRYPTO_TFM_REQ_FORBID_WEAK_KEYS); 154662306a36Sopenharmony_ci if (*key_size == 0) 154762306a36Sopenharmony_ci *key_size = crypto_skcipher_max_keysize(*key_tfm); 154862306a36Sopenharmony_ci get_random_bytes(dummy_key, *key_size); 154962306a36Sopenharmony_ci rc = crypto_skcipher_setkey(*key_tfm, dummy_key, *key_size); 155062306a36Sopenharmony_ci if (rc) { 155162306a36Sopenharmony_ci printk(KERN_ERR "Error attempting to set key of size [%zd] for " 155262306a36Sopenharmony_ci "cipher [%s]; rc = [%d]\n", *key_size, full_alg_name, 155362306a36Sopenharmony_ci rc); 155462306a36Sopenharmony_ci rc = -EINVAL; 155562306a36Sopenharmony_ci goto out; 155662306a36Sopenharmony_ci } 155762306a36Sopenharmony_ciout: 155862306a36Sopenharmony_ci kfree(full_alg_name); 155962306a36Sopenharmony_ci return rc; 156062306a36Sopenharmony_ci} 156162306a36Sopenharmony_ci 156262306a36Sopenharmony_cistruct kmem_cache *ecryptfs_key_tfm_cache; 156362306a36Sopenharmony_cistatic struct list_head key_tfm_list; 156462306a36Sopenharmony_ciDEFINE_MUTEX(key_tfm_list_mutex); 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ciint __init ecryptfs_init_crypto(void) 156762306a36Sopenharmony_ci{ 156862306a36Sopenharmony_ci INIT_LIST_HEAD(&key_tfm_list); 156962306a36Sopenharmony_ci return 0; 157062306a36Sopenharmony_ci} 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_ci/** 157362306a36Sopenharmony_ci * ecryptfs_destroy_crypto - free all cached key_tfms on key_tfm_list 157462306a36Sopenharmony_ci * 157562306a36Sopenharmony_ci * Called only at module unload time 157662306a36Sopenharmony_ci */ 157762306a36Sopenharmony_ciint ecryptfs_destroy_crypto(void) 157862306a36Sopenharmony_ci{ 157962306a36Sopenharmony_ci struct ecryptfs_key_tfm *key_tfm, *key_tfm_tmp; 158062306a36Sopenharmony_ci 158162306a36Sopenharmony_ci mutex_lock(&key_tfm_list_mutex); 158262306a36Sopenharmony_ci list_for_each_entry_safe(key_tfm, key_tfm_tmp, &key_tfm_list, 158362306a36Sopenharmony_ci key_tfm_list) { 158462306a36Sopenharmony_ci list_del(&key_tfm->key_tfm_list); 158562306a36Sopenharmony_ci crypto_free_skcipher(key_tfm->key_tfm); 158662306a36Sopenharmony_ci kmem_cache_free(ecryptfs_key_tfm_cache, key_tfm); 158762306a36Sopenharmony_ci } 158862306a36Sopenharmony_ci mutex_unlock(&key_tfm_list_mutex); 158962306a36Sopenharmony_ci return 0; 159062306a36Sopenharmony_ci} 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ciint 159362306a36Sopenharmony_ciecryptfs_add_new_key_tfm(struct ecryptfs_key_tfm **key_tfm, char *cipher_name, 159462306a36Sopenharmony_ci size_t key_size) 159562306a36Sopenharmony_ci{ 159662306a36Sopenharmony_ci struct ecryptfs_key_tfm *tmp_tfm; 159762306a36Sopenharmony_ci int rc = 0; 159862306a36Sopenharmony_ci 159962306a36Sopenharmony_ci BUG_ON(!mutex_is_locked(&key_tfm_list_mutex)); 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_ci tmp_tfm = kmem_cache_alloc(ecryptfs_key_tfm_cache, GFP_KERNEL); 160262306a36Sopenharmony_ci if (key_tfm) 160362306a36Sopenharmony_ci (*key_tfm) = tmp_tfm; 160462306a36Sopenharmony_ci if (!tmp_tfm) { 160562306a36Sopenharmony_ci rc = -ENOMEM; 160662306a36Sopenharmony_ci goto out; 160762306a36Sopenharmony_ci } 160862306a36Sopenharmony_ci mutex_init(&tmp_tfm->key_tfm_mutex); 160962306a36Sopenharmony_ci strncpy(tmp_tfm->cipher_name, cipher_name, 161062306a36Sopenharmony_ci ECRYPTFS_MAX_CIPHER_NAME_SIZE); 161162306a36Sopenharmony_ci tmp_tfm->cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE] = '\0'; 161262306a36Sopenharmony_ci tmp_tfm->key_size = key_size; 161362306a36Sopenharmony_ci rc = ecryptfs_process_key_cipher(&tmp_tfm->key_tfm, 161462306a36Sopenharmony_ci tmp_tfm->cipher_name, 161562306a36Sopenharmony_ci &tmp_tfm->key_size); 161662306a36Sopenharmony_ci if (rc) { 161762306a36Sopenharmony_ci printk(KERN_ERR "Error attempting to initialize key TFM " 161862306a36Sopenharmony_ci "cipher with name = [%s]; rc = [%d]\n", 161962306a36Sopenharmony_ci tmp_tfm->cipher_name, rc); 162062306a36Sopenharmony_ci kmem_cache_free(ecryptfs_key_tfm_cache, tmp_tfm); 162162306a36Sopenharmony_ci if (key_tfm) 162262306a36Sopenharmony_ci (*key_tfm) = NULL; 162362306a36Sopenharmony_ci goto out; 162462306a36Sopenharmony_ci } 162562306a36Sopenharmony_ci list_add(&tmp_tfm->key_tfm_list, &key_tfm_list); 162662306a36Sopenharmony_ciout: 162762306a36Sopenharmony_ci return rc; 162862306a36Sopenharmony_ci} 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_ci/** 163162306a36Sopenharmony_ci * ecryptfs_tfm_exists - Search for existing tfm for cipher_name. 163262306a36Sopenharmony_ci * @cipher_name: the name of the cipher to search for 163362306a36Sopenharmony_ci * @key_tfm: set to corresponding tfm if found 163462306a36Sopenharmony_ci * 163562306a36Sopenharmony_ci * Searches for cached key_tfm matching @cipher_name 163662306a36Sopenharmony_ci * Must be called with &key_tfm_list_mutex held 163762306a36Sopenharmony_ci * Returns 1 if found, with @key_tfm set 163862306a36Sopenharmony_ci * Returns 0 if not found, with @key_tfm set to NULL 163962306a36Sopenharmony_ci */ 164062306a36Sopenharmony_ciint ecryptfs_tfm_exists(char *cipher_name, struct ecryptfs_key_tfm **key_tfm) 164162306a36Sopenharmony_ci{ 164262306a36Sopenharmony_ci struct ecryptfs_key_tfm *tmp_key_tfm; 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ci BUG_ON(!mutex_is_locked(&key_tfm_list_mutex)); 164562306a36Sopenharmony_ci 164662306a36Sopenharmony_ci list_for_each_entry(tmp_key_tfm, &key_tfm_list, key_tfm_list) { 164762306a36Sopenharmony_ci if (strcmp(tmp_key_tfm->cipher_name, cipher_name) == 0) { 164862306a36Sopenharmony_ci if (key_tfm) 164962306a36Sopenharmony_ci (*key_tfm) = tmp_key_tfm; 165062306a36Sopenharmony_ci return 1; 165162306a36Sopenharmony_ci } 165262306a36Sopenharmony_ci } 165362306a36Sopenharmony_ci if (key_tfm) 165462306a36Sopenharmony_ci (*key_tfm) = NULL; 165562306a36Sopenharmony_ci return 0; 165662306a36Sopenharmony_ci} 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci/** 165962306a36Sopenharmony_ci * ecryptfs_get_tfm_and_mutex_for_cipher_name 166062306a36Sopenharmony_ci * 166162306a36Sopenharmony_ci * @tfm: set to cached tfm found, or new tfm created 166262306a36Sopenharmony_ci * @tfm_mutex: set to mutex for cached tfm found, or new tfm created 166362306a36Sopenharmony_ci * @cipher_name: the name of the cipher to search for and/or add 166462306a36Sopenharmony_ci * 166562306a36Sopenharmony_ci * Sets pointers to @tfm & @tfm_mutex matching @cipher_name. 166662306a36Sopenharmony_ci * Searches for cached item first, and creates new if not found. 166762306a36Sopenharmony_ci * Returns 0 on success, non-zero if adding new cipher failed 166862306a36Sopenharmony_ci */ 166962306a36Sopenharmony_ciint ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_skcipher **tfm, 167062306a36Sopenharmony_ci struct mutex **tfm_mutex, 167162306a36Sopenharmony_ci char *cipher_name) 167262306a36Sopenharmony_ci{ 167362306a36Sopenharmony_ci struct ecryptfs_key_tfm *key_tfm; 167462306a36Sopenharmony_ci int rc = 0; 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_ci (*tfm) = NULL; 167762306a36Sopenharmony_ci (*tfm_mutex) = NULL; 167862306a36Sopenharmony_ci 167962306a36Sopenharmony_ci mutex_lock(&key_tfm_list_mutex); 168062306a36Sopenharmony_ci if (!ecryptfs_tfm_exists(cipher_name, &key_tfm)) { 168162306a36Sopenharmony_ci rc = ecryptfs_add_new_key_tfm(&key_tfm, cipher_name, 0); 168262306a36Sopenharmony_ci if (rc) { 168362306a36Sopenharmony_ci printk(KERN_ERR "Error adding new key_tfm to list; " 168462306a36Sopenharmony_ci "rc = [%d]\n", rc); 168562306a36Sopenharmony_ci goto out; 168662306a36Sopenharmony_ci } 168762306a36Sopenharmony_ci } 168862306a36Sopenharmony_ci (*tfm) = key_tfm->key_tfm; 168962306a36Sopenharmony_ci (*tfm_mutex) = &key_tfm->key_tfm_mutex; 169062306a36Sopenharmony_ciout: 169162306a36Sopenharmony_ci mutex_unlock(&key_tfm_list_mutex); 169262306a36Sopenharmony_ci return rc; 169362306a36Sopenharmony_ci} 169462306a36Sopenharmony_ci 169562306a36Sopenharmony_ci/* 64 characters forming a 6-bit target field */ 169662306a36Sopenharmony_cistatic unsigned char *portable_filename_chars = ("-.0123456789ABCD" 169762306a36Sopenharmony_ci "EFGHIJKLMNOPQRST" 169862306a36Sopenharmony_ci "UVWXYZabcdefghij" 169962306a36Sopenharmony_ci "klmnopqrstuvwxyz"); 170062306a36Sopenharmony_ci 170162306a36Sopenharmony_ci/* We could either offset on every reverse map or just pad some 0x00's 170262306a36Sopenharmony_ci * at the front here */ 170362306a36Sopenharmony_cistatic const unsigned char filename_rev_map[256] = { 170462306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */ 170562306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 15 */ 170662306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */ 170762306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 31 */ 170862306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 39 */ 170962306a36Sopenharmony_ci 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, /* 47 */ 171062306a36Sopenharmony_ci 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, /* 55 */ 171162306a36Sopenharmony_ci 0x0A, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 63 */ 171262306a36Sopenharmony_ci 0x00, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, /* 71 */ 171362306a36Sopenharmony_ci 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, /* 79 */ 171462306a36Sopenharmony_ci 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, /* 87 */ 171562306a36Sopenharmony_ci 0x23, 0x24, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, /* 95 */ 171662306a36Sopenharmony_ci 0x00, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, /* 103 */ 171762306a36Sopenharmony_ci 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, /* 111 */ 171862306a36Sopenharmony_ci 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, /* 119 */ 171962306a36Sopenharmony_ci 0x3D, 0x3E, 0x3F /* 123 - 255 initialized to 0x00 */ 172062306a36Sopenharmony_ci}; 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_ci/** 172362306a36Sopenharmony_ci * ecryptfs_encode_for_filename 172462306a36Sopenharmony_ci * @dst: Destination location for encoded filename 172562306a36Sopenharmony_ci * @dst_size: Size of the encoded filename in bytes 172662306a36Sopenharmony_ci * @src: Source location for the filename to encode 172762306a36Sopenharmony_ci * @src_size: Size of the source in bytes 172862306a36Sopenharmony_ci */ 172962306a36Sopenharmony_cistatic void ecryptfs_encode_for_filename(unsigned char *dst, size_t *dst_size, 173062306a36Sopenharmony_ci unsigned char *src, size_t src_size) 173162306a36Sopenharmony_ci{ 173262306a36Sopenharmony_ci size_t num_blocks; 173362306a36Sopenharmony_ci size_t block_num = 0; 173462306a36Sopenharmony_ci size_t dst_offset = 0; 173562306a36Sopenharmony_ci unsigned char last_block[3]; 173662306a36Sopenharmony_ci 173762306a36Sopenharmony_ci if (src_size == 0) { 173862306a36Sopenharmony_ci (*dst_size) = 0; 173962306a36Sopenharmony_ci goto out; 174062306a36Sopenharmony_ci } 174162306a36Sopenharmony_ci num_blocks = (src_size / 3); 174262306a36Sopenharmony_ci if ((src_size % 3) == 0) { 174362306a36Sopenharmony_ci memcpy(last_block, (&src[src_size - 3]), 3); 174462306a36Sopenharmony_ci } else { 174562306a36Sopenharmony_ci num_blocks++; 174662306a36Sopenharmony_ci last_block[2] = 0x00; 174762306a36Sopenharmony_ci switch (src_size % 3) { 174862306a36Sopenharmony_ci case 1: 174962306a36Sopenharmony_ci last_block[0] = src[src_size - 1]; 175062306a36Sopenharmony_ci last_block[1] = 0x00; 175162306a36Sopenharmony_ci break; 175262306a36Sopenharmony_ci case 2: 175362306a36Sopenharmony_ci last_block[0] = src[src_size - 2]; 175462306a36Sopenharmony_ci last_block[1] = src[src_size - 1]; 175562306a36Sopenharmony_ci } 175662306a36Sopenharmony_ci } 175762306a36Sopenharmony_ci (*dst_size) = (num_blocks * 4); 175862306a36Sopenharmony_ci if (!dst) 175962306a36Sopenharmony_ci goto out; 176062306a36Sopenharmony_ci while (block_num < num_blocks) { 176162306a36Sopenharmony_ci unsigned char *src_block; 176262306a36Sopenharmony_ci unsigned char dst_block[4]; 176362306a36Sopenharmony_ci 176462306a36Sopenharmony_ci if (block_num == (num_blocks - 1)) 176562306a36Sopenharmony_ci src_block = last_block; 176662306a36Sopenharmony_ci else 176762306a36Sopenharmony_ci src_block = &src[block_num * 3]; 176862306a36Sopenharmony_ci dst_block[0] = ((src_block[0] >> 2) & 0x3F); 176962306a36Sopenharmony_ci dst_block[1] = (((src_block[0] << 4) & 0x30) 177062306a36Sopenharmony_ci | ((src_block[1] >> 4) & 0x0F)); 177162306a36Sopenharmony_ci dst_block[2] = (((src_block[1] << 2) & 0x3C) 177262306a36Sopenharmony_ci | ((src_block[2] >> 6) & 0x03)); 177362306a36Sopenharmony_ci dst_block[3] = (src_block[2] & 0x3F); 177462306a36Sopenharmony_ci dst[dst_offset++] = portable_filename_chars[dst_block[0]]; 177562306a36Sopenharmony_ci dst[dst_offset++] = portable_filename_chars[dst_block[1]]; 177662306a36Sopenharmony_ci dst[dst_offset++] = portable_filename_chars[dst_block[2]]; 177762306a36Sopenharmony_ci dst[dst_offset++] = portable_filename_chars[dst_block[3]]; 177862306a36Sopenharmony_ci block_num++; 177962306a36Sopenharmony_ci } 178062306a36Sopenharmony_ciout: 178162306a36Sopenharmony_ci return; 178262306a36Sopenharmony_ci} 178362306a36Sopenharmony_ci 178462306a36Sopenharmony_cistatic size_t ecryptfs_max_decoded_size(size_t encoded_size) 178562306a36Sopenharmony_ci{ 178662306a36Sopenharmony_ci /* Not exact; conservatively long. Every block of 4 178762306a36Sopenharmony_ci * encoded characters decodes into a block of 3 178862306a36Sopenharmony_ci * decoded characters. This segment of code provides 178962306a36Sopenharmony_ci * the caller with the maximum amount of allocated 179062306a36Sopenharmony_ci * space that @dst will need to point to in a 179162306a36Sopenharmony_ci * subsequent call. */ 179262306a36Sopenharmony_ci return ((encoded_size + 1) * 3) / 4; 179362306a36Sopenharmony_ci} 179462306a36Sopenharmony_ci 179562306a36Sopenharmony_ci/** 179662306a36Sopenharmony_ci * ecryptfs_decode_from_filename 179762306a36Sopenharmony_ci * @dst: If NULL, this function only sets @dst_size and returns. If 179862306a36Sopenharmony_ci * non-NULL, this function decodes the encoded octets in @src 179962306a36Sopenharmony_ci * into the memory that @dst points to. 180062306a36Sopenharmony_ci * @dst_size: Set to the size of the decoded string. 180162306a36Sopenharmony_ci * @src: The encoded set of octets to decode. 180262306a36Sopenharmony_ci * @src_size: The size of the encoded set of octets to decode. 180362306a36Sopenharmony_ci */ 180462306a36Sopenharmony_cistatic void 180562306a36Sopenharmony_ciecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size, 180662306a36Sopenharmony_ci const unsigned char *src, size_t src_size) 180762306a36Sopenharmony_ci{ 180862306a36Sopenharmony_ci u8 current_bit_offset = 0; 180962306a36Sopenharmony_ci size_t src_byte_offset = 0; 181062306a36Sopenharmony_ci size_t dst_byte_offset = 0; 181162306a36Sopenharmony_ci 181262306a36Sopenharmony_ci if (!dst) { 181362306a36Sopenharmony_ci (*dst_size) = ecryptfs_max_decoded_size(src_size); 181462306a36Sopenharmony_ci goto out; 181562306a36Sopenharmony_ci } 181662306a36Sopenharmony_ci while (src_byte_offset < src_size) { 181762306a36Sopenharmony_ci unsigned char src_byte = 181862306a36Sopenharmony_ci filename_rev_map[(int)src[src_byte_offset]]; 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_ci switch (current_bit_offset) { 182162306a36Sopenharmony_ci case 0: 182262306a36Sopenharmony_ci dst[dst_byte_offset] = (src_byte << 2); 182362306a36Sopenharmony_ci current_bit_offset = 6; 182462306a36Sopenharmony_ci break; 182562306a36Sopenharmony_ci case 6: 182662306a36Sopenharmony_ci dst[dst_byte_offset++] |= (src_byte >> 4); 182762306a36Sopenharmony_ci dst[dst_byte_offset] = ((src_byte & 0xF) 182862306a36Sopenharmony_ci << 4); 182962306a36Sopenharmony_ci current_bit_offset = 4; 183062306a36Sopenharmony_ci break; 183162306a36Sopenharmony_ci case 4: 183262306a36Sopenharmony_ci dst[dst_byte_offset++] |= (src_byte >> 2); 183362306a36Sopenharmony_ci dst[dst_byte_offset] = (src_byte << 6); 183462306a36Sopenharmony_ci current_bit_offset = 2; 183562306a36Sopenharmony_ci break; 183662306a36Sopenharmony_ci case 2: 183762306a36Sopenharmony_ci dst[dst_byte_offset++] |= (src_byte); 183862306a36Sopenharmony_ci current_bit_offset = 0; 183962306a36Sopenharmony_ci break; 184062306a36Sopenharmony_ci } 184162306a36Sopenharmony_ci src_byte_offset++; 184262306a36Sopenharmony_ci } 184362306a36Sopenharmony_ci (*dst_size) = dst_byte_offset; 184462306a36Sopenharmony_ciout: 184562306a36Sopenharmony_ci return; 184662306a36Sopenharmony_ci} 184762306a36Sopenharmony_ci 184862306a36Sopenharmony_ci/** 184962306a36Sopenharmony_ci * ecryptfs_encrypt_and_encode_filename - converts a plaintext file name to cipher text 185062306a36Sopenharmony_ci * @encoded_name: The encrypted name 185162306a36Sopenharmony_ci * @encoded_name_size: Length of the encrypted name 185262306a36Sopenharmony_ci * @mount_crypt_stat: The crypt_stat struct associated with the file name to encode 185362306a36Sopenharmony_ci * @name: The plaintext name 185462306a36Sopenharmony_ci * @name_size: The length of the plaintext name 185562306a36Sopenharmony_ci * 185662306a36Sopenharmony_ci * Encrypts and encodes a filename into something that constitutes a 185762306a36Sopenharmony_ci * valid filename for a filesystem, with printable characters. 185862306a36Sopenharmony_ci * 185962306a36Sopenharmony_ci * We assume that we have a properly initialized crypto context, 186062306a36Sopenharmony_ci * pointed to by crypt_stat->tfm. 186162306a36Sopenharmony_ci * 186262306a36Sopenharmony_ci * Returns zero on success; non-zero on otherwise 186362306a36Sopenharmony_ci */ 186462306a36Sopenharmony_ciint ecryptfs_encrypt_and_encode_filename( 186562306a36Sopenharmony_ci char **encoded_name, 186662306a36Sopenharmony_ci size_t *encoded_name_size, 186762306a36Sopenharmony_ci struct ecryptfs_mount_crypt_stat *mount_crypt_stat, 186862306a36Sopenharmony_ci const char *name, size_t name_size) 186962306a36Sopenharmony_ci{ 187062306a36Sopenharmony_ci size_t encoded_name_no_prefix_size; 187162306a36Sopenharmony_ci int rc = 0; 187262306a36Sopenharmony_ci 187362306a36Sopenharmony_ci (*encoded_name) = NULL; 187462306a36Sopenharmony_ci (*encoded_name_size) = 0; 187562306a36Sopenharmony_ci if (mount_crypt_stat && (mount_crypt_stat->flags 187662306a36Sopenharmony_ci & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)) { 187762306a36Sopenharmony_ci struct ecryptfs_filename *filename; 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_ci filename = kzalloc(sizeof(*filename), GFP_KERNEL); 188062306a36Sopenharmony_ci if (!filename) { 188162306a36Sopenharmony_ci rc = -ENOMEM; 188262306a36Sopenharmony_ci goto out; 188362306a36Sopenharmony_ci } 188462306a36Sopenharmony_ci filename->filename = (char *)name; 188562306a36Sopenharmony_ci filename->filename_size = name_size; 188662306a36Sopenharmony_ci rc = ecryptfs_encrypt_filename(filename, mount_crypt_stat); 188762306a36Sopenharmony_ci if (rc) { 188862306a36Sopenharmony_ci printk(KERN_ERR "%s: Error attempting to encrypt " 188962306a36Sopenharmony_ci "filename; rc = [%d]\n", __func__, rc); 189062306a36Sopenharmony_ci kfree(filename); 189162306a36Sopenharmony_ci goto out; 189262306a36Sopenharmony_ci } 189362306a36Sopenharmony_ci ecryptfs_encode_for_filename( 189462306a36Sopenharmony_ci NULL, &encoded_name_no_prefix_size, 189562306a36Sopenharmony_ci filename->encrypted_filename, 189662306a36Sopenharmony_ci filename->encrypted_filename_size); 189762306a36Sopenharmony_ci if (mount_crypt_stat 189862306a36Sopenharmony_ci && (mount_crypt_stat->flags 189962306a36Sopenharmony_ci & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK)) 190062306a36Sopenharmony_ci (*encoded_name_size) = 190162306a36Sopenharmony_ci (ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE 190262306a36Sopenharmony_ci + encoded_name_no_prefix_size); 190362306a36Sopenharmony_ci else 190462306a36Sopenharmony_ci (*encoded_name_size) = 190562306a36Sopenharmony_ci (ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX_SIZE 190662306a36Sopenharmony_ci + encoded_name_no_prefix_size); 190762306a36Sopenharmony_ci (*encoded_name) = kmalloc((*encoded_name_size) + 1, GFP_KERNEL); 190862306a36Sopenharmony_ci if (!(*encoded_name)) { 190962306a36Sopenharmony_ci rc = -ENOMEM; 191062306a36Sopenharmony_ci kfree(filename->encrypted_filename); 191162306a36Sopenharmony_ci kfree(filename); 191262306a36Sopenharmony_ci goto out; 191362306a36Sopenharmony_ci } 191462306a36Sopenharmony_ci if (mount_crypt_stat 191562306a36Sopenharmony_ci && (mount_crypt_stat->flags 191662306a36Sopenharmony_ci & ECRYPTFS_GLOBAL_ENCFN_USE_MOUNT_FNEK)) { 191762306a36Sopenharmony_ci memcpy((*encoded_name), 191862306a36Sopenharmony_ci ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX, 191962306a36Sopenharmony_ci ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE); 192062306a36Sopenharmony_ci ecryptfs_encode_for_filename( 192162306a36Sopenharmony_ci ((*encoded_name) 192262306a36Sopenharmony_ci + ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE), 192362306a36Sopenharmony_ci &encoded_name_no_prefix_size, 192462306a36Sopenharmony_ci filename->encrypted_filename, 192562306a36Sopenharmony_ci filename->encrypted_filename_size); 192662306a36Sopenharmony_ci (*encoded_name_size) = 192762306a36Sopenharmony_ci (ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE 192862306a36Sopenharmony_ci + encoded_name_no_prefix_size); 192962306a36Sopenharmony_ci (*encoded_name)[(*encoded_name_size)] = '\0'; 193062306a36Sopenharmony_ci } else { 193162306a36Sopenharmony_ci rc = -EOPNOTSUPP; 193262306a36Sopenharmony_ci } 193362306a36Sopenharmony_ci if (rc) { 193462306a36Sopenharmony_ci printk(KERN_ERR "%s: Error attempting to encode " 193562306a36Sopenharmony_ci "encrypted filename; rc = [%d]\n", __func__, 193662306a36Sopenharmony_ci rc); 193762306a36Sopenharmony_ci kfree((*encoded_name)); 193862306a36Sopenharmony_ci (*encoded_name) = NULL; 193962306a36Sopenharmony_ci (*encoded_name_size) = 0; 194062306a36Sopenharmony_ci } 194162306a36Sopenharmony_ci kfree(filename->encrypted_filename); 194262306a36Sopenharmony_ci kfree(filename); 194362306a36Sopenharmony_ci } else { 194462306a36Sopenharmony_ci rc = ecryptfs_copy_filename(encoded_name, 194562306a36Sopenharmony_ci encoded_name_size, 194662306a36Sopenharmony_ci name, name_size); 194762306a36Sopenharmony_ci } 194862306a36Sopenharmony_ciout: 194962306a36Sopenharmony_ci return rc; 195062306a36Sopenharmony_ci} 195162306a36Sopenharmony_ci 195262306a36Sopenharmony_cistatic bool is_dot_dotdot(const char *name, size_t name_size) 195362306a36Sopenharmony_ci{ 195462306a36Sopenharmony_ci if (name_size == 1 && name[0] == '.') 195562306a36Sopenharmony_ci return true; 195662306a36Sopenharmony_ci else if (name_size == 2 && name[0] == '.' && name[1] == '.') 195762306a36Sopenharmony_ci return true; 195862306a36Sopenharmony_ci 195962306a36Sopenharmony_ci return false; 196062306a36Sopenharmony_ci} 196162306a36Sopenharmony_ci 196262306a36Sopenharmony_ci/** 196362306a36Sopenharmony_ci * ecryptfs_decode_and_decrypt_filename - converts the encoded cipher text name to decoded plaintext 196462306a36Sopenharmony_ci * @plaintext_name: The plaintext name 196562306a36Sopenharmony_ci * @plaintext_name_size: The plaintext name size 196662306a36Sopenharmony_ci * @sb: Ecryptfs's super_block 196762306a36Sopenharmony_ci * @name: The filename in cipher text 196862306a36Sopenharmony_ci * @name_size: The cipher text name size 196962306a36Sopenharmony_ci * 197062306a36Sopenharmony_ci * Decrypts and decodes the filename. 197162306a36Sopenharmony_ci * 197262306a36Sopenharmony_ci * Returns zero on error; non-zero otherwise 197362306a36Sopenharmony_ci */ 197462306a36Sopenharmony_ciint ecryptfs_decode_and_decrypt_filename(char **plaintext_name, 197562306a36Sopenharmony_ci size_t *plaintext_name_size, 197662306a36Sopenharmony_ci struct super_block *sb, 197762306a36Sopenharmony_ci const char *name, size_t name_size) 197862306a36Sopenharmony_ci{ 197962306a36Sopenharmony_ci struct ecryptfs_mount_crypt_stat *mount_crypt_stat = 198062306a36Sopenharmony_ci &ecryptfs_superblock_to_private(sb)->mount_crypt_stat; 198162306a36Sopenharmony_ci char *decoded_name; 198262306a36Sopenharmony_ci size_t decoded_name_size; 198362306a36Sopenharmony_ci size_t packet_size; 198462306a36Sopenharmony_ci int rc = 0; 198562306a36Sopenharmony_ci 198662306a36Sopenharmony_ci if ((mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) && 198762306a36Sopenharmony_ci !(mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)) { 198862306a36Sopenharmony_ci if (is_dot_dotdot(name, name_size)) { 198962306a36Sopenharmony_ci rc = ecryptfs_copy_filename(plaintext_name, 199062306a36Sopenharmony_ci plaintext_name_size, 199162306a36Sopenharmony_ci name, name_size); 199262306a36Sopenharmony_ci goto out; 199362306a36Sopenharmony_ci } 199462306a36Sopenharmony_ci 199562306a36Sopenharmony_ci if (name_size <= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE || 199662306a36Sopenharmony_ci strncmp(name, ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX, 199762306a36Sopenharmony_ci ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE)) { 199862306a36Sopenharmony_ci rc = -EINVAL; 199962306a36Sopenharmony_ci goto out; 200062306a36Sopenharmony_ci } 200162306a36Sopenharmony_ci 200262306a36Sopenharmony_ci name += ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE; 200362306a36Sopenharmony_ci name_size -= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE; 200462306a36Sopenharmony_ci ecryptfs_decode_from_filename(NULL, &decoded_name_size, 200562306a36Sopenharmony_ci name, name_size); 200662306a36Sopenharmony_ci decoded_name = kmalloc(decoded_name_size, GFP_KERNEL); 200762306a36Sopenharmony_ci if (!decoded_name) { 200862306a36Sopenharmony_ci rc = -ENOMEM; 200962306a36Sopenharmony_ci goto out; 201062306a36Sopenharmony_ci } 201162306a36Sopenharmony_ci ecryptfs_decode_from_filename(decoded_name, &decoded_name_size, 201262306a36Sopenharmony_ci name, name_size); 201362306a36Sopenharmony_ci rc = ecryptfs_parse_tag_70_packet(plaintext_name, 201462306a36Sopenharmony_ci plaintext_name_size, 201562306a36Sopenharmony_ci &packet_size, 201662306a36Sopenharmony_ci mount_crypt_stat, 201762306a36Sopenharmony_ci decoded_name, 201862306a36Sopenharmony_ci decoded_name_size); 201962306a36Sopenharmony_ci if (rc) { 202062306a36Sopenharmony_ci ecryptfs_printk(KERN_DEBUG, 202162306a36Sopenharmony_ci "%s: Could not parse tag 70 packet from filename\n", 202262306a36Sopenharmony_ci __func__); 202362306a36Sopenharmony_ci goto out_free; 202462306a36Sopenharmony_ci } 202562306a36Sopenharmony_ci } else { 202662306a36Sopenharmony_ci rc = ecryptfs_copy_filename(plaintext_name, 202762306a36Sopenharmony_ci plaintext_name_size, 202862306a36Sopenharmony_ci name, name_size); 202962306a36Sopenharmony_ci goto out; 203062306a36Sopenharmony_ci } 203162306a36Sopenharmony_ciout_free: 203262306a36Sopenharmony_ci kfree(decoded_name); 203362306a36Sopenharmony_ciout: 203462306a36Sopenharmony_ci return rc; 203562306a36Sopenharmony_ci} 203662306a36Sopenharmony_ci 203762306a36Sopenharmony_ci#define ENC_NAME_MAX_BLOCKLEN_8_OR_16 143 203862306a36Sopenharmony_ci 203962306a36Sopenharmony_ciint ecryptfs_set_f_namelen(long *namelen, long lower_namelen, 204062306a36Sopenharmony_ci struct ecryptfs_mount_crypt_stat *mount_crypt_stat) 204162306a36Sopenharmony_ci{ 204262306a36Sopenharmony_ci struct crypto_skcipher *tfm; 204362306a36Sopenharmony_ci struct mutex *tfm_mutex; 204462306a36Sopenharmony_ci size_t cipher_blocksize; 204562306a36Sopenharmony_ci int rc; 204662306a36Sopenharmony_ci 204762306a36Sopenharmony_ci if (!(mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)) { 204862306a36Sopenharmony_ci (*namelen) = lower_namelen; 204962306a36Sopenharmony_ci return 0; 205062306a36Sopenharmony_ci } 205162306a36Sopenharmony_ci 205262306a36Sopenharmony_ci rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&tfm, &tfm_mutex, 205362306a36Sopenharmony_ci mount_crypt_stat->global_default_fn_cipher_name); 205462306a36Sopenharmony_ci if (unlikely(rc)) { 205562306a36Sopenharmony_ci (*namelen) = 0; 205662306a36Sopenharmony_ci return rc; 205762306a36Sopenharmony_ci } 205862306a36Sopenharmony_ci 205962306a36Sopenharmony_ci mutex_lock(tfm_mutex); 206062306a36Sopenharmony_ci cipher_blocksize = crypto_skcipher_blocksize(tfm); 206162306a36Sopenharmony_ci mutex_unlock(tfm_mutex); 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ci /* Return an exact amount for the common cases */ 206462306a36Sopenharmony_ci if (lower_namelen == NAME_MAX 206562306a36Sopenharmony_ci && (cipher_blocksize == 8 || cipher_blocksize == 16)) { 206662306a36Sopenharmony_ci (*namelen) = ENC_NAME_MAX_BLOCKLEN_8_OR_16; 206762306a36Sopenharmony_ci return 0; 206862306a36Sopenharmony_ci } 206962306a36Sopenharmony_ci 207062306a36Sopenharmony_ci /* Return a safe estimate for the uncommon cases */ 207162306a36Sopenharmony_ci (*namelen) = lower_namelen; 207262306a36Sopenharmony_ci (*namelen) -= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE; 207362306a36Sopenharmony_ci /* Since this is the max decoded size, subtract 1 "decoded block" len */ 207462306a36Sopenharmony_ci (*namelen) = ecryptfs_max_decoded_size(*namelen) - 3; 207562306a36Sopenharmony_ci (*namelen) -= ECRYPTFS_TAG_70_MAX_METADATA_SIZE; 207662306a36Sopenharmony_ci (*namelen) -= ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES; 207762306a36Sopenharmony_ci /* Worst case is that the filename is padded nearly a full block size */ 207862306a36Sopenharmony_ci (*namelen) -= cipher_blocksize - 1; 207962306a36Sopenharmony_ci 208062306a36Sopenharmony_ci if ((*namelen) < 0) 208162306a36Sopenharmony_ci (*namelen) = 0; 208262306a36Sopenharmony_ci 208362306a36Sopenharmony_ci return 0; 208462306a36Sopenharmony_ci} 2085