crypto: shash - Fix has_key setting
[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 = 0;
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         lock_sock(sk);
264         if (ask->refcnt)
265                 goto unlock_child;
266
267         psk = ask->parent;
268         pask = alg_sk(ask->parent);
269         tfm = pask->private;
270
271         err = -ENOKEY;
272         lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
273         if (!tfm->has_key)
274                 goto unlock;
275
276         if (!pask->refcnt++)
277                 sock_hold(psk);
278
279         ask->refcnt = 1;
280         sock_put(psk);
281
282         err = 0;
283
284 unlock:
285         release_sock(psk);
286 unlock_child:
287         release_sock(sk);
288
289         return err;
290 }
291
292 static int hash_sendmsg_nokey(struct kiocb *unused, struct socket *sock,
293                               struct msghdr *msg, size_t size)
294 {
295         int err;
296
297         err = hash_check_key(sock);
298         if (err)
299                 return err;
300
301         return hash_sendmsg(unused, sock, msg, size);
302 }
303
304 static ssize_t hash_sendpage_nokey(struct socket *sock, struct page *page,
305                                    int offset, size_t size, int flags)
306 {
307         int err;
308
309         err = hash_check_key(sock);
310         if (err)
311                 return err;
312
313         return hash_sendpage(sock, page, offset, size, flags);
314 }
315
316 static int hash_recvmsg_nokey(struct kiocb *unused, struct socket *sock,
317                               struct msghdr *msg, size_t ignored, int flags)
318 {
319         int err;
320
321         err = hash_check_key(sock);
322         if (err)
323                 return err;
324
325         return hash_recvmsg(unused, sock, msg, ignored, flags);
326 }
327
328 static int hash_accept_nokey(struct socket *sock, struct socket *newsock,
329                              int flags)
330 {
331         int err;
332
333         err = hash_check_key(sock);
334         if (err)
335                 return err;
336
337         return hash_accept(sock, newsock, flags);
338 }
339
340 static struct proto_ops algif_hash_ops_nokey = {
341         .family         =       PF_ALG,
342
343         .connect        =       sock_no_connect,
344         .socketpair     =       sock_no_socketpair,
345         .getname        =       sock_no_getname,
346         .ioctl          =       sock_no_ioctl,
347         .listen         =       sock_no_listen,
348         .shutdown       =       sock_no_shutdown,
349         .getsockopt     =       sock_no_getsockopt,
350         .mmap           =       sock_no_mmap,
351         .bind           =       sock_no_bind,
352         .setsockopt     =       sock_no_setsockopt,
353         .poll           =       sock_no_poll,
354
355         .release        =       af_alg_release,
356         .sendmsg        =       hash_sendmsg_nokey,
357         .sendpage       =       hash_sendpage_nokey,
358         .recvmsg        =       hash_recvmsg_nokey,
359         .accept         =       hash_accept_nokey,
360 };
361
362 static void *hash_bind(const char *name, u32 type, u32 mask)
363 {
364         struct algif_hash_tfm *tfm;
365         struct crypto_ahash *hash;
366
367         tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
368         if (!tfm)
369                 return ERR_PTR(-ENOMEM);
370
371         hash = crypto_alloc_ahash(name, type, mask);
372         if (IS_ERR(hash)) {
373                 kfree(tfm);
374                 return ERR_CAST(hash);
375         }
376
377         tfm->hash = hash;
378
379         return tfm;
380 }
381
382 static void hash_release(void *private)
383 {
384         struct algif_hash_tfm *tfm = private;
385
386         crypto_free_ahash(tfm->hash);
387         kfree(tfm);
388 }
389
390 static int hash_setkey(void *private, const u8 *key, unsigned int keylen)
391 {
392         struct algif_hash_tfm *tfm = private;
393         int err;
394
395         err = crypto_ahash_setkey(tfm->hash, key, keylen);
396         tfm->has_key = !err;
397
398         return err;
399 }
400
401 static void hash_sock_destruct(struct sock *sk)
402 {
403         struct alg_sock *ask = alg_sk(sk);
404         struct hash_ctx *ctx = ask->private;
405
406         sock_kfree_s(sk, ctx->result,
407                      crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req)));
408         sock_kfree_s(sk, ctx, ctx->len);
409         af_alg_release_parent(sk);
410 }
411
412 static int hash_accept_parent_nokey(void *private, struct sock *sk)
413 {
414         struct hash_ctx *ctx;
415         struct alg_sock *ask = alg_sk(sk);
416         struct algif_hash_tfm *tfm = private;
417         struct crypto_ahash *hash = tfm->hash;
418         unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(hash);
419         unsigned ds = crypto_ahash_digestsize(hash);
420
421         ctx = sock_kmalloc(sk, len, GFP_KERNEL);
422         if (!ctx)
423                 return -ENOMEM;
424
425         ctx->result = sock_kmalloc(sk, ds, GFP_KERNEL);
426         if (!ctx->result) {
427                 sock_kfree_s(sk, ctx, len);
428                 return -ENOMEM;
429         }
430
431         memset(ctx->result, 0, ds);
432
433         ctx->len = len;
434         ctx->more = 0;
435         af_alg_init_completion(&ctx->completion);
436
437         ask->private = ctx;
438
439         ahash_request_set_tfm(&ctx->req, hash);
440         ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
441                                    af_alg_complete, &ctx->completion);
442
443         sk->sk_destruct = hash_sock_destruct;
444
445         return 0;
446 }
447
448 static int hash_accept_parent(void *private, struct sock *sk)
449 {
450         struct algif_hash_tfm *tfm = private;
451
452         if (!tfm->has_key && crypto_ahash_has_setkey(tfm->hash))
453                 return -ENOKEY;
454
455         return hash_accept_parent_nokey(private, sk);
456 }
457
458 static const struct af_alg_type algif_type_hash = {
459         .bind           =       hash_bind,
460         .release        =       hash_release,
461         .setkey         =       hash_setkey,
462         .accept         =       hash_accept_parent,
463         .accept_nokey   =       hash_accept_parent_nokey,
464         .ops            =       &algif_hash_ops,
465         .ops_nokey      =       &algif_hash_ops_nokey,
466         .name           =       "hash",
467         .owner          =       THIS_MODULE
468 };
469
470 static int __init algif_hash_init(void)
471 {
472         return af_alg_register_type(&algif_type_hash);
473 }
474
475 static void __exit algif_hash_exit(void)
476 {
477         int err = af_alg_unregister_type(&algif_type_hash);
478         BUG_ON(err);
479 }
480
481 module_init(algif_hash_init);
482 module_exit(algif_hash_exit);
483 MODULE_LICENSE("GPL");