blob: 0b196b6775df92f0cd6fe9ed58d9d229d6b18d73 [file] [log] [blame]
developer34e20fa2023-11-14 13:49:21 +08001diff --git a/crypto/af_alg.c b/crypto/af_alg.c
2index 4a2e91baa..fb6b4f8a0 100644
3--- a/crypto/af_alg.c
4+++ b/crypto/af_alg.c
5@@ -226,6 +226,30 @@ static int alg_setkey(struct sock *sk, char __user *ukey,
6 return err;
7 }
8
9+static int alg_setentropy(struct sock *sk, char __user *ukey,
10+ unsigned int entropy_len)
11+{
12+ struct alg_sock *ask = alg_sk(sk);
13+ const struct af_alg_type *type = ask->type;
14+ u8 *entropy;
15+ int err;
16+
17+ entropy = sock_kmalloc(sk, entropy_len, GFP_KERNEL);
18+ if (!entropy)
19+ return -ENOMEM;
20+
21+ err = -EFAULT;
22+ if (copy_from_user(entropy, ukey, entropy_len))
23+ goto out;
24+
25+ err = type->setentropy(ask->private, entropy, entropy_len);
26+
27+out:
28+ sock_kzfree_s(sk, entropy, entropy_len);
29+
30+ return err;
31+}
32+
33 static int alg_setsockopt(struct socket *sock, int level, int optname,
34 char __user *optval, unsigned int optlen)
35 {
36@@ -250,7 +274,6 @@ static int alg_setsockopt(struct socket *sock, int level, int optname,
37 goto unlock;
38 if (!type->setkey)
39 goto unlock;
40-
41 err = alg_setkey(sk, optval, optlen);
42 break;
43 case ALG_SET_AEAD_AUTHSIZE:
44@@ -259,6 +282,15 @@ static int alg_setsockopt(struct socket *sock, int level, int optname,
45 if (!type->setauthsize)
46 goto unlock;
47 err = type->setauthsize(ask->private, optlen);
48+ break;
49+ case ALG_SET_DRBG_ENTROPY:
50+ if (sock->state == SS_CONNECTED)
51+ goto unlock;
52+ if (!type->setentropy)
53+ goto unlock;
54+ err = alg_setentropy(sk, optval, optlen);
55+ break;
56+
57 }
58
59 unlock:
60@@ -291,6 +323,11 @@ int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern)
61 security_sock_graft(sk2, newsock);
62 security_sk_clone(sk, sk2);
63
64+ /*
65+ * newsock->ops assigned here to allow type->accept call to override
66+ * them when required.
67+ */
68+ newsock->ops = type->ops;
69 err = type->accept(ask->private, sk2);
70
71 nokey = err == -ENOKEY;
72@@ -309,7 +346,6 @@ int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern)
73 alg_sk(sk2)->parent = sk;
74 alg_sk(sk2)->type = type;
75
76- newsock->ops = type->ops;
77 newsock->state = SS_CONNECTED;
78
79 if (nokey)
80diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c
81index 22df3799a..bce3aef53 100644
82--- a/crypto/algif_rng.c
83+++ b/crypto/algif_rng.c
84@@ -38,6 +38,7 @@
85 * DAMAGE.
86 */
87
88+#include <linux/capability.h>
89 #include <linux/module.h>
90 #include <crypto/rng.h>
91 #include <linux/random.h>
92@@ -53,15 +54,26 @@ struct rng_ctx {
93 #define MAXSIZE 128
94 unsigned int len;
95 struct crypto_rng *drng;
96+ u8 *addtl;
97+ size_t addtl_len;
98 };
99
100-static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
101- int flags)
102+struct rng_parent_ctx {
103+ struct crypto_rng *drng;
104+ u8 *entropy;
105+};
106+
107+static void rng_reset_addtl(struct rng_ctx *ctx)
108 {
109- struct sock *sk = sock->sk;
110- struct alg_sock *ask = alg_sk(sk);
111- struct rng_ctx *ctx = ask->private;
112- int err = -EFAULT;
113+ kzfree(ctx->addtl);
114+ ctx->addtl = NULL;
115+ ctx->addtl_len = 0;
116+}
117+
118+static int _rng_recvmsg(struct crypto_rng *drng, struct msghdr *msg, size_t len,
119+ u8 *addtl, size_t addtl_len)
120+{
121+ int err = 0;
122 int genlen = 0;
123 u8 result[MAXSIZE];
124
125@@ -82,7 +94,7 @@ static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
126 * seeding as they automatically seed. The X9.31 DRNG will return
127 * an error if it was not seeded properly.
128 */
129- genlen = crypto_rng_get_bytes(ctx->drng, result, len);
130+ genlen = crypto_rng_generate(drng, addtl, addtl_len, result, len);
131 if (genlen < 0)
132 return genlen;
133
134@@ -92,6 +104,63 @@ static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
135 return err ? err : len;
136 }
137
138+static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
139+ int flags)
140+{
141+ struct sock *sk = sock->sk;
142+ struct alg_sock *ask = alg_sk(sk);
143+ struct rng_ctx *ctx = ask->private;
144+
145+ return _rng_recvmsg(ctx->drng, msg, len, NULL, 0);
146+}
147+
148+static int rng_test_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
149+ int flags)
150+{
151+ struct sock *sk = sock->sk;
152+ struct alg_sock *ask = alg_sk(sk);
153+ struct rng_ctx *ctx = ask->private;
154+ int ret;
155+
156+ lock_sock(sock->sk);
157+ ret = _rng_recvmsg(ctx->drng, msg, len, ctx->addtl, ctx->addtl_len);
158+ rng_reset_addtl(ctx);
159+ release_sock(sock->sk);
160+
161+ return ret;
162+}
163+
164+static int rng_test_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
165+{
166+ int err;
167+ struct alg_sock *ask = alg_sk(sock->sk);
168+ struct rng_ctx *ctx = ask->private;
169+
170+ lock_sock(sock->sk);
171+ if (len > MAXSIZE) {
172+ err = -EMSGSIZE;
173+ goto unlock;
174+ }
175+
176+ rng_reset_addtl(ctx);
177+ ctx->addtl = kmalloc(len, GFP_KERNEL);
178+ if (!ctx->addtl) {
179+ err = -ENOMEM;
180+ goto unlock;
181+ }
182+
183+ err = memcpy_from_msg(ctx->addtl, msg, len);
184+ if (err) {
185+ rng_reset_addtl(ctx);
186+ goto unlock;
187+ }
188+ ctx->addtl_len = len;
189+
190+unlock:
191+ release_sock(sock->sk);
192+ return err ? err : len;
193+}
194+
195 static struct proto_ops algif_rng_ops = {
196 .family = PF_ALG,
197
198@@ -113,14 +182,53 @@ static struct proto_ops algif_rng_ops = {
199 .recvmsg = rng_recvmsg,
200 };
201
202+static struct proto_ops __maybe_unused algif_rng_test_ops = {
203+ .family = PF_ALG,
204+
205+ .connect = sock_no_connect,
206+ .socketpair = sock_no_socketpair,
207+ .getname = sock_no_getname,
208+ .ioctl = sock_no_ioctl,
209+ .listen = sock_no_listen,
210+ .shutdown = sock_no_shutdown,
211+ .mmap = sock_no_mmap,
212+ .bind = sock_no_bind,
213+ .accept = sock_no_accept,
214+ .sendpage = sock_no_sendpage,
215+
216+ .release = af_alg_release,
217+ .recvmsg = rng_test_recvmsg,
218+ .sendmsg = rng_test_sendmsg,
219+};
220+
221 static void *rng_bind(const char *name, u32 type, u32 mask)
222 {
223- return crypto_alloc_rng(name, type, mask);
224+ struct rng_parent_ctx *pctx;
225+ struct crypto_rng *rng;
226+
227+ pctx = kzalloc(sizeof(*pctx), GFP_KERNEL);
228+ if (!pctx)
229+ return ERR_PTR(-ENOMEM);
230+
231+ rng = crypto_alloc_rng(name, type, mask);
232+ if (IS_ERR(rng)) {
233+ kfree(pctx);
234+ return ERR_CAST(rng);
235+ }
236+
237+ pctx->drng = rng;
238+ return pctx;
239 }
240
241 static void rng_release(void *private)
242 {
243- crypto_free_rng(private);
244+ struct rng_parent_ctx *pctx = private;
245+ if (unlikely(!pctx))
246+ return;
247+ crypto_free_rng(pctx->drng);
248+ kzfree(pctx->entropy);
249+ kzfree(pctx);
250+ return;
251 }
252
253 static void rng_sock_destruct(struct sock *sk)
254@@ -128,6 +236,7 @@ static void rng_sock_destruct(struct sock *sk)
255 struct alg_sock *ask = alg_sk(sk);
256 struct rng_ctx *ctx = ask->private;
257
258+ rng_reset_addtl(ctx);
259 sock_kfree_s(sk, ctx, ctx->len);
260 af_alg_release_parent(sk);
261 }
262@@ -135,6 +244,7 @@ static void rng_sock_destruct(struct sock *sk)
263 static int rng_accept_parent(void *private, struct sock *sk)
264 {
265 struct rng_ctx *ctx;
266+ struct rng_parent_ctx *pctx = private;
267 struct alg_sock *ask = alg_sk(sk);
268 unsigned int len = sizeof(*ctx);
269
270@@ -143,6 +253,8 @@ static int rng_accept_parent(void *private, struct sock *sk)
271 return -ENOMEM;
272
273 ctx->len = len;
274+ ctx->addtl = NULL;
275+ ctx->addtl_len = 0;
276
277 /*
278 * No seeding done at that point -- if multiple accepts are
279@@ -150,20 +262,59 @@ static int rng_accept_parent(void *private, struct sock *sk)
280 * state of the RNG.
281 */
282
283- ctx->drng = private;
284+ ctx->drng = pctx->drng;
285 ask->private = ctx;
286 sk->sk_destruct = rng_sock_destruct;
287
288+ /*
289+ * Non NULL pctx->entropy means that CAVP test has been initiated on
290+ * this socket, replace proto_ops algif_rng_ops with algif_rng_test_ops.
291+ */
292+ if (IS_ENABLED(CONFIG_CRYPTO_USER_API_RNG_CAVP) && pctx->entropy)
293+ sk->sk_socket->ops = &algif_rng_test_ops;
294 return 0;
295 }
296
297 static int rng_setkey(void *private, const u8 *seed, unsigned int seedlen)
298 {
299+ struct rng_parent_ctx *pctx = private;
300 /*
301 * Check whether seedlen is of sufficient size is done in RNG
302 * implementations.
303 */
304- return crypto_rng_reset(private, seed, seedlen);
305+ return crypto_rng_reset(pctx->drng, seed, seedlen);
306+}
307+
308+static int __maybe_unused rng_setentropy(void *private, const u8 *entropy,
309+ unsigned int len)
310+{
311+ struct rng_parent_ctx *pctx = private;
312+ u8 *kentropy = NULL;
313+ int i;
314+
315+ if (!capable(CAP_SYS_ADMIN))
316+ return -EACCES;
317+
318+ if (pctx->entropy)
319+ return -EINVAL;
320+
321+ if (len > MAXSIZE)
322+ return -EMSGSIZE;
323+
324+ if (len) {
325+ kentropy = (u8*)kmalloc(len, GFP_KERNEL);
326+ memcpy(kentropy, entropy, len);
327+ if (IS_ERR(kentropy))
328+ return PTR_ERR(kentropy);
329+ }
330+
331+ crypto_rng_alg(pctx->drng)->set_ent(pctx->drng, kentropy, len);
332+ /*
333+ * Since rng doesn't perform any memory management for the entropy
334+ * buffer, save kentropy pointer to pctx now to free it after use.
335+ */
336+ pctx->entropy = kentropy;
337+ return 0;
338 }
339
340 static const struct af_alg_type algif_type_rng = {
341@@ -173,7 +324,10 @@ static const struct af_alg_type algif_type_rng = {
342 .setkey = rng_setkey,
343 .ops = &algif_rng_ops,
344 .name = "rng",
345- .owner = THIS_MODULE
346+ .owner = THIS_MODULE,
347+#ifdef CONFIG_CRYPTO_USER_API_RNG_CAVP
348+ .setentropy = rng_setentropy,
349+#endif
350 };
351
352 static int __init rng_init(void)
353diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
354index c1a8d4a41..ca06787f7 100644
355--- a/include/crypto/if_alg.h
356+++ b/include/crypto/if_alg.h
357@@ -46,6 +46,7 @@ struct af_alg_type {
358 void *(*bind)(const char *name, u32 type, u32 mask);
359 void (*release)(void *private);
360 int (*setkey)(void *private, const u8 *key, unsigned int keylen);
361+ int (*setentropy)(void *private, const u8 *key, unsigned int keylen);
362 int (*accept)(void *private, struct sock *sk);
363 int (*accept_nokey)(void *private, struct sock *sk);
364 int (*setauthsize)(void *private, unsigned int authsize);
365diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h
366index 769050771..dc52a11ba 100644
367--- a/include/uapi/linux/if_alg.h
368+++ b/include/uapi/linux/if_alg.h
369@@ -51,6 +51,7 @@ struct af_alg_iv {
370 #define ALG_SET_OP 3
371 #define ALG_SET_AEAD_ASSOCLEN 4
372 #define ALG_SET_AEAD_AUTHSIZE 5
373+#define ALG_SET_DRBG_ENTROPY 6
374
375 /* Operations */
376 #define ALG_OP_DECRYPT 0