Branch data Line data Source code
1 : : /*
2 : : * Scatterlist Cryptographic API.
3 : : *
4 : : * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
5 : : * Copyright (c) 2002 David S. Miller (davem@redhat.com)
6 : : * Copyright (c) 2005 Herbert Xu <herbert@gondor.apana.org.au>
7 : : *
8 : : * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
9 : : * and Nettle, by Niels Möller.
10 : : *
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
13 : : * Software Foundation; either version 2 of the License, or (at your option)
14 : : * any later version.
15 : : *
16 : : */
17 : :
18 : : #include <linux/err.h>
19 : : #include <linux/errno.h>
20 : : #include <linux/kernel.h>
21 : : #include <linux/kmod.h>
22 : : #include <linux/module.h>
23 : : #include <linux/param.h>
24 : : #include <linux/sched.h>
25 : : #include <linux/slab.h>
26 : : #include <linux/string.h>
27 : : #include "internal.h"
28 : :
29 : : LIST_HEAD(crypto_alg_list);
30 : : EXPORT_SYMBOL_GPL(crypto_alg_list);
31 : : DECLARE_RWSEM(crypto_alg_sem);
32 : : EXPORT_SYMBOL_GPL(crypto_alg_sem);
33 : :
34 : : BLOCKING_NOTIFIER_HEAD(crypto_chain);
35 : : EXPORT_SYMBOL_GPL(crypto_chain);
36 : :
37 : : static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg);
38 : :
39 : 0 : struct crypto_alg *crypto_mod_get(struct crypto_alg *alg)
40 : : {
41 [ # # ]: 0 : return try_module_get(alg->cra_module) ? crypto_alg_get(alg) : NULL;
42 : : }
43 : : EXPORT_SYMBOL_GPL(crypto_mod_get);
44 : :
45 : 0 : void crypto_mod_put(struct crypto_alg *alg)
46 : : {
47 : 0 : struct module *module = alg->cra_module;
48 : :
49 : : crypto_alg_put(alg);
50 : 0 : module_put(module);
51 : 0 : }
52 : : EXPORT_SYMBOL_GPL(crypto_mod_put);
53 : :
54 : : static inline int crypto_is_test_larval(struct crypto_larval *larval)
55 : : {
56 : : return larval->alg.cra_driver_name[0];
57 : : }
58 : :
59 : 0 : static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type,
60 : : u32 mask)
61 : : {
62 : 0 : struct crypto_alg *q, *alg = NULL;
63 : : int best = -2;
64 : :
65 [ # # ]: 0 : list_for_each_entry(q, &crypto_alg_list, cra_list) {
66 : : int exact, fuzzy;
67 : :
68 [ # # ]: 0 : if (crypto_is_moribund(q))
69 : 0 : continue;
70 : :
71 [ # # ]: 0 : if ((q->cra_flags ^ type) & mask)
72 : 0 : continue;
73 : :
74 [ # # ][ # # ]: 0 : if (crypto_is_larval(q) &&
75 [ # # ]: 0 : !crypto_is_test_larval((struct crypto_larval *)q) &&
76 : 0 : ((struct crypto_larval *)q)->mask != mask)
77 : 0 : continue;
78 : :
79 : 0 : exact = !strcmp(q->cra_driver_name, name);
80 : 0 : fuzzy = !strcmp(q->cra_name, name);
81 [ # # ][ # # ]: 0 : if (!exact && !(fuzzy && q->cra_priority > best))
[ # # ]
82 : 0 : continue;
83 : :
84 [ # # ]: 0 : if (unlikely(!crypto_mod_get(q)))
85 : 0 : continue;
86 : :
87 : 0 : best = q->cra_priority;
88 [ # # ]: 0 : if (alg)
89 : 0 : crypto_mod_put(alg);
90 : : alg = q;
91 : :
92 [ # # ]: 0 : if (exact)
93 : : break;
94 : : }
95 : :
96 : 0 : return alg;
97 : : }
98 : :
99 : 0 : static void crypto_larval_destroy(struct crypto_alg *alg)
100 : : {
101 : : struct crypto_larval *larval = (void *)alg;
102 : :
103 [ # # ]: 0 : BUG_ON(!crypto_is_larval(alg));
104 [ # # ]: 0 : if (larval->adult)
105 : 0 : crypto_mod_put(larval->adult);
106 : 0 : kfree(larval);
107 : 0 : }
108 : :
109 : 0 : struct crypto_larval *crypto_larval_alloc(const char *name, u32 type, u32 mask)
110 : : {
111 : : struct crypto_larval *larval;
112 : :
113 : : larval = kzalloc(sizeof(*larval), GFP_KERNEL);
114 [ # # ]: 0 : if (!larval)
115 : : return ERR_PTR(-ENOMEM);
116 : :
117 : 0 : larval->mask = mask;
118 : 0 : larval->alg.cra_flags = CRYPTO_ALG_LARVAL | type;
119 : 0 : larval->alg.cra_priority = -1;
120 : 0 : larval->alg.cra_destroy = crypto_larval_destroy;
121 : :
122 : 0 : strlcpy(larval->alg.cra_name, name, CRYPTO_MAX_ALG_NAME);
123 : : init_completion(&larval->completion);
124 : :
125 : 0 : return larval;
126 : : }
127 : : EXPORT_SYMBOL_GPL(crypto_larval_alloc);
128 : :
129 : 0 : static struct crypto_alg *crypto_larval_add(const char *name, u32 type,
130 : : u32 mask)
131 : : {
132 : 0 : struct crypto_alg *alg;
133 : : struct crypto_larval *larval;
134 : :
135 : 0 : larval = crypto_larval_alloc(name, type, mask);
136 [ # # ]: 0 : if (IS_ERR(larval))
137 : : return ERR_CAST(larval);
138 : :
139 : 0 : atomic_set(&larval->alg.cra_refcnt, 2);
140 : :
141 : 0 : down_write(&crypto_alg_sem);
142 : 0 : alg = __crypto_alg_lookup(name, type, mask);
143 [ # # ]: 0 : if (!alg) {
144 : 0 : alg = &larval->alg;
145 : : list_add(&alg->cra_list, &crypto_alg_list);
146 : : }
147 : 0 : up_write(&crypto_alg_sem);
148 : :
149 [ # # ]: 0 : if (alg != &larval->alg) {
150 : 0 : kfree(larval);
151 [ # # ]: 0 : if (crypto_is_larval(alg))
152 : 0 : alg = crypto_larval_wait(alg);
153 : : }
154 : :
155 : 0 : return alg;
156 : : }
157 : :
158 : 0 : void crypto_larval_kill(struct crypto_alg *alg)
159 : : {
160 : : struct crypto_larval *larval = (void *)alg;
161 : :
162 : 0 : down_write(&crypto_alg_sem);
163 : : list_del(&alg->cra_list);
164 : 0 : up_write(&crypto_alg_sem);
165 : 0 : complete_all(&larval->completion);
166 : : crypto_alg_put(alg);
167 : 0 : }
168 : : EXPORT_SYMBOL_GPL(crypto_larval_kill);
169 : :
170 : 0 : static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
171 : : {
172 : 0 : struct crypto_larval *larval = (void *)alg;
173 : : long timeout;
174 : :
175 : 0 : timeout = wait_for_completion_interruptible_timeout(
176 : : &larval->completion, 60 * HZ);
177 : :
178 : 0 : alg = larval->adult;
179 [ # # ]: 0 : if (timeout < 0)
180 : : alg = ERR_PTR(-EINTR);
181 [ # # ]: 0 : else if (!timeout)
182 : : alg = ERR_PTR(-ETIMEDOUT);
183 [ # # ]: 0 : else if (!alg)
184 : : alg = ERR_PTR(-ENOENT);
185 [ # # ][ # # ]: 0 : else if (crypto_is_test_larval(larval) &&
186 : 0 : !(alg->cra_flags & CRYPTO_ALG_TESTED))
187 : : alg = ERR_PTR(-EAGAIN);
188 [ # # ]: 0 : else if (!crypto_mod_get(alg))
189 : : alg = ERR_PTR(-EAGAIN);
190 : 0 : crypto_mod_put(&larval->alg);
191 : :
192 : 0 : return alg;
193 : : }
194 : :
195 : 0 : struct crypto_alg *crypto_alg_lookup(const char *name, u32 type, u32 mask)
196 : : {
197 : : struct crypto_alg *alg;
198 : :
199 : 0 : down_read(&crypto_alg_sem);
200 : 0 : alg = __crypto_alg_lookup(name, type, mask);
201 : 0 : up_read(&crypto_alg_sem);
202 : :
203 : 0 : return alg;
204 : : }
205 : : EXPORT_SYMBOL_GPL(crypto_alg_lookup);
206 : :
207 : 0 : struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask)
208 : : {
209 : 0 : struct crypto_alg *alg;
210 : :
211 [ # # ]: 0 : if (!name)
212 : : return ERR_PTR(-ENOENT);
213 : :
214 : 0 : mask &= ~(CRYPTO_ALG_LARVAL | CRYPTO_ALG_DEAD);
215 : 0 : type &= mask;
216 : :
217 : 0 : alg = crypto_alg_lookup(name, type, mask);
218 [ # # ]: 0 : if (!alg) {
219 : 0 : request_module("%s", name);
220 : :
221 [ # # ]: 0 : if (!((type ^ CRYPTO_ALG_NEED_FALLBACK) & mask &
222 : : CRYPTO_ALG_NEED_FALLBACK))
223 : 0 : request_module("%s-all", name);
224 : :
225 : 0 : alg = crypto_alg_lookup(name, type, mask);
226 : : }
227 : :
228 [ # # ]: 0 : if (alg)
229 [ # # ]: 0 : return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg;
230 : :
231 : 0 : return crypto_larval_add(name, type, mask);
232 : : }
233 : : EXPORT_SYMBOL_GPL(crypto_larval_lookup);
234 : :
235 : 0 : int crypto_probing_notify(unsigned long val, void *v)
236 : : {
237 : : int ok;
238 : :
239 : 0 : ok = blocking_notifier_call_chain(&crypto_chain, val, v);
240 [ # # ]: 0 : if (ok == NOTIFY_DONE) {
241 : 0 : request_module("cryptomgr");
242 : 0 : ok = blocking_notifier_call_chain(&crypto_chain, val, v);
243 : : }
244 : :
245 : 0 : return ok;
246 : : }
247 : : EXPORT_SYMBOL_GPL(crypto_probing_notify);
248 : :
249 : 0 : struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
250 : : {
251 : : struct crypto_alg *alg;
252 : 0 : struct crypto_alg *larval;
253 : : int ok;
254 : :
255 [ # # ]: 0 : if (!((type | mask) & CRYPTO_ALG_TESTED)) {
256 : 0 : type |= CRYPTO_ALG_TESTED;
257 : 0 : mask |= CRYPTO_ALG_TESTED;
258 : : }
259 : :
260 : 0 : larval = crypto_larval_lookup(name, type, mask);
261 [ # # ][ # # ]: 0 : if (IS_ERR(larval) || !crypto_is_larval(larval))
262 : : return larval;
263 : :
264 : 0 : ok = crypto_probing_notify(CRYPTO_MSG_ALG_REQUEST, larval);
265 : :
266 [ # # ]: 0 : if (ok == NOTIFY_STOP)
267 : 0 : alg = crypto_larval_wait(larval);
268 : : else {
269 : 0 : crypto_mod_put(larval);
270 : : alg = ERR_PTR(-ENOENT);
271 : : }
272 : 0 : crypto_larval_kill(larval);
273 : 0 : return alg;
274 : : }
275 : : EXPORT_SYMBOL_GPL(crypto_alg_mod_lookup);
276 : :
277 : 0 : static int crypto_init_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
278 : : {
279 : 0 : const struct crypto_type *type_obj = tfm->__crt_alg->cra_type;
280 : :
281 [ # # ]: 0 : if (type_obj)
282 : 0 : return type_obj->init(tfm, type, mask);
283 : :
284 [ # # # ]: 0 : switch (crypto_tfm_alg_type(tfm)) {
285 : : case CRYPTO_ALG_TYPE_CIPHER:
286 : 0 : return crypto_init_cipher_ops(tfm);
287 : :
288 : : case CRYPTO_ALG_TYPE_COMPRESS:
289 : 0 : return crypto_init_compress_ops(tfm);
290 : :
291 : : default:
292 : : break;
293 : : }
294 : :
295 : 0 : BUG();
296 : : return -EINVAL;
297 : : }
298 : :
299 : 0 : static void crypto_exit_ops(struct crypto_tfm *tfm)
300 : : {
301 : 0 : const struct crypto_type *type = tfm->__crt_alg->cra_type;
302 : :
303 [ # # ]: 0 : if (type) {
304 [ # # ]: 0 : if (tfm->exit)
305 : 0 : tfm->exit(tfm);
306 : 0 : return;
307 : : }
308 : :
309 [ # # # ]: 0 : switch (crypto_tfm_alg_type(tfm)) {
310 : : case CRYPTO_ALG_TYPE_CIPHER:
311 : 0 : crypto_exit_cipher_ops(tfm);
312 : 0 : break;
313 : :
314 : : case CRYPTO_ALG_TYPE_COMPRESS:
315 : 0 : crypto_exit_compress_ops(tfm);
316 : 0 : break;
317 : :
318 : : default:
319 : 0 : BUG();
320 : : }
321 : : }
322 : :
323 : 0 : static unsigned int crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask)
324 : : {
325 : 0 : const struct crypto_type *type_obj = alg->cra_type;
326 : : unsigned int len;
327 : :
328 : 0 : len = alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1);
329 [ # # ]: 0 : if (type_obj)
330 : 0 : return len + type_obj->ctxsize(alg, type, mask);
331 : :
332 [ # # # ]: 0 : switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
333 : : default:
334 : 0 : BUG();
335 : :
336 : : case CRYPTO_ALG_TYPE_CIPHER:
337 : 0 : len += crypto_cipher_ctxsize(alg);
338 : 0 : break;
339 : :
340 : : case CRYPTO_ALG_TYPE_COMPRESS:
341 : 0 : len += crypto_compress_ctxsize(alg);
342 : 0 : break;
343 : : }
344 : :
345 : 0 : return len;
346 : : }
347 : :
348 : 0 : void crypto_shoot_alg(struct crypto_alg *alg)
349 : : {
350 : 0 : down_write(&crypto_alg_sem);
351 : 0 : alg->cra_flags |= CRYPTO_ALG_DYING;
352 : 0 : up_write(&crypto_alg_sem);
353 : 0 : }
354 : : EXPORT_SYMBOL_GPL(crypto_shoot_alg);
355 : :
356 : 0 : struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
357 : : u32 mask)
358 : : {
359 : : struct crypto_tfm *tfm = NULL;
360 : : unsigned int tfm_size;
361 : : int err = -ENOMEM;
362 : :
363 : 0 : tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, type, mask);
364 : : tfm = kzalloc(tfm_size, GFP_KERNEL);
365 [ # # ]: 0 : if (tfm == NULL)
366 : : goto out_err;
367 : :
368 : 0 : tfm->__crt_alg = alg;
369 : :
370 : 0 : err = crypto_init_ops(tfm, type, mask);
371 [ # # ]: 0 : if (err)
372 : : goto out_free_tfm;
373 : :
374 [ # # ][ # # ]: 0 : if (!tfm->exit && alg->cra_init && (err = alg->cra_init(tfm)))
[ # # ]
375 : : goto cra_init_failed;
376 : :
377 : : goto out;
378 : :
379 : : cra_init_failed:
380 : 0 : crypto_exit_ops(tfm);
381 : : out_free_tfm:
382 [ # # ]: 0 : if (err == -EAGAIN)
383 : 0 : crypto_shoot_alg(alg);
384 : 0 : kfree(tfm);
385 : : out_err:
386 : : tfm = ERR_PTR(err);
387 : : out:
388 : 0 : return tfm;
389 : : }
390 : : EXPORT_SYMBOL_GPL(__crypto_alloc_tfm);
391 : :
392 : : /*
393 : : * crypto_alloc_base - Locate algorithm and allocate transform
394 : : * @alg_name: Name of algorithm
395 : : * @type: Type of algorithm
396 : : * @mask: Mask for type comparison
397 : : *
398 : : * This function should not be used by new algorithm types.
399 : : * Please use crypto_alloc_tfm instead.
400 : : *
401 : : * crypto_alloc_base() will first attempt to locate an already loaded
402 : : * algorithm. If that fails and the kernel supports dynamically loadable
403 : : * modules, it will then attempt to load a module of the same name or
404 : : * alias. If that fails it will send a query to any loaded crypto manager
405 : : * to construct an algorithm on the fly. A refcount is grabbed on the
406 : : * algorithm which is then associated with the new transform.
407 : : *
408 : : * The returned transform is of a non-determinate type. Most people
409 : : * should use one of the more specific allocation functions such as
410 : : * crypto_alloc_blkcipher.
411 : : *
412 : : * In case of error the return value is an error pointer.
413 : : */
414 : 0 : struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask)
415 : : {
416 : : struct crypto_tfm *tfm;
417 : : int err;
418 : :
419 : : for (;;) {
420 : : struct crypto_alg *alg;
421 : :
422 : 0 : alg = crypto_alg_mod_lookup(alg_name, type, mask);
423 [ # # ]: 0 : if (IS_ERR(alg)) {
424 : : err = PTR_ERR(alg);
425 : 0 : goto err;
426 : : }
427 : :
428 : 0 : tfm = __crypto_alloc_tfm(alg, type, mask);
429 [ # # ]: 0 : if (!IS_ERR(tfm))
430 : : return tfm;
431 : :
432 : 0 : crypto_mod_put(alg);
433 : : err = PTR_ERR(tfm);
434 : :
435 : : err:
436 [ # # ]: 0 : if (err != -EAGAIN)
437 : : break;
438 [ # # ]: 0 : if (signal_pending(current)) {
439 : : err = -EINTR;
440 : : break;
441 : : }
442 : : }
443 : :
444 : 0 : return ERR_PTR(err);
445 : : }
446 : : EXPORT_SYMBOL_GPL(crypto_alloc_base);
447 : :
448 : 0 : void *crypto_create_tfm(struct crypto_alg *alg,
449 : : const struct crypto_type *frontend)
450 : : {
451 : : char *mem;
452 : : struct crypto_tfm *tfm = NULL;
453 : : unsigned int tfmsize;
454 : : unsigned int total;
455 : : int err = -ENOMEM;
456 : :
457 : 0 : tfmsize = frontend->tfmsize;
458 : 0 : total = tfmsize + sizeof(*tfm) + frontend->extsize(alg);
459 : :
460 : : mem = kzalloc(total, GFP_KERNEL);
461 [ # # ]: 0 : if (mem == NULL)
462 : : goto out_err;
463 : :
464 : 0 : tfm = (struct crypto_tfm *)(mem + tfmsize);
465 : 0 : tfm->__crt_alg = alg;
466 : :
467 : 0 : err = frontend->init_tfm(tfm);
468 [ # # ]: 0 : if (err)
469 : : goto out_free_tfm;
470 : :
471 [ # # ][ # # ]: 0 : if (!tfm->exit && alg->cra_init && (err = alg->cra_init(tfm)))
[ # # ]
472 : : goto cra_init_failed;
473 : :
474 : : goto out;
475 : :
476 : : cra_init_failed:
477 : 0 : crypto_exit_ops(tfm);
478 : : out_free_tfm:
479 [ # # ]: 0 : if (err == -EAGAIN)
480 : 0 : crypto_shoot_alg(alg);
481 : 0 : kfree(mem);
482 : : out_err:
483 : : mem = ERR_PTR(err);
484 : : out:
485 : 0 : return mem;
486 : : }
487 : : EXPORT_SYMBOL_GPL(crypto_create_tfm);
488 : :
489 : 0 : struct crypto_alg *crypto_find_alg(const char *alg_name,
490 : : const struct crypto_type *frontend,
491 : : u32 type, u32 mask)
492 : : {
493 : : struct crypto_alg *(*lookup)(const char *name, u32 type, u32 mask) =
494 : : crypto_alg_mod_lookup;
495 : :
496 [ # # ][ # # ]: 0 : if (frontend) {
497 : 0 : type &= frontend->maskclear;
498 : 0 : mask &= frontend->maskclear;
499 : 0 : type |= frontend->type;
500 : 0 : mask |= frontend->maskset;
501 : :
502 [ # # ][ # # ]: 0 : if (frontend->lookup)
503 : : lookup = frontend->lookup;
504 : : }
505 : :
506 : 0 : return lookup(alg_name, type, mask);
507 : : }
508 : : EXPORT_SYMBOL_GPL(crypto_find_alg);
509 : :
510 : : /*
511 : : * crypto_alloc_tfm - Locate algorithm and allocate transform
512 : : * @alg_name: Name of algorithm
513 : : * @frontend: Frontend algorithm type
514 : : * @type: Type of algorithm
515 : : * @mask: Mask for type comparison
516 : : *
517 : : * crypto_alloc_tfm() will first attempt to locate an already loaded
518 : : * algorithm. If that fails and the kernel supports dynamically loadable
519 : : * modules, it will then attempt to load a module of the same name or
520 : : * alias. If that fails it will send a query to any loaded crypto manager
521 : : * to construct an algorithm on the fly. A refcount is grabbed on the
522 : : * algorithm which is then associated with the new transform.
523 : : *
524 : : * The returned transform is of a non-determinate type. Most people
525 : : * should use one of the more specific allocation functions such as
526 : : * crypto_alloc_blkcipher.
527 : : *
528 : : * In case of error the return value is an error pointer.
529 : : */
530 : 0 : void *crypto_alloc_tfm(const char *alg_name,
531 : : const struct crypto_type *frontend, u32 type, u32 mask)
532 : : {
533 : : void *tfm;
534 : : int err;
535 : :
536 : : for (;;) {
537 : : struct crypto_alg *alg;
538 : :
539 : : alg = crypto_find_alg(alg_name, frontend, type, mask);
540 [ # # ]: 0 : if (IS_ERR(alg)) {
541 : : err = PTR_ERR(alg);
542 : 0 : goto err;
543 : : }
544 : :
545 : 0 : tfm = crypto_create_tfm(alg, frontend);
546 [ # # ]: 0 : if (!IS_ERR(tfm))
547 : : return tfm;
548 : :
549 : 0 : crypto_mod_put(alg);
550 : : err = PTR_ERR(tfm);
551 : :
552 : : err:
553 [ # # ]: 0 : if (err != -EAGAIN)
554 : : break;
555 [ # # ]: 0 : if (signal_pending(current)) {
556 : : err = -EINTR;
557 : : break;
558 : : }
559 : : }
560 : :
561 : 0 : return ERR_PTR(err);
562 : : }
563 : : EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
564 : :
565 : : /*
566 : : * crypto_destroy_tfm - Free crypto transform
567 : : * @mem: Start of tfm slab
568 : : * @tfm: Transform to free
569 : : *
570 : : * This function frees up the transform and any associated resources,
571 : : * then drops the refcount on the associated algorithm.
572 : : */
573 : 0 : void crypto_destroy_tfm(void *mem, struct crypto_tfm *tfm)
574 : : {
575 : : struct crypto_alg *alg;
576 : :
577 [ # # ]: 0 : if (unlikely(!mem))
578 : 0 : return;
579 : :
580 : 0 : alg = tfm->__crt_alg;
581 : :
582 [ # # ][ # # ]: 0 : if (!tfm->exit && alg->cra_exit)
583 : 0 : alg->cra_exit(tfm);
584 : 0 : crypto_exit_ops(tfm);
585 : 0 : crypto_mod_put(alg);
586 : 0 : kzfree(mem);
587 : : }
588 : : EXPORT_SYMBOL_GPL(crypto_destroy_tfm);
589 : :
590 : 0 : int crypto_has_alg(const char *name, u32 type, u32 mask)
591 : : {
592 : : int ret = 0;
593 : 0 : struct crypto_alg *alg = crypto_alg_mod_lookup(name, type, mask);
594 : :
595 [ # # ]: 0 : if (!IS_ERR(alg)) {
596 : 0 : crypto_mod_put(alg);
597 : : ret = 1;
598 : : }
599 : :
600 : 0 : return ret;
601 : : }
602 : : EXPORT_SYMBOL_GPL(crypto_has_alg);
603 : :
604 : : MODULE_DESCRIPTION("Cryptographic core API");
605 : : MODULE_LICENSE("GPL");
|