⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 crypto.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	loff_t extent_offset;	int rc = 0;	ecryptfs_inode = page->mapping->host;	crypt_stat =		&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);	if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {		rc = ecryptfs_write_lower_page_segment(ecryptfs_inode, page,						       0, PAGE_CACHE_SIZE);		if (rc)			printk(KERN_ERR "%s: Error attempting to copy "			       "page at index [%ld]\n", __FUNCTION__,			       page->index);		goto out;	}	enc_extent_virt = kmalloc(PAGE_CACHE_SIZE, GFP_USER);	if (!enc_extent_virt) {		rc = -ENOMEM;		ecryptfs_printk(KERN_ERR, "Error allocating memory for "				"encrypted extent\n");		goto out;	}	enc_extent_page = virt_to_page(enc_extent_virt);	for (extent_offset = 0;	     extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);	     extent_offset++) {		loff_t offset;		rc = ecryptfs_encrypt_extent(enc_extent_page, crypt_stat, page,					     extent_offset);		if (rc) {			printk(KERN_ERR "%s: Error encrypting extent; "			       "rc = [%d]\n", __FUNCTION__, rc);			goto out;		}		ecryptfs_lower_offset_for_extent(			&offset, ((((loff_t)page->index)				   * (PAGE_CACHE_SIZE				      / crypt_stat->extent_size))				  + extent_offset), crypt_stat);		rc = ecryptfs_write_lower(ecryptfs_inode, enc_extent_virt,					  offset, crypt_stat->extent_size);		if (rc) {			ecryptfs_printk(KERN_ERR, "Error attempting "					"to write lower page; rc = [%d]"					"\n", rc);			goto out;		}	}out:	kfree(enc_extent_virt);	return rc;}static int ecryptfs_decrypt_extent(struct page *page,				   struct ecryptfs_crypt_stat *crypt_stat,				   struct page *enc_extent_page,				   unsigned long extent_offset){	loff_t extent_base;	char extent_iv[ECRYPTFS_MAX_IV_BYTES];	int rc;	extent_base = (((loff_t)page->index)		       * (PAGE_CACHE_SIZE / crypt_stat->extent_size));	rc = ecryptfs_derive_iv(extent_iv, crypt_stat,				(extent_base + extent_offset));	if (rc) {		ecryptfs_printk(KERN_ERR, "Error attempting to "				"derive IV for extent [0x%.16x]; "				"rc = [%d]\n", (extent_base + extent_offset),				rc);		goto out;	}	if (unlikely(ecryptfs_verbosity > 0)) {		ecryptfs_printk(KERN_DEBUG, "Decrypting extent "				"with iv:\n");		ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);		ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "				"decryption:\n");		ecryptfs_dump_hex((char *)				  (page_address(enc_extent_page)				   + (extent_offset * crypt_stat->extent_size)),				  8);	}	rc = ecryptfs_decrypt_page_offset(crypt_stat, page,					  (extent_offset					   * crypt_stat->extent_size),					  enc_extent_page, 0,					  crypt_stat->extent_size, extent_iv);	if (rc < 0) {		printk(KERN_ERR "%s: Error attempting to decrypt to page with "		       "page->index = [%ld], extent_offset = [%ld]; "		       "rc = [%d]\n", __FUNCTION__, page->index, extent_offset,		       rc);		goto out;	}	rc = 0;	if (unlikely(ecryptfs_verbosity > 0)) {		ecryptfs_printk(KERN_DEBUG, "Decrypt extent [0x%.16x]; "				"rc = [%d]\n", (extent_base + extent_offset),				rc);		ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "				"decryption:\n");		ecryptfs_dump_hex((char *)(page_address(page)					   + (extent_offset					      * crypt_stat->extent_size)), 8);	}out:	return rc;}/** * ecryptfs_decrypt_page * @page: Page mapped from the eCryptfs inode for the file; data read *        and decrypted from the lower file will be written into this *        page * * Decrypt an eCryptfs page. This is done on a per-extent basis. Note * that eCryptfs pages may straddle the lower pages -- for instance, * if the file was created on a machine with an 8K page size * (resulting in an 8K header), and then the file is copied onto a * host with a 32K page size, then when reading page 0 of the eCryptfs * file, 24K of page 0 of the lower file will be read and decrypted, * and then 8K of page 1 of the lower file will be read and decrypted. * * Returns zero on success; negative on error */int ecryptfs_decrypt_page(struct page *page){	struct inode *ecryptfs_inode;	struct ecryptfs_crypt_stat *crypt_stat;	char *enc_extent_virt = NULL;	struct page *enc_extent_page;	unsigned long extent_offset;	int rc = 0;	ecryptfs_inode = page->mapping->host;	crypt_stat =		&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);	if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {		rc = ecryptfs_read_lower_page_segment(page, page->index, 0,						      PAGE_CACHE_SIZE,						      ecryptfs_inode);		if (rc)			printk(KERN_ERR "%s: Error attempting to copy "			       "page at index [%ld]\n", __FUNCTION__,			       page->index);		goto out;	}	enc_extent_virt = kmalloc(PAGE_CACHE_SIZE, GFP_USER);	if (!enc_extent_virt) {		rc = -ENOMEM;		ecryptfs_printk(KERN_ERR, "Error allocating memory for "				"encrypted extent\n");		goto out;	}	enc_extent_page = virt_to_page(enc_extent_virt);	for (extent_offset = 0;	     extent_offset < (PAGE_CACHE_SIZE / crypt_stat->extent_size);	     extent_offset++) {		loff_t offset;		ecryptfs_lower_offset_for_extent(			&offset, ((page->index * (PAGE_CACHE_SIZE						  / crypt_stat->extent_size))				  + extent_offset), crypt_stat);		rc = ecryptfs_read_lower(enc_extent_virt, offset,					 crypt_stat->extent_size,					 ecryptfs_inode);		if (rc) {			ecryptfs_printk(KERN_ERR, "Error attempting "					"to read lower page; rc = [%d]"					"\n", rc);			goto out;		}		rc = ecryptfs_decrypt_extent(page, crypt_stat, enc_extent_page,					     extent_offset);		if (rc) {			printk(KERN_ERR "%s: Error encrypting extent; "			       "rc = [%d]\n", __FUNCTION__, rc);			goto out;		}	}out:	kfree(enc_extent_virt);	return rc;}/** * decrypt_scatterlist * @crypt_stat: Cryptographic context * @dest_sg: The destination scatterlist to decrypt into * @src_sg: The source scatterlist to decrypt from * @size: The number of bytes to decrypt * @iv: The initialization vector to use for the decryption * * Returns the number of bytes decrypted; negative value on error */static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,			       struct scatterlist *dest_sg,			       struct scatterlist *src_sg, int size,			       unsigned char *iv){	struct blkcipher_desc desc = {		.tfm = crypt_stat->tfm,		.info = iv,		.flags = CRYPTO_TFM_REQ_MAY_SLEEP	};	int rc = 0;	/* Consider doing this once, when the file is opened */	mutex_lock(&crypt_stat->cs_tfm_mutex);	rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key,				     crypt_stat->key_size);	if (rc) {		ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n",				rc);		mutex_unlock(&crypt_stat->cs_tfm_mutex);		rc = -EINVAL;		goto out;	}	ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size);	rc = crypto_blkcipher_decrypt_iv(&desc, dest_sg, src_sg, size);	mutex_unlock(&crypt_stat->cs_tfm_mutex);	if (rc) {		ecryptfs_printk(KERN_ERR, "Error decrypting; rc = [%d]\n",				rc);		goto out;	}	rc = size;out:	return rc;}/** * ecryptfs_encrypt_page_offset * @crypt_stat: The cryptographic context * @dst_page: The page to encrypt into * @dst_offset: The offset in the page to encrypt into * @src_page: The page to encrypt from * @src_offset: The offset in the page to encrypt from * @size: The number of bytes to encrypt * @iv: The initialization vector to use for the encryption * * Returns the number of bytes encrypted */static intecryptfs_encrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,			     struct page *dst_page, int dst_offset,			     struct page *src_page, int src_offset, int size,			     unsigned char *iv){	struct scatterlist src_sg, dst_sg;	sg_init_table(&src_sg, 1);	sg_init_table(&dst_sg, 1);	sg_set_page(&src_sg, src_page, size, src_offset);	sg_set_page(&dst_sg, dst_page, size, dst_offset);	return encrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv);}/** * ecryptfs_decrypt_page_offset * @crypt_stat: The cryptographic context * @dst_page: The page to decrypt into * @dst_offset: The offset in the page to decrypt into * @src_page: The page to decrypt from * @src_offset: The offset in the page to decrypt from * @size: The number of bytes to decrypt * @iv: The initialization vector to use for the decryption * * Returns the number of bytes decrypted */static intecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat,			     struct page *dst_page, int dst_offset,			     struct page *src_page, int src_offset, int size,			     unsigned char *iv){	struct scatterlist src_sg, dst_sg;	sg_init_table(&src_sg, 1);	sg_set_page(&src_sg, src_page, size, src_offset);	sg_init_table(&dst_sg, 1);	sg_set_page(&dst_sg, dst_page, size, dst_offset);	return decrypt_scatterlist(crypt_stat, &dst_sg, &src_sg, size, iv);}#define ECRYPTFS_MAX_SCATTERLIST_LEN 4/** * ecryptfs_init_crypt_ctx * @crypt_stat: Uninitilized crypt stats structure * * Initialize the crypto context. * * TODO: Performance: Keep a cache of initialized cipher contexts; * only init if needed */int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat){	char *full_alg_name;	int rc = -EINVAL;	if (!crypt_stat->cipher) {		ecryptfs_printk(KERN_ERR, "No cipher specified\n");		goto out;	}	ecryptfs_printk(KERN_DEBUG,			"Initializing cipher [%s]; strlen = [%d]; "			"key_size_bits = [%d]\n",			crypt_stat->cipher, (int)strlen(crypt_stat->cipher),			crypt_stat->key_size << 3);	if (crypt_stat->tfm) {		rc = 0;		goto out;	}	mutex_lock(&crypt_stat->cs_tfm_mutex);	rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name,						    crypt_stat->cipher, "cbc");	if (rc)		goto out_unlock;	crypt_stat->tfm = crypto_alloc_blkcipher(full_alg_name, 0,						 CRYPTO_ALG_ASYNC);	kfree(full_alg_name);	if (IS_ERR(crypt_stat->tfm)) {		rc = PTR_ERR(crypt_stat->tfm);		ecryptfs_printk(KERN_ERR, "cryptfs: init_crypt_ctx(): "				"Error initializing cipher [%s]\n",				crypt_stat->cipher);		goto out_unlock;	}	crypto_blkcipher_set_flags(crypt_stat->tfm, CRYPTO_TFM_REQ_WEAK_KEY);	rc = 0;out_unlock:	mutex_unlock(&crypt_stat->cs_tfm_mutex);out:	return rc;}static void set_extent_mask_and_shift(struct ecryptfs_crypt_stat *crypt_stat){	int extent_size_tmp;	crypt_stat->extent_mask = 0xFFFFFFFF;	crypt_stat->extent_shift = 0;	if (crypt_stat->extent_size == 0)		return;	extent_size_tmp = crypt_stat->extent_size;	while ((extent_size_tmp & 0x01) == 0) {		extent_size_tmp >>= 1;		crypt_stat->extent_mask <<= 1;		crypt_stat->extent_shift++;	}}void ecryptfs_set_default_sizes(struct ecryptfs_crypt_stat *crypt_stat){	/* Default values; may be overwritten as we are parsing the	 * packets. */	crypt_stat->extent_size = ECRYPTFS_DEFAULT_EXTENT_SIZE;	set_extent_mask_and_shift(crypt_stat);	crypt_stat->iv_bytes = ECRYPTFS_DEFAULT_IV_BYTES;	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)		crypt_stat->num_header_extents_at_front = 0;	else {		if (PAGE_CACHE_SIZE <= ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE)			crypt_stat->num_header_extents_at_front =				(ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE				 / crypt_stat->extent_size);		else			crypt_stat->num_header_extents_at_front =				(PAGE_CACHE_SIZE / crypt_stat->extent_size);	}}/** * ecryptfs_compute_root_iv * @crypt_stats * * On error, sets the root IV to all 0's. */int ecryptfs_compute_root_iv(struct ecryptfs_crypt_stat *crypt_stat){	int rc = 0;	char dst[MD5_DIGEST_SIZE];	BUG_ON(crypt_stat->iv_bytes > MD5_DIGEST_SIZE);	BUG_ON(crypt_stat->iv_bytes <= 0);	if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {		rc = -EINVAL;		ecryptfs_printk(KERN_WARNING, "Session key not valid; "				"cannot generate root IV\n");		goto out;	}	rc = ecryptfs_calculate_md5(dst, crypt_stat, crypt_stat->key,				    crypt_stat->key_size);	if (rc) {		ecryptfs_printk(KERN_WARNING, "Error attempting to compute "				"MD5 while generating root IV\n");		goto out;	}	memcpy(crypt_stat->root_iv, dst, crypt_stat->iv_bytes);out:	if (rc) {		memset(crypt_stat->root_iv, 0, crypt_stat->iv_bytes);		crypt_stat->flags |= ECRYPTFS_SECURITY_WARNING;	}	return rc;}static void ecryptfs_generate_new_key(struct ecryptfs_crypt_stat *crypt_stat){	get_random_bytes(crypt_stat->key, crypt_stat->key_size);	crypt_stat->flags |= ECRYPTFS_KEY_VALID;	ecryptfs_compute_root_iv(crypt_stat);	if (unlikely(ecryptfs_verbosity > 0)) {		ecryptfs_printk(KERN_DEBUG, "Generated new session key:\n");		ecryptfs_dump_hex(crypt_stat->key,				  crypt_stat->key_size);	}}/** * ecryptfs_copy_mount_wide_flags_to_inode_flags * @crypt_stat: The inode's cryptographic context * @mount_crypt_stat: The mount point's cryptographic context * * This function propagates the mount-wide flags to individual inode * flags. */static void ecryptfs_copy_mount_wide_flags_to_inode_flags(	struct ecryptfs_crypt_stat *crypt_stat,	struct ecryptfs_mount_crypt_stat *mount_crypt_stat){	if (mount_crypt_stat->flags & ECRYPTFS_XATTR_METADATA_ENABLED)		crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;	if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED)		crypt_stat->flags |= ECRYPTFS_VIEW_AS_ENCRYPTED;}static int ecryptfs_copy_mount_wide_sigs_to_inode_sigs(	struct ecryptfs_crypt_stat *crypt_stat,	struct ecryptfs_mount_crypt_stat *mount_crypt_stat){	struct ecryptfs_global_auth_tok *global_auth_tok;	int rc = 0;	mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);	list_for_each_entry(global_auth_tok,			    &mount_crypt_stat->global_auth_tok_list,			    mount_crypt_stat_list) {		rc = ecryptfs_add_keysig(crypt_stat, global_auth_tok->sig);		if (rc) {			printk(KERN_ERR "Error adding keysig; rc = [%d]\n", rc);			mutex_unlock(				&mount_crypt_stat->global_auth_tok_list_mutex);			goto out;		}	}	mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);out:	return rc;}/** * ecryptfs_set_default_crypt_stat_vals * @crypt_stat: The inode's cryptographic context * @mount_crypt_stat: The mount point's cryptographic context * * Default values in the event that policy does not override them. */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -