root/security/keys/dh.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dh_data_from_key
  2. dh_free_data
  3. dh_crypto_done
  4. kdf_alloc
  5. kdf_dealloc
  6. kdf_ctr
  7. keyctl_dh_compute_kdf
  8. __keyctl_dh_compute
  9. keyctl_dh_compute

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

/* [<][>][^][v][top][bottom][index][help] */