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