1ddbb4114SMat Martineau /* Crypto operations using stored keys 2ddbb4114SMat Martineau * 3ddbb4114SMat Martineau * Copyright (c) 2016, Intel Corporation 4ddbb4114SMat Martineau * 5ddbb4114SMat Martineau * This program is free software; you can redistribute it and/or 6ddbb4114SMat Martineau * modify it under the terms of the GNU General Public License 7ddbb4114SMat Martineau * as published by the Free Software Foundation; either version 8ddbb4114SMat Martineau * 2 of the License, or (at your option) any later version. 9ddbb4114SMat Martineau */ 10ddbb4114SMat Martineau 11ddbb4114SMat Martineau #include <linux/slab.h> 12ddbb4114SMat Martineau #include <linux/uaccess.h> 13*7cbe0932SMat Martineau #include <linux/scatterlist.h> 14f1c316a3SStephan Mueller #include <linux/crypto.h> 15f1c316a3SStephan Mueller #include <crypto/hash.h> 16*7cbe0932SMat Martineau #include <crypto/kpp.h> 17*7cbe0932SMat Martineau #include <crypto/dh.h> 18ddbb4114SMat Martineau #include <keys/user-type.h> 19ddbb4114SMat Martineau #include "internal.h" 20ddbb4114SMat Martineau 21*7cbe0932SMat Martineau static ssize_t dh_data_from_key(key_serial_t keyid, void **data) 22ddbb4114SMat Martineau { 23ddbb4114SMat Martineau struct key *key; 24ddbb4114SMat Martineau key_ref_t key_ref; 25ddbb4114SMat Martineau long status; 26ddbb4114SMat Martineau ssize_t ret; 27ddbb4114SMat Martineau 28ddbb4114SMat Martineau key_ref = lookup_user_key(keyid, 0, KEY_NEED_READ); 29ddbb4114SMat Martineau if (IS_ERR(key_ref)) { 30ddbb4114SMat Martineau ret = -ENOKEY; 31ddbb4114SMat Martineau goto error; 32ddbb4114SMat Martineau } 33ddbb4114SMat Martineau 34ddbb4114SMat Martineau key = key_ref_to_ptr(key_ref); 35ddbb4114SMat Martineau 36ddbb4114SMat Martineau ret = -EOPNOTSUPP; 37ddbb4114SMat Martineau if (key->type == &key_type_user) { 38ddbb4114SMat Martineau down_read(&key->sem); 39ddbb4114SMat Martineau status = key_validate(key); 40ddbb4114SMat Martineau if (status == 0) { 41ddbb4114SMat Martineau const struct user_key_payload *payload; 42*7cbe0932SMat Martineau uint8_t *duplicate; 43ddbb4114SMat Martineau 440837e49aSDavid Howells payload = user_key_payload_locked(key); 45ddbb4114SMat Martineau 46*7cbe0932SMat Martineau duplicate = kmemdup(payload->data, payload->datalen, 47*7cbe0932SMat Martineau GFP_KERNEL); 48*7cbe0932SMat Martineau if (duplicate) { 49*7cbe0932SMat Martineau *data = duplicate; 50ddbb4114SMat Martineau ret = payload->datalen; 51ddbb4114SMat Martineau } else { 52*7cbe0932SMat Martineau ret = -ENOMEM; 53ddbb4114SMat Martineau } 54ddbb4114SMat Martineau } 55ddbb4114SMat Martineau up_read(&key->sem); 56ddbb4114SMat Martineau } 57ddbb4114SMat Martineau 58ddbb4114SMat Martineau key_put(key); 59ddbb4114SMat Martineau error: 60ddbb4114SMat Martineau return ret; 61ddbb4114SMat Martineau } 62ddbb4114SMat Martineau 63*7cbe0932SMat Martineau static void dh_free_data(struct dh *dh) 64*7cbe0932SMat Martineau { 65*7cbe0932SMat Martineau kzfree(dh->key); 66*7cbe0932SMat Martineau kzfree(dh->p); 67*7cbe0932SMat Martineau kzfree(dh->g); 68*7cbe0932SMat Martineau } 69*7cbe0932SMat Martineau 70*7cbe0932SMat Martineau struct dh_completion { 71*7cbe0932SMat Martineau struct completion completion; 72*7cbe0932SMat Martineau int err; 73*7cbe0932SMat Martineau }; 74*7cbe0932SMat Martineau 75*7cbe0932SMat Martineau static void dh_crypto_done(struct crypto_async_request *req, int err) 76*7cbe0932SMat Martineau { 77*7cbe0932SMat Martineau struct dh_completion *compl = req->data; 78*7cbe0932SMat Martineau 79*7cbe0932SMat Martineau if (err == -EINPROGRESS) 80*7cbe0932SMat Martineau return; 81*7cbe0932SMat Martineau 82*7cbe0932SMat Martineau compl->err = err; 83*7cbe0932SMat Martineau complete(&compl->completion); 84*7cbe0932SMat Martineau } 85*7cbe0932SMat Martineau 86f1c316a3SStephan Mueller struct kdf_sdesc { 87f1c316a3SStephan Mueller struct shash_desc shash; 88f1c316a3SStephan Mueller char ctx[]; 89f1c316a3SStephan Mueller }; 90f1c316a3SStephan Mueller 91f1c316a3SStephan Mueller static int kdf_alloc(struct kdf_sdesc **sdesc_ret, char *hashname) 92f1c316a3SStephan Mueller { 93f1c316a3SStephan Mueller struct crypto_shash *tfm; 94f1c316a3SStephan Mueller struct kdf_sdesc *sdesc; 95f1c316a3SStephan Mueller int size; 96bbe24045SEric Biggers int err; 97f1c316a3SStephan Mueller 98f1c316a3SStephan Mueller /* allocate synchronous hash */ 99f1c316a3SStephan Mueller tfm = crypto_alloc_shash(hashname, 0, 0); 100f1c316a3SStephan Mueller if (IS_ERR(tfm)) { 101f1c316a3SStephan Mueller pr_info("could not allocate digest TFM handle %s\n", hashname); 102f1c316a3SStephan Mueller return PTR_ERR(tfm); 103f1c316a3SStephan Mueller } 104f1c316a3SStephan Mueller 105bbe24045SEric Biggers err = -EINVAL; 106bbe24045SEric Biggers if (crypto_shash_digestsize(tfm) == 0) 107bbe24045SEric Biggers goto out_free_tfm; 108bbe24045SEric Biggers 109bbe24045SEric Biggers err = -ENOMEM; 110f1c316a3SStephan Mueller size = sizeof(struct shash_desc) + crypto_shash_descsize(tfm); 111f1c316a3SStephan Mueller sdesc = kmalloc(size, GFP_KERNEL); 112f1c316a3SStephan Mueller if (!sdesc) 113bbe24045SEric Biggers goto out_free_tfm; 114f1c316a3SStephan Mueller sdesc->shash.tfm = tfm; 115f1c316a3SStephan Mueller sdesc->shash.flags = 0x0; 116f1c316a3SStephan Mueller 117f1c316a3SStephan Mueller *sdesc_ret = sdesc; 118f1c316a3SStephan Mueller 119f1c316a3SStephan Mueller return 0; 120bbe24045SEric Biggers 121bbe24045SEric Biggers out_free_tfm: 122bbe24045SEric Biggers crypto_free_shash(tfm); 123bbe24045SEric Biggers return err; 124f1c316a3SStephan Mueller } 125f1c316a3SStephan Mueller 126f1c316a3SStephan Mueller static void kdf_dealloc(struct kdf_sdesc *sdesc) 127f1c316a3SStephan Mueller { 128f1c316a3SStephan Mueller if (!sdesc) 129f1c316a3SStephan Mueller return; 130f1c316a3SStephan Mueller 131f1c316a3SStephan Mueller if (sdesc->shash.tfm) 132f1c316a3SStephan Mueller crypto_free_shash(sdesc->shash.tfm); 133f1c316a3SStephan Mueller 134f1c316a3SStephan Mueller kzfree(sdesc); 135f1c316a3SStephan Mueller } 136f1c316a3SStephan Mueller 137f1c316a3SStephan Mueller /* 138f1c316a3SStephan Mueller * Implementation of the KDF in counter mode according to SP800-108 section 5.1 139f1c316a3SStephan Mueller * as well as SP800-56A section 5.8.1 (Single-step KDF). 140f1c316a3SStephan Mueller * 141f1c316a3SStephan Mueller * SP800-56A: 142f1c316a3SStephan Mueller * The src pointer is defined as Z || other info where Z is the shared secret 143f1c316a3SStephan Mueller * from DH and other info is an arbitrary string (see SP800-56A section 144f1c316a3SStephan Mueller * 5.8.1.2). 145f1c316a3SStephan Mueller */ 146f1c316a3SStephan Mueller static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen, 147*7cbe0932SMat Martineau u8 *dst, unsigned int dlen, unsigned int zlen) 148f1c316a3SStephan Mueller { 149f1c316a3SStephan Mueller struct shash_desc *desc = &sdesc->shash; 150f1c316a3SStephan Mueller unsigned int h = crypto_shash_digestsize(desc->tfm); 151f1c316a3SStephan Mueller int err = 0; 152f1c316a3SStephan Mueller u8 *dst_orig = dst; 1530ddd9f1aSEric Biggers __be32 counter = cpu_to_be32(1); 154f1c316a3SStephan Mueller 155f1c316a3SStephan Mueller while (dlen) { 156f1c316a3SStephan Mueller err = crypto_shash_init(desc); 157f1c316a3SStephan Mueller if (err) 158f1c316a3SStephan Mueller goto err; 159f1c316a3SStephan Mueller 1600ddd9f1aSEric Biggers err = crypto_shash_update(desc, (u8 *)&counter, sizeof(__be32)); 161f1c316a3SStephan Mueller if (err) 162f1c316a3SStephan Mueller goto err; 163f1c316a3SStephan Mueller 164*7cbe0932SMat Martineau if (zlen && h) { 165*7cbe0932SMat Martineau u8 tmpbuffer[h]; 166*7cbe0932SMat Martineau size_t chunk = min_t(size_t, zlen, h); 167*7cbe0932SMat Martineau memset(tmpbuffer, 0, chunk); 168*7cbe0932SMat Martineau 169*7cbe0932SMat Martineau do { 170*7cbe0932SMat Martineau err = crypto_shash_update(desc, tmpbuffer, 171*7cbe0932SMat Martineau chunk); 172*7cbe0932SMat Martineau if (err) 173*7cbe0932SMat Martineau goto err; 174*7cbe0932SMat Martineau 175*7cbe0932SMat Martineau zlen -= chunk; 176*7cbe0932SMat Martineau chunk = min_t(size_t, zlen, h); 177*7cbe0932SMat Martineau } while (zlen); 178*7cbe0932SMat Martineau } 179*7cbe0932SMat Martineau 180f1c316a3SStephan Mueller if (src && slen) { 181f1c316a3SStephan Mueller err = crypto_shash_update(desc, src, slen); 182f1c316a3SStephan Mueller if (err) 183f1c316a3SStephan Mueller goto err; 184f1c316a3SStephan Mueller } 185f1c316a3SStephan Mueller 186f1c316a3SStephan Mueller if (dlen < h) { 187f1c316a3SStephan Mueller u8 tmpbuffer[h]; 188f1c316a3SStephan Mueller 189f1c316a3SStephan Mueller err = crypto_shash_final(desc, tmpbuffer); 190f1c316a3SStephan Mueller if (err) 191f1c316a3SStephan Mueller goto err; 192f1c316a3SStephan Mueller memcpy(dst, tmpbuffer, dlen); 193f1c316a3SStephan Mueller memzero_explicit(tmpbuffer, h); 194f1c316a3SStephan Mueller return 0; 195f1c316a3SStephan Mueller } else { 196f1c316a3SStephan Mueller err = crypto_shash_final(desc, dst); 197f1c316a3SStephan Mueller if (err) 198f1c316a3SStephan Mueller goto err; 199f1c316a3SStephan Mueller 200f1c316a3SStephan Mueller dlen -= h; 201f1c316a3SStephan Mueller dst += h; 2020ddd9f1aSEric Biggers counter = cpu_to_be32(be32_to_cpu(counter) + 1); 203f1c316a3SStephan Mueller } 204f1c316a3SStephan Mueller } 205f1c316a3SStephan Mueller 206f1c316a3SStephan Mueller return 0; 207f1c316a3SStephan Mueller 208f1c316a3SStephan Mueller err: 209f1c316a3SStephan Mueller memzero_explicit(dst_orig, dlen); 210f1c316a3SStephan Mueller return err; 211f1c316a3SStephan Mueller } 212f1c316a3SStephan Mueller 213f1c316a3SStephan Mueller static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc, 2144693fc73SStephan Mueller char __user *buffer, size_t buflen, 215*7cbe0932SMat Martineau uint8_t *kbuf, size_t kbuflen, size_t lzero) 216f1c316a3SStephan Mueller { 217f1c316a3SStephan Mueller uint8_t *outbuf = NULL; 218f1c316a3SStephan Mueller int ret; 219f1c316a3SStephan Mueller 220f1c316a3SStephan Mueller outbuf = kmalloc(buflen, GFP_KERNEL); 221f1c316a3SStephan Mueller if (!outbuf) { 222f1c316a3SStephan Mueller ret = -ENOMEM; 223f1c316a3SStephan Mueller goto err; 224f1c316a3SStephan Mueller } 225f1c316a3SStephan Mueller 226*7cbe0932SMat Martineau ret = kdf_ctr(sdesc, kbuf, kbuflen, outbuf, buflen, lzero); 227f1c316a3SStephan Mueller if (ret) 228f1c316a3SStephan Mueller goto err; 229f1c316a3SStephan Mueller 230f1c316a3SStephan Mueller ret = buflen; 231f1c316a3SStephan Mueller if (copy_to_user(buffer, outbuf, buflen) != 0) 232f1c316a3SStephan Mueller ret = -EFAULT; 233f1c316a3SStephan Mueller 234f1c316a3SStephan Mueller err: 235f1c316a3SStephan Mueller kzfree(outbuf); 236f1c316a3SStephan Mueller return ret; 237f1c316a3SStephan Mueller } 238f1c316a3SStephan Mueller 239f1c316a3SStephan Mueller long __keyctl_dh_compute(struct keyctl_dh_params __user *params, 240f1c316a3SStephan Mueller char __user *buffer, size_t buflen, 241f1c316a3SStephan Mueller struct keyctl_kdf_params *kdfcopy) 242ddbb4114SMat Martineau { 243ddbb4114SMat Martineau long ret; 244*7cbe0932SMat Martineau ssize_t dlen; 245*7cbe0932SMat Martineau int secretlen; 246*7cbe0932SMat Martineau int outlen; 247ddbb4114SMat Martineau struct keyctl_dh_params pcopy; 248*7cbe0932SMat Martineau struct dh dh_inputs; 249*7cbe0932SMat Martineau struct scatterlist outsg; 250*7cbe0932SMat Martineau struct dh_completion compl; 251*7cbe0932SMat Martineau struct crypto_kpp *tfm; 252*7cbe0932SMat Martineau struct kpp_request *req; 253*7cbe0932SMat Martineau uint8_t *secret; 254*7cbe0932SMat Martineau uint8_t *outbuf; 255f1c316a3SStephan Mueller struct kdf_sdesc *sdesc = NULL; 256ddbb4114SMat Martineau 257ddbb4114SMat Martineau if (!params || (!buffer && buflen)) { 258ddbb4114SMat Martineau ret = -EINVAL; 259*7cbe0932SMat Martineau goto out1; 260ddbb4114SMat Martineau } 261ddbb4114SMat Martineau if (copy_from_user(&pcopy, params, sizeof(pcopy)) != 0) { 262ddbb4114SMat Martineau ret = -EFAULT; 263*7cbe0932SMat Martineau goto out1; 264ddbb4114SMat Martineau } 265ddbb4114SMat Martineau 266f1c316a3SStephan Mueller if (kdfcopy) { 267f1c316a3SStephan Mueller char *hashname; 268f1c316a3SStephan Mueller 269f1c316a3SStephan Mueller if (buflen > KEYCTL_KDF_MAX_OUTPUT_LEN || 270f1c316a3SStephan Mueller kdfcopy->otherinfolen > KEYCTL_KDF_MAX_OI_LEN) { 271f1c316a3SStephan Mueller ret = -EMSGSIZE; 272*7cbe0932SMat Martineau goto out1; 2734693fc73SStephan Mueller } 2744693fc73SStephan Mueller 275f1c316a3SStephan Mueller /* get KDF name string */ 276f1c316a3SStephan Mueller hashname = strndup_user(kdfcopy->hashname, CRYPTO_MAX_ALG_NAME); 277f1c316a3SStephan Mueller if (IS_ERR(hashname)) { 278f1c316a3SStephan Mueller ret = PTR_ERR(hashname); 279*7cbe0932SMat Martineau goto out1; 280f1c316a3SStephan Mueller } 281f1c316a3SStephan Mueller 282f1c316a3SStephan Mueller /* allocate KDF from the kernel crypto API */ 283f1c316a3SStephan Mueller ret = kdf_alloc(&sdesc, hashname); 284f1c316a3SStephan Mueller kfree(hashname); 285f1c316a3SStephan Mueller if (ret) 286*7cbe0932SMat Martineau goto out1; 287f1c316a3SStephan Mueller } 288f1c316a3SStephan Mueller 289*7cbe0932SMat Martineau memset(&dh_inputs, 0, sizeof(dh_inputs)); 290*7cbe0932SMat Martineau 291*7cbe0932SMat Martineau dlen = dh_data_from_key(pcopy.prime, &dh_inputs.p); 292*7cbe0932SMat Martineau if (dlen < 0) { 293*7cbe0932SMat Martineau ret = dlen; 294*7cbe0932SMat Martineau goto out1; 295*7cbe0932SMat Martineau } 296*7cbe0932SMat Martineau dh_inputs.p_size = dlen; 297*7cbe0932SMat Martineau 298*7cbe0932SMat Martineau dlen = dh_data_from_key(pcopy.base, &dh_inputs.g); 299*7cbe0932SMat Martineau if (dlen < 0) { 300*7cbe0932SMat Martineau ret = dlen; 301*7cbe0932SMat Martineau goto out2; 302*7cbe0932SMat Martineau } 303*7cbe0932SMat Martineau dh_inputs.g_size = dlen; 304*7cbe0932SMat Martineau 305*7cbe0932SMat Martineau dlen = dh_data_from_key(pcopy.private, &dh_inputs.key); 306*7cbe0932SMat Martineau if (dlen < 0) { 307*7cbe0932SMat Martineau ret = dlen; 308*7cbe0932SMat Martineau goto out2; 309*7cbe0932SMat Martineau } 310*7cbe0932SMat Martineau dh_inputs.key_size = dlen; 311*7cbe0932SMat Martineau 312*7cbe0932SMat Martineau secretlen = crypto_dh_key_len(&dh_inputs); 313*7cbe0932SMat Martineau secret = kmalloc(secretlen, GFP_KERNEL); 314*7cbe0932SMat Martineau if (!secret) { 315*7cbe0932SMat Martineau ret = -ENOMEM; 316*7cbe0932SMat Martineau goto out2; 317*7cbe0932SMat Martineau } 318*7cbe0932SMat Martineau ret = crypto_dh_encode_key(secret, secretlen, &dh_inputs); 319*7cbe0932SMat Martineau if (ret) 320*7cbe0932SMat Martineau goto out3; 321*7cbe0932SMat Martineau 322*7cbe0932SMat Martineau tfm = crypto_alloc_kpp("dh", CRYPTO_ALG_TYPE_KPP, 0); 323*7cbe0932SMat Martineau if (IS_ERR(tfm)) { 324*7cbe0932SMat Martineau ret = PTR_ERR(tfm); 325*7cbe0932SMat Martineau goto out3; 326*7cbe0932SMat Martineau } 327*7cbe0932SMat Martineau 328*7cbe0932SMat Martineau ret = crypto_kpp_set_secret(tfm, secret, secretlen); 329*7cbe0932SMat Martineau if (ret) 330*7cbe0932SMat Martineau goto out4; 331*7cbe0932SMat Martineau 332*7cbe0932SMat Martineau outlen = crypto_kpp_maxsize(tfm); 333*7cbe0932SMat Martineau 334*7cbe0932SMat Martineau if (!kdfcopy) { 335*7cbe0932SMat Martineau /* 336*7cbe0932SMat Martineau * When not using a KDF, buflen 0 is used to read the 337*7cbe0932SMat Martineau * required buffer length 338*7cbe0932SMat Martineau */ 339*7cbe0932SMat Martineau if (buflen == 0) { 340*7cbe0932SMat Martineau ret = outlen; 341*7cbe0932SMat Martineau goto out4; 342*7cbe0932SMat Martineau } else if (outlen > buflen) { 343*7cbe0932SMat Martineau ret = -EOVERFLOW; 344*7cbe0932SMat Martineau goto out4; 345*7cbe0932SMat Martineau } 346*7cbe0932SMat Martineau } 347*7cbe0932SMat Martineau 348*7cbe0932SMat Martineau outbuf = kzalloc(kdfcopy ? (outlen + kdfcopy->otherinfolen) : outlen, 349*7cbe0932SMat Martineau GFP_KERNEL); 350*7cbe0932SMat Martineau if (!outbuf) { 351*7cbe0932SMat Martineau ret = -ENOMEM; 352*7cbe0932SMat Martineau goto out4; 353*7cbe0932SMat Martineau } 354*7cbe0932SMat Martineau 355*7cbe0932SMat Martineau sg_init_one(&outsg, outbuf, outlen); 356*7cbe0932SMat Martineau 357*7cbe0932SMat Martineau req = kpp_request_alloc(tfm, GFP_KERNEL); 358*7cbe0932SMat Martineau if (!req) { 359*7cbe0932SMat Martineau ret = -ENOMEM; 360*7cbe0932SMat Martineau goto out5; 361*7cbe0932SMat Martineau } 362*7cbe0932SMat Martineau 363*7cbe0932SMat Martineau kpp_request_set_input(req, NULL, 0); 364*7cbe0932SMat Martineau kpp_request_set_output(req, &outsg, outlen); 365*7cbe0932SMat Martineau init_completion(&compl.completion); 366*7cbe0932SMat Martineau kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | 367*7cbe0932SMat Martineau CRYPTO_TFM_REQ_MAY_SLEEP, 368*7cbe0932SMat Martineau dh_crypto_done, &compl); 369*7cbe0932SMat Martineau 370f1c316a3SStephan Mueller /* 371*7cbe0932SMat Martineau * For DH, generate_public_key and generate_shared_secret are 372*7cbe0932SMat Martineau * the same calculation 373f1c316a3SStephan Mueller */ 374*7cbe0932SMat Martineau ret = crypto_kpp_generate_public_key(req); 375*7cbe0932SMat Martineau if (ret == -EINPROGRESS) { 376*7cbe0932SMat Martineau wait_for_completion(&compl.completion); 377*7cbe0932SMat Martineau ret = compl.err; 378*7cbe0932SMat Martineau if (ret) 379*7cbe0932SMat Martineau goto out6; 380ddbb4114SMat Martineau } 381ddbb4114SMat Martineau 382*7cbe0932SMat Martineau if (kdfcopy) { 383f1c316a3SStephan Mueller /* 384f1c316a3SStephan Mueller * Concatenate SP800-56A otherinfo past DH shared secret -- the 385f1c316a3SStephan Mueller * input to the KDF is (DH shared secret || otherinfo) 386f1c316a3SStephan Mueller */ 387*7cbe0932SMat Martineau if (copy_from_user(outbuf + req->dst_len, kdfcopy->otherinfo, 388f1c316a3SStephan Mueller kdfcopy->otherinfolen) != 0) { 389f1c316a3SStephan Mueller ret = -EFAULT; 390*7cbe0932SMat Martineau goto out6; 391f1c316a3SStephan Mueller } 392f1c316a3SStephan Mueller 393*7cbe0932SMat Martineau ret = keyctl_dh_compute_kdf(sdesc, buffer, buflen, outbuf, 394*7cbe0932SMat Martineau req->dst_len + kdfcopy->otherinfolen, 395*7cbe0932SMat Martineau outlen - req->dst_len); 396*7cbe0932SMat Martineau } else if (copy_to_user(buffer, outbuf, req->dst_len) == 0) { 397*7cbe0932SMat Martineau ret = req->dst_len; 398f1c316a3SStephan Mueller } else { 399ddbb4114SMat Martineau ret = -EFAULT; 400f1c316a3SStephan Mueller } 401ddbb4114SMat Martineau 402*7cbe0932SMat Martineau out6: 403*7cbe0932SMat Martineau kpp_request_free(req); 404*7cbe0932SMat Martineau out5: 405*7cbe0932SMat Martineau kzfree(outbuf); 406*7cbe0932SMat Martineau out4: 407*7cbe0932SMat Martineau crypto_free_kpp(tfm); 408*7cbe0932SMat Martineau out3: 409*7cbe0932SMat Martineau kzfree(secret); 410*7cbe0932SMat Martineau out2: 411*7cbe0932SMat Martineau dh_free_data(&dh_inputs); 412*7cbe0932SMat Martineau out1: 413f1c316a3SStephan Mueller kdf_dealloc(sdesc); 414ddbb4114SMat Martineau return ret; 415ddbb4114SMat Martineau } 416f1c316a3SStephan Mueller 417f1c316a3SStephan Mueller long keyctl_dh_compute(struct keyctl_dh_params __user *params, 418f1c316a3SStephan Mueller char __user *buffer, size_t buflen, 419f1c316a3SStephan Mueller struct keyctl_kdf_params __user *kdf) 420f1c316a3SStephan Mueller { 421f1c316a3SStephan Mueller struct keyctl_kdf_params kdfcopy; 422f1c316a3SStephan Mueller 423f1c316a3SStephan Mueller if (!kdf) 424f1c316a3SStephan Mueller return __keyctl_dh_compute(params, buffer, buflen, NULL); 425f1c316a3SStephan Mueller 426f1c316a3SStephan Mueller if (copy_from_user(&kdfcopy, kdf, sizeof(kdfcopy)) != 0) 427f1c316a3SStephan Mueller return -EFAULT; 428f1c316a3SStephan Mueller 429f1c316a3SStephan Mueller return __keyctl_dh_compute(params, buffer, buflen, &kdfcopy); 430f1c316a3SStephan Mueller } 431