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

📄 crypto.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
static void ecryptfs_set_default_crypt_stat_vals(	struct ecryptfs_crypt_stat *crypt_stat,	struct ecryptfs_mount_crypt_stat *mount_crypt_stat){	ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,						      mount_crypt_stat);	ecryptfs_set_default_sizes(crypt_stat);	strcpy(crypt_stat->cipher, ECRYPTFS_DEFAULT_CIPHER);	crypt_stat->key_size = ECRYPTFS_DEFAULT_KEY_BYTES;	crypt_stat->flags &= ~(ECRYPTFS_KEY_VALID);	crypt_stat->file_version = ECRYPTFS_FILE_VERSION;	crypt_stat->mount_crypt_stat = mount_crypt_stat;}/** * ecryptfs_new_file_context * @ecryptfs_dentry: The eCryptfs dentry * * If the crypto context for the file has not yet been established, * this is where we do that.  Establishing a new crypto context * involves the following decisions: *  - What cipher to use? *  - What set of authentication tokens to use? * Here we just worry about getting enough information into the * authentication tokens so that we know that they are available. * We associate the available authentication tokens with the new file * via the set of signatures in the crypt_stat struct.  Later, when * the headers are actually written out, we may again defer to * userspace to perform the encryption of the session key; for the * foreseeable future, this will be the case with public key packets. * * Returns zero on success; non-zero otherwise */int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry){	struct ecryptfs_crypt_stat *crypt_stat =	    &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;	struct ecryptfs_mount_crypt_stat *mount_crypt_stat =	    &ecryptfs_superblock_to_private(		    ecryptfs_dentry->d_sb)->mount_crypt_stat;	int cipher_name_len;	int rc = 0;	ecryptfs_set_default_crypt_stat_vals(crypt_stat, mount_crypt_stat);	crypt_stat->flags |= (ECRYPTFS_ENCRYPTED | ECRYPTFS_KEY_VALID);	ecryptfs_copy_mount_wide_flags_to_inode_flags(crypt_stat,						      mount_crypt_stat);	rc = ecryptfs_copy_mount_wide_sigs_to_inode_sigs(crypt_stat,							 mount_crypt_stat);	if (rc) {		printk(KERN_ERR "Error attempting to copy mount-wide key sigs "		       "to the inode key sigs; rc = [%d]\n", rc);		goto out;	}	cipher_name_len =		strlen(mount_crypt_stat->global_default_cipher_name);	memcpy(crypt_stat->cipher,	       mount_crypt_stat->global_default_cipher_name,	       cipher_name_len);	crypt_stat->cipher[cipher_name_len] = '\0';	crypt_stat->key_size =		mount_crypt_stat->global_default_cipher_key_size;	ecryptfs_generate_new_key(crypt_stat);	rc = ecryptfs_init_crypt_ctx(crypt_stat);	if (rc)		ecryptfs_printk(KERN_ERR, "Error initializing cryptographic "				"context for cipher [%s]: rc = [%d]\n",				crypt_stat->cipher, rc);out:	return rc;}/** * contains_ecryptfs_marker - check for the ecryptfs marker * @data: The data block in which to check * * Returns one if marker found; zero if not found */static int contains_ecryptfs_marker(char *data){	u32 m_1, m_2;	memcpy(&m_1, data, 4);	m_1 = be32_to_cpu(m_1);	memcpy(&m_2, (data + 4), 4);	m_2 = be32_to_cpu(m_2);	if ((m_1 ^ MAGIC_ECRYPTFS_MARKER) == m_2)		return 1;	ecryptfs_printk(KERN_DEBUG, "m_1 = [0x%.8x]; m_2 = [0x%.8x]; "			"MAGIC_ECRYPTFS_MARKER = [0x%.8x]\n", m_1, m_2,			MAGIC_ECRYPTFS_MARKER);	ecryptfs_printk(KERN_DEBUG, "(m_1 ^ MAGIC_ECRYPTFS_MARKER) = "			"[0x%.8x]\n", (m_1 ^ MAGIC_ECRYPTFS_MARKER));	return 0;}struct ecryptfs_flag_map_elem {	u32 file_flag;	u32 local_flag;};/* Add support for additional flags by adding elements here. */static struct ecryptfs_flag_map_elem ecryptfs_flag_map[] = {	{0x00000001, ECRYPTFS_ENABLE_HMAC},	{0x00000002, ECRYPTFS_ENCRYPTED},	{0x00000004, ECRYPTFS_METADATA_IN_XATTR}};/** * ecryptfs_process_flags * @crypt_stat: The cryptographic context * @page_virt: Source data to be parsed * @bytes_read: Updated with the number of bytes read * * Returns zero on success; non-zero if the flag set is invalid */static int ecryptfs_process_flags(struct ecryptfs_crypt_stat *crypt_stat,				  char *page_virt, int *bytes_read){	int rc = 0;	int i;	u32 flags;	memcpy(&flags, page_virt, 4);	flags = be32_to_cpu(flags);	for (i = 0; i < ((sizeof(ecryptfs_flag_map)			  / sizeof(struct ecryptfs_flag_map_elem))); i++)		if (flags & ecryptfs_flag_map[i].file_flag) {			crypt_stat->flags |= ecryptfs_flag_map[i].local_flag;		} else			crypt_stat->flags &= ~(ecryptfs_flag_map[i].local_flag);	/* Version is in top 8 bits of the 32-bit flag vector */	crypt_stat->file_version = ((flags >> 24) & 0xFF);	(*bytes_read) = 4;	return rc;}/** * write_ecryptfs_marker * @page_virt: The pointer to in a page to begin writing the marker * @written: Number of bytes written * * Marker = 0x3c81b7f5 */static void write_ecryptfs_marker(char *page_virt, size_t *written){	u32 m_1, m_2;	get_random_bytes(&m_1, (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2));	m_2 = (m_1 ^ MAGIC_ECRYPTFS_MARKER);	m_1 = cpu_to_be32(m_1);	memcpy(page_virt, &m_1, (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2));	m_2 = cpu_to_be32(m_2);	memcpy(page_virt + (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2), &m_2,	       (MAGIC_ECRYPTFS_MARKER_SIZE_BYTES / 2));	(*written) = MAGIC_ECRYPTFS_MARKER_SIZE_BYTES;}static voidwrite_ecryptfs_flags(char *page_virt, struct ecryptfs_crypt_stat *crypt_stat,		     size_t *written){	u32 flags = 0;	int i;	for (i = 0; i < ((sizeof(ecryptfs_flag_map)			  / sizeof(struct ecryptfs_flag_map_elem))); i++)		if (crypt_stat->flags & ecryptfs_flag_map[i].local_flag)			flags |= ecryptfs_flag_map[i].file_flag;	/* Version is in top 8 bits of the 32-bit flag vector */	flags |= ((((u8)crypt_stat->file_version) << 24) & 0xFF000000);	flags = cpu_to_be32(flags);	memcpy(page_virt, &flags, 4);	(*written) = 4;}struct ecryptfs_cipher_code_str_map_elem {	char cipher_str[16];	u16 cipher_code;};/* Add support for additional ciphers by adding elements here. The * cipher_code is whatever OpenPGP applicatoins use to identify the * ciphers. List in order of probability. */static struct ecryptfs_cipher_code_str_map_elemecryptfs_cipher_code_str_map[] = {	{"aes",RFC2440_CIPHER_AES_128 },	{"blowfish", RFC2440_CIPHER_BLOWFISH},	{"des3_ede", RFC2440_CIPHER_DES3_EDE},	{"cast5", RFC2440_CIPHER_CAST_5},	{"twofish", RFC2440_CIPHER_TWOFISH},	{"cast6", RFC2440_CIPHER_CAST_6},	{"aes", RFC2440_CIPHER_AES_192},	{"aes", RFC2440_CIPHER_AES_256}};/** * ecryptfs_code_for_cipher_string * @crypt_stat: The cryptographic context * * Returns zero on no match, or the cipher code on match */u16 ecryptfs_code_for_cipher_string(struct ecryptfs_crypt_stat *crypt_stat){	int i;	u16 code = 0;	struct ecryptfs_cipher_code_str_map_elem *map =		ecryptfs_cipher_code_str_map;	if (strcmp(crypt_stat->cipher, "aes") == 0) {		switch (crypt_stat->key_size) {		case 16:			code = RFC2440_CIPHER_AES_128;			break;		case 24:			code = RFC2440_CIPHER_AES_192;			break;		case 32:			code = RFC2440_CIPHER_AES_256;		}	} else {		for (i = 0; i < ARRAY_SIZE(ecryptfs_cipher_code_str_map); i++)			if (strcmp(crypt_stat->cipher, map[i].cipher_str) == 0){				code = map[i].cipher_code;				break;			}	}	return code;}/** * ecryptfs_cipher_code_to_string * @str: Destination to write out the cipher name * @cipher_code: The code to convert to cipher name string * * Returns zero on success */int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code){	int rc = 0;	int i;	str[0] = '\0';	for (i = 0; i < ARRAY_SIZE(ecryptfs_cipher_code_str_map); i++)		if (cipher_code == ecryptfs_cipher_code_str_map[i].cipher_code)			strcpy(str, ecryptfs_cipher_code_str_map[i].cipher_str);	if (str[0] == '\0') {		ecryptfs_printk(KERN_WARNING, "Cipher code not recognized: "				"[%d]\n", cipher_code);		rc = -EINVAL;	}	return rc;}int ecryptfs_read_and_validate_header_region(char *data,					     struct inode *ecryptfs_inode){	struct ecryptfs_crypt_stat *crypt_stat =		&(ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat);	int rc;	rc = ecryptfs_read_lower(data, 0, crypt_stat->extent_size,				 ecryptfs_inode);	if (rc) {		printk(KERN_ERR "%s: Error reading header region; rc = [%d]\n",		       __FUNCTION__, rc);		goto out;	}	if (!contains_ecryptfs_marker(data + ECRYPTFS_FILE_SIZE_BYTES)) {		rc = -EINVAL;		ecryptfs_printk(KERN_DEBUG, "Valid marker not found\n");	}out:	return rc;}voidecryptfs_write_header_metadata(char *virt,			       struct ecryptfs_crypt_stat *crypt_stat,			       size_t *written){	u32 header_extent_size;	u16 num_header_extents_at_front;	header_extent_size = (u32)crypt_stat->extent_size;	num_header_extents_at_front =		(u16)crypt_stat->num_header_extents_at_front;	header_extent_size = cpu_to_be32(header_extent_size);	memcpy(virt, &header_extent_size, 4);	virt += 4;	num_header_extents_at_front = cpu_to_be16(num_header_extents_at_front);	memcpy(virt, &num_header_extents_at_front, 2);	(*written) = 6;}struct kmem_cache *ecryptfs_header_cache_0;struct kmem_cache *ecryptfs_header_cache_1;struct kmem_cache *ecryptfs_header_cache_2;/** * ecryptfs_write_headers_virt * @page_virt: The virtual address to write the headers to * @size: Set to the number of bytes written by this function * @crypt_stat: The cryptographic context * @ecryptfs_dentry: The eCryptfs dentry * * Format version: 1 * *   Header Extent: *     Octets 0-7:        Unencrypted file size (big-endian) *     Octets 8-15:       eCryptfs special marker *     Octets 16-19:      Flags *      Octet 16:         File format version number (between 0 and 255) *      Octets 17-18:     Reserved *      Octet 19:         Bit 1 (lsb): Reserved *                        Bit 2: Encrypted? *                        Bits 3-8: Reserved *     Octets 20-23:      Header extent size (big-endian) *     Octets 24-25:      Number of header extents at front of file *                        (big-endian) *     Octet  26:         Begin RFC 2440 authentication token packet set *   Data Extent 0: *     Lower data (CBC encrypted) *   Data Extent 1: *     Lower data (CBC encrypted) *   ... * * Returns zero on success */static int ecryptfs_write_headers_virt(char *page_virt, size_t *size,				       struct ecryptfs_crypt_stat *crypt_stat,				       struct dentry *ecryptfs_dentry){	int rc;	size_t written;	size_t offset;	offset = ECRYPTFS_FILE_SIZE_BYTES;	write_ecryptfs_marker((page_virt + offset), &written);	offset += written;	write_ecryptfs_flags((page_virt + offset), crypt_stat, &written);	offset += written;	ecryptfs_write_header_metadata((page_virt + offset), crypt_stat,				       &written);	offset += written;	rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat,					      ecryptfs_dentry, &written,					      PAGE_CACHE_SIZE - offset);	if (rc)		ecryptfs_printk(KERN_WARNING, "Error generating key packet "				"set; rc = [%d]\n", rc);	if (size) {		offset += written;		*size = offset;	}	return rc;}static intecryptfs_write_metadata_to_contents(struct ecryptfs_crypt_stat *crypt_stat,				    struct dentry *ecryptfs_dentry,				    char *page_virt){	int current_header_page;	int header_pages;	int rc;	rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, page_virt,				  0, PAGE_CACHE_SIZE);	if (rc) {		printk(KERN_ERR "%s: Error attempting to write header "		       "information to lower file; rc = [%d]\n", __FUNCTION__,		       rc);		goto out;	}	header_pages = ((crypt_stat->extent_size			 * crypt_stat->num_header_extents_at_front)			/ PAGE_CACHE_SIZE);	memset(page_virt, 0, PAGE_CACHE_SIZE);	current_header_page = 1;	while (current_header_page < header_pages) {		loff_t offset;		offset = (((loff_t)current_header_page) << PAGE_CACHE_SHIFT);		if ((rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode,					       page_virt, offset,					       PAGE_CACHE_SIZE))) {			printk(KERN_ERR "%s: Error attempting to write header "			       "information to lower file; rc = [%d]\n",			       __FUNCTION__, rc);			goto out;		}		current_header_page++;	}out:	return rc;}static intecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry,				 struct ecryptfs_crypt_stat *crypt_stat,				 char *page_virt, size_t size){	int rc;	rc = ecryptfs_setxattr(ecryptfs_dentry, ECRYPTFS_XATTR_NAME, page_virt,			       size, 0);	return rc;}/** * ecryptfs_write_metadata * @ecryptfs_dentry: The eCryptfs dentry * * Write the file headers out.  This will likely involve a userspace * callout, in which the session key is encrypted with one or more * public keys and/or the passphrase necessary to do the encryption is * retrieved via a prompt.  Exactly what happens at this point should * be policy-dependent. * * TODO: Support header information spanning multiple pages * * Returns zero on success; non-zero on error */int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry){	struct ecryptfs_crypt_stat *crypt_stat =		&ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;	char *page_virt;	size_t size = 0;	int rc = 0;	if (likely(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {		if (!(crypt_stat->flags & ECRYPTFS_KEY_VALID)) {			printk(KERN_ERR "Key is invalid; bailing out\n");			rc = -EINVAL;			goto out;		}	} else {		rc = -EINVAL;		ecryptfs_printk(KERN_WARNING,				"Called with crypt_stat->encrypted == 0\n");		goto out;	}	/* Released in this function */	page_virt = kmem_cache_zalloc(ecryptfs_header_cache_0, GFP_USER);	if (!page_virt) {		ecryptfs_printk(KERN_ERR, "Out of memory\n");		rc = -ENOMEM;		goto out;	}	rc = ecryptfs_write_headers_virt(page_virt, &size, crypt_stat,  					 ecryptfs_dentry);	if (unlikely(rc)) {		ecryptfs_printk(KERN_ERR, "Error whilst writing headers\n");		memset(page_virt, 0, PAGE_CACHE_SIZE);		goto out_free;	}	if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)		rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry,						      crypt_stat, page_virt,						      size);	else		rc = ecryptfs_write_metadata_to_contents(crypt_stat,							 ecryptfs_dentry,							 page_virt);	if (rc) {		printk(KERN_ERR "Error writing metadata out to lower file; "		       "rc = [%d]\n", rc);		goto out_free;	}out_free:	kmem_cache_free(ecryptfs_header_cache_0, page_virt);out:	return rc;}

⌨️ 快捷键说明

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