crypto: algif_skcipher - Add key check exception for cipher_null
[pandora-kernel.git] / crypto / algif_hash.c
1 /*
2  * algif_hash: User-space interface for hash algorithms
3  *
4  * This file provides the user-space API for hash algorithms.
5  *
6  * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the Free
10  * Software Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  *
13  */
14
15 #include <crypto/hash.h>
16 #include <crypto/if_alg.h>
17 #include <linux/init.h>
18 #include <linux/kernel.h>
19 #include <linux/mm.h>
20 #include <linux/module.h>
21 #include <linux/net.h>
22 #include <net/sock.h>
23
24 struct hash_ctx {
25         struct af_alg_sgl sgl;
26
27         u8 *result;
28
29         struct af_alg_completion completion;
30
31         unsigned int len;
32         bool more;
33
34         struct ahash_request req;
35 };
36
37 struct algif_hash_tfm {
38         struct crypto_ahash *hash;
39         bool has_key;
40 };
41
42 static int hash_sendmsg(struct kiocb *unused, struct socket *sock,
43                         struct msghdr *msg, size_t ignored)
44 {
45         int limit = ALG_MAX_PAGES * PAGE_SIZE;
46         struct sock *sk = sock->sk;
47         struct alg_sock *ask = alg_sk(sk);
48         struct hash_ctx *ctx = ask->private;
49         unsigned long iovlen;
50         struct iovec *iov;
51         long copied = 0;
52         int err;
53
54         if (limit > sk->sk_sndbuf)
55                 limit = sk->sk_sndbuf;
56
57         lock_sock(sk);
58         if (!ctx->more) {
59                 err = crypto_ahash_init(&ctx->req);
60                 if (err)
61                         goto unlock;
62         }
63
64         ctx->more = 0;
65
66         for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0;
67              iovlen--, iov++) {
68                 unsigned long seglen = iov->iov_len;
69                 char __user *from = iov->iov_base;
70
71                 while (seglen) {
72                         int len = min_t(unsigned long, seglen, limit);
73                         int newlen;
74
75                         newlen = af_alg_make_sg(&ctx->sgl, from, len, 0);
76                         if (newlen < 0) {
77                                 err = copied ? 0 : newlen;
78                                 goto unlock;
79                         }
80
81                         ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, NULL,
82                                                 newlen);
83
84                         err = af_alg_wait_for_completion(
85                                 crypto_ahash_update(&ctx->req),
86                                 &ctx->completion);
87
88                         af_alg_free_sg(&ctx->sgl);
89
90                         if (err)
91                                 goto unlock;
92
93                         seglen -= newlen;
94                         from += newlen;
95                         copied += newlen;
96                 }
97         }
98
99         err = 0;
100
101         ctx->more = msg->msg_flags & MSG_MORE;
102         if (!ctx->more) {
103                 ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0);
104                 err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req),
105                                                  &ctx->completion);
106         }
107
108 unlock:
109         release_sock(sk);
110
111         return err ?: copied;
112 }
113
114 static ssize_t hash_sendpage(struct socket *sock, struct page *page,
115                              int offset, size_t size, int flags)
116 {
117         struct sock *sk = sock->sk;
118         struct alg_sock *ask = alg_sk(sk);
119         struct hash_ctx *ctx = ask->private;
120         int err;
121
122         if (flags & MSG_SENDPAGE_NOTLAST)
123                 flags |= MSG_MORE;
124
125         lock_sock(sk);
126         sg_init_table(ctx->sgl.sg, 1);
127         sg_set_page(ctx->sgl.sg, page, size, offset);
128
129         ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, ctx->result, size);
130
131         if (!(flags & MSG_MORE)) {
132                 if (ctx->more)
133                         err = crypto_ahash_finup(&ctx->req);
134                 else
135                         err = crypto_ahash_digest(&ctx->req);
136         } else {
137                 if (!ctx->more) {
138                         err = crypto_ahash_init(&ctx->req);
139                         if (err)
140                                 goto unlock;
141                 }
142
143                 err = crypto_ahash_update(&ctx->req);
144         }
145
146         err = af_alg_wait_for_completion(err, &ctx->completion);
147         if (err)
148                 goto unlock;
149
150         ctx->more = flags & MSG_MORE;
151
152 unlock:
153         release_sock(sk);
154
155         return err ?: size;
156 }
157
158 static int hash_recvmsg(struct kiocb *unused, struct socket *sock,
159                         struct msghdr *msg, size_t len, int flags)
160 {
161         struct sock *sk = sock->sk;
162         struct alg_sock *ask = alg_sk(sk);
163         struct hash_ctx *ctx = ask->private;
164         unsigned ds = crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req));
165         int err;
166
167         if (len > ds)
168                 len = ds;
169         else if (len < ds)
170                 msg->msg_flags |= MSG_TRUNC;
171
172         lock_sock(sk);
173         if (ctx->more) {
174                 ctx->more = 0;
175                 ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0);
176                 err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req),
177                                                  &ctx->completion);
178                 if (err)
179                         goto unlock;
180         }
181
182         err = memcpy_toiovec(msg->msg_iov, ctx->result, len);
183
184 unlock:
185         release_sock(sk);
186
187         return err ?: len;
188 }
189
190 static int hash_accept(struct socket *sock, struct socket *newsock, int flags)
191 {
192         struct sock *sk = sock->sk;
193         struct alg_sock *ask = alg_sk(sk);
194         struct hash_ctx *ctx = ask->private;
195         struct ahash_request *req = &ctx->req;
196         char state[crypto_ahash_statesize(crypto_ahash_reqtfm(req))];
197         struct sock *sk2;
198         struct alg_sock *ask2;
199         struct hash_ctx *ctx2;
200         bool more;
201         int err;
202
203         lock_sock(sk);
204         more = ctx->more;
205         err = more ? crypto_ahash_export(req, state) : 0;
206         release_sock(sk);
207
208         if (err)
209                 return err;
210
211         err = af_alg_accept(ask->parent, newsock);
212         if (err)
213                 return err;
214
215         sk2 = newsock->sk;
216         ask2 = alg_sk(sk2);
217         ctx2 = ask2->private;
218         ctx2->more = more;
219
220         if (!more)
221                 return err;
222
223         err = crypto_ahash_import(&ctx2->req, state);
224         if (err) {
225                 sock_orphan(sk2);
226                 sock_put(sk2);
227         }
228
229         return err;
230 }
231
232 static struct proto_ops algif_hash_ops = {
233         .family         =       PF_ALG,
234
235         .connect        =       sock_no_connect,
236         .socketpair     =       sock_no_socketpair,
237         .getname        =       sock_no_getname,
238         .ioctl          =       sock_no_ioctl,
239         .listen         =       sock_no_listen,
240         .shutdown       =       sock_no_shutdown,
241         .getsockopt     =       sock_no_getsockopt,
242         .mmap           =       sock_no_mmap,
243         .bind           =       sock_no_bind,
244         .setsockopt     =       sock_no_setsockopt,
245         .poll           =       sock_no_poll,
246
247         .release        =       af_alg_release,
248         .sendmsg        =       hash_sendmsg,
249         .sendpage       =       hash_sendpage,
250         .recvmsg        =       hash_recvmsg,
251         .accept         =       hash_accept,
252 };
253
254 static int hash_check_key(struct socket *sock)
255 {
256         int err;
257         struct sock *psk;
258         struct alg_sock *pask;
259         struct algif_hash_tfm *tfm;
260         struct sock *sk = sock->sk;
261         struct alg_sock *ask = alg_sk(sk);
262
263         if (ask->refcnt)
264                 return 0;
265
266         psk = ask->parent;
267         pask = alg_sk(ask->parent);
268         tfm = pask->private;
269
270         err = -ENOKEY;
271         lock_sock(psk);
272         if (!tfm->has_key)
273                 goto unlock;
274
275         if (!pask->refcnt++)
276                 sock_hold(psk);
277
278         ask->refcnt = 1;
279         sock_put(psk);
280
281         err = 0;
282
283 unlock:
284         release_sock(psk);
285
286         return err;
287 }
288
289 static int hash_sendmsg_nokey(struct kiocb *unused, struct socket *sock,
290                               struct msghdr *msg, size_t size)
291 {
292         int err;
293
294         err = hash_check_key(sock);
295         if (err)
296                 return err;
297
298         return hash_sendmsg(unused, sock, msg, size);
299 }
300
301 static ssize_t hash_sendpage_nokey(struct socket *sock, struct page *page,
302                                    int offset, size_t size, int flags)
303 {
304         int err;
305
306         err = hash_check_key(sock);
307         if (err)
308                 return err;
309
310         return hash_sendpage(sock, page, offset, size, flags);
311 }
312
313 static int hash_recvmsg_nokey(struct kiocb *unused, struct socket *sock,
314                               struct msghdr *msg, size_t ignored, int flags)
315 {
316         int err;
317
318         err = hash_check_key(sock);
319         if (err)
320                 return err;
321
322         return hash_recvmsg(unused, sock, msg, ignored, flags);
323 }
324
325 static int hash_accept_nokey(struct socket *sock, struct socket *newsock,
326                              int flags)
327 {
328         int err;
329
330         err = hash_check_key(sock);
331         if (err)
332                 return err;
333
334         return hash_accept(sock, newsock, flags);
335 }
336
337 static struct proto_ops algif_hash_ops_nokey = {
338         .family         =       PF_ALG,
339
340         .connect        =       sock_no_connect,
341         .socketpair     =       sock_no_socketpair,
342         .getname        =       sock_no_getname,
343         .ioctl          =       sock_no_ioctl,
344         .listen         =       sock_no_listen,
345         .shutdown       =       sock_no_shutdown,
346         .getsockopt     =       sock_no_getsockopt,
347         .mmap           =       sock_no_mmap,
348         .bind           =       sock_no_bind,
349         .setsockopt     =       sock_no_setsockopt,
350         .poll           =       sock_no_poll,
351
352         .release        =       af_alg_release,
353         .sendmsg        =       hash_sendmsg_nokey,
354         .sendpage       =       hash_sendpage_nokey,
355         .recvmsg        =       hash_recvmsg_nokey,
356         .accept         =       hash_accept_nokey,
357 };
358
359 static void *hash_bind(const char *name, u32 type, u32 mask)
360 {
361         struct algif_hash_tfm *tfm;
362         struct crypto_ahash *hash;
363
364         tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
365         if (!tfm)
366                 return ERR_PTR(-ENOMEM);
367
368         hash = crypto_alloc_ahash(name, type, mask);
369         if (IS_ERR(hash)) {
370                 kfree(tfm);
371                 return ERR_CAST(hash);
372         }
373
374         tfm->hash = hash;
375
376         return tfm;
377 }
378
379 static void hash_release(void *private)
380 {
381         struct algif_hash_tfm *tfm = private;
382
383         crypto_free_ahash(tfm->hash);
384         kfree(tfm);
385 }
386
387 static int hash_setkey(void *private, const u8 *key, unsigned int keylen)
388 {
389         struct algif_hash_tfm *tfm = private;
390         int err;
391
392         err = crypto_ahash_setkey(tfm->hash, key, keylen);
393         tfm->has_key = !err;
394
395         return err;
396 }
397
398 static void hash_sock_destruct_common(struct sock *sk)
399 {
400         struct alg_sock *ask = alg_sk(sk);
401         struct hash_ctx *ctx = ask->private;
402
403         sock_kfree_s(sk, ctx->result,
404                      crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req)));
405         sock_kfree_s(sk, ctx, ctx->len);
406 }
407
408 static void hash_sock_destruct(struct sock *sk)
409 {
410         hash_sock_destruct_common(sk);
411         af_alg_release_parent(sk);
412 }
413
414 static void hash_release_parent_nokey(struct sock *sk)
415 {
416         struct alg_sock *ask = alg_sk(sk);
417
418         if (!ask->refcnt) {
419                 sock_put(ask->parent);
420                 return;
421         }
422
423         af_alg_release_parent(sk);
424 }
425
426 static void hash_sock_destruct_nokey(struct sock *sk)
427 {
428         hash_sock_destruct_common(sk);
429         hash_release_parent_nokey(sk);
430 }
431
432 static int hash_accept_parent_common(void *private, struct sock *sk)
433 {
434         struct hash_ctx *ctx;
435         struct alg_sock *ask = alg_sk(sk);
436         struct algif_hash_tfm *tfm = private;
437         struct crypto_ahash *hash = tfm->hash;
438         unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(hash);
439         unsigned ds = crypto_ahash_digestsize(hash);
440
441         ctx = sock_kmalloc(sk, len, GFP_KERNEL);
442         if (!ctx)
443                 return -ENOMEM;
444
445         ctx->result = sock_kmalloc(sk, ds, GFP_KERNEL);
446         if (!ctx->result) {
447                 sock_kfree_s(sk, ctx, len);
448                 return -ENOMEM;
449         }
450
451         memset(ctx->result, 0, ds);
452
453         ctx->len = len;
454         ctx->more = 0;
455         af_alg_init_completion(&ctx->completion);
456
457         ask->private = ctx;
458
459         ahash_request_set_tfm(&ctx->req, hash);
460         ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
461                                    af_alg_complete, &ctx->completion);
462
463         sk->sk_destruct = hash_sock_destruct;
464
465         return 0;
466 }
467
468 static int hash_accept_parent(void *private, struct sock *sk)
469 {
470         struct algif_hash_tfm *tfm = private;
471
472         if (!tfm->has_key && crypto_ahash_has_setkey(tfm->hash))
473                 return -ENOKEY;
474
475         return hash_accept_parent_common(private, sk);
476 }
477
478 static int hash_accept_parent_nokey(void *private, struct sock *sk)
479 {
480         int err;
481
482         err = hash_accept_parent_common(private, sk);
483         if (err)
484                 goto out;
485
486         sk->sk_destruct = hash_sock_destruct_nokey;
487
488 out:
489         return err;
490 }
491
492 static const struct af_alg_type algif_type_hash = {
493         .bind           =       hash_bind,
494         .release        =       hash_release,
495         .setkey         =       hash_setkey,
496         .accept         =       hash_accept_parent,
497         .accept_nokey   =       hash_accept_parent_nokey,
498         .ops            =       &algif_hash_ops,
499         .ops_nokey      =       &algif_hash_ops_nokey,
500         .name           =       "hash",
501         .owner          =       THIS_MODULE
502 };
503
504 static int __init algif_hash_init(void)
505 {
506         return af_alg_register_type(&algif_type_hash);
507 }
508
509 static void __exit algif_hash_exit(void)
510 {
511         int err = af_alg_unregister_type(&algif_type_hash);
512         BUG_ON(err);
513 }
514
515 module_init(algif_hash_init);
516 module_exit(algif_hash_exit);
517 MODULE_LICENSE("GPL");