aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/algapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/algapi.c')
-rw-r--r--crypto/algapi.c180
1 files changed, 154 insertions, 26 deletions
diff --git a/crypto/algapi.c b/crypto/algapi.c
index df0863d56995..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
84static 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
84static void crypto_remove_spawn(struct crypto_spawn *spawn, 107static 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
112static void crypto_remove_spawns(struct list_head *spawns, 131static 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
264complete: 313complete:
@@ -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}
489EXPORT_SYMBOL_GPL(crypto_init_spawn); 538EXPORT_SYMBOL_GPL(crypto_init_spawn);
490 539
540int 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
552out:
553 return err;
554}
555EXPORT_SYMBOL_GPL(crypto_init_spawn2);
556
491void crypto_drop_spawn(struct crypto_spawn *spawn) 557void 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}
497EXPORT_SYMBOL_GPL(crypto_drop_spawn); 566EXPORT_SYMBOL_GPL(crypto_drop_spawn);
498 567
499struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type, 568static 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
589struct 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}
533EXPORT_SYMBOL_GPL(crypto_spawn_tfm); 613EXPORT_SYMBOL_GPL(crypto_spawn_tfm);
534 614
615void *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
630out_put_alg:
631 crypto_mod_put(alg);
632 return tfm;
633}
634EXPORT_SYMBOL_GPL(crypto_spawn_tfm2);
635
535int crypto_register_notifier(struct notifier_block *nb) 636int 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}
596EXPORT_SYMBOL_GPL(crypto_attr_alg_name); 697EXPORT_SYMBOL_GPL(crypto_attr_alg_name);
597 698
598struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask) 699struct 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}
610EXPORT_SYMBOL_GPL(crypto_attr_alg); 713EXPORT_SYMBOL_GPL(crypto_attr_alg2);
611 714
612int crypto_attr_u32(struct rtattr *rta, u32 *num) 715int 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}
628EXPORT_SYMBOL_GPL(crypto_attr_u32); 731EXPORT_SYMBOL_GPL(crypto_attr_u32);
629 732
630struct crypto_instance *crypto_alloc_instance(const char *name, 733void *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
758err_free_inst:
759 kfree(p);
760 return ERR_PTR(err);
761}
762EXPORT_SYMBOL_GPL(crypto_alloc_instance2);
763
764struct 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
659err_free_inst: 784err_free_inst:
660 kfree(inst); 785 kfree(inst);
661 return ERR_PTR(err); 786 inst = ERR_PTR(err);
787
788out:
789 return inst;
662} 790}
663EXPORT_SYMBOL_GPL(crypto_alloc_instance); 791EXPORT_SYMBOL_GPL(crypto_alloc_instance);
664 792