dh.c (6858B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* Crypto operations using stored keys 3 * 4 * Copyright (c) 2016, Intel Corporation 5 */ 6 7#include <linux/slab.h> 8#include <linux/uaccess.h> 9#include <linux/scatterlist.h> 10#include <linux/crypto.h> 11#include <crypto/hash.h> 12#include <crypto/kpp.h> 13#include <crypto/dh.h> 14#include <crypto/kdf_sp800108.h> 15#include <keys/user-type.h> 16#include "internal.h" 17 18static ssize_t dh_data_from_key(key_serial_t keyid, const void **data) 19{ 20 struct key *key; 21 key_ref_t key_ref; 22 long status; 23 ssize_t ret; 24 25 key_ref = lookup_user_key(keyid, 0, KEY_NEED_READ); 26 if (IS_ERR(key_ref)) { 27 ret = -ENOKEY; 28 goto error; 29 } 30 31 key = key_ref_to_ptr(key_ref); 32 33 ret = -EOPNOTSUPP; 34 if (key->type == &key_type_user) { 35 down_read(&key->sem); 36 status = key_validate(key); 37 if (status == 0) { 38 const struct user_key_payload *payload; 39 uint8_t *duplicate; 40 41 payload = user_key_payload_locked(key); 42 43 duplicate = kmemdup(payload->data, payload->datalen, 44 GFP_KERNEL); 45 if (duplicate) { 46 *data = duplicate; 47 ret = payload->datalen; 48 } else { 49 ret = -ENOMEM; 50 } 51 } 52 up_read(&key->sem); 53 } 54 55 key_put(key); 56error: 57 return ret; 58} 59 60static void dh_free_data(struct dh *dh) 61{ 62 kfree_sensitive(dh->key); 63 kfree_sensitive(dh->p); 64 kfree_sensitive(dh->g); 65} 66 67struct dh_completion { 68 struct completion completion; 69 int err; 70}; 71 72static void dh_crypto_done(struct crypto_async_request *req, int err) 73{ 74 struct dh_completion *compl = req->data; 75 76 if (err == -EINPROGRESS) 77 return; 78 79 compl->err = err; 80 complete(&compl->completion); 81} 82 83static int kdf_alloc(struct crypto_shash **hash, char *hashname) 84{ 85 struct crypto_shash *tfm; 86 87 /* allocate synchronous hash */ 88 tfm = crypto_alloc_shash(hashname, 0, 0); 89 if (IS_ERR(tfm)) { 90 pr_info("could not allocate digest TFM handle %s\n", hashname); 91 return PTR_ERR(tfm); 92 } 93 94 if (crypto_shash_digestsize(tfm) == 0) { 95 crypto_free_shash(tfm); 96 return -EINVAL; 97 } 98 99 *hash = tfm; 100 101 return 0; 102} 103 104static void kdf_dealloc(struct crypto_shash *hash) 105{ 106 if (hash) 107 crypto_free_shash(hash); 108} 109 110static int keyctl_dh_compute_kdf(struct crypto_shash *hash, 111 char __user *buffer, size_t buflen, 112 uint8_t *kbuf, size_t kbuflen) 113{ 114 struct kvec kbuf_iov = { .iov_base = kbuf, .iov_len = kbuflen }; 115 uint8_t *outbuf = NULL; 116 int ret; 117 size_t outbuf_len = roundup(buflen, crypto_shash_digestsize(hash)); 118 119 outbuf = kmalloc(outbuf_len, GFP_KERNEL); 120 if (!outbuf) { 121 ret = -ENOMEM; 122 goto err; 123 } 124 125 ret = crypto_kdf108_ctr_generate(hash, &kbuf_iov, 1, outbuf, outbuf_len); 126 if (ret) 127 goto err; 128 129 ret = buflen; 130 if (copy_to_user(buffer, outbuf, buflen) != 0) 131 ret = -EFAULT; 132 133err: 134 kfree_sensitive(outbuf); 135 return ret; 136} 137 138long __keyctl_dh_compute(struct keyctl_dh_params __user *params, 139 char __user *buffer, size_t buflen, 140 struct keyctl_kdf_params *kdfcopy) 141{ 142 long ret; 143 ssize_t dlen; 144 int secretlen; 145 int outlen; 146 struct keyctl_dh_params pcopy; 147 struct dh dh_inputs; 148 struct scatterlist outsg; 149 struct dh_completion compl; 150 struct crypto_kpp *tfm; 151 struct kpp_request *req; 152 uint8_t *secret; 153 uint8_t *outbuf; 154 struct crypto_shash *hash = NULL; 155 156 if (!params || (!buffer && buflen)) { 157 ret = -EINVAL; 158 goto out1; 159 } 160 if (copy_from_user(&pcopy, params, sizeof(pcopy)) != 0) { 161 ret = -EFAULT; 162 goto out1; 163 } 164 165 if (kdfcopy) { 166 char *hashname; 167 168 if (memchr_inv(kdfcopy->__spare, 0, sizeof(kdfcopy->__spare))) { 169 ret = -EINVAL; 170 goto out1; 171 } 172 173 if (buflen > KEYCTL_KDF_MAX_OUTPUT_LEN || 174 kdfcopy->otherinfolen > KEYCTL_KDF_MAX_OI_LEN) { 175 ret = -EMSGSIZE; 176 goto out1; 177 } 178 179 /* get KDF name string */ 180 hashname = strndup_user(kdfcopy->hashname, CRYPTO_MAX_ALG_NAME); 181 if (IS_ERR(hashname)) { 182 ret = PTR_ERR(hashname); 183 goto out1; 184 } 185 186 /* allocate KDF from the kernel crypto API */ 187 ret = kdf_alloc(&hash, hashname); 188 kfree(hashname); 189 if (ret) 190 goto out1; 191 } 192 193 memset(&dh_inputs, 0, sizeof(dh_inputs)); 194 195 dlen = dh_data_from_key(pcopy.prime, &dh_inputs.p); 196 if (dlen < 0) { 197 ret = dlen; 198 goto out1; 199 } 200 dh_inputs.p_size = dlen; 201 202 dlen = dh_data_from_key(pcopy.base, &dh_inputs.g); 203 if (dlen < 0) { 204 ret = dlen; 205 goto out2; 206 } 207 dh_inputs.g_size = dlen; 208 209 dlen = dh_data_from_key(pcopy.private, &dh_inputs.key); 210 if (dlen < 0) { 211 ret = dlen; 212 goto out2; 213 } 214 dh_inputs.key_size = dlen; 215 216 secretlen = crypto_dh_key_len(&dh_inputs); 217 secret = kmalloc(secretlen, GFP_KERNEL); 218 if (!secret) { 219 ret = -ENOMEM; 220 goto out2; 221 } 222 ret = crypto_dh_encode_key(secret, secretlen, &dh_inputs); 223 if (ret) 224 goto out3; 225 226 tfm = crypto_alloc_kpp("dh", 0, 0); 227 if (IS_ERR(tfm)) { 228 ret = PTR_ERR(tfm); 229 goto out3; 230 } 231 232 ret = crypto_kpp_set_secret(tfm, secret, secretlen); 233 if (ret) 234 goto out4; 235 236 outlen = crypto_kpp_maxsize(tfm); 237 238 if (!kdfcopy) { 239 /* 240 * When not using a KDF, buflen 0 is used to read the 241 * required buffer length 242 */ 243 if (buflen == 0) { 244 ret = outlen; 245 goto out4; 246 } else if (outlen > buflen) { 247 ret = -EOVERFLOW; 248 goto out4; 249 } 250 } 251 252 outbuf = kzalloc(kdfcopy ? (outlen + kdfcopy->otherinfolen) : outlen, 253 GFP_KERNEL); 254 if (!outbuf) { 255 ret = -ENOMEM; 256 goto out4; 257 } 258 259 sg_init_one(&outsg, outbuf, outlen); 260 261 req = kpp_request_alloc(tfm, GFP_KERNEL); 262 if (!req) { 263 ret = -ENOMEM; 264 goto out5; 265 } 266 267 kpp_request_set_input(req, NULL, 0); 268 kpp_request_set_output(req, &outsg, outlen); 269 init_completion(&compl.completion); 270 kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | 271 CRYPTO_TFM_REQ_MAY_SLEEP, 272 dh_crypto_done, &compl); 273 274 /* 275 * For DH, generate_public_key and generate_shared_secret are 276 * the same calculation 277 */ 278 ret = crypto_kpp_generate_public_key(req); 279 if (ret == -EINPROGRESS) { 280 wait_for_completion(&compl.completion); 281 ret = compl.err; 282 if (ret) 283 goto out6; 284 } 285 286 if (kdfcopy) { 287 /* 288 * Concatenate SP800-56A otherinfo past DH shared secret -- the 289 * input to the KDF is (DH shared secret || otherinfo) 290 */ 291 if (copy_from_user(outbuf + req->dst_len, kdfcopy->otherinfo, 292 kdfcopy->otherinfolen) != 0) { 293 ret = -EFAULT; 294 goto out6; 295 } 296 297 ret = keyctl_dh_compute_kdf(hash, buffer, buflen, outbuf, 298 req->dst_len + kdfcopy->otherinfolen); 299 } else if (copy_to_user(buffer, outbuf, req->dst_len) == 0) { 300 ret = req->dst_len; 301 } else { 302 ret = -EFAULT; 303 } 304 305out6: 306 kpp_request_free(req); 307out5: 308 kfree_sensitive(outbuf); 309out4: 310 crypto_free_kpp(tfm); 311out3: 312 kfree_sensitive(secret); 313out2: 314 dh_free_data(&dh_inputs); 315out1: 316 kdf_dealloc(hash); 317 return ret; 318} 319 320long keyctl_dh_compute(struct keyctl_dh_params __user *params, 321 char __user *buffer, size_t buflen, 322 struct keyctl_kdf_params __user *kdf) 323{ 324 struct keyctl_kdf_params kdfcopy; 325 326 if (!kdf) 327 return __keyctl_dh_compute(params, buffer, buflen, NULL); 328 329 if (copy_from_user(&kdfcopy, kdf, sizeof(kdfcopy)) != 0) 330 return -EFAULT; 331 332 return __keyctl_dh_compute(params, buffer, buflen, &kdfcopy); 333}