341 lines · c
1/*2 * algif_rng: User-space interface for random number generators3 *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 without9 * modification, are permitted provided that the following conditions10 * are met:11 * 1. Redistributions of source code must retain the above copyright12 * 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 copyright15 * notice, this list of conditions and the following disclaimer in the16 * documentation and/or other materials provided with the distribution.17 * 3. The name of the author may not be used to endorse or promote18 * products derived from this software without specific prior19 * written permission.20 *21 * ALTERNATIVELY, this product may be distributed under the terms of22 * the GNU General Public License, in which case the provisions of the GPL223 * are required INSTEAD OF the above restrictions. (This clause is24 * necessary due to a potential bad interaction between the GPL and25 * the restrictions contained in a BSD-style copyright.)26 *27 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED28 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES29 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF30 * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT33 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR34 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF35 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE37 * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH38 * 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 12855 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 coding87 * errors88 */89 memset(result, 0, len);90 91 /*92 * The enforcement of a proper seeding of an RNG is done within an93 * RNG implementation. Some RNGs (DRBG, krng) do not need specific94 * seeding as they automatically seed. The X9.31 DRNG will return95 * 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 are257 * done on one RNG instance, each resulting FD points to the same258 * 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 on267 * 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 RNG280 * 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 entropy309 * 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_CAVP321 .setentropy = rng_setentropy,322#endif323 .ops = &algif_rng_ops,324 .name = "rng",325 .owner = THIS_MODULE326};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