Contents of /alx-src/tags/kernel26-2.6.12-alx-r9/crypto/api.c
Parent Directory | Revision Log
Revision 630 -
(show annotations)
(download)
Wed Mar 4 11:03:09 2009 UTC (15 years, 2 months ago) by niro
File MIME type: text/plain
File size: 4473 byte(s)
Wed Mar 4 11:03:09 2009 UTC (15 years, 2 months ago) by niro
File MIME type: text/plain
File size: 4473 byte(s)
Tag kernel26-2.6.12-alx-r9
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 | * |
7 | * Portions derived from Cryptoapi, by Alexander Kjeldaas <astor@fast.no> |
8 | * and Nettle, by Niels Möller. |
9 | * |
10 | * This program is free software; you can redistribute it and/or modify it |
11 | * under the terms of the GNU General Public License as published by the Free |
12 | * Software Foundation; either version 2 of the License, or (at your option) |
13 | * any later version. |
14 | * |
15 | */ |
16 | #include <linux/init.h> |
17 | #include <linux/crypto.h> |
18 | #include <linux/errno.h> |
19 | #include <linux/rwsem.h> |
20 | #include <linux/slab.h> |
21 | #include "internal.h" |
22 | |
23 | LIST_HEAD(crypto_alg_list); |
24 | DECLARE_RWSEM(crypto_alg_sem); |
25 | |
26 | static inline int crypto_alg_get(struct crypto_alg *alg) |
27 | { |
28 | return try_module_get(alg->cra_module); |
29 | } |
30 | |
31 | static inline void crypto_alg_put(struct crypto_alg *alg) |
32 | { |
33 | module_put(alg->cra_module); |
34 | } |
35 | |
36 | struct crypto_alg *crypto_alg_lookup(const char *name) |
37 | { |
38 | struct crypto_alg *q, *alg = NULL; |
39 | |
40 | if (!name) |
41 | return NULL; |
42 | |
43 | down_read(&crypto_alg_sem); |
44 | |
45 | list_for_each_entry(q, &crypto_alg_list, cra_list) { |
46 | if (!(strcmp(q->cra_name, name))) { |
47 | if (crypto_alg_get(q)) |
48 | alg = q; |
49 | break; |
50 | } |
51 | } |
52 | |
53 | up_read(&crypto_alg_sem); |
54 | return alg; |
55 | } |
56 | |
57 | static int crypto_init_flags(struct crypto_tfm *tfm, u32 flags) |
58 | { |
59 | tfm->crt_flags = 0; |
60 | |
61 | switch (crypto_tfm_alg_type(tfm)) { |
62 | case CRYPTO_ALG_TYPE_CIPHER: |
63 | return crypto_init_cipher_flags(tfm, flags); |
64 | |
65 | case CRYPTO_ALG_TYPE_DIGEST: |
66 | return crypto_init_digest_flags(tfm, flags); |
67 | |
68 | case CRYPTO_ALG_TYPE_COMPRESS: |
69 | return crypto_init_compress_flags(tfm, flags); |
70 | |
71 | default: |
72 | break; |
73 | } |
74 | |
75 | BUG(); |
76 | return -EINVAL; |
77 | } |
78 | |
79 | static int crypto_init_ops(struct crypto_tfm *tfm) |
80 | { |
81 | switch (crypto_tfm_alg_type(tfm)) { |
82 | case CRYPTO_ALG_TYPE_CIPHER: |
83 | return crypto_init_cipher_ops(tfm); |
84 | |
85 | case CRYPTO_ALG_TYPE_DIGEST: |
86 | return crypto_init_digest_ops(tfm); |
87 | |
88 | case CRYPTO_ALG_TYPE_COMPRESS: |
89 | return crypto_init_compress_ops(tfm); |
90 | |
91 | default: |
92 | break; |
93 | } |
94 | |
95 | BUG(); |
96 | return -EINVAL; |
97 | } |
98 | |
99 | static void crypto_exit_ops(struct crypto_tfm *tfm) |
100 | { |
101 | switch (crypto_tfm_alg_type(tfm)) { |
102 | case CRYPTO_ALG_TYPE_CIPHER: |
103 | crypto_exit_cipher_ops(tfm); |
104 | break; |
105 | |
106 | case CRYPTO_ALG_TYPE_DIGEST: |
107 | crypto_exit_digest_ops(tfm); |
108 | break; |
109 | |
110 | case CRYPTO_ALG_TYPE_COMPRESS: |
111 | crypto_exit_compress_ops(tfm); |
112 | break; |
113 | |
114 | default: |
115 | BUG(); |
116 | |
117 | } |
118 | } |
119 | |
120 | struct crypto_tfm *crypto_alloc_tfm(const char *name, u32 flags) |
121 | { |
122 | struct crypto_tfm *tfm = NULL; |
123 | struct crypto_alg *alg; |
124 | |
125 | alg = crypto_alg_mod_lookup(name); |
126 | if (alg == NULL) |
127 | goto out; |
128 | |
129 | tfm = kmalloc(sizeof(*tfm) + alg->cra_ctxsize, GFP_KERNEL); |
130 | if (tfm == NULL) |
131 | goto out_put; |
132 | |
133 | memset(tfm, 0, sizeof(*tfm) + alg->cra_ctxsize); |
134 | |
135 | tfm->__crt_alg = alg; |
136 | |
137 | if (crypto_init_flags(tfm, flags)) |
138 | goto out_free_tfm; |
139 | |
140 | if (crypto_init_ops(tfm)) { |
141 | crypto_exit_ops(tfm); |
142 | goto out_free_tfm; |
143 | } |
144 | |
145 | goto out; |
146 | |
147 | out_free_tfm: |
148 | kfree(tfm); |
149 | tfm = NULL; |
150 | out_put: |
151 | crypto_alg_put(alg); |
152 | out: |
153 | return tfm; |
154 | } |
155 | |
156 | void crypto_free_tfm(struct crypto_tfm *tfm) |
157 | { |
158 | struct crypto_alg *alg = tfm->__crt_alg; |
159 | int size = sizeof(*tfm) + alg->cra_ctxsize; |
160 | |
161 | crypto_exit_ops(tfm); |
162 | crypto_alg_put(alg); |
163 | memset(tfm, 0, size); |
164 | kfree(tfm); |
165 | } |
166 | |
167 | int crypto_register_alg(struct crypto_alg *alg) |
168 | { |
169 | int ret = 0; |
170 | struct crypto_alg *q; |
171 | |
172 | down_write(&crypto_alg_sem); |
173 | |
174 | list_for_each_entry(q, &crypto_alg_list, cra_list) { |
175 | if (!(strcmp(q->cra_name, alg->cra_name))) { |
176 | ret = -EEXIST; |
177 | goto out; |
178 | } |
179 | } |
180 | |
181 | list_add_tail(&alg->cra_list, &crypto_alg_list); |
182 | out: |
183 | up_write(&crypto_alg_sem); |
184 | return ret; |
185 | } |
186 | |
187 | int crypto_unregister_alg(struct crypto_alg *alg) |
188 | { |
189 | int ret = -ENOENT; |
190 | struct crypto_alg *q; |
191 | |
192 | BUG_ON(!alg->cra_module); |
193 | |
194 | down_write(&crypto_alg_sem); |
195 | list_for_each_entry(q, &crypto_alg_list, cra_list) { |
196 | if (alg == q) { |
197 | list_del(&alg->cra_list); |
198 | ret = 0; |
199 | goto out; |
200 | } |
201 | } |
202 | out: |
203 | up_write(&crypto_alg_sem); |
204 | return ret; |
205 | } |
206 | |
207 | int crypto_alg_available(const char *name, u32 flags) |
208 | { |
209 | int ret = 0; |
210 | struct crypto_alg *alg = crypto_alg_mod_lookup(name); |
211 | |
212 | if (alg) { |
213 | crypto_alg_put(alg); |
214 | ret = 1; |
215 | } |
216 | |
217 | return ret; |
218 | } |
219 | |
220 | static int __init init_crypto(void) |
221 | { |
222 | printk(KERN_INFO "Initializing Cryptographic API\n"); |
223 | crypto_init_proc(); |
224 | return 0; |
225 | } |
226 | |
227 | __initcall(init_crypto); |
228 | |
229 | EXPORT_SYMBOL_GPL(crypto_register_alg); |
230 | EXPORT_SYMBOL_GPL(crypto_unregister_alg); |
231 | EXPORT_SYMBOL_GPL(crypto_alloc_tfm); |
232 | EXPORT_SYMBOL_GPL(crypto_free_tfm); |
233 | EXPORT_SYMBOL_GPL(crypto_alg_available); |