LCOV - code coverage report
Current view: top level - security/keys - keyctl_pkey.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_qemu_modules_combined.info Lines: 0 97 0.0 %
Date: 2020-09-30 20:25:01 Functions: 0 6 0.0 %
Branches: 0 72 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /* Public-key operation keyctls
       3                 :            :  *
       4                 :            :  * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
       5                 :            :  * Written by David Howells (dhowells@redhat.com)
       6                 :            :  */
       7                 :            : 
       8                 :            : #include <linux/slab.h>
       9                 :            : #include <linux/err.h>
      10                 :            : #include <linux/key.h>
      11                 :            : #include <linux/keyctl.h>
      12                 :            : #include <linux/parser.h>
      13                 :            : #include <linux/uaccess.h>
      14                 :            : #include <keys/user-type.h>
      15                 :            : #include "internal.h"
      16                 :            : 
      17                 :            : static void keyctl_pkey_params_free(struct kernel_pkey_params *params)
      18                 :            : {
      19                 :          0 :         kfree(params->info);
      20                 :          0 :         key_put(params->key);
      21                 :            : }
      22                 :            : 
      23                 :            : enum {
      24                 :            :         Opt_err,
      25                 :            :         Opt_enc,                /* "enc=<encoding>" eg. "enc=oaep" */
      26                 :            :         Opt_hash,               /* "hash=<digest-name>" eg. "hash=sha1" */
      27                 :            : };
      28                 :            : 
      29                 :            : static const match_table_t param_keys = {
      30                 :            :         { Opt_enc,      "enc=%s" },
      31                 :            :         { Opt_hash,     "hash=%s" },
      32                 :            :         { Opt_err,      NULL }
      33                 :            : };
      34                 :            : 
      35                 :            : /*
      36                 :            :  * Parse the information string which consists of key=val pairs.
      37                 :            :  */
      38                 :          0 : static int keyctl_pkey_params_parse(struct kernel_pkey_params *params)
      39                 :            : {
      40                 :          0 :         unsigned long token_mask = 0;
      41                 :            :         substring_t args[MAX_OPT_ARGS];
      42                 :          0 :         char *c = params->info, *p, *q;
      43                 :            :         int token;
      44                 :            : 
      45         [ #  # ]:          0 :         while ((p = strsep(&c, " \t"))) {
      46   [ #  #  #  # ]:          0 :                 if (*p == '\0' || *p == ' ' || *p == '\t')
      47                 :          0 :                         continue;
      48                 :          0 :                 token = match_token(p, param_keys, args);
      49         [ #  # ]:          0 :                 if (token == Opt_err)
      50                 :            :                         return -EINVAL;
      51         [ #  # ]:          0 :                 if (__test_and_set_bit(token, &token_mask))
      52                 :            :                         return -EINVAL;
      53                 :          0 :                 q = args[0].from;
      54         [ #  # ]:          0 :                 if (!q[0])
      55                 :            :                         return -EINVAL;
      56                 :            : 
      57      [ #  #  # ]:          0 :                 switch (token) {
      58                 :            :                 case Opt_enc:
      59                 :          0 :                         params->encoding = q;
      60                 :          0 :                         break;
      61                 :            : 
      62                 :            :                 case Opt_hash:
      63                 :          0 :                         params->hash_algo = q;
      64                 :          0 :                         break;
      65                 :            : 
      66                 :            :                 default:
      67                 :            :                         return -EINVAL;
      68                 :            :                 }
      69                 :            :         }
      70                 :            : 
      71                 :            :         return 0;
      72                 :            : }
      73                 :            : 
      74                 :            : /*
      75                 :            :  * Interpret parameters.  Callers must always call the free function
      76                 :            :  * on params, even if an error is returned.
      77                 :            :  */
      78                 :          0 : static int keyctl_pkey_params_get(key_serial_t id,
      79                 :            :                                   const char __user *_info,
      80                 :            :                                   struct kernel_pkey_params *params)
      81                 :            : {
      82                 :            :         key_ref_t key_ref;
      83                 :            :         void *p;
      84                 :            :         int ret;
      85                 :            : 
      86                 :          0 :         memset(params, 0, sizeof(*params));
      87                 :          0 :         params->encoding = "raw";
      88                 :            : 
      89                 :          0 :         p = strndup_user(_info, PAGE_SIZE);
      90         [ #  # ]:          0 :         if (IS_ERR(p))
      91                 :          0 :                 return PTR_ERR(p);
      92                 :          0 :         params->info = p;
      93                 :            : 
      94                 :          0 :         ret = keyctl_pkey_params_parse(params);
      95         [ #  # ]:          0 :         if (ret < 0)
      96                 :            :                 return ret;
      97                 :            : 
      98                 :          0 :         key_ref = lookup_user_key(id, 0, KEY_NEED_SEARCH);
      99         [ #  # ]:          0 :         if (IS_ERR(key_ref))
     100                 :          0 :                 return PTR_ERR(key_ref);
     101                 :          0 :         params->key = key_ref_to_ptr(key_ref);
     102                 :            : 
     103         [ #  # ]:          0 :         if (!params->key->type->asym_query)
     104                 :            :                 return -EOPNOTSUPP;
     105                 :            : 
     106                 :          0 :         return 0;
     107                 :            : }
     108                 :            : 
     109                 :            : /*
     110                 :            :  * Get parameters from userspace.  Callers must always call the free function
     111                 :            :  * on params, even if an error is returned.
     112                 :            :  */
     113                 :          0 : static int keyctl_pkey_params_get_2(const struct keyctl_pkey_params __user *_params,
     114                 :            :                                     const char __user *_info,
     115                 :            :                                     int op,
     116                 :            :                                     struct kernel_pkey_params *params)
     117                 :            : {
     118                 :            :         struct keyctl_pkey_params uparams;
     119                 :            :         struct kernel_pkey_query info;
     120                 :            :         int ret;
     121                 :            : 
     122                 :          0 :         memset(params, 0, sizeof(*params));
     123                 :          0 :         params->encoding = "raw";
     124                 :            : 
     125         [ #  # ]:          0 :         if (copy_from_user(&uparams, _params, sizeof(uparams)) != 0)
     126                 :            :                 return -EFAULT;
     127                 :            : 
     128                 :          0 :         ret = keyctl_pkey_params_get(uparams.key_id, _info, params);
     129         [ #  # ]:          0 :         if (ret < 0)
     130                 :            :                 return ret;
     131                 :            : 
     132                 :          0 :         ret = params->key->type->asym_query(params, &info);
     133         [ #  # ]:          0 :         if (ret < 0)
     134                 :            :                 return ret;
     135                 :            : 
     136      [ #  #  # ]:          0 :         switch (op) {
     137                 :            :         case KEYCTL_PKEY_ENCRYPT:
     138                 :            :         case KEYCTL_PKEY_DECRYPT:
     139   [ #  #  #  # ]:          0 :                 if (uparams.in_len  > info.max_enc_size ||
     140                 :          0 :                     uparams.out_len > info.max_dec_size)
     141                 :            :                         return -EINVAL;
     142                 :            :                 break;
     143                 :            :         case KEYCTL_PKEY_SIGN:
     144                 :            :         case KEYCTL_PKEY_VERIFY:
     145   [ #  #  #  # ]:          0 :                 if (uparams.in_len  > info.max_sig_size ||
     146                 :          0 :                     uparams.out_len > info.max_data_size)
     147                 :            :                         return -EINVAL;
     148                 :            :                 break;
     149                 :            :         default:
     150                 :          0 :                 BUG();
     151                 :            :         }
     152                 :            : 
     153                 :          0 :         params->in_len  = uparams.in_len;
     154                 :          0 :         params->out_len = uparams.out_len;
     155                 :          0 :         return 0;
     156                 :            : }
     157                 :            : 
     158                 :            : /*
     159                 :            :  * Query information about an asymmetric key.
     160                 :            :  */
     161                 :          0 : long keyctl_pkey_query(key_serial_t id,
     162                 :            :                        const char __user *_info,
     163                 :            :                        struct keyctl_pkey_query __user *_res)
     164                 :            : {
     165                 :            :         struct kernel_pkey_params params;
     166                 :            :         struct kernel_pkey_query res;
     167                 :            :         long ret;
     168                 :            : 
     169                 :          0 :         memset(&params, 0, sizeof(params));
     170                 :            : 
     171                 :          0 :         ret = keyctl_pkey_params_get(id, _info, &params);
     172         [ #  # ]:          0 :         if (ret < 0)
     173                 :            :                 goto error;
     174                 :            : 
     175                 :          0 :         ret = params.key->type->asym_query(&params, &res);
     176         [ #  # ]:          0 :         if (ret < 0)
     177                 :            :                 goto error;
     178                 :            : 
     179                 :            :         ret = -EFAULT;
     180   [ #  #  #  # ]:          0 :         if (copy_to_user(_res, &res, sizeof(res)) == 0 &&
     181                 :          0 :             clear_user(_res->__spare, sizeof(_res->__spare)) == 0)
     182                 :            :                 ret = 0;
     183                 :            : 
     184                 :            : error:
     185                 :            :         keyctl_pkey_params_free(&params);
     186                 :          0 :         return ret;
     187                 :            : }
     188                 :            : 
     189                 :            : /*
     190                 :            :  * Encrypt/decrypt/sign
     191                 :            :  *
     192                 :            :  * Encrypt data, decrypt data or sign data using a public key.
     193                 :            :  *
     194                 :            :  * _info is a string of supplementary information in key=val format.  For
     195                 :            :  * instance, it might contain:
     196                 :            :  *
     197                 :            :  *      "enc=pkcs1 hash=sha256"
     198                 :            :  *
     199                 :            :  * where enc= specifies the encoding and hash= selects the OID to go in that
     200                 :            :  * particular encoding if required.  If enc= isn't supplied, it's assumed that
     201                 :            :  * the caller is supplying raw values.
     202                 :            :  *
     203                 :            :  * If successful, the amount of data written into the output buffer is
     204                 :            :  * returned.
     205                 :            :  */
     206                 :          0 : long keyctl_pkey_e_d_s(int op,
     207                 :            :                        const struct keyctl_pkey_params __user *_params,
     208                 :            :                        const char __user *_info,
     209                 :            :                        const void __user *_in,
     210                 :            :                        void __user *_out)
     211                 :            : {
     212                 :            :         struct kernel_pkey_params params;
     213                 :            :         void *in, *out;
     214                 :            :         long ret;
     215                 :            : 
     216                 :          0 :         ret = keyctl_pkey_params_get_2(_params, _info, op, &params);
     217         [ #  # ]:          0 :         if (ret < 0)
     218                 :            :                 goto error_params;
     219                 :            : 
     220                 :            :         ret = -EOPNOTSUPP;
     221         [ #  # ]:          0 :         if (!params.key->type->asym_eds_op)
     222                 :            :                 goto error_params;
     223                 :            : 
     224   [ #  #  #  # ]:          0 :         switch (op) {
     225                 :            :         case KEYCTL_PKEY_ENCRYPT:
     226                 :          0 :                 params.op = kernel_pkey_encrypt;
     227                 :          0 :                 break;
     228                 :            :         case KEYCTL_PKEY_DECRYPT:
     229                 :          0 :                 params.op = kernel_pkey_decrypt;
     230                 :          0 :                 break;
     231                 :            :         case KEYCTL_PKEY_SIGN:
     232                 :          0 :                 params.op = kernel_pkey_sign;
     233                 :          0 :                 break;
     234                 :            :         default:
     235                 :          0 :                 BUG();
     236                 :            :         }
     237                 :            : 
     238                 :          0 :         in = memdup_user(_in, params.in_len);
     239         [ #  # ]:          0 :         if (IS_ERR(in)) {
     240                 :            :                 ret = PTR_ERR(in);
     241                 :          0 :                 goto error_params;
     242                 :            :         }
     243                 :            : 
     244                 :            :         ret = -ENOMEM;
     245                 :          0 :         out = kmalloc(params.out_len, GFP_KERNEL);
     246         [ #  # ]:          0 :         if (!out)
     247                 :            :                 goto error_in;
     248                 :            : 
     249                 :          0 :         ret = params.key->type->asym_eds_op(&params, in, out);
     250         [ #  # ]:          0 :         if (ret < 0)
     251                 :            :                 goto error_out;
     252                 :            : 
     253         [ #  # ]:          0 :         if (copy_to_user(_out, out, ret) != 0)
     254                 :            :                 ret = -EFAULT;
     255                 :            : 
     256                 :            : error_out:
     257                 :          0 :         kfree(out);
     258                 :            : error_in:
     259                 :          0 :         kfree(in);
     260                 :            : error_params:
     261                 :            :         keyctl_pkey_params_free(&params);
     262                 :          0 :         return ret;
     263                 :            : }
     264                 :            : 
     265                 :            : /*
     266                 :            :  * Verify a signature.
     267                 :            :  *
     268                 :            :  * Verify a public key signature using the given key, or if not given, search
     269                 :            :  * for a matching key.
     270                 :            :  *
     271                 :            :  * _info is a string of supplementary information in key=val format.  For
     272                 :            :  * instance, it might contain:
     273                 :            :  *
     274                 :            :  *      "enc=pkcs1 hash=sha256"
     275                 :            :  *
     276                 :            :  * where enc= specifies the signature blob encoding and hash= selects the OID
     277                 :            :  * to go in that particular encoding.  If enc= isn't supplied, it's assumed
     278                 :            :  * that the caller is supplying raw values.
     279                 :            :  *
     280                 :            :  * If successful, 0 is returned.
     281                 :            :  */
     282                 :          0 : long keyctl_pkey_verify(const struct keyctl_pkey_params __user *_params,
     283                 :            :                         const char __user *_info,
     284                 :            :                         const void __user *_in,
     285                 :            :                         const void __user *_in2)
     286                 :            : {
     287                 :            :         struct kernel_pkey_params params;
     288                 :            :         void *in, *in2;
     289                 :            :         long ret;
     290                 :            : 
     291                 :          0 :         ret = keyctl_pkey_params_get_2(_params, _info, KEYCTL_PKEY_VERIFY,
     292                 :            :                                        &params);
     293         [ #  # ]:          0 :         if (ret < 0)
     294                 :            :                 goto error_params;
     295                 :            : 
     296                 :            :         ret = -EOPNOTSUPP;
     297         [ #  # ]:          0 :         if (!params.key->type->asym_verify_signature)
     298                 :            :                 goto error_params;
     299                 :            : 
     300                 :          0 :         in = memdup_user(_in, params.in_len);
     301         [ #  # ]:          0 :         if (IS_ERR(in)) {
     302                 :            :                 ret = PTR_ERR(in);
     303                 :          0 :                 goto error_params;
     304                 :            :         }
     305                 :            : 
     306                 :          0 :         in2 = memdup_user(_in2, params.in2_len);
     307         [ #  # ]:          0 :         if (IS_ERR(in2)) {
     308                 :            :                 ret = PTR_ERR(in2);
     309                 :          0 :                 goto error_in;
     310                 :            :         }
     311                 :            : 
     312                 :          0 :         params.op = kernel_pkey_verify;
     313                 :          0 :         ret = params.key->type->asym_verify_signature(&params, in, in2);
     314                 :            : 
     315                 :          0 :         kfree(in2);
     316                 :            : error_in:
     317                 :          0 :         kfree(in);
     318                 :            : error_params:
     319                 :            :         keyctl_pkey_params_free(&params);
     320                 :          0 :         return ret;
     321                 :            : }

Generated by: LCOV version 1.14