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

📄 keystore.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key,	       auth_tok->session_key.decrypted_key_size);	crypt_stat->key_size = auth_tok->session_key.decrypted_key_size;	rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher, cipher_code);	if (rc) {		ecryptfs_printk(KERN_ERR, "Cipher code [%d] is invalid\n",				cipher_code)		goto out;	}	crypt_stat->flags |= ECRYPTFS_KEY_VALID;	if (ecryptfs_verbosity > 0) {		ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n");		ecryptfs_dump_hex(crypt_stat->key,				  crypt_stat->key_size);	}out:	if (msg)		kfree(msg);	return rc;}static void wipe_auth_tok_list(struct list_head *auth_tok_list_head){	struct ecryptfs_auth_tok_list_item *auth_tok_list_item;	struct ecryptfs_auth_tok_list_item *auth_tok_list_item_tmp;	list_for_each_entry_safe(auth_tok_list_item, auth_tok_list_item_tmp,				 auth_tok_list_head, list) {		list_del(&auth_tok_list_item->list);		kmem_cache_free(ecryptfs_auth_tok_list_item_cache,				auth_tok_list_item);	}}struct kmem_cache *ecryptfs_auth_tok_list_item_cache;/** * parse_tag_1_packet * @crypt_stat: The cryptographic context to modify based on packet contents * @data: The raw bytes of the packet. * @auth_tok_list: eCryptfs parses packets into authentication tokens; *                 a new authentication token will be placed at the *                 end of this list for this packet. * @new_auth_tok: Pointer to a pointer to memory that this function *                allocates; sets the memory address of the pointer to *                NULL on error. This object is added to the *                auth_tok_list. * @packet_size: This function writes the size of the parsed packet *               into this memory location; zero on error. * @max_packet_size: The maximum allowable packet size * * Returns zero on success; non-zero on error. */static intparse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat,		   unsigned char *data, struct list_head *auth_tok_list,		   struct ecryptfs_auth_tok **new_auth_tok,		   size_t *packet_size, size_t max_packet_size){	size_t body_size;	struct ecryptfs_auth_tok_list_item *auth_tok_list_item;	size_t length_size;	int rc = 0;	(*packet_size) = 0;	(*new_auth_tok) = NULL;	/**	 * This format is inspired by OpenPGP; see RFC 2440	 * packet tag 1	 *	 * Tag 1 identifier (1 byte)	 * Max Tag 1 packet size (max 3 bytes)	 * Version (1 byte)	 * Key identifier (8 bytes; ECRYPTFS_SIG_SIZE)	 * Cipher identifier (1 byte)	 * Encrypted key size (arbitrary)	 *	 * 12 bytes minimum packet size	 */	if (unlikely(max_packet_size < 12)) {		printk(KERN_ERR "Invalid max packet size; must be >=12\n");		rc = -EINVAL;		goto out;	}	if (data[(*packet_size)++] != ECRYPTFS_TAG_1_PACKET_TYPE) {		printk(KERN_ERR "Enter w/ first byte != 0x%.2x\n",		       ECRYPTFS_TAG_1_PACKET_TYPE);		rc = -EINVAL;		goto out;	}	/* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or	 * at end of function upon failure */	auth_tok_list_item =		kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache,				  GFP_KERNEL);	if (!auth_tok_list_item) {		printk(KERN_ERR "Unable to allocate memory\n");		rc = -ENOMEM;		goto out;	}	(*new_auth_tok) = &auth_tok_list_item->auth_tok;	rc = parse_packet_length(&data[(*packet_size)], &body_size,				 &length_size);	if (rc) {		printk(KERN_WARNING "Error parsing packet length; "		       "rc = [%d]\n", rc);		goto out_free;	}	if (unlikely(body_size < (ECRYPTFS_SIG_SIZE + 2))) {		printk(KERN_WARNING "Invalid body size ([%td])\n", body_size);		rc = -EINVAL;		goto out_free;	}	(*packet_size) += length_size;	if (unlikely((*packet_size) + body_size > max_packet_size)) {		printk(KERN_WARNING "Packet size exceeds max\n");		rc = -EINVAL;		goto out_free;	}	if (unlikely(data[(*packet_size)++] != 0x03)) {		printk(KERN_WARNING "Unknown version number [%d]\n",		       data[(*packet_size) - 1]);		rc = -EINVAL;		goto out_free;	}	ecryptfs_to_hex((*new_auth_tok)->token.private_key.signature,			&data[(*packet_size)], ECRYPTFS_SIG_SIZE);	*packet_size += ECRYPTFS_SIG_SIZE;	/* This byte is skipped because the kernel does not need to	 * know which public key encryption algorithm was used */	(*packet_size)++;	(*new_auth_tok)->session_key.encrypted_key_size =		body_size - (ECRYPTFS_SIG_SIZE + 2);	if ((*new_auth_tok)->session_key.encrypted_key_size	    > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {		printk(KERN_WARNING "Tag 1 packet contains key larger "		       "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES");		rc = -EINVAL;		goto out;	}	memcpy((*new_auth_tok)->session_key.encrypted_key,	       &data[(*packet_size)], (body_size - (ECRYPTFS_SIG_SIZE + 2)));	(*packet_size) += (*new_auth_tok)->session_key.encrypted_key_size;	(*new_auth_tok)->session_key.flags &=		~ECRYPTFS_CONTAINS_DECRYPTED_KEY;	(*new_auth_tok)->session_key.flags |=		ECRYPTFS_CONTAINS_ENCRYPTED_KEY;	(*new_auth_tok)->token_type = ECRYPTFS_PRIVATE_KEY;	(*new_auth_tok)->flags = 0;	(*new_auth_tok)->session_key.flags &=		~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);	(*new_auth_tok)->session_key.flags &=		~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);	list_add(&auth_tok_list_item->list, auth_tok_list);	goto out;out_free:	(*new_auth_tok) = NULL;	memset(auth_tok_list_item, 0,	       sizeof(struct ecryptfs_auth_tok_list_item));	kmem_cache_free(ecryptfs_auth_tok_list_item_cache,			auth_tok_list_item);out:	if (rc)		(*packet_size) = 0;	return rc;}/** * parse_tag_3_packet * @crypt_stat: The cryptographic context to modify based on packet *              contents. * @data: The raw bytes of the packet. * @auth_tok_list: eCryptfs parses packets into authentication tokens; *                 a new authentication token will be placed at the end *                 of this list for this packet. * @new_auth_tok: Pointer to a pointer to memory that this function *                allocates; sets the memory address of the pointer to *                NULL on error. This object is added to the *                auth_tok_list. * @packet_size: This function writes the size of the parsed packet *               into this memory location; zero on error. * @max_packet_size: maximum number of bytes to parse * * Returns zero on success; non-zero on error. */static intparse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,		   unsigned char *data, struct list_head *auth_tok_list,		   struct ecryptfs_auth_tok **new_auth_tok,		   size_t *packet_size, size_t max_packet_size){	size_t body_size;	struct ecryptfs_auth_tok_list_item *auth_tok_list_item;	size_t length_size;	int rc = 0;	(*packet_size) = 0;	(*new_auth_tok) = NULL;	/**	 *This format is inspired by OpenPGP; see RFC 2440	 * packet tag 3	 *	 * Tag 3 identifier (1 byte)	 * Max Tag 3 packet size (max 3 bytes)	 * Version (1 byte)	 * Cipher code (1 byte)	 * S2K specifier (1 byte)	 * Hash identifier (1 byte)	 * Salt (ECRYPTFS_SALT_SIZE)	 * Hash iterations (1 byte)	 * Encrypted key (arbitrary)	 *	 * (ECRYPTFS_SALT_SIZE + 7) minimum packet size	 */	if (max_packet_size < (ECRYPTFS_SALT_SIZE + 7)) {		printk(KERN_ERR "Max packet size too large\n");		rc = -EINVAL;		goto out;	}	if (data[(*packet_size)++] != ECRYPTFS_TAG_3_PACKET_TYPE) {		printk(KERN_ERR "First byte != 0x%.2x; invalid packet\n",		       ECRYPTFS_TAG_3_PACKET_TYPE);		rc = -EINVAL;		goto out;	}	/* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or	 * at end of function upon failure */	auth_tok_list_item =	    kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL);	if (!auth_tok_list_item) {		printk(KERN_ERR "Unable to allocate memory\n");		rc = -ENOMEM;		goto out;	}	(*new_auth_tok) = &auth_tok_list_item->auth_tok;	rc = parse_packet_length(&data[(*packet_size)], &body_size,				 &length_size);	if (rc) {		printk(KERN_WARNING "Error parsing packet length; rc = [%d]\n",		       rc);		goto out_free;	}	if (unlikely(body_size < (ECRYPTFS_SALT_SIZE + 5))) {		printk(KERN_WARNING "Invalid body size ([%td])\n", body_size);		rc = -EINVAL;		goto out_free;	}	(*packet_size) += length_size;	if (unlikely((*packet_size) + body_size > max_packet_size)) {		printk(KERN_ERR "Packet size exceeds max\n");		rc = -EINVAL;		goto out_free;	}	(*new_auth_tok)->session_key.encrypted_key_size =		(body_size - (ECRYPTFS_SALT_SIZE + 5));	if (unlikely(data[(*packet_size)++] != 0x04)) {		printk(KERN_WARNING "Unknown version number [%d]\n",		       data[(*packet_size) - 1]);		rc = -EINVAL;		goto out_free;	}	ecryptfs_cipher_code_to_string(crypt_stat->cipher,				       (u16)data[(*packet_size)]);	/* A little extra work to differentiate among the AES key	 * sizes; see RFC2440 */	switch(data[(*packet_size)++]) {	case RFC2440_CIPHER_AES_192:		crypt_stat->key_size = 24;		break;	default:		crypt_stat->key_size =			(*new_auth_tok)->session_key.encrypted_key_size;	}	ecryptfs_init_crypt_ctx(crypt_stat);	if (unlikely(data[(*packet_size)++] != 0x03)) {		printk(KERN_WARNING "Only S2K ID 3 is currently supported\n");		rc = -ENOSYS;		goto out_free;	}	/* TODO: finish the hash mapping */	switch (data[(*packet_size)++]) {	case 0x01: /* See RFC2440 for these numbers and their mappings */		/* Choose MD5 */		memcpy((*new_auth_tok)->token.password.salt,		       &data[(*packet_size)], ECRYPTFS_SALT_SIZE);		(*packet_size) += ECRYPTFS_SALT_SIZE;		/* This conversion was taken straight from RFC2440 */		(*new_auth_tok)->token.password.hash_iterations =			((u32) 16 + (data[(*packet_size)] & 15))				<< ((data[(*packet_size)] >> 4) + 6);		(*packet_size)++;		/* Friendly reminder:		 * (*new_auth_tok)->session_key.encrypted_key_size =		 *         (body_size - (ECRYPTFS_SALT_SIZE + 5)); */		memcpy((*new_auth_tok)->session_key.encrypted_key,		       &data[(*packet_size)],		       (*new_auth_tok)->session_key.encrypted_key_size);		(*packet_size) +=			(*new_auth_tok)->session_key.encrypted_key_size;		(*new_auth_tok)->session_key.flags &=			~ECRYPTFS_CONTAINS_DECRYPTED_KEY;		(*new_auth_tok)->session_key.flags |=			ECRYPTFS_CONTAINS_ENCRYPTED_KEY;		(*new_auth_tok)->token.password.hash_algo = 0x01; /* MD5 */		break;	default:		ecryptfs_printk(KERN_ERR, "Unsupported hash algorithm: "				"[%d]\n", data[(*packet_size) - 1]);		rc = -ENOSYS;		goto out_free;	}	(*new_auth_tok)->token_type = ECRYPTFS_PASSWORD;	/* TODO: Parametarize; we might actually want userspace to	 * decrypt the session key. */	(*new_auth_tok)->session_key.flags &=			    ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);	(*new_auth_tok)->session_key.flags &=			    ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);	list_add(&auth_tok_list_item->list, auth_tok_list);	goto out;out_free:	(*new_auth_tok) = NULL;	memset(auth_tok_list_item, 0,	       sizeof(struct ecryptfs_auth_tok_list_item));	kmem_cache_free(ecryptfs_auth_tok_list_item_cache,			auth_tok_list_item);out:	if (rc)		(*packet_size) = 0;	return rc;}/** * parse_tag_11_packet * @data: The raw bytes of the packet * @contents: This function writes the data contents of the literal *            packet into this memory location * @max_contents_bytes: The maximum number of bytes that this function *                      is allowed to write into contents * @tag_11_contents_size: This function writes the size of the parsed *                        contents into this memory location; zero on *                        error * @packet_size: This function writes the size of the parsed packet *               into this memory location; zero on error * @max_packet_size: maximum number of bytes to parse * * Returns zero on success; non-zero on error. */static intparse_tag_11_packet(unsigned char *data, unsigned char *contents,		    size_t max_contents_bytes, size_t *tag_11_contents_size,		    size_t *packet_size, size_t max_packet_size){	size_t body_size;	size_t length_size;	int rc = 0;	(*packet_size) = 0;	(*tag_11_contents_size) = 0;	/* This format is inspired by OpenPGP; see RFC 2440	 * packet tag 11	 *	 * Tag 11 identifier (1 byte)	 * Max Tag 11 packet size (max 3 bytes)	 * Binary format specifier (1 byte)	 * Filename length (1 byte)	 * Filename ("_CONSOLE") (8 bytes)	 * Modification date (4 bytes)	 * Literal data (arbitrary)	 *	 * We need at least 16 bytes of data for the packet to even be	 * valid.	 */	if (max_packet_size < 16) {		printk(KERN_ERR "Maximum packet size too small\n");		rc = -EINVAL;		goto out;	}	if (data[(*packet_size)++] != ECRYPTFS_TAG_11_PACKET_TYPE) {		printk(KERN_WARNING "Invalid tag 11 packet format\n");		rc = -EINVAL;		goto out;	}	rc = parse_packet_length(&data[(*packet_size)], &body_size,				 &length_size);	if (rc) {		printk(KERN_WARNING "Invalid tag 11 packet format\n");		goto out;	}	if (body_size < 14) {		printk(KERN_WARNING "Invalid body size ([%td])\n", body_size);		rc = -EINVAL;		goto out;	}	(*packet_size) += length_size;	(*tag_11_contents_size) = (body_size - 14);	if (unlikely((*packet_size) + body_size + 1 > max_packet_size)) {		printk(KERN_ERR "Packet size exceeds max\n");		rc = -EINVAL;		goto out;	}	if (data[(*packet_size)++] != 0x62) {		printk(KERN_WARNING "Unrecognizable packet\n");		rc = -EINVAL;		goto out;	}	if (data[(*packet_size)++] != 0x08) {		printk(KERN_WARNING "Unrecognizable packet\n");		rc = -EINVAL;		goto out;	}	(*packet_size) += 12; /* Ignore filename and modification date */	memcpy(contents, &data[(*packet_size)], (*tag_11_contents_size));	(*packet_size) += (*tag_11_contents_size);out:	if (rc) {		(*packet_size) = 0;		(*tag_11_contents_size) = 0;	}	return rc;}static intecryptfs_find_global_auth_tok_for_sig(	struct ecryptfs_global_auth_tok **global_auth_tok,	struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig){	struct ecryptfs_global_auth_tok *walker;	int rc = 0;	(*global_auth_tok) = NULL;	mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);	list_for_each_entry(walker,			    &mount_crypt_stat->global_auth_tok_list,			    mount_crypt_stat_list) {		if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX) == 0) {			(*global_auth_tok) = walker;			goto out;		}	}	rc = -EINVAL;out:	mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);	return rc;}/** * ecryptfs_verify_version * @version: The version number to confirm * * Returns zero on good version; non-zero otherwise */static int ecryptfs_verify_version(u16 version){	int rc = 0;	unsigned char major;	unsigned char minor;	major = ((version >> 8) & 0xFF);	minor = (version & 0xFF);	if (major != ECRYPTFS_VERSION_MAJOR) {		ecryptfs_printk(KERN_ERR, "Major version number mismatch. "				"Expected [%d]; got [%d]\n",				ECRYPTFS_VERSION_MAJOR, major);		rc = -EINVAL;		goto out;	}	if (minor != ECRYPTFS_VERSION_MINOR) {		ecryptfs_printk(KERN_ERR, "Minor version number mismatch. "				"Expected [%d]; got [%d]\n",				ECRYPTFS_VERSION_MINOR, minor);

⌨️ 快捷键说明

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