2 * Scatterlist Cryptographic API.
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>
8 * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no>
9 * and Nettle, by Niels Möller.
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)
18 #include <linux/errno.h>
19 #include <linux/kernel.h>
20 #include <linux/kmod.h>
21 #include <linux/slab.h>
22 #include <linux/string.h>
25 LIST_HEAD(crypto_alg_list);
26 EXPORT_SYMBOL_GPL(crypto_alg_list);
27 DECLARE_RWSEM(crypto_alg_sem);
28 EXPORT_SYMBOL_GPL(crypto_alg_sem);
30 static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg)
32 atomic_inc(&alg->cra_refcnt);
36 static inline void crypto_alg_put(struct crypto_alg *alg)
38 if (atomic_dec_and_test(&alg->cra_refcnt) && alg->cra_destroy)
39 alg->cra_destroy(alg);
42 static struct crypto_alg *crypto_mod_get(struct crypto_alg *alg)
44 return try_module_get(alg->cra_module) ? crypto_alg_get(alg) : NULL;
47 static void crypto_mod_put(struct crypto_alg *alg)
50 module_put(alg->cra_module);
53 static struct crypto_alg *crypto_alg_lookup(const char *name)
55 struct crypto_alg *q, *alg = NULL;
61 down_read(&crypto_alg_sem);
63 list_for_each_entry(q, &crypto_alg_list, cra_list) {
66 exact = !strcmp(q->cra_driver_name, name);
67 fuzzy = !strcmp(q->cra_name, name);
68 if (!exact && !(fuzzy && q->cra_priority > best))
71 if (unlikely(!crypto_mod_get(q)))
74 best = q->cra_priority;
83 up_read(&crypto_alg_sem);
87 /* A far more intelligent version of this is planned. For now, just
88 * try an exact match on the name of the algorithm. */
89 static inline struct crypto_alg *crypto_alg_mod_lookup(const char *name)
91 return try_then_request_module(crypto_alg_lookup(name), name);
94 static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags)
96 tfm->crt_flags = flags & CRYPTO_TFM_REQ_MASK;
97 flags &= ~CRYPTO_TFM_REQ_MASK;
99 switch (crypto_tfm_alg_type(tfm)) {
100 case CRYPTO_ALG_TYPE_CIPHER:
101 return crypto_init_cipher_flags(tfm, flags);
103 case CRYPTO_ALG_TYPE_DIGEST:
104 return crypto_init_digest_flags(tfm, flags);
106 case CRYPTO_ALG_TYPE_COMPRESS:
107 return crypto_init_compress_flags(tfm, flags);
117 static int crypto_init_ops(struct crypto_tfm *tfm)
119 switch (crypto_tfm_alg_type(tfm)) {
120 case CRYPTO_ALG_TYPE_CIPHER:
121 return crypto_init_cipher_ops(tfm);
123 case CRYPTO_ALG_TYPE_DIGEST:
124 return crypto_init_digest_ops(tfm);
126 case CRYPTO_ALG_TYPE_COMPRESS:
127 return crypto_init_compress_ops(tfm);
137 static void crypto_exit_ops(struct crypto_tfm *tfm)
139 switch (crypto_tfm_alg_type(tfm)) {
140 case CRYPTO_ALG_TYPE_CIPHER:
141 crypto_exit_cipher_ops(tfm);
144 case CRYPTO_ALG_TYPE_DIGEST:
145 crypto_exit_digest_ops(tfm);
148 case CRYPTO_ALG_TYPE_COMPRESS:
149 crypto_exit_compress_ops(tfm);
158 static unsigned int crypto_ctxsize(struct crypto_alg *alg, int flags)
162 switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
166 case CRYPTO_ALG_TYPE_CIPHER:
167 len = crypto_cipher_ctxsize(alg, flags);
170 case CRYPTO_ALG_TYPE_DIGEST:
171 len = crypto_digest_ctxsize(alg, flags);
174 case CRYPTO_ALG_TYPE_COMPRESS:
175 len = crypto_compress_ctxsize(alg, flags);
179 return len + (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1));
182 struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags)
184 struct crypto_tfm *tfm = NULL;
185 struct crypto_alg *alg;
186 unsigned int tfm_size;
188 alg = crypto_alg_mod_lookup(name);
192 tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, flags);
193 tfm = kzalloc(tfm_size, GFP_KERNEL);
197 tfm->__crt_alg = alg;
199 if (crypto_init_flags(tfm, flags))
202 if (crypto_init_ops(tfm))
205 if (alg->cra_init && alg->cra_init(tfm))
206 goto cra_init_failed;
211 crypto_exit_ops(tfm);
221 void crypto_free_tfm(struct crypto_tfm *tfm)
223 struct crypto_alg *alg;
229 alg = tfm->__crt_alg;
230 size = sizeof(*tfm) + alg->cra_ctxsize;
234 crypto_exit_ops(tfm);
236 memset(tfm, 0, size);
240 int crypto_alg_available(const char *name, u32 flags)
243 struct crypto_alg *alg = crypto_alg_mod_lookup(name);
253 EXPORT_SYMBOL_GPL(crypto_alloc_tfm);
254 EXPORT_SYMBOL_GPL(crypto_free_tfm);
255 EXPORT_SYMBOL_GPL(crypto_alg_available);