linux/crypto/algif_rng.c
<<
>>
Prefs
   1/*
   2 * algif_rng: User-space interface for random number generators
   3 *
   4 * This file provides the user-space API for random number generators.
   5 *
   6 * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de>
   7 *
   8 * Redistribution and use in source and binary forms, with or without
   9 * modification, are permitted provided that the following conditions
  10 * are met:
  11 * 1. Redistributions of source code must retain the above copyright
  12 *    notice, and the entire permission notice in its entirety,
  13 *    including the disclaimer of warranties.
  14 * 2. Redistributions in binary form must reproduce the above copyright
  15 *    notice, this list of conditions and the following disclaimer in the
  16 *    documentation and/or other materials provided with the distribution.
  17 * 3. The name of the author may not be used to endorse or promote
  18 *    products derived from this software without specific prior
  19 *    written permission.
  20 *
  21 * ALTERNATIVELY, this product may be distributed under the terms of
  22 * the GNU General Public License, in which case the provisions of the GPL2
  23 * are required INSTEAD OF the above restrictions.  (This clause is
  24 * necessary due to a potential bad interaction between the GPL and
  25 * the restrictions contained in a BSD-style copyright.)
  26 *
  27 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  28 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  29 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
  30 * WHICH ARE HEREBY DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE
  31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  33 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  34 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  35 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  37 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
  38 * DAMAGE.
  39 */
  40
  41#include <linux/capability.h>
  42#include <linux/module.h>
  43#include <crypto/rng.h>
  44#include <linux/random.h>
  45#include <crypto/if_alg.h>
  46#include <linux/net.h>
  47#include <net/sock.h>
  48
  49MODULE_LICENSE("GPL");
  50MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
  51MODULE_DESCRIPTION("User-space interface for random number generators");
  52
  53struct rng_ctx {
  54#define MAXSIZE 128
  55        unsigned int len;
  56        struct crypto_rng *drng;
  57        u8 *addtl;
  58        size_t addtl_len;
  59};
  60
  61struct rng_parent_ctx {
  62        struct crypto_rng *drng;
  63        u8 *entropy;
  64};
  65
  66static void rng_reset_addtl(struct rng_ctx *ctx)
  67{
  68        kfree_sensitive(ctx->addtl);
  69        ctx->addtl = NULL;
  70        ctx->addtl_len = 0;
  71}
  72
  73static int _rng_recvmsg(struct crypto_rng *drng, struct msghdr *msg, size_t len,
  74                        u8 *addtl, size_t addtl_len)
  75{
  76        int err = 0;
  77        int genlen = 0;
  78        u8 result[MAXSIZE];
  79
  80        if (len == 0)
  81                return 0;
  82        if (len > MAXSIZE)
  83                len = MAXSIZE;
  84
  85        /*
  86         * although not strictly needed, this is a precaution against coding
  87         * errors
  88         */
  89        memset(result, 0, len);
  90
  91        /*
  92         * The enforcement of a proper seeding of an RNG is done within an
  93         * RNG implementation. Some RNGs (DRBG, krng) do not need specific
  94         * seeding as they automatically seed. The X9.31 DRNG will return
  95         * an error if it was not seeded properly.
  96         */
  97        genlen = crypto_rng_generate(drng, addtl, addtl_len, result, len);
  98        if (genlen < 0)
  99                return genlen;
 100
 101        err = memcpy_to_msg(msg, result, len);
 102        memzero_explicit(result, len);
 103
 104        return err ? err : len;
 105}
 106
 107static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 108                       int flags)
 109{
 110        struct sock *sk = sock->sk;
 111        struct alg_sock *ask = alg_sk(sk);
 112        struct rng_ctx *ctx = ask->private;
 113
 114        return _rng_recvmsg(ctx->drng, msg, len, NULL, 0);
 115}
 116
 117static int rng_test_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 118                            int flags)
 119{
 120        struct sock *sk = sock->sk;
 121        struct alg_sock *ask = alg_sk(sk);
 122        struct rng_ctx *ctx = ask->private;
 123        int ret;
 124
 125        lock_sock(sock->sk);
 126        ret = _rng_recvmsg(ctx->drng, msg, len, ctx->addtl, ctx->addtl_len);
 127        rng_reset_addtl(ctx);
 128        release_sock(sock->sk);
 129
 130        return ret;
 131}
 132
 133static int rng_test_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
 134{
 135        int err;
 136        struct alg_sock *ask = alg_sk(sock->sk);
 137        struct rng_ctx *ctx = ask->private;
 138
 139        lock_sock(sock->sk);
 140        if (len > MAXSIZE) {
 141                err = -EMSGSIZE;
 142                goto unlock;
 143        }
 144
 145        rng_reset_addtl(ctx);
 146        ctx->addtl = kmalloc(len, GFP_KERNEL);
 147        if (!ctx->addtl) {
 148                err = -ENOMEM;
 149                goto unlock;
 150        }
 151
 152        err = memcpy_from_msg(ctx->addtl, msg, len);
 153        if (err) {
 154                rng_reset_addtl(ctx);
 155                goto unlock;
 156        }
 157        ctx->addtl_len = len;
 158
 159unlock:
 160        release_sock(sock->sk);
 161        return err ? err : len;
 162}
 163
 164static struct proto_ops algif_rng_ops = {
 165        .family         =       PF_ALG,
 166
 167        .connect        =       sock_no_connect,
 168        .socketpair     =       sock_no_socketpair,
 169        .getname        =       sock_no_getname,
 170        .ioctl          =       sock_no_ioctl,
 171        .listen         =       sock_no_listen,
 172        .shutdown       =       sock_no_shutdown,
 173        .mmap           =       sock_no_mmap,
 174        .bind           =       sock_no_bind,
 175        .accept         =       sock_no_accept,
 176        .sendmsg        =       sock_no_sendmsg,
 177
 178        .release        =       af_alg_release,
 179        .recvmsg        =       rng_recvmsg,
 180};
 181
 182static struct proto_ops __maybe_unused algif_rng_test_ops = {
 183        .family         =       PF_ALG,
 184
 185        .connect        =       sock_no_connect,
 186        .socketpair     =       sock_no_socketpair,
 187        .getname        =       sock_no_getname,
 188        .ioctl          =       sock_no_ioctl,
 189        .listen         =       sock_no_listen,
 190        .shutdown       =       sock_no_shutdown,
 191        .mmap           =       sock_no_mmap,
 192        .bind           =       sock_no_bind,
 193        .accept         =       sock_no_accept,
 194
 195        .release        =       af_alg_release,
 196        .recvmsg        =       rng_test_recvmsg,
 197        .sendmsg        =       rng_test_sendmsg,
 198};
 199
 200static void *rng_bind(const char *name, u32 type, u32 mask)
 201{
 202        struct rng_parent_ctx *pctx;
 203        struct crypto_rng *rng;
 204
 205        pctx = kzalloc(sizeof(*pctx), GFP_KERNEL);
 206        if (!pctx)
 207                return ERR_PTR(-ENOMEM);
 208
 209        rng = crypto_alloc_rng(name, type, mask);
 210        if (IS_ERR(rng)) {
 211                kfree(pctx);
 212                return ERR_CAST(rng);
 213        }
 214
 215        pctx->drng = rng;
 216        return pctx;
 217}
 218
 219static void rng_release(void *private)
 220{
 221        struct rng_parent_ctx *pctx = private;
 222
 223        if (unlikely(!pctx))
 224                return;
 225        crypto_free_rng(pctx->drng);
 226        kfree_sensitive(pctx->entropy);
 227        kfree_sensitive(pctx);
 228}
 229
 230static void rng_sock_destruct(struct sock *sk)
 231{
 232        struct alg_sock *ask = alg_sk(sk);
 233        struct rng_ctx *ctx = ask->private;
 234
 235        rng_reset_addtl(ctx);
 236        sock_kfree_s(sk, ctx, ctx->len);
 237        af_alg_release_parent(sk);
 238}
 239
 240static int rng_accept_parent(void *private, struct sock *sk)
 241{
 242        struct rng_ctx *ctx;
 243        struct rng_parent_ctx *pctx = private;
 244        struct alg_sock *ask = alg_sk(sk);
 245        unsigned int len = sizeof(*ctx);
 246
 247        ctx = sock_kmalloc(sk, len, GFP_KERNEL);
 248        if (!ctx)
 249                return -ENOMEM;
 250
 251        ctx->len = len;
 252        ctx->addtl = NULL;
 253        ctx->addtl_len = 0;
 254
 255        /*
 256         * No seeding done at that point -- if multiple accepts are
 257         * done on one RNG instance, each resulting FD points to the same
 258         * state of the RNG.
 259         */
 260
 261        ctx->drng = pctx->drng;
 262        ask->private = ctx;
 263        sk->sk_destruct = rng_sock_destruct;
 264
 265        /*
 266         * Non NULL pctx->entropy means that CAVP test has been initiated on
 267         * this socket, replace proto_ops algif_rng_ops with algif_rng_test_ops.
 268         */
 269        if (IS_ENABLED(CONFIG_CRYPTO_USER_API_RNG_CAVP) && pctx->entropy)
 270                sk->sk_socket->ops = &algif_rng_test_ops;
 271
 272        return 0;
 273}
 274
 275static int rng_setkey(void *private, const u8 *seed, unsigned int seedlen)
 276{
 277        struct rng_parent_ctx *pctx = private;
 278        /*
 279         * Check whether seedlen is of sufficient size is done in RNG
 280         * implementations.
 281         */
 282        return crypto_rng_reset(pctx->drng, seed, seedlen);
 283}
 284
 285static int __maybe_unused rng_setentropy(void *private, sockptr_t entropy,
 286                                         unsigned int len)
 287{
 288        struct rng_parent_ctx *pctx = private;
 289        u8 *kentropy = NULL;
 290
 291        if (!capable(CAP_SYS_ADMIN))
 292                return -EACCES;
 293
 294        if (pctx->entropy)
 295                return -EINVAL;
 296
 297        if (len > MAXSIZE)
 298                return -EMSGSIZE;
 299
 300        if (len) {
 301                kentropy = memdup_sockptr(entropy, len);
 302                if (IS_ERR(kentropy))
 303                        return PTR_ERR(kentropy);
 304        }
 305
 306        crypto_rng_alg(pctx->drng)->set_ent(pctx->drng, kentropy, len);
 307        /*
 308         * Since rng doesn't perform any memory management for the entropy
 309         * buffer, save kentropy pointer to pctx now to free it after use.
 310         */
 311        pctx->entropy = kentropy;
 312        return 0;
 313}
 314
 315static const struct af_alg_type algif_type_rng = {
 316        .bind           =       rng_bind,
 317        .release        =       rng_release,
 318        .accept         =       rng_accept_parent,
 319        .setkey         =       rng_setkey,
 320#ifdef CONFIG_CRYPTO_USER_API_RNG_CAVP
 321        .setentropy     =       rng_setentropy,
 322#endif
 323        .ops            =       &algif_rng_ops,
 324        .name           =       "rng",
 325        .owner          =       THIS_MODULE
 326};
 327
 328static int __init rng_init(void)
 329{
 330        return af_alg_register_type(&algif_type_rng);
 331}
 332
 333static void __exit rng_exit(void)
 334{
 335        int err = af_alg_unregister_type(&algif_type_rng);
 336        BUG_ON(err);
 337}
 338
 339module_init(rng_init);
 340module_exit(rng_exit);
 341