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
@ -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 New Issue
Block a user