linux/security/keys/dh.c
<<
>>
Prefs
   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
  17static 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);
  55error:
  56        return ret;
  57}
  58
  59static void dh_free_data(struct dh *dh)
  60{
  61        kfree_sensitive(dh->key);
  62        kfree_sensitive(dh->p);
  63        kfree_sensitive(dh->g);
  64}
  65
  66struct dh_completion {
  67        struct completion completion;
  68        int err;
  69};
  70
  71static 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
  82struct kdf_sdesc {
  83        struct shash_desc shash;
  84        char ctx[];
  85};
  86
  87static 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
 116out_free_tfm:
 117        crypto_free_shash(tfm);
 118        return err;
 119}
 120
 121static 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        kfree_sensitive(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 */
 143static 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
 194err:
 195        memzero_explicit(dst_orig, dlen);
 196        return err;
 197}
 198
 199static 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
 222err:
 223        kfree_sensitive(outbuf);
 224        return ret;
 225}
 226
 227long __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
 395out6:
 396        kpp_request_free(req);
 397out5:
 398        kfree_sensitive(outbuf);
 399out4:
 400        crypto_free_kpp(tfm);
 401out3:
 402        kfree_sensitive(secret);
 403out2:
 404        dh_free_data(&dh_inputs);
 405out1:
 406        kdf_dealloc(sdesc);
 407        return ret;
 408}
 409
 410long 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}
 424