diff options
-rw-r--r-- | crypto/algif_rng.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c new file mode 100644 index 000000000000..91c06f5673dd --- /dev/null +++ b/crypto/algif_rng.c | |||
@@ -0,0 +1,192 @@ | |||
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 | |||
48 | MODULE_LICENSE("GPL"); | ||
49 | MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>"); | ||
50 | MODULE_DESCRIPTION("User-space interface for random number generators"); | ||
51 | |||
52 | struct rng_ctx { | ||
53 | #define MAXSIZE 128 | ||
54 | unsigned int len; | ||
55 | struct crypto_rng *drng; | ||
56 | }; | ||
57 | |||
58 | static int rng_recvmsg(struct kiocb *unused, struct socket *sock, | ||
59 | struct msghdr *msg, size_t len, 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, genlen); | ||
91 | |||
92 | return err ? err : len; | ||
93 | } | ||
94 | |||
95 | static 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 | .poll = sock_no_poll, | ||
110 | .sendmsg = sock_no_sendmsg, | ||
111 | .sendpage = sock_no_sendpage, | ||
112 | |||
113 | .release = af_alg_release, | ||
114 | .recvmsg = rng_recvmsg, | ||
115 | }; | ||
116 | |||
117 | static void *rng_bind(const char *name, u32 type, u32 mask) | ||
118 | { | ||
119 | return crypto_alloc_rng(name, type, mask); | ||
120 | } | ||
121 | |||
122 | static void rng_release(void *private) | ||
123 | { | ||
124 | crypto_free_rng(private); | ||
125 | } | ||
126 | |||
127 | static void rng_sock_destruct(struct sock *sk) | ||
128 | { | ||
129 | struct alg_sock *ask = alg_sk(sk); | ||
130 | struct rng_ctx *ctx = ask->private; | ||
131 | |||
132 | sock_kfree_s(sk, ctx, ctx->len); | ||
133 | af_alg_release_parent(sk); | ||
134 | } | ||
135 | |||
136 | static int rng_accept_parent(void *private, struct sock *sk) | ||
137 | { | ||
138 | struct rng_ctx *ctx; | ||
139 | struct alg_sock *ask = alg_sk(sk); | ||
140 | unsigned int len = sizeof(*ctx); | ||
141 | |||
142 | ctx = sock_kmalloc(sk, len, GFP_KERNEL); | ||
143 | if (!ctx) | ||
144 | return -ENOMEM; | ||
145 | |||
146 | ctx->len = len; | ||
147 | |||
148 | /* | ||
149 | * No seeding done at that point -- if multiple accepts are | ||
150 | * done on one RNG instance, each resulting FD points to the same | ||
151 | * state of the RNG. | ||
152 | */ | ||
153 | |||
154 | ctx->drng = private; | ||
155 | ask->private = ctx; | ||
156 | sk->sk_destruct = rng_sock_destruct; | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static int rng_setkey(void *private, const u8 *seed, unsigned int seedlen) | ||
162 | { | ||
163 | /* | ||
164 | * Check whether seedlen is of sufficient size is done in RNG | ||
165 | * implementations. | ||
166 | */ | ||
167 | return crypto_rng_reset(private, (u8 *)seed, seedlen); | ||
168 | } | ||
169 | |||
170 | static const struct af_alg_type algif_type_rng = { | ||
171 | .bind = rng_bind, | ||
172 | .release = rng_release, | ||
173 | .accept = rng_accept_parent, | ||
174 | .setkey = rng_setkey, | ||
175 | .ops = &algif_rng_ops, | ||
176 | .name = "rng", | ||
177 | .owner = THIS_MODULE | ||
178 | }; | ||
179 | |||
180 | static int __init rng_init(void) | ||
181 | { | ||
182 | return af_alg_register_type(&algif_type_rng); | ||
183 | } | ||
184 | |||
185 | void __exit rng_exit(void) | ||
186 | { | ||
187 | int err = af_alg_unregister_type(&algif_type_rng); | ||
188 | BUG_ON(err); | ||
189 | } | ||
190 | |||
191 | module_init(rng_init); | ||
192 | module_exit(rng_exit); | ||