Magellan Linux

Annotation of /alx-src/tags/kernel26-2.6.12-alx-r9/crypto/api.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 630 - (hide annotations) (download)
Wed Mar 4 11:03:09 2009 UTC (15 years, 6 months ago) by niro
File MIME type: text/plain
File size: 4473 byte(s)
Tag kernel26-2.6.12-alx-r9
1 niro 628 /*
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);