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