mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-05 02:19:51 +00:00
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