cregit-Linux how code gets into the kernel

Release 4.10 fs/ecryptfs/keystore.c

Directory: fs/ecryptfs
/**
 * eCryptfs: Linux filesystem encryption layer
 * In-kernel key management code.  Includes functions to parse and
 * write authentication token-related packets with the underlying
 * file.
 *
 * Copyright (C) 2004-2006 International Business Machines Corp.
 *   Author(s): Michael A. Halcrow <mhalcrow@us.ibm.com>
 *              Michael C. Thompson <mcthomps@us.ibm.com>
 *              Trevor S. Highland <trevor.highland@gmail.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 * 02111-1307, USA.
 */

#include <crypto/hash.h>
#include <crypto/skcipher.h>
#include <linux/string.h>
#include <linux/pagemap.h>
#include <linux/key.h>
#include <linux/random.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include "ecryptfs_kernel.h"

/**
 * request_key returned an error instead of a valid key address;
 * determine the type of error, make appropriate log entries, and
 * return an error code.
 */

static int process_request_key_err(long err_code) { int rc = 0; switch (err_code) { case -ENOKEY: ecryptfs_printk(KERN_WARNING, "No key\n"); rc = -ENOENT; break; case -EKEYEXPIRED: ecryptfs_printk(KERN_WARNING, "Key expired\n"); rc = -ETIME; break; case -EKEYREVOKED: ecryptfs_printk(KERN_WARNING, "Key revoked\n"); rc = -EINVAL; break; default: ecryptfs_printk(KERN_WARNING, "Unknown error code: " "[0x%.16lx]\n", err_code); rc = -EINVAL; } return rc; }

Contributors

PersonTokensPropCommitsCommitProp
michael halcrowmichael halcrow8695.56%250.00%
eric sandeeneric sandeen33.33%125.00%
joe perchesjoe perches11.11%125.00%
Total90100.00%4100.00%


static int process_find_global_auth_tok_for_sig_err(int err_code) { int rc = err_code; switch (err_code) { case -ENOENT: ecryptfs_printk(KERN_WARNING, "Missing auth tok\n"); break; case -EINVAL: ecryptfs_printk(KERN_WARNING, "Invalid auth tok\n"); break; default: rc = process_request_key_err(err_code); break; } return rc; }

Contributors

PersonTokensPropCommitsCommitProp
roberto sassuroberto sassu56100.00%1100.00%
Total56100.00%1100.00%

/** * ecryptfs_parse_packet_length * @data: Pointer to memory containing length at offset * @size: This function writes the decoded size to this memory * address; zero on error * @length_size: The number of bytes occupied by the encoded length * * Returns zero on success; non-zero on error */
int ecryptfs_parse_packet_length(unsigned char *data, size_t *size, size_t *length_size) { int rc = 0; (*length_size) = 0; (*size) = 0; if (data[0] < 192) { /* One-byte length */ (*size) = data[0]; (*length_size) = 1; } else if (data[0] < 224) { /* Two-byte length */ (*size) = (data[0] - 192) * 256; (*size) += data[1] + 192; (*length_size) = 2; } else if (data[0] == 255) { /* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */ ecryptfs_printk(KERN_ERR, "Five-byte packet length not " "supported\n"); rc = -EINVAL; goto out; } else { ecryptfs_printk(KERN_ERR, "Error parsing packet length\n"); rc = -EINVAL; goto out; } out: return rc; }

Contributors

PersonTokensPropCommitsCommitProp
michael halcrowmichael halcrow16599.40%266.67%
tyler hickstyler hicks10.60%133.33%
Total166100.00%3100.00%

/** * ecryptfs_write_packet_length * @dest: The byte array target into which to write the length. Must * have at least ECRYPTFS_MAX_PKT_LEN_SIZE bytes allocated. * @size: The length to write. * @packet_size_length: The number of bytes used to encode the packet * length is written to this address. * * Returns zero on success; non-zero on error. */
int ecryptfs_write_packet_length(char *dest, size_t size, size_t *packet_size_length) { int rc = 0; if (size < 192) { dest[0] = size; (*packet_size_length) = 1; } else if (size < 65536) { dest[0] = (((size - 192) / 256) + 192); dest[1] = ((size - 192) % 256); (*packet_size_length) = 2; } else { /* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */ rc = -EINVAL; ecryptfs_printk(KERN_WARNING, "Unsupported packet size: [%zd]\n", size); } return rc; }

Contributors

PersonTokensPropCommitsCommitProp
michael halcrowmichael halcrow11298.25%250.00%
tyler hickstyler hicks21.75%250.00%
Total114100.00%4100.00%


static int write_tag_64_packet(char *signature, struct ecryptfs_session_key *session_key, char **packet, size_t *packet_len) { size_t i = 0; size_t data_len; size_t packet_size_len; char *message; int rc; /* * ***** TAG 64 Packet Format ***** * | Content Type | 1 byte | * | Key Identifier Size | 1 or 2 bytes | * | Key Identifier | arbitrary | * | Encrypted File Encryption Key Size | 1 or 2 bytes | * | Encrypted File Encryption Key | arbitrary | */ data_len = (5 + ECRYPTFS_SIG_SIZE_HEX + session_key->encrypted_key_size); *packet = kmalloc(data_len, GFP_KERNEL); message = *packet; if (!message) { ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n"); rc = -ENOMEM; goto out; } message[i++] = ECRYPTFS_TAG_64_PACKET_TYPE; rc = ecryptfs_write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX, &packet_size_len); if (rc) { ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet " "header; cannot generate packet length\n"); goto out; } i += packet_size_len; memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX); i += ECRYPTFS_SIG_SIZE_HEX; rc = ecryptfs_write_packet_length(&message[i], session_key->encrypted_key_size, &packet_size_len); if (rc) { ecryptfs_printk(KERN_ERR, "Error generating tag 64 packet " "header; cannot generate packet length\n"); goto out; } i += packet_size_len; memcpy(&message[i], session_key->encrypted_key, session_key->encrypted_key_size); i += session_key->encrypted_key_size; *packet_len = i; out: return rc; }

Contributors

PersonTokensPropCommitsCommitProp
michael halcrowmichael halcrow226100.00%3100.00%
Total226100.00%3100.00%


static int parse_tag_65_packet(struct ecryptfs_session_key *session_key, u8 *cipher_code, struct ecryptfs_message *msg) { size_t i = 0; char *data; size_t data_len; size_t m_size; size_t message_len; u16 checksum = 0; u16 expected_checksum = 0; int rc; /* * ***** TAG 65 Packet Format ***** * | Content Type | 1 byte | * | Status Indicator | 1 byte | * | File Encryption Key Size | 1 or 2 bytes | * | File Encryption Key | arbitrary | */ message_len = msg->data_len; data = msg->data; if (message_len < 4) { rc = -EIO; goto out; } if (data[i++] != ECRYPTFS_TAG_65_PACKET_TYPE) { ecryptfs_printk(KERN_ERR, "Type should be ECRYPTFS_TAG_65\n"); rc = -EIO; goto out; } if (data[i++]) { ecryptfs_printk(KERN_ERR, "Status indicator has non-zero value " "[%d]\n", data[i-1]); rc = -EIO; goto out; } rc = ecryptfs_parse_packet_length(&data[i], &m_size, &data_len); if (rc) { ecryptfs_printk(KERN_WARNING, "Error parsing packet length; " "rc = [%d]\n", rc); goto out; } i += data_len; if (message_len < (i + m_size)) { ecryptfs_printk(KERN_ERR, "The message received from ecryptfsd " "is shorter than expected\n"); rc = -EIO; goto out; } if (m_size < 3) { ecryptfs_printk(KERN_ERR, "The decrypted key is not long enough to " "include a cipher code and checksum\n"); rc = -EIO; goto out; } *cipher_code = data[i++]; /* The decrypted key includes 1 byte cipher code and 2 byte checksum */ session_key->decrypted_key_size = m_size - 3; if (session_key->decrypted_key_size > ECRYPTFS_MAX_KEY_BYTES) { ecryptfs_printk(KERN_ERR, "key_size [%d] larger than " "the maximum key size [%d]\n", session_key->decrypted_key_size, ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES); rc = -EIO; goto out; } memcpy(session_key->decrypted_key, &data[i], session_key->decrypted_key_size); i += session_key->decrypted_key_size; expected_checksum += (unsigned char)(data[i++]) << 8; expected_checksum += (unsigned char)(data[i++]); for (i = 0; i < session_key->decrypted_key_size; i++) checksum += session_key->decrypted_key[i]; if (expected_checksum != checksum) { ecryptfs_printk(KERN_ERR, "Invalid checksum for file " "encryption key; expected [%x]; calculated " "[%x]\n", expected_checksum, checksum); rc = -EIO; } out: return rc; }

Contributors

PersonTokensPropCommitsCommitProp
michael halcrowmichael halcrow38799.23%360.00%
tyler hickstyler hicks20.51%120.00%
trevor highlandtrevor highland10.26%120.00%
Total390100.00%5100.00%


static int write_tag_66_packet(char *signature, u8 cipher_code, struct ecryptfs_crypt_stat *crypt_stat, char **packet, size_t *packet_len) { size_t i = 0; size_t j; size_t data_len; size_t checksum = 0; size_t packet_size_len; char *message; int rc; /* * ***** TAG 66 Packet Format ***** * | Content Type | 1 byte | * | Key Identifier Size | 1 or 2 bytes | * | Key Identifier | arbitrary | * | File Encryption Key Size | 1 or 2 bytes | * | File Encryption Key | arbitrary | */ data_len = (5 + ECRYPTFS_SIG_SIZE_HEX + crypt_stat->key_size); *packet = kmalloc(data_len, GFP_KERNEL); message = *packet; if (!message) { ecryptfs_printk(KERN_ERR, "Unable to allocate memory\n"); rc = -ENOMEM; goto out; } message[i++] = ECRYPTFS_TAG_66_PACKET_TYPE; rc = ecryptfs_write_packet_length(&message[i], ECRYPTFS_SIG_SIZE_HEX, &packet_size_len); if (rc) { ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet " "header; cannot generate packet length\n"); goto out; } i += packet_size_len; memcpy(&message[i], signature, ECRYPTFS_SIG_SIZE_HEX); i += ECRYPTFS_SIG_SIZE_HEX; /* The encrypted key includes 1 byte cipher code and 2 byte checksum */ rc = ecryptfs_write_packet_length(&message[i], crypt_stat->key_size + 3, &packet_size_len); if (rc) { ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet " "header; cannot generate packet length\n"); goto out; } i += packet_size_len; message[i++] = cipher_code; memcpy(&message[i], crypt_stat->key, crypt_stat->key_size); i += crypt_stat->key_size; for (j = 0; j < crypt_stat->key_size; j++) checksum += crypt_stat->key[j]; message[i++] = (checksum / 256) % 256; message[i++] = (checksum % 256); *packet_len = i; out: return rc; }

Contributors

PersonTokensPropCommitsCommitProp
michael halcrowmichael halcrow29799.66%375.00%
trevor highlandtrevor highland10.34%125.00%
Total298100.00%4100.00%


static int parse_tag_67_packet(struct ecryptfs_key_record *key_rec, struct ecryptfs_message *msg) { size_t i = 0; char *data; size_t data_len; size_t message_len; int rc; /* * ***** TAG 65 Packet Format ***** * | Content Type | 1 byte | * | Status Indicator | 1 byte | * | Encrypted File Encryption Key Size | 1 or 2 bytes | * | Encrypted File Encryption Key | arbitrary | */ message_len = msg->data_len; data = msg->data; /* verify that everything through the encrypted FEK size is present */ if (message_len < 4) { rc = -EIO; printk(KERN_ERR "%s: message_len is [%zd]; minimum acceptable " "message length is [%d]\n", __func__, message_len, 4); goto out; } if (data[i++] != ECRYPTFS_TAG_67_PACKET_TYPE) { rc = -EIO; printk(KERN_ERR "%s: Type should be ECRYPTFS_TAG_67\n", __func__); goto out; } if (data[i++]) { rc = -EIO; printk(KERN_ERR "%s: Status indicator has non zero " "value [%d]\n", __func__, data[i-1]); goto out; } rc = ecryptfs_parse_packet_length(&data[i], &key_rec->enc_key_size, &data_len); if (rc) { ecryptfs_printk(KERN_WARNING, "Error parsing packet length; " "rc = [%d]\n", rc); goto out; } i += data_len; if (message_len < (i + key_rec->enc_key_size)) { rc = -EIO; printk(KERN_ERR "%s: message_len [%zd]; max len is [%zd]\n", __func__, message_len, (i + key_rec->enc_key_size)); goto out; } if (key_rec->enc_key_size > ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES) { rc = -EIO; printk(KERN_ERR "%s: Encrypted key_size [%zd] larger than " "the maximum key size [%d]\n", __func__, key_rec->enc_key_size, ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES); goto out; } memcpy(key_rec->enc_key, &data[i], key_rec->enc_key_size); out: return rc; }

Contributors

PersonTokensPropCommitsCommitProp
michael halcrowmichael halcrow276100.00%5100.00%
Total276100.00%5100.00%

/** * ecryptfs_verify_version * @version: The version number to confirm * * Returns zero on good version; non-zero otherwise */
static int ecryptfs_verify_version(u16 version) { int rc = 0; unsigned char major; unsigned char minor; major = ((version >> 8) & 0xFF); minor = (version & 0xFF); if (major != ECRYPTFS_VERSION_MAJOR) { ecryptfs_printk(KERN_ERR, "Major version number mismatch. " "Expected [%d]; got [%d]\n", ECRYPTFS_VERSION_MAJOR, major); rc = -EINVAL; goto out; } if (minor != ECRYPTFS_VERSION_MINOR) { ecryptfs_printk(KERN_ERR, "Minor version number mismatch. " "Expected [%d]; got [%d]\n", ECRYPTFS_VERSION_MINOR, minor); rc = -EINVAL; goto out; } out: return rc; }

Contributors

PersonTokensPropCommitsCommitProp
roberto sassuroberto sassu103100.00%1100.00%
Total103100.00%1100.00%

/** * ecryptfs_verify_auth_tok_from_key * @auth_tok_key: key containing the authentication token * @auth_tok: authentication token * * Returns zero on valid auth tok; -EINVAL otherwise */
static int ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key, struct ecryptfs_auth_tok **auth_tok) { int rc = 0; (*auth_tok) = ecryptfs_get_key_payload_data(auth_tok_key); if (ecryptfs_verify_version((*auth_tok)->version)) { printk(KERN_ERR "Data structure version mismatch. Userspace " "tools must match eCryptfs kernel module with major " "version [%d] and minor version [%d]\n", ECRYPTFS_VERSION_MAJOR, ECRYPTFS_VERSION_MINOR); rc = -EINVAL; goto out; } if ((*auth_tok)->token_type != ECRYPTFS_PASSWORD && (*auth_tok)->token_type != ECRYPTFS_PRIVATE_KEY) { printk(KERN_ERR "Invalid auth_tok structure " "returned from key query\n"); rc = -EINVAL; goto out; } out: return rc; }

Contributors

PersonTokensPropCommitsCommitProp
roberto sassuroberto sassu108100.00%1100.00%
Total108100.00%1100.00%


static int ecryptfs_find_global_auth_tok_for_sig( struct key **auth_tok_key, struct ecryptfs_auth_tok **auth_tok, struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig) { struct ecryptfs_global_auth_tok *walker; int rc = 0; (*auth_tok_key) = NULL; (*auth_tok) = NULL; mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex); list_for_each_entry(walker, &mount_crypt_stat->global_auth_tok_list, mount_crypt_stat_list) { if (memcmp(walker->sig, sig, ECRYPTFS_SIG_SIZE_HEX)) continue; if (walker->flags & ECRYPTFS_AUTH_TOK_INVALID) { rc = -EINVAL; goto out; } rc = key_validate(walker->global_auth_tok_key); if (rc) { if (rc == -EKEYEXPIRED) goto out; goto out_invalid_auth_tok; } down_write(&(walker->global_auth_tok_key->sem)); rc = ecryptfs_verify_auth_tok_from_key( walker->global_auth_tok_key, auth_tok); if (rc) goto out_invalid_auth_tok_unlock; (*auth_tok_key) = walker->global_auth_tok_key; key_get(*auth_tok_key); goto out; } rc = -ENOENT; goto out; out_invalid_auth_tok_unlock: up_write(&(walker->global_auth_tok_key->sem)); out_invalid_auth_tok: printk(KERN_WARNING "Invalidating auth tok with sig = [%s]\n", sig); walker->flags |= ECRYPTFS_AUTH_TOK_INVALID; key_put(walker->global_auth_tok_key); walker->global_auth_tok_key = NULL; out: mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex); return rc; }

Contributors

PersonTokensPropCommitsCommitProp
roberto sassuroberto sassu13556.02%240.00%
michael halcrowmichael halcrow9338.59%240.00%
tyler hickstyler hicks135.39%120.00%
Total241100.00%5100.00%

/** * ecryptfs_find_auth_tok_for_sig * @auth_tok: Set to the matching auth_tok; NULL if not found * @crypt_stat: inode crypt_stat crypto context * @sig: Sig of auth_tok to find * * For now, this function simply looks at the registered auth_tok's * linked off the mount_crypt_stat, so all the auth_toks that can be * used must be registered at mount time. This function could * potentially try a lot harder to find auth_tok's (e.g., by calling * out to ecryptfsd to dynamically retrieve an auth_tok object) so * that static registration of auth_tok's will no longer be necessary. * * Returns zero on no error; non-zero on error */
static int ecryptfs_find_auth_tok_for_sig( struct key **auth_tok_key, struct ecryptfs_auth_tok **auth_tok, struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *sig) { int rc = 0; rc = ecryptfs_find_global_auth_tok_for_sig(auth_tok_key, auth_tok, mount_crypt_stat, sig); if (rc == -ENOENT) { /* if the flag ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY is set in the * mount_crypt_stat structure, we prevent to use auth toks that * are not inserted through the ecryptfs_add_global_auth_tok * function. */ if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_MOUNT_AUTH_TOK_ONLY) return -EINVAL; rc = ecryptfs_keyring_auth_tok_for_sig(auth_tok_key, auth_tok, sig); } return rc; }

Contributors

PersonTokensPropCommitsCommitProp
michael halcrowmichael halcrow5162.96%125.00%
roberto sassuroberto sassu3037.04%375.00%
Total81100.00%4100.00%

/** * write_tag_70_packet can gobble a lot of stack space. We stuff most * of the function's parameters in a kmalloc'd struct to help reduce * eCryptfs' overall stack usage. */ struct ecryptfs_write_tag_70_packet_silly_stack { u8 cipher_code; size_t max_packet_size; size_t packet_size_len; size_t block_aligned_filename_size; size_t block_size; size_t i; size_t j; size_t num_rand_bytes; struct mutex *tfm_mutex; char *block_aligned_filename; struct ecryptfs_auth_tok *auth_tok; struct scatterlist src_sg[2]; struct scatterlist dst_sg[2]; struct crypto_skcipher *skcipher_tfm; struct skcipher_request *skcipher_req; char iv[ECRYPTFS_MAX_IV_BYTES]; char hash[ECRYPTFS_TAG_70_DIGEST_SIZE]; char tmp_hash[ECRYPTFS_TAG_70_DIGEST_SIZE]; struct crypto_shash *hash_tfm; struct shash_desc *hash_desc; }; /** * write_tag_70_packet - Write encrypted filename (EFN) packet against FNEK * @filename: NULL-terminated filename string * * This is the simplest mechanism for achieving filename encryption in * eCryptfs. It encrypts the given filename with the mount-wide * filename encryption key (FNEK) and stores it in a packet to @dest, * which the callee will encode and write directly into the dentry * name. */
int ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, size_t *packet_size, struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *filename, size_t filename_size) { struct ecryptfs_write_tag_70_packet_silly_stack *s; struct key *auth_tok_key = NULL; int rc = 0; s = kzalloc(sizeof(*s), GFP_KERNEL); if (!s) { printk(KERN_ERR "%s: Out of memory whilst trying to kmalloc " "[%zd] bytes of kernel memory\n", __func__, sizeof(*s)); return -ENOMEM; } (*packet_size) = 0; rc = ecryptfs_find_auth_tok_for_sig( &auth_tok_key, &s->auth_tok, mount_crypt_stat, mount_crypt_stat->global_default_fnek_sig); if (rc) { printk(KERN_ERR "%s: Error attempting to find auth tok for " "fnek sig [%s]; rc = [%d]\n", __func__, mount_crypt_stat->global_default_fnek_sig, rc); goto out; } rc = ecryptfs_get_tfm_and_mutex_for_cipher_name( &s->skcipher_tfm, &s->tfm_mutex, mount_crypt_stat->global_default_fn_cipher_name); if (unlikely(rc)) { printk(KERN_ERR "Internal error whilst attempting to get " "tfm and mutex for cipher name [%s]; rc = [%d]\n", mount_crypt_stat->global_default_fn_cipher_name, rc); goto out; } mutex_lock(s->tfm_mutex); s->block_size = crypto_skcipher_blocksize(s->skcipher_tfm); /* Plus one for the \0 separator between the random prefix * and the plaintext filename */ s->num_rand_bytes = (ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES + 1); s->block_aligned_filename_size = (s->num_rand_bytes + filename_size); if ((s->block_aligned_filename_size % s->block_size) != 0) { s->num_rand_bytes += (s->block_size - (s->block_aligned_filename_size % s->block_size)); s->block_aligned_filename_size = (s->num_rand_bytes + filename_size); } /* Octet 0: Tag 70 identifier * Octets 1-N1: Tag 70 packet size (includes cipher identifier * and block-aligned encrypted filename size) * Octets N1-N2: FNEK sig (ECRYPTFS_SIG_SIZE) * Octet N2-N3: Cipher identifier (1 octet) * Octets N3-N4: Block-aligned encrypted filename * - Consists of a minimum number of random characters, a \0 * separator, and then the filename */ s->max_packet_size = (ECRYPTFS_TAG_70_MAX_METADATA_SIZE + s->block_aligned_filename_size); if (dest == NULL) { (*packet_size) = s->max_packet_size; goto out_unlock; } if (s->max_packet_size > (*remaining_bytes)) { printk(KERN_WARNING "%s: Require [%zd] bytes to write; only " "[%zd] available\n", __func__, s->max_packet_size, (*remaining_bytes)); rc = -EINVAL; goto out_unlock; } s->skcipher_req = skcipher_request_alloc(s->skcipher_tfm, GFP_KERNEL); if (!s->skcipher_req) { printk(KERN_ERR "%s: Out of kernel memory whilst attempting to " "skcipher_request_alloc for %s\n", __func__, crypto_skcipher_driver_name(s->skcipher_tfm)); rc = -ENOMEM; goto out_unlock; } skcipher_request_set_callback(s->skcipher_req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); s->block_aligned_filename = kzalloc(s->block_aligned_filename_size, GFP_KERNEL); if (!s->block_aligned_filename) { printk(KERN_ERR "%s: Out of kernel memory whilst attempting to " "kzalloc [%zd] bytes\n", __func__, s->block_aligned_filename_size); rc = -ENOMEM; goto out_unlock; } dest[s->i++] = ECRYPTFS_TAG_70_PACKET_TYPE; rc = ecryptfs_write_packet_length(&dest[s->i], (ECRYPTFS_SIG_SIZE + 1 /* Cipher code */ + s->block_aligned_filename_size), &s->packet_size_len); if (rc) { printk(KERN_ERR "%s: Error generating tag 70 packet " "header; cannot generate packet length; rc = [%d]\n", __func__, rc); goto out_free_unlock; } s->i += s->packet_size_len; ecryptfs_from_hex(&dest[s->i], mount_crypt_stat->global_default_fnek_sig, ECRYPTFS_SIG_SIZE); s->i += ECRYPTFS_SIG_SIZE; s->cipher_code = ecryptfs_code_for_cipher_string( mount_crypt_stat->global_default_fn_cipher_name, mount_crypt_stat->global_default_fn_cipher_key_bytes); if (s->cipher_code == 0) { printk(KERN_WARNING "%s: Unable to generate code for " "cipher [%s] with key bytes [%zd]\n", __func__, mount_crypt_stat->global_default_fn_cipher_name, mount_crypt_stat->global_default_fn_cipher_key_bytes); rc = -EINVAL; goto out_free_unlock; } dest[s->i++] = s->cipher_code; /* TODO: Support other key modules than passphrase for * filename encryption */ if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) { rc = -EOPNOTSUPP; printk(KERN_INFO "%s: Filename encryption only supports " "password tokens\n", __func__); goto out_free_unlock; } s->hash_tfm =