1 /*
2  * 2007+ Copyright (c) Evgeniy Polyakov <zbr@ioremap.net>
3  * All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15 
16 #include <linux/crypto.h>
17 #include <linux/highmem.h>
18 #include <linux/kthread.h>
19 #include <linux/pagemap.h>
20 #include <linux/slab.h>
21 
22 #include "netfs.h"
23 
pohmelfs_init_hash(struct pohmelfs_sb * psb)24 static struct crypto_hash *pohmelfs_init_hash(struct pohmelfs_sb *psb)
25 {
26 	int err;
27 	struct crypto_hash *hash;
28 
29 	hash = crypto_alloc_hash(psb->hash_string, 0, CRYPTO_ALG_ASYNC);
30 	if (IS_ERR(hash)) {
31 		err = PTR_ERR(hash);
32 		dprintk("%s: idx: %u: failed to allocate hash '%s', err: %d.\n",
33 				__func__, psb->idx, psb->hash_string, err);
34 		goto err_out_exit;
35 	}
36 
37 	psb->crypto_attached_size = crypto_hash_digestsize(hash);
38 
39 	if (!psb->hash_keysize)
40 		return hash;
41 
42 	err = crypto_hash_setkey(hash, psb->hash_key, psb->hash_keysize);
43 	if (err) {
44 		dprintk("%s: idx: %u: failed to set key for hash '%s', err: %d.\n",
45 				__func__, psb->idx, psb->hash_string, err);
46 		goto err_out_free;
47 	}
48 
49 	return hash;
50 
51 err_out_free:
52 	crypto_free_hash(hash);
53 err_out_exit:
54 	return ERR_PTR(err);
55 }
56 
pohmelfs_init_cipher(struct pohmelfs_sb * psb)57 static struct crypto_ablkcipher *pohmelfs_init_cipher(struct pohmelfs_sb *psb)
58 {
59 	int err = -EINVAL;
60 	struct crypto_ablkcipher *cipher;
61 
62 	if (!psb->cipher_keysize)
63 		goto err_out_exit;
64 
65 	cipher = crypto_alloc_ablkcipher(psb->cipher_string, 0, 0);
66 	if (IS_ERR(cipher)) {
67 		err = PTR_ERR(cipher);
68 		dprintk("%s: idx: %u: failed to allocate cipher '%s', err: %d.\n",
69 				__func__, psb->idx, psb->cipher_string, err);
70 		goto err_out_exit;
71 	}
72 
73 	crypto_ablkcipher_clear_flags(cipher, ~0);
74 
75 	err = crypto_ablkcipher_setkey(cipher, psb->cipher_key, psb->cipher_keysize);
76 	if (err) {
77 		dprintk("%s: idx: %u: failed to set key for cipher '%s', err: %d.\n",
78 				__func__, psb->idx, psb->cipher_string, err);
79 		goto err_out_free;
80 	}
81 
82 	return cipher;
83 
84 err_out_free:
85 	crypto_free_ablkcipher(cipher);
86 err_out_exit:
87 	return ERR_PTR(err);
88 }
89 
pohmelfs_crypto_engine_init(struct pohmelfs_crypto_engine * e,struct pohmelfs_sb * psb)90 int pohmelfs_crypto_engine_init(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb)
91 {
92 	int err;
93 
94 	e->page_num = 0;
95 
96 	e->size = PAGE_SIZE;
97 	e->data = kmalloc(e->size, GFP_KERNEL);
98 	if (!e->data) {
99 		err = -ENOMEM;
100 		goto err_out_exit;
101 	}
102 
103 	if (psb->hash_string) {
104 		e->hash = pohmelfs_init_hash(psb);
105 		if (IS_ERR(e->hash)) {
106 			err = PTR_ERR(e->hash);
107 			e->hash = NULL;
108 			goto err_out_free;
109 		}
110 	}
111 
112 	if (psb->cipher_string) {
113 		e->cipher = pohmelfs_init_cipher(psb);
114 		if (IS_ERR(e->cipher)) {
115 			err = PTR_ERR(e->cipher);
116 			e->cipher = NULL;
117 			goto err_out_free_hash;
118 		}
119 	}
120 
121 	return 0;
122 
123 err_out_free_hash:
124 	crypto_free_hash(e->hash);
125 err_out_free:
126 	kfree(e->data);
127 err_out_exit:
128 	return err;
129 }
130 
pohmelfs_crypto_engine_exit(struct pohmelfs_crypto_engine * e)131 void pohmelfs_crypto_engine_exit(struct pohmelfs_crypto_engine *e)
132 {
133 	crypto_free_hash(e->hash);
134 	crypto_free_ablkcipher(e->cipher);
135 	kfree(e->data);
136 }
137 
pohmelfs_crypto_complete(struct crypto_async_request * req,int err)138 static void pohmelfs_crypto_complete(struct crypto_async_request *req, int err)
139 {
140 	struct pohmelfs_crypto_completion *c = req->data;
141 
142 	if (err == -EINPROGRESS)
143 		return;
144 
145 	dprintk("%s: req: %p, err: %d.\n", __func__, req, err);
146 	c->error = err;
147 	complete(&c->complete);
148 }
149 
pohmelfs_crypto_process(struct ablkcipher_request * req,struct scatterlist * sg_dst,struct scatterlist * sg_src,void * iv,int enc,unsigned long timeout)150 static int pohmelfs_crypto_process(struct ablkcipher_request *req,
151 		struct scatterlist *sg_dst, struct scatterlist *sg_src,
152 		void *iv, int enc, unsigned long timeout)
153 {
154 	struct pohmelfs_crypto_completion complete;
155 	int err;
156 
157 	init_completion(&complete.complete);
158 	complete.error = -EINPROGRESS;
159 
160 	ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
161 					pohmelfs_crypto_complete, &complete);
162 
163 	ablkcipher_request_set_crypt(req, sg_src, sg_dst, sg_src->length, iv);
164 
165 	if (enc)
166 		err = crypto_ablkcipher_encrypt(req);
167 	else
168 		err = crypto_ablkcipher_decrypt(req);
169 
170 	switch (err) {
171 	case -EINPROGRESS:
172 	case -EBUSY:
173 		err = wait_for_completion_interruptible_timeout(&complete.complete,
174 					timeout);
175 		if (!err)
176 			err = -ETIMEDOUT;
177 		else if (err > 0)
178 			err = complete.error;
179 		break;
180 	default:
181 		break;
182 	}
183 
184 	return err;
185 }
186 
pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine * e,u64 cmd_iv,void * data,struct page * page,unsigned int size)187 int pohmelfs_crypto_process_input_data(struct pohmelfs_crypto_engine *e, u64 cmd_iv,
188 		void *data, struct page *page, unsigned int size)
189 {
190 	int err;
191 	struct scatterlist sg;
192 
193 	if (!e->cipher && !e->hash)
194 		return 0;
195 
196 	dprintk("%s: eng: %p, iv: %llx, data: %p, page: %p/%lu, size: %u.\n",
197 		__func__, e, cmd_iv, data, page, (page) ? page->index : 0, size);
198 
199 	if (data) {
200 		sg_init_one(&sg, data, size);
201 	} else {
202 		sg_init_table(&sg, 1);
203 		sg_set_page(&sg, page, size, 0);
204 	}
205 
206 	if (e->cipher) {
207 		struct ablkcipher_request *req = e->data + crypto_hash_digestsize(e->hash);
208 		u8 iv[32];
209 
210 		memset(iv, 0, sizeof(iv));
211 		memcpy(iv, &cmd_iv, sizeof(cmd_iv));
212 
213 		ablkcipher_request_set_tfm(req, e->cipher);
214 
215 		err = pohmelfs_crypto_process(req, &sg, &sg, iv, 0, e->timeout);
216 		if (err)
217 			goto err_out_exit;
218 	}
219 
220 	if (e->hash) {
221 		struct hash_desc desc;
222 		void *dst = e->data + e->size/2;
223 
224 		desc.tfm = e->hash;
225 		desc.flags = 0;
226 
227 		err = crypto_hash_init(&desc);
228 		if (err)
229 			goto err_out_exit;
230 
231 		err = crypto_hash_update(&desc, &sg, size);
232 		if (err)
233 			goto err_out_exit;
234 
235 		err = crypto_hash_final(&desc, dst);
236 		if (err)
237 			goto err_out_exit;
238 
239 		err = !!memcmp(dst, e->data, crypto_hash_digestsize(e->hash));
240 
241 		if (err) {
242 #ifdef CONFIG_POHMELFS_DEBUG
243 			unsigned int i;
244 			unsigned char *recv = e->data, *calc = dst;
245 
246 			dprintk("%s: eng: %p, hash: %p, cipher: %p: iv : %llx, hash mismatch (recv/calc): ",
247 					__func__, e, e->hash, e->cipher, cmd_iv);
248 			for (i = 0; i < crypto_hash_digestsize(e->hash); ++i) {
249 #if 0
250 				dprintka("%02x ", recv[i]);
251 				if (recv[i] != calc[i]) {
252 					dprintka("| calc byte: %02x.\n", calc[i]);
253 					break;
254 				}
255 #else
256 				dprintka("%02x/%02x ", recv[i], calc[i]);
257 #endif
258 			}
259 			dprintk("\n");
260 #endif
261 			goto err_out_exit;
262 		} else {
263 			dprintk("%s: eng: %p, hash: %p, cipher: %p: hashes matched.\n",
264 					__func__, e, e->hash, e->cipher);
265 		}
266 	}
267 
268 	dprintk("%s: eng: %p, size: %u, hash: %p, cipher: %p: completed.\n",
269 			__func__, e, e->size, e->hash, e->cipher);
270 
271 	return 0;
272 
273 err_out_exit:
274 	dprintk("%s: eng: %p, hash: %p, cipher: %p: err: %d.\n",
275 			__func__, e, e->hash, e->cipher, err);
276 	return err;
277 }
278 
pohmelfs_trans_iter(struct netfs_trans * t,struct pohmelfs_crypto_engine * e,int (* iterator)(struct pohmelfs_crypto_engine * e,struct scatterlist * dst,struct scatterlist * src))279 static int pohmelfs_trans_iter(struct netfs_trans *t, struct pohmelfs_crypto_engine *e,
280 		int (*iterator) (struct pohmelfs_crypto_engine *e,
281 				  struct scatterlist *dst,
282 				  struct scatterlist *src))
283 {
284 	void *data = t->iovec.iov_base + sizeof(struct netfs_cmd) + t->psb->crypto_attached_size;
285 	unsigned int size = t->iovec.iov_len - sizeof(struct netfs_cmd) - t->psb->crypto_attached_size;
286 	struct netfs_cmd *cmd = data;
287 	unsigned int sz, pages = t->attached_pages, i, csize, cmd_cmd, dpage_idx;
288 	struct scatterlist sg_src, sg_dst;
289 	int err;
290 
291 	while (size) {
292 		cmd = data;
293 		cmd_cmd = __be16_to_cpu(cmd->cmd);
294 		csize = __be32_to_cpu(cmd->size);
295 		cmd->iv = __cpu_to_be64(e->iv);
296 
297 		if (cmd_cmd == NETFS_READ_PAGES || cmd_cmd == NETFS_READ_PAGE)
298 			csize = __be16_to_cpu(cmd->ext);
299 
300 		sz = csize + __be16_to_cpu(cmd->cpad) + sizeof(struct netfs_cmd);
301 
302 		dprintk("%s: size: %u, sz: %u, cmd_size: %u, cmd_cpad: %u.\n",
303 				__func__, size, sz, __be32_to_cpu(cmd->size), __be16_to_cpu(cmd->cpad));
304 
305 		data += sz;
306 		size -= sz;
307 
308 		sg_init_one(&sg_src, cmd->data, sz - sizeof(struct netfs_cmd));
309 		sg_init_one(&sg_dst, cmd->data, sz - sizeof(struct netfs_cmd));
310 
311 		err = iterator(e, &sg_dst, &sg_src);
312 		if (err)
313 			return err;
314 	}
315 
316 	if (!pages)
317 		return 0;
318 
319 	dpage_idx = 0;
320 	for (i = 0; i < t->page_num; ++i) {
321 		struct page *page = t->pages[i];
322 		struct page *dpage = e->pages[dpage_idx];
323 
324 		if (!page)
325 			continue;
326 
327 		sg_init_table(&sg_src, 1);
328 		sg_init_table(&sg_dst, 1);
329 		sg_set_page(&sg_src, page, page_private(page), 0);
330 		sg_set_page(&sg_dst, dpage, page_private(page), 0);
331 
332 		err = iterator(e, &sg_dst, &sg_src);
333 		if (err)
334 			return err;
335 
336 		pages--;
337 		if (!pages)
338 			break;
339 		dpage_idx++;
340 	}
341 
342 	return 0;
343 }
344 
pohmelfs_encrypt_iterator(struct pohmelfs_crypto_engine * e,struct scatterlist * sg_dst,struct scatterlist * sg_src)345 static int pohmelfs_encrypt_iterator(struct pohmelfs_crypto_engine *e,
346 		struct scatterlist *sg_dst, struct scatterlist *sg_src)
347 {
348 	struct ablkcipher_request *req = e->data;
349 	u8 iv[32];
350 
351 	memset(iv, 0, sizeof(iv));
352 
353 	memcpy(iv, &e->iv, sizeof(e->iv));
354 
355 	return pohmelfs_crypto_process(req, sg_dst, sg_src, iv, 1, e->timeout);
356 }
357 
pohmelfs_encrypt(struct pohmelfs_crypto_thread * tc)358 static int pohmelfs_encrypt(struct pohmelfs_crypto_thread *tc)
359 {
360 	struct netfs_trans *t = tc->trans;
361 	struct pohmelfs_crypto_engine *e = &tc->eng;
362 	struct ablkcipher_request *req = e->data;
363 
364 	memset(req, 0, sizeof(struct ablkcipher_request));
365 	ablkcipher_request_set_tfm(req, e->cipher);
366 
367 	e->iv = pohmelfs_gen_iv(t);
368 
369 	return pohmelfs_trans_iter(t, e, pohmelfs_encrypt_iterator);
370 }
371 
pohmelfs_hash_iterator(struct pohmelfs_crypto_engine * e,struct scatterlist * sg_dst,struct scatterlist * sg_src)372 static int pohmelfs_hash_iterator(struct pohmelfs_crypto_engine *e,
373 		struct scatterlist *sg_dst, struct scatterlist *sg_src)
374 {
375 	return crypto_hash_update(e->data, sg_src, sg_src->length);
376 }
377 
pohmelfs_hash(struct pohmelfs_crypto_thread * tc)378 static int pohmelfs_hash(struct pohmelfs_crypto_thread *tc)
379 {
380 	struct pohmelfs_crypto_engine *e = &tc->eng;
381 	struct hash_desc *desc = e->data;
382 	unsigned char *dst = tc->trans->iovec.iov_base + sizeof(struct netfs_cmd);
383 	int err;
384 
385 	desc->tfm = e->hash;
386 	desc->flags = 0;
387 
388 	err = crypto_hash_init(desc);
389 	if (err)
390 		return err;
391 
392 	err = pohmelfs_trans_iter(tc->trans, e, pohmelfs_hash_iterator);
393 	if (err)
394 		return err;
395 
396 	err = crypto_hash_final(desc, dst);
397 	if (err)
398 		return err;
399 
400 	{
401 		unsigned int i;
402 		dprintk("%s: ", __func__);
403 		for (i = 0; i < tc->psb->crypto_attached_size; ++i)
404 			dprintka("%02x ", dst[i]);
405 		dprintka("\n");
406 	}
407 
408 	return 0;
409 }
410 
pohmelfs_crypto_pages_free(struct pohmelfs_crypto_engine * e)411 static void pohmelfs_crypto_pages_free(struct pohmelfs_crypto_engine *e)
412 {
413 	unsigned int i;
414 
415 	for (i = 0; i < e->page_num; ++i)
416 		__free_page(e->pages[i]);
417 	kfree(e->pages);
418 }
419 
pohmelfs_crypto_pages_alloc(struct pohmelfs_crypto_engine * e,struct pohmelfs_sb * psb)420 static int pohmelfs_crypto_pages_alloc(struct pohmelfs_crypto_engine *e, struct pohmelfs_sb *psb)
421 {
422 	unsigned int i;
423 
424 	e->pages = kmalloc(psb->trans_max_pages * sizeof(struct page *), GFP_KERNEL);
425 	if (!e->pages)
426 		return -ENOMEM;
427 
428 	for (i = 0; i < psb->trans_max_pages; ++i) {
429 		e->pages[i] = alloc_page(GFP_KERNEL);
430 		if (!e->pages[i])
431 			break;
432 	}
433 
434 	e->page_num = i;
435 	if (!e->page_num)
436 		goto err_out_free;
437 
438 	return 0;
439 
440 err_out_free:
441 	kfree(e->pages);
442 	return -ENOMEM;
443 }
444 
pohmelfs_sys_crypto_exit_one(struct pohmelfs_crypto_thread * t)445 static void pohmelfs_sys_crypto_exit_one(struct pohmelfs_crypto_thread *t)
446 {
447 	struct pohmelfs_sb *psb = t->psb;
448 
449 	if (t->thread)
450 		kthread_stop(t->thread);
451 
452 	mutex_lock(&psb->crypto_thread_lock);
453 	list_del(&t->thread_entry);
454 	psb->crypto_thread_num--;
455 	mutex_unlock(&psb->crypto_thread_lock);
456 
457 	pohmelfs_crypto_engine_exit(&t->eng);
458 	pohmelfs_crypto_pages_free(&t->eng);
459 	kfree(t);
460 }
461 
pohmelfs_crypto_finish(struct netfs_trans * t,struct pohmelfs_sb * psb,int err)462 static int pohmelfs_crypto_finish(struct netfs_trans *t, struct pohmelfs_sb *psb, int err)
463 {
464 	struct netfs_cmd *cmd = t->iovec.iov_base;
465 	netfs_convert_cmd(cmd);
466 
467 	if (likely(!err))
468 		err = netfs_trans_finish_send(t, psb);
469 
470 	t->result = err;
471 	netfs_trans_put(t);
472 
473 	return err;
474 }
475 
pohmelfs_crypto_thread_make_ready(struct pohmelfs_crypto_thread * th)476 void pohmelfs_crypto_thread_make_ready(struct pohmelfs_crypto_thread *th)
477 {
478 	struct pohmelfs_sb *psb = th->psb;
479 
480 	th->page = NULL;
481 	th->trans = NULL;
482 
483 	mutex_lock(&psb->crypto_thread_lock);
484 	list_move_tail(&th->thread_entry, &psb->crypto_ready_list);
485 	mutex_unlock(&psb->crypto_thread_lock);
486 	wake_up(&psb->wait);
487 }
488 
pohmelfs_crypto_thread_trans(struct pohmelfs_crypto_thread * t)489 static int pohmelfs_crypto_thread_trans(struct pohmelfs_crypto_thread *t)
490 {
491 	struct netfs_trans *trans;
492 	int err = 0;
493 
494 	trans = t->trans;
495 	trans->eng = NULL;
496 
497 	if (t->eng.hash) {
498 		err = pohmelfs_hash(t);
499 		if (err)
500 			goto out_complete;
501 	}
502 
503 	if (t->eng.cipher) {
504 		err = pohmelfs_encrypt(t);
505 		if (err)
506 			goto out_complete;
507 		trans->eng = &t->eng;
508 	}
509 
510 out_complete:
511 	t->page = NULL;
512 	t->trans = NULL;
513 
514 	if (!trans->eng)
515 		pohmelfs_crypto_thread_make_ready(t);
516 
517 	pohmelfs_crypto_finish(trans, t->psb, err);
518 	return err;
519 }
520 
pohmelfs_crypto_thread_page(struct pohmelfs_crypto_thread * t)521 static int pohmelfs_crypto_thread_page(struct pohmelfs_crypto_thread *t)
522 {
523 	struct pohmelfs_crypto_engine *e = &t->eng;
524 	struct page *page = t->page;
525 	int err;
526 
527 	WARN_ON(!PageChecked(page));
528 
529 	err = pohmelfs_crypto_process_input_data(e, e->iv, NULL, page, t->size);
530 	if (!err)
531 		SetPageUptodate(page);
532 	else
533 		SetPageError(page);
534 	unlock_page(page);
535 	page_cache_release(page);
536 
537 	pohmelfs_crypto_thread_make_ready(t);
538 
539 	return err;
540 }
541 
pohmelfs_crypto_thread_func(void * data)542 static int pohmelfs_crypto_thread_func(void *data)
543 {
544 	struct pohmelfs_crypto_thread *t = data;
545 
546 	while (!kthread_should_stop()) {
547 		wait_event_interruptible(t->wait, kthread_should_stop() ||
548 				t->trans || t->page);
549 
550 		if (kthread_should_stop())
551 			break;
552 
553 		if (!t->trans && !t->page)
554 			continue;
555 
556 		dprintk("%s: thread: %p, trans: %p, page: %p.\n",
557 				__func__, t, t->trans, t->page);
558 
559 		if (t->trans)
560 			pohmelfs_crypto_thread_trans(t);
561 		else if (t->page)
562 			pohmelfs_crypto_thread_page(t);
563 	}
564 
565 	return 0;
566 }
567 
pohmelfs_crypto_flush(struct pohmelfs_sb * psb,struct list_head * head)568 static void pohmelfs_crypto_flush(struct pohmelfs_sb *psb, struct list_head *head)
569 {
570 	while (!list_empty(head)) {
571 		struct pohmelfs_crypto_thread *t = NULL;
572 
573 		mutex_lock(&psb->crypto_thread_lock);
574 		if (!list_empty(head)) {
575 			t = list_first_entry(head, struct pohmelfs_crypto_thread, thread_entry);
576 			list_del_init(&t->thread_entry);
577 		}
578 		mutex_unlock(&psb->crypto_thread_lock);
579 
580 		if (t)
581 			pohmelfs_sys_crypto_exit_one(t);
582 	}
583 }
584 
pohmelfs_sys_crypto_exit(struct pohmelfs_sb * psb)585 static void pohmelfs_sys_crypto_exit(struct pohmelfs_sb *psb)
586 {
587 	while (!list_empty(&psb->crypto_active_list) || !list_empty(&psb->crypto_ready_list)) {
588 		dprintk("%s: crypto_thread_num: %u.\n", __func__, psb->crypto_thread_num);
589 		pohmelfs_crypto_flush(psb, &psb->crypto_active_list);
590 		pohmelfs_crypto_flush(psb, &psb->crypto_ready_list);
591 	}
592 }
593 
pohmelfs_sys_crypto_init(struct pohmelfs_sb * psb)594 static int pohmelfs_sys_crypto_init(struct pohmelfs_sb *psb)
595 {
596 	unsigned int i;
597 	struct pohmelfs_crypto_thread *t;
598 	struct pohmelfs_config *c;
599 	struct netfs_state *st;
600 	int err;
601 
602 	list_for_each_entry(c, &psb->state_list, config_entry) {
603 		st = &c->state;
604 
605 		err = pohmelfs_crypto_engine_init(&st->eng, psb);
606 		if (err)
607 			goto err_out_exit;
608 
609 		dprintk("%s: st: %p, eng: %p, hash: %p, cipher: %p.\n",
610 				__func__, st, &st->eng, &st->eng.hash, &st->eng.cipher);
611 	}
612 
613 	for (i = 0; i < psb->crypto_thread_num; ++i) {
614 		err = -ENOMEM;
615 		t = kzalloc(sizeof(struct pohmelfs_crypto_thread), GFP_KERNEL);
616 		if (!t)
617 			goto err_out_free_state_engines;
618 
619 		init_waitqueue_head(&t->wait);
620 
621 		t->psb = psb;
622 		t->trans = NULL;
623 		t->eng.thread = t;
624 
625 		err = pohmelfs_crypto_engine_init(&t->eng, psb);
626 		if (err)
627 			goto err_out_free_state_engines;
628 
629 		err = pohmelfs_crypto_pages_alloc(&t->eng, psb);
630 		if (err)
631 			goto err_out_free;
632 
633 		t->thread = kthread_run(pohmelfs_crypto_thread_func, t,
634 				"pohmelfs-crypto-%d-%d", psb->idx, i);
635 		if (IS_ERR(t->thread)) {
636 			err = PTR_ERR(t->thread);
637 			t->thread = NULL;
638 			goto err_out_free;
639 		}
640 
641 		if (t->eng.cipher)
642 			psb->crypto_align_size = crypto_ablkcipher_blocksize(t->eng.cipher);
643 
644 		mutex_lock(&psb->crypto_thread_lock);
645 		list_add_tail(&t->thread_entry, &psb->crypto_ready_list);
646 		mutex_unlock(&psb->crypto_thread_lock);
647 	}
648 
649 	psb->crypto_thread_num = i;
650 	return 0;
651 
652 err_out_free:
653 	pohmelfs_sys_crypto_exit_one(t);
654 err_out_free_state_engines:
655 	list_for_each_entry(c, &psb->state_list, config_entry) {
656 		st = &c->state;
657 		pohmelfs_crypto_engine_exit(&st->eng);
658 	}
659 err_out_exit:
660 	pohmelfs_sys_crypto_exit(psb);
661 	return err;
662 }
663 
pohmelfs_crypto_exit(struct pohmelfs_sb * psb)664 void pohmelfs_crypto_exit(struct pohmelfs_sb *psb)
665 {
666 	pohmelfs_sys_crypto_exit(psb);
667 
668 	kfree(psb->hash_string);
669 	kfree(psb->cipher_string);
670 }
671 
pohmelfs_crypt_init_complete(struct page ** pages,unsigned int page_num,void * private,int err)672 static int pohmelfs_crypt_init_complete(struct page **pages, unsigned int page_num,
673 		void *private, int err)
674 {
675 	struct pohmelfs_sb *psb = private;
676 
677 	psb->flags = -err;
678 	dprintk("%s: err: %d.\n", __func__, err);
679 
680 	wake_up(&psb->wait);
681 
682 	return err;
683 }
684 
pohmelfs_crypto_init_handshake(struct pohmelfs_sb * psb)685 static int pohmelfs_crypto_init_handshake(struct pohmelfs_sb *psb)
686 {
687 	struct netfs_trans *t;
688 	struct netfs_crypto_capabilities *cap;
689 	struct netfs_cmd *cmd;
690 	char *str;
691 	int err = -ENOMEM, size;
692 
693 	size = sizeof(struct netfs_crypto_capabilities) +
694 		psb->cipher_strlen + psb->hash_strlen + 2; /* 0 bytes */
695 
696 	t = netfs_trans_alloc(psb, size, 0, 0);
697 	if (!t)
698 		goto err_out_exit;
699 
700 	t->complete = pohmelfs_crypt_init_complete;
701 	t->private = psb;
702 
703 	cmd = netfs_trans_current(t);
704 	cap = (struct netfs_crypto_capabilities *)(cmd + 1);
705 	str = (char *)(cap + 1);
706 
707 	cmd->cmd = NETFS_CAPABILITIES;
708 	cmd->id = POHMELFS_CRYPTO_CAPABILITIES;
709 	cmd->size = size;
710 	cmd->start = 0;
711 	cmd->ext = 0;
712 	cmd->csize = 0;
713 
714 	netfs_convert_cmd(cmd);
715 	netfs_trans_update(cmd, t, size);
716 
717 	cap->hash_strlen = psb->hash_strlen;
718 	if (cap->hash_strlen) {
719 		sprintf(str, "%s", psb->hash_string);
720 		str += cap->hash_strlen;
721 	}
722 
723 	cap->cipher_strlen = psb->cipher_strlen;
724 	cap->cipher_keysize = psb->cipher_keysize;
725 	if (cap->cipher_strlen)
726 		sprintf(str, "%s", psb->cipher_string);
727 
728 	netfs_convert_crypto_capabilities(cap);
729 
730 	psb->flags = ~0;
731 	err = netfs_trans_finish(t, psb);
732 	if (err)
733 		goto err_out_exit;
734 
735 	err = wait_event_interruptible_timeout(psb->wait, (psb->flags != ~0),
736 			psb->wait_on_page_timeout);
737 	if (!err)
738 		err = -ETIMEDOUT;
739 	else if (err > 0)
740 		err = -psb->flags;
741 
742 	if (!err)
743 		psb->perform_crypto = 1;
744 	psb->flags = 0;
745 
746 	/*
747 	 * At this point NETFS_CAPABILITIES response command
748 	 * should setup superblock in a way, which is acceptable
749 	 * for both client and server, so if server refuses connection,
750 	 * it will send error in transaction response.
751 	 */
752 
753 	if (err)
754 		goto err_out_exit;
755 
756 	return 0;
757 
758 err_out_exit:
759 	return err;
760 }
761 
pohmelfs_crypto_init(struct pohmelfs_sb * psb)762 int pohmelfs_crypto_init(struct pohmelfs_sb *psb)
763 {
764 	int err;
765 
766 	if (!psb->cipher_string && !psb->hash_string)
767 		return 0;
768 
769 	err = pohmelfs_crypto_init_handshake(psb);
770 	if (err)
771 		return err;
772 
773 	err = pohmelfs_sys_crypto_init(psb);
774 	if (err)
775 		return err;
776 
777 	return 0;
778 }
779 
pohmelfs_crypto_thread_get(struct pohmelfs_sb * psb,int (* action)(struct pohmelfs_crypto_thread * t,void * data),void * data)780 static int pohmelfs_crypto_thread_get(struct pohmelfs_sb *psb,
781 		int (*action)(struct pohmelfs_crypto_thread *t, void *data), void *data)
782 {
783 	struct pohmelfs_crypto_thread *t = NULL;
784 	int err;
785 
786 	while (!t) {
787 		err = wait_event_interruptible_timeout(psb->wait,
788 				!list_empty(&psb->crypto_ready_list),
789 				psb->wait_on_page_timeout);
790 
791 		t = NULL;
792 		err = 0;
793 		mutex_lock(&psb->crypto_thread_lock);
794 		if (!list_empty(&psb->crypto_ready_list)) {
795 			t = list_entry(psb->crypto_ready_list.prev,
796 					struct pohmelfs_crypto_thread,
797 					thread_entry);
798 
799 			list_move_tail(&t->thread_entry,
800 					&psb->crypto_active_list);
801 
802 			action(t, data);
803 			wake_up(&t->wait);
804 
805 		}
806 		mutex_unlock(&psb->crypto_thread_lock);
807 	}
808 
809 	return err;
810 }
811 
pohmelfs_trans_crypt_action(struct pohmelfs_crypto_thread * t,void * data)812 static int pohmelfs_trans_crypt_action(struct pohmelfs_crypto_thread *t, void *data)
813 {
814 	struct netfs_trans *trans = data;
815 
816 	netfs_trans_get(trans);
817 	t->trans = trans;
818 
819 	dprintk("%s: t: %p, gen: %u, thread: %p.\n", __func__, trans, trans->gen, t);
820 	return 0;
821 }
822 
pohmelfs_trans_crypt(struct netfs_trans * trans,struct pohmelfs_sb * psb)823 int pohmelfs_trans_crypt(struct netfs_trans *trans, struct pohmelfs_sb *psb)
824 {
825 	if ((!psb->hash_string && !psb->cipher_string) || !psb->perform_crypto) {
826 		netfs_trans_get(trans);
827 		return pohmelfs_crypto_finish(trans, psb, 0);
828 	}
829 
830 	return pohmelfs_crypto_thread_get(psb, pohmelfs_trans_crypt_action, trans);
831 }
832 
833 struct pohmelfs_crypto_input_action_data {
834 	struct page			*page;
835 	struct pohmelfs_crypto_engine	*e;
836 	u64				iv;
837 	unsigned int			size;
838 };
839 
pohmelfs_crypt_input_page_action(struct pohmelfs_crypto_thread * t,void * data)840 static int pohmelfs_crypt_input_page_action(struct pohmelfs_crypto_thread *t, void *data)
841 {
842 	struct pohmelfs_crypto_input_action_data *act = data;
843 
844 	memcpy(t->eng.data, act->e->data, t->psb->crypto_attached_size);
845 
846 	t->size = act->size;
847 	t->eng.iv = act->iv;
848 
849 	t->page = act->page;
850 	return 0;
851 }
852 
pohmelfs_crypto_process_input_page(struct pohmelfs_crypto_engine * e,struct page * page,unsigned int size,u64 iv)853 int pohmelfs_crypto_process_input_page(struct pohmelfs_crypto_engine *e,
854 		struct page *page, unsigned int size, u64 iv)
855 {
856 	struct inode *inode = page->mapping->host;
857 	struct pohmelfs_crypto_input_action_data act;
858 	int err = -ENOENT;
859 
860 	act.page = page;
861 	act.e = e;
862 	act.size = size;
863 	act.iv = iv;
864 
865 	err = pohmelfs_crypto_thread_get(POHMELFS_SB(inode->i_sb),
866 			pohmelfs_crypt_input_page_action, &act);
867 	if (err)
868 		goto err_out_exit;
869 
870 	return 0;
871 
872 err_out_exit:
873 	SetPageUptodate(page);
874 	page_cache_release(page);
875 
876 	return err;
877 }
878