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/module.h>
  42#include <crypto/rng.h>
  43#include <linux/random.h>
  44#include <crypto/if_alg.h>
  45#include <linux/net.h>
  46#include <net/sock.h>
  47
  48MODULE_LICENSE("GPL");
  49MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
  50MODULE_DESCRIPTION("User-space interface for random number generators");
  51
  52struct rng_ctx {
  53#define MAXSIZE 128
  54        unsigned int len;
  55        struct crypto_rng *drng;
  56};
  57
  58static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
  59                       int flags)
  60{
  61        struct sock *sk = sock->sk;
  62        struct alg_sock *ask = alg_sk(sk);
  63        struct rng_ctx *ctx = ask->private;
  64        int err = -EFAULT;
  65        int genlen = 0;
  66        u8 result[MAXSIZE];
  67
  68        if (len == 0)
  69                return 0;
  70        if (len > MAXSIZE)
  71                len = MAXSIZE;
  72
  73        /*
  74         * although not strictly needed, this is a precaution against coding
  75         * errors
  76         */
  77        memset(result, 0, len);
  78
  79        /*
  80         * The enforcement of a proper seeding of an RNG is done within an
  81         * RNG implementation. Some RNGs (DRBG, krng) do not need specific
  82         * seeding as they automatically seed. The X9.31 DRNG will return
  83         * an error if it was not seeded properly.
  84         */
  85        genlen = crypto_rng_get_bytes(ctx->drng, result, len);
  86        if (genlen < 0)
  87                return genlen;
  88
  89        err = memcpy_to_msg(msg, result, len);
  90        memzero_explicit(result, len);
  91
  92        return err ? err : len;
  93}
  94
  95static struct proto_ops algif_rng_ops = {
  96        .family         =       PF_ALG,
  97
  98        .connect        =       sock_no_connect,
  99        .socketpair     =       sock_no_socketpair,
 100        .getname        =       sock_no_getname,
 101        .ioctl          =       sock_no_ioctl,
 102        .listen         =       sock_no_listen,
 103        .shutdown       =       sock_no_shutdown,
 104        .getsockopt     =       sock_no_getsockopt,
 105        .mmap           =       sock_no_mmap,
 106        .bind           =       sock_no_bind,
 107        .accept         =       sock_no_accept,
 108        .setsockopt     =       sock_no_setsockopt,
 109        .sendmsg        =       sock_no_sendmsg,
 110        .sendpage       =       sock_no_sendpage,
 111
 112        .release        =       af_alg_release,
 113        .recvmsg        =       rng_recvmsg,
 114};
 115
 116static void *rng_bind(const char *name, u32 type, u32 mask)
 117{
 118        return crypto_alloc_rng(name, type, mask);
 119}
 120
 121static void rng_release(void *private)
 122{
 123        crypto_free_rng(private);
 124}
 125
 126static void rng_sock_destruct(struct sock *sk)
 127{
 128        struct alg_sock *ask = alg_sk(sk);
 129        struct rng_ctx *ctx = ask->private;
 130
 131        sock_kfree_s(sk, ctx, ctx->len);
 132        af_alg_release_parent(sk);
 133}
 134
 135static int rng_accept_parent(void *private, struct sock *sk)
 136{
 137        struct rng_ctx *ctx;
 138        struct alg_sock *ask = alg_sk(sk);
 139        unsigned int len = sizeof(*ctx);
 140
 141        ctx = sock_kmalloc(sk, len, GFP_KERNEL);
 142        if (!ctx)
 143                return -ENOMEM;
 144
 145        ctx->len = len;
 146
 147        /*
 148         * No seeding done at that point -- if multiple accepts are
 149         * done on one RNG instance, each resulting FD points to the same
 150         * state of the RNG.
 151         */
 152
 153        ctx->drng = private;
 154        ask->private = ctx;
 155        sk->sk_destruct = rng_sock_destruct;
 156
 157        return 0;
 158}
 159
 160static int rng_setkey(void *private, const u8 *seed, unsigned int seedlen)
 161{
 162        /*
 163         * Check whether seedlen is of sufficient size is done in RNG
 164         * implementations.
 165         */
 166        return crypto_rng_reset(private, seed, seedlen);
 167}
 168
 169static const struct af_alg_type algif_type_rng = {
 170        .bind           =       rng_bind,
 171        .release        =       rng_release,
 172        .accept         =       rng_accept_parent,
 173        .setkey         =       rng_setkey,
 174        .ops            =       &algif_rng_ops,
 175        .name           =       "rng",
 176        .owner          =       THIS_MODULE
 177};
 178
 179static int __init rng_init(void)
 180{
 181        return af_alg_register_type(&algif_type_rng);
 182}
 183
 184static void __exit rng_exit(void)
 185{
 186        int err = af_alg_unregister_type(&algif_type_rng);
 187        BUG_ON(err);
 188}
 189
 190module_init(rng_init);
 191module_exit(rng_exit);
 192