162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * eCryptfs: Linux filesystem encryption layer
462306a36Sopenharmony_ci * In-kernel key management code.  Includes functions to parse and
562306a36Sopenharmony_ci * write authentication token-related packets with the underlying
662306a36Sopenharmony_ci * file.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Copyright (C) 2004-2006 International Business Machines Corp.
962306a36Sopenharmony_ci *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
1062306a36Sopenharmony_ci *              Michael C. Thompson <mcthomps@us.ibm.com>
1162306a36Sopenharmony_ci *              Trevor S. Highland <trevor.highland@gmail.com>
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#include <crypto/hash.h>
1562306a36Sopenharmony_ci#include <crypto/skcipher.h>
1662306a36Sopenharmony_ci#include <linux/string.h>
1762306a36Sopenharmony_ci#include <linux/pagemap.h>
1862306a36Sopenharmony_ci#include <linux/key.h>
1962306a36Sopenharmony_ci#include <linux/random.h>
2062306a36Sopenharmony_ci#include <linux/scatterlist.h>
2162306a36Sopenharmony_ci#include <linux/slab.h>
2262306a36Sopenharmony_ci#include "ecryptfs_kernel.h"
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci/*
2562306a36Sopenharmony_ci * request_key returned an error instead of a valid key address;
2662306a36Sopenharmony_ci * determine the type of error, make appropriate log entries, and
2762306a36Sopenharmony_ci * return an error code.
2862306a36Sopenharmony_ci */
2962306a36Sopenharmony_cistatic int process_request_key_err(long err_code)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	int rc = 0;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	switch (err_code) {
3462306a36Sopenharmony_ci	case -ENOKEY:
3562306a36Sopenharmony_ci		ecryptfs_printk(KERN_WARNING, "No key\n");
3662306a36Sopenharmony_ci		rc = -ENOENT;
3762306a36Sopenharmony_ci		break;
3862306a36Sopenharmony_ci	case -EKEYEXPIRED:
3962306a36Sopenharmony_ci		ecryptfs_printk(KERN_WARNING, "Key expired\n");
4062306a36Sopenharmony_ci		rc = -ETIME;
4162306a36Sopenharmony_ci		break;
4262306a36Sopenharmony_ci	case -EKEYREVOKED:
4362306a36Sopenharmony_ci		ecryptfs_printk(KERN_WARNING, "Key revoked\n");
4462306a36Sopenharmony_ci		rc = -EINVAL;
4562306a36Sopenharmony_ci		break;
4662306a36Sopenharmony_ci	default:
4762306a36Sopenharmony_ci		ecryptfs_printk(KERN_WARNING, "Unknown error code: "
4862306a36Sopenharmony_ci				"[0x%.16lx]\n", err_code);
4962306a36Sopenharmony_ci		rc = -EINVAL;
5062306a36Sopenharmony_ci	}
5162306a36Sopenharmony_ci	return rc;
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistatic int process_find_global_auth_tok_for_sig_err(int err_code)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	int rc = err_code;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	switch (err_code) {
5962306a36Sopenharmony_ci	case -ENOENT:
6062306a36Sopenharmony_ci		ecryptfs_printk(KERN_WARNING, "Missing auth tok\n");
6162306a36Sopenharmony_ci		break;
6262306a36Sopenharmony_ci	case -EINVAL:
6362306a36Sopenharmony_ci		ecryptfs_printk(KERN_WARNING, "Invalid auth tok\n");
6462306a36Sopenharmony_ci		break;
6562306a36Sopenharmony_ci	default:
6662306a36Sopenharmony_ci		rc = process_request_key_err(err_code);
6762306a36Sopenharmony_ci		break;
6862306a36Sopenharmony_ci	}
6962306a36Sopenharmony_ci	return rc;
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci/**
7362306a36Sopenharmony_ci * ecryptfs_parse_packet_length
7462306a36Sopenharmony_ci * @data: Pointer to memory containing length at offset
7562306a36Sopenharmony_ci * @size: This function writes the decoded size to this memory
7662306a36Sopenharmony_ci *        address; zero on error
7762306a36Sopenharmony_ci * @length_size: The number of bytes occupied by the encoded length
7862306a36Sopenharmony_ci *
7962306a36Sopenharmony_ci * Returns zero on success; non-zero on error
8062306a36Sopenharmony_ci */
8162306a36Sopenharmony_ciint ecryptfs_parse_packet_length(unsigned char *data, size_t *size,
8262306a36Sopenharmony_ci				 size_t *length_size)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	int rc = 0;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	(*length_size) = 0;
8762306a36Sopenharmony_ci	(*size) = 0;
8862306a36Sopenharmony_ci	if (data[0] < 192) {
8962306a36Sopenharmony_ci		/* One-byte length */
9062306a36Sopenharmony_ci		(*size) = data[0];
9162306a36Sopenharmony_ci		(*length_size) = 1;
9262306a36Sopenharmony_ci	} else if (data[0] < 224) {
9362306a36Sopenharmony_ci		/* Two-byte length */
9462306a36Sopenharmony_ci		(*size) = (data[0] - 192) * 256;
9562306a36Sopenharmony_ci		(*size) += data[1] + 192;
9662306a36Sopenharmony_ci		(*length_size) = 2;
9762306a36Sopenharmony_ci	} else if (data[0] == 255) {
9862306a36Sopenharmony_ci		/* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */
9962306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Five-byte packet length not "
10062306a36Sopenharmony_ci				"supported\n");
10162306a36Sopenharmony_ci		rc = -EINVAL;
10262306a36Sopenharmony_ci		goto out;
10362306a36Sopenharmony_ci	} else {
10462306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error parsing packet length\n");
10562306a36Sopenharmony_ci		rc = -EINVAL;
10662306a36Sopenharmony_ci		goto out;
10762306a36Sopenharmony_ci	}
10862306a36Sopenharmony_ciout:
10962306a36Sopenharmony_ci	return rc;
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci/**
11362306a36Sopenharmony_ci * ecryptfs_write_packet_length
11462306a36Sopenharmony_ci * @dest: The byte array target into which to write the length. Must
11562306a36Sopenharmony_ci *        have at least ECRYPTFS_MAX_PKT_LEN_SIZE bytes allocated.
11662306a36Sopenharmony_ci * @size: The length to write.
11762306a36Sopenharmony_ci * @packet_size_length: The number of bytes used to encode the packet
11862306a36Sopenharmony_ci *                      length is written to this address.
11962306a36Sopenharmony_ci *
12062306a36Sopenharmony_ci * Returns zero on success; non-zero on error.
12162306a36Sopenharmony_ci */
12262306a36Sopenharmony_ciint ecryptfs_write_packet_length(char *dest, size_t size,
12362306a36Sopenharmony_ci				 size_t *packet_size_length)
12462306a36Sopenharmony_ci{
12562306a36Sopenharmony_ci	int rc = 0;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	if (size < 192) {
12862306a36Sopenharmony_ci		dest[0] = size;
12962306a36Sopenharmony_ci		(*packet_size_length) = 1;
13062306a36Sopenharmony_ci	} else if (size < 65536) {
13162306a36Sopenharmony_ci		dest[0] = (((size - 192) / 256) + 192);
13262306a36Sopenharmony_ci		dest[1] = ((size - 192) % 256);
13362306a36Sopenharmony_ci		(*packet_size_length) = 2;
13462306a36Sopenharmony_ci	} else {
13562306a36Sopenharmony_ci		/* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */
13662306a36Sopenharmony_ci		rc = -EINVAL;
13762306a36Sopenharmony_ci		ecryptfs_printk(KERN_WARNING,
13862306a36Sopenharmony_ci				"Unsupported packet size: [%zd]\n", size);
13962306a36Sopenharmony_ci	}
14062306a36Sopenharmony_ci	return rc;
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_cistatic int
14462306a36Sopenharmony_ciwrite_tag_64_packet(char *signature, struct ecryptfs_session_key *session_key,
14562306a36Sopenharmony_ci		    char **packet, size_t *packet_len)
14662306a36Sopenharmony_ci{
14762306a36Sopenharmony_ci	size_t i = 0;
14862306a36Sopenharmony_ci	size_t data_len;
14962306a36Sopenharmony_ci	size_t packet_size_len;
15062306a36Sopenharmony_ci	char *message;
15162306a36Sopenharmony_ci	int rc;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	/*
15462306a36Sopenharmony_ci	 *              ***** TAG 64 Packet Format *****
15562306a36Sopenharmony_ci	 *    | Content Type                       | 1 byte       |
15662306a36Sopenharmony_ci	 *    | Key Identifier Size                | 1 or 2 bytes |
15762306a36Sopenharmony_ci	 *    | Key Identifier                     | arbitrary    |
15862306a36Sopenharmony_ci	 *    | Encrypted File Encryption Key Size | 1 or 2 bytes |
15962306a36Sopenharmony_ci	 *    | Encrypted File Encryption Key      | arbitrary    |
16062306a36Sopenharmony_ci	 */
16162306a36Sopenharmony_ci	data_len = (5 + ECRYPTFS_SIG_SIZE_HEX
16262306a36Sopenharmony_ci		    + session_key->encrypted_key_size);
16362306a36Sopenharmony_ci	*packet = kmalloc(data_len, GFP_KERNEL);
16462306a36Sopenharmony_ci	message = *packet;
16562306a36Sopenharmony_ci	if (!message) {
16662306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
16762306a36Sopenharmony_ci		rc = -ENOMEM;
16862306a36Sopenharmony_ci		goto out;
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci	message[i++] = ECRYPTFS_TAG_64_PACKET_TYPE;
17162306a36Sopenharmony_ci	rc = ecryptfs_write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
17262306a36Sopenharmony_ci					  &packet_size_len);
17362306a36Sopenharmony_ci	if (rc) {
17462306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet "
17562306a36Sopenharmony_ci				"header; cannot generate packet length\n");
17662306a36Sopenharmony_ci		goto out;
17762306a36Sopenharmony_ci	}
17862306a36Sopenharmony_ci	i += packet_size_len;
17962306a36Sopenharmony_ci	memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX);
18062306a36Sopenharmony_ci	i += ECRYPTFS_SIG_SIZE_HEX;
18162306a36Sopenharmony_ci	rc = ecryptfs_write_packet_length(&message[i],
18262306a36Sopenharmony_ci					  session_key->encrypted_key_size,
18362306a36Sopenharmony_ci					  &packet_size_len);
18462306a36Sopenharmony_ci	if (rc) {
18562306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet "
18662306a36Sopenharmony_ci				"header; cannot generate packet length\n");
18762306a36Sopenharmony_ci		goto out;
18862306a36Sopenharmony_ci	}
18962306a36Sopenharmony_ci	i += packet_size_len;
19062306a36Sopenharmony_ci	memcpy(&message[i], session_key->encrypted_key,
19162306a36Sopenharmony_ci	       session_key->encrypted_key_size);
19262306a36Sopenharmony_ci	i += session_key->encrypted_key_size;
19362306a36Sopenharmony_ci	*packet_len = i;
19462306a36Sopenharmony_ciout:
19562306a36Sopenharmony_ci	return rc;
19662306a36Sopenharmony_ci}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_cistatic int
19962306a36Sopenharmony_ciparse_tag_65_packet(struct ecryptfs_session_key *session_key, u8 *cipher_code,
20062306a36Sopenharmony_ci		    struct ecryptfs_message *msg)
20162306a36Sopenharmony_ci{
20262306a36Sopenharmony_ci	size_t i = 0;
20362306a36Sopenharmony_ci	char *data;
20462306a36Sopenharmony_ci	size_t data_len;
20562306a36Sopenharmony_ci	size_t m_size;
20662306a36Sopenharmony_ci	size_t message_len;
20762306a36Sopenharmony_ci	u16 checksum = 0;
20862306a36Sopenharmony_ci	u16 expected_checksum = 0;
20962306a36Sopenharmony_ci	int rc;
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	/*
21262306a36Sopenharmony_ci	 *              ***** TAG 65 Packet Format *****
21362306a36Sopenharmony_ci	 *         | Content Type             | 1 byte       |
21462306a36Sopenharmony_ci	 *         | Status Indicator         | 1 byte       |
21562306a36Sopenharmony_ci	 *         | File Encryption Key Size | 1 or 2 bytes |
21662306a36Sopenharmony_ci	 *         | File Encryption Key      | arbitrary    |
21762306a36Sopenharmony_ci	 */
21862306a36Sopenharmony_ci	message_len = msg->data_len;
21962306a36Sopenharmony_ci	data = msg->data;
22062306a36Sopenharmony_ci	if (message_len < 4) {
22162306a36Sopenharmony_ci		rc = -EIO;
22262306a36Sopenharmony_ci		goto out;
22362306a36Sopenharmony_ci	}
22462306a36Sopenharmony_ci	if (data[i++] != ECRYPTFS_TAG_65_PACKET_TYPE) {
22562306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Type should be ECRYPTFS_TAG_65\n");
22662306a36Sopenharmony_ci		rc = -EIO;
22762306a36Sopenharmony_ci		goto out;
22862306a36Sopenharmony_ci	}
22962306a36Sopenharmony_ci	if (data[i++]) {
23062306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Status indicator has non-zero value "
23162306a36Sopenharmony_ci				"[%d]\n", data[i-1]);
23262306a36Sopenharmony_ci		rc = -EIO;
23362306a36Sopenharmony_ci		goto out;
23462306a36Sopenharmony_ci	}
23562306a36Sopenharmony_ci	rc = ecryptfs_parse_packet_length(&data[i], &m_size, &data_len);
23662306a36Sopenharmony_ci	if (rc) {
23762306a36Sopenharmony_ci		ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
23862306a36Sopenharmony_ci				"rc = [%d]\n", rc);
23962306a36Sopenharmony_ci		goto out;
24062306a36Sopenharmony_ci	}
24162306a36Sopenharmony_ci	i += data_len;
24262306a36Sopenharmony_ci	if (message_len < (i + m_size)) {
24362306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "The message received from ecryptfsd "
24462306a36Sopenharmony_ci				"is shorter than expected\n");
24562306a36Sopenharmony_ci		rc = -EIO;
24662306a36Sopenharmony_ci		goto out;
24762306a36Sopenharmony_ci	}
24862306a36Sopenharmony_ci	if (m_size < 3) {
24962306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR,
25062306a36Sopenharmony_ci				"The decrypted key is not long enough to "
25162306a36Sopenharmony_ci				"include a cipher code and checksum\n");
25262306a36Sopenharmony_ci		rc = -EIO;
25362306a36Sopenharmony_ci		goto out;
25462306a36Sopenharmony_ci	}
25562306a36Sopenharmony_ci	*cipher_code = data[i++];
25662306a36Sopenharmony_ci	/* The decrypted key includes 1 byte cipher code and 2 byte checksum */
25762306a36Sopenharmony_ci	session_key->decrypted_key_size = m_size - 3;
25862306a36Sopenharmony_ci	if (session_key->decrypted_key_size > ECRYPTFS_MAX_KEY_BYTES) {
25962306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "key_size [%d] larger than "
26062306a36Sopenharmony_ci				"the maximum key size [%d]\n",
26162306a36Sopenharmony_ci				session_key->decrypted_key_size,
26262306a36Sopenharmony_ci				ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES);
26362306a36Sopenharmony_ci		rc = -EIO;
26462306a36Sopenharmony_ci		goto out;
26562306a36Sopenharmony_ci	}
26662306a36Sopenharmony_ci	memcpy(session_key->decrypted_key, &data[i],
26762306a36Sopenharmony_ci	       session_key->decrypted_key_size);
26862306a36Sopenharmony_ci	i += session_key->decrypted_key_size;
26962306a36Sopenharmony_ci	expected_checksum += (unsigned char)(data[i++]) << 8;
27062306a36Sopenharmony_ci	expected_checksum += (unsigned char)(data[i++]);
27162306a36Sopenharmony_ci	for (i = 0; i < session_key->decrypted_key_size; i++)
27262306a36Sopenharmony_ci		checksum += session_key->decrypted_key[i];
27362306a36Sopenharmony_ci	if (expected_checksum != checksum) {
27462306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Invalid checksum for file "
27562306a36Sopenharmony_ci				"encryption  key; expected [%x]; calculated "
27662306a36Sopenharmony_ci				"[%x]\n", expected_checksum, checksum);
27762306a36Sopenharmony_ci		rc = -EIO;
27862306a36Sopenharmony_ci	}
27962306a36Sopenharmony_ciout:
28062306a36Sopenharmony_ci	return rc;
28162306a36Sopenharmony_ci}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_cistatic int
28562306a36Sopenharmony_ciwrite_tag_66_packet(char *signature, u8 cipher_code,
28662306a36Sopenharmony_ci		    struct ecryptfs_crypt_stat *crypt_stat, char **packet,
28762306a36Sopenharmony_ci		    size_t *packet_len)
28862306a36Sopenharmony_ci{
28962306a36Sopenharmony_ci	size_t i = 0;
29062306a36Sopenharmony_ci	size_t j;
29162306a36Sopenharmony_ci	size_t data_len;
29262306a36Sopenharmony_ci	size_t checksum = 0;
29362306a36Sopenharmony_ci	size_t packet_size_len;
29462306a36Sopenharmony_ci	char *message;
29562306a36Sopenharmony_ci	int rc;
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	/*
29862306a36Sopenharmony_ci	 *              ***** TAG 66 Packet Format *****
29962306a36Sopenharmony_ci	 *         | Content Type             | 1 byte       |
30062306a36Sopenharmony_ci	 *         | Key Identifier Size      | 1 or 2 bytes |
30162306a36Sopenharmony_ci	 *         | Key Identifier           | arbitrary    |
30262306a36Sopenharmony_ci	 *         | File Encryption Key Size | 1 or 2 bytes |
30362306a36Sopenharmony_ci	 *         | File Encryption Key      | arbitrary    |
30462306a36Sopenharmony_ci	 */
30562306a36Sopenharmony_ci	data_len = (5 + ECRYPTFS_SIG_SIZE_HEX + crypt_stat->key_size);
30662306a36Sopenharmony_ci	*packet = kmalloc(data_len, GFP_KERNEL);
30762306a36Sopenharmony_ci	message = *packet;
30862306a36Sopenharmony_ci	if (!message) {
30962306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n");
31062306a36Sopenharmony_ci		rc = -ENOMEM;
31162306a36Sopenharmony_ci		goto out;
31262306a36Sopenharmony_ci	}
31362306a36Sopenharmony_ci	message[i++] = ECRYPTFS_TAG_66_PACKET_TYPE;
31462306a36Sopenharmony_ci	rc = ecryptfs_write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX,
31562306a36Sopenharmony_ci					  &packet_size_len);
31662306a36Sopenharmony_ci	if (rc) {
31762306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet "
31862306a36Sopenharmony_ci				"header; cannot generate packet length\n");
31962306a36Sopenharmony_ci		goto out;
32062306a36Sopenharmony_ci	}
32162306a36Sopenharmony_ci	i += packet_size_len;
32262306a36Sopenharmony_ci	memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX);
32362306a36Sopenharmony_ci	i += ECRYPTFS_SIG_SIZE_HEX;
32462306a36Sopenharmony_ci	/* The encrypted key includes 1 byte cipher code and 2 byte checksum */
32562306a36Sopenharmony_ci	rc = ecryptfs_write_packet_length(&message[i], crypt_stat->key_size + 3,
32662306a36Sopenharmony_ci					  &packet_size_len);
32762306a36Sopenharmony_ci	if (rc) {
32862306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet "
32962306a36Sopenharmony_ci				"header; cannot generate packet length\n");
33062306a36Sopenharmony_ci		goto out;
33162306a36Sopenharmony_ci	}
33262306a36Sopenharmony_ci	i += packet_size_len;
33362306a36Sopenharmony_ci	message[i++] = cipher_code;
33462306a36Sopenharmony_ci	memcpy(&message[i], crypt_stat->key, crypt_stat->key_size);
33562306a36Sopenharmony_ci	i += crypt_stat->key_size;
33662306a36Sopenharmony_ci	for (j = 0; j < crypt_stat->key_size; j++)
33762306a36Sopenharmony_ci		checksum += crypt_stat->key[j];
33862306a36Sopenharmony_ci	message[i++] = (checksum / 256) % 256;
33962306a36Sopenharmony_ci	message[i++] = (checksum % 256);
34062306a36Sopenharmony_ci	*packet_len = i;
34162306a36Sopenharmony_ciout:
34262306a36Sopenharmony_ci	return rc;
34362306a36Sopenharmony_ci}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_cistatic int
34662306a36Sopenharmony_ciparse_tag_67_packet(struct ecryptfs_key_record *key_rec,
34762306a36Sopenharmony_ci		    struct ecryptfs_message *msg)
34862306a36Sopenharmony_ci{
34962306a36Sopenharmony_ci	size_t i = 0;
35062306a36Sopenharmony_ci	char *data;
35162306a36Sopenharmony_ci	size_t data_len;
35262306a36Sopenharmony_ci	size_t message_len;
35362306a36Sopenharmony_ci	int rc;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	/*
35662306a36Sopenharmony_ci	 *              ***** TAG 65 Packet Format *****
35762306a36Sopenharmony_ci	 *    | Content Type                       | 1 byte       |
35862306a36Sopenharmony_ci	 *    | Status Indicator                   | 1 byte       |
35962306a36Sopenharmony_ci	 *    | Encrypted File Encryption Key Size | 1 or 2 bytes |
36062306a36Sopenharmony_ci	 *    | Encrypted File Encryption Key      | arbitrary    |
36162306a36Sopenharmony_ci	 */
36262306a36Sopenharmony_ci	message_len = msg->data_len;
36362306a36Sopenharmony_ci	data = msg->data;
36462306a36Sopenharmony_ci	/* verify that everything through the encrypted FEK size is present */
36562306a36Sopenharmony_ci	if (message_len < 4) {
36662306a36Sopenharmony_ci		rc = -EIO;
36762306a36Sopenharmony_ci		printk(KERN_ERR "%s: message_len is [%zd]; minimum acceptable "
36862306a36Sopenharmony_ci		       "message length is [%d]\n", __func__, message_len, 4);
36962306a36Sopenharmony_ci		goto out;
37062306a36Sopenharmony_ci	}
37162306a36Sopenharmony_ci	if (data[i++] != ECRYPTFS_TAG_67_PACKET_TYPE) {
37262306a36Sopenharmony_ci		rc = -EIO;
37362306a36Sopenharmony_ci		printk(KERN_ERR "%s: Type should be ECRYPTFS_TAG_67\n",
37462306a36Sopenharmony_ci		       __func__);
37562306a36Sopenharmony_ci		goto out;
37662306a36Sopenharmony_ci	}
37762306a36Sopenharmony_ci	if (data[i++]) {
37862306a36Sopenharmony_ci		rc = -EIO;
37962306a36Sopenharmony_ci		printk(KERN_ERR "%s: Status indicator has non zero "
38062306a36Sopenharmony_ci		       "value [%d]\n", __func__, data[i-1]);
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci		goto out;
38362306a36Sopenharmony_ci	}
38462306a36Sopenharmony_ci	rc = ecryptfs_parse_packet_length(&data[i], &key_rec->enc_key_size,
38562306a36Sopenharmony_ci					  &data_len);
38662306a36Sopenharmony_ci	if (rc) {
38762306a36Sopenharmony_ci		ecryptfs_printk(KERN_WARNING, "Error parsing packet length; "
38862306a36Sopenharmony_ci				"rc = [%d]\n", rc);
38962306a36Sopenharmony_ci		goto out;
39062306a36Sopenharmony_ci	}
39162306a36Sopenharmony_ci	i += data_len;
39262306a36Sopenharmony_ci	if (message_len < (i + key_rec->enc_key_size)) {
39362306a36Sopenharmony_ci		rc = -EIO;
39462306a36Sopenharmony_ci		printk(KERN_ERR "%s: message_len [%zd]; max len is [%zd]\n",
39562306a36Sopenharmony_ci		       __func__, message_len, (i + key_rec->enc_key_size));
39662306a36Sopenharmony_ci		goto out;
39762306a36Sopenharmony_ci	}
39862306a36Sopenharmony_ci	if (key_rec->enc_key_size > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
39962306a36Sopenharmony_ci		rc = -EIO;
40062306a36Sopenharmony_ci		printk(KERN_ERR "%s: Encrypted key_size [%zd] larger than "
40162306a36Sopenharmony_ci		       "the maximum key size [%d]\n", __func__,
40262306a36Sopenharmony_ci		       key_rec->enc_key_size,
40362306a36Sopenharmony_ci		       ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES);
40462306a36Sopenharmony_ci		goto out;
40562306a36Sopenharmony_ci	}
40662306a36Sopenharmony_ci	memcpy(key_rec->enc_key, &data[i], key_rec->enc_key_size);
40762306a36Sopenharmony_ciout:
40862306a36Sopenharmony_ci	return rc;
40962306a36Sopenharmony_ci}
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci/**
41262306a36Sopenharmony_ci * ecryptfs_verify_version
41362306a36Sopenharmony_ci * @version: The version number to confirm
41462306a36Sopenharmony_ci *
41562306a36Sopenharmony_ci * Returns zero on good version; non-zero otherwise
41662306a36Sopenharmony_ci */
41762306a36Sopenharmony_cistatic int ecryptfs_verify_version(u16 version)
41862306a36Sopenharmony_ci{
41962306a36Sopenharmony_ci	int rc = 0;
42062306a36Sopenharmony_ci	unsigned char major;
42162306a36Sopenharmony_ci	unsigned char minor;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	major = ((version >> 8) & 0xFF);
42462306a36Sopenharmony_ci	minor = (version & 0xFF);
42562306a36Sopenharmony_ci	if (major != ECRYPTFS_VERSION_MAJOR) {
42662306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Major version number mismatch. "
42762306a36Sopenharmony_ci				"Expected [%d]; got [%d]\n",
42862306a36Sopenharmony_ci				ECRYPTFS_VERSION_MAJOR, major);
42962306a36Sopenharmony_ci		rc = -EINVAL;
43062306a36Sopenharmony_ci		goto out;
43162306a36Sopenharmony_ci	}
43262306a36Sopenharmony_ci	if (minor != ECRYPTFS_VERSION_MINOR) {
43362306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Minor version number mismatch. "
43462306a36Sopenharmony_ci				"Expected [%d]; got [%d]\n",
43562306a36Sopenharmony_ci				ECRYPTFS_VERSION_MINOR, minor);
43662306a36Sopenharmony_ci		rc = -EINVAL;
43762306a36Sopenharmony_ci		goto out;
43862306a36Sopenharmony_ci	}
43962306a36Sopenharmony_ciout:
44062306a36Sopenharmony_ci	return rc;
44162306a36Sopenharmony_ci}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci/**
44462306a36Sopenharmony_ci * ecryptfs_verify_auth_tok_from_key
44562306a36Sopenharmony_ci * @auth_tok_key: key containing the authentication token
44662306a36Sopenharmony_ci * @auth_tok: authentication token
44762306a36Sopenharmony_ci *
44862306a36Sopenharmony_ci * Returns zero on valid auth tok; -EINVAL if the payload is invalid; or
44962306a36Sopenharmony_ci * -EKEYREVOKED if the key was revoked before we acquired its semaphore.
45062306a36Sopenharmony_ci */
45162306a36Sopenharmony_cistatic int
45262306a36Sopenharmony_ciecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key,
45362306a36Sopenharmony_ci				  struct ecryptfs_auth_tok **auth_tok)
45462306a36Sopenharmony_ci{
45562306a36Sopenharmony_ci	int rc = 0;
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci	(*auth_tok) = ecryptfs_get_key_payload_data(auth_tok_key);
45862306a36Sopenharmony_ci	if (IS_ERR(*auth_tok)) {
45962306a36Sopenharmony_ci		rc = PTR_ERR(*auth_tok);
46062306a36Sopenharmony_ci		*auth_tok = NULL;
46162306a36Sopenharmony_ci		goto out;
46262306a36Sopenharmony_ci	}
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	if (ecryptfs_verify_version((*auth_tok)->version)) {
46562306a36Sopenharmony_ci		printk(KERN_ERR "Data structure version mismatch. Userspace "
46662306a36Sopenharmony_ci		       "tools must match eCryptfs kernel module with major "
46762306a36Sopenharmony_ci		       "version [%d] and minor version [%d]\n",
46862306a36Sopenharmony_ci		       ECRYPTFS_VERSION_MAJOR, ECRYPTFS_VERSION_MINOR);
46962306a36Sopenharmony_ci		rc = -EINVAL;
47062306a36Sopenharmony_ci		goto out;
47162306a36Sopenharmony_ci	}
47262306a36Sopenharmony_ci	if ((*auth_tok)->token_type != ECRYPTFS_PASSWORD
47362306a36Sopenharmony_ci	    && (*auth_tok)->token_type != ECRYPTFS_PRIVATE_KEY) {
47462306a36Sopenharmony_ci		printk(KERN_ERR "Invalid auth_tok structure "
47562306a36Sopenharmony_ci		       "returned from key query\n");
47662306a36Sopenharmony_ci		rc = -EINVAL;
47762306a36Sopenharmony_ci		goto out;
47862306a36Sopenharmony_ci	}
47962306a36Sopenharmony_ciout:
48062306a36Sopenharmony_ci	return rc;
48162306a36Sopenharmony_ci}
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_cistatic int
48462306a36Sopenharmony_ciecryptfs_find_global_auth_tok_for_sig(
48562306a36Sopenharmony_ci	struct key **auth_tok_key,
48662306a36Sopenharmony_ci	struct ecryptfs_auth_tok **auth_tok,
48762306a36Sopenharmony_ci	struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig)
48862306a36Sopenharmony_ci{
48962306a36Sopenharmony_ci	struct ecryptfs_global_auth_tok *walker;
49062306a36Sopenharmony_ci	int rc = 0;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	(*auth_tok_key) = NULL;
49362306a36Sopenharmony_ci	(*auth_tok) = NULL;
49462306a36Sopenharmony_ci	mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
49562306a36Sopenharmony_ci	list_for_each_entry(walker,
49662306a36Sopenharmony_ci			    &mount_crypt_stat->global_auth_tok_list,
49762306a36Sopenharmony_ci			    mount_crypt_stat_list) {
49862306a36Sopenharmony_ci		if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX))
49962306a36Sopenharmony_ci			continue;
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci		if (walker->flags & ECRYPTFS_AUTH_TOK_INVALID) {
50262306a36Sopenharmony_ci			rc = -EINVAL;
50362306a36Sopenharmony_ci			goto out;
50462306a36Sopenharmony_ci		}
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci		rc = key_validate(walker->global_auth_tok_key);
50762306a36Sopenharmony_ci		if (rc) {
50862306a36Sopenharmony_ci			if (rc == -EKEYEXPIRED)
50962306a36Sopenharmony_ci				goto out;
51062306a36Sopenharmony_ci			goto out_invalid_auth_tok;
51162306a36Sopenharmony_ci		}
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci		down_write(&(walker->global_auth_tok_key->sem));
51462306a36Sopenharmony_ci		rc = ecryptfs_verify_auth_tok_from_key(
51562306a36Sopenharmony_ci				walker->global_auth_tok_key, auth_tok);
51662306a36Sopenharmony_ci		if (rc)
51762306a36Sopenharmony_ci			goto out_invalid_auth_tok_unlock;
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci		(*auth_tok_key) = walker->global_auth_tok_key;
52062306a36Sopenharmony_ci		key_get(*auth_tok_key);
52162306a36Sopenharmony_ci		goto out;
52262306a36Sopenharmony_ci	}
52362306a36Sopenharmony_ci	rc = -ENOENT;
52462306a36Sopenharmony_ci	goto out;
52562306a36Sopenharmony_ciout_invalid_auth_tok_unlock:
52662306a36Sopenharmony_ci	up_write(&(walker->global_auth_tok_key->sem));
52762306a36Sopenharmony_ciout_invalid_auth_tok:
52862306a36Sopenharmony_ci	printk(KERN_WARNING "Invalidating auth tok with sig = [%s]\n", sig);
52962306a36Sopenharmony_ci	walker->flags |= ECRYPTFS_AUTH_TOK_INVALID;
53062306a36Sopenharmony_ci	key_put(walker->global_auth_tok_key);
53162306a36Sopenharmony_ci	walker->global_auth_tok_key = NULL;
53262306a36Sopenharmony_ciout:
53362306a36Sopenharmony_ci	mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
53462306a36Sopenharmony_ci	return rc;
53562306a36Sopenharmony_ci}
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci/**
53862306a36Sopenharmony_ci * ecryptfs_find_auth_tok_for_sig
53962306a36Sopenharmony_ci * @auth_tok_key: key containing the authentication token
54062306a36Sopenharmony_ci * @auth_tok: Set to the matching auth_tok; NULL if not found
54162306a36Sopenharmony_ci * @mount_crypt_stat: inode crypt_stat crypto context
54262306a36Sopenharmony_ci * @sig: Sig of auth_tok to find
54362306a36Sopenharmony_ci *
54462306a36Sopenharmony_ci * For now, this function simply looks at the registered auth_tok's
54562306a36Sopenharmony_ci * linked off the mount_crypt_stat, so all the auth_toks that can be
54662306a36Sopenharmony_ci * used must be registered at mount time. This function could
54762306a36Sopenharmony_ci * potentially try a lot harder to find auth_tok's (e.g., by calling
54862306a36Sopenharmony_ci * out to ecryptfsd to dynamically retrieve an auth_tok object) so
54962306a36Sopenharmony_ci * that static registration of auth_tok's will no longer be necessary.
55062306a36Sopenharmony_ci *
55162306a36Sopenharmony_ci * Returns zero on no error; non-zero on error
55262306a36Sopenharmony_ci */
55362306a36Sopenharmony_cistatic int
55462306a36Sopenharmony_ciecryptfs_find_auth_tok_for_sig(
55562306a36Sopenharmony_ci	struct key **auth_tok_key,
55662306a36Sopenharmony_ci	struct ecryptfs_auth_tok **auth_tok,
55762306a36Sopenharmony_ci	struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
55862306a36Sopenharmony_ci	char *sig)
55962306a36Sopenharmony_ci{
56062306a36Sopenharmony_ci	int rc = 0;
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	rc = ecryptfs_find_global_auth_tok_for_sig(auth_tok_key, auth_tok,
56362306a36Sopenharmony_ci						   mount_crypt_stat, sig);
56462306a36Sopenharmony_ci	if (rc == -ENOENT) {
56562306a36Sopenharmony_ci		/* if the flag ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY is set in the
56662306a36Sopenharmony_ci		 * mount_crypt_stat structure, we prevent to use auth toks that
56762306a36Sopenharmony_ci		 * are not inserted through the ecryptfs_add_global_auth_tok
56862306a36Sopenharmony_ci		 * function.
56962306a36Sopenharmony_ci		 */
57062306a36Sopenharmony_ci		if (mount_crypt_stat->flags
57162306a36Sopenharmony_ci				& ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY)
57262306a36Sopenharmony_ci			return -EINVAL;
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci		rc = ecryptfs_keyring_auth_tok_for_sig(auth_tok_key, auth_tok,
57562306a36Sopenharmony_ci						       sig);
57662306a36Sopenharmony_ci	}
57762306a36Sopenharmony_ci	return rc;
57862306a36Sopenharmony_ci}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci/*
58162306a36Sopenharmony_ci * write_tag_70_packet can gobble a lot of stack space. We stuff most
58262306a36Sopenharmony_ci * of the function's parameters in a kmalloc'd struct to help reduce
58362306a36Sopenharmony_ci * eCryptfs' overall stack usage.
58462306a36Sopenharmony_ci */
58562306a36Sopenharmony_cistruct ecryptfs_write_tag_70_packet_silly_stack {
58662306a36Sopenharmony_ci	u8 cipher_code;
58762306a36Sopenharmony_ci	size_t max_packet_size;
58862306a36Sopenharmony_ci	size_t packet_size_len;
58962306a36Sopenharmony_ci	size_t block_aligned_filename_size;
59062306a36Sopenharmony_ci	size_t block_size;
59162306a36Sopenharmony_ci	size_t i;
59262306a36Sopenharmony_ci	size_t j;
59362306a36Sopenharmony_ci	size_t num_rand_bytes;
59462306a36Sopenharmony_ci	struct mutex *tfm_mutex;
59562306a36Sopenharmony_ci	char *block_aligned_filename;
59662306a36Sopenharmony_ci	struct ecryptfs_auth_tok *auth_tok;
59762306a36Sopenharmony_ci	struct scatterlist src_sg[2];
59862306a36Sopenharmony_ci	struct scatterlist dst_sg[2];
59962306a36Sopenharmony_ci	struct crypto_skcipher *skcipher_tfm;
60062306a36Sopenharmony_ci	struct skcipher_request *skcipher_req;
60162306a36Sopenharmony_ci	char iv[ECRYPTFS_MAX_IV_BYTES];
60262306a36Sopenharmony_ci	char hash[ECRYPTFS_TAG_70_DIGEST_SIZE];
60362306a36Sopenharmony_ci	char tmp_hash[ECRYPTFS_TAG_70_DIGEST_SIZE];
60462306a36Sopenharmony_ci	struct crypto_shash *hash_tfm;
60562306a36Sopenharmony_ci	struct shash_desc *hash_desc;
60662306a36Sopenharmony_ci};
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci/*
60962306a36Sopenharmony_ci * write_tag_70_packet - Write encrypted filename (EFN) packet against FNEK
61062306a36Sopenharmony_ci * @filename: NULL-terminated filename string
61162306a36Sopenharmony_ci *
61262306a36Sopenharmony_ci * This is the simplest mechanism for achieving filename encryption in
61362306a36Sopenharmony_ci * eCryptfs. It encrypts the given filename with the mount-wide
61462306a36Sopenharmony_ci * filename encryption key (FNEK) and stores it in a packet to @dest,
61562306a36Sopenharmony_ci * which the callee will encode and write directly into the dentry
61662306a36Sopenharmony_ci * name.
61762306a36Sopenharmony_ci */
61862306a36Sopenharmony_ciint
61962306a36Sopenharmony_ciecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
62062306a36Sopenharmony_ci			     size_t *packet_size,
62162306a36Sopenharmony_ci			     struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
62262306a36Sopenharmony_ci			     char *filename, size_t filename_size)
62362306a36Sopenharmony_ci{
62462306a36Sopenharmony_ci	struct ecryptfs_write_tag_70_packet_silly_stack *s;
62562306a36Sopenharmony_ci	struct key *auth_tok_key = NULL;
62662306a36Sopenharmony_ci	int rc = 0;
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	s = kzalloc(sizeof(*s), GFP_KERNEL);
62962306a36Sopenharmony_ci	if (!s)
63062306a36Sopenharmony_ci		return -ENOMEM;
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	(*packet_size) = 0;
63362306a36Sopenharmony_ci	rc = ecryptfs_find_auth_tok_for_sig(
63462306a36Sopenharmony_ci		&auth_tok_key,
63562306a36Sopenharmony_ci		&s->auth_tok, mount_crypt_stat,
63662306a36Sopenharmony_ci		mount_crypt_stat->global_default_fnek_sig);
63762306a36Sopenharmony_ci	if (rc) {
63862306a36Sopenharmony_ci		printk(KERN_ERR "%s: Error attempting to find auth tok for "
63962306a36Sopenharmony_ci		       "fnek sig [%s]; rc = [%d]\n", __func__,
64062306a36Sopenharmony_ci		       mount_crypt_stat->global_default_fnek_sig, rc);
64162306a36Sopenharmony_ci		goto out;
64262306a36Sopenharmony_ci	}
64362306a36Sopenharmony_ci	rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(
64462306a36Sopenharmony_ci		&s->skcipher_tfm,
64562306a36Sopenharmony_ci		&s->tfm_mutex, mount_crypt_stat->global_default_fn_cipher_name);
64662306a36Sopenharmony_ci	if (unlikely(rc)) {
64762306a36Sopenharmony_ci		printk(KERN_ERR "Internal error whilst attempting to get "
64862306a36Sopenharmony_ci		       "tfm and mutex for cipher name [%s]; rc = [%d]\n",
64962306a36Sopenharmony_ci		       mount_crypt_stat->global_default_fn_cipher_name, rc);
65062306a36Sopenharmony_ci		goto out;
65162306a36Sopenharmony_ci	}
65262306a36Sopenharmony_ci	mutex_lock(s->tfm_mutex);
65362306a36Sopenharmony_ci	s->block_size = crypto_skcipher_blocksize(s->skcipher_tfm);
65462306a36Sopenharmony_ci	/* Plus one for the \0 separator between the random prefix
65562306a36Sopenharmony_ci	 * and the plaintext filename */
65662306a36Sopenharmony_ci	s->num_rand_bytes = (ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES + 1);
65762306a36Sopenharmony_ci	s->block_aligned_filename_size = (s->num_rand_bytes + filename_size);
65862306a36Sopenharmony_ci	if ((s->block_aligned_filename_size % s->block_size) != 0) {
65962306a36Sopenharmony_ci		s->num_rand_bytes += (s->block_size
66062306a36Sopenharmony_ci				      - (s->block_aligned_filename_size
66162306a36Sopenharmony_ci					 % s->block_size));
66262306a36Sopenharmony_ci		s->block_aligned_filename_size = (s->num_rand_bytes
66362306a36Sopenharmony_ci						  + filename_size);
66462306a36Sopenharmony_ci	}
66562306a36Sopenharmony_ci	/* Octet 0: Tag 70 identifier
66662306a36Sopenharmony_ci	 * Octets 1-N1: Tag 70 packet size (includes cipher identifier
66762306a36Sopenharmony_ci	 *              and block-aligned encrypted filename size)
66862306a36Sopenharmony_ci	 * Octets N1-N2: FNEK sig (ECRYPTFS_SIG_SIZE)
66962306a36Sopenharmony_ci	 * Octet N2-N3: Cipher identifier (1 octet)
67062306a36Sopenharmony_ci	 * Octets N3-N4: Block-aligned encrypted filename
67162306a36Sopenharmony_ci	 *  - Consists of a minimum number of random characters, a \0
67262306a36Sopenharmony_ci	 *    separator, and then the filename */
67362306a36Sopenharmony_ci	s->max_packet_size = (ECRYPTFS_TAG_70_MAX_METADATA_SIZE
67462306a36Sopenharmony_ci			      + s->block_aligned_filename_size);
67562306a36Sopenharmony_ci	if (!dest) {
67662306a36Sopenharmony_ci		(*packet_size) = s->max_packet_size;
67762306a36Sopenharmony_ci		goto out_unlock;
67862306a36Sopenharmony_ci	}
67962306a36Sopenharmony_ci	if (s->max_packet_size > (*remaining_bytes)) {
68062306a36Sopenharmony_ci		printk(KERN_WARNING "%s: Require [%zd] bytes to write; only "
68162306a36Sopenharmony_ci		       "[%zd] available\n", __func__, s->max_packet_size,
68262306a36Sopenharmony_ci		       (*remaining_bytes));
68362306a36Sopenharmony_ci		rc = -EINVAL;
68462306a36Sopenharmony_ci		goto out_unlock;
68562306a36Sopenharmony_ci	}
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	s->skcipher_req = skcipher_request_alloc(s->skcipher_tfm, GFP_KERNEL);
68862306a36Sopenharmony_ci	if (!s->skcipher_req) {
68962306a36Sopenharmony_ci		printk(KERN_ERR "%s: Out of kernel memory whilst attempting to "
69062306a36Sopenharmony_ci		       "skcipher_request_alloc for %s\n", __func__,
69162306a36Sopenharmony_ci		       crypto_skcipher_driver_name(s->skcipher_tfm));
69262306a36Sopenharmony_ci		rc = -ENOMEM;
69362306a36Sopenharmony_ci		goto out_unlock;
69462306a36Sopenharmony_ci	}
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	skcipher_request_set_callback(s->skcipher_req,
69762306a36Sopenharmony_ci				      CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	s->block_aligned_filename = kzalloc(s->block_aligned_filename_size,
70062306a36Sopenharmony_ci					    GFP_KERNEL);
70162306a36Sopenharmony_ci	if (!s->block_aligned_filename) {
70262306a36Sopenharmony_ci		rc = -ENOMEM;
70362306a36Sopenharmony_ci		goto out_unlock;
70462306a36Sopenharmony_ci	}
70562306a36Sopenharmony_ci	dest[s->i++] = ECRYPTFS_TAG_70_PACKET_TYPE;
70662306a36Sopenharmony_ci	rc = ecryptfs_write_packet_length(&dest[s->i],
70762306a36Sopenharmony_ci					  (ECRYPTFS_SIG_SIZE
70862306a36Sopenharmony_ci					   + 1 /* Cipher code */
70962306a36Sopenharmony_ci					   + s->block_aligned_filename_size),
71062306a36Sopenharmony_ci					  &s->packet_size_len);
71162306a36Sopenharmony_ci	if (rc) {
71262306a36Sopenharmony_ci		printk(KERN_ERR "%s: Error generating tag 70 packet "
71362306a36Sopenharmony_ci		       "header; cannot generate packet length; rc = [%d]\n",
71462306a36Sopenharmony_ci		       __func__, rc);
71562306a36Sopenharmony_ci		goto out_free_unlock;
71662306a36Sopenharmony_ci	}
71762306a36Sopenharmony_ci	s->i += s->packet_size_len;
71862306a36Sopenharmony_ci	ecryptfs_from_hex(&dest[s->i],
71962306a36Sopenharmony_ci			  mount_crypt_stat->global_default_fnek_sig,
72062306a36Sopenharmony_ci			  ECRYPTFS_SIG_SIZE);
72162306a36Sopenharmony_ci	s->i += ECRYPTFS_SIG_SIZE;
72262306a36Sopenharmony_ci	s->cipher_code = ecryptfs_code_for_cipher_string(
72362306a36Sopenharmony_ci		mount_crypt_stat->global_default_fn_cipher_name,
72462306a36Sopenharmony_ci		mount_crypt_stat->global_default_fn_cipher_key_bytes);
72562306a36Sopenharmony_ci	if (s->cipher_code == 0) {
72662306a36Sopenharmony_ci		printk(KERN_WARNING "%s: Unable to generate code for "
72762306a36Sopenharmony_ci		       "cipher [%s] with key bytes [%zd]\n", __func__,
72862306a36Sopenharmony_ci		       mount_crypt_stat->global_default_fn_cipher_name,
72962306a36Sopenharmony_ci		       mount_crypt_stat->global_default_fn_cipher_key_bytes);
73062306a36Sopenharmony_ci		rc = -EINVAL;
73162306a36Sopenharmony_ci		goto out_free_unlock;
73262306a36Sopenharmony_ci	}
73362306a36Sopenharmony_ci	dest[s->i++] = s->cipher_code;
73462306a36Sopenharmony_ci	/* TODO: Support other key modules than passphrase for
73562306a36Sopenharmony_ci	 * filename encryption */
73662306a36Sopenharmony_ci	if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) {
73762306a36Sopenharmony_ci		rc = -EOPNOTSUPP;
73862306a36Sopenharmony_ci		printk(KERN_INFO "%s: Filename encryption only supports "
73962306a36Sopenharmony_ci		       "password tokens\n", __func__);
74062306a36Sopenharmony_ci		goto out_free_unlock;
74162306a36Sopenharmony_ci	}
74262306a36Sopenharmony_ci	s->hash_tfm = crypto_alloc_shash(ECRYPTFS_TAG_70_DIGEST, 0, 0);
74362306a36Sopenharmony_ci	if (IS_ERR(s->hash_tfm)) {
74462306a36Sopenharmony_ci			rc = PTR_ERR(s->hash_tfm);
74562306a36Sopenharmony_ci			printk(KERN_ERR "%s: Error attempting to "
74662306a36Sopenharmony_ci			       "allocate hash crypto context; rc = [%d]\n",
74762306a36Sopenharmony_ci			       __func__, rc);
74862306a36Sopenharmony_ci			goto out_free_unlock;
74962306a36Sopenharmony_ci	}
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci	s->hash_desc = kmalloc(sizeof(*s->hash_desc) +
75262306a36Sopenharmony_ci			       crypto_shash_descsize(s->hash_tfm), GFP_KERNEL);
75362306a36Sopenharmony_ci	if (!s->hash_desc) {
75462306a36Sopenharmony_ci		rc = -ENOMEM;
75562306a36Sopenharmony_ci		goto out_release_free_unlock;
75662306a36Sopenharmony_ci	}
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci	s->hash_desc->tfm = s->hash_tfm;
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	rc = crypto_shash_digest(s->hash_desc,
76162306a36Sopenharmony_ci				 (u8 *)s->auth_tok->token.password.session_key_encryption_key,
76262306a36Sopenharmony_ci				 s->auth_tok->token.password.session_key_encryption_key_bytes,
76362306a36Sopenharmony_ci				 s->hash);
76462306a36Sopenharmony_ci	if (rc) {
76562306a36Sopenharmony_ci		printk(KERN_ERR
76662306a36Sopenharmony_ci		       "%s: Error computing crypto hash; rc = [%d]\n",
76762306a36Sopenharmony_ci		       __func__, rc);
76862306a36Sopenharmony_ci		goto out_release_free_unlock;
76962306a36Sopenharmony_ci	}
77062306a36Sopenharmony_ci	for (s->j = 0; s->j < (s->num_rand_bytes - 1); s->j++) {
77162306a36Sopenharmony_ci		s->block_aligned_filename[s->j] =
77262306a36Sopenharmony_ci			s->hash[(s->j % ECRYPTFS_TAG_70_DIGEST_SIZE)];
77362306a36Sopenharmony_ci		if ((s->j % ECRYPTFS_TAG_70_DIGEST_SIZE)
77462306a36Sopenharmony_ci		    == (ECRYPTFS_TAG_70_DIGEST_SIZE - 1)) {
77562306a36Sopenharmony_ci			rc = crypto_shash_digest(s->hash_desc, (u8 *)s->hash,
77662306a36Sopenharmony_ci						ECRYPTFS_TAG_70_DIGEST_SIZE,
77762306a36Sopenharmony_ci						s->tmp_hash);
77862306a36Sopenharmony_ci			if (rc) {
77962306a36Sopenharmony_ci				printk(KERN_ERR
78062306a36Sopenharmony_ci				       "%s: Error computing crypto hash; "
78162306a36Sopenharmony_ci				       "rc = [%d]\n", __func__, rc);
78262306a36Sopenharmony_ci				goto out_release_free_unlock;
78362306a36Sopenharmony_ci			}
78462306a36Sopenharmony_ci			memcpy(s->hash, s->tmp_hash,
78562306a36Sopenharmony_ci			       ECRYPTFS_TAG_70_DIGEST_SIZE);
78662306a36Sopenharmony_ci		}
78762306a36Sopenharmony_ci		if (s->block_aligned_filename[s->j] == '\0')
78862306a36Sopenharmony_ci			s->block_aligned_filename[s->j] = ECRYPTFS_NON_NULL;
78962306a36Sopenharmony_ci	}
79062306a36Sopenharmony_ci	memcpy(&s->block_aligned_filename[s->num_rand_bytes], filename,
79162306a36Sopenharmony_ci	       filename_size);
79262306a36Sopenharmony_ci	rc = virt_to_scatterlist(s->block_aligned_filename,
79362306a36Sopenharmony_ci				 s->block_aligned_filename_size, s->src_sg, 2);
79462306a36Sopenharmony_ci	if (rc < 1) {
79562306a36Sopenharmony_ci		printk(KERN_ERR "%s: Internal error whilst attempting to "
79662306a36Sopenharmony_ci		       "convert filename memory to scatterlist; rc = [%d]. "
79762306a36Sopenharmony_ci		       "block_aligned_filename_size = [%zd]\n", __func__, rc,
79862306a36Sopenharmony_ci		       s->block_aligned_filename_size);
79962306a36Sopenharmony_ci		goto out_release_free_unlock;
80062306a36Sopenharmony_ci	}
80162306a36Sopenharmony_ci	rc = virt_to_scatterlist(&dest[s->i], s->block_aligned_filename_size,
80262306a36Sopenharmony_ci				 s->dst_sg, 2);
80362306a36Sopenharmony_ci	if (rc < 1) {
80462306a36Sopenharmony_ci		printk(KERN_ERR "%s: Internal error whilst attempting to "
80562306a36Sopenharmony_ci		       "convert encrypted filename memory to scatterlist; "
80662306a36Sopenharmony_ci		       "rc = [%d]. block_aligned_filename_size = [%zd]\n",
80762306a36Sopenharmony_ci		       __func__, rc, s->block_aligned_filename_size);
80862306a36Sopenharmony_ci		goto out_release_free_unlock;
80962306a36Sopenharmony_ci	}
81062306a36Sopenharmony_ci	/* The characters in the first block effectively do the job
81162306a36Sopenharmony_ci	 * of the IV here, so we just use 0's for the IV. Note the
81262306a36Sopenharmony_ci	 * constraint that ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES
81362306a36Sopenharmony_ci	 * >= ECRYPTFS_MAX_IV_BYTES. */
81462306a36Sopenharmony_ci	rc = crypto_skcipher_setkey(
81562306a36Sopenharmony_ci		s->skcipher_tfm,
81662306a36Sopenharmony_ci		s->auth_tok->token.password.session_key_encryption_key,
81762306a36Sopenharmony_ci		mount_crypt_stat->global_default_fn_cipher_key_bytes);
81862306a36Sopenharmony_ci	if (rc < 0) {
81962306a36Sopenharmony_ci		printk(KERN_ERR "%s: Error setting key for crypto context; "
82062306a36Sopenharmony_ci		       "rc = [%d]. s->auth_tok->token.password.session_key_"
82162306a36Sopenharmony_ci		       "encryption_key = [0x%p]; mount_crypt_stat->"
82262306a36Sopenharmony_ci		       "global_default_fn_cipher_key_bytes = [%zd]\n", __func__,
82362306a36Sopenharmony_ci		       rc,
82462306a36Sopenharmony_ci		       s->auth_tok->token.password.session_key_encryption_key,
82562306a36Sopenharmony_ci		       mount_crypt_stat->global_default_fn_cipher_key_bytes);
82662306a36Sopenharmony_ci		goto out_release_free_unlock;
82762306a36Sopenharmony_ci	}
82862306a36Sopenharmony_ci	skcipher_request_set_crypt(s->skcipher_req, s->src_sg, s->dst_sg,
82962306a36Sopenharmony_ci				   s->block_aligned_filename_size, s->iv);
83062306a36Sopenharmony_ci	rc = crypto_skcipher_encrypt(s->skcipher_req);
83162306a36Sopenharmony_ci	if (rc) {
83262306a36Sopenharmony_ci		printk(KERN_ERR "%s: Error attempting to encrypt filename; "
83362306a36Sopenharmony_ci		       "rc = [%d]\n", __func__, rc);
83462306a36Sopenharmony_ci		goto out_release_free_unlock;
83562306a36Sopenharmony_ci	}
83662306a36Sopenharmony_ci	s->i += s->block_aligned_filename_size;
83762306a36Sopenharmony_ci	(*packet_size) = s->i;
83862306a36Sopenharmony_ci	(*remaining_bytes) -= (*packet_size);
83962306a36Sopenharmony_ciout_release_free_unlock:
84062306a36Sopenharmony_ci	crypto_free_shash(s->hash_tfm);
84162306a36Sopenharmony_ciout_free_unlock:
84262306a36Sopenharmony_ci	kfree_sensitive(s->block_aligned_filename);
84362306a36Sopenharmony_ciout_unlock:
84462306a36Sopenharmony_ci	mutex_unlock(s->tfm_mutex);
84562306a36Sopenharmony_ciout:
84662306a36Sopenharmony_ci	if (auth_tok_key) {
84762306a36Sopenharmony_ci		up_write(&(auth_tok_key->sem));
84862306a36Sopenharmony_ci		key_put(auth_tok_key);
84962306a36Sopenharmony_ci	}
85062306a36Sopenharmony_ci	skcipher_request_free(s->skcipher_req);
85162306a36Sopenharmony_ci	kfree_sensitive(s->hash_desc);
85262306a36Sopenharmony_ci	kfree(s);
85362306a36Sopenharmony_ci	return rc;
85462306a36Sopenharmony_ci}
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_cistruct ecryptfs_parse_tag_70_packet_silly_stack {
85762306a36Sopenharmony_ci	u8 cipher_code;
85862306a36Sopenharmony_ci	size_t max_packet_size;
85962306a36Sopenharmony_ci	size_t packet_size_len;
86062306a36Sopenharmony_ci	size_t parsed_tag_70_packet_size;
86162306a36Sopenharmony_ci	size_t block_aligned_filename_size;
86262306a36Sopenharmony_ci	size_t block_size;
86362306a36Sopenharmony_ci	size_t i;
86462306a36Sopenharmony_ci	struct mutex *tfm_mutex;
86562306a36Sopenharmony_ci	char *decrypted_filename;
86662306a36Sopenharmony_ci	struct ecryptfs_auth_tok *auth_tok;
86762306a36Sopenharmony_ci	struct scatterlist src_sg[2];
86862306a36Sopenharmony_ci	struct scatterlist dst_sg[2];
86962306a36Sopenharmony_ci	struct crypto_skcipher *skcipher_tfm;
87062306a36Sopenharmony_ci	struct skcipher_request *skcipher_req;
87162306a36Sopenharmony_ci	char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1];
87262306a36Sopenharmony_ci	char iv[ECRYPTFS_MAX_IV_BYTES];
87362306a36Sopenharmony_ci	char cipher_string[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1];
87462306a36Sopenharmony_ci};
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci/**
87762306a36Sopenharmony_ci * ecryptfs_parse_tag_70_packet - Parse and process FNEK-encrypted passphrase packet
87862306a36Sopenharmony_ci * @filename: This function kmalloc's the memory for the filename
87962306a36Sopenharmony_ci * @filename_size: This function sets this to the amount of memory
88062306a36Sopenharmony_ci *                 kmalloc'd for the filename
88162306a36Sopenharmony_ci * @packet_size: This function sets this to the the number of octets
88262306a36Sopenharmony_ci *               in the packet parsed
88362306a36Sopenharmony_ci * @mount_crypt_stat: The mount-wide cryptographic context
88462306a36Sopenharmony_ci * @data: The memory location containing the start of the tag 70
88562306a36Sopenharmony_ci *        packet
88662306a36Sopenharmony_ci * @max_packet_size: The maximum legal size of the packet to be parsed
88762306a36Sopenharmony_ci *                   from @data
88862306a36Sopenharmony_ci *
88962306a36Sopenharmony_ci * Returns zero on success; non-zero otherwise
89062306a36Sopenharmony_ci */
89162306a36Sopenharmony_ciint
89262306a36Sopenharmony_ciecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
89362306a36Sopenharmony_ci			     size_t *packet_size,
89462306a36Sopenharmony_ci			     struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
89562306a36Sopenharmony_ci			     char *data, size_t max_packet_size)
89662306a36Sopenharmony_ci{
89762306a36Sopenharmony_ci	struct ecryptfs_parse_tag_70_packet_silly_stack *s;
89862306a36Sopenharmony_ci	struct key *auth_tok_key = NULL;
89962306a36Sopenharmony_ci	int rc = 0;
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	(*packet_size) = 0;
90262306a36Sopenharmony_ci	(*filename_size) = 0;
90362306a36Sopenharmony_ci	(*filename) = NULL;
90462306a36Sopenharmony_ci	s = kzalloc(sizeof(*s), GFP_KERNEL);
90562306a36Sopenharmony_ci	if (!s)
90662306a36Sopenharmony_ci		return -ENOMEM;
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci	if (max_packet_size < ECRYPTFS_TAG_70_MIN_METADATA_SIZE) {
90962306a36Sopenharmony_ci		printk(KERN_WARNING "%s: max_packet_size is [%zd]; it must be "
91062306a36Sopenharmony_ci		       "at least [%d]\n", __func__, max_packet_size,
91162306a36Sopenharmony_ci		       ECRYPTFS_TAG_70_MIN_METADATA_SIZE);
91262306a36Sopenharmony_ci		rc = -EINVAL;
91362306a36Sopenharmony_ci		goto out;
91462306a36Sopenharmony_ci	}
91562306a36Sopenharmony_ci	/* Octet 0: Tag 70 identifier
91662306a36Sopenharmony_ci	 * Octets 1-N1: Tag 70 packet size (includes cipher identifier
91762306a36Sopenharmony_ci	 *              and block-aligned encrypted filename size)
91862306a36Sopenharmony_ci	 * Octets N1-N2: FNEK sig (ECRYPTFS_SIG_SIZE)
91962306a36Sopenharmony_ci	 * Octet N2-N3: Cipher identifier (1 octet)
92062306a36Sopenharmony_ci	 * Octets N3-N4: Block-aligned encrypted filename
92162306a36Sopenharmony_ci	 *  - Consists of a minimum number of random numbers, a \0
92262306a36Sopenharmony_ci	 *    separator, and then the filename */
92362306a36Sopenharmony_ci	if (data[(*packet_size)++] != ECRYPTFS_TAG_70_PACKET_TYPE) {
92462306a36Sopenharmony_ci		printk(KERN_WARNING "%s: Invalid packet tag [0x%.2x]; must be "
92562306a36Sopenharmony_ci		       "tag [0x%.2x]\n", __func__,
92662306a36Sopenharmony_ci		       data[((*packet_size) - 1)], ECRYPTFS_TAG_70_PACKET_TYPE);
92762306a36Sopenharmony_ci		rc = -EINVAL;
92862306a36Sopenharmony_ci		goto out;
92962306a36Sopenharmony_ci	}
93062306a36Sopenharmony_ci	rc = ecryptfs_parse_packet_length(&data[(*packet_size)],
93162306a36Sopenharmony_ci					  &s->parsed_tag_70_packet_size,
93262306a36Sopenharmony_ci					  &s->packet_size_len);
93362306a36Sopenharmony_ci	if (rc) {
93462306a36Sopenharmony_ci		printk(KERN_WARNING "%s: Error parsing packet length; "
93562306a36Sopenharmony_ci		       "rc = [%d]\n", __func__, rc);
93662306a36Sopenharmony_ci		goto out;
93762306a36Sopenharmony_ci	}
93862306a36Sopenharmony_ci	s->block_aligned_filename_size = (s->parsed_tag_70_packet_size
93962306a36Sopenharmony_ci					  - ECRYPTFS_SIG_SIZE - 1);
94062306a36Sopenharmony_ci	if ((1 + s->packet_size_len + s->parsed_tag_70_packet_size)
94162306a36Sopenharmony_ci	    > max_packet_size) {
94262306a36Sopenharmony_ci		printk(KERN_WARNING "%s: max_packet_size is [%zd]; real packet "
94362306a36Sopenharmony_ci		       "size is [%zd]\n", __func__, max_packet_size,
94462306a36Sopenharmony_ci		       (1 + s->packet_size_len + 1
94562306a36Sopenharmony_ci			+ s->block_aligned_filename_size));
94662306a36Sopenharmony_ci		rc = -EINVAL;
94762306a36Sopenharmony_ci		goto out;
94862306a36Sopenharmony_ci	}
94962306a36Sopenharmony_ci	(*packet_size) += s->packet_size_len;
95062306a36Sopenharmony_ci	ecryptfs_to_hex(s->fnek_sig_hex, &data[(*packet_size)],
95162306a36Sopenharmony_ci			ECRYPTFS_SIG_SIZE);
95262306a36Sopenharmony_ci	s->fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX] = '\0';
95362306a36Sopenharmony_ci	(*packet_size) += ECRYPTFS_SIG_SIZE;
95462306a36Sopenharmony_ci	s->cipher_code = data[(*packet_size)++];
95562306a36Sopenharmony_ci	rc = ecryptfs_cipher_code_to_string(s->cipher_string, s->cipher_code);
95662306a36Sopenharmony_ci	if (rc) {
95762306a36Sopenharmony_ci		printk(KERN_WARNING "%s: Cipher code [%d] is invalid\n",
95862306a36Sopenharmony_ci		       __func__, s->cipher_code);
95962306a36Sopenharmony_ci		goto out;
96062306a36Sopenharmony_ci	}
96162306a36Sopenharmony_ci	rc = ecryptfs_find_auth_tok_for_sig(&auth_tok_key,
96262306a36Sopenharmony_ci					    &s->auth_tok, mount_crypt_stat,
96362306a36Sopenharmony_ci					    s->fnek_sig_hex);
96462306a36Sopenharmony_ci	if (rc) {
96562306a36Sopenharmony_ci		printk(KERN_ERR "%s: Error attempting to find auth tok for "
96662306a36Sopenharmony_ci		       "fnek sig [%s]; rc = [%d]\n", __func__, s->fnek_sig_hex,
96762306a36Sopenharmony_ci		       rc);
96862306a36Sopenharmony_ci		goto out;
96962306a36Sopenharmony_ci	}
97062306a36Sopenharmony_ci	rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&s->skcipher_tfm,
97162306a36Sopenharmony_ci							&s->tfm_mutex,
97262306a36Sopenharmony_ci							s->cipher_string);
97362306a36Sopenharmony_ci	if (unlikely(rc)) {
97462306a36Sopenharmony_ci		printk(KERN_ERR "Internal error whilst attempting to get "
97562306a36Sopenharmony_ci		       "tfm and mutex for cipher name [%s]; rc = [%d]\n",
97662306a36Sopenharmony_ci		       s->cipher_string, rc);
97762306a36Sopenharmony_ci		goto out;
97862306a36Sopenharmony_ci	}
97962306a36Sopenharmony_ci	mutex_lock(s->tfm_mutex);
98062306a36Sopenharmony_ci	rc = virt_to_scatterlist(&data[(*packet_size)],
98162306a36Sopenharmony_ci				 s->block_aligned_filename_size, s->src_sg, 2);
98262306a36Sopenharmony_ci	if (rc < 1) {
98362306a36Sopenharmony_ci		printk(KERN_ERR "%s: Internal error whilst attempting to "
98462306a36Sopenharmony_ci		       "convert encrypted filename memory to scatterlist; "
98562306a36Sopenharmony_ci		       "rc = [%d]. block_aligned_filename_size = [%zd]\n",
98662306a36Sopenharmony_ci		       __func__, rc, s->block_aligned_filename_size);
98762306a36Sopenharmony_ci		goto out_unlock;
98862306a36Sopenharmony_ci	}
98962306a36Sopenharmony_ci	(*packet_size) += s->block_aligned_filename_size;
99062306a36Sopenharmony_ci	s->decrypted_filename = kmalloc(s->block_aligned_filename_size,
99162306a36Sopenharmony_ci					GFP_KERNEL);
99262306a36Sopenharmony_ci	if (!s->decrypted_filename) {
99362306a36Sopenharmony_ci		rc = -ENOMEM;
99462306a36Sopenharmony_ci		goto out_unlock;
99562306a36Sopenharmony_ci	}
99662306a36Sopenharmony_ci	rc = virt_to_scatterlist(s->decrypted_filename,
99762306a36Sopenharmony_ci				 s->block_aligned_filename_size, s->dst_sg, 2);
99862306a36Sopenharmony_ci	if (rc < 1) {
99962306a36Sopenharmony_ci		printk(KERN_ERR "%s: Internal error whilst attempting to "
100062306a36Sopenharmony_ci		       "convert decrypted filename memory to scatterlist; "
100162306a36Sopenharmony_ci		       "rc = [%d]. block_aligned_filename_size = [%zd]\n",
100262306a36Sopenharmony_ci		       __func__, rc, s->block_aligned_filename_size);
100362306a36Sopenharmony_ci		goto out_free_unlock;
100462306a36Sopenharmony_ci	}
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci	s->skcipher_req = skcipher_request_alloc(s->skcipher_tfm, GFP_KERNEL);
100762306a36Sopenharmony_ci	if (!s->skcipher_req) {
100862306a36Sopenharmony_ci		printk(KERN_ERR "%s: Out of kernel memory whilst attempting to "
100962306a36Sopenharmony_ci		       "skcipher_request_alloc for %s\n", __func__,
101062306a36Sopenharmony_ci		       crypto_skcipher_driver_name(s->skcipher_tfm));
101162306a36Sopenharmony_ci		rc = -ENOMEM;
101262306a36Sopenharmony_ci		goto out_free_unlock;
101362306a36Sopenharmony_ci	}
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci	skcipher_request_set_callback(s->skcipher_req,
101662306a36Sopenharmony_ci				      CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL);
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	/* The characters in the first block effectively do the job of
101962306a36Sopenharmony_ci	 * the IV here, so we just use 0's for the IV. Note the
102062306a36Sopenharmony_ci	 * constraint that ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES
102162306a36Sopenharmony_ci	 * >= ECRYPTFS_MAX_IV_BYTES. */
102262306a36Sopenharmony_ci	/* TODO: Support other key modules than passphrase for
102362306a36Sopenharmony_ci	 * filename encryption */
102462306a36Sopenharmony_ci	if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) {
102562306a36Sopenharmony_ci		rc = -EOPNOTSUPP;
102662306a36Sopenharmony_ci		printk(KERN_INFO "%s: Filename encryption only supports "
102762306a36Sopenharmony_ci		       "password tokens\n", __func__);
102862306a36Sopenharmony_ci		goto out_free_unlock;
102962306a36Sopenharmony_ci	}
103062306a36Sopenharmony_ci	rc = crypto_skcipher_setkey(
103162306a36Sopenharmony_ci		s->skcipher_tfm,
103262306a36Sopenharmony_ci		s->auth_tok->token.password.session_key_encryption_key,
103362306a36Sopenharmony_ci		mount_crypt_stat->global_default_fn_cipher_key_bytes);
103462306a36Sopenharmony_ci	if (rc < 0) {
103562306a36Sopenharmony_ci		printk(KERN_ERR "%s: Error setting key for crypto context; "
103662306a36Sopenharmony_ci		       "rc = [%d]. s->auth_tok->token.password.session_key_"
103762306a36Sopenharmony_ci		       "encryption_key = [0x%p]; mount_crypt_stat->"
103862306a36Sopenharmony_ci		       "global_default_fn_cipher_key_bytes = [%zd]\n", __func__,
103962306a36Sopenharmony_ci		       rc,
104062306a36Sopenharmony_ci		       s->auth_tok->token.password.session_key_encryption_key,
104162306a36Sopenharmony_ci		       mount_crypt_stat->global_default_fn_cipher_key_bytes);
104262306a36Sopenharmony_ci		goto out_free_unlock;
104362306a36Sopenharmony_ci	}
104462306a36Sopenharmony_ci	skcipher_request_set_crypt(s->skcipher_req, s->src_sg, s->dst_sg,
104562306a36Sopenharmony_ci				   s->block_aligned_filename_size, s->iv);
104662306a36Sopenharmony_ci	rc = crypto_skcipher_decrypt(s->skcipher_req);
104762306a36Sopenharmony_ci	if (rc) {
104862306a36Sopenharmony_ci		printk(KERN_ERR "%s: Error attempting to decrypt filename; "
104962306a36Sopenharmony_ci		       "rc = [%d]\n", __func__, rc);
105062306a36Sopenharmony_ci		goto out_free_unlock;
105162306a36Sopenharmony_ci	}
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	while (s->i < s->block_aligned_filename_size &&
105462306a36Sopenharmony_ci	       s->decrypted_filename[s->i] != '\0')
105562306a36Sopenharmony_ci		s->i++;
105662306a36Sopenharmony_ci	if (s->i == s->block_aligned_filename_size) {
105762306a36Sopenharmony_ci		printk(KERN_WARNING "%s: Invalid tag 70 packet; could not "
105862306a36Sopenharmony_ci		       "find valid separator between random characters and "
105962306a36Sopenharmony_ci		       "the filename\n", __func__);
106062306a36Sopenharmony_ci		rc = -EINVAL;
106162306a36Sopenharmony_ci		goto out_free_unlock;
106262306a36Sopenharmony_ci	}
106362306a36Sopenharmony_ci	s->i++;
106462306a36Sopenharmony_ci	(*filename_size) = (s->block_aligned_filename_size - s->i);
106562306a36Sopenharmony_ci	if (!((*filename_size) > 0 && (*filename_size < PATH_MAX))) {
106662306a36Sopenharmony_ci		printk(KERN_WARNING "%s: Filename size is [%zd], which is "
106762306a36Sopenharmony_ci		       "invalid\n", __func__, (*filename_size));
106862306a36Sopenharmony_ci		rc = -EINVAL;
106962306a36Sopenharmony_ci		goto out_free_unlock;
107062306a36Sopenharmony_ci	}
107162306a36Sopenharmony_ci	(*filename) = kmalloc(((*filename_size) + 1), GFP_KERNEL);
107262306a36Sopenharmony_ci	if (!(*filename)) {
107362306a36Sopenharmony_ci		rc = -ENOMEM;
107462306a36Sopenharmony_ci		goto out_free_unlock;
107562306a36Sopenharmony_ci	}
107662306a36Sopenharmony_ci	memcpy((*filename), &s->decrypted_filename[s->i], (*filename_size));
107762306a36Sopenharmony_ci	(*filename)[(*filename_size)] = '\0';
107862306a36Sopenharmony_ciout_free_unlock:
107962306a36Sopenharmony_ci	kfree(s->decrypted_filename);
108062306a36Sopenharmony_ciout_unlock:
108162306a36Sopenharmony_ci	mutex_unlock(s->tfm_mutex);
108262306a36Sopenharmony_ciout:
108362306a36Sopenharmony_ci	if (rc) {
108462306a36Sopenharmony_ci		(*packet_size) = 0;
108562306a36Sopenharmony_ci		(*filename_size) = 0;
108662306a36Sopenharmony_ci		(*filename) = NULL;
108762306a36Sopenharmony_ci	}
108862306a36Sopenharmony_ci	if (auth_tok_key) {
108962306a36Sopenharmony_ci		up_write(&(auth_tok_key->sem));
109062306a36Sopenharmony_ci		key_put(auth_tok_key);
109162306a36Sopenharmony_ci	}
109262306a36Sopenharmony_ci	skcipher_request_free(s->skcipher_req);
109362306a36Sopenharmony_ci	kfree(s);
109462306a36Sopenharmony_ci	return rc;
109562306a36Sopenharmony_ci}
109662306a36Sopenharmony_ci
109762306a36Sopenharmony_cistatic int
109862306a36Sopenharmony_ciecryptfs_get_auth_tok_sig(char **sig, struct ecryptfs_auth_tok *auth_tok)
109962306a36Sopenharmony_ci{
110062306a36Sopenharmony_ci	int rc = 0;
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	(*sig) = NULL;
110362306a36Sopenharmony_ci	switch (auth_tok->token_type) {
110462306a36Sopenharmony_ci	case ECRYPTFS_PASSWORD:
110562306a36Sopenharmony_ci		(*sig) = auth_tok->token.password.signature;
110662306a36Sopenharmony_ci		break;
110762306a36Sopenharmony_ci	case ECRYPTFS_PRIVATE_KEY:
110862306a36Sopenharmony_ci		(*sig) = auth_tok->token.private_key.signature;
110962306a36Sopenharmony_ci		break;
111062306a36Sopenharmony_ci	default:
111162306a36Sopenharmony_ci		printk(KERN_ERR "Cannot get sig for auth_tok of type [%d]\n",
111262306a36Sopenharmony_ci		       auth_tok->token_type);
111362306a36Sopenharmony_ci		rc = -EINVAL;
111462306a36Sopenharmony_ci	}
111562306a36Sopenharmony_ci	return rc;
111662306a36Sopenharmony_ci}
111762306a36Sopenharmony_ci
111862306a36Sopenharmony_ci/**
111962306a36Sopenharmony_ci * decrypt_pki_encrypted_session_key - Decrypt the session key with the given auth_tok.
112062306a36Sopenharmony_ci * @auth_tok: The key authentication token used to decrypt the session key
112162306a36Sopenharmony_ci * @crypt_stat: The cryptographic context
112262306a36Sopenharmony_ci *
112362306a36Sopenharmony_ci * Returns zero on success; non-zero error otherwise.
112462306a36Sopenharmony_ci */
112562306a36Sopenharmony_cistatic int
112662306a36Sopenharmony_cidecrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
112762306a36Sopenharmony_ci				  struct ecryptfs_crypt_stat *crypt_stat)
112862306a36Sopenharmony_ci{
112962306a36Sopenharmony_ci	u8 cipher_code = 0;
113062306a36Sopenharmony_ci	struct ecryptfs_msg_ctx *msg_ctx;
113162306a36Sopenharmony_ci	struct ecryptfs_message *msg = NULL;
113262306a36Sopenharmony_ci	char *auth_tok_sig;
113362306a36Sopenharmony_ci	char *payload = NULL;
113462306a36Sopenharmony_ci	size_t payload_len = 0;
113562306a36Sopenharmony_ci	int rc;
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	rc = ecryptfs_get_auth_tok_sig(&auth_tok_sig, auth_tok);
113862306a36Sopenharmony_ci	if (rc) {
113962306a36Sopenharmony_ci		printk(KERN_ERR "Unrecognized auth tok type: [%d]\n",
114062306a36Sopenharmony_ci		       auth_tok->token_type);
114162306a36Sopenharmony_ci		goto out;
114262306a36Sopenharmony_ci	}
114362306a36Sopenharmony_ci	rc = write_tag_64_packet(auth_tok_sig, &(auth_tok->session_key),
114462306a36Sopenharmony_ci				 &payload, &payload_len);
114562306a36Sopenharmony_ci	if (rc) {
114662306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Failed to write tag 64 packet\n");
114762306a36Sopenharmony_ci		goto out;
114862306a36Sopenharmony_ci	}
114962306a36Sopenharmony_ci	rc = ecryptfs_send_message(payload, payload_len, &msg_ctx);
115062306a36Sopenharmony_ci	if (rc) {
115162306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error sending message to "
115262306a36Sopenharmony_ci				"ecryptfsd: %d\n", rc);
115362306a36Sopenharmony_ci		goto out;
115462306a36Sopenharmony_ci	}
115562306a36Sopenharmony_ci	rc = ecryptfs_wait_for_response(msg_ctx, &msg);
115662306a36Sopenharmony_ci	if (rc) {
115762306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Failed to receive tag 65 packet "
115862306a36Sopenharmony_ci				"from the user space daemon\n");
115962306a36Sopenharmony_ci		rc = -EIO;
116062306a36Sopenharmony_ci		goto out;
116162306a36Sopenharmony_ci	}
116262306a36Sopenharmony_ci	rc = parse_tag_65_packet(&(auth_tok->session_key),
116362306a36Sopenharmony_ci				 &cipher_code, msg);
116462306a36Sopenharmony_ci	if (rc) {
116562306a36Sopenharmony_ci		printk(KERN_ERR "Failed to parse tag 65 packet; rc = [%d]\n",
116662306a36Sopenharmony_ci		       rc);
116762306a36Sopenharmony_ci		goto out;
116862306a36Sopenharmony_ci	}
116962306a36Sopenharmony_ci	auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY;
117062306a36Sopenharmony_ci	memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key,
117162306a36Sopenharmony_ci	       auth_tok->session_key.decrypted_key_size);
117262306a36Sopenharmony_ci	crypt_stat->key_size = auth_tok->session_key.decrypted_key_size;
117362306a36Sopenharmony_ci	rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher, cipher_code);
117462306a36Sopenharmony_ci	if (rc) {
117562306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Cipher code [%d] is invalid\n",
117662306a36Sopenharmony_ci				cipher_code);
117762306a36Sopenharmony_ci		goto out;
117862306a36Sopenharmony_ci	}
117962306a36Sopenharmony_ci	crypt_stat->flags |= ECRYPTFS_KEY_VALID;
118062306a36Sopenharmony_ci	if (ecryptfs_verbosity > 0) {
118162306a36Sopenharmony_ci		ecryptfs_printk(KERN_DEBUG, "Decrypted session key:\n");
118262306a36Sopenharmony_ci		ecryptfs_dump_hex(crypt_stat->key,
118362306a36Sopenharmony_ci				  crypt_stat->key_size);
118462306a36Sopenharmony_ci	}
118562306a36Sopenharmony_ciout:
118662306a36Sopenharmony_ci	kfree(msg);
118762306a36Sopenharmony_ci	kfree(payload);
118862306a36Sopenharmony_ci	return rc;
118962306a36Sopenharmony_ci}
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_cistatic void wipe_auth_tok_list(struct list_head *auth_tok_list_head)
119262306a36Sopenharmony_ci{
119362306a36Sopenharmony_ci	struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
119462306a36Sopenharmony_ci	struct ecryptfs_auth_tok_list_item *auth_tok_list_item_tmp;
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	list_for_each_entry_safe(auth_tok_list_item, auth_tok_list_item_tmp,
119762306a36Sopenharmony_ci				 auth_tok_list_head, list) {
119862306a36Sopenharmony_ci		list_del(&auth_tok_list_item->list);
119962306a36Sopenharmony_ci		kmem_cache_free(ecryptfs_auth_tok_list_item_cache,
120062306a36Sopenharmony_ci				auth_tok_list_item);
120162306a36Sopenharmony_ci	}
120262306a36Sopenharmony_ci}
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_cistruct kmem_cache *ecryptfs_auth_tok_list_item_cache;
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci/**
120762306a36Sopenharmony_ci * parse_tag_1_packet
120862306a36Sopenharmony_ci * @crypt_stat: The cryptographic context to modify based on packet contents
120962306a36Sopenharmony_ci * @data: The raw bytes of the packet.
121062306a36Sopenharmony_ci * @auth_tok_list: eCryptfs parses packets into authentication tokens;
121162306a36Sopenharmony_ci *                 a new authentication token will be placed at the
121262306a36Sopenharmony_ci *                 end of this list for this packet.
121362306a36Sopenharmony_ci * @new_auth_tok: Pointer to a pointer to memory that this function
121462306a36Sopenharmony_ci *                allocates; sets the memory address of the pointer to
121562306a36Sopenharmony_ci *                NULL on error. This object is added to the
121662306a36Sopenharmony_ci *                auth_tok_list.
121762306a36Sopenharmony_ci * @packet_size: This function writes the size of the parsed packet
121862306a36Sopenharmony_ci *               into this memory location; zero on error.
121962306a36Sopenharmony_ci * @max_packet_size: The maximum allowable packet size
122062306a36Sopenharmony_ci *
122162306a36Sopenharmony_ci * Returns zero on success; non-zero on error.
122262306a36Sopenharmony_ci */
122362306a36Sopenharmony_cistatic int
122462306a36Sopenharmony_ciparse_tag_1_packet(struct ecryptfs_crypt_stat *crypt_stat,
122562306a36Sopenharmony_ci		   unsigned char *data, struct list_head *auth_tok_list,
122662306a36Sopenharmony_ci		   struct ecryptfs_auth_tok **new_auth_tok,
122762306a36Sopenharmony_ci		   size_t *packet_size, size_t max_packet_size)
122862306a36Sopenharmony_ci{
122962306a36Sopenharmony_ci	size_t body_size;
123062306a36Sopenharmony_ci	struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
123162306a36Sopenharmony_ci	size_t length_size;
123262306a36Sopenharmony_ci	int rc = 0;
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci	(*packet_size) = 0;
123562306a36Sopenharmony_ci	(*new_auth_tok) = NULL;
123662306a36Sopenharmony_ci	/**
123762306a36Sopenharmony_ci	 * This format is inspired by OpenPGP; see RFC 2440
123862306a36Sopenharmony_ci	 * packet tag 1
123962306a36Sopenharmony_ci	 *
124062306a36Sopenharmony_ci	 * Tag 1 identifier (1 byte)
124162306a36Sopenharmony_ci	 * Max Tag 1 packet size (max 3 bytes)
124262306a36Sopenharmony_ci	 * Version (1 byte)
124362306a36Sopenharmony_ci	 * Key identifier (8 bytes; ECRYPTFS_SIG_SIZE)
124462306a36Sopenharmony_ci	 * Cipher identifier (1 byte)
124562306a36Sopenharmony_ci	 * Encrypted key size (arbitrary)
124662306a36Sopenharmony_ci	 *
124762306a36Sopenharmony_ci	 * 12 bytes minimum packet size
124862306a36Sopenharmony_ci	 */
124962306a36Sopenharmony_ci	if (unlikely(max_packet_size < 12)) {
125062306a36Sopenharmony_ci		printk(KERN_ERR "Invalid max packet size; must be >=12\n");
125162306a36Sopenharmony_ci		rc = -EINVAL;
125262306a36Sopenharmony_ci		goto out;
125362306a36Sopenharmony_ci	}
125462306a36Sopenharmony_ci	if (data[(*packet_size)++] != ECRYPTFS_TAG_1_PACKET_TYPE) {
125562306a36Sopenharmony_ci		printk(KERN_ERR "Enter w/ first byte != 0x%.2x\n",
125662306a36Sopenharmony_ci		       ECRYPTFS_TAG_1_PACKET_TYPE);
125762306a36Sopenharmony_ci		rc = -EINVAL;
125862306a36Sopenharmony_ci		goto out;
125962306a36Sopenharmony_ci	}
126062306a36Sopenharmony_ci	/* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or
126162306a36Sopenharmony_ci	 * at end of function upon failure */
126262306a36Sopenharmony_ci	auth_tok_list_item =
126362306a36Sopenharmony_ci		kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache,
126462306a36Sopenharmony_ci				  GFP_KERNEL);
126562306a36Sopenharmony_ci	if (!auth_tok_list_item) {
126662306a36Sopenharmony_ci		printk(KERN_ERR "Unable to allocate memory\n");
126762306a36Sopenharmony_ci		rc = -ENOMEM;
126862306a36Sopenharmony_ci		goto out;
126962306a36Sopenharmony_ci	}
127062306a36Sopenharmony_ci	(*new_auth_tok) = &auth_tok_list_item->auth_tok;
127162306a36Sopenharmony_ci	rc = ecryptfs_parse_packet_length(&data[(*packet_size)], &body_size,
127262306a36Sopenharmony_ci					  &length_size);
127362306a36Sopenharmony_ci	if (rc) {
127462306a36Sopenharmony_ci		printk(KERN_WARNING "Error parsing packet length; "
127562306a36Sopenharmony_ci		       "rc = [%d]\n", rc);
127662306a36Sopenharmony_ci		goto out_free;
127762306a36Sopenharmony_ci	}
127862306a36Sopenharmony_ci	if (unlikely(body_size < (ECRYPTFS_SIG_SIZE + 2))) {
127962306a36Sopenharmony_ci		printk(KERN_WARNING "Invalid body size ([%td])\n", body_size);
128062306a36Sopenharmony_ci		rc = -EINVAL;
128162306a36Sopenharmony_ci		goto out_free;
128262306a36Sopenharmony_ci	}
128362306a36Sopenharmony_ci	(*packet_size) += length_size;
128462306a36Sopenharmony_ci	if (unlikely((*packet_size) + body_size > max_packet_size)) {
128562306a36Sopenharmony_ci		printk(KERN_WARNING "Packet size exceeds max\n");
128662306a36Sopenharmony_ci		rc = -EINVAL;
128762306a36Sopenharmony_ci		goto out_free;
128862306a36Sopenharmony_ci	}
128962306a36Sopenharmony_ci	if (unlikely(data[(*packet_size)++] != 0x03)) {
129062306a36Sopenharmony_ci		printk(KERN_WARNING "Unknown version number [%d]\n",
129162306a36Sopenharmony_ci		       data[(*packet_size) - 1]);
129262306a36Sopenharmony_ci		rc = -EINVAL;
129362306a36Sopenharmony_ci		goto out_free;
129462306a36Sopenharmony_ci	}
129562306a36Sopenharmony_ci	ecryptfs_to_hex((*new_auth_tok)->token.private_key.signature,
129662306a36Sopenharmony_ci			&data[(*packet_size)], ECRYPTFS_SIG_SIZE);
129762306a36Sopenharmony_ci	*packet_size += ECRYPTFS_SIG_SIZE;
129862306a36Sopenharmony_ci	/* This byte is skipped because the kernel does not need to
129962306a36Sopenharmony_ci	 * know which public key encryption algorithm was used */
130062306a36Sopenharmony_ci	(*packet_size)++;
130162306a36Sopenharmony_ci	(*new_auth_tok)->session_key.encrypted_key_size =
130262306a36Sopenharmony_ci		body_size - (ECRYPTFS_SIG_SIZE + 2);
130362306a36Sopenharmony_ci	if ((*new_auth_tok)->session_key.encrypted_key_size
130462306a36Sopenharmony_ci	    > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
130562306a36Sopenharmony_ci		printk(KERN_WARNING "Tag 1 packet contains key larger "
130662306a36Sopenharmony_ci		       "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES\n");
130762306a36Sopenharmony_ci		rc = -EINVAL;
130862306a36Sopenharmony_ci		goto out_free;
130962306a36Sopenharmony_ci	}
131062306a36Sopenharmony_ci	memcpy((*new_auth_tok)->session_key.encrypted_key,
131162306a36Sopenharmony_ci	       &data[(*packet_size)], (body_size - (ECRYPTFS_SIG_SIZE + 2)));
131262306a36Sopenharmony_ci	(*packet_size) += (*new_auth_tok)->session_key.encrypted_key_size;
131362306a36Sopenharmony_ci	(*new_auth_tok)->session_key.flags &=
131462306a36Sopenharmony_ci		~ECRYPTFS_CONTAINS_DECRYPTED_KEY;
131562306a36Sopenharmony_ci	(*new_auth_tok)->session_key.flags |=
131662306a36Sopenharmony_ci		ECRYPTFS_CONTAINS_ENCRYPTED_KEY;
131762306a36Sopenharmony_ci	(*new_auth_tok)->token_type = ECRYPTFS_PRIVATE_KEY;
131862306a36Sopenharmony_ci	(*new_auth_tok)->flags = 0;
131962306a36Sopenharmony_ci	(*new_auth_tok)->session_key.flags &=
132062306a36Sopenharmony_ci		~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
132162306a36Sopenharmony_ci	(*new_auth_tok)->session_key.flags &=
132262306a36Sopenharmony_ci		~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);
132362306a36Sopenharmony_ci	list_add(&auth_tok_list_item->list, auth_tok_list);
132462306a36Sopenharmony_ci	goto out;
132562306a36Sopenharmony_ciout_free:
132662306a36Sopenharmony_ci	(*new_auth_tok) = NULL;
132762306a36Sopenharmony_ci	memset(auth_tok_list_item, 0,
132862306a36Sopenharmony_ci	       sizeof(struct ecryptfs_auth_tok_list_item));
132962306a36Sopenharmony_ci	kmem_cache_free(ecryptfs_auth_tok_list_item_cache,
133062306a36Sopenharmony_ci			auth_tok_list_item);
133162306a36Sopenharmony_ciout:
133262306a36Sopenharmony_ci	if (rc)
133362306a36Sopenharmony_ci		(*packet_size) = 0;
133462306a36Sopenharmony_ci	return rc;
133562306a36Sopenharmony_ci}
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_ci/**
133862306a36Sopenharmony_ci * parse_tag_3_packet
133962306a36Sopenharmony_ci * @crypt_stat: The cryptographic context to modify based on packet
134062306a36Sopenharmony_ci *              contents.
134162306a36Sopenharmony_ci * @data: The raw bytes of the packet.
134262306a36Sopenharmony_ci * @auth_tok_list: eCryptfs parses packets into authentication tokens;
134362306a36Sopenharmony_ci *                 a new authentication token will be placed at the end
134462306a36Sopenharmony_ci *                 of this list for this packet.
134562306a36Sopenharmony_ci * @new_auth_tok: Pointer to a pointer to memory that this function
134662306a36Sopenharmony_ci *                allocates; sets the memory address of the pointer to
134762306a36Sopenharmony_ci *                NULL on error. This object is added to the
134862306a36Sopenharmony_ci *                auth_tok_list.
134962306a36Sopenharmony_ci * @packet_size: This function writes the size of the parsed packet
135062306a36Sopenharmony_ci *               into this memory location; zero on error.
135162306a36Sopenharmony_ci * @max_packet_size: maximum number of bytes to parse
135262306a36Sopenharmony_ci *
135362306a36Sopenharmony_ci * Returns zero on success; non-zero on error.
135462306a36Sopenharmony_ci */
135562306a36Sopenharmony_cistatic int
135662306a36Sopenharmony_ciparse_tag_3_packet(struct ecryptfs_crypt_stat *crypt_stat,
135762306a36Sopenharmony_ci		   unsigned char *data, struct list_head *auth_tok_list,
135862306a36Sopenharmony_ci		   struct ecryptfs_auth_tok **new_auth_tok,
135962306a36Sopenharmony_ci		   size_t *packet_size, size_t max_packet_size)
136062306a36Sopenharmony_ci{
136162306a36Sopenharmony_ci	size_t body_size;
136262306a36Sopenharmony_ci	struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
136362306a36Sopenharmony_ci	size_t length_size;
136462306a36Sopenharmony_ci	int rc = 0;
136562306a36Sopenharmony_ci
136662306a36Sopenharmony_ci	(*packet_size) = 0;
136762306a36Sopenharmony_ci	(*new_auth_tok) = NULL;
136862306a36Sopenharmony_ci	/**
136962306a36Sopenharmony_ci	 *This format is inspired by OpenPGP; see RFC 2440
137062306a36Sopenharmony_ci	 * packet tag 3
137162306a36Sopenharmony_ci	 *
137262306a36Sopenharmony_ci	 * Tag 3 identifier (1 byte)
137362306a36Sopenharmony_ci	 * Max Tag 3 packet size (max 3 bytes)
137462306a36Sopenharmony_ci	 * Version (1 byte)
137562306a36Sopenharmony_ci	 * Cipher code (1 byte)
137662306a36Sopenharmony_ci	 * S2K specifier (1 byte)
137762306a36Sopenharmony_ci	 * Hash identifier (1 byte)
137862306a36Sopenharmony_ci	 * Salt (ECRYPTFS_SALT_SIZE)
137962306a36Sopenharmony_ci	 * Hash iterations (1 byte)
138062306a36Sopenharmony_ci	 * Encrypted key (arbitrary)
138162306a36Sopenharmony_ci	 *
138262306a36Sopenharmony_ci	 * (ECRYPTFS_SALT_SIZE + 7) minimum packet size
138362306a36Sopenharmony_ci	 */
138462306a36Sopenharmony_ci	if (max_packet_size < (ECRYPTFS_SALT_SIZE + 7)) {
138562306a36Sopenharmony_ci		printk(KERN_ERR "Max packet size too large\n");
138662306a36Sopenharmony_ci		rc = -EINVAL;
138762306a36Sopenharmony_ci		goto out;
138862306a36Sopenharmony_ci	}
138962306a36Sopenharmony_ci	if (data[(*packet_size)++] != ECRYPTFS_TAG_3_PACKET_TYPE) {
139062306a36Sopenharmony_ci		printk(KERN_ERR "First byte != 0x%.2x; invalid packet\n",
139162306a36Sopenharmony_ci		       ECRYPTFS_TAG_3_PACKET_TYPE);
139262306a36Sopenharmony_ci		rc = -EINVAL;
139362306a36Sopenharmony_ci		goto out;
139462306a36Sopenharmony_ci	}
139562306a36Sopenharmony_ci	/* Released: wipe_auth_tok_list called in ecryptfs_parse_packet_set or
139662306a36Sopenharmony_ci	 * at end of function upon failure */
139762306a36Sopenharmony_ci	auth_tok_list_item =
139862306a36Sopenharmony_ci	    kmem_cache_zalloc(ecryptfs_auth_tok_list_item_cache, GFP_KERNEL);
139962306a36Sopenharmony_ci	if (!auth_tok_list_item) {
140062306a36Sopenharmony_ci		printk(KERN_ERR "Unable to allocate memory\n");
140162306a36Sopenharmony_ci		rc = -ENOMEM;
140262306a36Sopenharmony_ci		goto out;
140362306a36Sopenharmony_ci	}
140462306a36Sopenharmony_ci	(*new_auth_tok) = &auth_tok_list_item->auth_tok;
140562306a36Sopenharmony_ci	rc = ecryptfs_parse_packet_length(&data[(*packet_size)], &body_size,
140662306a36Sopenharmony_ci					  &length_size);
140762306a36Sopenharmony_ci	if (rc) {
140862306a36Sopenharmony_ci		printk(KERN_WARNING "Error parsing packet length; rc = [%d]\n",
140962306a36Sopenharmony_ci		       rc);
141062306a36Sopenharmony_ci		goto out_free;
141162306a36Sopenharmony_ci	}
141262306a36Sopenharmony_ci	if (unlikely(body_size < (ECRYPTFS_SALT_SIZE + 5))) {
141362306a36Sopenharmony_ci		printk(KERN_WARNING "Invalid body size ([%td])\n", body_size);
141462306a36Sopenharmony_ci		rc = -EINVAL;
141562306a36Sopenharmony_ci		goto out_free;
141662306a36Sopenharmony_ci	}
141762306a36Sopenharmony_ci	(*packet_size) += length_size;
141862306a36Sopenharmony_ci	if (unlikely((*packet_size) + body_size > max_packet_size)) {
141962306a36Sopenharmony_ci		printk(KERN_ERR "Packet size exceeds max\n");
142062306a36Sopenharmony_ci		rc = -EINVAL;
142162306a36Sopenharmony_ci		goto out_free;
142262306a36Sopenharmony_ci	}
142362306a36Sopenharmony_ci	(*new_auth_tok)->session_key.encrypted_key_size =
142462306a36Sopenharmony_ci		(body_size - (ECRYPTFS_SALT_SIZE + 5));
142562306a36Sopenharmony_ci	if ((*new_auth_tok)->session_key.encrypted_key_size
142662306a36Sopenharmony_ci	    > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) {
142762306a36Sopenharmony_ci		printk(KERN_WARNING "Tag 3 packet contains key larger "
142862306a36Sopenharmony_ci		       "than ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES\n");
142962306a36Sopenharmony_ci		rc = -EINVAL;
143062306a36Sopenharmony_ci		goto out_free;
143162306a36Sopenharmony_ci	}
143262306a36Sopenharmony_ci	if (unlikely(data[(*packet_size)++] != 0x04)) {
143362306a36Sopenharmony_ci		printk(KERN_WARNING "Unknown version number [%d]\n",
143462306a36Sopenharmony_ci		       data[(*packet_size) - 1]);
143562306a36Sopenharmony_ci		rc = -EINVAL;
143662306a36Sopenharmony_ci		goto out_free;
143762306a36Sopenharmony_ci	}
143862306a36Sopenharmony_ci	rc = ecryptfs_cipher_code_to_string(crypt_stat->cipher,
143962306a36Sopenharmony_ci					    (u16)data[(*packet_size)]);
144062306a36Sopenharmony_ci	if (rc)
144162306a36Sopenharmony_ci		goto out_free;
144262306a36Sopenharmony_ci	/* A little extra work to differentiate among the AES key
144362306a36Sopenharmony_ci	 * sizes; see RFC2440 */
144462306a36Sopenharmony_ci	switch(data[(*packet_size)++]) {
144562306a36Sopenharmony_ci	case RFC2440_CIPHER_AES_192:
144662306a36Sopenharmony_ci		crypt_stat->key_size = 24;
144762306a36Sopenharmony_ci		break;
144862306a36Sopenharmony_ci	default:
144962306a36Sopenharmony_ci		crypt_stat->key_size =
145062306a36Sopenharmony_ci			(*new_auth_tok)->session_key.encrypted_key_size;
145162306a36Sopenharmony_ci	}
145262306a36Sopenharmony_ci	rc = ecryptfs_init_crypt_ctx(crypt_stat);
145362306a36Sopenharmony_ci	if (rc)
145462306a36Sopenharmony_ci		goto out_free;
145562306a36Sopenharmony_ci	if (unlikely(data[(*packet_size)++] != 0x03)) {
145662306a36Sopenharmony_ci		printk(KERN_WARNING "Only S2K ID 3 is currently supported\n");
145762306a36Sopenharmony_ci		rc = -ENOSYS;
145862306a36Sopenharmony_ci		goto out_free;
145962306a36Sopenharmony_ci	}
146062306a36Sopenharmony_ci	/* TODO: finish the hash mapping */
146162306a36Sopenharmony_ci	switch (data[(*packet_size)++]) {
146262306a36Sopenharmony_ci	case 0x01: /* See RFC2440 for these numbers and their mappings */
146362306a36Sopenharmony_ci		/* Choose MD5 */
146462306a36Sopenharmony_ci		memcpy((*new_auth_tok)->token.password.salt,
146562306a36Sopenharmony_ci		       &data[(*packet_size)], ECRYPTFS_SALT_SIZE);
146662306a36Sopenharmony_ci		(*packet_size) += ECRYPTFS_SALT_SIZE;
146762306a36Sopenharmony_ci		/* This conversion was taken straight from RFC2440 */
146862306a36Sopenharmony_ci		(*new_auth_tok)->token.password.hash_iterations =
146962306a36Sopenharmony_ci			((u32) 16 + (data[(*packet_size)] & 15))
147062306a36Sopenharmony_ci				<< ((data[(*packet_size)] >> 4) + 6);
147162306a36Sopenharmony_ci		(*packet_size)++;
147262306a36Sopenharmony_ci		/* Friendly reminder:
147362306a36Sopenharmony_ci		 * (*new_auth_tok)->session_key.encrypted_key_size =
147462306a36Sopenharmony_ci		 *         (body_size - (ECRYPTFS_SALT_SIZE + 5)); */
147562306a36Sopenharmony_ci		memcpy((*new_auth_tok)->session_key.encrypted_key,
147662306a36Sopenharmony_ci		       &data[(*packet_size)],
147762306a36Sopenharmony_ci		       (*new_auth_tok)->session_key.encrypted_key_size);
147862306a36Sopenharmony_ci		(*packet_size) +=
147962306a36Sopenharmony_ci			(*new_auth_tok)->session_key.encrypted_key_size;
148062306a36Sopenharmony_ci		(*new_auth_tok)->session_key.flags &=
148162306a36Sopenharmony_ci			~ECRYPTFS_CONTAINS_DECRYPTED_KEY;
148262306a36Sopenharmony_ci		(*new_auth_tok)->session_key.flags |=
148362306a36Sopenharmony_ci			ECRYPTFS_CONTAINS_ENCRYPTED_KEY;
148462306a36Sopenharmony_ci		(*new_auth_tok)->token.password.hash_algo = 0x01; /* MD5 */
148562306a36Sopenharmony_ci		break;
148662306a36Sopenharmony_ci	default:
148762306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Unsupported hash algorithm: "
148862306a36Sopenharmony_ci				"[%d]\n", data[(*packet_size) - 1]);
148962306a36Sopenharmony_ci		rc = -ENOSYS;
149062306a36Sopenharmony_ci		goto out_free;
149162306a36Sopenharmony_ci	}
149262306a36Sopenharmony_ci	(*new_auth_tok)->token_type = ECRYPTFS_PASSWORD;
149362306a36Sopenharmony_ci	/* TODO: Parametarize; we might actually want userspace to
149462306a36Sopenharmony_ci	 * decrypt the session key. */
149562306a36Sopenharmony_ci	(*new_auth_tok)->session_key.flags &=
149662306a36Sopenharmony_ci			    ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT);
149762306a36Sopenharmony_ci	(*new_auth_tok)->session_key.flags &=
149862306a36Sopenharmony_ci			    ~(ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT);
149962306a36Sopenharmony_ci	list_add(&auth_tok_list_item->list, auth_tok_list);
150062306a36Sopenharmony_ci	goto out;
150162306a36Sopenharmony_ciout_free:
150262306a36Sopenharmony_ci	(*new_auth_tok) = NULL;
150362306a36Sopenharmony_ci	memset(auth_tok_list_item, 0,
150462306a36Sopenharmony_ci	       sizeof(struct ecryptfs_auth_tok_list_item));
150562306a36Sopenharmony_ci	kmem_cache_free(ecryptfs_auth_tok_list_item_cache,
150662306a36Sopenharmony_ci			auth_tok_list_item);
150762306a36Sopenharmony_ciout:
150862306a36Sopenharmony_ci	if (rc)
150962306a36Sopenharmony_ci		(*packet_size) = 0;
151062306a36Sopenharmony_ci	return rc;
151162306a36Sopenharmony_ci}
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci/**
151462306a36Sopenharmony_ci * parse_tag_11_packet
151562306a36Sopenharmony_ci * @data: The raw bytes of the packet
151662306a36Sopenharmony_ci * @contents: This function writes the data contents of the literal
151762306a36Sopenharmony_ci *            packet into this memory location
151862306a36Sopenharmony_ci * @max_contents_bytes: The maximum number of bytes that this function
151962306a36Sopenharmony_ci *                      is allowed to write into contents
152062306a36Sopenharmony_ci * @tag_11_contents_size: This function writes the size of the parsed
152162306a36Sopenharmony_ci *                        contents into this memory location; zero on
152262306a36Sopenharmony_ci *                        error
152362306a36Sopenharmony_ci * @packet_size: This function writes the size of the parsed packet
152462306a36Sopenharmony_ci *               into this memory location; zero on error
152562306a36Sopenharmony_ci * @max_packet_size: maximum number of bytes to parse
152662306a36Sopenharmony_ci *
152762306a36Sopenharmony_ci * Returns zero on success; non-zero on error.
152862306a36Sopenharmony_ci */
152962306a36Sopenharmony_cistatic int
153062306a36Sopenharmony_ciparse_tag_11_packet(unsigned char *data, unsigned char *contents,
153162306a36Sopenharmony_ci		    size_t max_contents_bytes, size_t *tag_11_contents_size,
153262306a36Sopenharmony_ci		    size_t *packet_size, size_t max_packet_size)
153362306a36Sopenharmony_ci{
153462306a36Sopenharmony_ci	size_t body_size;
153562306a36Sopenharmony_ci	size_t length_size;
153662306a36Sopenharmony_ci	int rc = 0;
153762306a36Sopenharmony_ci
153862306a36Sopenharmony_ci	(*packet_size) = 0;
153962306a36Sopenharmony_ci	(*tag_11_contents_size) = 0;
154062306a36Sopenharmony_ci	/* This format is inspired by OpenPGP; see RFC 2440
154162306a36Sopenharmony_ci	 * packet tag 11
154262306a36Sopenharmony_ci	 *
154362306a36Sopenharmony_ci	 * Tag 11 identifier (1 byte)
154462306a36Sopenharmony_ci	 * Max Tag 11 packet size (max 3 bytes)
154562306a36Sopenharmony_ci	 * Binary format specifier (1 byte)
154662306a36Sopenharmony_ci	 * Filename length (1 byte)
154762306a36Sopenharmony_ci	 * Filename ("_CONSOLE") (8 bytes)
154862306a36Sopenharmony_ci	 * Modification date (4 bytes)
154962306a36Sopenharmony_ci	 * Literal data (arbitrary)
155062306a36Sopenharmony_ci	 *
155162306a36Sopenharmony_ci	 * We need at least 16 bytes of data for the packet to even be
155262306a36Sopenharmony_ci	 * valid.
155362306a36Sopenharmony_ci	 */
155462306a36Sopenharmony_ci	if (max_packet_size < 16) {
155562306a36Sopenharmony_ci		printk(KERN_ERR "Maximum packet size too small\n");
155662306a36Sopenharmony_ci		rc = -EINVAL;
155762306a36Sopenharmony_ci		goto out;
155862306a36Sopenharmony_ci	}
155962306a36Sopenharmony_ci	if (data[(*packet_size)++] != ECRYPTFS_TAG_11_PACKET_TYPE) {
156062306a36Sopenharmony_ci		printk(KERN_WARNING "Invalid tag 11 packet format\n");
156162306a36Sopenharmony_ci		rc = -EINVAL;
156262306a36Sopenharmony_ci		goto out;
156362306a36Sopenharmony_ci	}
156462306a36Sopenharmony_ci	rc = ecryptfs_parse_packet_length(&data[(*packet_size)], &body_size,
156562306a36Sopenharmony_ci					  &length_size);
156662306a36Sopenharmony_ci	if (rc) {
156762306a36Sopenharmony_ci		printk(KERN_WARNING "Invalid tag 11 packet format\n");
156862306a36Sopenharmony_ci		goto out;
156962306a36Sopenharmony_ci	}
157062306a36Sopenharmony_ci	if (body_size < 14) {
157162306a36Sopenharmony_ci		printk(KERN_WARNING "Invalid body size ([%td])\n", body_size);
157262306a36Sopenharmony_ci		rc = -EINVAL;
157362306a36Sopenharmony_ci		goto out;
157462306a36Sopenharmony_ci	}
157562306a36Sopenharmony_ci	(*packet_size) += length_size;
157662306a36Sopenharmony_ci	(*tag_11_contents_size) = (body_size - 14);
157762306a36Sopenharmony_ci	if (unlikely((*packet_size) + body_size + 1 > max_packet_size)) {
157862306a36Sopenharmony_ci		printk(KERN_ERR "Packet size exceeds max\n");
157962306a36Sopenharmony_ci		rc = -EINVAL;
158062306a36Sopenharmony_ci		goto out;
158162306a36Sopenharmony_ci	}
158262306a36Sopenharmony_ci	if (unlikely((*tag_11_contents_size) > max_contents_bytes)) {
158362306a36Sopenharmony_ci		printk(KERN_ERR "Literal data section in tag 11 packet exceeds "
158462306a36Sopenharmony_ci		       "expected size\n");
158562306a36Sopenharmony_ci		rc = -EINVAL;
158662306a36Sopenharmony_ci		goto out;
158762306a36Sopenharmony_ci	}
158862306a36Sopenharmony_ci	if (data[(*packet_size)++] != 0x62) {
158962306a36Sopenharmony_ci		printk(KERN_WARNING "Unrecognizable packet\n");
159062306a36Sopenharmony_ci		rc = -EINVAL;
159162306a36Sopenharmony_ci		goto out;
159262306a36Sopenharmony_ci	}
159362306a36Sopenharmony_ci	if (data[(*packet_size)++] != 0x08) {
159462306a36Sopenharmony_ci		printk(KERN_WARNING "Unrecognizable packet\n");
159562306a36Sopenharmony_ci		rc = -EINVAL;
159662306a36Sopenharmony_ci		goto out;
159762306a36Sopenharmony_ci	}
159862306a36Sopenharmony_ci	(*packet_size) += 12; /* Ignore filename and modification date */
159962306a36Sopenharmony_ci	memcpy(contents, &data[(*packet_size)], (*tag_11_contents_size));
160062306a36Sopenharmony_ci	(*packet_size) += (*tag_11_contents_size);
160162306a36Sopenharmony_ciout:
160262306a36Sopenharmony_ci	if (rc) {
160362306a36Sopenharmony_ci		(*packet_size) = 0;
160462306a36Sopenharmony_ci		(*tag_11_contents_size) = 0;
160562306a36Sopenharmony_ci	}
160662306a36Sopenharmony_ci	return rc;
160762306a36Sopenharmony_ci}
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ciint ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
161062306a36Sopenharmony_ci				      struct ecryptfs_auth_tok **auth_tok,
161162306a36Sopenharmony_ci				      char *sig)
161262306a36Sopenharmony_ci{
161362306a36Sopenharmony_ci	int rc = 0;
161462306a36Sopenharmony_ci
161562306a36Sopenharmony_ci	(*auth_tok_key) = request_key(&key_type_user, sig, NULL);
161662306a36Sopenharmony_ci	if (IS_ERR(*auth_tok_key)) {
161762306a36Sopenharmony_ci		(*auth_tok_key) = ecryptfs_get_encrypted_key(sig);
161862306a36Sopenharmony_ci		if (IS_ERR(*auth_tok_key)) {
161962306a36Sopenharmony_ci			printk(KERN_ERR "Could not find key with description: [%s]\n",
162062306a36Sopenharmony_ci			      sig);
162162306a36Sopenharmony_ci			rc = process_request_key_err(PTR_ERR(*auth_tok_key));
162262306a36Sopenharmony_ci			(*auth_tok_key) = NULL;
162362306a36Sopenharmony_ci			goto out;
162462306a36Sopenharmony_ci		}
162562306a36Sopenharmony_ci	}
162662306a36Sopenharmony_ci	down_write(&(*auth_tok_key)->sem);
162762306a36Sopenharmony_ci	rc = ecryptfs_verify_auth_tok_from_key(*auth_tok_key, auth_tok);
162862306a36Sopenharmony_ci	if (rc) {
162962306a36Sopenharmony_ci		up_write(&(*auth_tok_key)->sem);
163062306a36Sopenharmony_ci		key_put(*auth_tok_key);
163162306a36Sopenharmony_ci		(*auth_tok_key) = NULL;
163262306a36Sopenharmony_ci		goto out;
163362306a36Sopenharmony_ci	}
163462306a36Sopenharmony_ciout:
163562306a36Sopenharmony_ci	return rc;
163662306a36Sopenharmony_ci}
163762306a36Sopenharmony_ci
163862306a36Sopenharmony_ci/**
163962306a36Sopenharmony_ci * decrypt_passphrase_encrypted_session_key - Decrypt the session key with the given auth_tok.
164062306a36Sopenharmony_ci * @auth_tok: The passphrase authentication token to use to encrypt the FEK
164162306a36Sopenharmony_ci * @crypt_stat: The cryptographic context
164262306a36Sopenharmony_ci *
164362306a36Sopenharmony_ci * Returns zero on success; non-zero error otherwise
164462306a36Sopenharmony_ci */
164562306a36Sopenharmony_cistatic int
164662306a36Sopenharmony_cidecrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,
164762306a36Sopenharmony_ci					 struct ecryptfs_crypt_stat *crypt_stat)
164862306a36Sopenharmony_ci{
164962306a36Sopenharmony_ci	struct scatterlist dst_sg[2];
165062306a36Sopenharmony_ci	struct scatterlist src_sg[2];
165162306a36Sopenharmony_ci	struct mutex *tfm_mutex;
165262306a36Sopenharmony_ci	struct crypto_skcipher *tfm;
165362306a36Sopenharmony_ci	struct skcipher_request *req = NULL;
165462306a36Sopenharmony_ci	int rc = 0;
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_ci	if (unlikely(ecryptfs_verbosity > 0)) {
165762306a36Sopenharmony_ci		ecryptfs_printk(
165862306a36Sopenharmony_ci			KERN_DEBUG, "Session key encryption key (size [%d]):\n",
165962306a36Sopenharmony_ci			auth_tok->token.password.session_key_encryption_key_bytes);
166062306a36Sopenharmony_ci		ecryptfs_dump_hex(
166162306a36Sopenharmony_ci			auth_tok->token.password.session_key_encryption_key,
166262306a36Sopenharmony_ci			auth_tok->token.password.session_key_encryption_key_bytes);
166362306a36Sopenharmony_ci	}
166462306a36Sopenharmony_ci	rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&tfm, &tfm_mutex,
166562306a36Sopenharmony_ci							crypt_stat->cipher);
166662306a36Sopenharmony_ci	if (unlikely(rc)) {
166762306a36Sopenharmony_ci		printk(KERN_ERR "Internal error whilst attempting to get "
166862306a36Sopenharmony_ci		       "tfm and mutex for cipher name [%s]; rc = [%d]\n",
166962306a36Sopenharmony_ci		       crypt_stat->cipher, rc);
167062306a36Sopenharmony_ci		goto out;
167162306a36Sopenharmony_ci	}
167262306a36Sopenharmony_ci	rc = virt_to_scatterlist(auth_tok->session_key.encrypted_key,
167362306a36Sopenharmony_ci				 auth_tok->session_key.encrypted_key_size,
167462306a36Sopenharmony_ci				 src_sg, 2);
167562306a36Sopenharmony_ci	if (rc < 1 || rc > 2) {
167662306a36Sopenharmony_ci		printk(KERN_ERR "Internal error whilst attempting to convert "
167762306a36Sopenharmony_ci			"auth_tok->session_key.encrypted_key to scatterlist; "
167862306a36Sopenharmony_ci			"expected rc = 1; got rc = [%d]. "
167962306a36Sopenharmony_ci		       "auth_tok->session_key.encrypted_key_size = [%d]\n", rc,
168062306a36Sopenharmony_ci			auth_tok->session_key.encrypted_key_size);
168162306a36Sopenharmony_ci		goto out;
168262306a36Sopenharmony_ci	}
168362306a36Sopenharmony_ci	auth_tok->session_key.decrypted_key_size =
168462306a36Sopenharmony_ci		auth_tok->session_key.encrypted_key_size;
168562306a36Sopenharmony_ci	rc = virt_to_scatterlist(auth_tok->session_key.decrypted_key,
168662306a36Sopenharmony_ci				 auth_tok->session_key.decrypted_key_size,
168762306a36Sopenharmony_ci				 dst_sg, 2);
168862306a36Sopenharmony_ci	if (rc < 1 || rc > 2) {
168962306a36Sopenharmony_ci		printk(KERN_ERR "Internal error whilst attempting to convert "
169062306a36Sopenharmony_ci			"auth_tok->session_key.decrypted_key to scatterlist; "
169162306a36Sopenharmony_ci			"expected rc = 1; got rc = [%d]\n", rc);
169262306a36Sopenharmony_ci		goto out;
169362306a36Sopenharmony_ci	}
169462306a36Sopenharmony_ci	mutex_lock(tfm_mutex);
169562306a36Sopenharmony_ci	req = skcipher_request_alloc(tfm, GFP_KERNEL);
169662306a36Sopenharmony_ci	if (!req) {
169762306a36Sopenharmony_ci		mutex_unlock(tfm_mutex);
169862306a36Sopenharmony_ci		printk(KERN_ERR "%s: Out of kernel memory whilst attempting to "
169962306a36Sopenharmony_ci		       "skcipher_request_alloc for %s\n", __func__,
170062306a36Sopenharmony_ci		       crypto_skcipher_driver_name(tfm));
170162306a36Sopenharmony_ci		rc = -ENOMEM;
170262306a36Sopenharmony_ci		goto out;
170362306a36Sopenharmony_ci	}
170462306a36Sopenharmony_ci
170562306a36Sopenharmony_ci	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
170662306a36Sopenharmony_ci				      NULL, NULL);
170762306a36Sopenharmony_ci	rc = crypto_skcipher_setkey(
170862306a36Sopenharmony_ci		tfm, auth_tok->token.password.session_key_encryption_key,
170962306a36Sopenharmony_ci		crypt_stat->key_size);
171062306a36Sopenharmony_ci	if (unlikely(rc < 0)) {
171162306a36Sopenharmony_ci		mutex_unlock(tfm_mutex);
171262306a36Sopenharmony_ci		printk(KERN_ERR "Error setting key for crypto context\n");
171362306a36Sopenharmony_ci		rc = -EINVAL;
171462306a36Sopenharmony_ci		goto out;
171562306a36Sopenharmony_ci	}
171662306a36Sopenharmony_ci	skcipher_request_set_crypt(req, src_sg, dst_sg,
171762306a36Sopenharmony_ci				   auth_tok->session_key.encrypted_key_size,
171862306a36Sopenharmony_ci				   NULL);
171962306a36Sopenharmony_ci	rc = crypto_skcipher_decrypt(req);
172062306a36Sopenharmony_ci	mutex_unlock(tfm_mutex);
172162306a36Sopenharmony_ci	if (unlikely(rc)) {
172262306a36Sopenharmony_ci		printk(KERN_ERR "Error decrypting; rc = [%d]\n", rc);
172362306a36Sopenharmony_ci		goto out;
172462306a36Sopenharmony_ci	}
172562306a36Sopenharmony_ci	auth_tok->session_key.flags |= ECRYPTFS_CONTAINS_DECRYPTED_KEY;
172662306a36Sopenharmony_ci	memcpy(crypt_stat->key, auth_tok->session_key.decrypted_key,
172762306a36Sopenharmony_ci	       auth_tok->session_key.decrypted_key_size);
172862306a36Sopenharmony_ci	crypt_stat->flags |= ECRYPTFS_KEY_VALID;
172962306a36Sopenharmony_ci	if (unlikely(ecryptfs_verbosity > 0)) {
173062306a36Sopenharmony_ci		ecryptfs_printk(KERN_DEBUG, "FEK of size [%zd]:\n",
173162306a36Sopenharmony_ci				crypt_stat->key_size);
173262306a36Sopenharmony_ci		ecryptfs_dump_hex(crypt_stat->key,
173362306a36Sopenharmony_ci				  crypt_stat->key_size);
173462306a36Sopenharmony_ci	}
173562306a36Sopenharmony_ciout:
173662306a36Sopenharmony_ci	skcipher_request_free(req);
173762306a36Sopenharmony_ci	return rc;
173862306a36Sopenharmony_ci}
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_ci/**
174162306a36Sopenharmony_ci * ecryptfs_parse_packet_set
174262306a36Sopenharmony_ci * @crypt_stat: The cryptographic context
174362306a36Sopenharmony_ci * @src: Virtual address of region of memory containing the packets
174462306a36Sopenharmony_ci * @ecryptfs_dentry: The eCryptfs dentry associated with the packet set
174562306a36Sopenharmony_ci *
174662306a36Sopenharmony_ci * Get crypt_stat to have the file's session key if the requisite key
174762306a36Sopenharmony_ci * is available to decrypt the session key.
174862306a36Sopenharmony_ci *
174962306a36Sopenharmony_ci * Returns Zero if a valid authentication token was retrieved and
175062306a36Sopenharmony_ci * processed; negative value for file not encrypted or for error
175162306a36Sopenharmony_ci * conditions.
175262306a36Sopenharmony_ci */
175362306a36Sopenharmony_ciint ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,
175462306a36Sopenharmony_ci			      unsigned char *src,
175562306a36Sopenharmony_ci			      struct dentry *ecryptfs_dentry)
175662306a36Sopenharmony_ci{
175762306a36Sopenharmony_ci	size_t i = 0;
175862306a36Sopenharmony_ci	size_t found_auth_tok;
175962306a36Sopenharmony_ci	size_t next_packet_is_auth_tok_packet;
176062306a36Sopenharmony_ci	struct list_head auth_tok_list;
176162306a36Sopenharmony_ci	struct ecryptfs_auth_tok *matching_auth_tok;
176262306a36Sopenharmony_ci	struct ecryptfs_auth_tok *candidate_auth_tok;
176362306a36Sopenharmony_ci	char *candidate_auth_tok_sig;
176462306a36Sopenharmony_ci	size_t packet_size;
176562306a36Sopenharmony_ci	struct ecryptfs_auth_tok *new_auth_tok;
176662306a36Sopenharmony_ci	unsigned char sig_tmp_space[ECRYPTFS_SIG_SIZE];
176762306a36Sopenharmony_ci	struct ecryptfs_auth_tok_list_item *auth_tok_list_item;
176862306a36Sopenharmony_ci	size_t tag_11_contents_size;
176962306a36Sopenharmony_ci	size_t tag_11_packet_size;
177062306a36Sopenharmony_ci	struct key *auth_tok_key = NULL;
177162306a36Sopenharmony_ci	int rc = 0;
177262306a36Sopenharmony_ci
177362306a36Sopenharmony_ci	INIT_LIST_HEAD(&auth_tok_list);
177462306a36Sopenharmony_ci	/* Parse the header to find as many packets as we can; these will be
177562306a36Sopenharmony_ci	 * added the our &auth_tok_list */
177662306a36Sopenharmony_ci	next_packet_is_auth_tok_packet = 1;
177762306a36Sopenharmony_ci	while (next_packet_is_auth_tok_packet) {
177862306a36Sopenharmony_ci		size_t max_packet_size = ((PAGE_SIZE - 8) - i);
177962306a36Sopenharmony_ci
178062306a36Sopenharmony_ci		switch (src[i]) {
178162306a36Sopenharmony_ci		case ECRYPTFS_TAG_3_PACKET_TYPE:
178262306a36Sopenharmony_ci			rc = parse_tag_3_packet(crypt_stat,
178362306a36Sopenharmony_ci						(unsigned char *)&src[i],
178462306a36Sopenharmony_ci						&auth_tok_list, &new_auth_tok,
178562306a36Sopenharmony_ci						&packet_size, max_packet_size);
178662306a36Sopenharmony_ci			if (rc) {
178762306a36Sopenharmony_ci				ecryptfs_printk(KERN_ERR, "Error parsing "
178862306a36Sopenharmony_ci						"tag 3 packet\n");
178962306a36Sopenharmony_ci				rc = -EIO;
179062306a36Sopenharmony_ci				goto out_wipe_list;
179162306a36Sopenharmony_ci			}
179262306a36Sopenharmony_ci			i += packet_size;
179362306a36Sopenharmony_ci			rc = parse_tag_11_packet((unsigned char *)&src[i],
179462306a36Sopenharmony_ci						 sig_tmp_space,
179562306a36Sopenharmony_ci						 ECRYPTFS_SIG_SIZE,
179662306a36Sopenharmony_ci						 &tag_11_contents_size,
179762306a36Sopenharmony_ci						 &tag_11_packet_size,
179862306a36Sopenharmony_ci						 max_packet_size);
179962306a36Sopenharmony_ci			if (rc) {
180062306a36Sopenharmony_ci				ecryptfs_printk(KERN_ERR, "No valid "
180162306a36Sopenharmony_ci						"(ecryptfs-specific) literal "
180262306a36Sopenharmony_ci						"packet containing "
180362306a36Sopenharmony_ci						"authentication token "
180462306a36Sopenharmony_ci						"signature found after "
180562306a36Sopenharmony_ci						"tag 3 packet\n");
180662306a36Sopenharmony_ci				rc = -EIO;
180762306a36Sopenharmony_ci				goto out_wipe_list;
180862306a36Sopenharmony_ci			}
180962306a36Sopenharmony_ci			i += tag_11_packet_size;
181062306a36Sopenharmony_ci			if (ECRYPTFS_SIG_SIZE != tag_11_contents_size) {
181162306a36Sopenharmony_ci				ecryptfs_printk(KERN_ERR, "Expected "
181262306a36Sopenharmony_ci						"signature of size [%d]; "
181362306a36Sopenharmony_ci						"read size [%zd]\n",
181462306a36Sopenharmony_ci						ECRYPTFS_SIG_SIZE,
181562306a36Sopenharmony_ci						tag_11_contents_size);
181662306a36Sopenharmony_ci				rc = -EIO;
181762306a36Sopenharmony_ci				goto out_wipe_list;
181862306a36Sopenharmony_ci			}
181962306a36Sopenharmony_ci			ecryptfs_to_hex(new_auth_tok->token.password.signature,
182062306a36Sopenharmony_ci					sig_tmp_space, tag_11_contents_size);
182162306a36Sopenharmony_ci			new_auth_tok->token.password.signature[
182262306a36Sopenharmony_ci				ECRYPTFS_PASSWORD_SIG_SIZE] = '\0';
182362306a36Sopenharmony_ci			crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
182462306a36Sopenharmony_ci			break;
182562306a36Sopenharmony_ci		case ECRYPTFS_TAG_1_PACKET_TYPE:
182662306a36Sopenharmony_ci			rc = parse_tag_1_packet(crypt_stat,
182762306a36Sopenharmony_ci						(unsigned char *)&src[i],
182862306a36Sopenharmony_ci						&auth_tok_list, &new_auth_tok,
182962306a36Sopenharmony_ci						&packet_size, max_packet_size);
183062306a36Sopenharmony_ci			if (rc) {
183162306a36Sopenharmony_ci				ecryptfs_printk(KERN_ERR, "Error parsing "
183262306a36Sopenharmony_ci						"tag 1 packet\n");
183362306a36Sopenharmony_ci				rc = -EIO;
183462306a36Sopenharmony_ci				goto out_wipe_list;
183562306a36Sopenharmony_ci			}
183662306a36Sopenharmony_ci			i += packet_size;
183762306a36Sopenharmony_ci			crypt_stat->flags |= ECRYPTFS_ENCRYPTED;
183862306a36Sopenharmony_ci			break;
183962306a36Sopenharmony_ci		case ECRYPTFS_TAG_11_PACKET_TYPE:
184062306a36Sopenharmony_ci			ecryptfs_printk(KERN_WARNING, "Invalid packet set "
184162306a36Sopenharmony_ci					"(Tag 11 not allowed by itself)\n");
184262306a36Sopenharmony_ci			rc = -EIO;
184362306a36Sopenharmony_ci			goto out_wipe_list;
184462306a36Sopenharmony_ci		default:
184562306a36Sopenharmony_ci			ecryptfs_printk(KERN_DEBUG, "No packet at offset [%zd] "
184662306a36Sopenharmony_ci					"of the file header; hex value of "
184762306a36Sopenharmony_ci					"character is [0x%.2x]\n", i, src[i]);
184862306a36Sopenharmony_ci			next_packet_is_auth_tok_packet = 0;
184962306a36Sopenharmony_ci		}
185062306a36Sopenharmony_ci	}
185162306a36Sopenharmony_ci	if (list_empty(&auth_tok_list)) {
185262306a36Sopenharmony_ci		printk(KERN_ERR "The lower file appears to be a non-encrypted "
185362306a36Sopenharmony_ci		       "eCryptfs file; this is not supported in this version "
185462306a36Sopenharmony_ci		       "of the eCryptfs kernel module\n");
185562306a36Sopenharmony_ci		rc = -EINVAL;
185662306a36Sopenharmony_ci		goto out;
185762306a36Sopenharmony_ci	}
185862306a36Sopenharmony_ci	/* auth_tok_list contains the set of authentication tokens
185962306a36Sopenharmony_ci	 * parsed from the metadata. We need to find a matching
186062306a36Sopenharmony_ci	 * authentication token that has the secret component(s)
186162306a36Sopenharmony_ci	 * necessary to decrypt the EFEK in the auth_tok parsed from
186262306a36Sopenharmony_ci	 * the metadata. There may be several potential matches, but
186362306a36Sopenharmony_ci	 * just one will be sufficient to decrypt to get the FEK. */
186462306a36Sopenharmony_cifind_next_matching_auth_tok:
186562306a36Sopenharmony_ci	found_auth_tok = 0;
186662306a36Sopenharmony_ci	list_for_each_entry(auth_tok_list_item, &auth_tok_list, list) {
186762306a36Sopenharmony_ci		candidate_auth_tok = &auth_tok_list_item->auth_tok;
186862306a36Sopenharmony_ci		if (unlikely(ecryptfs_verbosity > 0)) {
186962306a36Sopenharmony_ci			ecryptfs_printk(KERN_DEBUG,
187062306a36Sopenharmony_ci					"Considering candidate auth tok:\n");
187162306a36Sopenharmony_ci			ecryptfs_dump_auth_tok(candidate_auth_tok);
187262306a36Sopenharmony_ci		}
187362306a36Sopenharmony_ci		rc = ecryptfs_get_auth_tok_sig(&candidate_auth_tok_sig,
187462306a36Sopenharmony_ci					       candidate_auth_tok);
187562306a36Sopenharmony_ci		if (rc) {
187662306a36Sopenharmony_ci			printk(KERN_ERR
187762306a36Sopenharmony_ci			       "Unrecognized candidate auth tok type: [%d]\n",
187862306a36Sopenharmony_ci			       candidate_auth_tok->token_type);
187962306a36Sopenharmony_ci			rc = -EINVAL;
188062306a36Sopenharmony_ci			goto out_wipe_list;
188162306a36Sopenharmony_ci		}
188262306a36Sopenharmony_ci		rc = ecryptfs_find_auth_tok_for_sig(&auth_tok_key,
188362306a36Sopenharmony_ci					       &matching_auth_tok,
188462306a36Sopenharmony_ci					       crypt_stat->mount_crypt_stat,
188562306a36Sopenharmony_ci					       candidate_auth_tok_sig);
188662306a36Sopenharmony_ci		if (!rc) {
188762306a36Sopenharmony_ci			found_auth_tok = 1;
188862306a36Sopenharmony_ci			goto found_matching_auth_tok;
188962306a36Sopenharmony_ci		}
189062306a36Sopenharmony_ci	}
189162306a36Sopenharmony_ci	if (!found_auth_tok) {
189262306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Could not find a usable "
189362306a36Sopenharmony_ci				"authentication token\n");
189462306a36Sopenharmony_ci		rc = -EIO;
189562306a36Sopenharmony_ci		goto out_wipe_list;
189662306a36Sopenharmony_ci	}
189762306a36Sopenharmony_cifound_matching_auth_tok:
189862306a36Sopenharmony_ci	if (candidate_auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
189962306a36Sopenharmony_ci		memcpy(&(candidate_auth_tok->token.private_key),
190062306a36Sopenharmony_ci		       &(matching_auth_tok->token.private_key),
190162306a36Sopenharmony_ci		       sizeof(struct ecryptfs_private_key));
190262306a36Sopenharmony_ci		up_write(&(auth_tok_key->sem));
190362306a36Sopenharmony_ci		key_put(auth_tok_key);
190462306a36Sopenharmony_ci		rc = decrypt_pki_encrypted_session_key(candidate_auth_tok,
190562306a36Sopenharmony_ci						       crypt_stat);
190662306a36Sopenharmony_ci	} else if (candidate_auth_tok->token_type == ECRYPTFS_PASSWORD) {
190762306a36Sopenharmony_ci		memcpy(&(candidate_auth_tok->token.password),
190862306a36Sopenharmony_ci		       &(matching_auth_tok->token.password),
190962306a36Sopenharmony_ci		       sizeof(struct ecryptfs_password));
191062306a36Sopenharmony_ci		up_write(&(auth_tok_key->sem));
191162306a36Sopenharmony_ci		key_put(auth_tok_key);
191262306a36Sopenharmony_ci		rc = decrypt_passphrase_encrypted_session_key(
191362306a36Sopenharmony_ci			candidate_auth_tok, crypt_stat);
191462306a36Sopenharmony_ci	} else {
191562306a36Sopenharmony_ci		up_write(&(auth_tok_key->sem));
191662306a36Sopenharmony_ci		key_put(auth_tok_key);
191762306a36Sopenharmony_ci		rc = -EINVAL;
191862306a36Sopenharmony_ci	}
191962306a36Sopenharmony_ci	if (rc) {
192062306a36Sopenharmony_ci		struct ecryptfs_auth_tok_list_item *auth_tok_list_item_tmp;
192162306a36Sopenharmony_ci
192262306a36Sopenharmony_ci		ecryptfs_printk(KERN_WARNING, "Error decrypting the "
192362306a36Sopenharmony_ci				"session key for authentication token with sig "
192462306a36Sopenharmony_ci				"[%.*s]; rc = [%d]. Removing auth tok "
192562306a36Sopenharmony_ci				"candidate from the list and searching for "
192662306a36Sopenharmony_ci				"the next match.\n", ECRYPTFS_SIG_SIZE_HEX,
192762306a36Sopenharmony_ci				candidate_auth_tok_sig,	rc);
192862306a36Sopenharmony_ci		list_for_each_entry_safe(auth_tok_list_item,
192962306a36Sopenharmony_ci					 auth_tok_list_item_tmp,
193062306a36Sopenharmony_ci					 &auth_tok_list, list) {
193162306a36Sopenharmony_ci			if (candidate_auth_tok
193262306a36Sopenharmony_ci			    == &auth_tok_list_item->auth_tok) {
193362306a36Sopenharmony_ci				list_del(&auth_tok_list_item->list);
193462306a36Sopenharmony_ci				kmem_cache_free(
193562306a36Sopenharmony_ci					ecryptfs_auth_tok_list_item_cache,
193662306a36Sopenharmony_ci					auth_tok_list_item);
193762306a36Sopenharmony_ci				goto find_next_matching_auth_tok;
193862306a36Sopenharmony_ci			}
193962306a36Sopenharmony_ci		}
194062306a36Sopenharmony_ci		BUG();
194162306a36Sopenharmony_ci	}
194262306a36Sopenharmony_ci	rc = ecryptfs_compute_root_iv(crypt_stat);
194362306a36Sopenharmony_ci	if (rc) {
194462306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error computing "
194562306a36Sopenharmony_ci				"the root IV\n");
194662306a36Sopenharmony_ci		goto out_wipe_list;
194762306a36Sopenharmony_ci	}
194862306a36Sopenharmony_ci	rc = ecryptfs_init_crypt_ctx(crypt_stat);
194962306a36Sopenharmony_ci	if (rc) {
195062306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error initializing crypto "
195162306a36Sopenharmony_ci				"context for cipher [%s]; rc = [%d]\n",
195262306a36Sopenharmony_ci				crypt_stat->cipher, rc);
195362306a36Sopenharmony_ci	}
195462306a36Sopenharmony_ciout_wipe_list:
195562306a36Sopenharmony_ci	wipe_auth_tok_list(&auth_tok_list);
195662306a36Sopenharmony_ciout:
195762306a36Sopenharmony_ci	return rc;
195862306a36Sopenharmony_ci}
195962306a36Sopenharmony_ci
196062306a36Sopenharmony_cistatic int
196162306a36Sopenharmony_cipki_encrypt_session_key(struct key *auth_tok_key,
196262306a36Sopenharmony_ci			struct ecryptfs_auth_tok *auth_tok,
196362306a36Sopenharmony_ci			struct ecryptfs_crypt_stat *crypt_stat,
196462306a36Sopenharmony_ci			struct ecryptfs_key_record *key_rec)
196562306a36Sopenharmony_ci{
196662306a36Sopenharmony_ci	struct ecryptfs_msg_ctx *msg_ctx = NULL;
196762306a36Sopenharmony_ci	char *payload = NULL;
196862306a36Sopenharmony_ci	size_t payload_len = 0;
196962306a36Sopenharmony_ci	struct ecryptfs_message *msg;
197062306a36Sopenharmony_ci	int rc;
197162306a36Sopenharmony_ci
197262306a36Sopenharmony_ci	rc = write_tag_66_packet(auth_tok->token.private_key.signature,
197362306a36Sopenharmony_ci				 ecryptfs_code_for_cipher_string(
197462306a36Sopenharmony_ci					 crypt_stat->cipher,
197562306a36Sopenharmony_ci					 crypt_stat->key_size),
197662306a36Sopenharmony_ci				 crypt_stat, &payload, &payload_len);
197762306a36Sopenharmony_ci	up_write(&(auth_tok_key->sem));
197862306a36Sopenharmony_ci	key_put(auth_tok_key);
197962306a36Sopenharmony_ci	if (rc) {
198062306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n");
198162306a36Sopenharmony_ci		goto out;
198262306a36Sopenharmony_ci	}
198362306a36Sopenharmony_ci	rc = ecryptfs_send_message(payload, payload_len, &msg_ctx);
198462306a36Sopenharmony_ci	if (rc) {
198562306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error sending message to "
198662306a36Sopenharmony_ci				"ecryptfsd: %d\n", rc);
198762306a36Sopenharmony_ci		goto out;
198862306a36Sopenharmony_ci	}
198962306a36Sopenharmony_ci	rc = ecryptfs_wait_for_response(msg_ctx, &msg);
199062306a36Sopenharmony_ci	if (rc) {
199162306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Failed to receive tag 67 packet "
199262306a36Sopenharmony_ci				"from the user space daemon\n");
199362306a36Sopenharmony_ci		rc = -EIO;
199462306a36Sopenharmony_ci		goto out;
199562306a36Sopenharmony_ci	}
199662306a36Sopenharmony_ci	rc = parse_tag_67_packet(key_rec, msg);
199762306a36Sopenharmony_ci	if (rc)
199862306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error parsing tag 67 packet\n");
199962306a36Sopenharmony_ci	kfree(msg);
200062306a36Sopenharmony_ciout:
200162306a36Sopenharmony_ci	kfree(payload);
200262306a36Sopenharmony_ci	return rc;
200362306a36Sopenharmony_ci}
200462306a36Sopenharmony_ci/**
200562306a36Sopenharmony_ci * write_tag_1_packet - Write an RFC2440-compatible tag 1 (public key) packet
200662306a36Sopenharmony_ci * @dest: Buffer into which to write the packet
200762306a36Sopenharmony_ci * @remaining_bytes: Maximum number of bytes that can be writtn
200862306a36Sopenharmony_ci * @auth_tok_key: The authentication token key to unlock and put when done with
200962306a36Sopenharmony_ci *                @auth_tok
201062306a36Sopenharmony_ci * @auth_tok: The authentication token used for generating the tag 1 packet
201162306a36Sopenharmony_ci * @crypt_stat: The cryptographic context
201262306a36Sopenharmony_ci * @key_rec: The key record struct for the tag 1 packet
201362306a36Sopenharmony_ci * @packet_size: This function will write the number of bytes that end
201462306a36Sopenharmony_ci *               up constituting the packet; set to zero on error
201562306a36Sopenharmony_ci *
201662306a36Sopenharmony_ci * Returns zero on success; non-zero on error.
201762306a36Sopenharmony_ci */
201862306a36Sopenharmony_cistatic int
201962306a36Sopenharmony_ciwrite_tag_1_packet(char *dest, size_t *remaining_bytes,
202062306a36Sopenharmony_ci		   struct key *auth_tok_key, struct ecryptfs_auth_tok *auth_tok,
202162306a36Sopenharmony_ci		   struct ecryptfs_crypt_stat *crypt_stat,
202262306a36Sopenharmony_ci		   struct ecryptfs_key_record *key_rec, size_t *packet_size)
202362306a36Sopenharmony_ci{
202462306a36Sopenharmony_ci	size_t i;
202562306a36Sopenharmony_ci	size_t encrypted_session_key_valid = 0;
202662306a36Sopenharmony_ci	size_t packet_size_length;
202762306a36Sopenharmony_ci	size_t max_packet_size;
202862306a36Sopenharmony_ci	int rc = 0;
202962306a36Sopenharmony_ci
203062306a36Sopenharmony_ci	(*packet_size) = 0;
203162306a36Sopenharmony_ci	ecryptfs_from_hex(key_rec->sig, auth_tok->token.private_key.signature,
203262306a36Sopenharmony_ci			  ECRYPTFS_SIG_SIZE);
203362306a36Sopenharmony_ci	encrypted_session_key_valid = 0;
203462306a36Sopenharmony_ci	for (i = 0; i < crypt_stat->key_size; i++)
203562306a36Sopenharmony_ci		encrypted_session_key_valid |=
203662306a36Sopenharmony_ci			auth_tok->session_key.encrypted_key[i];
203762306a36Sopenharmony_ci	if (encrypted_session_key_valid) {
203862306a36Sopenharmony_ci		memcpy(key_rec->enc_key,
203962306a36Sopenharmony_ci		       auth_tok->session_key.encrypted_key,
204062306a36Sopenharmony_ci		       auth_tok->session_key.encrypted_key_size);
204162306a36Sopenharmony_ci		up_write(&(auth_tok_key->sem));
204262306a36Sopenharmony_ci		key_put(auth_tok_key);
204362306a36Sopenharmony_ci		goto encrypted_session_key_set;
204462306a36Sopenharmony_ci	}
204562306a36Sopenharmony_ci	if (auth_tok->session_key.encrypted_key_size == 0)
204662306a36Sopenharmony_ci		auth_tok->session_key.encrypted_key_size =
204762306a36Sopenharmony_ci			auth_tok->token.private_key.key_size;
204862306a36Sopenharmony_ci	rc = pki_encrypt_session_key(auth_tok_key, auth_tok, crypt_stat,
204962306a36Sopenharmony_ci				     key_rec);
205062306a36Sopenharmony_ci	if (rc) {
205162306a36Sopenharmony_ci		printk(KERN_ERR "Failed to encrypt session key via a key "
205262306a36Sopenharmony_ci		       "module; rc = [%d]\n", rc);
205362306a36Sopenharmony_ci		goto out;
205462306a36Sopenharmony_ci	}
205562306a36Sopenharmony_ci	if (ecryptfs_verbosity > 0) {
205662306a36Sopenharmony_ci		ecryptfs_printk(KERN_DEBUG, "Encrypted key:\n");
205762306a36Sopenharmony_ci		ecryptfs_dump_hex(key_rec->enc_key, key_rec->enc_key_size);
205862306a36Sopenharmony_ci	}
205962306a36Sopenharmony_ciencrypted_session_key_set:
206062306a36Sopenharmony_ci	/* This format is inspired by OpenPGP; see RFC 2440
206162306a36Sopenharmony_ci	 * packet tag 1 */
206262306a36Sopenharmony_ci	max_packet_size = (1                         /* Tag 1 identifier */
206362306a36Sopenharmony_ci			   + 3                       /* Max Tag 1 packet size */
206462306a36Sopenharmony_ci			   + 1                       /* Version */
206562306a36Sopenharmony_ci			   + ECRYPTFS_SIG_SIZE       /* Key identifier */
206662306a36Sopenharmony_ci			   + 1                       /* Cipher identifier */
206762306a36Sopenharmony_ci			   + key_rec->enc_key_size); /* Encrypted key size */
206862306a36Sopenharmony_ci	if (max_packet_size > (*remaining_bytes)) {
206962306a36Sopenharmony_ci		printk(KERN_ERR "Packet length larger than maximum allowable; "
207062306a36Sopenharmony_ci		       "need up to [%td] bytes, but there are only [%td] "
207162306a36Sopenharmony_ci		       "available\n", max_packet_size, (*remaining_bytes));
207262306a36Sopenharmony_ci		rc = -EINVAL;
207362306a36Sopenharmony_ci		goto out;
207462306a36Sopenharmony_ci	}
207562306a36Sopenharmony_ci	dest[(*packet_size)++] = ECRYPTFS_TAG_1_PACKET_TYPE;
207662306a36Sopenharmony_ci	rc = ecryptfs_write_packet_length(&dest[(*packet_size)],
207762306a36Sopenharmony_ci					  (max_packet_size - 4),
207862306a36Sopenharmony_ci					  &packet_size_length);
207962306a36Sopenharmony_ci	if (rc) {
208062306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error generating tag 1 packet "
208162306a36Sopenharmony_ci				"header; cannot generate packet length\n");
208262306a36Sopenharmony_ci		goto out;
208362306a36Sopenharmony_ci	}
208462306a36Sopenharmony_ci	(*packet_size) += packet_size_length;
208562306a36Sopenharmony_ci	dest[(*packet_size)++] = 0x03; /* version 3 */
208662306a36Sopenharmony_ci	memcpy(&dest[(*packet_size)], key_rec->sig, ECRYPTFS_SIG_SIZE);
208762306a36Sopenharmony_ci	(*packet_size) += ECRYPTFS_SIG_SIZE;
208862306a36Sopenharmony_ci	dest[(*packet_size)++] = RFC2440_CIPHER_RSA;
208962306a36Sopenharmony_ci	memcpy(&dest[(*packet_size)], key_rec->enc_key,
209062306a36Sopenharmony_ci	       key_rec->enc_key_size);
209162306a36Sopenharmony_ci	(*packet_size) += key_rec->enc_key_size;
209262306a36Sopenharmony_ciout:
209362306a36Sopenharmony_ci	if (rc)
209462306a36Sopenharmony_ci		(*packet_size) = 0;
209562306a36Sopenharmony_ci	else
209662306a36Sopenharmony_ci		(*remaining_bytes) -= (*packet_size);
209762306a36Sopenharmony_ci	return rc;
209862306a36Sopenharmony_ci}
209962306a36Sopenharmony_ci
210062306a36Sopenharmony_ci/**
210162306a36Sopenharmony_ci * write_tag_11_packet
210262306a36Sopenharmony_ci * @dest: Target into which Tag 11 packet is to be written
210362306a36Sopenharmony_ci * @remaining_bytes: Maximum packet length
210462306a36Sopenharmony_ci * @contents: Byte array of contents to copy in
210562306a36Sopenharmony_ci * @contents_length: Number of bytes in contents
210662306a36Sopenharmony_ci * @packet_length: Length of the Tag 11 packet written; zero on error
210762306a36Sopenharmony_ci *
210862306a36Sopenharmony_ci * Returns zero on success; non-zero on error.
210962306a36Sopenharmony_ci */
211062306a36Sopenharmony_cistatic int
211162306a36Sopenharmony_ciwrite_tag_11_packet(char *dest, size_t *remaining_bytes, char *contents,
211262306a36Sopenharmony_ci		    size_t contents_length, size_t *packet_length)
211362306a36Sopenharmony_ci{
211462306a36Sopenharmony_ci	size_t packet_size_length;
211562306a36Sopenharmony_ci	size_t max_packet_size;
211662306a36Sopenharmony_ci	int rc = 0;
211762306a36Sopenharmony_ci
211862306a36Sopenharmony_ci	(*packet_length) = 0;
211962306a36Sopenharmony_ci	/* This format is inspired by OpenPGP; see RFC 2440
212062306a36Sopenharmony_ci	 * packet tag 11 */
212162306a36Sopenharmony_ci	max_packet_size = (1                   /* Tag 11 identifier */
212262306a36Sopenharmony_ci			   + 3                 /* Max Tag 11 packet size */
212362306a36Sopenharmony_ci			   + 1                 /* Binary format specifier */
212462306a36Sopenharmony_ci			   + 1                 /* Filename length */
212562306a36Sopenharmony_ci			   + 8                 /* Filename ("_CONSOLE") */
212662306a36Sopenharmony_ci			   + 4                 /* Modification date */
212762306a36Sopenharmony_ci			   + contents_length); /* Literal data */
212862306a36Sopenharmony_ci	if (max_packet_size > (*remaining_bytes)) {
212962306a36Sopenharmony_ci		printk(KERN_ERR "Packet length larger than maximum allowable; "
213062306a36Sopenharmony_ci		       "need up to [%td] bytes, but there are only [%td] "
213162306a36Sopenharmony_ci		       "available\n", max_packet_size, (*remaining_bytes));
213262306a36Sopenharmony_ci		rc = -EINVAL;
213362306a36Sopenharmony_ci		goto out;
213462306a36Sopenharmony_ci	}
213562306a36Sopenharmony_ci	dest[(*packet_length)++] = ECRYPTFS_TAG_11_PACKET_TYPE;
213662306a36Sopenharmony_ci	rc = ecryptfs_write_packet_length(&dest[(*packet_length)],
213762306a36Sopenharmony_ci					  (max_packet_size - 4),
213862306a36Sopenharmony_ci					  &packet_size_length);
213962306a36Sopenharmony_ci	if (rc) {
214062306a36Sopenharmony_ci		printk(KERN_ERR "Error generating tag 11 packet header; cannot "
214162306a36Sopenharmony_ci		       "generate packet length. rc = [%d]\n", rc);
214262306a36Sopenharmony_ci		goto out;
214362306a36Sopenharmony_ci	}
214462306a36Sopenharmony_ci	(*packet_length) += packet_size_length;
214562306a36Sopenharmony_ci	dest[(*packet_length)++] = 0x62; /* binary data format specifier */
214662306a36Sopenharmony_ci	dest[(*packet_length)++] = 8;
214762306a36Sopenharmony_ci	memcpy(&dest[(*packet_length)], "_CONSOLE", 8);
214862306a36Sopenharmony_ci	(*packet_length) += 8;
214962306a36Sopenharmony_ci	memset(&dest[(*packet_length)], 0x00, 4);
215062306a36Sopenharmony_ci	(*packet_length) += 4;
215162306a36Sopenharmony_ci	memcpy(&dest[(*packet_length)], contents, contents_length);
215262306a36Sopenharmony_ci	(*packet_length) += contents_length;
215362306a36Sopenharmony_ci out:
215462306a36Sopenharmony_ci	if (rc)
215562306a36Sopenharmony_ci		(*packet_length) = 0;
215662306a36Sopenharmony_ci	else
215762306a36Sopenharmony_ci		(*remaining_bytes) -= (*packet_length);
215862306a36Sopenharmony_ci	return rc;
215962306a36Sopenharmony_ci}
216062306a36Sopenharmony_ci
216162306a36Sopenharmony_ci/**
216262306a36Sopenharmony_ci * write_tag_3_packet
216362306a36Sopenharmony_ci * @dest: Buffer into which to write the packet
216462306a36Sopenharmony_ci * @remaining_bytes: Maximum number of bytes that can be written
216562306a36Sopenharmony_ci * @auth_tok: Authentication token
216662306a36Sopenharmony_ci * @crypt_stat: The cryptographic context
216762306a36Sopenharmony_ci * @key_rec: encrypted key
216862306a36Sopenharmony_ci * @packet_size: This function will write the number of bytes that end
216962306a36Sopenharmony_ci *               up constituting the packet; set to zero on error
217062306a36Sopenharmony_ci *
217162306a36Sopenharmony_ci * Returns zero on success; non-zero on error.
217262306a36Sopenharmony_ci */
217362306a36Sopenharmony_cistatic int
217462306a36Sopenharmony_ciwrite_tag_3_packet(char *dest, size_t *remaining_bytes,
217562306a36Sopenharmony_ci		   struct ecryptfs_auth_tok *auth_tok,
217662306a36Sopenharmony_ci		   struct ecryptfs_crypt_stat *crypt_stat,
217762306a36Sopenharmony_ci		   struct ecryptfs_key_record *key_rec, size_t *packet_size)
217862306a36Sopenharmony_ci{
217962306a36Sopenharmony_ci	size_t i;
218062306a36Sopenharmony_ci	size_t encrypted_session_key_valid = 0;
218162306a36Sopenharmony_ci	char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES];
218262306a36Sopenharmony_ci	struct scatterlist dst_sg[2];
218362306a36Sopenharmony_ci	struct scatterlist src_sg[2];
218462306a36Sopenharmony_ci	struct mutex *tfm_mutex = NULL;
218562306a36Sopenharmony_ci	u8 cipher_code;
218662306a36Sopenharmony_ci	size_t packet_size_length;
218762306a36Sopenharmony_ci	size_t max_packet_size;
218862306a36Sopenharmony_ci	struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
218962306a36Sopenharmony_ci		crypt_stat->mount_crypt_stat;
219062306a36Sopenharmony_ci	struct crypto_skcipher *tfm;
219162306a36Sopenharmony_ci	struct skcipher_request *req;
219262306a36Sopenharmony_ci	int rc = 0;
219362306a36Sopenharmony_ci
219462306a36Sopenharmony_ci	(*packet_size) = 0;
219562306a36Sopenharmony_ci	ecryptfs_from_hex(key_rec->sig, auth_tok->token.password.signature,
219662306a36Sopenharmony_ci			  ECRYPTFS_SIG_SIZE);
219762306a36Sopenharmony_ci	rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&tfm, &tfm_mutex,
219862306a36Sopenharmony_ci							crypt_stat->cipher);
219962306a36Sopenharmony_ci	if (unlikely(rc)) {
220062306a36Sopenharmony_ci		printk(KERN_ERR "Internal error whilst attempting to get "
220162306a36Sopenharmony_ci		       "tfm and mutex for cipher name [%s]; rc = [%d]\n",
220262306a36Sopenharmony_ci		       crypt_stat->cipher, rc);
220362306a36Sopenharmony_ci		goto out;
220462306a36Sopenharmony_ci	}
220562306a36Sopenharmony_ci	if (mount_crypt_stat->global_default_cipher_key_size == 0) {
220662306a36Sopenharmony_ci		printk(KERN_WARNING "No key size specified at mount; "
220762306a36Sopenharmony_ci		       "defaulting to [%d]\n",
220862306a36Sopenharmony_ci		       crypto_skcipher_max_keysize(tfm));
220962306a36Sopenharmony_ci		mount_crypt_stat->global_default_cipher_key_size =
221062306a36Sopenharmony_ci			crypto_skcipher_max_keysize(tfm);
221162306a36Sopenharmony_ci	}
221262306a36Sopenharmony_ci	if (crypt_stat->key_size == 0)
221362306a36Sopenharmony_ci		crypt_stat->key_size =
221462306a36Sopenharmony_ci			mount_crypt_stat->global_default_cipher_key_size;
221562306a36Sopenharmony_ci	if (auth_tok->session_key.encrypted_key_size == 0)
221662306a36Sopenharmony_ci		auth_tok->session_key.encrypted_key_size =
221762306a36Sopenharmony_ci			crypt_stat->key_size;
221862306a36Sopenharmony_ci	if (crypt_stat->key_size == 24
221962306a36Sopenharmony_ci	    && strcmp("aes", crypt_stat->cipher) == 0) {
222062306a36Sopenharmony_ci		memset((crypt_stat->key + 24), 0, 8);
222162306a36Sopenharmony_ci		auth_tok->session_key.encrypted_key_size = 32;
222262306a36Sopenharmony_ci	} else
222362306a36Sopenharmony_ci		auth_tok->session_key.encrypted_key_size = crypt_stat->key_size;
222462306a36Sopenharmony_ci	key_rec->enc_key_size =
222562306a36Sopenharmony_ci		auth_tok->session_key.encrypted_key_size;
222662306a36Sopenharmony_ci	encrypted_session_key_valid = 0;
222762306a36Sopenharmony_ci	for (i = 0; i < auth_tok->session_key.encrypted_key_size; i++)
222862306a36Sopenharmony_ci		encrypted_session_key_valid |=
222962306a36Sopenharmony_ci			auth_tok->session_key.encrypted_key[i];
223062306a36Sopenharmony_ci	if (encrypted_session_key_valid) {
223162306a36Sopenharmony_ci		ecryptfs_printk(KERN_DEBUG, "encrypted_session_key_valid != 0; "
223262306a36Sopenharmony_ci				"using auth_tok->session_key.encrypted_key, "
223362306a36Sopenharmony_ci				"where key_rec->enc_key_size = [%zd]\n",
223462306a36Sopenharmony_ci				key_rec->enc_key_size);
223562306a36Sopenharmony_ci		memcpy(key_rec->enc_key,
223662306a36Sopenharmony_ci		       auth_tok->session_key.encrypted_key,
223762306a36Sopenharmony_ci		       key_rec->enc_key_size);
223862306a36Sopenharmony_ci		goto encrypted_session_key_set;
223962306a36Sopenharmony_ci	}
224062306a36Sopenharmony_ci	if (auth_tok->token.password.flags &
224162306a36Sopenharmony_ci	    ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET) {
224262306a36Sopenharmony_ci		ecryptfs_printk(KERN_DEBUG, "Using previously generated "
224362306a36Sopenharmony_ci				"session key encryption key of size [%d]\n",
224462306a36Sopenharmony_ci				auth_tok->token.password.
224562306a36Sopenharmony_ci				session_key_encryption_key_bytes);
224662306a36Sopenharmony_ci		memcpy(session_key_encryption_key,
224762306a36Sopenharmony_ci		       auth_tok->token.password.session_key_encryption_key,
224862306a36Sopenharmony_ci		       crypt_stat->key_size);
224962306a36Sopenharmony_ci		ecryptfs_printk(KERN_DEBUG,
225062306a36Sopenharmony_ci				"Cached session key encryption key:\n");
225162306a36Sopenharmony_ci		if (ecryptfs_verbosity > 0)
225262306a36Sopenharmony_ci			ecryptfs_dump_hex(session_key_encryption_key, 16);
225362306a36Sopenharmony_ci	}
225462306a36Sopenharmony_ci	if (unlikely(ecryptfs_verbosity > 0)) {
225562306a36Sopenharmony_ci		ecryptfs_printk(KERN_DEBUG, "Session key encryption key:\n");
225662306a36Sopenharmony_ci		ecryptfs_dump_hex(session_key_encryption_key, 16);
225762306a36Sopenharmony_ci	}
225862306a36Sopenharmony_ci	rc = virt_to_scatterlist(crypt_stat->key, key_rec->enc_key_size,
225962306a36Sopenharmony_ci				 src_sg, 2);
226062306a36Sopenharmony_ci	if (rc < 1 || rc > 2) {
226162306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
226262306a36Sopenharmony_ci				"for crypt_stat session key; expected rc = 1; "
226362306a36Sopenharmony_ci				"got rc = [%d]. key_rec->enc_key_size = [%zd]\n",
226462306a36Sopenharmony_ci				rc, key_rec->enc_key_size);
226562306a36Sopenharmony_ci		rc = -ENOMEM;
226662306a36Sopenharmony_ci		goto out;
226762306a36Sopenharmony_ci	}
226862306a36Sopenharmony_ci	rc = virt_to_scatterlist(key_rec->enc_key, key_rec->enc_key_size,
226962306a36Sopenharmony_ci				 dst_sg, 2);
227062306a36Sopenharmony_ci	if (rc < 1 || rc > 2) {
227162306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error generating scatterlist "
227262306a36Sopenharmony_ci				"for crypt_stat encrypted session key; "
227362306a36Sopenharmony_ci				"expected rc = 1; got rc = [%d]. "
227462306a36Sopenharmony_ci				"key_rec->enc_key_size = [%zd]\n", rc,
227562306a36Sopenharmony_ci				key_rec->enc_key_size);
227662306a36Sopenharmony_ci		rc = -ENOMEM;
227762306a36Sopenharmony_ci		goto out;
227862306a36Sopenharmony_ci	}
227962306a36Sopenharmony_ci	mutex_lock(tfm_mutex);
228062306a36Sopenharmony_ci	rc = crypto_skcipher_setkey(tfm, session_key_encryption_key,
228162306a36Sopenharmony_ci				    crypt_stat->key_size);
228262306a36Sopenharmony_ci	if (rc < 0) {
228362306a36Sopenharmony_ci		mutex_unlock(tfm_mutex);
228462306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error setting key for crypto "
228562306a36Sopenharmony_ci				"context; rc = [%d]\n", rc);
228662306a36Sopenharmony_ci		goto out;
228762306a36Sopenharmony_ci	}
228862306a36Sopenharmony_ci
228962306a36Sopenharmony_ci	req = skcipher_request_alloc(tfm, GFP_KERNEL);
229062306a36Sopenharmony_ci	if (!req) {
229162306a36Sopenharmony_ci		mutex_unlock(tfm_mutex);
229262306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Out of kernel memory whilst "
229362306a36Sopenharmony_ci				"attempting to skcipher_request_alloc for "
229462306a36Sopenharmony_ci				"%s\n", crypto_skcipher_driver_name(tfm));
229562306a36Sopenharmony_ci		rc = -ENOMEM;
229662306a36Sopenharmony_ci		goto out;
229762306a36Sopenharmony_ci	}
229862306a36Sopenharmony_ci
229962306a36Sopenharmony_ci	skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
230062306a36Sopenharmony_ci				      NULL, NULL);
230162306a36Sopenharmony_ci
230262306a36Sopenharmony_ci	rc = 0;
230362306a36Sopenharmony_ci	ecryptfs_printk(KERN_DEBUG, "Encrypting [%zd] bytes of the key\n",
230462306a36Sopenharmony_ci			crypt_stat->key_size);
230562306a36Sopenharmony_ci	skcipher_request_set_crypt(req, src_sg, dst_sg,
230662306a36Sopenharmony_ci				   (*key_rec).enc_key_size, NULL);
230762306a36Sopenharmony_ci	rc = crypto_skcipher_encrypt(req);
230862306a36Sopenharmony_ci	mutex_unlock(tfm_mutex);
230962306a36Sopenharmony_ci	skcipher_request_free(req);
231062306a36Sopenharmony_ci	if (rc) {
231162306a36Sopenharmony_ci		printk(KERN_ERR "Error encrypting; rc = [%d]\n", rc);
231262306a36Sopenharmony_ci		goto out;
231362306a36Sopenharmony_ci	}
231462306a36Sopenharmony_ci	ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n");
231562306a36Sopenharmony_ci	if (ecryptfs_verbosity > 0) {
231662306a36Sopenharmony_ci		ecryptfs_printk(KERN_DEBUG, "EFEK of size [%zd]:\n",
231762306a36Sopenharmony_ci				key_rec->enc_key_size);
231862306a36Sopenharmony_ci		ecryptfs_dump_hex(key_rec->enc_key,
231962306a36Sopenharmony_ci				  key_rec->enc_key_size);
232062306a36Sopenharmony_ci	}
232162306a36Sopenharmony_ciencrypted_session_key_set:
232262306a36Sopenharmony_ci	/* This format is inspired by OpenPGP; see RFC 2440
232362306a36Sopenharmony_ci	 * packet tag 3 */
232462306a36Sopenharmony_ci	max_packet_size = (1                         /* Tag 3 identifier */
232562306a36Sopenharmony_ci			   + 3                       /* Max Tag 3 packet size */
232662306a36Sopenharmony_ci			   + 1                       /* Version */
232762306a36Sopenharmony_ci			   + 1                       /* Cipher code */
232862306a36Sopenharmony_ci			   + 1                       /* S2K specifier */
232962306a36Sopenharmony_ci			   + 1                       /* Hash identifier */
233062306a36Sopenharmony_ci			   + ECRYPTFS_SALT_SIZE      /* Salt */
233162306a36Sopenharmony_ci			   + 1                       /* Hash iterations */
233262306a36Sopenharmony_ci			   + key_rec->enc_key_size); /* Encrypted key size */
233362306a36Sopenharmony_ci	if (max_packet_size > (*remaining_bytes)) {
233462306a36Sopenharmony_ci		printk(KERN_ERR "Packet too large; need up to [%td] bytes, but "
233562306a36Sopenharmony_ci		       "there are only [%td] available\n", max_packet_size,
233662306a36Sopenharmony_ci		       (*remaining_bytes));
233762306a36Sopenharmony_ci		rc = -EINVAL;
233862306a36Sopenharmony_ci		goto out;
233962306a36Sopenharmony_ci	}
234062306a36Sopenharmony_ci	dest[(*packet_size)++] = ECRYPTFS_TAG_3_PACKET_TYPE;
234162306a36Sopenharmony_ci	/* Chop off the Tag 3 identifier(1) and Tag 3 packet size(3)
234262306a36Sopenharmony_ci	 * to get the number of octets in the actual Tag 3 packet */
234362306a36Sopenharmony_ci	rc = ecryptfs_write_packet_length(&dest[(*packet_size)],
234462306a36Sopenharmony_ci					  (max_packet_size - 4),
234562306a36Sopenharmony_ci					  &packet_size_length);
234662306a36Sopenharmony_ci	if (rc) {
234762306a36Sopenharmony_ci		printk(KERN_ERR "Error generating tag 3 packet header; cannot "
234862306a36Sopenharmony_ci		       "generate packet length. rc = [%d]\n", rc);
234962306a36Sopenharmony_ci		goto out;
235062306a36Sopenharmony_ci	}
235162306a36Sopenharmony_ci	(*packet_size) += packet_size_length;
235262306a36Sopenharmony_ci	dest[(*packet_size)++] = 0x04; /* version 4 */
235362306a36Sopenharmony_ci	/* TODO: Break from RFC2440 so that arbitrary ciphers can be
235462306a36Sopenharmony_ci	 * specified with strings */
235562306a36Sopenharmony_ci	cipher_code = ecryptfs_code_for_cipher_string(crypt_stat->cipher,
235662306a36Sopenharmony_ci						      crypt_stat->key_size);
235762306a36Sopenharmony_ci	if (cipher_code == 0) {
235862306a36Sopenharmony_ci		ecryptfs_printk(KERN_WARNING, "Unable to generate code for "
235962306a36Sopenharmony_ci				"cipher [%s]\n", crypt_stat->cipher);
236062306a36Sopenharmony_ci		rc = -EINVAL;
236162306a36Sopenharmony_ci		goto out;
236262306a36Sopenharmony_ci	}
236362306a36Sopenharmony_ci	dest[(*packet_size)++] = cipher_code;
236462306a36Sopenharmony_ci	dest[(*packet_size)++] = 0x03;	/* S2K */
236562306a36Sopenharmony_ci	dest[(*packet_size)++] = 0x01;	/* MD5 (TODO: parameterize) */
236662306a36Sopenharmony_ci	memcpy(&dest[(*packet_size)], auth_tok->token.password.salt,
236762306a36Sopenharmony_ci	       ECRYPTFS_SALT_SIZE);
236862306a36Sopenharmony_ci	(*packet_size) += ECRYPTFS_SALT_SIZE;	/* salt */
236962306a36Sopenharmony_ci	dest[(*packet_size)++] = 0x60;	/* hash iterations (65536) */
237062306a36Sopenharmony_ci	memcpy(&dest[(*packet_size)], key_rec->enc_key,
237162306a36Sopenharmony_ci	       key_rec->enc_key_size);
237262306a36Sopenharmony_ci	(*packet_size) += key_rec->enc_key_size;
237362306a36Sopenharmony_ciout:
237462306a36Sopenharmony_ci	if (rc)
237562306a36Sopenharmony_ci		(*packet_size) = 0;
237662306a36Sopenharmony_ci	else
237762306a36Sopenharmony_ci		(*remaining_bytes) -= (*packet_size);
237862306a36Sopenharmony_ci	return rc;
237962306a36Sopenharmony_ci}
238062306a36Sopenharmony_ci
238162306a36Sopenharmony_cistruct kmem_cache *ecryptfs_key_record_cache;
238262306a36Sopenharmony_ci
238362306a36Sopenharmony_ci/**
238462306a36Sopenharmony_ci * ecryptfs_generate_key_packet_set
238562306a36Sopenharmony_ci * @dest_base: Virtual address from which to write the key record set
238662306a36Sopenharmony_ci * @crypt_stat: The cryptographic context from which the
238762306a36Sopenharmony_ci *              authentication tokens will be retrieved
238862306a36Sopenharmony_ci * @ecryptfs_dentry: The dentry, used to retrieve the mount crypt stat
238962306a36Sopenharmony_ci *                   for the global parameters
239062306a36Sopenharmony_ci * @len: The amount written
239162306a36Sopenharmony_ci * @max: The maximum amount of data allowed to be written
239262306a36Sopenharmony_ci *
239362306a36Sopenharmony_ci * Generates a key packet set and writes it to the virtual address
239462306a36Sopenharmony_ci * passed in.
239562306a36Sopenharmony_ci *
239662306a36Sopenharmony_ci * Returns zero on success; non-zero on error.
239762306a36Sopenharmony_ci */
239862306a36Sopenharmony_ciint
239962306a36Sopenharmony_ciecryptfs_generate_key_packet_set(char *dest_base,
240062306a36Sopenharmony_ci				 struct ecryptfs_crypt_stat *crypt_stat,
240162306a36Sopenharmony_ci				 struct dentry *ecryptfs_dentry, size_t *len,
240262306a36Sopenharmony_ci				 size_t max)
240362306a36Sopenharmony_ci{
240462306a36Sopenharmony_ci	struct ecryptfs_auth_tok *auth_tok;
240562306a36Sopenharmony_ci	struct key *auth_tok_key = NULL;
240662306a36Sopenharmony_ci	struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
240762306a36Sopenharmony_ci		&ecryptfs_superblock_to_private(
240862306a36Sopenharmony_ci			ecryptfs_dentry->d_sb)->mount_crypt_stat;
240962306a36Sopenharmony_ci	size_t written;
241062306a36Sopenharmony_ci	struct ecryptfs_key_record *key_rec;
241162306a36Sopenharmony_ci	struct ecryptfs_key_sig *key_sig;
241262306a36Sopenharmony_ci	int rc = 0;
241362306a36Sopenharmony_ci
241462306a36Sopenharmony_ci	(*len) = 0;
241562306a36Sopenharmony_ci	mutex_lock(&crypt_stat->keysig_list_mutex);
241662306a36Sopenharmony_ci	key_rec = kmem_cache_alloc(ecryptfs_key_record_cache, GFP_KERNEL);
241762306a36Sopenharmony_ci	if (!key_rec) {
241862306a36Sopenharmony_ci		rc = -ENOMEM;
241962306a36Sopenharmony_ci		goto out;
242062306a36Sopenharmony_ci	}
242162306a36Sopenharmony_ci	list_for_each_entry(key_sig, &crypt_stat->keysig_list,
242262306a36Sopenharmony_ci			    crypt_stat_list) {
242362306a36Sopenharmony_ci		memset(key_rec, 0, sizeof(*key_rec));
242462306a36Sopenharmony_ci		rc = ecryptfs_find_global_auth_tok_for_sig(&auth_tok_key,
242562306a36Sopenharmony_ci							   &auth_tok,
242662306a36Sopenharmony_ci							   mount_crypt_stat,
242762306a36Sopenharmony_ci							   key_sig->keysig);
242862306a36Sopenharmony_ci		if (rc) {
242962306a36Sopenharmony_ci			printk(KERN_WARNING "Unable to retrieve auth tok with "
243062306a36Sopenharmony_ci			       "sig = [%s]\n", key_sig->keysig);
243162306a36Sopenharmony_ci			rc = process_find_global_auth_tok_for_sig_err(rc);
243262306a36Sopenharmony_ci			goto out_free;
243362306a36Sopenharmony_ci		}
243462306a36Sopenharmony_ci		if (auth_tok->token_type == ECRYPTFS_PASSWORD) {
243562306a36Sopenharmony_ci			rc = write_tag_3_packet((dest_base + (*len)),
243662306a36Sopenharmony_ci						&max, auth_tok,
243762306a36Sopenharmony_ci						crypt_stat, key_rec,
243862306a36Sopenharmony_ci						&written);
243962306a36Sopenharmony_ci			up_write(&(auth_tok_key->sem));
244062306a36Sopenharmony_ci			key_put(auth_tok_key);
244162306a36Sopenharmony_ci			if (rc) {
244262306a36Sopenharmony_ci				ecryptfs_printk(KERN_WARNING, "Error "
244362306a36Sopenharmony_ci						"writing tag 3 packet\n");
244462306a36Sopenharmony_ci				goto out_free;
244562306a36Sopenharmony_ci			}
244662306a36Sopenharmony_ci			(*len) += written;
244762306a36Sopenharmony_ci			/* Write auth tok signature packet */
244862306a36Sopenharmony_ci			rc = write_tag_11_packet((dest_base + (*len)), &max,
244962306a36Sopenharmony_ci						 key_rec->sig,
245062306a36Sopenharmony_ci						 ECRYPTFS_SIG_SIZE, &written);
245162306a36Sopenharmony_ci			if (rc) {
245262306a36Sopenharmony_ci				ecryptfs_printk(KERN_ERR, "Error writing "
245362306a36Sopenharmony_ci						"auth tok signature packet\n");
245462306a36Sopenharmony_ci				goto out_free;
245562306a36Sopenharmony_ci			}
245662306a36Sopenharmony_ci			(*len) += written;
245762306a36Sopenharmony_ci		} else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) {
245862306a36Sopenharmony_ci			rc = write_tag_1_packet(dest_base + (*len), &max,
245962306a36Sopenharmony_ci						auth_tok_key, auth_tok,
246062306a36Sopenharmony_ci						crypt_stat, key_rec, &written);
246162306a36Sopenharmony_ci			if (rc) {
246262306a36Sopenharmony_ci				ecryptfs_printk(KERN_WARNING, "Error "
246362306a36Sopenharmony_ci						"writing tag 1 packet\n");
246462306a36Sopenharmony_ci				goto out_free;
246562306a36Sopenharmony_ci			}
246662306a36Sopenharmony_ci			(*len) += written;
246762306a36Sopenharmony_ci		} else {
246862306a36Sopenharmony_ci			up_write(&(auth_tok_key->sem));
246962306a36Sopenharmony_ci			key_put(auth_tok_key);
247062306a36Sopenharmony_ci			ecryptfs_printk(KERN_WARNING, "Unsupported "
247162306a36Sopenharmony_ci					"authentication token type\n");
247262306a36Sopenharmony_ci			rc = -EINVAL;
247362306a36Sopenharmony_ci			goto out_free;
247462306a36Sopenharmony_ci		}
247562306a36Sopenharmony_ci	}
247662306a36Sopenharmony_ci	if (likely(max > 0)) {
247762306a36Sopenharmony_ci		dest_base[(*len)] = 0x00;
247862306a36Sopenharmony_ci	} else {
247962306a36Sopenharmony_ci		ecryptfs_printk(KERN_ERR, "Error writing boundary byte\n");
248062306a36Sopenharmony_ci		rc = -EIO;
248162306a36Sopenharmony_ci	}
248262306a36Sopenharmony_ciout_free:
248362306a36Sopenharmony_ci	kmem_cache_free(ecryptfs_key_record_cache, key_rec);
248462306a36Sopenharmony_ciout:
248562306a36Sopenharmony_ci	if (rc)
248662306a36Sopenharmony_ci		(*len) = 0;
248762306a36Sopenharmony_ci	mutex_unlock(&crypt_stat->keysig_list_mutex);
248862306a36Sopenharmony_ci	return rc;
248962306a36Sopenharmony_ci}
249062306a36Sopenharmony_ci
249162306a36Sopenharmony_cistruct kmem_cache *ecryptfs_key_sig_cache;
249262306a36Sopenharmony_ci
249362306a36Sopenharmony_ciint ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig)
249462306a36Sopenharmony_ci{
249562306a36Sopenharmony_ci	struct ecryptfs_key_sig *new_key_sig;
249662306a36Sopenharmony_ci
249762306a36Sopenharmony_ci	new_key_sig = kmem_cache_alloc(ecryptfs_key_sig_cache, GFP_KERNEL);
249862306a36Sopenharmony_ci	if (!new_key_sig)
249962306a36Sopenharmony_ci		return -ENOMEM;
250062306a36Sopenharmony_ci
250162306a36Sopenharmony_ci	memcpy(new_key_sig->keysig, sig, ECRYPTFS_SIG_SIZE_HEX);
250262306a36Sopenharmony_ci	new_key_sig->keysig[ECRYPTFS_SIG_SIZE_HEX] = '\0';
250362306a36Sopenharmony_ci	/* Caller must hold keysig_list_mutex */
250462306a36Sopenharmony_ci	list_add(&new_key_sig->crypt_stat_list, &crypt_stat->keysig_list);
250562306a36Sopenharmony_ci
250662306a36Sopenharmony_ci	return 0;
250762306a36Sopenharmony_ci}
250862306a36Sopenharmony_ci
250962306a36Sopenharmony_cistruct kmem_cache *ecryptfs_global_auth_tok_cache;
251062306a36Sopenharmony_ci
251162306a36Sopenharmony_ciint
251262306a36Sopenharmony_ciecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,
251362306a36Sopenharmony_ci			     char *sig, u32 global_auth_tok_flags)
251462306a36Sopenharmony_ci{
251562306a36Sopenharmony_ci	struct ecryptfs_global_auth_tok *new_auth_tok;
251662306a36Sopenharmony_ci
251762306a36Sopenharmony_ci	new_auth_tok = kmem_cache_zalloc(ecryptfs_global_auth_tok_cache,
251862306a36Sopenharmony_ci					GFP_KERNEL);
251962306a36Sopenharmony_ci	if (!new_auth_tok)
252062306a36Sopenharmony_ci		return -ENOMEM;
252162306a36Sopenharmony_ci
252262306a36Sopenharmony_ci	memcpy(new_auth_tok->sig, sig, ECRYPTFS_SIG_SIZE_HEX);
252362306a36Sopenharmony_ci	new_auth_tok->flags = global_auth_tok_flags;
252462306a36Sopenharmony_ci	new_auth_tok->sig[ECRYPTFS_SIG_SIZE_HEX] = '\0';
252562306a36Sopenharmony_ci	mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);
252662306a36Sopenharmony_ci	list_add(&new_auth_tok->mount_crypt_stat_list,
252762306a36Sopenharmony_ci		 &mount_crypt_stat->global_auth_tok_list);
252862306a36Sopenharmony_ci	mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);
252962306a36Sopenharmony_ci	return 0;
253062306a36Sopenharmony_ci}
253162306a36Sopenharmony_ci
2532