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        .sendpage       =       sock_no_sendpage,
 178
 179        .release        =       af_alg_release,
 180        .recvmsg        =       rng_recvmsg,
 181};
 182
 183static struct proto_ops __maybe_unused algif_rng_test_ops = {
 184        .family         =       PF_ALG,
 185
 186        .connect        =       sock_no_connect,
 187        .socketpair     =       sock_no_socketpair,
 188        .getname        =       sock_no_getname,
 189        .ioctl          =       sock_no_ioctl,
 190        .listen         =       sock_no_listen,
 191        .shutdown       =       sock_no_shutdown,
 192        .mmap           =       sock_no_mmap,
 193        .bind           =       sock_no_bind,
 194        .accept         =       sock_no_accept,
 195        .sendpage       =       sock_no_sendpage,
 196
 197        .release        =       af_alg_release,
 198        .recvmsg        =       rng_test_recvmsg,
 199        .sendmsg        =       rng_test_sendmsg,
 200};
 201
 202static void *rng_bind(const char *name, u32 type, u32 mask)
 203{
 204        struct rng_parent_ctx *pctx;
 205        struct crypto_rng *rng;
 206
 207        pctx = kzalloc(sizeof(*pctx), GFP_KERNEL);
 208        if (!pctx)
 209                return ERR_PTR(-ENOMEM);
 210
 211        rng = crypto_alloc_rng(name, type, mask);
 212        if (IS_ERR(rng)) {
 213                kfree(pctx);
 214                return ERR_CAST(rng);
 215        }
 216
 217        pctx->drng = rng;
 218        return pctx;
 219}
 220
 221static void rng_release(void *private)
 222{
 223        struct rng_parent_ctx *pctx = private;
 224
 225        if (unlikely(!pctx))
 226                return;
 227        crypto_free_rng(pctx->drng);
 228        kfree_sensitive(pctx->entropy);
 229        kfree_sensitive(pctx);
 230}
 231
 232static void rng_sock_destruct(struct sock *sk)
 233{
 234        struct alg_sock *ask = alg_sk(sk);
 235        struct rng_ctx *ctx = ask->private;
 236
 237        rng_reset_addtl(ctx);
 238        sock_kfree_s(sk, ctx, ctx->len);
 239        af_alg_release_parent(sk);
 240}
 241
 242static int rng_accept_parent(void *private, struct sock *sk)
 243{
 244        struct rng_ctx *ctx;
 245        struct rng_parent_ctx *pctx = private;
 246        struct alg_sock *ask = alg_sk(sk);
 247        unsigned int len = sizeof(*ctx);
 248
 249        ctx = sock_kmalloc(sk, len, GFP_KERNEL);
 250        if (!ctx)
 251                return -ENOMEM;
 252
 253        ctx->len = len;
 254        ctx->addtl = NULL;
 255        ctx->addtl_len = 0;
 256
 257        /*
 258         * No seeding done at that point -- if multiple accepts are
 259         * done on one RNG instance, each resulting FD points to the same
 260         * state of the RNG.
 261         */
 262
 263        ctx->drng = pctx->drng;
 264        ask->private = ctx;
 265        sk->sk_destruct = rng_sock_destruct;
 266
 267        /*
 268         * Non NULL pctx->entropy means that CAVP test has been initiated on
 269         * this socket, replace proto_ops algif_rng_ops with algif_rng_test_ops.
 270         */
 271        if (IS_ENABLED(CONFIG_CRYPTO_USER_API_RNG_CAVP) && pctx->entropy)
 272                sk->sk_socket->ops = &algif_rng_test_ops;
 273
 274        return 0;
 275}
 276
 277static int rng_setkey(void *private, const u8 *seed, unsigned int seedlen)
 278{
 279        struct rng_parent_ctx *pctx = private;
 280        /*
 281         * Check whether seedlen is of sufficient size is done in RNG
 282         * implementations.
 283         */
 284        return crypto_rng_reset(pctx->drng, seed, seedlen);
 285}
 286
 287static int __maybe_unused rng_setentropy(void *private, sockptr_t entropy,
 288                                         unsigned int len)
 289{
 290        struct rng_parent_ctx *pctx = private;
 291        u8 *kentropy = NULL;
 292
 293        if (!capable(CAP_SYS_ADMIN))
 294                return -EACCES;
 295
 296        if (pctx->entropy)
 297                return -EINVAL;
 298
 299        if (len > MAXSIZE)
 300                return -EMSGSIZE;
 301
 302        if (len) {
 303                kentropy = memdup_sockptr(entropy, len);
 304                if (IS_ERR(kentropy))
 305                        return PTR_ERR(kentropy);
 306        }
 307
 308        crypto_rng_alg(pctx->drng)->set_ent(pctx->drng, kentropy, len);
 309        /*
 310         * Since rng doesn't perform any memory management for the entropy
 311         * buffer, save kentropy pointer to pctx now to free it after use.
 312         */
 313        pctx->entropy = kentropy;
 314        return 0;
 315}
 316
 317static const struct af_alg_type algif_type_rng = {
 318        .bind           =       rng_bind,
 319        .release        =       rng_release,
 320        .accept         =       rng_accept_parent,
 321        .setkey         =       rng_setkey,
 322#ifdef CONFIG_CRYPTO_USER_API_RNG_CAVP
 323        .setentropy     =       rng_setentropy,
 324#endif
 325        .ops            =       &algif_rng_ops,
 326        .name           =       "rng",
 327        .owner          =       THIS_MODULE
 328};
 329
 330static int __init rng_init(void)
 331{
 332        return af_alg_register_type(&algif_type_rng);
 333}
 334
 335static void __exit rng_exit(void)
 336{
 337        int err = af_alg_unregister_type(&algif_type_rng);
 338        BUG_ON(err);
 339}
 340
 341module_init(rng_init);
 342module_exit(rng_exit);
 343
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.