LCOV - code coverage report
Current view: top level - crypto/asymmetric_keys - asymmetric_type.c (source / functions) Hit Total Coverage
Test: Real Lines: 87 199 43.7 %
Date: 2020-10-17 15:46:16 Functions: 0 23 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /* Asymmetric public-key cryptography key type
       3                 :            :  *
       4                 :            :  * See Documentation/crypto/asymmetric-keys.txt
       5                 :            :  *
       6                 :            :  * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
       7                 :            :  * Written by David Howells (dhowells@redhat.com)
       8                 :            :  */
       9                 :            : #include <keys/asymmetric-subtype.h>
      10                 :            : #include <keys/asymmetric-parser.h>
      11                 :            : #include <crypto/public_key.h>
      12                 :            : #include <linux/seq_file.h>
      13                 :            : #include <linux/module.h>
      14                 :            : #include <linux/slab.h>
      15                 :            : #include <linux/ctype.h>
      16                 :            : #include <keys/system_keyring.h>
      17                 :            : #include <keys/user-type.h>
      18                 :            : #include "asymmetric_keys.h"
      19                 :            : 
      20                 :            : MODULE_LICENSE("GPL");
      21                 :            : 
      22                 :            : const char *const key_being_used_for[NR__KEY_BEING_USED_FOR] = {
      23                 :            :         [VERIFYING_MODULE_SIGNATURE]            = "mod sig",
      24                 :            :         [VERIFYING_FIRMWARE_SIGNATURE]          = "firmware sig",
      25                 :            :         [VERIFYING_KEXEC_PE_SIGNATURE]          = "kexec PE sig",
      26                 :            :         [VERIFYING_KEY_SIGNATURE]               = "key sig",
      27                 :            :         [VERIFYING_KEY_SELF_SIGNATURE]          = "key self sig",
      28                 :            :         [VERIFYING_UNSPECIFIED_SIGNATURE]       = "unspec sig",
      29                 :            : };
      30                 :            : EXPORT_SYMBOL_GPL(key_being_used_for);
      31                 :            : 
      32                 :            : static LIST_HEAD(asymmetric_key_parsers);
      33                 :            : static DECLARE_RWSEM(asymmetric_key_parsers_sem);
      34                 :            : 
      35                 :            : /**
      36                 :            :  * find_asymmetric_key - Find a key by ID.
      37                 :            :  * @keyring: The keys to search.
      38                 :            :  * @id_0: The first ID to look for or NULL.
      39                 :            :  * @id_1: The second ID to look for or NULL.
      40                 :            :  * @partial: Use partial match if true, exact if false.
      41                 :            :  *
      42                 :            :  * Find a key in the given keyring by identifier.  The preferred identifier is
      43                 :            :  * the id_0 and the fallback identifier is the id_1.  If both are given, the
      44                 :            :  * lookup is by the former, but the latter must also match.
      45                 :            :  */
      46                 :          3 : struct key *find_asymmetric_key(struct key *keyring,
      47                 :            :                                 const struct asymmetric_key_id *id_0,
      48                 :            :                                 const struct asymmetric_key_id *id_1,
      49                 :            :                                 bool partial)
      50                 :            : {
      51                 :            :         struct key *key;
      52                 :            :         key_ref_t ref;
      53                 :            :         const char *lookup;
      54                 :            :         char *req, *p;
      55                 :            :         int len;
      56                 :            : 
      57                 :          3 :         BUG_ON(!id_0 && !id_1);
      58                 :            : 
      59                 :          3 :         if (id_0) {
      60                 :          3 :                 lookup = id_0->data;
      61                 :          3 :                 len = id_0->len;
      62                 :            :         } else {
      63                 :          0 :                 lookup = id_1->data;
      64                 :          0 :                 len = id_1->len;
      65                 :            :         }
      66                 :            : 
      67                 :            :         /* Construct an identifier "id:<keyid>". */
      68                 :          3 :         p = req = kmalloc(2 + 1 + len * 2 + 1, GFP_KERNEL);
      69                 :          3 :         if (!req)
      70                 :            :                 return ERR_PTR(-ENOMEM);
      71                 :            : 
      72                 :          3 :         if (partial) {
      73                 :          0 :                 *p++ = 'i';
      74                 :          0 :                 *p++ = 'd';
      75                 :            :         } else {
      76                 :          3 :                 *p++ = 'e';
      77                 :          3 :                 *p++ = 'x';
      78                 :            :         }
      79                 :          3 :         *p++ = ':';
      80                 :          3 :         p = bin2hex(p, lookup, len);
      81                 :          3 :         *p = 0;
      82                 :            : 
      83                 :            :         pr_debug("Look up: \"%s\"\n", req);
      84                 :            : 
      85                 :          3 :         ref = keyring_search(make_key_ref(keyring, 1),
      86                 :            :                              &key_type_asymmetric, req, true);
      87                 :            :         if (IS_ERR(ref))
      88                 :            :                 pr_debug("Request for key '%s' err %ld\n", req, PTR_ERR(ref));
      89                 :          3 :         kfree(req);
      90                 :            : 
      91                 :          3 :         if (IS_ERR(ref)) {
      92                 :          0 :                 switch (PTR_ERR(ref)) {
      93                 :            :                         /* Hide some search errors */
      94                 :            :                 case -EACCES:
      95                 :            :                 case -ENOTDIR:
      96                 :            :                 case -EAGAIN:
      97                 :            :                         return ERR_PTR(-ENOKEY);
      98                 :            :                 default:
      99                 :          0 :                         return ERR_CAST(ref);
     100                 :            :                 }
     101                 :            :         }
     102                 :            : 
     103                 :            :         key = key_ref_to_ptr(ref);
     104                 :          3 :         if (id_0 && id_1) {
     105                 :            :                 const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
     106                 :            : 
     107                 :          0 :                 if (!kids->id[1]) {
     108                 :            :                         pr_debug("First ID matches, but second is missing\n");
     109                 :            :                         goto reject;
     110                 :            :                 }
     111                 :          0 :                 if (!asymmetric_key_id_same(id_1, kids->id[1])) {
     112                 :            :                         pr_debug("First ID matches, but second does not\n");
     113                 :            :                         goto reject;
     114                 :            :                 }
     115                 :            :         }
     116                 :            : 
     117                 :            :         pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key));
     118                 :            :         return key;
     119                 :            : 
     120                 :            : reject:
     121                 :          0 :         key_put(key);
     122                 :          0 :         return ERR_PTR(-EKEYREJECTED);
     123                 :            : }
     124                 :            : EXPORT_SYMBOL_GPL(find_asymmetric_key);
     125                 :            : 
     126                 :            : /**
     127                 :            :  * asymmetric_key_generate_id: Construct an asymmetric key ID
     128                 :            :  * @val_1: First binary blob
     129                 :            :  * @len_1: Length of first binary blob
     130                 :            :  * @val_2: Second binary blob
     131                 :            :  * @len_2: Length of second binary blob
     132                 :            :  *
     133                 :            :  * Construct an asymmetric key ID from a pair of binary blobs.
     134                 :            :  */
     135                 :          3 : struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1,
     136                 :            :                                                      size_t len_1,
     137                 :            :                                                      const void *val_2,
     138                 :            :                                                      size_t len_2)
     139                 :            : {
     140                 :            :         struct asymmetric_key_id *kid;
     141                 :            : 
     142                 :          3 :         kid = kmalloc(sizeof(struct asymmetric_key_id) + len_1 + len_2,
     143                 :            :                       GFP_KERNEL);
     144                 :          3 :         if (!kid)
     145                 :            :                 return ERR_PTR(-ENOMEM);
     146                 :          3 :         kid->len = len_1 + len_2;
     147                 :          3 :         memcpy(kid->data, val_1, len_1);
     148                 :          3 :         memcpy(kid->data + len_1, val_2, len_2);
     149                 :          3 :         return kid;
     150                 :            : }
     151                 :            : EXPORT_SYMBOL_GPL(asymmetric_key_generate_id);
     152                 :            : 
     153                 :            : /**
     154                 :            :  * asymmetric_key_id_same - Return true if two asymmetric keys IDs are the same.
     155                 :            :  * @kid_1, @kid_2: The key IDs to compare
     156                 :            :  */
     157                 :          3 : bool asymmetric_key_id_same(const struct asymmetric_key_id *kid1,
     158                 :            :                             const struct asymmetric_key_id *kid2)
     159                 :            : {
     160                 :          3 :         if (!kid1 || !kid2)
     161                 :            :                 return false;
     162                 :          3 :         if (kid1->len != kid2->len)
     163                 :            :                 return false;
     164                 :          3 :         return memcmp(kid1->data, kid2->data, kid1->len) == 0;
     165                 :            : }
     166                 :            : EXPORT_SYMBOL_GPL(asymmetric_key_id_same);
     167                 :            : 
     168                 :            : /**
     169                 :            :  * asymmetric_key_id_partial - Return true if two asymmetric keys IDs
     170                 :            :  * partially match
     171                 :            :  * @kid_1, @kid_2: The key IDs to compare
     172                 :            :  */
     173                 :          0 : bool asymmetric_key_id_partial(const struct asymmetric_key_id *kid1,
     174                 :            :                                const struct asymmetric_key_id *kid2)
     175                 :            : {
     176                 :          0 :         if (!kid1 || !kid2)
     177                 :            :                 return false;
     178                 :          0 :         if (kid1->len < kid2->len)
     179                 :            :                 return false;
     180                 :          0 :         return memcmp(kid1->data + (kid1->len - kid2->len),
     181                 :          0 :                       kid2->data, kid2->len) == 0;
     182                 :            : }
     183                 :            : EXPORT_SYMBOL_GPL(asymmetric_key_id_partial);
     184                 :            : 
     185                 :            : /**
     186                 :            :  * asymmetric_match_key_ids - Search asymmetric key IDs
     187                 :            :  * @kids: The list of key IDs to check
     188                 :            :  * @match_id: The key ID we're looking for
     189                 :            :  * @match: The match function to use
     190                 :            :  */
     191                 :          3 : static bool asymmetric_match_key_ids(
     192                 :            :         const struct asymmetric_key_ids *kids,
     193                 :            :         const struct asymmetric_key_id *match_id,
     194                 :            :         bool (*match)(const struct asymmetric_key_id *kid1,
     195                 :            :                       const struct asymmetric_key_id *kid2))
     196                 :            : {
     197                 :            :         int i;
     198                 :            : 
     199                 :          3 :         if (!kids || !match_id)
     200                 :            :                 return false;
     201                 :          0 :         for (i = 0; i < ARRAY_SIZE(kids->id); i++)
     202                 :          3 :                 if (match(kids->id[i], match_id))
     203                 :            :                         return true;
     204                 :            :         return false;
     205                 :            : }
     206                 :            : 
     207                 :            : /* helper function can be called directly with pre-allocated memory */
     208                 :          0 : inline int __asymmetric_key_hex_to_key_id(const char *id,
     209                 :            :                                    struct asymmetric_key_id *match_id,
     210                 :            :                                    size_t hexlen)
     211                 :            : {
     212                 :          3 :         match_id->len = hexlen;
     213                 :          3 :         return hex2bin(match_id->data, id, hexlen);
     214                 :            : }
     215                 :            : 
     216                 :            : /**
     217                 :            :  * asymmetric_key_hex_to_key_id - Convert a hex string into a key ID.
     218                 :            :  * @id: The ID as a hex string.
     219                 :            :  */
     220                 :          3 : struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id)
     221                 :            : {
     222                 :            :         struct asymmetric_key_id *match_id;
     223                 :            :         size_t asciihexlen;
     224                 :            :         int ret;
     225                 :            : 
     226                 :          3 :         if (!*id)
     227                 :            :                 return ERR_PTR(-EINVAL);
     228                 :          3 :         asciihexlen = strlen(id);
     229                 :          3 :         if (asciihexlen & 1)
     230                 :            :                 return ERR_PTR(-EINVAL);
     231                 :            : 
     232                 :          3 :         match_id = kmalloc(sizeof(struct asymmetric_key_id) + asciihexlen / 2,
     233                 :            :                            GFP_KERNEL);
     234                 :          3 :         if (!match_id)
     235                 :            :                 return ERR_PTR(-ENOMEM);
     236                 :            :         ret = __asymmetric_key_hex_to_key_id(id, match_id, asciihexlen / 2);
     237                 :          3 :         if (ret < 0) {
     238                 :          0 :                 kfree(match_id);
     239                 :          0 :                 return ERR_PTR(-EINVAL);
     240                 :            :         }
     241                 :            :         return match_id;
     242                 :            : }
     243                 :            : 
     244                 :            : /*
     245                 :            :  * Match asymmetric keys by an exact match on an ID.
     246                 :            :  */
     247                 :          3 : static bool asymmetric_key_cmp(const struct key *key,
     248                 :            :                                const struct key_match_data *match_data)
     249                 :            : {
     250                 :            :         const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
     251                 :          3 :         const struct asymmetric_key_id *match_id = match_data->preparsed;
     252                 :            : 
     253                 :          3 :         return asymmetric_match_key_ids(kids, match_id,
     254                 :            :                                         asymmetric_key_id_same);
     255                 :            : }
     256                 :            : 
     257                 :            : /*
     258                 :            :  * Match asymmetric keys by a partial match on an IDs.
     259                 :            :  */
     260                 :          0 : static bool asymmetric_key_cmp_partial(const struct key *key,
     261                 :            :                                        const struct key_match_data *match_data)
     262                 :            : {
     263                 :            :         const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
     264                 :          0 :         const struct asymmetric_key_id *match_id = match_data->preparsed;
     265                 :            : 
     266                 :          0 :         return asymmetric_match_key_ids(kids, match_id,
     267                 :            :                                         asymmetric_key_id_partial);
     268                 :            : }
     269                 :            : 
     270                 :            : /*
     271                 :            :  * Preparse the match criterion.  If we don't set lookup_type and cmp,
     272                 :            :  * the default will be an exact match on the key description.
     273                 :            :  *
     274                 :            :  * There are some specifiers for matching key IDs rather than by the key
     275                 :            :  * description:
     276                 :            :  *
     277                 :            :  *      "id:<id>" - find a key by partial match on any available ID
     278                 :            :  *      "ex:<id>" - find a key by exact match on any available ID
     279                 :            :  *
     280                 :            :  * These have to be searched by iteration rather than by direct lookup because
     281                 :            :  * the key is hashed according to its description.
     282                 :            :  */
     283                 :          3 : static int asymmetric_key_match_preparse(struct key_match_data *match_data)
     284                 :            : {
     285                 :            :         struct asymmetric_key_id *match_id;
     286                 :          3 :         const char *spec = match_data->raw_data;
     287                 :            :         const char *id;
     288                 :            :         bool (*cmp)(const struct key *, const struct key_match_data *) =
     289                 :            :                 asymmetric_key_cmp;
     290                 :            : 
     291                 :          3 :         if (!spec || !*spec)
     292                 :            :                 return -EINVAL;
     293                 :          3 :         if (spec[0] == 'i' &&
     294                 :          0 :             spec[1] == 'd' &&
     295                 :          0 :             spec[2] == ':') {
     296                 :          0 :                 id = spec + 3;
     297                 :          0 :                 cmp = asymmetric_key_cmp_partial;
     298                 :          3 :         } else if (spec[0] == 'e' &&
     299                 :          3 :                    spec[1] == 'x' &&
     300                 :          3 :                    spec[2] == ':') {
     301                 :          3 :                 id = spec + 3;
     302                 :            :         } else {
     303                 :            :                 goto default_match;
     304                 :            :         }
     305                 :            : 
     306                 :          3 :         match_id = asymmetric_key_hex_to_key_id(id);
     307                 :          3 :         if (IS_ERR(match_id))
     308                 :          0 :                 return PTR_ERR(match_id);
     309                 :            : 
     310                 :          3 :         match_data->preparsed = match_id;
     311                 :          3 :         match_data->cmp = cmp;
     312                 :          3 :         match_data->lookup_type = KEYRING_SEARCH_LOOKUP_ITERATE;
     313                 :          3 :         return 0;
     314                 :            : 
     315                 :            : default_match:
     316                 :            :         return 0;
     317                 :            : }
     318                 :            : 
     319                 :            : /*
     320                 :            :  * Free the preparsed the match criterion.
     321                 :            :  */
     322                 :          3 : static void asymmetric_key_match_free(struct key_match_data *match_data)
     323                 :            : {
     324                 :          3 :         kfree(match_data->preparsed);
     325                 :          3 : }
     326                 :            : 
     327                 :            : /*
     328                 :            :  * Describe the asymmetric key
     329                 :            :  */
     330                 :          0 : static void asymmetric_key_describe(const struct key *key, struct seq_file *m)
     331                 :            : {
     332                 :            :         const struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
     333                 :            :         const struct asymmetric_key_ids *kids = asymmetric_key_ids(key);
     334                 :            :         const struct asymmetric_key_id *kid;
     335                 :            :         const unsigned char *p;
     336                 :            :         int n;
     337                 :            : 
     338                 :          0 :         seq_puts(m, key->description);
     339                 :            : 
     340                 :          0 :         if (subtype) {
     341                 :          0 :                 seq_puts(m, ": ");
     342                 :          0 :                 subtype->describe(key, m);
     343                 :            : 
     344                 :          0 :                 if (kids && kids->id[1]) {
     345                 :            :                         kid = kids->id[1];
     346                 :          0 :                         seq_putc(m, ' ');
     347                 :          0 :                         n = kid->len;
     348                 :          0 :                         p = kid->data;
     349                 :          0 :                         if (n > 4) {
     350                 :          0 :                                 p += n - 4;
     351                 :            :                                 n = 4;
     352                 :            :                         }
     353                 :          0 :                         seq_printf(m, "%*phN", n, p);
     354                 :            :                 }
     355                 :            : 
     356                 :          0 :                 seq_puts(m, " [");
     357                 :            :                 /* put something here to indicate the key's capabilities */
     358                 :          0 :                 seq_putc(m, ']');
     359                 :            :         }
     360                 :          0 : }
     361                 :            : 
     362                 :            : /*
     363                 :            :  * Preparse a asymmetric payload to get format the contents appropriately for the
     364                 :            :  * internal payload to cut down on the number of scans of the data performed.
     365                 :            :  *
     366                 :            :  * We also generate a proposed description from the contents of the key that
     367                 :            :  * can be used to name the key if the user doesn't want to provide one.
     368                 :            :  */
     369                 :          3 : static int asymmetric_key_preparse(struct key_preparsed_payload *prep)
     370                 :            : {
     371                 :            :         struct asymmetric_key_parser *parser;
     372                 :            :         int ret;
     373                 :            : 
     374                 :            :         pr_devel("==>%s()\n", __func__);
     375                 :            : 
     376                 :          3 :         if (prep->datalen == 0)
     377                 :            :                 return -EINVAL;
     378                 :            : 
     379                 :          3 :         down_read(&asymmetric_key_parsers_sem);
     380                 :            : 
     381                 :            :         ret = -EBADMSG;
     382                 :          3 :         list_for_each_entry(parser, &asymmetric_key_parsers, link) {
     383                 :            :                 pr_debug("Trying parser '%s'\n", parser->name);
     384                 :            : 
     385                 :          3 :                 ret = parser->parse(prep);
     386                 :          3 :                 if (ret != -EBADMSG) {
     387                 :            :                         pr_debug("Parser recognised the format (ret %d)\n",
     388                 :            :                                  ret);
     389                 :            :                         break;
     390                 :            :                 }
     391                 :            :         }
     392                 :            : 
     393                 :          3 :         up_read(&asymmetric_key_parsers_sem);
     394                 :            :         pr_devel("<==%s() = %d\n", __func__, ret);
     395                 :          3 :         return ret;
     396                 :            : }
     397                 :            : 
     398                 :            : /*
     399                 :            :  * Clean up the key ID list
     400                 :            :  */
     401                 :          3 : static void asymmetric_key_free_kids(struct asymmetric_key_ids *kids)
     402                 :            : {
     403                 :            :         int i;
     404                 :            : 
     405                 :          3 :         if (kids) {
     406                 :          0 :                 for (i = 0; i < ARRAY_SIZE(kids->id); i++)
     407                 :          0 :                         kfree(kids->id[i]);
     408                 :          0 :                 kfree(kids);
     409                 :            :         }
     410                 :          3 : }
     411                 :            : 
     412                 :            : /*
     413                 :            :  * Clean up the preparse data
     414                 :            :  */
     415                 :          3 : static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
     416                 :            : {
     417                 :          3 :         struct asymmetric_key_subtype *subtype = prep->payload.data[asym_subtype];
     418                 :          3 :         struct asymmetric_key_ids *kids = prep->payload.data[asym_key_ids];
     419                 :            : 
     420                 :            :         pr_devel("==>%s()\n", __func__);
     421                 :            : 
     422                 :          3 :         if (subtype) {
     423                 :          0 :                 subtype->destroy(prep->payload.data[asym_crypto],
     424                 :            :                                  prep->payload.data[asym_auth]);
     425                 :          0 :                 module_put(subtype->owner);
     426                 :            :         }
     427                 :          3 :         asymmetric_key_free_kids(kids);
     428                 :          3 :         kfree(prep->description);
     429                 :          3 : }
     430                 :            : 
     431                 :            : /*
     432                 :            :  * dispose of the data dangling from the corpse of a asymmetric key
     433                 :            :  */
     434                 :          0 : static void asymmetric_key_destroy(struct key *key)
     435                 :            : {
     436                 :            :         struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
     437                 :          0 :         struct asymmetric_key_ids *kids = key->payload.data[asym_key_ids];
     438                 :          0 :         void *data = key->payload.data[asym_crypto];
     439                 :          0 :         void *auth = key->payload.data[asym_auth];
     440                 :            : 
     441                 :          0 :         key->payload.data[asym_crypto] = NULL;
     442                 :          0 :         key->payload.data[asym_subtype] = NULL;
     443                 :          0 :         key->payload.data[asym_key_ids] = NULL;
     444                 :          0 :         key->payload.data[asym_auth] = NULL;
     445                 :            : 
     446                 :          0 :         if (subtype) {
     447                 :          0 :                 subtype->destroy(data, auth);
     448                 :          0 :                 module_put(subtype->owner);
     449                 :            :         }
     450                 :            : 
     451                 :          0 :         asymmetric_key_free_kids(kids);
     452                 :          0 : }
     453                 :            : 
     454                 :            : static struct key_restriction *asymmetric_restriction_alloc(
     455                 :            :         key_restrict_link_func_t check,
     456                 :            :         struct key *key)
     457                 :            : {
     458                 :          0 :         struct key_restriction *keyres =
     459                 :            :                 kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
     460                 :            : 
     461                 :          0 :         if (!keyres)
     462                 :            :                 return ERR_PTR(-ENOMEM);
     463                 :            : 
     464                 :          0 :         keyres->check = check;
     465                 :          0 :         keyres->key = key;
     466                 :          0 :         keyres->keytype = &key_type_asymmetric;
     467                 :            : 
     468                 :            :         return keyres;
     469                 :            : }
     470                 :            : 
     471                 :            : /*
     472                 :            :  * look up keyring restrict functions for asymmetric keys
     473                 :            :  */
     474                 :          0 : static struct key_restriction *asymmetric_lookup_restriction(
     475                 :            :         const char *restriction)
     476                 :            : {
     477                 :            :         char *restrict_method;
     478                 :            :         char *parse_buf;
     479                 :            :         char *next;
     480                 :            :         struct key_restriction *ret = ERR_PTR(-EINVAL);
     481                 :            : 
     482                 :          0 :         if (strcmp("builtin_trusted", restriction) == 0)
     483                 :          0 :                 return asymmetric_restriction_alloc(
     484                 :            :                         restrict_link_by_builtin_trusted, NULL);
     485                 :            : 
     486                 :          0 :         if (strcmp("builtin_and_secondary_trusted", restriction) == 0)
     487                 :          0 :                 return asymmetric_restriction_alloc(
     488                 :            :                         restrict_link_by_builtin_and_secondary_trusted, NULL);
     489                 :            : 
     490                 :          0 :         parse_buf = kstrndup(restriction, PAGE_SIZE, GFP_KERNEL);
     491                 :          0 :         if (!parse_buf)
     492                 :            :                 return ERR_PTR(-ENOMEM);
     493                 :            : 
     494                 :          0 :         next = parse_buf;
     495                 :          0 :         restrict_method = strsep(&next, ":");
     496                 :            : 
     497                 :          0 :         if ((strcmp(restrict_method, "key_or_keyring") == 0) && next) {
     498                 :            :                 char *key_text;
     499                 :            :                 key_serial_t serial;
     500                 :            :                 struct key *key;
     501                 :            :                 key_restrict_link_func_t link_fn =
     502                 :            :                         restrict_link_by_key_or_keyring;
     503                 :            :                 bool allow_null_key = false;
     504                 :            : 
     505                 :          0 :                 key_text = strsep(&next, ":");
     506                 :            : 
     507                 :          0 :                 if (next) {
     508                 :          0 :                         if (strcmp(next, "chain") != 0)
     509                 :            :                                 goto out;
     510                 :            : 
     511                 :            :                         link_fn = restrict_link_by_key_or_keyring_chain;
     512                 :            :                         allow_null_key = true;
     513                 :            :                 }
     514                 :            : 
     515                 :          0 :                 if (kstrtos32(key_text, 0, &serial) < 0)
     516                 :            :                         goto out;
     517                 :            : 
     518                 :          0 :                 if ((serial == 0) && allow_null_key) {
     519                 :            :                         key = NULL;
     520                 :            :                 } else {
     521                 :          0 :                         key = key_lookup(serial);
     522                 :          0 :                         if (IS_ERR(key)) {
     523                 :            :                                 ret = ERR_CAST(key);
     524                 :            :                                 goto out;
     525                 :            :                         }
     526                 :            :                 }
     527                 :            : 
     528                 :            :                 ret = asymmetric_restriction_alloc(link_fn, key);
     529                 :          0 :                 if (IS_ERR(ret))
     530                 :          0 :                         key_put(key);
     531                 :            :         }
     532                 :            : 
     533                 :            : out:
     534                 :          0 :         kfree(parse_buf);
     535                 :          0 :         return ret;
     536                 :            : }
     537                 :            : 
     538                 :          0 : int asymmetric_key_eds_op(struct kernel_pkey_params *params,
     539                 :            :                           const void *in, void *out)
     540                 :            : {
     541                 :            :         const struct asymmetric_key_subtype *subtype;
     542                 :          0 :         struct key *key = params->key;
     543                 :            :         int ret;
     544                 :            : 
     545                 :            :         pr_devel("==>%s()\n", __func__);
     546                 :            : 
     547                 :          0 :         if (key->type != &key_type_asymmetric)
     548                 :            :                 return -EINVAL;
     549                 :            :         subtype = asymmetric_key_subtype(key);
     550                 :          0 :         if (!subtype ||
     551                 :          0 :             !key->payload.data[0])
     552                 :            :                 return -EINVAL;
     553                 :          0 :         if (!subtype->eds_op)
     554                 :            :                 return -ENOTSUPP;
     555                 :            : 
     556                 :          0 :         ret = subtype->eds_op(params, in, out);
     557                 :            : 
     558                 :            :         pr_devel("<==%s() = %d\n", __func__, ret);
     559                 :          0 :         return ret;
     560                 :            : }
     561                 :            : 
     562                 :          0 : static int asymmetric_key_verify_signature(struct kernel_pkey_params *params,
     563                 :            :                                            const void *in, const void *in2)
     564                 :            : {
     565                 :          0 :         struct public_key_signature sig = {
     566                 :          0 :                 .s_size         = params->in2_len,
     567                 :          0 :                 .digest_size    = params->in_len,
     568                 :          0 :                 .encoding       = params->encoding,
     569                 :          0 :                 .hash_algo      = params->hash_algo,
     570                 :            :                 .digest         = (void *)in,
     571                 :            :                 .s              = (void *)in2,
     572                 :            :         };
     573                 :            : 
     574                 :          0 :         return verify_signature(params->key, &sig);
     575                 :            : }
     576                 :            : 
     577                 :            : struct key_type key_type_asymmetric = {
     578                 :            :         .name                   = "asymmetric",
     579                 :            :         .preparse               = asymmetric_key_preparse,
     580                 :            :         .free_preparse          = asymmetric_key_free_preparse,
     581                 :            :         .instantiate            = generic_key_instantiate,
     582                 :            :         .match_preparse         = asymmetric_key_match_preparse,
     583                 :            :         .match_free             = asymmetric_key_match_free,
     584                 :            :         .destroy                = asymmetric_key_destroy,
     585                 :            :         .describe               = asymmetric_key_describe,
     586                 :            :         .lookup_restriction     = asymmetric_lookup_restriction,
     587                 :            :         .asym_query             = query_asymmetric_key,
     588                 :            :         .asym_eds_op            = asymmetric_key_eds_op,
     589                 :            :         .asym_verify_signature  = asymmetric_key_verify_signature,
     590                 :            : };
     591                 :            : EXPORT_SYMBOL_GPL(key_type_asymmetric);
     592                 :            : 
     593                 :            : /**
     594                 :            :  * register_asymmetric_key_parser - Register a asymmetric key blob parser
     595                 :            :  * @parser: The parser to register
     596                 :            :  */
     597                 :          3 : int register_asymmetric_key_parser(struct asymmetric_key_parser *parser)
     598                 :            : {
     599                 :            :         struct asymmetric_key_parser *cursor;
     600                 :            :         int ret;
     601                 :            : 
     602                 :          3 :         down_write(&asymmetric_key_parsers_sem);
     603                 :            : 
     604                 :          3 :         list_for_each_entry(cursor, &asymmetric_key_parsers, link) {
     605                 :          0 :                 if (strcmp(cursor->name, parser->name) == 0) {
     606                 :          0 :                         pr_err("Asymmetric key parser '%s' already registered\n",
     607                 :            :                                parser->name);
     608                 :            :                         ret = -EEXIST;
     609                 :          0 :                         goto out;
     610                 :            :                 }
     611                 :            :         }
     612                 :            : 
     613                 :          3 :         list_add_tail(&parser->link, &asymmetric_key_parsers);
     614                 :            : 
     615                 :          3 :         pr_notice("Asymmetric key parser '%s' registered\n", parser->name);
     616                 :            :         ret = 0;
     617                 :            : 
     618                 :            : out:
     619                 :          3 :         up_write(&asymmetric_key_parsers_sem);
     620                 :          3 :         return ret;
     621                 :            : }
     622                 :            : EXPORT_SYMBOL_GPL(register_asymmetric_key_parser);
     623                 :            : 
     624                 :            : /**
     625                 :            :  * unregister_asymmetric_key_parser - Unregister a asymmetric key blob parser
     626                 :            :  * @parser: The parser to unregister
     627                 :            :  */
     628                 :          0 : void unregister_asymmetric_key_parser(struct asymmetric_key_parser *parser)
     629                 :            : {
     630                 :          0 :         down_write(&asymmetric_key_parsers_sem);
     631                 :            :         list_del(&parser->link);
     632                 :          0 :         up_write(&asymmetric_key_parsers_sem);
     633                 :            : 
     634                 :          0 :         pr_notice("Asymmetric key parser '%s' unregistered\n", parser->name);
     635                 :          0 : }
     636                 :            : EXPORT_SYMBOL_GPL(unregister_asymmetric_key_parser);
     637                 :            : 
     638                 :            : /*
     639                 :            :  * Module stuff
     640                 :            :  */
     641                 :          3 : static int __init asymmetric_key_init(void)
     642                 :            : {
     643                 :          3 :         return register_key_type(&key_type_asymmetric);
     644                 :            : }
     645                 :            : 
     646                 :          0 : static void __exit asymmetric_key_cleanup(void)
     647                 :            : {
     648                 :          0 :         unregister_key_type(&key_type_asymmetric);
     649                 :          0 : }
     650                 :            : 
     651                 :            : module_init(asymmetric_key_init);
     652                 :            : module_exit(asymmetric_key_cleanup);
    

Generated by: LCOV version 1.14