0001
0002
0003
0004
0005
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,
0026 Opt_hash,
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
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
0076
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
0111
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;
0163 return 0;
0164 }
0165
0166
0167
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, ¶ms);
0178 if (ret < 0)
0179 goto error;
0180
0181 ret = params.key->type->asym_query(¶ms, &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(¶ms);
0192 return ret;
0193 }
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
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, ¶ms);
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(¶ms, 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(¶ms);
0268 return ret;
0269 }
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
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 ¶ms);
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(¶ms, in, in2);
0320
0321 kfree(in2);
0322 error_in:
0323 kfree(in);
0324 error_params:
0325 keyctl_pkey_params_free(¶ms);
0326 return ret;
0327 }