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);
 | 
						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.
 | 
					 * 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 crypto_akcipher *tfm;
 | 
				
			||||||
	struct akcipher_request *req;
 | 
						struct akcipher_request *req;
 | 
				
			||||||
	struct scatterlist sig_sg, digest_sg;
 | 
						struct scatterlist sig_sg, digest_sg;
 | 
				
			||||||
	const char *alg_name;
 | 
						char alg_name[CRYPTO_MAX_ALG_NAME];
 | 
				
			||||||
	char alg_name_buf[CRYPTO_MAX_ALG_NAME];
 | 
					 | 
				
			||||||
	void *output;
 | 
						void *output;
 | 
				
			||||||
	unsigned int outlen;
 | 
						unsigned int outlen;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
| 
						 | 
					@ -81,21 +155,11 @@ int public_key_verify_signature(const struct public_key *pkey,
 | 
				
			||||||
	BUG_ON(!sig);
 | 
						BUG_ON(!sig);
 | 
				
			||||||
	BUG_ON(!sig->s);
 | 
						BUG_ON(!sig->s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!sig->digest)
 | 
						ret = software_key_determine_akcipher(sig->encoding,
 | 
				
			||||||
		return -ENOPKG;
 | 
										      sig->hash_algo,
 | 
				
			||||||
 | 
										      pkey, alg_name);
 | 
				
			||||||
	alg_name = sig->pkey_algo;
 | 
						if (ret < 0)
 | 
				
			||||||
	if (strcmp(sig->pkey_algo, "rsa") == 0) {
 | 
							return ret;
 | 
				
			||||||
		/* 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;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tfm = crypto_alloc_akcipher(alg_name, 0, 0);
 | 
						tfm = crypto_alloc_akcipher(alg_name, 0, 0);
 | 
				
			||||||
	if (IS_ERR(tfm))
 | 
						if (IS_ERR(tfm))
 | 
				
			||||||
| 
						 | 
					@ -167,6 +231,7 @@ struct asymmetric_key_subtype public_key_subtype = {
 | 
				
			||||||
	.name_len		= sizeof("public_key") - 1,
 | 
						.name_len		= sizeof("public_key") - 1,
 | 
				
			||||||
	.describe		= public_key_describe,
 | 
						.describe		= public_key_describe,
 | 
				
			||||||
	.destroy		= public_key_destroy,
 | 
						.destroy		= public_key_destroy,
 | 
				
			||||||
 | 
						.query			= software_key_query,
 | 
				
			||||||
	.verify_signature	= public_key_verify_signature_2,
 | 
						.verify_signature	= public_key_verify_signature_2,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
EXPORT_SYMBOL_GPL(public_key_subtype);
 | 
					EXPORT_SYMBOL_GPL(public_key_subtype);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue