diff options
Diffstat (limited to 'fs/ecryptfs/keystore.c')
| -rw-r--r-- | fs/ecryptfs/keystore.c | 408 | 
1 files changed, 239 insertions, 169 deletions
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index b1f6858a522..4725a07f003 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c @@ -59,12 +59,30 @@ static int process_request_key_err(long err_code)  		break;  	default:  		ecryptfs_printk(KERN_WARNING, "Unknown error code: " -				"[0x%.16x]\n", err_code); +				"[0x%.16lx]\n", err_code);  		rc = -EINVAL;  	}  	return rc;  } +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; +} +  /**   * ecryptfs_parse_packet_length   * @data: Pointer to memory containing length at offset @@ -91,7 +109,7 @@ int ecryptfs_parse_packet_length(unsigned char *data, size_t *size,  		(*size) += ((unsigned char)(data[1]) + 192);  		(*length_size) = 2;  	} else if (data[0] == 255) { -		/* Five-byte length; we're not supposed to see this */ +		/* If support is added, adjust ECRYPTFS_MAX_PKT_LEN_SIZE */  		ecryptfs_printk(KERN_ERR, "Five-byte packet length not "  				"supported\n");  		rc = -EINVAL; @@ -108,7 +126,7 @@ out:  /**   * ecryptfs_write_packet_length   * @dest: The byte array target into which to write the length. Must - *        have at least 5 bytes allocated. + *        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. @@ -128,9 +146,10 @@ int ecryptfs_write_packet_length(char *dest, size_t size,  		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: [%d]\n", size); +				"Unsupported packet size: [%zd]\n", size);  	}  	return rc;  } @@ -403,27 +422,120 @@ out:  	return rc;  } +/** + * ecryptfs_verify_version + * @version: The version number to confirm + * + * Returns zero on good version; non-zero otherwise + */ +static int ecryptfs_verify_version(u16 version) +{ +	int rc = 0; +	unsigned char major; +	unsigned char minor; + +	major = ((version >> 8) & 0xFF); +	minor = (version & 0xFF); +	if (major != ECRYPTFS_VERSION_MAJOR) { +		ecryptfs_printk(KERN_ERR, "Major version number mismatch. " +				"Expected [%d]; got [%d]\n", +				ECRYPTFS_VERSION_MAJOR, major); +		rc = -EINVAL; +		goto out; +	} +	if (minor != ECRYPTFS_VERSION_MINOR) { +		ecryptfs_printk(KERN_ERR, "Minor version number mismatch. " +				"Expected [%d]; got [%d]\n", +				ECRYPTFS_VERSION_MINOR, minor); +		rc = -EINVAL; +		goto out; +	} +out: +	return rc; +} + +/** + * 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; +} +  static int  ecryptfs_find_global_auth_tok_for_sig( -	struct ecryptfs_global_auth_tok **global_auth_tok, +	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; -	(*global_auth_tok) = NULL; +	(*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) == 0) { -			rc = key_validate(walker->global_auth_tok_key); -			if (!rc) -				(*global_auth_tok) = walker; +		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 = -EINVAL; +	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; @@ -451,14 +563,11 @@ ecryptfs_find_auth_tok_for_sig(  	struct ecryptfs_mount_crypt_stat *mount_crypt_stat,  	char *sig)  { -	struct ecryptfs_global_auth_tok *global_auth_tok;  	int rc = 0; -	(*auth_tok_key) = NULL; -	(*auth_tok) = NULL; -	if (ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok, -						  mount_crypt_stat, sig)) { - +	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 @@ -470,8 +579,7 @@ ecryptfs_find_auth_tok_for_sig(  		rc = ecryptfs_keyring_auth_tok_for_sig(auth_tok_key, auth_tok,  						       sig); -	} else -		(*auth_tok) = global_auth_tok->global_auth_tok; +	}  	return rc;  } @@ -492,8 +600,8 @@ struct ecryptfs_write_tag_70_packet_silly_stack {  	struct mutex *tfm_mutex;  	char *block_aligned_filename;  	struct ecryptfs_auth_tok *auth_tok; -	struct scatterlist src_sg; -	struct scatterlist dst_sg; +	struct scatterlist src_sg[2]; +	struct scatterlist dst_sg[2];  	struct blkcipher_desc desc;  	char iv[ECRYPTFS_MAX_IV_BYTES];  	char hash[ECRYPTFS_TAG_70_DIGEST_SIZE]; @@ -531,6 +639,16 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,  	}  	s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;  	(*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->desc.tfm,  		&s->tfm_mutex, mount_crypt_stat->global_default_fn_cipher_name); @@ -561,10 +679,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,  	 * 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 = (1                   /* Tag 70 identifier */ -			      + 3                 /* Max Tag 70 packet size */ -			      + ECRYPTFS_SIG_SIZE /* FNEK sig */ -			      + 1                 /* Cipher identifier */ +	s->max_packet_size = (ECRYPTFS_TAG_70_MAX_METADATA_SIZE  			      + s->block_aligned_filename_size);  	if (dest == NULL) {  		(*packet_size) = s->max_packet_size; @@ -616,16 +731,6 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,  		goto out_free_unlock;  	}  	dest[s->i++] = s->cipher_code; -	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_free_unlock; -	}  	/* TODO: Support other key modules than passphrase for  	 * filename encryption */  	if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) { @@ -709,23 +814,21 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,  	memcpy(&s->block_aligned_filename[s->num_rand_bytes], filename,  	       filename_size);  	rc = virt_to_scatterlist(s->block_aligned_filename, -				 s->block_aligned_filename_size, &s->src_sg, 1); -	if (rc != 1) { +				 s->block_aligned_filename_size, s->src_sg, 2); +	if (rc < 1) {  		printk(KERN_ERR "%s: Internal error whilst attempting to " -		       "convert filename memory to scatterlist; " -		       "expected rc = 1; got rc = [%d]. " +		       "convert filename memory to scatterlist; rc = [%d]. "  		       "block_aligned_filename_size = [%zd]\n", __func__, rc,  		       s->block_aligned_filename_size);  		goto out_release_free_unlock;  	}  	rc = virt_to_scatterlist(&dest[s->i], s->block_aligned_filename_size, -				 &s->dst_sg, 1); -	if (rc != 1) { +				 s->dst_sg, 2); +	if (rc < 1) {  		printk(KERN_ERR "%s: Internal error whilst attempting to "  		       "convert encrypted filename memory to scatterlist; " -		       "expected rc = 1; got rc = [%d]. " -		       "block_aligned_filename_size = [%zd]\n", __func__, rc, -		       s->block_aligned_filename_size); +		       "rc = [%d]. block_aligned_filename_size = [%zd]\n", +		       __func__, rc, s->block_aligned_filename_size);  		goto out_release_free_unlock;  	}  	/* The characters in the first block effectively do the job @@ -748,7 +851,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,  		       mount_crypt_stat->global_default_fn_cipher_key_bytes);  		goto out_release_free_unlock;  	} -	rc = crypto_blkcipher_encrypt_iv(&s->desc, &s->dst_sg, &s->src_sg, +	rc = crypto_blkcipher_encrypt_iv(&s->desc, s->dst_sg, s->src_sg,  					 s->block_aligned_filename_size);  	if (rc) {  		printk(KERN_ERR "%s: Error attempting to encrypt filename; " @@ -765,8 +868,10 @@ out_free_unlock:  out_unlock:  	mutex_unlock(s->tfm_mutex);  out: -	if (auth_tok_key) +	if (auth_tok_key) { +		up_write(&(auth_tok_key->sem));  		key_put(auth_tok_key); +	}  	kfree(s);  	return rc;  } @@ -782,8 +887,8 @@ struct ecryptfs_parse_tag_70_packet_silly_stack {  	struct mutex *tfm_mutex;  	char *decrypted_filename;  	struct ecryptfs_auth_tok *auth_tok; -	struct scatterlist src_sg; -	struct scatterlist dst_sg; +	struct scatterlist src_sg[2]; +	struct scatterlist dst_sg[2];  	struct blkcipher_desc desc;  	char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1];  	char iv[ECRYPTFS_MAX_IV_BYTES]; @@ -826,10 +931,10 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,  		goto out;  	}  	s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; -	if (max_packet_size < (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)) { +	if (max_packet_size < ECRYPTFS_TAG_70_MIN_METADATA_SIZE) {  		printk(KERN_WARNING "%s: max_packet_size is [%zd]; it must be "  		       "at least [%d]\n", __func__, max_packet_size, -			(1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)); +		       ECRYPTFS_TAG_70_MIN_METADATA_SIZE);  		rc = -EINVAL;  		goto out;  	} @@ -879,6 +984,15 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,  		       __func__, s->cipher_code);  		goto out;  	} +	rc = ecryptfs_find_auth_tok_for_sig(&auth_tok_key, +					    &s->auth_tok, mount_crypt_stat, +					    s->fnek_sig_hex); +	if (rc) { +		printk(KERN_ERR "%s: Error attempting to find auth tok for " +		       "fnek sig [%s]; rc = [%d]\n", __func__, s->fnek_sig_hex, +		       rc); +		goto out; +	}  	rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&s->desc.tfm,  							&s->tfm_mutex,  							s->cipher_string); @@ -890,13 +1004,12 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,  	}  	mutex_lock(s->tfm_mutex);  	rc = virt_to_scatterlist(&data[(*packet_size)], -				 s->block_aligned_filename_size, &s->src_sg, 1); -	if (rc != 1) { +				 s->block_aligned_filename_size, s->src_sg, 2); +	if (rc < 1) {  		printk(KERN_ERR "%s: Internal error whilst attempting to "  		       "convert encrypted filename memory to scatterlist; " -		       "expected rc = 1; got rc = [%d]. " -		       "block_aligned_filename_size = [%zd]\n", __func__, rc, -		       s->block_aligned_filename_size); +		       "rc = [%d]. block_aligned_filename_size = [%zd]\n", +		       __func__, rc, s->block_aligned_filename_size);  		goto out_unlock;  	}  	(*packet_size) += s->block_aligned_filename_size; @@ -910,13 +1023,12 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,  		goto out_unlock;  	}  	rc = virt_to_scatterlist(s->decrypted_filename, -				 s->block_aligned_filename_size, &s->dst_sg, 1); -	if (rc != 1) { +				 s->block_aligned_filename_size, s->dst_sg, 2); +	if (rc < 1) {  		printk(KERN_ERR "%s: Internal error whilst attempting to "  		       "convert decrypted filename memory to scatterlist; " -		       "expected rc = 1; got rc = [%d]. " -		       "block_aligned_filename_size = [%zd]\n", __func__, rc, -		       s->block_aligned_filename_size); +		       "rc = [%d]. block_aligned_filename_size = [%zd]\n", +		       __func__, rc, s->block_aligned_filename_size);  		goto out_free_unlock;  	}  	/* The characters in the first block effectively do the job of @@ -925,15 +1037,6 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,  	 * >= ECRYPTFS_MAX_IV_BYTES. */  	memset(s->iv, 0, ECRYPTFS_MAX_IV_BYTES);  	s->desc.info = s->iv; -	rc = ecryptfs_find_auth_tok_for_sig(&auth_tok_key, -					    &s->auth_tok, mount_crypt_stat, -					    s->fnek_sig_hex); -	if (rc) { -		printk(KERN_ERR "%s: Error attempting to find auth tok for " -		       "fnek sig [%s]; rc = [%d]\n", __func__, s->fnek_sig_hex, -		       rc); -		goto out_free_unlock; -	}  	/* TODO: Support other key modules than passphrase for  	 * filename encryption */  	if (s->auth_tok->token_type != ECRYPTFS_PASSWORD) { @@ -956,7 +1059,7 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,  		       mount_crypt_stat->global_default_fn_cipher_key_bytes);  		goto out_free_unlock;  	} -	rc = crypto_blkcipher_decrypt_iv(&s->desc, &s->dst_sg, &s->src_sg, +	rc = crypto_blkcipher_decrypt_iv(&s->desc, s->dst_sg, s->src_sg,  					 s->block_aligned_filename_size);  	if (rc) {  		printk(KERN_ERR "%s: Error attempting to decrypt filename; " @@ -1002,8 +1105,10 @@ out:  		(*filename_size) = 0;  		(*filename) = NULL;  	} -	if (auth_tok_key) +	if (auth_tok_key) { +		up_write(&(auth_tok_key->sem));  		key_put(auth_tok_key); +	}  	kfree(s);  	return rc;  } @@ -1044,8 +1149,8 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,  	struct ecryptfs_msg_ctx *msg_ctx;  	struct ecryptfs_message *msg = NULL;  	char *auth_tok_sig; -	char *payload; -	size_t payload_len; +	char *payload = NULL; +	size_t payload_len = 0;  	int rc;  	rc = ecryptfs_get_auth_tok_sig(&auth_tok_sig, auth_tok); @@ -1063,7 +1168,7 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,  	rc = ecryptfs_send_message(payload, payload_len, &msg_ctx);  	if (rc) {  		ecryptfs_printk(KERN_ERR, "Error sending message to " -				"ecryptfsd\n"); +				"ecryptfsd: %d\n", rc);  		goto out;  	}  	rc = ecryptfs_wait_for_response(msg_ctx, &msg); @@ -1097,8 +1202,8 @@ decrypt_pki_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,  				  crypt_stat->key_size);  	}  out: -	if (msg) -		kfree(msg); +	kfree(msg); +	kfree(payload);  	return rc;  } @@ -1520,38 +1625,6 @@ out:  	return rc;  } -/** - * ecryptfs_verify_version - * @version: The version number to confirm - * - * Returns zero on good version; non-zero otherwise - */ -static int ecryptfs_verify_version(u16 version) -{ -	int rc = 0; -	unsigned char major; -	unsigned char minor; - -	major = ((version >> 8) & 0xFF); -	minor = (version & 0xFF); -	if (major != ECRYPTFS_VERSION_MAJOR) { -		ecryptfs_printk(KERN_ERR, "Major version number mismatch. " -				"Expected [%d]; got [%d]\n", -				ECRYPTFS_VERSION_MAJOR, major); -		rc = -EINVAL; -		goto out; -	} -	if (minor != ECRYPTFS_VERSION_MINOR) { -		ecryptfs_printk(KERN_ERR, "Minor version number mismatch. " -				"Expected [%d]; got [%d]\n", -				ECRYPTFS_VERSION_MINOR, minor); -		rc = -EINVAL; -		goto out; -	} -out: -	return rc; -} -  int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,  				      struct ecryptfs_auth_tok **auth_tok,  				      char *sig) @@ -1560,34 +1633,22 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,  	(*auth_tok_key) = request_key(&key_type_user, sig, NULL);  	if (!(*auth_tok_key) || IS_ERR(*auth_tok_key)) { -		printk(KERN_ERR "Could not find key with description: [%s]\n", -		       sig); -		rc = process_request_key_err(PTR_ERR(*auth_tok_key)); -		goto out; -	} -	(*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_release_key; -	} -	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_release_key; +		(*auth_tok_key) = ecryptfs_get_encrypted_key(sig); +		if (!(*auth_tok_key) || IS_ERR(*auth_tok_key)) { +			printk(KERN_ERR "Could not find key with description: [%s]\n", +			      sig); +			rc = process_request_key_err(PTR_ERR(*auth_tok_key)); +			(*auth_tok_key) = NULL; +			goto out; +		}  	} -out_release_key: +	down_write(&(*auth_tok_key)->sem); +	rc = ecryptfs_verify_auth_tok_from_key(*auth_tok_key, auth_tok);  	if (rc) { +		up_write(&(*auth_tok_key)->sem);  		key_put(*auth_tok_key);  		(*auth_tok_key) = NULL; +		goto out;  	}  out:  	return rc; @@ -1672,7 +1733,7 @@ decrypt_passphrase_encrypted_session_key(struct ecryptfs_auth_tok *auth_tok,  	       auth_tok->session_key.decrypted_key_size);  	crypt_stat->flags |= ECRYPTFS_KEY_VALID;  	if (unlikely(ecryptfs_verbosity > 0)) { -		ecryptfs_printk(KERN_DEBUG, "FEK of size [%d]:\n", +		ecryptfs_printk(KERN_DEBUG, "FEK of size [%zd]:\n",  				crypt_stat->key_size);  		ecryptfs_dump_hex(crypt_stat->key,  				  crypt_stat->key_size); @@ -1754,7 +1815,7 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,  			if (ECRYPTFS_SIG_SIZE != tag_11_contents_size) {  				ecryptfs_printk(KERN_ERR, "Expected "  						"signature of size [%d]; " -						"read size [%d]\n", +						"read size [%zd]\n",  						ECRYPTFS_SIG_SIZE,  						tag_11_contents_size);  				rc = -EIO; @@ -1787,8 +1848,8 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,  			goto out_wipe_list;  			break;  		default: -			ecryptfs_printk(KERN_DEBUG, "No packet at offset " -					"[%d] of the file header; hex value of " +			ecryptfs_printk(KERN_DEBUG, "No packet at offset [%zd] " +					"of the file header; hex value of "  					"character is [0x%.2x]\n", i, src[i]);  			next_packet_is_auth_tok_packet = 0;  		} @@ -1808,10 +1869,6 @@ int ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat,  	 * just one will be sufficient to decrypt to get the FEK. */  find_next_matching_auth_tok:  	found_auth_tok = 0; -	if (auth_tok_key) { -		key_put(auth_tok_key); -		auth_tok_key = NULL; -	}  	list_for_each_entry(auth_tok_list_item, &auth_tok_list, list) {  		candidate_auth_tok = &auth_tok_list_item->auth_tok;  		if (unlikely(ecryptfs_verbosity > 0)) { @@ -1848,14 +1905,22 @@ found_matching_auth_tok:  		memcpy(&(candidate_auth_tok->token.private_key),  		       &(matching_auth_tok->token.private_key),  		       sizeof(struct ecryptfs_private_key)); +		up_write(&(auth_tok_key->sem)); +		key_put(auth_tok_key);  		rc = decrypt_pki_encrypted_session_key(candidate_auth_tok,  						       crypt_stat);  	} else if (candidate_auth_tok->token_type == ECRYPTFS_PASSWORD) {  		memcpy(&(candidate_auth_tok->token.password),  		       &(matching_auth_tok->token.password),  		       sizeof(struct ecryptfs_password)); +		up_write(&(auth_tok_key->sem)); +		key_put(auth_tok_key);  		rc = decrypt_passphrase_encrypted_session_key(  			candidate_auth_tok, crypt_stat); +	} else { +		up_write(&(auth_tok_key->sem)); +		key_put(auth_tok_key); +		rc = -EINVAL;  	}  	if (rc) {  		struct ecryptfs_auth_tok_list_item *auth_tok_list_item_tmp; @@ -1864,8 +1929,8 @@ found_matching_auth_tok:  				"session key for authentication token with sig "  				"[%.*s]; rc = [%d]. Removing auth tok "  				"candidate from the list and searching for " -				"the next match.\n", candidate_auth_tok_sig, -				ECRYPTFS_SIG_SIZE_HEX, rc); +				"the next match.\n", ECRYPTFS_SIG_SIZE_HEX, +				candidate_auth_tok_sig,	rc);  		list_for_each_entry_safe(auth_tok_list_item,  					 auth_tok_list_item_tmp,  					 &auth_tok_list, list) { @@ -1895,19 +1960,18 @@ found_matching_auth_tok:  out_wipe_list:  	wipe_auth_tok_list(&auth_tok_list);  out: -	if (auth_tok_key) -		key_put(auth_tok_key);  	return rc;  }  static int -pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok, +pki_encrypt_session_key(struct key *auth_tok_key, +			struct ecryptfs_auth_tok *auth_tok,  			struct ecryptfs_crypt_stat *crypt_stat,  			struct ecryptfs_key_record *key_rec)  {  	struct ecryptfs_msg_ctx *msg_ctx = NULL;  	char *payload = NULL; -	size_t payload_len; +	size_t payload_len = 0;  	struct ecryptfs_message *msg;  	int rc; @@ -1916,6 +1980,8 @@ pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,  					 crypt_stat->cipher,  					 crypt_stat->key_size),  				 crypt_stat, &payload, &payload_len); +	up_write(&(auth_tok_key->sem)); +	key_put(auth_tok_key);  	if (rc) {  		ecryptfs_printk(KERN_ERR, "Error generating tag 66 packet\n");  		goto out; @@ -1923,7 +1989,7 @@ pki_encrypt_session_key(struct ecryptfs_auth_tok *auth_tok,  	rc = ecryptfs_send_message(payload, payload_len, &msg_ctx);  	if (rc) {  		ecryptfs_printk(KERN_ERR, "Error sending message to " -				"ecryptfsd\n"); +				"ecryptfsd: %d\n", rc);  		goto out;  	}  	rc = ecryptfs_wait_for_response(msg_ctx, &msg); @@ -1945,6 +2011,8 @@ out:   * write_tag_1_packet - Write an RFC2440-compatible tag 1 (public key) packet   * @dest: Buffer into which to write the packet   * @remaining_bytes: Maximum number of bytes that can be writtn + * @auth_tok_key: The authentication token key to unlock and put when done with + *                @auth_tok   * @auth_tok: The authentication token used for generating the tag 1 packet   * @crypt_stat: The cryptographic context   * @key_rec: The key record struct for the tag 1 packet @@ -1955,7 +2023,7 @@ out:   */  static int  write_tag_1_packet(char *dest, size_t *remaining_bytes, -		   struct ecryptfs_auth_tok *auth_tok, +		   struct key *auth_tok_key, struct ecryptfs_auth_tok *auth_tok,  		   struct ecryptfs_crypt_stat *crypt_stat,  		   struct ecryptfs_key_record *key_rec, size_t *packet_size)  { @@ -1976,12 +2044,15 @@ write_tag_1_packet(char *dest, size_t *remaining_bytes,  		memcpy(key_rec->enc_key,  		       auth_tok->session_key.encrypted_key,  		       auth_tok->session_key.encrypted_key_size); +		up_write(&(auth_tok_key->sem)); +		key_put(auth_tok_key);  		goto encrypted_session_key_set;  	}  	if (auth_tok->session_key.encrypted_key_size == 0)  		auth_tok->session_key.encrypted_key_size =  			auth_tok->token.private_key.key_size; -	rc = pki_encrypt_session_key(auth_tok, crypt_stat, key_rec); +	rc = pki_encrypt_session_key(auth_tok_key, auth_tok, crypt_stat, +				     key_rec);  	if (rc) {  		printk(KERN_ERR "Failed to encrypt session key via a key "  		       "module; rc = [%d]\n", rc); @@ -2168,7 +2239,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,  	if (encrypted_session_key_valid) {  		ecryptfs_printk(KERN_DEBUG, "encrypted_session_key_valid != 0; "  				"using auth_tok->session_key.encrypted_key, " -				"where key_rec->enc_key_size = [%d]\n", +				"where key_rec->enc_key_size = [%zd]\n",  				key_rec->enc_key_size);  		memcpy(key_rec->enc_key,  		       auth_tok->session_key.encrypted_key, @@ -2185,7 +2256,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,  		       auth_tok->token.password.session_key_encryption_key,  		       crypt_stat->key_size);  		ecryptfs_printk(KERN_DEBUG, -				"Cached session key " "encryption key: \n"); +				"Cached session key encryption key:\n");  		if (ecryptfs_verbosity > 0)  			ecryptfs_dump_hex(session_key_encryption_key, 16);  	} @@ -2198,7 +2269,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,  	if (rc < 1 || rc > 2) {  		ecryptfs_printk(KERN_ERR, "Error generating scatterlist "  				"for crypt_stat session key; expected rc = 1; " -				"got rc = [%d]. key_rec->enc_key_size = [%d]\n", +				"got rc = [%d]. key_rec->enc_key_size = [%zd]\n",  				rc, key_rec->enc_key_size);  		rc = -ENOMEM;  		goto out; @@ -2209,7 +2280,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,  		ecryptfs_printk(KERN_ERR, "Error generating scatterlist "  				"for crypt_stat encrypted session key; "  				"expected rc = 1; got rc = [%d]. " -				"key_rec->enc_key_size = [%d]\n", rc, +				"key_rec->enc_key_size = [%zd]\n", rc,  				key_rec->enc_key_size);  		rc = -ENOMEM;  		goto out; @@ -2224,7 +2295,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,  		goto out;  	}  	rc = 0; -	ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes of the key\n", +	ecryptfs_printk(KERN_DEBUG, "Encrypting [%zd] bytes of the key\n",  			crypt_stat->key_size);  	rc = crypto_blkcipher_encrypt(&desc, dst_sg, src_sg,  				      (*key_rec).enc_key_size); @@ -2235,7 +2306,7 @@ write_tag_3_packet(char *dest, size_t *remaining_bytes,  	}  	ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n");  	if (ecryptfs_verbosity > 0) { -		ecryptfs_printk(KERN_DEBUG, "EFEK of size [%d]:\n", +		ecryptfs_printk(KERN_DEBUG, "EFEK of size [%zd]:\n",  				key_rec->enc_key_size);  		ecryptfs_dump_hex(key_rec->enc_key,  				  key_rec->enc_key_size); @@ -2324,7 +2395,7 @@ ecryptfs_generate_key_packet_set(char *dest_base,  				 size_t max)  {  	struct ecryptfs_auth_tok *auth_tok; -	struct ecryptfs_global_auth_tok *global_auth_tok; +	struct key *auth_tok_key = NULL;  	struct ecryptfs_mount_crypt_stat *mount_crypt_stat =  		&ecryptfs_superblock_to_private(  			ecryptfs_dentry->d_sb)->mount_crypt_stat; @@ -2343,26 +2414,23 @@ ecryptfs_generate_key_packet_set(char *dest_base,  	list_for_each_entry(key_sig, &crypt_stat->keysig_list,  			    crypt_stat_list) {  		memset(key_rec, 0, sizeof(*key_rec)); -		rc = ecryptfs_find_global_auth_tok_for_sig(&global_auth_tok, +		rc = ecryptfs_find_global_auth_tok_for_sig(&auth_tok_key, +							   &auth_tok,  							   mount_crypt_stat,  							   key_sig->keysig);  		if (rc) { -			printk(KERN_ERR "Error attempting to get the global " -			       "auth_tok; rc = [%d]\n", rc); +			printk(KERN_WARNING "Unable to retrieve auth tok with " +			       "sig = [%s]\n", key_sig->keysig); +			rc = process_find_global_auth_tok_for_sig_err(rc);  			goto out_free;  		} -		if (global_auth_tok->flags & ECRYPTFS_AUTH_TOK_INVALID) { -			printk(KERN_WARNING -			       "Skipping invalid auth tok with sig = [%s]\n", -			       global_auth_tok->sig); -			continue; -		} -		auth_tok = global_auth_tok->global_auth_tok;  		if (auth_tok->token_type == ECRYPTFS_PASSWORD) {  			rc = write_tag_3_packet((dest_base + (*len)),  						&max, auth_tok,  						crypt_stat, key_rec,  						&written); +			up_write(&(auth_tok_key->sem)); +			key_put(auth_tok_key);  			if (rc) {  				ecryptfs_printk(KERN_WARNING, "Error "  						"writing tag 3 packet\n"); @@ -2380,8 +2448,8 @@ ecryptfs_generate_key_packet_set(char *dest_base,  			}  			(*len) += written;  		} else if (auth_tok->token_type == ECRYPTFS_PRIVATE_KEY) { -			rc = write_tag_1_packet(dest_base + (*len), -						&max, auth_tok, +			rc = write_tag_1_packet(dest_base + (*len), &max, +						auth_tok_key, auth_tok,  						crypt_stat, key_rec, &written);  			if (rc) {  				ecryptfs_printk(KERN_WARNING, "Error " @@ -2390,6 +2458,8 @@ ecryptfs_generate_key_packet_set(char *dest_base,  			}  			(*len) += written;  		} else { +			up_write(&(auth_tok_key->sem)); +			key_put(auth_tok_key);  			ecryptfs_printk(KERN_WARNING, "Unsupported "  					"authentication token type\n");  			rc = -EINVAL; @@ -2424,6 +2494,7 @@ int ecryptfs_add_keysig(struct ecryptfs_crypt_stat *crypt_stat, char *sig)  		return -ENOMEM;  	}  	memcpy(new_key_sig->keysig, sig, ECRYPTFS_SIG_SIZE_HEX); +	new_key_sig->keysig[ECRYPTFS_SIG_SIZE_HEX] = '\0';  	/* Caller must hold keysig_list_mutex */  	list_add(&new_key_sig->crypt_stat_list, &crypt_stat->keysig_list); @@ -2453,7 +2524,6 @@ ecryptfs_add_global_auth_tok(struct ecryptfs_mount_crypt_stat *mount_crypt_stat,  	mutex_lock(&mount_crypt_stat->global_auth_tok_list_mutex);  	list_add(&new_auth_tok->mount_crypt_stat_list,  		 &mount_crypt_stat->global_auth_tok_list); -	mount_crypt_stat->num_global_auth_toks++;  	mutex_unlock(&mount_crypt_stat->global_auth_tok_list_mutex);  out:  	return rc;  | 
