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(¶ms, 0, sizeof(params)); 170 : : 171 : 0 : ret = keyctl_pkey_params_get(id, _info, ¶ms); 172 : 0 : if (ret < 0) 173 : : goto error; 174 : : 175 : 0 : ret = params.key->type->asym_query(¶ms, &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(¶ms); 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, ¶ms); 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(¶ms, 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(¶ms); 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 : : ¶ms); 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(¶ms, in, in2); 314 : : 315 : 0 : kfree(in2); 316 : : error_in: 317 : 0 : kfree(in); 318 : : error_params: 319 : : keyctl_pkey_params_free(¶ms); 320 : 0 : return ret; 321 : : }