Commit 6bfd48096ff8ecabf955958b51ddfa7988eb0a14
1 parent
492e2b63eb
Exists in
master
and in
39 other branches
[CRYPTO] api: Added spawns
Spawns lock a specific crypto algorithm in place. They can then be used with crypto_spawn_tfm to allocate a tfm for that algorithm. When the base algorithm of a spawn is deregistered, all its spawns will be automatically removed. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 6 changed files with 280 additions and 53 deletions Inline Diff
crypto/algapi.c
1 | /* | 1 | /* |
2 | * Cryptographic API for algorithms (i.e., low-level API). | 2 | * Cryptographic API for algorithms (i.e., low-level API). |
3 | * | 3 | * |
4 | * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> | 4 | * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the Free | 7 | * under the terms of the GNU General Public License as published by the Free |
8 | * Software Foundation; either version 2 of the License, or (at your option) | 8 | * Software Foundation; either version 2 of the License, or (at your option) |
9 | * any later version. | 9 | * any later version. |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/err.h> | ||
13 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
14 | #include <linux/init.h> | 15 | #include <linux/init.h> |
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
16 | #include <linux/list.h> | 17 | #include <linux/list.h> |
17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
18 | #include <linux/string.h> | 19 | #include <linux/string.h> |
19 | 20 | ||
20 | #include "internal.h" | 21 | #include "internal.h" |
21 | 22 | ||
22 | static LIST_HEAD(crypto_template_list); | 23 | static LIST_HEAD(crypto_template_list); |
23 | 24 | ||
24 | void crypto_larval_error(const char *name, u32 type, u32 mask) | 25 | void crypto_larval_error(const char *name, u32 type, u32 mask) |
25 | { | 26 | { |
26 | struct crypto_alg *alg; | 27 | struct crypto_alg *alg; |
27 | 28 | ||
28 | down_read(&crypto_alg_sem); | 29 | down_read(&crypto_alg_sem); |
29 | alg = __crypto_alg_lookup(name, type, mask); | 30 | alg = __crypto_alg_lookup(name, type, mask); |
30 | up_read(&crypto_alg_sem); | 31 | up_read(&crypto_alg_sem); |
31 | 32 | ||
32 | if (alg) { | 33 | if (alg) { |
33 | if (crypto_is_larval(alg)) { | 34 | if (crypto_is_larval(alg)) { |
34 | struct crypto_larval *larval = (void *)alg; | 35 | struct crypto_larval *larval = (void *)alg; |
35 | complete(&larval->completion); | 36 | complete(&larval->completion); |
36 | } | 37 | } |
37 | crypto_mod_put(alg); | 38 | crypto_mod_put(alg); |
38 | } | 39 | } |
39 | } | 40 | } |
40 | EXPORT_SYMBOL_GPL(crypto_larval_error); | 41 | EXPORT_SYMBOL_GPL(crypto_larval_error); |
41 | 42 | ||
42 | static inline int crypto_set_driver_name(struct crypto_alg *alg) | 43 | static inline int crypto_set_driver_name(struct crypto_alg *alg) |
43 | { | 44 | { |
44 | static const char suffix[] = "-generic"; | 45 | static const char suffix[] = "-generic"; |
45 | char *driver_name = alg->cra_driver_name; | 46 | char *driver_name = alg->cra_driver_name; |
46 | int len; | 47 | int len; |
47 | 48 | ||
48 | if (*driver_name) | 49 | if (*driver_name) |
49 | return 0; | 50 | return 0; |
50 | 51 | ||
51 | len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); | 52 | len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); |
52 | if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME) | 53 | if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME) |
53 | return -ENAMETOOLONG; | 54 | return -ENAMETOOLONG; |
54 | 55 | ||
55 | memcpy(driver_name + len, suffix, sizeof(suffix)); | 56 | memcpy(driver_name + len, suffix, sizeof(suffix)); |
56 | return 0; | 57 | return 0; |
57 | } | 58 | } |
58 | 59 | ||
59 | static int crypto_check_alg(struct crypto_alg *alg) | 60 | static int crypto_check_alg(struct crypto_alg *alg) |
60 | { | 61 | { |
61 | if (alg->cra_alignmask & (alg->cra_alignmask + 1)) | 62 | if (alg->cra_alignmask & (alg->cra_alignmask + 1)) |
62 | return -EINVAL; | 63 | return -EINVAL; |
63 | 64 | ||
64 | if (alg->cra_alignmask & alg->cra_blocksize) | 65 | if (alg->cra_alignmask & alg->cra_blocksize) |
65 | return -EINVAL; | 66 | return -EINVAL; |
66 | 67 | ||
67 | if (alg->cra_blocksize > PAGE_SIZE / 8) | 68 | if (alg->cra_blocksize > PAGE_SIZE / 8) |
68 | return -EINVAL; | 69 | return -EINVAL; |
69 | 70 | ||
70 | if (alg->cra_priority < 0) | 71 | if (alg->cra_priority < 0) |
71 | return -EINVAL; | 72 | return -EINVAL; |
72 | 73 | ||
73 | return crypto_set_driver_name(alg); | 74 | return crypto_set_driver_name(alg); |
74 | } | 75 | } |
75 | 76 | ||
76 | static int __crypto_register_alg(struct crypto_alg *alg) | 77 | static void crypto_destroy_instance(struct crypto_alg *alg) |
77 | { | 78 | { |
79 | struct crypto_instance *inst = (void *)alg; | ||
80 | struct crypto_template *tmpl = inst->tmpl; | ||
81 | |||
82 | tmpl->free(inst); | ||
83 | crypto_tmpl_put(tmpl); | ||
84 | } | ||
85 | |||
86 | static void crypto_remove_spawns(struct list_head *spawns, | ||
87 | struct list_head *list) | ||
88 | { | ||
89 | struct crypto_spawn *spawn, *n; | ||
90 | |||
91 | list_for_each_entry_safe(spawn, n, spawns, list) { | ||
92 | struct crypto_instance *inst = spawn->inst; | ||
93 | struct crypto_template *tmpl = inst->tmpl; | ||
94 | |||
95 | list_del_init(&spawn->list); | ||
96 | spawn->alg = NULL; | ||
97 | |||
98 | if (crypto_is_dead(&inst->alg)) | ||
99 | continue; | ||
100 | |||
101 | inst->alg.cra_flags |= CRYPTO_ALG_DEAD; | ||
102 | if (!tmpl || !crypto_tmpl_get(tmpl)) | ||
103 | continue; | ||
104 | |||
105 | crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg); | ||
106 | list_move(&inst->alg.cra_list, list); | ||
107 | hlist_del(&inst->list); | ||
108 | inst->alg.cra_destroy = crypto_destroy_instance; | ||
109 | |||
110 | if (!list_empty(&inst->alg.cra_users)) { | ||
111 | if (&n->list == spawns) | ||
112 | n = list_entry(inst->alg.cra_users.next, | ||
113 | typeof(*n), list); | ||
114 | __list_splice(&inst->alg.cra_users, spawns->prev); | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | |||
119 | static int __crypto_register_alg(struct crypto_alg *alg, | ||
120 | struct list_head *list) | ||
121 | { | ||
78 | struct crypto_alg *q; | 122 | struct crypto_alg *q; |
79 | int ret = -EEXIST; | 123 | int ret = -EAGAIN; |
80 | 124 | ||
125 | if (crypto_is_dead(alg)) | ||
126 | goto out; | ||
127 | |||
128 | INIT_LIST_HEAD(&alg->cra_users); | ||
129 | |||
130 | ret = -EEXIST; | ||
131 | |||
81 | atomic_set(&alg->cra_refcnt, 1); | 132 | atomic_set(&alg->cra_refcnt, 1); |
82 | list_for_each_entry(q, &crypto_alg_list, cra_list) { | 133 | list_for_each_entry(q, &crypto_alg_list, cra_list) { |
83 | if (q == alg) | 134 | if (q == alg) |
84 | goto out; | 135 | goto out; |
85 | if (crypto_is_larval(q) && | 136 | |
86 | (!strcmp(alg->cra_name, q->cra_name) || | 137 | if (crypto_is_moribund(q)) |
87 | !strcmp(alg->cra_driver_name, q->cra_name))) { | 138 | continue; |
139 | |||
140 | if (crypto_is_larval(q)) { | ||
88 | struct crypto_larval *larval = (void *)q; | 141 | struct crypto_larval *larval = (void *)q; |
89 | 142 | ||
143 | if (strcmp(alg->cra_name, q->cra_name) && | ||
144 | strcmp(alg->cra_driver_name, q->cra_name)) | ||
145 | continue; | ||
146 | |||
147 | if (larval->adult) | ||
148 | continue; | ||
90 | if ((q->cra_flags ^ alg->cra_flags) & larval->mask) | 149 | if ((q->cra_flags ^ alg->cra_flags) & larval->mask) |
91 | continue; | 150 | continue; |
92 | if (!crypto_mod_get(alg)) | 151 | if (!crypto_mod_get(alg)) |
93 | continue; | 152 | continue; |
153 | |||
94 | larval->adult = alg; | 154 | larval->adult = alg; |
95 | complete(&larval->completion); | 155 | complete(&larval->completion); |
156 | continue; | ||
96 | } | 157 | } |
158 | |||
159 | if (strcmp(alg->cra_name, q->cra_name)) | ||
160 | continue; | ||
161 | |||
162 | if (strcmp(alg->cra_driver_name, q->cra_driver_name) && | ||
163 | q->cra_priority > alg->cra_priority) | ||
164 | continue; | ||
165 | |||
166 | crypto_remove_spawns(&q->cra_users, list); | ||
97 | } | 167 | } |
98 | 168 | ||
99 | list_add(&alg->cra_list, &crypto_alg_list); | 169 | list_add(&alg->cra_list, &crypto_alg_list); |
100 | 170 | ||
101 | crypto_notify(CRYPTO_MSG_ALG_REGISTER, alg); | 171 | crypto_notify(CRYPTO_MSG_ALG_REGISTER, alg); |
102 | ret = 0; | 172 | ret = 0; |
103 | 173 | ||
104 | out: | 174 | out: |
105 | return ret; | 175 | return ret; |
106 | } | 176 | } |
107 | 177 | ||
178 | static void crypto_remove_final(struct list_head *list) | ||
179 | { | ||
180 | struct crypto_alg *alg; | ||
181 | struct crypto_alg *n; | ||
182 | |||
183 | list_for_each_entry_safe(alg, n, list, cra_list) { | ||
184 | list_del_init(&alg->cra_list); | ||
185 | crypto_alg_put(alg); | ||
186 | } | ||
187 | } | ||
188 | |||
108 | int crypto_register_alg(struct crypto_alg *alg) | 189 | int crypto_register_alg(struct crypto_alg *alg) |
109 | { | 190 | { |
191 | LIST_HEAD(list); | ||
110 | int err; | 192 | int err; |
111 | 193 | ||
112 | err = crypto_check_alg(alg); | 194 | err = crypto_check_alg(alg); |
113 | if (err) | 195 | if (err) |
114 | return err; | 196 | return err; |
115 | 197 | ||
116 | down_write(&crypto_alg_sem); | 198 | down_write(&crypto_alg_sem); |
117 | err = __crypto_register_alg(alg); | 199 | err = __crypto_register_alg(alg, &list); |
118 | up_write(&crypto_alg_sem); | 200 | up_write(&crypto_alg_sem); |
119 | 201 | ||
202 | crypto_remove_final(&list); | ||
120 | return err; | 203 | return err; |
121 | } | 204 | } |
122 | EXPORT_SYMBOL_GPL(crypto_register_alg); | 205 | EXPORT_SYMBOL_GPL(crypto_register_alg); |
123 | 206 | ||
207 | static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list) | ||
208 | { | ||
209 | if (unlikely(list_empty(&alg->cra_list))) | ||
210 | return -ENOENT; | ||
211 | |||
212 | alg->cra_flags |= CRYPTO_ALG_DEAD; | ||
213 | |||
214 | crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg); | ||
215 | list_del_init(&alg->cra_list); | ||
216 | crypto_remove_spawns(&alg->cra_users, list); | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
124 | int crypto_unregister_alg(struct crypto_alg *alg) | 221 | int crypto_unregister_alg(struct crypto_alg *alg) |
125 | { | 222 | { |
126 | int ret = -ENOENT; | 223 | int ret; |
224 | LIST_HEAD(list); | ||
127 | 225 | ||
128 | down_write(&crypto_alg_sem); | 226 | down_write(&crypto_alg_sem); |
129 | if (likely(!list_empty(&alg->cra_list))) { | 227 | ret = crypto_remove_alg(alg, &list); |
130 | list_del_init(&alg->cra_list); | ||
131 | ret = 0; | ||
132 | } | ||
133 | crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, alg); | ||
134 | up_write(&crypto_alg_sem); | 228 | up_write(&crypto_alg_sem); |
135 | 229 | ||
136 | if (ret) | 230 | if (ret) |
137 | return ret; | 231 | return ret; |
138 | 232 | ||
139 | BUG_ON(atomic_read(&alg->cra_refcnt) != 1); | 233 | BUG_ON(atomic_read(&alg->cra_refcnt) != 1); |
140 | if (alg->cra_destroy) | 234 | if (alg->cra_destroy) |
141 | alg->cra_destroy(alg); | 235 | alg->cra_destroy(alg); |
142 | 236 | ||
237 | crypto_remove_final(&list); | ||
143 | return 0; | 238 | return 0; |
144 | } | 239 | } |
145 | EXPORT_SYMBOL_GPL(crypto_unregister_alg); | 240 | EXPORT_SYMBOL_GPL(crypto_unregister_alg); |
146 | 241 | ||
147 | int crypto_register_template(struct crypto_template *tmpl) | 242 | int crypto_register_template(struct crypto_template *tmpl) |
148 | { | 243 | { |
149 | struct crypto_template *q; | 244 | struct crypto_template *q; |
150 | int err = -EEXIST; | 245 | int err = -EEXIST; |
151 | 246 | ||
152 | down_write(&crypto_alg_sem); | 247 | down_write(&crypto_alg_sem); |
153 | 248 | ||
154 | list_for_each_entry(q, &crypto_template_list, list) { | 249 | list_for_each_entry(q, &crypto_template_list, list) { |
155 | if (q == tmpl) | 250 | if (q == tmpl) |
156 | goto out; | 251 | goto out; |
157 | } | 252 | } |
158 | 253 | ||
159 | list_add(&tmpl->list, &crypto_template_list); | 254 | list_add(&tmpl->list, &crypto_template_list); |
160 | crypto_notify(CRYPTO_MSG_TMPL_REGISTER, tmpl); | 255 | crypto_notify(CRYPTO_MSG_TMPL_REGISTER, tmpl); |
161 | err = 0; | 256 | err = 0; |
162 | out: | 257 | out: |
163 | up_write(&crypto_alg_sem); | 258 | up_write(&crypto_alg_sem); |
164 | return err; | 259 | return err; |
165 | } | 260 | } |
166 | EXPORT_SYMBOL_GPL(crypto_register_template); | 261 | EXPORT_SYMBOL_GPL(crypto_register_template); |
167 | 262 | ||
168 | void crypto_unregister_template(struct crypto_template *tmpl) | 263 | void crypto_unregister_template(struct crypto_template *tmpl) |
169 | { | 264 | { |
170 | struct crypto_instance *inst; | 265 | struct crypto_instance *inst; |
171 | struct hlist_node *p, *n; | 266 | struct hlist_node *p, *n; |
172 | struct hlist_head *list; | 267 | struct hlist_head *list; |
268 | LIST_HEAD(users); | ||
173 | 269 | ||
174 | down_write(&crypto_alg_sem); | 270 | down_write(&crypto_alg_sem); |
175 | 271 | ||
176 | BUG_ON(list_empty(&tmpl->list)); | 272 | BUG_ON(list_empty(&tmpl->list)); |
177 | list_del_init(&tmpl->list); | 273 | list_del_init(&tmpl->list); |
178 | 274 | ||
179 | list = &tmpl->instances; | 275 | list = &tmpl->instances; |
180 | hlist_for_each_entry(inst, p, list, list) { | 276 | hlist_for_each_entry(inst, p, list, list) { |
181 | BUG_ON(list_empty(&inst->alg.cra_list)); | 277 | int err = crypto_remove_alg(&inst->alg, &users); |
182 | list_del_init(&inst->alg.cra_list); | 278 | BUG_ON(err); |
183 | crypto_notify(CRYPTO_MSG_ALG_UNREGISTER, &inst->alg); | ||
184 | } | 279 | } |
185 | 280 | ||
186 | crypto_notify(CRYPTO_MSG_TMPL_UNREGISTER, tmpl); | 281 | crypto_notify(CRYPTO_MSG_TMPL_UNREGISTER, tmpl); |
187 | 282 | ||
188 | up_write(&crypto_alg_sem); | 283 | up_write(&crypto_alg_sem); |
189 | 284 | ||
190 | hlist_for_each_entry_safe(inst, p, n, list, list) { | 285 | hlist_for_each_entry_safe(inst, p, n, list, list) { |
191 | BUG_ON(atomic_read(&inst->alg.cra_refcnt) != 1); | 286 | BUG_ON(atomic_read(&inst->alg.cra_refcnt) != 1); |
192 | tmpl->free(inst); | 287 | tmpl->free(inst); |
193 | } | 288 | } |
289 | crypto_remove_final(&users); | ||
194 | } | 290 | } |
195 | EXPORT_SYMBOL_GPL(crypto_unregister_template); | 291 | EXPORT_SYMBOL_GPL(crypto_unregister_template); |
196 | 292 | ||
197 | static struct crypto_template *__crypto_lookup_template(const char *name) | 293 | static struct crypto_template *__crypto_lookup_template(const char *name) |
198 | { | 294 | { |
199 | struct crypto_template *q, *tmpl = NULL; | 295 | struct crypto_template *q, *tmpl = NULL; |
200 | 296 | ||
201 | down_read(&crypto_alg_sem); | 297 | down_read(&crypto_alg_sem); |
202 | list_for_each_entry(q, &crypto_template_list, list) { | 298 | list_for_each_entry(q, &crypto_template_list, list) { |
203 | if (strcmp(q->name, name)) | 299 | if (strcmp(q->name, name)) |
204 | continue; | 300 | continue; |
205 | if (unlikely(!crypto_tmpl_get(q))) | 301 | if (unlikely(!crypto_tmpl_get(q))) |
206 | continue; | 302 | continue; |
207 | 303 | ||
208 | tmpl = q; | 304 | tmpl = q; |
209 | break; | 305 | break; |
210 | } | 306 | } |
211 | up_read(&crypto_alg_sem); | 307 | up_read(&crypto_alg_sem); |
212 | 308 | ||
213 | return tmpl; | 309 | return tmpl; |
214 | } | 310 | } |
215 | 311 | ||
216 | struct crypto_template *crypto_lookup_template(const char *name) | 312 | struct crypto_template *crypto_lookup_template(const char *name) |
217 | { | 313 | { |
218 | return try_then_request_module(__crypto_lookup_template(name), name); | 314 | return try_then_request_module(__crypto_lookup_template(name), name); |
219 | } | 315 | } |
220 | EXPORT_SYMBOL_GPL(crypto_lookup_template); | 316 | EXPORT_SYMBOL_GPL(crypto_lookup_template); |
221 | 317 | ||
222 | int crypto_register_instance(struct crypto_template *tmpl, | 318 | int crypto_register_instance(struct crypto_template *tmpl, |
223 | struct crypto_instance *inst) | 319 | struct crypto_instance *inst) |
224 | { | 320 | { |
321 | LIST_HEAD(list); | ||
225 | int err = -EINVAL; | 322 | int err = -EINVAL; |
226 | 323 | ||
227 | if (inst->alg.cra_destroy) | 324 | if (inst->alg.cra_destroy) |
228 | goto err; | 325 | goto err; |
229 | 326 | ||
230 | err = crypto_check_alg(&inst->alg); | 327 | err = crypto_check_alg(&inst->alg); |
231 | if (err) | 328 | if (err) |
232 | goto err; | 329 | goto err; |
233 | 330 | ||
234 | inst->alg.cra_module = tmpl->module; | 331 | inst->alg.cra_module = tmpl->module; |
235 | 332 | ||
236 | down_write(&crypto_alg_sem); | 333 | down_write(&crypto_alg_sem); |
237 | 334 | ||
238 | err = __crypto_register_alg(&inst->alg); | 335 | err = __crypto_register_alg(&inst->alg, &list); |
239 | if (err) | 336 | if (err) |
240 | goto unlock; | 337 | goto unlock; |
241 | 338 | ||
242 | hlist_add_head(&inst->list, &tmpl->instances); | 339 | hlist_add_head(&inst->list, &tmpl->instances); |
243 | inst->tmpl = tmpl; | 340 | inst->tmpl = tmpl; |
244 | 341 | ||
245 | unlock: | 342 | unlock: |
246 | up_write(&crypto_alg_sem); | 343 | up_write(&crypto_alg_sem); |
247 | 344 | ||
345 | crypto_remove_final(&list); | ||
346 | |||
248 | err: | 347 | err: |
249 | return err; | 348 | return err; |
250 | } | 349 | } |
251 | EXPORT_SYMBOL_GPL(crypto_register_instance); | 350 | EXPORT_SYMBOL_GPL(crypto_register_instance); |
351 | |||
352 | int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg, | ||
353 | struct crypto_instance *inst) | ||
354 | { | ||
355 | int err = -EAGAIN; | ||
356 | |||
357 | spawn->inst = inst; | ||
358 | |||
359 | down_write(&crypto_alg_sem); | ||
360 | if (!crypto_is_moribund(alg)) { | ||
361 | list_add(&spawn->list, &alg->cra_users); | ||
362 | spawn->alg = alg; | ||
363 | err = 0; | ||
364 | } | ||
365 | up_write(&crypto_alg_sem); | ||
366 | |||
367 | return err; | ||
368 | } | ||
369 | EXPORT_SYMBOL_GPL(crypto_init_spawn); | ||
370 | |||
371 | void crypto_drop_spawn(struct crypto_spawn *spawn) | ||
372 | { | ||
373 | down_write(&crypto_alg_sem); | ||
374 | list_del(&spawn->list); | ||
375 | up_write(&crypto_alg_sem); | ||
376 | } | ||
377 | EXPORT_SYMBOL_GPL(crypto_drop_spawn); | ||
378 | |||
379 | struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn) | ||
380 | { | ||
381 | struct crypto_alg *alg; | ||
382 | struct crypto_alg *alg2; | ||
383 | struct crypto_tfm *tfm; | ||
384 | |||
385 | down_read(&crypto_alg_sem); | ||
386 | alg = spawn->alg; | ||
387 | alg2 = alg; | ||
388 | if (alg2) | ||
389 | alg2 = crypto_mod_get(alg2); | ||
390 | up_read(&crypto_alg_sem); | ||
391 | |||
392 | if (!alg2) { | ||
393 | if (alg) | ||
394 | crypto_shoot_alg(alg); | ||
395 | return ERR_PTR(-EAGAIN); | ||
396 | } | ||
397 | |||
398 | tfm = __crypto_alloc_tfm(alg, 0); | ||
399 | if (IS_ERR(tfm)) | ||
400 | crypto_mod_put(alg); | ||
401 | |||
402 | return tfm; | ||
403 | } | ||
404 | EXPORT_SYMBOL_GPL(crypto_spawn_tfm); | ||
252 | 405 | ||
253 | int crypto_register_notifier(struct notifier_block *nb) | 406 | int crypto_register_notifier(struct notifier_block *nb) |
254 | { | 407 | { |
255 | return blocking_notifier_chain_register(&crypto_chain, nb); | 408 | return blocking_notifier_chain_register(&crypto_chain, nb); |
256 | } | 409 | } |
257 | EXPORT_SYMBOL_GPL(crypto_register_notifier); | 410 | EXPORT_SYMBOL_GPL(crypto_register_notifier); |
258 | 411 | ||
259 | int crypto_unregister_notifier(struct notifier_block *nb) | 412 | int crypto_unregister_notifier(struct notifier_block *nb) |
260 | { | 413 | { |
261 | return blocking_notifier_chain_unregister(&crypto_chain, nb); | 414 | return blocking_notifier_chain_unregister(&crypto_chain, nb); |
262 | } | 415 | } |
263 | EXPORT_SYMBOL_GPL(crypto_unregister_notifier); | 416 | EXPORT_SYMBOL_GPL(crypto_unregister_notifier); |
264 | 417 | ||
265 | static int __init crypto_algapi_init(void) | 418 | static int __init crypto_algapi_init(void) |
266 | { | 419 | { |
267 | crypto_init_proc(); | 420 | crypto_init_proc(); |
268 | return 0; | 421 | return 0; |
269 | } | 422 | } |
270 | 423 | ||
271 | static void __exit crypto_algapi_exit(void) | 424 | static void __exit crypto_algapi_exit(void) |
272 | { | 425 | { |
273 | crypto_exit_proc(); | 426 | crypto_exit_proc(); |
274 | } | 427 | } |
275 | 428 | ||
276 | module_init(crypto_algapi_init); | 429 | module_init(crypto_algapi_init); |
crypto/api.c
1 | /* | 1 | /* |
2 | * Scatterlist Cryptographic API. | 2 | * Scatterlist Cryptographic API. |
3 | * | 3 | * |
4 | * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> | 4 | * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> |
5 | * Copyright (c) 2002 David S. Miller (davem@redhat.com) | 5 | * Copyright (c) 2002 David S. Miller (davem@redhat.com) |
6 | * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au> | 6 | * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au> |
7 | * | 7 | * |
8 | * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no> | 8 | * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no> |
9 | * and Nettle, by Niels Mรถller. | 9 | * and Nettle, by Niels Mรถller. |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify it | 11 | * This program is free software; you can redistribute it and/or modify it |
12 | * under the terms of the GNU General Public License as published by the Free | 12 | * under the terms of the GNU General Public License as published by the Free |
13 | * Software Foundation; either version 2 of the License, or (at your option) | 13 | * Software Foundation; either version 2 of the License, or (at your option) |
14 | * any later version. | 14 | * any later version. |
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/err.h> | ||
18 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
19 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
20 | #include <linux/kmod.h> | 21 | #include <linux/kmod.h> |
21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
22 | #include <linux/param.h> | 23 | #include <linux/param.h> |
24 | #include <linux/sched.h> | ||
23 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
24 | #include <linux/string.h> | 26 | #include <linux/string.h> |
25 | #include "internal.h" | 27 | #include "internal.h" |
26 | 28 | ||
27 | LIST_HEAD(crypto_alg_list); | 29 | LIST_HEAD(crypto_alg_list); |
28 | EXPORT_SYMBOL_GPL(crypto_alg_list); | 30 | EXPORT_SYMBOL_GPL(crypto_alg_list); |
29 | DECLARE_RWSEM(crypto_alg_sem); | 31 | DECLARE_RWSEM(crypto_alg_sem); |
30 | EXPORT_SYMBOL_GPL(crypto_alg_sem); | 32 | EXPORT_SYMBOL_GPL(crypto_alg_sem); |
31 | 33 | ||
32 | BLOCKING_NOTIFIER_HEAD(crypto_chain); | 34 | BLOCKING_NOTIFIER_HEAD(crypto_chain); |
33 | EXPORT_SYMBOL_GPL(crypto_chain); | 35 | EXPORT_SYMBOL_GPL(crypto_chain); |
34 | 36 | ||
35 | static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg) | 37 | static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg) |
36 | { | 38 | { |
37 | atomic_inc(&alg->cra_refcnt); | 39 | atomic_inc(&alg->cra_refcnt); |
38 | return alg; | 40 | return alg; |
39 | } | 41 | } |
40 | 42 | ||
41 | static inline void crypto_alg_put(struct crypto_alg *alg) | ||
42 | { | ||
43 | if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy) | ||
44 | alg->cra_destroy(alg); | ||
45 | } | ||
46 | |||
47 | struct crypto_alg *crypto_mod_get(struct crypto_alg *alg) | 43 | struct crypto_alg *crypto_mod_get(struct crypto_alg *alg) |
48 | { | 44 | { |
49 | return try_module_get(alg->cra_module) ? crypto_alg_get(alg) : NULL; | 45 | return try_module_get(alg->cra_module) ? crypto_alg_get(alg) : NULL; |
50 | } | 46 | } |
51 | EXPORT_SYMBOL_GPL(crypto_mod_get); | 47 | EXPORT_SYMBOL_GPL(crypto_mod_get); |
52 | 48 | ||
53 | void crypto_mod_put(struct crypto_alg *alg) | 49 | void crypto_mod_put(struct crypto_alg *alg) |
54 | { | 50 | { |
55 | crypto_alg_put(alg); | 51 | crypto_alg_put(alg); |
56 | module_put(alg->cra_module); | 52 | module_put(alg->cra_module); |
57 | } | 53 | } |
58 | EXPORT_SYMBOL_GPL(crypto_mod_put); | 54 | EXPORT_SYMBOL_GPL(crypto_mod_put); |
59 | 55 | ||
60 | struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask) | 56 | struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask) |
61 | { | 57 | { |
62 | struct crypto_alg *q, *alg = NULL; | 58 | struct crypto_alg *q, *alg = NULL; |
63 | int best = -2; | 59 | int best = -2; |
64 | 60 | ||
65 | list_for_each_entry(q, &crypto_alg_list, cra_list) { | 61 | list_for_each_entry(q, &crypto_alg_list, cra_list) { |
66 | int exact, fuzzy; | 62 | int exact, fuzzy; |
67 | 63 | ||
64 | if (crypto_is_moribund(q)) | ||
65 | continue; | ||
66 | |||
68 | if ((q->cra_flags ^ type) & mask) | 67 | if ((q->cra_flags ^ type) & mask) |
69 | continue; | 68 | continue; |
70 | 69 | ||
71 | if (crypto_is_larval(q) && | 70 | if (crypto_is_larval(q) && |
72 | ((struct crypto_larval *)q)->mask != mask) | 71 | ((struct crypto_larval *)q)->mask != mask) |
73 | continue; | 72 | continue; |
74 | 73 | ||
75 | exact = !strcmp(q->cra_driver_name, name); | 74 | exact = !strcmp(q->cra_driver_name, name); |
76 | fuzzy = !strcmp(q->cra_name, name); | 75 | fuzzy = !strcmp(q->cra_name, name); |
77 | if (!exact && !(fuzzy && q->cra_priority > best)) | 76 | if (!exact && !(fuzzy && q->cra_priority > best)) |
78 | continue; | 77 | continue; |
79 | 78 | ||
80 | if (unlikely(!crypto_mod_get(q))) | 79 | if (unlikely(!crypto_mod_get(q))) |
81 | continue; | 80 | continue; |
82 | 81 | ||
83 | best = q->cra_priority; | 82 | best = q->cra_priority; |
84 | if (alg) | 83 | if (alg) |
85 | crypto_mod_put(alg); | 84 | crypto_mod_put(alg); |
86 | alg = q; | 85 | alg = q; |
87 | 86 | ||
88 | if (exact) | 87 | if (exact) |
89 | break; | 88 | break; |
90 | } | 89 | } |
91 | 90 | ||
92 | return alg; | 91 | return alg; |
93 | } | 92 | } |
94 | EXPORT_SYMBOL_GPL(__crypto_alg_lookup); | 93 | EXPORT_SYMBOL_GPL(__crypto_alg_lookup); |
95 | 94 | ||
96 | static void crypto_larval_destroy(struct crypto_alg *alg) | 95 | static void crypto_larval_destroy(struct crypto_alg *alg) |
97 | { | 96 | { |
98 | struct crypto_larval *larval = (void *)alg; | 97 | struct crypto_larval *larval = (void *)alg; |
99 | 98 | ||
100 | BUG_ON(!crypto_is_larval(alg)); | 99 | BUG_ON(!crypto_is_larval(alg)); |
101 | if (larval->adult) | 100 | if (larval->adult) |
102 | crypto_mod_put(larval->adult); | 101 | crypto_mod_put(larval->adult); |
103 | kfree(larval); | 102 | kfree(larval); |
104 | } | 103 | } |
105 | 104 | ||
106 | static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type, | 105 | static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type, |
107 | u32 mask) | 106 | u32 mask) |
108 | { | 107 | { |
109 | struct crypto_alg *alg; | 108 | struct crypto_alg *alg; |
110 | struct crypto_larval *larval; | 109 | struct crypto_larval *larval; |
111 | 110 | ||
112 | larval = kzalloc(sizeof(*larval), GFP_KERNEL); | 111 | larval = kzalloc(sizeof(*larval), GFP_KERNEL); |
113 | if (!larval) | 112 | if (!larval) |
114 | return NULL; | 113 | return ERR_PTR(-ENOMEM); |
115 | 114 | ||
116 | larval->mask = mask; | 115 | larval->mask = mask; |
117 | larval->alg.cra_flags = CRYPTO_ALG_LARVAL | type; | 116 | larval->alg.cra_flags = CRYPTO_ALG_LARVAL | type; |
118 | larval->alg.cra_priority = -1; | 117 | larval->alg.cra_priority = -1; |
119 | larval->alg.cra_destroy = crypto_larval_destroy; | 118 | larval->alg.cra_destroy = crypto_larval_destroy; |
120 | 119 | ||
121 | atomic_set(&larval->alg.cra_refcnt, 2); | 120 | atomic_set(&larval->alg.cra_refcnt, 2); |
122 | strlcpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME); | 121 | strlcpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME); |
123 | init_completion(&larval->completion); | 122 | init_completion(&larval->completion); |
124 | 123 | ||
125 | down_write(&crypto_alg_sem); | 124 | down_write(&crypto_alg_sem); |
126 | alg = __crypto_alg_lookup(name, type, mask); | 125 | alg = __crypto_alg_lookup(name, type, mask); |
127 | if (!alg) { | 126 | if (!alg) { |
128 | alg = &larval->alg; | 127 | alg = &larval->alg; |
129 | list_add(&alg->cra_list, &crypto_alg_list); | 128 | list_add(&alg->cra_list, &crypto_alg_list); |
130 | } | 129 | } |
131 | up_write(&crypto_alg_sem); | 130 | up_write(&crypto_alg_sem); |
132 | 131 | ||
133 | if (alg != &larval->alg) | 132 | if (alg != &larval->alg) |
134 | kfree(larval); | 133 | kfree(larval); |
135 | 134 | ||
136 | return alg; | 135 | return alg; |
137 | } | 136 | } |
138 | 137 | ||
139 | static void crypto_larval_kill(struct crypto_alg *alg) | 138 | static void crypto_larval_kill(struct crypto_alg *alg) |
140 | { | 139 | { |
141 | struct crypto_larval *larval = (void *)alg; | 140 | struct crypto_larval *larval = (void *)alg; |
142 | 141 | ||
143 | down_write(&crypto_alg_sem); | 142 | down_write(&crypto_alg_sem); |
144 | list_del(&alg->cra_list); | 143 | list_del(&alg->cra_list); |
145 | up_write(&crypto_alg_sem); | 144 | up_write(&crypto_alg_sem); |
146 | complete(&larval->completion); | 145 | complete(&larval->completion); |
147 | crypto_alg_put(alg); | 146 | crypto_alg_put(alg); |
148 | } | 147 | } |
149 | 148 | ||
150 | static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) | 149 | static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg) |
151 | { | 150 | { |
152 | struct crypto_larval *larval = (void *)alg; | 151 | struct crypto_larval *larval = (void *)alg; |
153 | 152 | ||
154 | wait_for_completion_interruptible_timeout(&larval->completion, 60 * HZ); | 153 | wait_for_completion_interruptible_timeout(&larval->completion, 60 * HZ); |
155 | alg = larval->adult; | 154 | alg = larval->adult; |
156 | if (alg && !crypto_mod_get(alg)) | 155 | if (alg) { |
157 | alg = NULL; | 156 | if (!crypto_mod_get(alg)) |
157 | alg = ERR_PTR(-EAGAIN); | ||
158 | } else | ||
159 | alg = ERR_PTR(-ENOENT); | ||
158 | crypto_mod_put(&larval->alg); | 160 | crypto_mod_put(&larval->alg); |
159 | 161 | ||
160 | return alg; | 162 | return alg; |
161 | } | 163 | } |
162 | 164 | ||
163 | static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type, | 165 | static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type, |
164 | u32 mask) | 166 | u32 mask) |
165 | { | 167 | { |
166 | struct crypto_alg *alg; | 168 | struct crypto_alg *alg; |
167 | 169 | ||
168 | if (!name) | ||
169 | return NULL; | ||
170 | |||
171 | down_read(&crypto_alg_sem); | 170 | down_read(&crypto_alg_sem); |
172 | alg = __crypto_alg_lookup(name, type, mask); | 171 | alg = __crypto_alg_lookup(name, type, mask); |
173 | up_read(&crypto_alg_sem); | 172 | up_read(&crypto_alg_sem); |
174 | 173 | ||
175 | return alg; | 174 | return alg; |
176 | } | 175 | } |
177 | 176 | ||
178 | struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask) | 177 | struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask) |
179 | { | 178 | { |
180 | struct crypto_alg *alg; | 179 | struct crypto_alg *alg; |
181 | struct crypto_alg *larval; | 180 | struct crypto_alg *larval; |
182 | int ok; | 181 | int ok; |
183 | 182 | ||
184 | mask &= ~CRYPTO_ALG_LARVAL; | 183 | if (!name) |
184 | return ERR_PTR(-ENOENT); | ||
185 | |||
186 | mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD); | ||
185 | type &= mask; | 187 | type &= mask; |
186 | 188 | ||
187 | alg = try_then_request_module(crypto_alg_lookup(name, type, mask), | 189 | alg = try_then_request_module(crypto_alg_lookup(name, type, mask), |
188 | name); | 190 | name); |
189 | if (alg) | 191 | if (alg) |
190 | return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg; | 192 | return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg; |
191 | 193 | ||
192 | larval = crypto_larval_alloc(name, type, mask); | 194 | larval = crypto_larval_alloc(name, type, mask); |
193 | if (!larval || !crypto_is_larval(larval)) | 195 | if (IS_ERR(larval) || !crypto_is_larval(larval)) |
194 | return larval; | 196 | return larval; |
195 | 197 | ||
196 | ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval); | 198 | ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval); |
197 | if (ok == NOTIFY_DONE) { | 199 | if (ok == NOTIFY_DONE) { |
198 | request_module("cryptomgr"); | 200 | request_module("cryptomgr"); |
199 | ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval); | 201 | ok = crypto_notify(CRYPTO_MSG_ALG_REQUEST, larval); |
200 | } | 202 | } |
201 | 203 | ||
202 | if (ok == NOTIFY_STOP) | 204 | if (ok == NOTIFY_STOP) |
203 | alg = crypto_larval_wait(larval); | 205 | alg = crypto_larval_wait(larval); |
204 | else { | 206 | else { |
205 | crypto_mod_put(larval); | 207 | crypto_mod_put(larval); |
206 | alg = NULL; | 208 | alg = ERR_PTR(-ENOENT); |
207 | } | 209 | } |
208 | crypto_larval_kill(larval); | 210 | crypto_larval_kill(larval); |
209 | return alg; | 211 | return alg; |
210 | } | 212 | } |
211 | EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup); | 213 | EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup); |
212 | 214 | ||
213 | static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags) | 215 | static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags) |
214 | { | 216 | { |
215 | tfm->crt_flags = flags & CRYPTO_TFM_REQ_MASK; | 217 | tfm->crt_flags = flags & CRYPTO_TFM_REQ_MASK; |
216 | flags &= ~CRYPTO_TFM_REQ_MASK; | 218 | flags &= ~CRYPTO_TFM_REQ_MASK; |
217 | 219 | ||
218 | switch (crypto_tfm_alg_type(tfm)) { | 220 | switch (crypto_tfm_alg_type(tfm)) { |
219 | case CRYPTO_ALG_TYPE_CIPHER: | 221 | case CRYPTO_ALG_TYPE_CIPHER: |
220 | return crypto_init_cipher_flags(tfm, flags); | 222 | return crypto_init_cipher_flags(tfm, flags); |
221 | 223 | ||
222 | case CRYPTO_ALG_TYPE_DIGEST: | 224 | case CRYPTO_ALG_TYPE_DIGEST: |
223 | return crypto_init_digest_flags(tfm, flags); | 225 | return crypto_init_digest_flags(tfm, flags); |
224 | 226 | ||
225 | case CRYPTO_ALG_TYPE_COMPRESS: | 227 | case CRYPTO_ALG_TYPE_COMPRESS: |
226 | return crypto_init_compress_flags(tfm, flags); | 228 | return crypto_init_compress_flags(tfm, flags); |
227 | 229 | ||
228 | default: | 230 | default: |
229 | break; | 231 | break; |
230 | } | 232 | } |
231 | 233 | ||
232 | BUG(); | 234 | BUG(); |
233 | return -EINVAL; | 235 | return -EINVAL; |
234 | } | 236 | } |
235 | 237 | ||
236 | static int crypto_init_ops(struct crypto_tfm *tfm) | 238 | static int crypto_init_ops(struct crypto_tfm *tfm) |
237 | { | 239 | { |
238 | switch (crypto_tfm_alg_type(tfm)) { | 240 | switch (crypto_tfm_alg_type(tfm)) { |
239 | case CRYPTO_ALG_TYPE_CIPHER: | 241 | case CRYPTO_ALG_TYPE_CIPHER: |
240 | return crypto_init_cipher_ops(tfm); | 242 | return crypto_init_cipher_ops(tfm); |
241 | 243 | ||
242 | case CRYPTO_ALG_TYPE_DIGEST: | 244 | case CRYPTO_ALG_TYPE_DIGEST: |
243 | return crypto_init_digest_ops(tfm); | 245 | return crypto_init_digest_ops(tfm); |
244 | 246 | ||
245 | case CRYPTO_ALG_TYPE_COMPRESS: | 247 | case CRYPTO_ALG_TYPE_COMPRESS: |
246 | return crypto_init_compress_ops(tfm); | 248 | return crypto_init_compress_ops(tfm); |
247 | 249 | ||
248 | default: | 250 | default: |
249 | break; | 251 | break; |
250 | } | 252 | } |
251 | 253 | ||
252 | BUG(); | 254 | BUG(); |
253 | return -EINVAL; | 255 | return -EINVAL; |
254 | } | 256 | } |
255 | 257 | ||
256 | static void crypto_exit_ops(struct crypto_tfm *tfm) | 258 | static void crypto_exit_ops(struct crypto_tfm *tfm) |
257 | { | 259 | { |
258 | switch (crypto_tfm_alg_type(tfm)) { | 260 | switch (crypto_tfm_alg_type(tfm)) { |
259 | case CRYPTO_ALG_TYPE_CIPHER: | 261 | case CRYPTO_ALG_TYPE_CIPHER: |
260 | crypto_exit_cipher_ops(tfm); | 262 | crypto_exit_cipher_ops(tfm); |
261 | break; | 263 | break; |
262 | 264 | ||
263 | case CRYPTO_ALG_TYPE_DIGEST: | 265 | case CRYPTO_ALG_TYPE_DIGEST: |
264 | crypto_exit_digest_ops(tfm); | 266 | crypto_exit_digest_ops(tfm); |
265 | break; | 267 | break; |
266 | 268 | ||
267 | case CRYPTO_ALG_TYPE_COMPRESS: | 269 | case CRYPTO_ALG_TYPE_COMPRESS: |
268 | crypto_exit_compress_ops(tfm); | 270 | crypto_exit_compress_ops(tfm); |
269 | break; | 271 | break; |
270 | 272 | ||
271 | default: | 273 | default: |
272 | BUG(); | 274 | BUG(); |
273 | 275 | ||
274 | } | 276 | } |
275 | } | 277 | } |
276 | 278 | ||
277 | static unsigned int crypto_ctxsize(struct crypto_alg *alg, int flags) | 279 | static unsigned int crypto_ctxsize(struct crypto_alg *alg, int flags) |
278 | { | 280 | { |
279 | unsigned int len; | 281 | unsigned int len; |
280 | 282 | ||
281 | switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { | 283 | switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { |
282 | default: | 284 | default: |
283 | BUG(); | 285 | BUG(); |
284 | 286 | ||
285 | case CRYPTO_ALG_TYPE_CIPHER: | 287 | case CRYPTO_ALG_TYPE_CIPHER: |
286 | len = crypto_cipher_ctxsize(alg, flags); | 288 | len = crypto_cipher_ctxsize(alg, flags); |
287 | break; | 289 | break; |
288 | 290 | ||
289 | case CRYPTO_ALG_TYPE_DIGEST: | 291 | case CRYPTO_ALG_TYPE_DIGEST: |
290 | len = crypto_digest_ctxsize(alg, flags); | 292 | len = crypto_digest_ctxsize(alg, flags); |
291 | break; | 293 | break; |
292 | 294 | ||
293 | case CRYPTO_ALG_TYPE_COMPRESS: | 295 | case CRYPTO_ALG_TYPE_COMPRESS: |
294 | len = crypto_compress_ctxsize(alg, flags); | 296 | len = crypto_compress_ctxsize(alg, flags); |
295 | break; | 297 | break; |
296 | } | 298 | } |
297 | 299 | ||
298 | return len + (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1)); | 300 | return len + (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1)); |
299 | } | 301 | } |
300 | 302 | ||
301 | struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) | 303 | void crypto_shoot_alg(struct crypto_alg *alg) |
302 | { | 304 | { |
305 | down_write(&crypto_alg_sem); | ||
306 | alg->cra_flags |= CRYPTO_ALG_DYING; | ||
307 | up_write(&crypto_alg_sem); | ||
308 | } | ||
309 | EXPORT_SYMBOL_GPL(crypto_shoot_alg); | ||
310 | |||
311 | struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags) | ||
312 | { | ||
303 | struct crypto_tfm *tfm = NULL; | 313 | struct crypto_tfm *tfm = NULL; |
304 | struct crypto_alg *alg; | ||
305 | unsigned int tfm_size; | 314 | unsigned int tfm_size; |
315 | int err = -ENOMEM; | ||
306 | 316 | ||
307 | alg = crypto_alg_mod_lookup(name, 0, 0); | ||
308 | if (alg == NULL) | ||
309 | goto out; | ||
310 | |||
311 | tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, flags); | 317 | tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, flags); |
312 | tfm = kzalloc(tfm_size, GFP_KERNEL); | 318 | tfm = kzalloc(tfm_size, GFP_KERNEL); |
313 | if (tfm == NULL) | 319 | if (tfm == NULL) |
314 | goto out_put; | 320 | goto out; |
315 | 321 | ||
316 | tfm->__crt_alg = alg; | 322 | tfm->__crt_alg = alg; |
317 | 323 | ||
318 | if (crypto_init_flags(tfm, flags)) | 324 | err = crypto_init_flags(tfm, flags); |
325 | if (err) | ||
319 | goto out_free_tfm; | 326 | goto out_free_tfm; |
320 | 327 | ||
321 | if (crypto_init_ops(tfm)) | 328 | err = crypto_init_ops(tfm); |
329 | if (err) | ||
322 | goto out_free_tfm; | 330 | goto out_free_tfm; |
323 | 331 | ||
324 | if (alg->cra_init && alg->cra_init(tfm)) | 332 | if (alg->cra_init && (err = alg->cra_init(tfm))) { |
333 | if (err == -EAGAIN) | ||
334 | crypto_shoot_alg(alg); | ||
325 | goto cra_init_failed; | 335 | goto cra_init_failed; |
336 | } | ||
326 | 337 | ||
327 | goto out; | 338 | goto out; |
328 | 339 | ||
329 | cra_init_failed: | 340 | cra_init_failed: |
330 | crypto_exit_ops(tfm); | 341 | crypto_exit_ops(tfm); |
331 | out_free_tfm: | 342 | out_free_tfm: |
332 | kfree(tfm); | 343 | kfree(tfm); |
333 | tfm = NULL; | 344 | tfm = ERR_PTR(err); |
334 | out_put: | ||
335 | crypto_mod_put(alg); | ||
336 | out: | 345 | out: |
337 | return tfm; | 346 | return tfm; |
338 | } | 347 | } |
348 | EXPORT_SYMBOL_GPL(__crypto_alloc_tfm); | ||
339 | 349 | ||
350 | struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) | ||
351 | { | ||
352 | struct crypto_tfm *tfm = NULL; | ||
353 | int err; | ||
354 | |||
355 | do { | ||
356 | struct crypto_alg *alg; | ||
357 | |||
358 | alg = crypto_alg_mod_lookup(name, 0, 0); | ||
359 | err = PTR_ERR(alg); | ||
360 | if (IS_ERR(alg)) | ||
361 | continue; | ||
362 | |||
363 | tfm = __crypto_alloc_tfm(alg, flags); | ||
364 | err = 0; | ||
365 | if (IS_ERR(tfm)) { | ||
366 | crypto_mod_put(alg); | ||
367 | err = PTR_ERR(tfm); | ||
368 | tfm = NULL; | ||
369 | } | ||
370 | } while (err == -EAGAIN && !signal_pending(current)); | ||
371 | |||
372 | return tfm; | ||
373 | } | ||
374 | |||
340 | void crypto_free_tfm(struct crypto_tfm *tfm) | 375 | void crypto_free_tfm(struct crypto_tfm *tfm) |
341 | { | 376 | { |
342 | struct crypto_alg *alg; | 377 | struct crypto_alg *alg; |
343 | int size; | 378 | int size; |
344 | 379 | ||
345 | if (unlikely(!tfm)) | 380 | if (unlikely(!tfm)) |
346 | return; | 381 | return; |
347 | 382 | ||
348 | alg = tfm->__crt_alg; | 383 | alg = tfm->__crt_alg; |
349 | size = sizeof(*tfm) + alg->cra_ctxsize; | 384 | size = sizeof(*tfm) + alg->cra_ctxsize; |
350 | 385 | ||
351 | if (alg->cra_exit) | 386 | if (alg->cra_exit) |
352 | alg->cra_exit(tfm); | 387 | alg->cra_exit(tfm); |
353 | crypto_exit_ops(tfm); | 388 | crypto_exit_ops(tfm); |
354 | crypto_mod_put(alg); | 389 | crypto_mod_put(alg); |
355 | memset(tfm, 0, size); | 390 | memset(tfm, 0, size); |
356 | kfree(tfm); | 391 | kfree(tfm); |
357 | } | 392 | } |
358 | 393 | ||
359 | int crypto_alg_available(const char *name, u32 flags) | 394 | int crypto_alg_available(const char *name, u32 flags) |
crypto/cryptomgr.c
1 | /* | 1 | /* |
2 | * Create default crypto algorithm instances. | 2 | * Create default crypto algorithm instances. |
3 | * | 3 | * |
4 | * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> | 4 | * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the Free | 7 | * under the terms of the GNU General Public License as published by the Free |
8 | * Software Foundation; either version 2 of the License, or (at your option) | 8 | * Software Foundation; either version 2 of the License, or (at your option) |
9 | * any later version. | 9 | * any later version. |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/crypto.h> | 13 | #include <linux/crypto.h> |
14 | #include <linux/ctype.h> | 14 | #include <linux/ctype.h> |
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/notifier.h> | 18 | #include <linux/notifier.h> |
19 | #include <linux/rtnetlink.h> | 19 | #include <linux/rtnetlink.h> |
20 | #include <linux/sched.h> | ||
20 | #include <linux/string.h> | 21 | #include <linux/string.h> |
21 | #include <linux/workqueue.h> | 22 | #include <linux/workqueue.h> |
22 | 23 | ||
23 | #include "internal.h" | 24 | #include "internal.h" |
24 | 25 | ||
25 | struct cryptomgr_param { | 26 | struct cryptomgr_param { |
26 | struct work_struct work; | 27 | struct work_struct work; |
27 | 28 | ||
28 | struct { | 29 | struct { |
29 | struct rtattr attr; | 30 | struct rtattr attr; |
30 | struct crypto_attr_alg data; | 31 | struct crypto_attr_alg data; |
31 | } alg; | 32 | } alg; |
32 | 33 | ||
33 | struct { | 34 | struct { |
34 | u32 type; | 35 | u32 type; |
35 | u32 mask; | 36 | u32 mask; |
36 | char name[CRYPTO_MAX_ALG_NAME]; | 37 | char name[CRYPTO_MAX_ALG_NAME]; |
37 | } larval; | 38 | } larval; |
38 | 39 | ||
39 | char template[CRYPTO_MAX_ALG_NAME]; | 40 | char template[CRYPTO_MAX_ALG_NAME]; |
40 | }; | 41 | }; |
41 | 42 | ||
42 | static void cryptomgr_probe(void *data) | 43 | static void cryptomgr_probe(void *data) |
43 | { | 44 | { |
44 | struct cryptomgr_param *param = data; | 45 | struct cryptomgr_param *param = data; |
45 | struct crypto_template *tmpl; | 46 | struct crypto_template *tmpl; |
46 | struct crypto_instance *inst; | 47 | struct crypto_instance *inst; |
48 | int err; | ||
47 | 49 | ||
48 | tmpl = crypto_lookup_template(param->template); | 50 | tmpl = crypto_lookup_template(param->template); |
49 | if (!tmpl) | 51 | if (!tmpl) |
50 | goto err; | 52 | goto err; |
51 | 53 | ||
52 | inst = tmpl->alloc(¶m->alg, sizeof(param->alg)); | 54 | do { |
53 | if (IS_ERR(inst)) | 55 | inst = tmpl->alloc(¶m->alg, sizeof(param->alg)); |
54 | goto err; | 56 | if (IS_ERR(inst)) |
55 | else if ((err = crypto_register_instance(tmpl, inst))) { | 57 | err = PTR_ERR(inst); |
56 | tmpl->free(inst); | 58 | else if ((err = crypto_register_instance(tmpl, inst))) |
57 | goto err; | 59 | tmpl->free(inst); |
58 | } | 60 | } while (err == -EAGAIN && !signal_pending(current)); |
59 | 61 | ||
60 | crypto_tmpl_put(tmpl); | 62 | crypto_tmpl_put(tmpl); |
63 | |||
64 | if (err) | ||
65 | goto err; | ||
61 | 66 | ||
62 | out: | 67 | out: |
63 | kfree(param); | 68 | kfree(param); |
64 | return; | 69 | return; |
65 | 70 | ||
66 | err: | 71 | err: |
67 | crypto_larval_error(param->larval.name, param->larval.type, | 72 | crypto_larval_error(param->larval.name, param->larval.type, |
68 | param->larval.mask); | 73 | param->larval.mask); |
69 | goto out; | 74 | goto out; |
70 | } | 75 | } |
71 | 76 | ||
72 | static int cryptomgr_schedule_probe(struct crypto_larval *larval) | 77 | static int cryptomgr_schedule_probe(struct crypto_larval *larval) |
73 | { | 78 | { |
74 | struct cryptomgr_param *param; | 79 | struct cryptomgr_param *param; |
75 | const char *name = larval->alg.cra_name; | 80 | const char *name = larval->alg.cra_name; |
76 | const char *p; | 81 | const char *p; |
77 | unsigned int len; | 82 | unsigned int len; |
78 | 83 | ||
79 | param = kmalloc(sizeof(*param), GFP_KERNEL); | 84 | param = kmalloc(sizeof(*param), GFP_KERNEL); |
80 | if (!param) | 85 | if (!param) |
81 | goto err; | 86 | goto err; |
82 | 87 | ||
83 | for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++) | 88 | for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++) |
84 | ; | 89 | ; |
85 | 90 | ||
86 | len = p - name; | 91 | len = p - name; |
87 | if (!len || *p != '(') | 92 | if (!len || *p != '(') |
88 | goto err_free_param; | 93 | goto err_free_param; |
89 | 94 | ||
90 | memcpy(param->template, name, len); | 95 | memcpy(param->template, name, len); |
91 | param->template[len] = 0; | 96 | param->template[len] = 0; |
92 | 97 | ||
93 | name = p + 1; | 98 | name = p + 1; |
94 | for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++) | 99 | for (p = name; isalnum(*p) || *p == '-' || *p == '_'; p++) |
95 | ; | 100 | ; |
96 | 101 | ||
97 | len = p - name; | 102 | len = p - name; |
98 | if (!len || *p != ')' || p[1]) | 103 | if (!len || *p != ')' || p[1]) |
99 | goto err_free_param; | 104 | goto err_free_param; |
100 | 105 | ||
101 | param->alg.attr.rta_len = sizeof(param->alg); | 106 | param->alg.attr.rta_len = sizeof(param->alg); |
102 | param->alg.attr.rta_type = CRYPTOA_ALG; | 107 | param->alg.attr.rta_type = CRYPTOA_ALG; |
103 | memcpy(param->alg.data.name, name, len); | 108 | memcpy(param->alg.data.name, name, len); |
104 | param->alg.data.name[len] = 0; | 109 | param->alg.data.name[len] = 0; |
105 | 110 | ||
106 | memcpy(param->larval.name, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME); | 111 | memcpy(param->larval.name, larval->alg.cra_name, CRYPTO_MAX_ALG_NAME); |
107 | param->larval.type = larval->alg.cra_flags; | 112 | param->larval.type = larval->alg.cra_flags; |
108 | param->larval.mask = larval->mask; | 113 | param->larval.mask = larval->mask; |
109 | 114 | ||
110 | INIT_WORK(¶m->work, cryptomgr_probe, param); | 115 | INIT_WORK(¶m->work, cryptomgr_probe, param); |
111 | schedule_work(¶m->work); | 116 | schedule_work(¶m->work); |
112 | 117 | ||
113 | return NOTIFY_STOP; | 118 | return NOTIFY_STOP; |
114 | 119 | ||
115 | err_free_param: | 120 | err_free_param: |
116 | kfree(param); | 121 | kfree(param); |
117 | err: | 122 | err: |
118 | return NOTIFY_OK; | 123 | return NOTIFY_OK; |
119 | } | 124 | } |
120 | 125 | ||
121 | static int cryptomgr_notify(struct notifier_block *this, unsigned long msg, | 126 | static int cryptomgr_notify(struct notifier_block *this, unsigned long msg, |
122 | void *data) | 127 | void *data) |
123 | { | 128 | { |
124 | switch (msg) { | 129 | switch (msg) { |
125 | case CRYPTO_MSG_ALG_REQUEST: | 130 | case CRYPTO_MSG_ALG_REQUEST: |
126 | return cryptomgr_schedule_probe(data); | 131 | return cryptomgr_schedule_probe(data); |
127 | } | 132 | } |
128 | 133 | ||
129 | return NOTIFY_DONE; | 134 | return NOTIFY_DONE; |
130 | } | 135 | } |
131 | 136 | ||
132 | static struct notifier_block cryptomgr_notifier = { | 137 | static struct notifier_block cryptomgr_notifier = { |
133 | .notifier_call = cryptomgr_notify, | 138 | .notifier_call = cryptomgr_notify, |
134 | }; | 139 | }; |
135 | 140 | ||
136 | static int __init cryptomgr_init(void) | 141 | static int __init cryptomgr_init(void) |
137 | { | 142 | { |
138 | return crypto_register_notifier(&cryptomgr_notifier); | 143 | return crypto_register_notifier(&cryptomgr_notifier); |
139 | } | 144 | } |
140 | 145 | ||
141 | static void __exit cryptomgr_exit(void) | 146 | static void __exit cryptomgr_exit(void) |
142 | { | 147 | { |
143 | int err = crypto_unregister_notifier(&cryptomgr_notifier); | 148 | int err = crypto_unregister_notifier(&cryptomgr_notifier); |
144 | BUG_ON(err); | 149 | BUG_ON(err); |
145 | } | 150 | } |
146 | 151 | ||
147 | module_init(cryptomgr_init); | 152 | module_init(cryptomgr_init); |
148 | module_exit(cryptomgr_exit); | 153 | module_exit(cryptomgr_exit); |
149 | 154 | ||
150 | MODULE_LICENSE("GPL"); | 155 | MODULE_LICENSE("GPL"); |
151 | MODULE_DESCRIPTION("Crypto Algorithm Manager"); | 156 | MODULE_DESCRIPTION("Crypto Algorithm Manager"); |
152 | 157 |
crypto/internal.h
1 | /* | 1 | /* |
2 | * Cryptographic API. | 2 | * Cryptographic API. |
3 | * | 3 | * |
4 | * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> | 4 | * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> |
5 | * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au> | 5 | * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
8 | * under the terms of the GNU General Public License as published by the Free | 8 | * under the terms of the GNU General Public License as published by the Free |
9 | * Software Foundation; either version 2 of the License, or (at your option) | 9 | * Software Foundation; either version 2 of the License, or (at your option) |
10 | * any later version. | 10 | * any later version. |
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | #ifndef _CRYPTO_INTERNAL_H | 13 | #ifndef _CRYPTO_INTERNAL_H |
14 | #define _CRYPTO_INTERNAL_H | 14 | #define _CRYPTO_INTERNAL_H |
15 | 15 | ||
16 | #include <crypto/algapi.h> | 16 | #include <crypto/algapi.h> |
17 | #include <linux/completion.h> | 17 | #include <linux/completion.h> |
18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
19 | #include <linux/highmem.h> | 19 | #include <linux/highmem.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/list.h> | 22 | #include <linux/list.h> |
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/notifier.h> | 25 | #include <linux/notifier.h> |
26 | #include <linux/rwsem.h> | 26 | #include <linux/rwsem.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <asm/kmap_types.h> | 28 | #include <asm/kmap_types.h> |
29 | 29 | ||
30 | /* Crypto notification events. */ | 30 | /* Crypto notification events. */ |
31 | enum { | 31 | enum { |
32 | CRYPTO_MSG_ALG_REQUEST, | 32 | CRYPTO_MSG_ALG_REQUEST, |
33 | CRYPTO_MSG_ALG_REGISTER, | 33 | CRYPTO_MSG_ALG_REGISTER, |
34 | CRYPTO_MSG_ALG_UNREGISTER, | 34 | CRYPTO_MSG_ALG_UNREGISTER, |
35 | CRYPTO_MSG_TMPL_REGISTER, | 35 | CRYPTO_MSG_TMPL_REGISTER, |
36 | CRYPTO_MSG_TMPL_UNREGISTER, | 36 | CRYPTO_MSG_TMPL_UNREGISTER, |
37 | }; | 37 | }; |
38 | 38 | ||
39 | struct crypto_instance; | 39 | struct crypto_instance; |
40 | struct crypto_template; | 40 | struct crypto_template; |
41 | 41 | ||
42 | struct crypto_larval { | 42 | struct crypto_larval { |
43 | struct crypto_alg alg; | 43 | struct crypto_alg alg; |
44 | struct crypto_alg *adult; | 44 | struct crypto_alg *adult; |
45 | struct completion completion; | 45 | struct completion completion; |
46 | u32 mask; | 46 | u32 mask; |
47 | }; | 47 | }; |
48 | 48 | ||
49 | extern struct list_head crypto_alg_list; | 49 | extern struct list_head crypto_alg_list; |
50 | extern struct rw_semaphore crypto_alg_sem; | 50 | extern struct rw_semaphore crypto_alg_sem; |
51 | extern struct blocking_notifier_head crypto_chain; | 51 | extern struct blocking_notifier_head crypto_chain; |
52 | 52 | ||
53 | extern enum km_type crypto_km_types[]; | 53 | extern enum km_type crypto_km_types[]; |
54 | 54 | ||
55 | static inline enum km_type crypto_kmap_type(int out) | 55 | static inline enum km_type crypto_kmap_type(int out) |
56 | { | 56 | { |
57 | return crypto_km_types[(in_softirq() ? 2 : 0) + out]; | 57 | return crypto_km_types[(in_softirq() ? 2 : 0) + out]; |
58 | } | 58 | } |
59 | 59 | ||
60 | static inline void *crypto_kmap(struct page *page, int out) | 60 | static inline void *crypto_kmap(struct page *page, int out) |
61 | { | 61 | { |
62 | return kmap_atomic(page, crypto_kmap_type(out)); | 62 | return kmap_atomic(page, crypto_kmap_type(out)); |
63 | } | 63 | } |
64 | 64 | ||
65 | static inline void crypto_kunmap(void *vaddr, int out) | 65 | static inline void crypto_kunmap(void *vaddr, int out) |
66 | { | 66 | { |
67 | kunmap_atomic(vaddr, crypto_kmap_type(out)); | 67 | kunmap_atomic(vaddr, crypto_kmap_type(out)); |
68 | } | 68 | } |
69 | 69 | ||
70 | static inline void crypto_yield(struct crypto_tfm *tfm) | 70 | static inline void crypto_yield(struct crypto_tfm *tfm) |
71 | { | 71 | { |
72 | if (tfm->crt_flags & CRYPTO_TFM_REQ_MAY_SLEEP) | 72 | if (tfm->crt_flags & CRYPTO_TFM_REQ_MAY_SLEEP) |
73 | cond_resched(); | 73 | cond_resched(); |
74 | } | 74 | } |
75 | 75 | ||
76 | #ifdef CONFIG_CRYPTO_HMAC | 76 | #ifdef CONFIG_CRYPTO_HMAC |
77 | int crypto_alloc_hmac_block(struct crypto_tfm *tfm); | 77 | int crypto_alloc_hmac_block(struct crypto_tfm *tfm); |
78 | void crypto_free_hmac_block(struct crypto_tfm *tfm); | 78 | void crypto_free_hmac_block(struct crypto_tfm *tfm); |
79 | #else | 79 | #else |
80 | static inline int crypto_alloc_hmac_block(struct crypto_tfm *tfm) | 80 | static inline int crypto_alloc_hmac_block(struct crypto_tfm *tfm) |
81 | { | 81 | { |
82 | return 0; | 82 | return 0; |
83 | } | 83 | } |
84 | 84 | ||
85 | static inline void crypto_free_hmac_block(struct crypto_tfm *tfm) | 85 | static inline void crypto_free_hmac_block(struct crypto_tfm *tfm) |
86 | { } | 86 | { } |
87 | #endif | 87 | #endif |
88 | 88 | ||
89 | #ifdef CONFIG_PROC_FS | 89 | #ifdef CONFIG_PROC_FS |
90 | void __init crypto_init_proc(void); | 90 | void __init crypto_init_proc(void); |
91 | void __exit crypto_exit_proc(void); | 91 | void __exit crypto_exit_proc(void); |
92 | #else | 92 | #else |
93 | static inline void crypto_init_proc(void) | 93 | static inline void crypto_init_proc(void) |
94 | { } | 94 | { } |
95 | static inline void crypto_exit_proc(void) | 95 | static inline void crypto_exit_proc(void) |
96 | { } | 96 | { } |
97 | #endif | 97 | #endif |
98 | 98 | ||
99 | static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg, | 99 | static inline unsigned int crypto_digest_ctxsize(struct crypto_alg *alg, |
100 | int flags) | 100 | int flags) |
101 | { | 101 | { |
102 | return alg->cra_ctxsize; | 102 | return alg->cra_ctxsize; |
103 | } | 103 | } |
104 | 104 | ||
105 | static inline unsigned int crypto_cipher_ctxsize(struct crypto_alg *alg, | 105 | static inline unsigned int crypto_cipher_ctxsize(struct crypto_alg *alg, |
106 | int flags) | 106 | int flags) |
107 | { | 107 | { |
108 | unsigned int len = alg->cra_ctxsize; | 108 | unsigned int len = alg->cra_ctxsize; |
109 | 109 | ||
110 | switch (flags & CRYPTO_TFM_MODE_MASK) { | 110 | switch (flags & CRYPTO_TFM_MODE_MASK) { |
111 | case CRYPTO_TFM_MODE_CBC: | 111 | case CRYPTO_TFM_MODE_CBC: |
112 | len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1); | 112 | len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1); |
113 | len += alg->cra_blocksize; | 113 | len += alg->cra_blocksize; |
114 | break; | 114 | break; |
115 | } | 115 | } |
116 | 116 | ||
117 | return len; | 117 | return len; |
118 | } | 118 | } |
119 | 119 | ||
120 | static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg, | 120 | static inline unsigned int crypto_compress_ctxsize(struct crypto_alg *alg, |
121 | int flags) | 121 | int flags) |
122 | { | 122 | { |
123 | return alg->cra_ctxsize; | 123 | return alg->cra_ctxsize; |
124 | } | 124 | } |
125 | 125 | ||
126 | struct crypto_alg *crypto_mod_get(struct crypto_alg *alg); | 126 | struct crypto_alg *crypto_mod_get(struct crypto_alg *alg); |
127 | void crypto_mod_put(struct crypto_alg *alg); | 127 | void crypto_mod_put(struct crypto_alg *alg); |
128 | struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask); | 128 | struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type, u32 mask); |
129 | struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask); | 129 | struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask); |
130 | 130 | ||
131 | int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags); | 131 | int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags); |
132 | int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags); | 132 | int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags); |
133 | int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags); | 133 | int crypto_init_compress_flags(struct crypto_tfm *tfm, u32 flags); |
134 | 134 | ||
135 | int crypto_init_digest_ops(struct crypto_tfm *tfm); | 135 | int crypto_init_digest_ops(struct crypto_tfm *tfm); |
136 | int crypto_init_cipher_ops(struct crypto_tfm *tfm); | 136 | int crypto_init_cipher_ops(struct crypto_tfm *tfm); |
137 | int crypto_init_compress_ops(struct crypto_tfm *tfm); | 137 | int crypto_init_compress_ops(struct crypto_tfm *tfm); |
138 | 138 | ||
139 | void crypto_exit_digest_ops(struct crypto_tfm *tfm); | 139 | void crypto_exit_digest_ops(struct crypto_tfm *tfm); |
140 | void crypto_exit_cipher_ops(struct crypto_tfm *tfm); | 140 | void crypto_exit_cipher_ops(struct crypto_tfm *tfm); |
141 | void crypto_exit_compress_ops(struct crypto_tfm *tfm); | 141 | void crypto_exit_compress_ops(struct crypto_tfm *tfm); |
142 | 142 | ||
143 | void crypto_larval_error(const char *name, u32 type, u32 mask); | 143 | void crypto_larval_error(const char *name, u32 type, u32 mask); |
144 | 144 | ||
145 | void crypto_shoot_alg(struct crypto_alg *alg); | ||
146 | struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 flags); | ||
147 | |||
145 | int crypto_register_instance(struct crypto_template *tmpl, | 148 | int crypto_register_instance(struct crypto_template *tmpl, |
146 | struct crypto_instance *inst); | 149 | struct crypto_instance *inst); |
147 | 150 | ||
148 | int crypto_register_notifier(struct notifier_block *nb); | 151 | int crypto_register_notifier(struct notifier_block *nb); |
149 | int crypto_unregister_notifier(struct notifier_block *nb); | 152 | int crypto_unregister_notifier(struct notifier_block *nb); |
150 | 153 | ||
154 | static inline void crypto_alg_put(struct crypto_alg *alg) | ||
155 | { | ||
156 | if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy) | ||
157 | alg->cra_destroy(alg); | ||
158 | } | ||
159 | |||
151 | static inline int crypto_tmpl_get(struct crypto_template *tmpl) | 160 | static inline int crypto_tmpl_get(struct crypto_template *tmpl) |
152 | { | 161 | { |
153 | return try_module_get(tmpl->module); | 162 | return try_module_get(tmpl->module); |
154 | } | 163 | } |
155 | 164 | ||
156 | static inline void crypto_tmpl_put(struct crypto_template *tmpl) | 165 | static inline void crypto_tmpl_put(struct crypto_template *tmpl) |
157 | { | 166 | { |
158 | module_put(tmpl->module); | 167 | module_put(tmpl->module); |
159 | } | 168 | } |
160 | 169 | ||
161 | static inline int crypto_is_larval(struct crypto_alg *alg) | 170 | static inline int crypto_is_larval(struct crypto_alg *alg) |
162 | { | 171 | { |
163 | return alg->cra_flags & CRYPTO_ALG_LARVAL; | 172 | return alg->cra_flags & CRYPTO_ALG_LARVAL; |
173 | } | ||
174 | |||
175 | static inline int crypto_is_dead(struct crypto_alg *alg) | ||
176 | { | ||
177 | return alg->cra_flags & CRYPTO_ALG_DEAD; | ||
178 | } | ||
179 | |||
180 | static inline int crypto_is_moribund(struct crypto_alg *alg) | ||
181 | { | ||
182 | return alg->cra_flags & (CRYPTO_ALG_DEAD | CRYPTO_ALG_DYING); | ||
164 | } | 183 | } |
165 | 184 | ||
166 | static inline int crypto_notify(unsigned long val, void *v) | 185 | static inline int crypto_notify(unsigned long val, void *v) |
167 | { | 186 | { |
168 | return blocking_notifier_call_chain(&crypto_chain, val, v); | 187 | return blocking_notifier_call_chain(&crypto_chain, val, v); |
169 | } | 188 | } |
170 | 189 | ||
171 | #endif /* _CRYPTO_INTERNAL_H */ | 190 | #endif /* _CRYPTO_INTERNAL_H */ |
172 | 191 | ||
173 | 192 |
include/crypto/algapi.h
1 | /* | 1 | /* |
2 | * Cryptographic API for algorithms (i.e., low-level API). | 2 | * Cryptographic API for algorithms (i.e., low-level API). |
3 | * | 3 | * |
4 | * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> | 4 | * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the Free | 7 | * under the terms of the GNU General Public License as published by the Free |
8 | * Software Foundation; either version 2 of the License, or (at your option) | 8 | * Software Foundation; either version 2 of the License, or (at your option) |
9 | * any later version. | 9 | * any later version. |
10 | * | 10 | * |
11 | */ | 11 | */ |
12 | #ifndef _CRYPTO_ALGAPI_H | 12 | #ifndef _CRYPTO_ALGAPI_H |
13 | #define _CRYPTO_ALGAPI_H | 13 | #define _CRYPTO_ALGAPI_H |
14 | 14 | ||
15 | #include <linux/crypto.h> | 15 | #include <linux/crypto.h> |
16 | 16 | ||
17 | struct module; | 17 | struct module; |
18 | 18 | ||
19 | struct crypto_instance { | 19 | struct crypto_instance { |
20 | struct crypto_alg alg; | 20 | struct crypto_alg alg; |
21 | 21 | ||
22 | struct crypto_template *tmpl; | 22 | struct crypto_template *tmpl; |
23 | struct hlist_node list; | 23 | struct hlist_node list; |
24 | 24 | ||
25 | void *__ctx[] CRYPTO_MINALIGN_ATTR; | 25 | void *__ctx[] CRYPTO_MINALIGN_ATTR; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | struct crypto_template { | 28 | struct crypto_template { |
29 | struct list_head list; | 29 | struct list_head list; |
30 | struct hlist_head instances; | 30 | struct hlist_head instances; |
31 | struct module *module; | 31 | struct module *module; |
32 | 32 | ||
33 | struct crypto_instance *(*alloc)(void *param, unsigned int len); | 33 | struct crypto_instance *(*alloc)(void *param, unsigned int len); |
34 | void (*free)(struct crypto_instance *inst); | 34 | void (*free)(struct crypto_instance *inst); |
35 | 35 | ||
36 | char name[CRYPTO_MAX_ALG_NAME]; | 36 | char name[CRYPTO_MAX_ALG_NAME]; |
37 | }; | 37 | }; |
38 | 38 | ||
39 | struct crypto_spawn { | ||
40 | struct list_head list; | ||
41 | struct crypto_alg *alg; | ||
42 | struct crypto_instance *inst; | ||
43 | }; | ||
44 | |||
39 | int crypto_register_template(struct crypto_template *tmpl); | 45 | int crypto_register_template(struct crypto_template *tmpl); |
40 | void crypto_unregister_template(struct crypto_template *tmpl); | 46 | void crypto_unregister_template(struct crypto_template *tmpl); |
41 | struct crypto_template *crypto_lookup_template(const char *name); | 47 | struct crypto_template *crypto_lookup_template(const char *name); |
48 | |||
49 | int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg, | ||
50 | struct crypto_instance *inst); | ||
51 | void crypto_drop_spawn(struct crypto_spawn *spawn); | ||
52 | struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn); | ||
42 | 53 | ||
43 | static inline void *crypto_instance_ctx(struct crypto_instance *inst) | 54 | static inline void *crypto_instance_ctx(struct crypto_instance *inst) |
44 | { | 55 | { |
45 | return inst->__ctx; | 56 | return inst->__ctx; |
46 | } | 57 | } |
47 | 58 | ||
48 | #endif /* _CRYPTO_ALGAPI_H */ | 59 | #endif /* _CRYPTO_ALGAPI_H */ |
49 | 60 | ||
50 | 61 |
include/linux/crypto.h
1 | /* | 1 | /* |
2 | * Scatterlist Cryptographic API. | 2 | * Scatterlist Cryptographic API. |
3 | * | 3 | * |
4 | * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> | 4 | * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> |
5 | * Copyright (c) 2002 David S. Miller (davem@redhat.com) | 5 | * Copyright (c) 2002 David S. Miller (davem@redhat.com) |
6 | * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au> | 6 | * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au> |
7 | * | 7 | * |
8 | * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no> | 8 | * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no> |
9 | * and Nettle, by Niels Mรถller. | 9 | * and Nettle, by Niels Mรถller. |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify it | 11 | * This program is free software; you can redistribute it and/or modify it |
12 | * under the terms of the GNU General Public License as published by the Free | 12 | * under the terms of the GNU General Public License as published by the Free |
13 | * Software Foundation; either version 2 of the License, or (at your option) | 13 | * Software Foundation; either version 2 of the License, or (at your option) |
14 | * any later version. | 14 | * any later version. |
15 | * | 15 | * |
16 | */ | 16 | */ |
17 | #ifndef _LINUX_CRYPTO_H | 17 | #ifndef _LINUX_CRYPTO_H |
18 | #define _LINUX_CRYPTO_H | 18 | #define _LINUX_CRYPTO_H |
19 | 19 | ||
20 | #include <asm/atomic.h> | 20 | #include <asm/atomic.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/string.h> | 26 | #include <linux/string.h> |
27 | #include <linux/uaccess.h> | 27 | #include <linux/uaccess.h> |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * Algorithm masks and types. | 30 | * Algorithm masks and types. |
31 | */ | 31 | */ |
32 | #define CRYPTO_ALG_TYPE_MASK 0x0000000f | 32 | #define CRYPTO_ALG_TYPE_MASK 0x0000000f |
33 | #define CRYPTO_ALG_TYPE_CIPHER 0x00000001 | 33 | #define CRYPTO_ALG_TYPE_CIPHER 0x00000001 |
34 | #define CRYPTO_ALG_TYPE_DIGEST 0x00000002 | 34 | #define CRYPTO_ALG_TYPE_DIGEST 0x00000002 |
35 | #define CRYPTO_ALG_TYPE_COMPRESS 0x00000004 | 35 | #define CRYPTO_ALG_TYPE_COMPRESS 0x00000004 |
36 | 36 | ||
37 | #define CRYPTO_ALG_LARVAL 0x00000010 | 37 | #define CRYPTO_ALG_LARVAL 0x00000010 |
38 | #define CRYPTO_ALG_DEAD 0x00000020 | ||
39 | #define CRYPTO_ALG_DYING 0x00000040 | ||
38 | 40 | ||
39 | /* | 41 | /* |
40 | * Transform masks and values (for crt_flags). | 42 | * Transform masks and values (for crt_flags). |
41 | */ | 43 | */ |
42 | #define CRYPTO_TFM_MODE_MASK 0x000000ff | 44 | #define CRYPTO_TFM_MODE_MASK 0x000000ff |
43 | #define CRYPTO_TFM_REQ_MASK 0x000fff00 | 45 | #define CRYPTO_TFM_REQ_MASK 0x000fff00 |
44 | #define CRYPTO_TFM_RES_MASK 0xfff00000 | 46 | #define CRYPTO_TFM_RES_MASK 0xfff00000 |
45 | 47 | ||
46 | #define CRYPTO_TFM_MODE_ECB 0x00000001 | 48 | #define CRYPTO_TFM_MODE_ECB 0x00000001 |
47 | #define CRYPTO_TFM_MODE_CBC 0x00000002 | 49 | #define CRYPTO_TFM_MODE_CBC 0x00000002 |
48 | #define CRYPTO_TFM_MODE_CFB 0x00000004 | 50 | #define CRYPTO_TFM_MODE_CFB 0x00000004 |
49 | #define CRYPTO_TFM_MODE_CTR 0x00000008 | 51 | #define CRYPTO_TFM_MODE_CTR 0x00000008 |
50 | 52 | ||
51 | #define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100 | 53 | #define CRYPTO_TFM_REQ_WEAK_KEY 0x00000100 |
52 | #define CRYPTO_TFM_REQ_MAY_SLEEP 0x00000200 | 54 | #define CRYPTO_TFM_REQ_MAY_SLEEP 0x00000200 |
53 | #define CRYPTO_TFM_RES_WEAK_KEY 0x00100000 | 55 | #define CRYPTO_TFM_RES_WEAK_KEY 0x00100000 |
54 | #define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000 | 56 | #define CRYPTO_TFM_RES_BAD_KEY_LEN 0x00200000 |
55 | #define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000 | 57 | #define CRYPTO_TFM_RES_BAD_KEY_SCHED 0x00400000 |
56 | #define CRYPTO_TFM_RES_BAD_BLOCK_LEN 0x00800000 | 58 | #define CRYPTO_TFM_RES_BAD_BLOCK_LEN 0x00800000 |
57 | #define CRYPTO_TFM_RES_BAD_FLAGS 0x01000000 | 59 | #define CRYPTO_TFM_RES_BAD_FLAGS 0x01000000 |
58 | 60 | ||
59 | /* | 61 | /* |
60 | * Miscellaneous stuff. | 62 | * Miscellaneous stuff. |
61 | */ | 63 | */ |
62 | #define CRYPTO_UNSPEC 0 | 64 | #define CRYPTO_UNSPEC 0 |
63 | #define CRYPTO_MAX_ALG_NAME 64 | 65 | #define CRYPTO_MAX_ALG_NAME 64 |
64 | 66 | ||
65 | #define CRYPTO_DIR_ENCRYPT 1 | 67 | #define CRYPTO_DIR_ENCRYPT 1 |
66 | #define CRYPTO_DIR_DECRYPT 0 | 68 | #define CRYPTO_DIR_DECRYPT 0 |
67 | 69 | ||
68 | /* | 70 | /* |
69 | * The macro CRYPTO_MINALIGN_ATTR (along with the void * type in the actual | 71 | * The macro CRYPTO_MINALIGN_ATTR (along with the void * type in the actual |
70 | * declaration) is used to ensure that the crypto_tfm context structure is | 72 | * declaration) is used to ensure that the crypto_tfm context structure is |
71 | * aligned correctly for the given architecture so that there are no alignment | 73 | * aligned correctly for the given architecture so that there are no alignment |
72 | * faults for C data types. In particular, this is required on platforms such | 74 | * faults for C data types. In particular, this is required on platforms such |
73 | * as arm where pointers are 32-bit aligned but there are data types such as | 75 | * as arm where pointers are 32-bit aligned but there are data types such as |
74 | * u64 which require 64-bit alignment. | 76 | * u64 which require 64-bit alignment. |
75 | */ | 77 | */ |
76 | #if defined(ARCH_KMALLOC_MINALIGN) | 78 | #if defined(ARCH_KMALLOC_MINALIGN) |
77 | #define CRYPTO_MINALIGN ARCH_KMALLOC_MINALIGN | 79 | #define CRYPTO_MINALIGN ARCH_KMALLOC_MINALIGN |
78 | #elif defined(ARCH_SLAB_MINALIGN) | 80 | #elif defined(ARCH_SLAB_MINALIGN) |
79 | #define CRYPTO_MINALIGN ARCH_SLAB_MINALIGN | 81 | #define CRYPTO_MINALIGN ARCH_SLAB_MINALIGN |
80 | #endif | 82 | #endif |
81 | 83 | ||
82 | #ifdef CRYPTO_MINALIGN | 84 | #ifdef CRYPTO_MINALIGN |
83 | #define CRYPTO_MINALIGN_ATTR __attribute__ ((__aligned__(CRYPTO_MINALIGN))) | 85 | #define CRYPTO_MINALIGN_ATTR __attribute__ ((__aligned__(CRYPTO_MINALIGN))) |
84 | #else | 86 | #else |
85 | #define CRYPTO_MINALIGN_ATTR | 87 | #define CRYPTO_MINALIGN_ATTR |
86 | #endif | 88 | #endif |
87 | 89 | ||
88 | struct scatterlist; | 90 | struct scatterlist; |
89 | struct crypto_tfm; | 91 | struct crypto_tfm; |
90 | 92 | ||
91 | struct cipher_desc { | 93 | struct cipher_desc { |
92 | struct crypto_tfm *tfm; | 94 | struct crypto_tfm *tfm; |
93 | void (*crfn)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); | 95 | void (*crfn)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); |
94 | unsigned int (*prfn)(const struct cipher_desc *desc, u8 *dst, | 96 | unsigned int (*prfn)(const struct cipher_desc *desc, u8 *dst, |
95 | const u8 *src, unsigned int nbytes); | 97 | const u8 *src, unsigned int nbytes); |
96 | void *info; | 98 | void *info; |
97 | }; | 99 | }; |
98 | 100 | ||
99 | /* | 101 | /* |
100 | * Algorithms: modular crypto algorithm implementations, managed | 102 | * Algorithms: modular crypto algorithm implementations, managed |
101 | * via crypto_register_alg() and crypto_unregister_alg(). | 103 | * via crypto_register_alg() and crypto_unregister_alg(). |
102 | */ | 104 | */ |
103 | struct cipher_alg { | 105 | struct cipher_alg { |
104 | unsigned int cia_min_keysize; | 106 | unsigned int cia_min_keysize; |
105 | unsigned int cia_max_keysize; | 107 | unsigned int cia_max_keysize; |
106 | int (*cia_setkey)(struct crypto_tfm *tfm, const u8 *key, | 108 | int (*cia_setkey)(struct crypto_tfm *tfm, const u8 *key, |
107 | unsigned int keylen, u32 *flags); | 109 | unsigned int keylen, u32 *flags); |
108 | void (*cia_encrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); | 110 | void (*cia_encrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); |
109 | void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); | 111 | void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src); |
110 | 112 | ||
111 | unsigned int (*cia_encrypt_ecb)(const struct cipher_desc *desc, | 113 | unsigned int (*cia_encrypt_ecb)(const struct cipher_desc *desc, |
112 | u8 *dst, const u8 *src, | 114 | u8 *dst, const u8 *src, |
113 | unsigned int nbytes); | 115 | unsigned int nbytes); |
114 | unsigned int (*cia_decrypt_ecb)(const struct cipher_desc *desc, | 116 | unsigned int (*cia_decrypt_ecb)(const struct cipher_desc *desc, |
115 | u8 *dst, const u8 *src, | 117 | u8 *dst, const u8 *src, |
116 | unsigned int nbytes); | 118 | unsigned int nbytes); |
117 | unsigned int (*cia_encrypt_cbc)(const struct cipher_desc *desc, | 119 | unsigned int (*cia_encrypt_cbc)(const struct cipher_desc *desc, |
118 | u8 *dst, const u8 *src, | 120 | u8 *dst, const u8 *src, |
119 | unsigned int nbytes); | 121 | unsigned int nbytes); |
120 | unsigned int (*cia_decrypt_cbc)(const struct cipher_desc *desc, | 122 | unsigned int (*cia_decrypt_cbc)(const struct cipher_desc *desc, |
121 | u8 *dst, const u8 *src, | 123 | u8 *dst, const u8 *src, |
122 | unsigned int nbytes); | 124 | unsigned int nbytes); |
123 | }; | 125 | }; |
124 | 126 | ||
125 | struct digest_alg { | 127 | struct digest_alg { |
126 | unsigned int dia_digestsize; | 128 | unsigned int dia_digestsize; |
127 | void (*dia_init)(struct crypto_tfm *tfm); | 129 | void (*dia_init)(struct crypto_tfm *tfm); |
128 | void (*dia_update)(struct crypto_tfm *tfm, const u8 *data, | 130 | void (*dia_update)(struct crypto_tfm *tfm, const u8 *data, |
129 | unsigned int len); | 131 | unsigned int len); |
130 | void (*dia_final)(struct crypto_tfm *tfm, u8 *out); | 132 | void (*dia_final)(struct crypto_tfm *tfm, u8 *out); |
131 | int (*dia_setkey)(struct crypto_tfm *tfm, const u8 *key, | 133 | int (*dia_setkey)(struct crypto_tfm *tfm, const u8 *key, |
132 | unsigned int keylen, u32 *flags); | 134 | unsigned int keylen, u32 *flags); |
133 | }; | 135 | }; |
134 | 136 | ||
135 | struct compress_alg { | 137 | struct compress_alg { |
136 | int (*coa_compress)(struct crypto_tfm *tfm, const u8 *src, | 138 | int (*coa_compress)(struct crypto_tfm *tfm, const u8 *src, |
137 | unsigned int slen, u8 *dst, unsigned int *dlen); | 139 | unsigned int slen, u8 *dst, unsigned int *dlen); |
138 | int (*coa_decompress)(struct crypto_tfm *tfm, const u8 *src, | 140 | int (*coa_decompress)(struct crypto_tfm *tfm, const u8 *src, |
139 | unsigned int slen, u8 *dst, unsigned int *dlen); | 141 | unsigned int slen, u8 *dst, unsigned int *dlen); |
140 | }; | 142 | }; |
141 | 143 | ||
142 | #define cra_cipher cra_u.cipher | 144 | #define cra_cipher cra_u.cipher |
143 | #define cra_digest cra_u.digest | 145 | #define cra_digest cra_u.digest |
144 | #define cra_compress cra_u.compress | 146 | #define cra_compress cra_u.compress |
145 | 147 | ||
146 | struct crypto_alg { | 148 | struct crypto_alg { |
147 | struct list_head cra_list; | 149 | struct list_head cra_list; |
150 | struct list_head cra_users; | ||
151 | |||
148 | u32 cra_flags; | 152 | u32 cra_flags; |
149 | unsigned int cra_blocksize; | 153 | unsigned int cra_blocksize; |
150 | unsigned int cra_ctxsize; | 154 | unsigned int cra_ctxsize; |
151 | unsigned int cra_alignmask; | 155 | unsigned int cra_alignmask; |
152 | 156 | ||
153 | int cra_priority; | 157 | int cra_priority; |
154 | atomic_t cra_refcnt; | 158 | atomic_t cra_refcnt; |
155 | 159 | ||
156 | char cra_name[CRYPTO_MAX_ALG_NAME]; | 160 | char cra_name[CRYPTO_MAX_ALG_NAME]; |
157 | char cra_driver_name[CRYPTO_MAX_ALG_NAME]; | 161 | char cra_driver_name[CRYPTO_MAX_ALG_NAME]; |
158 | 162 | ||
159 | union { | 163 | union { |
160 | struct cipher_alg cipher; | 164 | struct cipher_alg cipher; |
161 | struct digest_alg digest; | 165 | struct digest_alg digest; |
162 | struct compress_alg compress; | 166 | struct compress_alg compress; |
163 | } cra_u; | 167 | } cra_u; |
164 | 168 | ||
165 | int (*cra_init)(struct crypto_tfm *tfm); | 169 | int (*cra_init)(struct crypto_tfm *tfm); |
166 | void (*cra_exit)(struct crypto_tfm *tfm); | 170 | void (*cra_exit)(struct crypto_tfm *tfm); |
167 | void (*cra_destroy)(struct crypto_alg *alg); | 171 | void (*cra_destroy)(struct crypto_alg *alg); |
168 | 172 | ||
169 | struct module *cra_module; | 173 | struct module *cra_module; |
170 | }; | 174 | }; |
171 | 175 | ||
172 | /* | 176 | /* |
173 | * Algorithm registration interface. | 177 | * Algorithm registration interface. |
174 | */ | 178 | */ |
175 | int crypto_register_alg(struct crypto_alg *alg); | 179 | int crypto_register_alg(struct crypto_alg *alg); |
176 | int crypto_unregister_alg(struct crypto_alg *alg); | 180 | int crypto_unregister_alg(struct crypto_alg *alg); |
177 | 181 | ||
178 | /* | 182 | /* |
179 | * Algorithm query interface. | 183 | * Algorithm query interface. |
180 | */ | 184 | */ |
181 | #ifdef CONFIG_CRYPTO | 185 | #ifdef CONFIG_CRYPTO |
182 | int crypto_alg_available(const char *name, u32 flags); | 186 | int crypto_alg_available(const char *name, u32 flags); |
183 | #else | 187 | #else |
184 | static inline int crypto_alg_available(const char *name, u32 flags) | 188 | static inline int crypto_alg_available(const char *name, u32 flags) |
185 | { | 189 | { |
186 | return 0; | 190 | return 0; |
187 | } | 191 | } |
188 | #endif | 192 | #endif |
189 | 193 | ||
190 | /* | 194 | /* |
191 | * Transforms: user-instantiated objects which encapsulate algorithms | 195 | * Transforms: user-instantiated objects which encapsulate algorithms |
192 | * and core processing logic. Managed via crypto_alloc_tfm() and | 196 | * and core processing logic. Managed via crypto_alloc_tfm() and |
193 | * crypto_free_tfm(), as well as the various helpers below. | 197 | * crypto_free_tfm(), as well as the various helpers below. |
194 | */ | 198 | */ |
195 | 199 | ||
196 | struct cipher_tfm { | 200 | struct cipher_tfm { |
197 | void *cit_iv; | 201 | void *cit_iv; |
198 | unsigned int cit_ivsize; | 202 | unsigned int cit_ivsize; |
199 | u32 cit_mode; | 203 | u32 cit_mode; |
200 | int (*cit_setkey)(struct crypto_tfm *tfm, | 204 | int (*cit_setkey)(struct crypto_tfm *tfm, |
201 | const u8 *key, unsigned int keylen); | 205 | const u8 *key, unsigned int keylen); |
202 | int (*cit_encrypt)(struct crypto_tfm *tfm, | 206 | int (*cit_encrypt)(struct crypto_tfm *tfm, |
203 | struct scatterlist *dst, | 207 | struct scatterlist *dst, |
204 | struct scatterlist *src, | 208 | struct scatterlist *src, |
205 | unsigned int nbytes); | 209 | unsigned int nbytes); |
206 | int (*cit_encrypt_iv)(struct crypto_tfm *tfm, | 210 | int (*cit_encrypt_iv)(struct crypto_tfm *tfm, |
207 | struct scatterlist *dst, | 211 | struct scatterlist *dst, |
208 | struct scatterlist *src, | 212 | struct scatterlist *src, |
209 | unsigned int nbytes, u8 *iv); | 213 | unsigned int nbytes, u8 *iv); |
210 | int (*cit_decrypt)(struct crypto_tfm *tfm, | 214 | int (*cit_decrypt)(struct crypto_tfm *tfm, |
211 | struct scatterlist *dst, | 215 | struct scatterlist *dst, |
212 | struct scatterlist *src, | 216 | struct scatterlist *src, |
213 | unsigned int nbytes); | 217 | unsigned int nbytes); |
214 | int (*cit_decrypt_iv)(struct crypto_tfm *tfm, | 218 | int (*cit_decrypt_iv)(struct crypto_tfm *tfm, |
215 | struct scatterlist *dst, | 219 | struct scatterlist *dst, |
216 | struct scatterlist *src, | 220 | struct scatterlist *src, |
217 | unsigned int nbytes, u8 *iv); | 221 | unsigned int nbytes, u8 *iv); |
218 | void (*cit_xor_block)(u8 *dst, const u8 *src); | 222 | void (*cit_xor_block)(u8 *dst, const u8 *src); |
219 | }; | 223 | }; |
220 | 224 | ||
221 | struct digest_tfm { | 225 | struct digest_tfm { |
222 | void (*dit_init)(struct crypto_tfm *tfm); | 226 | void (*dit_init)(struct crypto_tfm *tfm); |
223 | void (*dit_update)(struct crypto_tfm *tfm, | 227 | void (*dit_update)(struct crypto_tfm *tfm, |
224 | struct scatterlist *sg, unsigned int nsg); | 228 | struct scatterlist *sg, unsigned int nsg); |
225 | void (*dit_final)(struct crypto_tfm *tfm, u8 *out); | 229 | void (*dit_final)(struct crypto_tfm *tfm, u8 *out); |
226 | void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg, | 230 | void (*dit_digest)(struct crypto_tfm *tfm, struct scatterlist *sg, |
227 | unsigned int nsg, u8 *out); | 231 | unsigned int nsg, u8 *out); |
228 | int (*dit_setkey)(struct crypto_tfm *tfm, | 232 | int (*dit_setkey)(struct crypto_tfm *tfm, |
229 | const u8 *key, unsigned int keylen); | 233 | const u8 *key, unsigned int keylen); |
230 | #ifdef CONFIG_CRYPTO_HMAC | 234 | #ifdef CONFIG_CRYPTO_HMAC |
231 | void *dit_hmac_block; | 235 | void *dit_hmac_block; |
232 | #endif | 236 | #endif |
233 | }; | 237 | }; |
234 | 238 | ||
235 | struct compress_tfm { | 239 | struct compress_tfm { |
236 | int (*cot_compress)(struct crypto_tfm *tfm, | 240 | int (*cot_compress)(struct crypto_tfm *tfm, |
237 | const u8 *src, unsigned int slen, | 241 | const u8 *src, unsigned int slen, |
238 | u8 *dst, unsigned int *dlen); | 242 | u8 *dst, unsigned int *dlen); |
239 | int (*cot_decompress)(struct crypto_tfm *tfm, | 243 | int (*cot_decompress)(struct crypto_tfm *tfm, |
240 | const u8 *src, unsigned int slen, | 244 | const u8 *src, unsigned int slen, |
241 | u8 *dst, unsigned int *dlen); | 245 | u8 *dst, unsigned int *dlen); |
242 | }; | 246 | }; |
243 | 247 | ||
244 | #define crt_cipher crt_u.cipher | 248 | #define crt_cipher crt_u.cipher |
245 | #define crt_digest crt_u.digest | 249 | #define crt_digest crt_u.digest |
246 | #define crt_compress crt_u.compress | 250 | #define crt_compress crt_u.compress |
247 | 251 | ||
248 | struct crypto_tfm { | 252 | struct crypto_tfm { |
249 | 253 | ||
250 | u32 crt_flags; | 254 | u32 crt_flags; |
251 | 255 | ||
252 | union { | 256 | union { |
253 | struct cipher_tfm cipher; | 257 | struct cipher_tfm cipher; |
254 | struct digest_tfm digest; | 258 | struct digest_tfm digest; |
255 | struct compress_tfm compress; | 259 | struct compress_tfm compress; |
256 | } crt_u; | 260 | } crt_u; |
257 | 261 | ||
258 | struct crypto_alg *__crt_alg; | 262 | struct crypto_alg *__crt_alg; |
259 | 263 | ||
260 | void *__crt_ctx[] CRYPTO_MINALIGN_ATTR; | 264 | void *__crt_ctx[] CRYPTO_MINALIGN_ATTR; |
261 | }; | 265 | }; |
262 | 266 | ||
263 | enum { | 267 | enum { |
264 | CRYPTOA_UNSPEC, | 268 | CRYPTOA_UNSPEC, |
265 | CRYPTOA_ALG, | 269 | CRYPTOA_ALG, |
266 | }; | 270 | }; |
267 | 271 | ||
268 | struct crypto_attr_alg { | 272 | struct crypto_attr_alg { |
269 | char name[CRYPTO_MAX_ALG_NAME]; | 273 | char name[CRYPTO_MAX_ALG_NAME]; |
270 | }; | 274 | }; |
271 | 275 | ||
272 | /* | 276 | /* |
273 | * Transform user interface. | 277 | * Transform user interface. |
274 | */ | 278 | */ |
275 | 279 | ||
276 | /* | 280 | /* |
277 | * crypto_alloc_tfm() will first attempt to locate an already loaded algorithm. | 281 | * crypto_alloc_tfm() will first attempt to locate an already loaded algorithm. |
278 | * If that fails and the kernel supports dynamically loadable modules, it | 282 | * If that fails and the kernel supports dynamically loadable modules, it |
279 | * will then attempt to load a module of the same name or alias. A refcount | 283 | * will then attempt to load a module of the same name or alias. A refcount |
280 | * is grabbed on the algorithm which is then associated with the new transform. | 284 | * is grabbed on the algorithm which is then associated with the new transform. |
281 | * | 285 | * |
282 | * crypto_free_tfm() frees up the transform and any associated resources, | 286 | * crypto_free_tfm() frees up the transform and any associated resources, |
283 | * then drops the refcount on the associated algorithm. | 287 | * then drops the refcount on the associated algorithm. |
284 | */ | 288 | */ |
285 | struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags); | 289 | struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags); |
286 | void crypto_free_tfm(struct crypto_tfm *tfm); | 290 | void crypto_free_tfm(struct crypto_tfm *tfm); |
287 | 291 | ||
288 | /* | 292 | /* |
289 | * Transform helpers which query the underlying algorithm. | 293 | * Transform helpers which query the underlying algorithm. |
290 | */ | 294 | */ |
291 | static inline const char *crypto_tfm_alg_name(struct crypto_tfm *tfm) | 295 | static inline const char *crypto_tfm_alg_name(struct crypto_tfm *tfm) |
292 | { | 296 | { |
293 | return tfm->__crt_alg->cra_name; | 297 | return tfm->__crt_alg->cra_name; |
294 | } | 298 | } |
295 | 299 | ||
296 | static inline const char *crypto_tfm_alg_modname(struct crypto_tfm *tfm) | 300 | static inline const char *crypto_tfm_alg_modname(struct crypto_tfm *tfm) |
297 | { | 301 | { |
298 | return module_name(tfm->__crt_alg->cra_module); | 302 | return module_name(tfm->__crt_alg->cra_module); |
299 | } | 303 | } |
300 | 304 | ||
301 | static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm) | 305 | static inline u32 crypto_tfm_alg_type(struct crypto_tfm *tfm) |
302 | { | 306 | { |
303 | return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK; | 307 | return tfm->__crt_alg->cra_flags & CRYPTO_ALG_TYPE_MASK; |
304 | } | 308 | } |
305 | 309 | ||
306 | static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm) | 310 | static inline unsigned int crypto_tfm_alg_min_keysize(struct crypto_tfm *tfm) |
307 | { | 311 | { |
308 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); | 312 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); |
309 | return tfm->__crt_alg->cra_cipher.cia_min_keysize; | 313 | return tfm->__crt_alg->cra_cipher.cia_min_keysize; |
310 | } | 314 | } |
311 | 315 | ||
312 | static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm) | 316 | static inline unsigned int crypto_tfm_alg_max_keysize(struct crypto_tfm *tfm) |
313 | { | 317 | { |
314 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); | 318 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); |
315 | return tfm->__crt_alg->cra_cipher.cia_max_keysize; | 319 | return tfm->__crt_alg->cra_cipher.cia_max_keysize; |
316 | } | 320 | } |
317 | 321 | ||
318 | static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm) | 322 | static inline unsigned int crypto_tfm_alg_ivsize(struct crypto_tfm *tfm) |
319 | { | 323 | { |
320 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); | 324 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); |
321 | return tfm->crt_cipher.cit_ivsize; | 325 | return tfm->crt_cipher.cit_ivsize; |
322 | } | 326 | } |
323 | 327 | ||
324 | static inline unsigned int crypto_tfm_alg_blocksize(struct crypto_tfm *tfm) | 328 | static inline unsigned int crypto_tfm_alg_blocksize(struct crypto_tfm *tfm) |
325 | { | 329 | { |
326 | return tfm->__crt_alg->cra_blocksize; | 330 | return tfm->__crt_alg->cra_blocksize; |
327 | } | 331 | } |
328 | 332 | ||
329 | static inline unsigned int crypto_tfm_alg_digestsize(struct crypto_tfm *tfm) | 333 | static inline unsigned int crypto_tfm_alg_digestsize(struct crypto_tfm *tfm) |
330 | { | 334 | { |
331 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); | 335 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); |
332 | return tfm->__crt_alg->cra_digest.dia_digestsize; | 336 | return tfm->__crt_alg->cra_digest.dia_digestsize; |
333 | } | 337 | } |
334 | 338 | ||
335 | static inline unsigned int crypto_tfm_alg_alignmask(struct crypto_tfm *tfm) | 339 | static inline unsigned int crypto_tfm_alg_alignmask(struct crypto_tfm *tfm) |
336 | { | 340 | { |
337 | return tfm->__crt_alg->cra_alignmask; | 341 | return tfm->__crt_alg->cra_alignmask; |
338 | } | 342 | } |
339 | 343 | ||
340 | static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) | 344 | static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) |
341 | { | 345 | { |
342 | return tfm->__crt_ctx; | 346 | return tfm->__crt_ctx; |
343 | } | 347 | } |
344 | 348 | ||
345 | static inline unsigned int crypto_tfm_ctx_alignment(void) | 349 | static inline unsigned int crypto_tfm_ctx_alignment(void) |
346 | { | 350 | { |
347 | struct crypto_tfm *tfm; | 351 | struct crypto_tfm *tfm; |
348 | return __alignof__(tfm->__crt_ctx); | 352 | return __alignof__(tfm->__crt_ctx); |
349 | } | 353 | } |
350 | 354 | ||
351 | /* | 355 | /* |
352 | * API wrappers. | 356 | * API wrappers. |
353 | */ | 357 | */ |
354 | static inline void crypto_digest_init(struct crypto_tfm *tfm) | 358 | static inline void crypto_digest_init(struct crypto_tfm *tfm) |
355 | { | 359 | { |
356 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); | 360 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); |
357 | tfm->crt_digest.dit_init(tfm); | 361 | tfm->crt_digest.dit_init(tfm); |
358 | } | 362 | } |
359 | 363 | ||
360 | static inline void crypto_digest_update(struct crypto_tfm *tfm, | 364 | static inline void crypto_digest_update(struct crypto_tfm *tfm, |
361 | struct scatterlist *sg, | 365 | struct scatterlist *sg, |
362 | unsigned int nsg) | 366 | unsigned int nsg) |
363 | { | 367 | { |
364 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); | 368 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); |
365 | tfm->crt_digest.dit_update(tfm, sg, nsg); | 369 | tfm->crt_digest.dit_update(tfm, sg, nsg); |
366 | } | 370 | } |
367 | 371 | ||
368 | static inline void crypto_digest_final(struct crypto_tfm *tfm, u8 *out) | 372 | static inline void crypto_digest_final(struct crypto_tfm *tfm, u8 *out) |
369 | { | 373 | { |
370 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); | 374 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); |
371 | tfm->crt_digest.dit_final(tfm, out); | 375 | tfm->crt_digest.dit_final(tfm, out); |
372 | } | 376 | } |
373 | 377 | ||
374 | static inline void crypto_digest_digest(struct crypto_tfm *tfm, | 378 | static inline void crypto_digest_digest(struct crypto_tfm *tfm, |
375 | struct scatterlist *sg, | 379 | struct scatterlist *sg, |
376 | unsigned int nsg, u8 *out) | 380 | unsigned int nsg, u8 *out) |
377 | { | 381 | { |
378 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); | 382 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); |
379 | tfm->crt_digest.dit_digest(tfm, sg, nsg, out); | 383 | tfm->crt_digest.dit_digest(tfm, sg, nsg, out); |
380 | } | 384 | } |
381 | 385 | ||
382 | static inline int crypto_digest_setkey(struct crypto_tfm *tfm, | 386 | static inline int crypto_digest_setkey(struct crypto_tfm *tfm, |
383 | const u8 *key, unsigned int keylen) | 387 | const u8 *key, unsigned int keylen) |
384 | { | 388 | { |
385 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); | 389 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_DIGEST); |
386 | if (tfm->crt_digest.dit_setkey == NULL) | 390 | if (tfm->crt_digest.dit_setkey == NULL) |
387 | return -ENOSYS; | 391 | return -ENOSYS; |
388 | return tfm->crt_digest.dit_setkey(tfm, key, keylen); | 392 | return tfm->crt_digest.dit_setkey(tfm, key, keylen); |
389 | } | 393 | } |
390 | 394 | ||
391 | static inline int crypto_cipher_setkey(struct crypto_tfm *tfm, | 395 | static inline int crypto_cipher_setkey(struct crypto_tfm *tfm, |
392 | const u8 *key, unsigned int keylen) | 396 | const u8 *key, unsigned int keylen) |
393 | { | 397 | { |
394 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); | 398 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); |
395 | return tfm->crt_cipher.cit_setkey(tfm, key, keylen); | 399 | return tfm->crt_cipher.cit_setkey(tfm, key, keylen); |
396 | } | 400 | } |
397 | 401 | ||
398 | static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm, | 402 | static inline int crypto_cipher_encrypt(struct crypto_tfm *tfm, |
399 | struct scatterlist *dst, | 403 | struct scatterlist *dst, |
400 | struct scatterlist *src, | 404 | struct scatterlist *src, |
401 | unsigned int nbytes) | 405 | unsigned int nbytes) |
402 | { | 406 | { |
403 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); | 407 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); |
404 | return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes); | 408 | return tfm->crt_cipher.cit_encrypt(tfm, dst, src, nbytes); |
405 | } | 409 | } |
406 | 410 | ||
407 | static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm, | 411 | static inline int crypto_cipher_encrypt_iv(struct crypto_tfm *tfm, |
408 | struct scatterlist *dst, | 412 | struct scatterlist *dst, |
409 | struct scatterlist *src, | 413 | struct scatterlist *src, |
410 | unsigned int nbytes, u8 *iv) | 414 | unsigned int nbytes, u8 *iv) |
411 | { | 415 | { |
412 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); | 416 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); |
413 | BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); | 417 | BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); |
414 | return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv); | 418 | return tfm->crt_cipher.cit_encrypt_iv(tfm, dst, src, nbytes, iv); |
415 | } | 419 | } |
416 | 420 | ||
417 | static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm, | 421 | static inline int crypto_cipher_decrypt(struct crypto_tfm *tfm, |
418 | struct scatterlist *dst, | 422 | struct scatterlist *dst, |
419 | struct scatterlist *src, | 423 | struct scatterlist *src, |
420 | unsigned int nbytes) | 424 | unsigned int nbytes) |
421 | { | 425 | { |
422 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); | 426 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); |
423 | return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes); | 427 | return tfm->crt_cipher.cit_decrypt(tfm, dst, src, nbytes); |
424 | } | 428 | } |
425 | 429 | ||
426 | static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm, | 430 | static inline int crypto_cipher_decrypt_iv(struct crypto_tfm *tfm, |
427 | struct scatterlist *dst, | 431 | struct scatterlist *dst, |
428 | struct scatterlist *src, | 432 | struct scatterlist *src, |
429 | unsigned int nbytes, u8 *iv) | 433 | unsigned int nbytes, u8 *iv) |
430 | { | 434 | { |
431 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); | 435 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); |
432 | BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); | 436 | BUG_ON(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB); |
433 | return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv); | 437 | return tfm->crt_cipher.cit_decrypt_iv(tfm, dst, src, nbytes, iv); |
434 | } | 438 | } |
435 | 439 | ||
436 | static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm, | 440 | static inline void crypto_cipher_set_iv(struct crypto_tfm *tfm, |
437 | const u8 *src, unsigned int len) | 441 | const u8 *src, unsigned int len) |
438 | { | 442 | { |
439 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); | 443 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); |
440 | memcpy(tfm->crt_cipher.cit_iv, src, len); | 444 | memcpy(tfm->crt_cipher.cit_iv, src, len); |
441 | } | 445 | } |
442 | 446 | ||
443 | static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm, | 447 | static inline void crypto_cipher_get_iv(struct crypto_tfm *tfm, |
444 | u8 *dst, unsigned int len) | 448 | u8 *dst, unsigned int len) |
445 | { | 449 | { |
446 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); | 450 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER); |
447 | memcpy(dst, tfm->crt_cipher.cit_iv, len); | 451 | memcpy(dst, tfm->crt_cipher.cit_iv, len); |
448 | } | 452 | } |
449 | 453 | ||
450 | static inline int crypto_comp_compress(struct crypto_tfm *tfm, | 454 | static inline int crypto_comp_compress(struct crypto_tfm *tfm, |
451 | const u8 *src, unsigned int slen, | 455 | const u8 *src, unsigned int slen, |
452 | u8 *dst, unsigned int *dlen) | 456 | u8 *dst, unsigned int *dlen) |
453 | { | 457 | { |
454 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); | 458 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); |
455 | return tfm->crt_compress.cot_compress(tfm, src, slen, dst, dlen); | 459 | return tfm->crt_compress.cot_compress(tfm, src, slen, dst, dlen); |
456 | } | 460 | } |
457 | 461 | ||
458 | static inline int crypto_comp_decompress(struct crypto_tfm *tfm, | 462 | static inline int crypto_comp_decompress(struct crypto_tfm *tfm, |
459 | const u8 *src, unsigned int slen, | 463 | const u8 *src, unsigned int slen, |
460 | u8 *dst, unsigned int *dlen) | 464 | u8 *dst, unsigned int *dlen) |
461 | { | 465 | { |
462 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); | 466 | BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_COMPRESS); |
463 | return tfm->crt_compress.cot_decompress(tfm, src, slen, dst, dlen); | 467 | return tfm->crt_compress.cot_decompress(tfm, src, slen, dst, dlen); |
464 | } | 468 | } |
465 | 469 | ||
466 | /* | 470 | /* |
467 | * HMAC support. | 471 | * HMAC support. |
468 | */ | 472 | */ |
469 | #ifdef CONFIG_CRYPTO_HMAC | 473 | #ifdef CONFIG_CRYPTO_HMAC |
470 | void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen); | 474 | void crypto_hmac_init(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen); |
471 | void crypto_hmac_update(struct crypto_tfm *tfm, | 475 | void crypto_hmac_update(struct crypto_tfm *tfm, |
472 | struct scatterlist *sg, unsigned int nsg); | 476 | struct scatterlist *sg, unsigned int nsg); |
473 | void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key, | 477 | void crypto_hmac_final(struct crypto_tfm *tfm, u8 *key, |
474 | unsigned int *keylen, u8 *out); | 478 | unsigned int *keylen, u8 *out); |
475 | void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen, | 479 | void crypto_hmac(struct crypto_tfm *tfm, u8 *key, unsigned int *keylen, |
476 | struct scatterlist *sg, unsigned int nsg, u8 *out); | 480 | struct scatterlist *sg, unsigned int nsg, u8 *out); |
477 | #endif /* CONFIG_CRYPTO_HMAC */ | 481 | #endif /* CONFIG_CRYPTO_HMAC */ |
478 | 482 | ||
479 | #endif /* _LINUX_CRYPTO_H */ | 483 | #endif /* _LINUX_CRYPTO_H */ |
480 | 484 | ||
481 | 485 |