OSDN Git Service

KEYS: Provide software public key query function [ver #2]
authorDavid Howells <dhowells@redhat.com>
Tue, 9 Oct 2018 16:47:23 +0000 (17:47 +0100)
committerJames Morris <james.morris@microsoft.com>
Fri, 26 Oct 2018 08:30:46 +0000 (09:30 +0100)
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>
crypto/asymmetric_keys/public_key.c

index e929fe1..761bfab 100644 (file)
@@ -60,6 +60,81 @@ static void public_key_destroy(void *payload0, void *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.
  */
 int public_key_verify_signature(const struct public_key *pkey,
@@ -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);