diff options
Diffstat (limited to 'crypto/algapi.c')
| -rw-r--r-- | crypto/algapi.c | 191 |
1 files changed, 163 insertions, 28 deletions
diff --git a/crypto/algapi.c b/crypto/algapi.c index 56c62e2858d5..f149b1c8b76d 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c | |||
| @@ -81,16 +81,35 @@ static void crypto_destroy_instance(struct crypto_alg *alg) | |||
| 81 | crypto_tmpl_put(tmpl); | 81 | crypto_tmpl_put(tmpl); |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | static struct list_head *crypto_more_spawns(struct crypto_alg *alg, | ||
| 85 | struct list_head *stack, | ||
| 86 | struct list_head *top, | ||
| 87 | struct list_head *secondary_spawns) | ||
| 88 | { | ||
| 89 | struct crypto_spawn *spawn, *n; | ||
| 90 | |||
| 91 | if (list_empty(stack)) | ||
| 92 | return NULL; | ||
| 93 | |||
| 94 | spawn = list_first_entry(stack, struct crypto_spawn, list); | ||
| 95 | n = list_entry(spawn->list.next, struct crypto_spawn, list); | ||
| 96 | |||
| 97 | if (spawn->alg && &n->list != stack && !n->alg) | ||
| 98 | n->alg = (n->list.next == stack) ? alg : | ||
| 99 | &list_entry(n->list.next, struct crypto_spawn, | ||
| 100 | list)->inst->alg; | ||
| 101 | |||
| 102 | list_move(&spawn->list, secondary_spawns); | ||
| 103 | |||
| 104 | return &n->list == stack ? top : &n->inst->alg.cra_users; | ||
| 105 | } | ||
| 106 | |||
| 84 | static void crypto_remove_spawn(struct crypto_spawn *spawn, | 107 | static void crypto_remove_spawn(struct crypto_spawn *spawn, |
| 85 | struct list_head *list, | 108 | struct list_head *list) |
| 86 | struct list_head *secondary_spawns) | ||
| 87 | { | 109 | { |
| 88 | struct crypto_instance *inst = spawn->inst; | 110 | struct crypto_instance *inst = spawn->inst; |
| 89 | struct crypto_template *tmpl = inst->tmpl; | 111 | struct crypto_template *tmpl = inst->tmpl; |
| 90 | 112 | ||
| 91 | list_del_init(&spawn->list); | ||
| 92 | spawn->alg = NULL; | ||
| 93 | |||
| 94 | if (crypto_is_dead(&inst->alg)) | 113 | if (crypto_is_dead(&inst->alg)) |
| 95 | return; | 114 | return; |
| 96 | 115 | ||
| @@ -106,25 +125,55 @@ static void crypto_remove_spawn(struct crypto_spawn *spawn, | |||
| 106 | hlist_del(&inst->list); | 125 | hlist_del(&inst->list); |
| 107 | inst->alg.cra_destroy = crypto_destroy_instance; | 126 | inst->alg.cra_destroy = crypto_destroy_instance; |
| 108 | 127 | ||
| 109 | list_splice(&inst->alg.cra_users, secondary_spawns); | 128 | BUG_ON(!list_empty(&inst->alg.cra_users)); |
| 110 | } | 129 | } |
| 111 | 130 | ||
| 112 | static void crypto_remove_spawns(struct list_head *spawns, | 131 | static void crypto_remove_spawns(struct crypto_alg *alg, |
| 113 | struct list_head *list, u32 new_type) | 132 | struct list_head *list, |
| 133 | struct crypto_alg *nalg) | ||
| 114 | { | 134 | { |
| 135 | u32 new_type = (nalg ?: alg)->cra_flags; | ||
| 115 | struct crypto_spawn *spawn, *n; | 136 | struct crypto_spawn *spawn, *n; |
| 116 | LIST_HEAD(secondary_spawns); | 137 | LIST_HEAD(secondary_spawns); |
| 138 | struct list_head *spawns; | ||
| 139 | LIST_HEAD(stack); | ||
| 140 | LIST_HEAD(top); | ||
| 117 | 141 | ||
| 142 | spawns = &alg->cra_users; | ||
| 118 | list_for_each_entry_safe(spawn, n, spawns, list) { | 143 | list_for_each_entry_safe(spawn, n, spawns, list) { |
| 119 | if ((spawn->alg->cra_flags ^ new_type) & spawn->mask) | 144 | if ((spawn->alg->cra_flags ^ new_type) & spawn->mask) |
| 120 | continue; | 145 | continue; |
| 121 | 146 | ||
| 122 | crypto_remove_spawn(spawn, list, &secondary_spawns); | 147 | list_move(&spawn->list, &top); |
| 123 | } | 148 | } |
| 124 | 149 | ||
| 125 | while (!list_empty(&secondary_spawns)) { | 150 | spawns = ⊤ |
| 126 | list_for_each_entry_safe(spawn, n, &secondary_spawns, list) | 151 | do { |
| 127 | crypto_remove_spawn(spawn, list, &secondary_spawns); | 152 | while (!list_empty(spawns)) { |
| 153 | struct crypto_instance *inst; | ||
| 154 | |||
| 155 | spawn = list_first_entry(spawns, struct crypto_spawn, | ||
| 156 | list); | ||
| 157 | inst = spawn->inst; | ||
| 158 | |||
| 159 | BUG_ON(&inst->alg == alg); | ||
| 160 | |||
| 161 | list_move(&spawn->list, &stack); | ||
| 162 | |||
| 163 | if (&inst->alg == nalg) | ||
| 164 | break; | ||
| 165 | |||
| 166 | spawn->alg = NULL; | ||
| 167 | spawns = &inst->alg.cra_users; | ||
| 168 | } | ||
| 169 | } while ((spawns = crypto_more_spawns(alg, &stack, &top, | ||
| 170 | &secondary_spawns))); | ||
| 171 | |||
| 172 | list_for_each_entry_safe(spawn, n, &secondary_spawns, list) { | ||
| 173 | if (spawn->alg) | ||
| 174 | list_move(&spawn->list, &spawn->alg->cra_users); | ||
| 175 | else | ||
| 176 | crypto_remove_spawn(spawn, list); | ||
| 128 | } | 177 | } |
| 129 | } | 178 | } |
| 130 | 179 | ||
| @@ -258,7 +307,7 @@ found: | |||
| 258 | q->cra_priority > alg->cra_priority) | 307 | q->cra_priority > alg->cra_priority) |
| 259 | continue; | 308 | continue; |
| 260 | 309 | ||
| 261 | crypto_remove_spawns(&q->cra_users, &list, alg->cra_flags); | 310 | crypto_remove_spawns(q, &list, alg); |
| 262 | } | 311 | } |
| 263 | 312 | ||
| 264 | complete: | 313 | complete: |
| @@ -330,7 +379,7 @@ static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list) | |||
| 330 | 379 | ||
| 331 | crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg); | 380 | crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg); |
| 332 | list_del_init(&alg->cra_list); | 381 | list_del_init(&alg->cra_list); |
| 333 | crypto_remove_spawns(&alg->cra_users, list, alg->cra_flags); | 382 | crypto_remove_spawns(alg, list, NULL); |
| 334 | 383 | ||
| 335 | return 0; | 384 | return 0; |
| 336 | } | 385 | } |
| @@ -488,20 +537,38 @@ int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg, | |||
| 488 | } | 537 | } |
| 489 | EXPORT_SYMBOL_GPL(crypto_init_spawn); | 538 | EXPORT_SYMBOL_GPL(crypto_init_spawn); |
| 490 | 539 | ||
| 540 | int crypto_init_spawn2(struct crypto_spawn *spawn, struct crypto_alg *alg, | ||
| 541 | struct crypto_instance *inst, | ||
| 542 | const struct crypto_type *frontend) | ||
| 543 | { | ||
| 544 | int err = -EINVAL; | ||
| 545 | |||
| 546 | if (frontend && (alg->cra_flags ^ frontend->type) & frontend->maskset) | ||
| 547 | goto out; | ||
| 548 | |||
| 549 | spawn->frontend = frontend; | ||
| 550 | err = crypto_init_spawn(spawn, alg, inst, frontend->maskset); | ||
| 551 | |||
| 552 | out: | ||
| 553 | return err; | ||
| 554 | } | ||
| 555 | EXPORT_SYMBOL_GPL(crypto_init_spawn2); | ||
| 556 | |||
| 491 | void crypto_drop_spawn(struct crypto_spawn *spawn) | 557 | void crypto_drop_spawn(struct crypto_spawn *spawn) |
| 492 | { | 558 | { |
| 559 | if (!spawn->alg) | ||
| 560 | return; | ||
| 561 | |||
| 493 | down_write(&crypto_alg_sem); | 562 | down_write(&crypto_alg_sem); |
| 494 | list_del(&spawn->list); | 563 | list_del(&spawn->list); |
| 495 | up_write(&crypto_alg_sem); | 564 | up_write(&crypto_alg_sem); |
| 496 | } | 565 | } |
| 497 | EXPORT_SYMBOL_GPL(crypto_drop_spawn); | 566 | EXPORT_SYMBOL_GPL(crypto_drop_spawn); |
| 498 | 567 | ||
| 499 | struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type, | 568 | static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn) |
| 500 | u32 mask) | ||
| 501 | { | 569 | { |
| 502 | struct crypto_alg *alg; | 570 | struct crypto_alg *alg; |
| 503 | struct crypto_alg *alg2; | 571 | struct crypto_alg *alg2; |
| 504 | struct crypto_tfm *tfm; | ||
| 505 | 572 | ||
| 506 | down_read(&crypto_alg_sem); | 573 | down_read(&crypto_alg_sem); |
| 507 | alg = spawn->alg; | 574 | alg = spawn->alg; |
| @@ -516,6 +583,19 @@ struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type, | |||
| 516 | return ERR_PTR(-EAGAIN); | 583 | return ERR_PTR(-EAGAIN); |
| 517 | } | 584 | } |
| 518 | 585 | ||
| 586 | return alg; | ||
| 587 | } | ||
| 588 | |||
| 589 | struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type, | ||
| 590 | u32 mask) | ||
| 591 | { | ||
| 592 | struct crypto_alg *alg; | ||
| 593 | struct crypto_tfm *tfm; | ||
| 594 | |||
| 595 | alg = crypto_spawn_alg(spawn); | ||
| 596 | if (IS_ERR(alg)) | ||
| 597 | return ERR_CAST(alg); | ||
| 598 | |||
| 519 | tfm = ERR_PTR(-EINVAL); | 599 | tfm = ERR_PTR(-EINVAL); |
| 520 | if (unlikely((alg->cra_flags ^ type) & mask)) | 600 | if (unlikely((alg->cra_flags ^ type) & mask)) |
| 521 | goto out_put_alg; | 601 | goto out_put_alg; |
| @@ -532,6 +612,27 @@ out_put_alg: | |||
| 532 | } | 612 | } |
| 533 | EXPORT_SYMBOL_GPL(crypto_spawn_tfm); | 613 | EXPORT_SYMBOL_GPL(crypto_spawn_tfm); |
| 534 | 614 | ||
| 615 | void *crypto_spawn_tfm2(struct crypto_spawn *spawn) | ||
| 616 | { | ||
| 617 | struct crypto_alg *alg; | ||
| 618 | struct crypto_tfm *tfm; | ||
| 619 | |||
| 620 | alg = crypto_spawn_alg(spawn); | ||
| 621 | if (IS_ERR(alg)) | ||
| 622 | return ERR_CAST(alg); | ||
| 623 | |||
| 624 | tfm = crypto_create_tfm(alg, spawn->frontend); | ||
| 625 | if (IS_ERR(tfm)) | ||
| 626 | goto out_put_alg; | ||
| 627 | |||
| 628 | return tfm; | ||
| 629 | |||
| 630 | out_put_alg: | ||
| 631 | crypto_mod_put(alg); | ||
| 632 | return tfm; | ||
| 633 | } | ||
| 634 | EXPORT_SYMBOL_GPL(crypto_spawn_tfm2); | ||
| 635 | |||
| 535 | int crypto_register_notifier(struct notifier_block *nb) | 636 | int crypto_register_notifier(struct notifier_block *nb) |
| 536 | { | 637 | { |
| 537 | return blocking_notifier_chain_register(&crypto_chain, nb); | 638 | return blocking_notifier_chain_register(&crypto_chain, nb); |
| @@ -595,7 +696,9 @@ const char *crypto_attr_alg_name(struct rtattr *rta) | |||
| 595 | } | 696 | } |
| 596 | EXPORT_SYMBOL_GPL(crypto_attr_alg_name); | 697 | EXPORT_SYMBOL_GPL(crypto_attr_alg_name); |
| 597 | 698 | ||
| 598 | struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask) | 699 | struct crypto_alg *crypto_attr_alg2(struct rtattr *rta, |
| 700 | const struct crypto_type *frontend, | ||
| 701 | u32 type, u32 mask) | ||
| 599 | { | 702 | { |
| 600 | const char *name; | 703 | const char *name; |
| 601 | int err; | 704 | int err; |
| @@ -605,9 +708,9 @@ struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask) | |||
| 605 | if (IS_ERR(name)) | 708 | if (IS_ERR(name)) |
| 606 | return ERR_PTR(err); | 709 | return ERR_PTR(err); |
| 607 | 710 | ||
| 608 | return crypto_alg_mod_lookup(name, type, mask); | 711 | return crypto_find_alg(name, frontend, type, mask); |
| 609 | } | 712 | } |
| 610 | EXPORT_SYMBOL_GPL(crypto_attr_alg); | 713 | EXPORT_SYMBOL_GPL(crypto_attr_alg2); |
| 611 | 714 | ||
| 612 | int crypto_attr_u32(struct rtattr *rta, u32 *num) | 715 | int crypto_attr_u32(struct rtattr *rta, u32 *num) |
| 613 | { | 716 | { |
| @@ -627,17 +730,20 @@ int crypto_attr_u32(struct rtattr *rta, u32 *num) | |||
| 627 | } | 730 | } |
| 628 | EXPORT_SYMBOL_GPL(crypto_attr_u32); | 731 | EXPORT_SYMBOL_GPL(crypto_attr_u32); |
| 629 | 732 | ||
| 630 | struct crypto_instance *crypto_alloc_instance(const char *name, | 733 | void *crypto_alloc_instance2(const char *name, struct crypto_alg *alg, |
| 631 | struct crypto_alg *alg) | 734 | unsigned int head) |
| 632 | { | 735 | { |
| 633 | struct crypto_instance *inst; | 736 | struct crypto_instance *inst; |
| 634 | struct crypto_spawn *spawn; | 737 | char *p; |
| 635 | int err; | 738 | int err; |
| 636 | 739 | ||
| 637 | inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); | 740 | p = kzalloc(head + sizeof(*inst) + sizeof(struct crypto_spawn), |
| 638 | if (!inst) | 741 | GFP_KERNEL); |
| 742 | if (!p) | ||
| 639 | return ERR_PTR(-ENOMEM); | 743 | return ERR_PTR(-ENOMEM); |
| 640 | 744 | ||
| 745 | inst = (void *)(p + head); | ||
| 746 | |||
| 641 | err = -ENAMETOOLONG; | 747 | err = -ENAMETOOLONG; |
| 642 | if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "%s(%s)", name, | 748 | if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "%s(%s)", name, |
| 643 | alg->cra_name) >= CRYPTO_MAX_ALG_NAME) | 749 | alg->cra_name) >= CRYPTO_MAX_ALG_NAME) |
| @@ -647,6 +753,25 @@ struct crypto_instance *crypto_alloc_instance(const char *name, | |||
| 647 | name, alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) | 753 | name, alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME) |
| 648 | goto err_free_inst; | 754 | goto err_free_inst; |
| 649 | 755 | ||
| 756 | return p; | ||
| 757 | |||
| 758 | err_free_inst: | ||
| 759 | kfree(p); | ||
| 760 | return ERR_PTR(err); | ||
| 761 | } | ||
| 762 | EXPORT_SYMBOL_GPL(crypto_alloc_instance2); | ||
| 763 | |||
| 764 | struct crypto_instance *crypto_alloc_instance(const char *name, | ||
| 765 | struct crypto_alg *alg) | ||
| 766 | { | ||
| 767 | struct crypto_instance *inst; | ||
| 768 | struct crypto_spawn *spawn; | ||
| 769 | int err; | ||
| 770 | |||
| 771 | inst = crypto_alloc_instance2(name, alg, 0); | ||
| 772 | if (IS_ERR(inst)) | ||
| 773 | goto out; | ||
| 774 | |||
| 650 | spawn = crypto_instance_ctx(inst); | 775 | spawn = crypto_instance_ctx(inst); |
| 651 | err = crypto_init_spawn(spawn, alg, inst, | 776 | err = crypto_init_spawn(spawn, alg, inst, |
| 652 | CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC); | 777 | CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC); |
| @@ -658,7 +783,10 @@ struct crypto_instance *crypto_alloc_instance(const char *name, | |||
| 658 | 783 | ||
| 659 | err_free_inst: | 784 | err_free_inst: |
| 660 | kfree(inst); | 785 | kfree(inst); |
| 661 | return ERR_PTR(err); | 786 | inst = ERR_PTR(err); |
| 787 | |||
| 788 | out: | ||
| 789 | return inst; | ||
| 662 | } | 790 | } |
| 663 | EXPORT_SYMBOL_GPL(crypto_alloc_instance); | 791 | EXPORT_SYMBOL_GPL(crypto_alloc_instance); |
| 664 | 792 | ||
| @@ -692,7 +820,7 @@ out: | |||
| 692 | } | 820 | } |
| 693 | EXPORT_SYMBOL_GPL(crypto_enqueue_request); | 821 | EXPORT_SYMBOL_GPL(crypto_enqueue_request); |
| 694 | 822 | ||
| 695 | struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue) | 823 | void *__crypto_dequeue_request(struct crypto_queue *queue, unsigned int offset) |
| 696 | { | 824 | { |
| 697 | struct list_head *request; | 825 | struct list_head *request; |
| 698 | 826 | ||
| @@ -707,7 +835,14 @@ struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue) | |||
| 707 | request = queue->list.next; | 835 | request = queue->list.next; |
| 708 | list_del(request); | 836 | list_del(request); |
| 709 | 837 | ||
| 710 | return list_entry(request, struct crypto_async_request, list); | 838 | return (char *)list_entry(request, struct crypto_async_request, list) - |
| 839 | offset; | ||
| 840 | } | ||
| 841 | EXPORT_SYMBOL_GPL(__crypto_dequeue_request); | ||
| 842 | |||
| 843 | struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue) | ||
| 844 | { | ||
| 845 | return __crypto_dequeue_request(queue, 0); | ||
| 711 | } | 846 | } |
| 712 | EXPORT_SYMBOL_GPL(crypto_dequeue_request); | 847 | EXPORT_SYMBOL_GPL(crypto_dequeue_request); |
| 713 | 848 | ||
