LCOV - code coverage report
Current view: top level - crypto/asymmetric_keys - restrict.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 79 0.0 %
Date: 2022-04-01 13:59:58 Functions: 0 5 0.0 %
Branches: 0 74 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /* Instantiate a public key crypto key from an X.509 Certificate
       3                 :            :  *
       4                 :            :  * Copyright (C) 2012, 2016 Red Hat, Inc. All Rights Reserved.
       5                 :            :  * Written by David Howells (dhowells@redhat.com)
       6                 :            :  */
       7                 :            : 
       8                 :            : #define pr_fmt(fmt) "ASYM: "fmt
       9                 :            : #include <linux/module.h>
      10                 :            : #include <linux/kernel.h>
      11                 :            : #include <linux/err.h>
      12                 :            : #include <crypto/public_key.h>
      13                 :            : #include "asymmetric_keys.h"
      14                 :            : 
      15                 :            : static bool use_builtin_keys;
      16                 :            : static struct asymmetric_key_id *ca_keyid;
      17                 :            : 
      18                 :            : #ifndef MODULE
      19                 :            : static struct {
      20                 :            :         struct asymmetric_key_id id;
      21                 :            :         unsigned char data[10];
      22                 :            : } cakey;
      23                 :            : 
      24                 :          0 : static int __init ca_keys_setup(char *str)
      25                 :            : {
      26         [ #  # ]:          0 :         if (!str)               /* default system keyring */
      27                 :            :                 return 1;
      28                 :            : 
      29         [ #  # ]:          0 :         if (strncmp(str, "id:", 3) == 0) {
      30                 :          0 :                 struct asymmetric_key_id *p = &cakey.id;
      31                 :          0 :                 size_t hexlen = (strlen(str) - 3) / 2;
      32                 :          0 :                 int ret;
      33                 :            : 
      34         [ #  # ]:          0 :                 if (hexlen == 0 || hexlen > sizeof(cakey.data)) {
      35                 :          0 :                         pr_err("Missing or invalid ca_keys id\n");
      36                 :          0 :                         return 1;
      37                 :            :                 }
      38                 :            : 
      39                 :          0 :                 ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen);
      40         [ #  # ]:          0 :                 if (ret < 0)
      41                 :          0 :                         pr_err("Unparsable ca_keys id hex string\n");
      42                 :            :                 else
      43                 :          0 :                         ca_keyid = p;   /* owner key 'id:xxxxxx' */
      44         [ #  # ]:          0 :         } else if (strcmp(str, "builtin") == 0) {
      45                 :          0 :                 use_builtin_keys = true;
      46                 :            :         }
      47                 :            : 
      48                 :            :         return 1;
      49                 :            : }
      50                 :            : __setup("ca_keys=", ca_keys_setup);
      51                 :            : #endif
      52                 :            : 
      53                 :            : /**
      54                 :            :  * restrict_link_by_signature - Restrict additions to a ring of public keys
      55                 :            :  * @dest_keyring: Keyring being linked to.
      56                 :            :  * @type: The type of key being added.
      57                 :            :  * @payload: The payload of the new key.
      58                 :            :  * @trust_keyring: A ring of keys that can be used to vouch for the new cert.
      59                 :            :  *
      60                 :            :  * Check the new certificate against the ones in the trust keyring.  If one of
      61                 :            :  * those is the signing key and validates the new certificate, then mark the
      62                 :            :  * new certificate as being trusted.
      63                 :            :  *
      64                 :            :  * Returns 0 if the new certificate was accepted, -ENOKEY if we couldn't find a
      65                 :            :  * matching parent certificate in the trusted list, -EKEYREJECTED if the
      66                 :            :  * signature check fails or the key is blacklisted, -ENOPKG if the signature
      67                 :            :  * uses unsupported crypto, or some other error if there is a matching
      68                 :            :  * certificate but the signature check cannot be performed.
      69                 :            :  */
      70                 :          0 : int restrict_link_by_signature(struct key *dest_keyring,
      71                 :            :                                const struct key_type *type,
      72                 :            :                                const union key_payload *payload,
      73                 :            :                                struct key *trust_keyring)
      74                 :            : {
      75                 :          0 :         const struct public_key_signature *sig;
      76                 :          0 :         struct key *key;
      77                 :          0 :         int ret;
      78                 :            : 
      79                 :          0 :         pr_devel("==>%s()\n", __func__);
      80                 :            : 
      81         [ #  # ]:          0 :         if (!trust_keyring)
      82                 :            :                 return -ENOKEY;
      83                 :            : 
      84         [ #  # ]:          0 :         if (type != &key_type_asymmetric)
      85                 :            :                 return -EOPNOTSUPP;
      86                 :            : 
      87                 :          0 :         sig = payload->data[asym_auth];
      88         [ #  # ]:          0 :         if (!sig)
      89                 :            :                 return -ENOPKG;
      90   [ #  #  #  # ]:          0 :         if (!sig->auth_ids[0] && !sig->auth_ids[1])
      91                 :            :                 return -ENOKEY;
      92                 :            : 
      93   [ #  #  #  # ]:          0 :         if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid))
      94                 :            :                 return -EPERM;
      95                 :            : 
      96                 :            :         /* See if we have a key that signed this one. */
      97                 :          0 :         key = find_asymmetric_key(trust_keyring,
      98                 :          0 :                                   sig->auth_ids[0], sig->auth_ids[1],
      99                 :            :                                   false);
     100         [ #  # ]:          0 :         if (IS_ERR(key))
     101                 :            :                 return -ENOKEY;
     102                 :            : 
     103   [ #  #  #  # ]:          0 :         if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags))
     104                 :            :                 ret = -ENOKEY;
     105                 :            :         else
     106                 :          0 :                 ret = verify_signature(key, sig);
     107                 :          0 :         key_put(key);
     108                 :          0 :         return ret;
     109                 :            : }
     110                 :            : 
     111                 :            : static bool match_either_id(const struct asymmetric_key_ids *pair,
     112                 :            :                             const struct asymmetric_key_id *single)
     113                 :            : {
     114                 :            :         return (asymmetric_key_id_same(pair->id[0], single) ||
     115                 :            :                 asymmetric_key_id_same(pair->id[1], single));
     116                 :            : }
     117                 :            : 
     118                 :          0 : static int key_or_keyring_common(struct key *dest_keyring,
     119                 :            :                                  const struct key_type *type,
     120                 :            :                                  const union key_payload *payload,
     121                 :            :                                  struct key *trusted, bool check_dest)
     122                 :            : {
     123                 :          0 :         const struct public_key_signature *sig;
     124                 :          0 :         struct key *key = NULL;
     125                 :          0 :         int ret;
     126                 :            : 
     127                 :          0 :         pr_devel("==>%s()\n", __func__);
     128                 :            : 
     129         [ #  # ]:          0 :         if (!dest_keyring)
     130                 :            :                 return -ENOKEY;
     131         [ #  # ]:          0 :         else if (dest_keyring->type != &key_type_keyring)
     132                 :            :                 return -EOPNOTSUPP;
     133                 :            : 
     134         [ #  # ]:          0 :         if (!trusted && !check_dest)
     135                 :            :                 return -ENOKEY;
     136                 :            : 
     137         [ #  # ]:          0 :         if (type != &key_type_asymmetric)
     138                 :            :                 return -EOPNOTSUPP;
     139                 :            : 
     140                 :          0 :         sig = payload->data[asym_auth];
     141         [ #  # ]:          0 :         if (!sig)
     142                 :            :                 return -ENOPKG;
     143   [ #  #  #  # ]:          0 :         if (!sig->auth_ids[0] && !sig->auth_ids[1])
     144                 :            :                 return -ENOKEY;
     145                 :            : 
     146         [ #  # ]:          0 :         if (trusted) {
     147         [ #  # ]:          0 :                 if (trusted->type == &key_type_keyring) {
     148                 :            :                         /* See if we have a key that signed this one. */
     149                 :          0 :                         key = find_asymmetric_key(trusted, sig->auth_ids[0],
     150                 :          0 :                                                   sig->auth_ids[1], false);
     151         [ #  # ]:          0 :                         if (IS_ERR(key))
     152                 :          0 :                                 key = NULL;
     153         [ #  # ]:          0 :                 } else if (trusted->type == &key_type_asymmetric) {
     154                 :          0 :                         const struct asymmetric_key_ids *signer_ids;
     155                 :            : 
     156         [ #  # ]:          0 :                         signer_ids = asymmetric_key_ids(trusted);
     157                 :            : 
     158                 :            :                         /*
     159                 :            :                          * The auth_ids come from the candidate key (the
     160                 :            :                          * one that is being considered for addition to
     161                 :            :                          * dest_keyring) and identify the key that was
     162                 :            :                          * used to sign.
     163                 :            :                          *
     164                 :            :                          * The signer_ids are identifiers for the
     165                 :            :                          * signing key specified for dest_keyring.
     166                 :            :                          *
     167                 :            :                          * The first auth_id is the preferred id, and
     168                 :            :                          * the second is the fallback. If only one
     169                 :            :                          * auth_id is present, it may match against
     170                 :            :                          * either signer_id. If two auth_ids are
     171                 :            :                          * present, the first auth_id must match one
     172                 :            :                          * signer_id and the second auth_id must match
     173                 :            :                          * the second signer_id.
     174                 :            :                          */
     175   [ #  #  #  # ]:          0 :                         if (!sig->auth_ids[0] || !sig->auth_ids[1]) {
     176                 :          0 :                                 const struct asymmetric_key_id *auth_id;
     177                 :            : 
     178         [ #  # ]:          0 :                                 auth_id = sig->auth_ids[0] ?: sig->auth_ids[1];
     179         [ #  # ]:          0 :                                 if (match_either_id(signer_ids, auth_id))
     180                 :          0 :                                         key = __key_get(trusted);
     181                 :            : 
     182         [ #  # ]:          0 :                         } else if (asymmetric_key_id_same(signer_ids->id[1],
     183         [ #  # ]:          0 :                                                           sig->auth_ids[1]) &&
     184                 :          0 :                                    match_either_id(signer_ids,
     185                 :          0 :                                                    sig->auth_ids[0])) {
     186                 :          0 :                                 key = __key_get(trusted);
     187                 :            :                         }
     188                 :            :                 } else {
     189                 :            :                         return -EOPNOTSUPP;
     190                 :            :                 }
     191                 :            :         }
     192                 :            : 
     193         [ #  # ]:          0 :         if (check_dest && !key) {
     194                 :            :                 /* See if the destination has a key that signed this one. */
     195                 :          0 :                 key = find_asymmetric_key(dest_keyring, sig->auth_ids[0],
     196                 :          0 :                                           sig->auth_ids[1], false);
     197         [ #  # ]:          0 :                 if (IS_ERR(key))
     198                 :            :                         key = NULL;
     199                 :            :         }
     200                 :            : 
     201         [ #  # ]:          0 :         if (!key)
     202                 :          0 :                 return -ENOKEY;
     203                 :            : 
     204                 :          0 :         ret = key_validate(key);
     205         [ #  # ]:          0 :         if (ret == 0)
     206                 :          0 :                 ret = verify_signature(key, sig);
     207                 :            : 
     208                 :          0 :         key_put(key);
     209                 :          0 :         return ret;
     210                 :            : }
     211                 :            : 
     212                 :            : /**
     213                 :            :  * restrict_link_by_key_or_keyring - Restrict additions to a ring of public
     214                 :            :  * keys using the restrict_key information stored in the ring.
     215                 :            :  * @dest_keyring: Keyring being linked to.
     216                 :            :  * @type: The type of key being added.
     217                 :            :  * @payload: The payload of the new key.
     218                 :            :  * @trusted: A key or ring of keys that can be used to vouch for the new cert.
     219                 :            :  *
     220                 :            :  * Check the new certificate only against the key or keys passed in the data
     221                 :            :  * parameter. If one of those is the signing key and validates the new
     222                 :            :  * certificate, then mark the new certificate as being ok to link.
     223                 :            :  *
     224                 :            :  * Returns 0 if the new certificate was accepted, -ENOKEY if we
     225                 :            :  * couldn't find a matching parent certificate in the trusted list,
     226                 :            :  * -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses
     227                 :            :  * unsupported crypto, or some other error if there is a matching certificate
     228                 :            :  * but the signature check cannot be performed.
     229                 :            :  */
     230                 :          0 : int restrict_link_by_key_or_keyring(struct key *dest_keyring,
     231                 :            :                                     const struct key_type *type,
     232                 :            :                                     const union key_payload *payload,
     233                 :            :                                     struct key *trusted)
     234                 :            : {
     235                 :          0 :         return key_or_keyring_common(dest_keyring, type, payload, trusted,
     236                 :            :                                      false);
     237                 :            : }
     238                 :            : 
     239                 :            : /**
     240                 :            :  * restrict_link_by_key_or_keyring_chain - Restrict additions to a ring of
     241                 :            :  * public keys using the restrict_key information stored in the ring.
     242                 :            :  * @dest_keyring: Keyring being linked to.
     243                 :            :  * @type: The type of key being added.
     244                 :            :  * @payload: The payload of the new key.
     245                 :            :  * @trusted: A key or ring of keys that can be used to vouch for the new cert.
     246                 :            :  *
     247                 :            :  * Check the new certificate only against the key or keys passed in the data
     248                 :            :  * parameter. If one of those is the signing key and validates the new
     249                 :            :  * certificate, then mark the new certificate as being ok to link.
     250                 :            :  *
     251                 :            :  * Returns 0 if the new certificate was accepted, -ENOKEY if we
     252                 :            :  * couldn't find a matching parent certificate in the trusted list,
     253                 :            :  * -EKEYREJECTED if the signature check fails, -ENOPKG if the signature uses
     254                 :            :  * unsupported crypto, or some other error if there is a matching certificate
     255                 :            :  * but the signature check cannot be performed.
     256                 :            :  */
     257                 :          0 : int restrict_link_by_key_or_keyring_chain(struct key *dest_keyring,
     258                 :            :                                           const struct key_type *type,
     259                 :            :                                           const union key_payload *payload,
     260                 :            :                                           struct key *trusted)
     261                 :            : {
     262                 :          0 :         return key_or_keyring_common(dest_keyring, type, payload, trusted,
     263                 :            :                                      true);
     264                 :            : }

Generated by: LCOV version 1.14