forked from mirrors/linux
		
	KEYS: Provide software public key query function [ver #2]
Provide a query function for the software public key implementation. This permits information about such a key to be obtained using query_asymmetric_key() or KEYCTL_PKEY_QUERY. Signed-off-by: David Howells <dhowells@redhat.com> Tested-by: Marcel Holtmann <marcel@holtmann.org> Reviewed-by: Marcel Holtmann <marcel@holtmann.org> Reviewed-by: Denis Kenzior <denkenz@gmail.com> Tested-by: Denis Kenzior <denkenz@gmail.com> Signed-off-by: James Morris <james.morris@microsoft.com>
This commit is contained in:
		
							parent
							
								
									0398849077
								
							
						
					
					
						commit
						82f94f2447
					
				
					 1 changed files with 82 additions and 17 deletions
				
			
		| 
						 | 
				
			
			@ -59,6 +59,81 @@ static void public_key_destroy(void *payload0, void *payload3)
 | 
			
		|||
	public_key_signature_free(payload3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Determine the crypto algorithm name.
 | 
			
		||||
 */
 | 
			
		||||
static
 | 
			
		||||
int software_key_determine_akcipher(const char *encoding,
 | 
			
		||||
				    const char *hash_algo,
 | 
			
		||||
				    const struct public_key *pkey,
 | 
			
		||||
				    char alg_name[CRYPTO_MAX_ALG_NAME])
 | 
			
		||||
{
 | 
			
		||||
	int n;
 | 
			
		||||
 | 
			
		||||
	if (strcmp(encoding, "pkcs1") == 0) {
 | 
			
		||||
		/* The data wangled by the RSA algorithm is typically padded
 | 
			
		||||
		 * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447
 | 
			
		||||
		 * sec 8.2].
 | 
			
		||||
		 */
 | 
			
		||||
		if (!hash_algo)
 | 
			
		||||
			n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
 | 
			
		||||
				     "pkcs1pad(%s)",
 | 
			
		||||
				     pkey->pkey_algo);
 | 
			
		||||
		else
 | 
			
		||||
			n = snprintf(alg_name, CRYPTO_MAX_ALG_NAME,
 | 
			
		||||
				     "pkcs1pad(%s,%s)",
 | 
			
		||||
				     pkey->pkey_algo, hash_algo);
 | 
			
		||||
		return n >= CRYPTO_MAX_ALG_NAME ? -EINVAL : 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (strcmp(encoding, "raw") == 0) {
 | 
			
		||||
		strcpy(alg_name, pkey->pkey_algo);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return -ENOPKG;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Query information about a key.
 | 
			
		||||
 */
 | 
			
		||||
static int software_key_query(const struct kernel_pkey_params *params,
 | 
			
		||||
			      struct kernel_pkey_query *info)
 | 
			
		||||
{
 | 
			
		||||
	struct crypto_akcipher *tfm;
 | 
			
		||||
	struct public_key *pkey = params->key->payload.data[asym_crypto];
 | 
			
		||||
	char alg_name[CRYPTO_MAX_ALG_NAME];
 | 
			
		||||
	int ret, len;
 | 
			
		||||
 | 
			
		||||
	ret = software_key_determine_akcipher(params->encoding,
 | 
			
		||||
					      params->hash_algo,
 | 
			
		||||
					      pkey, alg_name);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	tfm = crypto_alloc_akcipher(alg_name, 0, 0);
 | 
			
		||||
	if (IS_ERR(tfm))
 | 
			
		||||
		return PTR_ERR(tfm);
 | 
			
		||||
 | 
			
		||||
	ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		goto error_free_tfm;
 | 
			
		||||
 | 
			
		||||
	len = crypto_akcipher_maxsize(tfm);
 | 
			
		||||
	info->key_size = len * 8;
 | 
			
		||||
	info->max_data_size = len;
 | 
			
		||||
	info->max_sig_size = len;
 | 
			
		||||
	info->max_enc_size = len;
 | 
			
		||||
	info->max_dec_size = len;
 | 
			
		||||
	info->supported_ops = KEYCTL_SUPPORTS_VERIFY;
 | 
			
		||||
	ret = 0;
 | 
			
		||||
 | 
			
		||||
error_free_tfm:
 | 
			
		||||
	crypto_free_akcipher(tfm);
 | 
			
		||||
	pr_devel("<==%s() = %d\n", __func__, ret);
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Verify a signature using a public key.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -69,8 +144,7 @@ int public_key_verify_signature(const struct public_key *pkey,
 | 
			
		|||
	struct crypto_akcipher *tfm;
 | 
			
		||||
	struct akcipher_request *req;
 | 
			
		||||
	struct scatterlist sig_sg, digest_sg;
 | 
			
		||||
	const char *alg_name;
 | 
			
		||||
	char alg_name_buf[CRYPTO_MAX_ALG_NAME];
 | 
			
		||||
	char alg_name[CRYPTO_MAX_ALG_NAME];
 | 
			
		||||
	void *output;
 | 
			
		||||
	unsigned int outlen;
 | 
			
		||||
	int ret;
 | 
			
		||||
| 
						 | 
				
			
			@ -81,21 +155,11 @@ int public_key_verify_signature(const struct public_key *pkey,
 | 
			
		|||
	BUG_ON(!sig);
 | 
			
		||||
	BUG_ON(!sig->s);
 | 
			
		||||
 | 
			
		||||
	if (!sig->digest)
 | 
			
		||||
		return -ENOPKG;
 | 
			
		||||
 | 
			
		||||
	alg_name = sig->pkey_algo;
 | 
			
		||||
	if (strcmp(sig->pkey_algo, "rsa") == 0) {
 | 
			
		||||
		/* The data wangled by the RSA algorithm is typically padded
 | 
			
		||||
		 * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447
 | 
			
		||||
		 * sec 8.2].
 | 
			
		||||
		 */
 | 
			
		||||
		if (snprintf(alg_name_buf, CRYPTO_MAX_ALG_NAME,
 | 
			
		||||
			     "pkcs1pad(rsa,%s)", sig->hash_algo
 | 
			
		||||
			     ) >= CRYPTO_MAX_ALG_NAME)
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
		alg_name = alg_name_buf;
 | 
			
		||||
	}
 | 
			
		||||
	ret = software_key_determine_akcipher(sig->encoding,
 | 
			
		||||
					      sig->hash_algo,
 | 
			
		||||
					      pkey, alg_name);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	tfm = crypto_alloc_akcipher(alg_name, 0, 0);
 | 
			
		||||
	if (IS_ERR(tfm))
 | 
			
		||||
| 
						 | 
				
			
			@ -167,6 +231,7 @@ struct asymmetric_key_subtype public_key_subtype = {
 | 
			
		|||
	.name_len		= sizeof("public_key") - 1,
 | 
			
		||||
	.describe		= public_key_describe,
 | 
			
		||||
	.destroy		= public_key_destroy,
 | 
			
		||||
	.query			= software_key_query,
 | 
			
		||||
	.verify_signature	= public_key_verify_signature_2,
 | 
			
		||||
};
 | 
			
		||||
EXPORT_SYMBOL_GPL(public_key_subtype);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue