Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* Public-key operation keyctls
0003  *
0004  * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
0005  * Written by David Howells (dhowells@redhat.com)
0006  */
0007 
0008 #include <linux/slab.h>
0009 #include <linux/err.h>
0010 #include <linux/key.h>
0011 #include <linux/keyctl.h>
0012 #include <linux/parser.h>
0013 #include <linux/uaccess.h>
0014 #include <keys/user-type.h>
0015 #include "internal.h"
0016 
0017 static void keyctl_pkey_params_free(struct kernel_pkey_params *params)
0018 {
0019     kfree(params->info);
0020     key_put(params->key);
0021 }
0022 
0023 enum {
0024     Opt_err,
0025     Opt_enc,        /* "enc=<encoding>" eg. "enc=oaep" */
0026     Opt_hash,       /* "hash=<digest-name>" eg. "hash=sha1" */
0027 };
0028 
0029 static const match_table_t param_keys = {
0030     { Opt_enc,  "enc=%s" },
0031     { Opt_hash, "hash=%s" },
0032     { Opt_err,  NULL }
0033 };
0034 
0035 /*
0036  * Parse the information string which consists of key=val pairs.
0037  */
0038 static int keyctl_pkey_params_parse(struct kernel_pkey_params *params)
0039 {
0040     unsigned long token_mask = 0;
0041     substring_t args[MAX_OPT_ARGS];
0042     char *c = params->info, *p, *q;
0043     int token;
0044 
0045     while ((p = strsep(&c, " \t"))) {
0046         if (*p == '\0' || *p == ' ' || *p == '\t')
0047             continue;
0048         token = match_token(p, param_keys, args);
0049         if (token == Opt_err)
0050             return -EINVAL;
0051         if (__test_and_set_bit(token, &token_mask))
0052             return -EINVAL;
0053         q = args[0].from;
0054         if (!q[0])
0055             return -EINVAL;
0056 
0057         switch (token) {
0058         case Opt_enc:
0059             params->encoding = q;
0060             break;
0061 
0062         case Opt_hash:
0063             params->hash_algo = q;
0064             break;
0065 
0066         default:
0067             return -EINVAL;
0068         }
0069     }
0070 
0071     return 0;
0072 }
0073 
0074 /*
0075  * Interpret parameters.  Callers must always call the free function
0076  * on params, even if an error is returned.
0077  */
0078 static int keyctl_pkey_params_get(key_serial_t id,
0079                   const char __user *_info,
0080                   struct kernel_pkey_params *params)
0081 {
0082     key_ref_t key_ref;
0083     void *p;
0084     int ret;
0085 
0086     memset(params, 0, sizeof(*params));
0087     params->encoding = "raw";
0088 
0089     p = strndup_user(_info, PAGE_SIZE);
0090     if (IS_ERR(p))
0091         return PTR_ERR(p);
0092     params->info = p;
0093 
0094     ret = keyctl_pkey_params_parse(params);
0095     if (ret < 0)
0096         return ret;
0097 
0098     key_ref = lookup_user_key(id, 0, KEY_NEED_SEARCH);
0099     if (IS_ERR(key_ref))
0100         return PTR_ERR(key_ref);
0101     params->key = key_ref_to_ptr(key_ref);
0102 
0103     if (!params->key->type->asym_query)
0104         return -EOPNOTSUPP;
0105 
0106     return 0;
0107 }
0108 
0109 /*
0110  * Get parameters from userspace.  Callers must always call the free function
0111  * on params, even if an error is returned.
0112  */
0113 static int keyctl_pkey_params_get_2(const struct keyctl_pkey_params __user *_params,
0114                     const char __user *_info,
0115                     int op,
0116                     struct kernel_pkey_params *params)
0117 {
0118     struct keyctl_pkey_params uparams;
0119     struct kernel_pkey_query info;
0120     int ret;
0121 
0122     memset(params, 0, sizeof(*params));
0123     params->encoding = "raw";
0124 
0125     if (copy_from_user(&uparams, _params, sizeof(uparams)) != 0)
0126         return -EFAULT;
0127 
0128     ret = keyctl_pkey_params_get(uparams.key_id, _info, params);
0129     if (ret < 0)
0130         return ret;
0131 
0132     ret = params->key->type->asym_query(params, &info);
0133     if (ret < 0)
0134         return ret;
0135 
0136     switch (op) {
0137     case KEYCTL_PKEY_ENCRYPT:
0138         if (uparams.in_len  > info.max_dec_size ||
0139             uparams.out_len > info.max_enc_size)
0140             return -EINVAL;
0141         break;
0142     case KEYCTL_PKEY_DECRYPT:
0143         if (uparams.in_len  > info.max_enc_size ||
0144             uparams.out_len > info.max_dec_size)
0145             return -EINVAL;
0146         break;
0147     case KEYCTL_PKEY_SIGN:
0148         if (uparams.in_len  > info.max_data_size ||
0149             uparams.out_len > info.max_sig_size)
0150             return -EINVAL;
0151         break;
0152     case KEYCTL_PKEY_VERIFY:
0153         if (uparams.in_len  > info.max_data_size ||
0154             uparams.in2_len > info.max_sig_size)
0155             return -EINVAL;
0156         break;
0157     default:
0158         BUG();
0159     }
0160 
0161     params->in_len  = uparams.in_len;
0162     params->out_len = uparams.out_len; /* Note: same as in2_len */
0163     return 0;
0164 }
0165 
0166 /*
0167  * Query information about an asymmetric key.
0168  */
0169 long keyctl_pkey_query(key_serial_t id,
0170                const char __user *_info,
0171                struct keyctl_pkey_query __user *_res)
0172 {
0173     struct kernel_pkey_params params;
0174     struct kernel_pkey_query res;
0175     long ret;
0176 
0177     ret = keyctl_pkey_params_get(id, _info, &params);
0178     if (ret < 0)
0179         goto error;
0180 
0181     ret = params.key->type->asym_query(&params, &res);
0182     if (ret < 0)
0183         goto error;
0184 
0185     ret = -EFAULT;
0186     if (copy_to_user(_res, &res, sizeof(res)) == 0 &&
0187         clear_user(_res->__spare, sizeof(_res->__spare)) == 0)
0188         ret = 0;
0189 
0190 error:
0191     keyctl_pkey_params_free(&params);
0192     return ret;
0193 }
0194 
0195 /*
0196  * Encrypt/decrypt/sign
0197  *
0198  * Encrypt data, decrypt data or sign data using a public key.
0199  *
0200  * _info is a string of supplementary information in key=val format.  For
0201  * instance, it might contain:
0202  *
0203  *  "enc=pkcs1 hash=sha256"
0204  *
0205  * where enc= specifies the encoding and hash= selects the OID to go in that
0206  * particular encoding if required.  If enc= isn't supplied, it's assumed that
0207  * the caller is supplying raw values.
0208  *
0209  * If successful, the amount of data written into the output buffer is
0210  * returned.
0211  */
0212 long keyctl_pkey_e_d_s(int op,
0213                const struct keyctl_pkey_params __user *_params,
0214                const char __user *_info,
0215                const void __user *_in,
0216                void __user *_out)
0217 {
0218     struct kernel_pkey_params params;
0219     void *in, *out;
0220     long ret;
0221 
0222     ret = keyctl_pkey_params_get_2(_params, _info, op, &params);
0223     if (ret < 0)
0224         goto error_params;
0225 
0226     ret = -EOPNOTSUPP;
0227     if (!params.key->type->asym_eds_op)
0228         goto error_params;
0229 
0230     switch (op) {
0231     case KEYCTL_PKEY_ENCRYPT:
0232         params.op = kernel_pkey_encrypt;
0233         break;
0234     case KEYCTL_PKEY_DECRYPT:
0235         params.op = kernel_pkey_decrypt;
0236         break;
0237     case KEYCTL_PKEY_SIGN:
0238         params.op = kernel_pkey_sign;
0239         break;
0240     default:
0241         BUG();
0242     }
0243 
0244     in = memdup_user(_in, params.in_len);
0245     if (IS_ERR(in)) {
0246         ret = PTR_ERR(in);
0247         goto error_params;
0248     }
0249 
0250     ret = -ENOMEM;
0251     out = kmalloc(params.out_len, GFP_KERNEL);
0252     if (!out)
0253         goto error_in;
0254 
0255     ret = params.key->type->asym_eds_op(&params, in, out);
0256     if (ret < 0)
0257         goto error_out;
0258 
0259     if (copy_to_user(_out, out, ret) != 0)
0260         ret = -EFAULT;
0261 
0262 error_out:
0263     kfree(out);
0264 error_in:
0265     kfree(in);
0266 error_params:
0267     keyctl_pkey_params_free(&params);
0268     return ret;
0269 }
0270 
0271 /*
0272  * Verify a signature.
0273  *
0274  * Verify a public key signature using the given key, or if not given, search
0275  * for a matching key.
0276  *
0277  * _info is a string of supplementary information in key=val format.  For
0278  * instance, it might contain:
0279  *
0280  *  "enc=pkcs1 hash=sha256"
0281  *
0282  * where enc= specifies the signature blob encoding and hash= selects the OID
0283  * to go in that particular encoding.  If enc= isn't supplied, it's assumed
0284  * that the caller is supplying raw values.
0285  *
0286  * If successful, 0 is returned.
0287  */
0288 long keyctl_pkey_verify(const struct keyctl_pkey_params __user *_params,
0289             const char __user *_info,
0290             const void __user *_in,
0291             const void __user *_in2)
0292 {
0293     struct kernel_pkey_params params;
0294     void *in, *in2;
0295     long ret;
0296 
0297     ret = keyctl_pkey_params_get_2(_params, _info, KEYCTL_PKEY_VERIFY,
0298                        &params);
0299     if (ret < 0)
0300         goto error_params;
0301 
0302     ret = -EOPNOTSUPP;
0303     if (!params.key->type->asym_verify_signature)
0304         goto error_params;
0305 
0306     in = memdup_user(_in, params.in_len);
0307     if (IS_ERR(in)) {
0308         ret = PTR_ERR(in);
0309         goto error_params;
0310     }
0311 
0312     in2 = memdup_user(_in2, params.in2_len);
0313     if (IS_ERR(in2)) {
0314         ret = PTR_ERR(in2);
0315         goto error_in;
0316     }
0317 
0318     params.op = kernel_pkey_verify;
0319     ret = params.key->type->asym_verify_signature(&params, in, in2);
0320 
0321     kfree(in2);
0322 error_in:
0323     kfree(in);
0324 error_params:
0325     keyctl_pkey_params_free(&params);
0326     return ret;
0327 }