mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	KEYS: asym_tpm: Implement encryption operation [ver #2]
This patch impelements the pkey_encrypt operation. The public key portion extracted from the TPM key blob is used. The operation is performed entirely in software using the crypto API. Signed-off-by: Denis Kenzior <denkenz@gmail.com> Signed-off-by: David Howells <dhowells@redhat.com> Tested-by: Marcel Holtmann <marcel@holtmann.org> Reviewed-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: James Morris <james.morris@microsoft.com>
This commit is contained in:
		
							parent
							
								
									dff5a61a59
								
							
						
					
					
						commit
						ad4b1eb5fb
					
				
					 1 changed files with 84 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -165,6 +165,8 @@ static int tpm_key_query(const struct kernel_pkey_params *params,
 | 
			
		|||
	info->max_enc_size = len;
 | 
			
		||||
	info->max_dec_size = tk->key_len / 8;
 | 
			
		||||
 | 
			
		||||
	info->supported_ops = KEYCTL_SUPPORTS_ENCRYPT;
 | 
			
		||||
 | 
			
		||||
	ret = 0;
 | 
			
		||||
error_free_tfm:
 | 
			
		||||
	crypto_free_akcipher(tfm);
 | 
			
		||||
| 
						 | 
				
			
			@ -172,6 +174,87 @@ static int tpm_key_query(const struct kernel_pkey_params *params,
 | 
			
		|||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Encryption operation is performed with the public key.  Hence it is done
 | 
			
		||||
 * in software
 | 
			
		||||
 */
 | 
			
		||||
static int tpm_key_encrypt(struct tpm_key *tk,
 | 
			
		||||
			   struct kernel_pkey_params *params,
 | 
			
		||||
			   const void *in, void *out)
 | 
			
		||||
{
 | 
			
		||||
	char alg_name[CRYPTO_MAX_ALG_NAME];
 | 
			
		||||
	struct crypto_akcipher *tfm;
 | 
			
		||||
	struct akcipher_request *req;
 | 
			
		||||
	struct crypto_wait cwait;
 | 
			
		||||
	struct scatterlist in_sg, out_sg;
 | 
			
		||||
	uint8_t der_pub_key[PUB_KEY_BUF_SIZE];
 | 
			
		||||
	uint32_t der_pub_key_len;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	pr_devel("==>%s()\n", __func__);
 | 
			
		||||
 | 
			
		||||
	ret = determine_akcipher(params->encoding, params->hash_algo, alg_name);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	tfm = crypto_alloc_akcipher(alg_name, 0, 0);
 | 
			
		||||
	if (IS_ERR(tfm))
 | 
			
		||||
		return PTR_ERR(tfm);
 | 
			
		||||
 | 
			
		||||
	der_pub_key_len = derive_pub_key(tk->pub_key, tk->pub_key_len,
 | 
			
		||||
					 der_pub_key);
 | 
			
		||||
 | 
			
		||||
	ret = crypto_akcipher_set_pub_key(tfm, der_pub_key, der_pub_key_len);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		goto error_free_tfm;
 | 
			
		||||
 | 
			
		||||
	req = akcipher_request_alloc(tfm, GFP_KERNEL);
 | 
			
		||||
	if (!req)
 | 
			
		||||
		goto error_free_tfm;
 | 
			
		||||
 | 
			
		||||
	sg_init_one(&in_sg, in, params->in_len);
 | 
			
		||||
	sg_init_one(&out_sg, out, params->out_len);
 | 
			
		||||
	akcipher_request_set_crypt(req, &in_sg, &out_sg, params->in_len,
 | 
			
		||||
				   params->out_len);
 | 
			
		||||
	crypto_init_wait(&cwait);
 | 
			
		||||
	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
 | 
			
		||||
				      CRYPTO_TFM_REQ_MAY_SLEEP,
 | 
			
		||||
				      crypto_req_done, &cwait);
 | 
			
		||||
 | 
			
		||||
	ret = crypto_akcipher_encrypt(req);
 | 
			
		||||
	ret = crypto_wait_req(ret, &cwait);
 | 
			
		||||
 | 
			
		||||
	if (ret == 0)
 | 
			
		||||
		ret = req->dst_len;
 | 
			
		||||
 | 
			
		||||
	akcipher_request_free(req);
 | 
			
		||||
error_free_tfm:
 | 
			
		||||
	crypto_free_akcipher(tfm);
 | 
			
		||||
	pr_devel("<==%s() = %d\n", __func__, ret);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Do encryption, decryption and signing ops.
 | 
			
		||||
 */
 | 
			
		||||
static int tpm_key_eds_op(struct kernel_pkey_params *params,
 | 
			
		||||
			  const void *in, void *out)
 | 
			
		||||
{
 | 
			
		||||
	struct tpm_key *tk = params->key->payload.data[asym_crypto];
 | 
			
		||||
	int ret = -EOPNOTSUPP;
 | 
			
		||||
 | 
			
		||||
	/* Perform the encryption calculation. */
 | 
			
		||||
	switch (params->op) {
 | 
			
		||||
	case kernel_pkey_encrypt:
 | 
			
		||||
		ret = tpm_key_encrypt(tk, params, in, out);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		BUG();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Parse enough information out of TPM_KEY structure:
 | 
			
		||||
 * TPM_STRUCT_VER -> 4 bytes
 | 
			
		||||
| 
						 | 
				
			
			@ -329,6 +412,7 @@ struct asymmetric_key_subtype asym_tpm_subtype = {
 | 
			
		|||
	.describe		= asym_tpm_describe,
 | 
			
		||||
	.destroy		= asym_tpm_destroy,
 | 
			
		||||
	.query			= tpm_key_query,
 | 
			
		||||
	.eds_op			= tpm_key_eds_op,
 | 
			
		||||
};
 | 
			
		||||
EXPORT_SYMBOL_GPL(asym_tpm_subtype);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue