diff options
Diffstat (limited to 'crypto/ablkcipher.c')
-rw-r--r-- | crypto/ablkcipher.c | 241 |
1 files changed, 239 insertions, 2 deletions
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c index 2731acb86e7d..3bcb099b4a85 100644 --- a/crypto/ablkcipher.c +++ b/crypto/ablkcipher.c | |||
@@ -13,14 +13,18 @@ | |||
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <crypto/algapi.h> | 16 | #include <crypto/internal/skcipher.h> |
17 | #include <linux/errno.h> | 17 | #include <linux/err.h> |
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/rtnetlink.h> | ||
22 | #include <linux/sched.h> | ||
21 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
22 | #include <linux/seq_file.h> | 24 | #include <linux/seq_file.h> |
23 | 25 | ||
26 | #include "internal.h" | ||
27 | |||
24 | static int setkey_unaligned(struct crypto_ablkcipher *tfm, const u8 *key, | 28 | static int setkey_unaligned(struct crypto_ablkcipher *tfm, const u8 *key, |
25 | unsigned int keylen) | 29 | unsigned int keylen) |
26 | { | 30 | { |
@@ -66,6 +70,16 @@ static unsigned int crypto_ablkcipher_ctxsize(struct crypto_alg *alg, u32 type, | |||
66 | return alg->cra_ctxsize; | 70 | return alg->cra_ctxsize; |
67 | } | 71 | } |
68 | 72 | ||
73 | int skcipher_null_givencrypt(struct skcipher_givcrypt_request *req) | ||
74 | { | ||
75 | return crypto_ablkcipher_encrypt(&req->creq); | ||
76 | } | ||
77 | |||
78 | int skcipher_null_givdecrypt(struct skcipher_givcrypt_request *req) | ||
79 | { | ||
80 | return crypto_ablkcipher_decrypt(&req->creq); | ||
81 | } | ||
82 | |||
69 | static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type, | 83 | static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type, |
70 | u32 mask) | 84 | u32 mask) |
71 | { | 85 | { |
@@ -78,6 +92,11 @@ static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type, | |||
78 | crt->setkey = setkey; | 92 | crt->setkey = setkey; |
79 | crt->encrypt = alg->encrypt; | 93 | crt->encrypt = alg->encrypt; |
80 | crt->decrypt = alg->decrypt; | 94 | crt->decrypt = alg->decrypt; |
95 | if (!alg->ivsize) { | ||
96 | crt->givencrypt = skcipher_null_givencrypt; | ||
97 | crt->givdecrypt = skcipher_null_givdecrypt; | ||
98 | } | ||
99 | crt->base = __crypto_ablkcipher_cast(tfm); | ||
81 | crt->ivsize = alg->ivsize; | 100 | crt->ivsize = alg->ivsize; |
82 | 101 | ||
83 | return 0; | 102 | return 0; |
@@ -90,10 +109,13 @@ static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg) | |||
90 | struct ablkcipher_alg *ablkcipher = &alg->cra_ablkcipher; | 109 | struct ablkcipher_alg *ablkcipher = &alg->cra_ablkcipher; |
91 | 110 | ||
92 | seq_printf(m, "type : ablkcipher\n"); | 111 | seq_printf(m, "type : ablkcipher\n"); |
112 | seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ? | ||
113 | "yes" : "no"); | ||
93 | seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); | 114 | seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); |
94 | seq_printf(m, "min keysize : %u\n", ablkcipher->min_keysize); | 115 | seq_printf(m, "min keysize : %u\n", ablkcipher->min_keysize); |
95 | seq_printf(m, "max keysize : %u\n", ablkcipher->max_keysize); | 116 | seq_printf(m, "max keysize : %u\n", ablkcipher->max_keysize); |
96 | seq_printf(m, "ivsize : %u\n", ablkcipher->ivsize); | 117 | seq_printf(m, "ivsize : %u\n", ablkcipher->ivsize); |
118 | seq_printf(m, "geniv : %s\n", ablkcipher->geniv ?: "<default>"); | ||
97 | } | 119 | } |
98 | 120 | ||
99 | const struct crypto_type crypto_ablkcipher_type = { | 121 | const struct crypto_type crypto_ablkcipher_type = { |
@@ -105,5 +127,220 @@ const struct crypto_type crypto_ablkcipher_type = { | |||
105 | }; | 127 | }; |
106 | EXPORT_SYMBOL_GPL(crypto_ablkcipher_type); | 128 | EXPORT_SYMBOL_GPL(crypto_ablkcipher_type); |
107 | 129 | ||
130 | static int no_givdecrypt(struct skcipher_givcrypt_request *req) | ||
131 | { | ||
132 | return -ENOSYS; | ||
133 | } | ||
134 | |||
135 | static int crypto_init_givcipher_ops(struct crypto_tfm *tfm, u32 type, | ||
136 | u32 mask) | ||
137 | { | ||
138 | struct ablkcipher_alg *alg = &tfm->__crt_alg->cra_ablkcipher; | ||
139 | struct ablkcipher_tfm *crt = &tfm->crt_ablkcipher; | ||
140 | |||
141 | if (alg->ivsize > PAGE_SIZE / 8) | ||
142 | return -EINVAL; | ||
143 | |||
144 | crt->setkey = tfm->__crt_alg->cra_flags & CRYPTO_ALG_GENIV ? | ||
145 | alg->setkey : setkey; | ||
146 | crt->encrypt = alg->encrypt; | ||
147 | crt->decrypt = alg->decrypt; | ||
148 | crt->givencrypt = alg->givencrypt; | ||
149 | crt->givdecrypt = alg->givdecrypt ?: no_givdecrypt; | ||
150 | crt->base = __crypto_ablkcipher_cast(tfm); | ||
151 | crt->ivsize = alg->ivsize; | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg) | ||
157 | __attribute__ ((unused)); | ||
158 | static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg) | ||
159 | { | ||
160 | struct ablkcipher_alg *ablkcipher = &alg->cra_ablkcipher; | ||
161 | |||
162 | seq_printf(m, "type : givcipher\n"); | ||
163 | seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ? | ||
164 | "yes" : "no"); | ||
165 | seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); | ||
166 | seq_printf(m, "min keysize : %u\n", ablkcipher->min_keysize); | ||
167 | seq_printf(m, "max keysize : %u\n", ablkcipher->max_keysize); | ||
168 | seq_printf(m, "ivsize : %u\n", ablkcipher->ivsize); | ||
169 | seq_printf(m, "geniv : %s\n", ablkcipher->geniv ?: "<built-in>"); | ||
170 | } | ||
171 | |||
172 | const struct crypto_type crypto_givcipher_type = { | ||
173 | .ctxsize = crypto_ablkcipher_ctxsize, | ||
174 | .init = crypto_init_givcipher_ops, | ||
175 | #ifdef CONFIG_PROC_FS | ||
176 | .show = crypto_givcipher_show, | ||
177 | #endif | ||
178 | }; | ||
179 | EXPORT_SYMBOL_GPL(crypto_givcipher_type); | ||
180 | |||
181 | const char *crypto_default_geniv(const struct crypto_alg *alg) | ||
182 | { | ||
183 | return alg->cra_flags & CRYPTO_ALG_ASYNC ? "eseqiv" : "chainiv"; | ||
184 | } | ||
185 | |||
186 | static int crypto_givcipher_default(struct crypto_alg *alg, u32 type, u32 mask) | ||
187 | { | ||
188 | struct rtattr *tb[3]; | ||
189 | struct { | ||
190 | struct rtattr attr; | ||
191 | struct crypto_attr_type data; | ||
192 | } ptype; | ||
193 | struct { | ||
194 | struct rtattr attr; | ||
195 | struct crypto_attr_alg data; | ||
196 | } palg; | ||
197 | struct crypto_template *tmpl; | ||
198 | struct crypto_instance *inst; | ||
199 | struct crypto_alg *larval; | ||
200 | const char *geniv; | ||
201 | int err; | ||
202 | |||
203 | larval = crypto_larval_lookup(alg->cra_driver_name, | ||
204 | CRYPTO_ALG_TYPE_GIVCIPHER, | ||
205 | CRYPTO_ALG_TYPE_MASK); | ||
206 | err = PTR_ERR(larval); | ||
207 | if (IS_ERR(larval)) | ||
208 | goto out; | ||
209 | |||
210 | err = -EAGAIN; | ||
211 | if (!crypto_is_larval(larval)) | ||
212 | goto drop_larval; | ||
213 | |||
214 | ptype.attr.rta_len = sizeof(ptype); | ||
215 | ptype.attr.rta_type = CRYPTOA_TYPE; | ||
216 | ptype.data.type = type | CRYPTO_ALG_GENIV; | ||
217 | /* GENIV tells the template that we're making a default geniv. */ | ||
218 | ptype.data.mask = mask | CRYPTO_ALG_GENIV; | ||
219 | tb[0] = &ptype.attr; | ||
220 | |||
221 | palg.attr.rta_len = sizeof(palg); | ||
222 | palg.attr.rta_type = CRYPTOA_ALG; | ||
223 | /* Must use the exact name to locate ourselves. */ | ||
224 | memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME); | ||
225 | tb[1] = &palg.attr; | ||
226 | |||
227 | tb[2] = NULL; | ||
228 | |||
229 | if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == | ||
230 | CRYPTO_ALG_TYPE_BLKCIPHER) | ||
231 | geniv = alg->cra_blkcipher.geniv; | ||
232 | else | ||
233 | geniv = alg->cra_ablkcipher.geniv; | ||
234 | |||
235 | if (!geniv) | ||
236 | geniv = crypto_default_geniv(alg); | ||
237 | |||
238 | tmpl = crypto_lookup_template(geniv); | ||
239 | err = -ENOENT; | ||
240 | if (!tmpl) | ||
241 | goto kill_larval; | ||
242 | |||
243 | inst = tmpl->alloc(tb); | ||
244 | err = PTR_ERR(inst); | ||
245 | if (IS_ERR(inst)) | ||
246 | goto put_tmpl; | ||
247 | |||
248 | if ((err = crypto_register_instance(tmpl, inst))) { | ||
249 | tmpl->free(inst); | ||
250 | goto put_tmpl; | ||
251 | } | ||
252 | |||
253 | /* Redo the lookup to use the instance we just registered. */ | ||
254 | err = -EAGAIN; | ||
255 | |||
256 | put_tmpl: | ||
257 | crypto_tmpl_put(tmpl); | ||
258 | kill_larval: | ||
259 | crypto_larval_kill(larval); | ||
260 | drop_larval: | ||
261 | crypto_mod_put(larval); | ||
262 | out: | ||
263 | crypto_mod_put(alg); | ||
264 | return err; | ||
265 | } | ||
266 | |||
267 | static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type, | ||
268 | u32 mask) | ||
269 | { | ||
270 | struct crypto_alg *alg; | ||
271 | |||
272 | alg = crypto_alg_mod_lookup(name, type, mask); | ||
273 | if (IS_ERR(alg)) | ||
274 | return alg; | ||
275 | |||
276 | if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == | ||
277 | CRYPTO_ALG_TYPE_GIVCIPHER) | ||
278 | return alg; | ||
279 | |||
280 | if (!((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == | ||
281 | CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize : | ||
282 | alg->cra_ablkcipher.ivsize)) | ||
283 | return alg; | ||
284 | |||
285 | return ERR_PTR(crypto_givcipher_default(alg, type, mask)); | ||
286 | } | ||
287 | |||
288 | int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name, | ||
289 | u32 type, u32 mask) | ||
290 | { | ||
291 | struct crypto_alg *alg; | ||
292 | int err; | ||
293 | |||
294 | type = crypto_skcipher_type(type); | ||
295 | mask = crypto_skcipher_mask(mask); | ||
296 | |||
297 | alg = crypto_lookup_skcipher(name, type, mask); | ||
298 | if (IS_ERR(alg)) | ||
299 | return PTR_ERR(alg); | ||
300 | |||
301 | err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask); | ||
302 | crypto_mod_put(alg); | ||
303 | return err; | ||
304 | } | ||
305 | EXPORT_SYMBOL_GPL(crypto_grab_skcipher); | ||
306 | |||
307 | struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name, | ||
308 | u32 type, u32 mask) | ||
309 | { | ||
310 | struct crypto_tfm *tfm; | ||
311 | int err; | ||
312 | |||
313 | type = crypto_skcipher_type(type); | ||
314 | mask = crypto_skcipher_mask(mask); | ||
315 | |||
316 | for (;;) { | ||
317 | struct crypto_alg *alg; | ||
318 | |||
319 | alg = crypto_lookup_skcipher(alg_name, type, mask); | ||
320 | if (IS_ERR(alg)) { | ||
321 | err = PTR_ERR(alg); | ||
322 | goto err; | ||
323 | } | ||
324 | |||
325 | tfm = __crypto_alloc_tfm(alg, type, mask); | ||
326 | if (!IS_ERR(tfm)) | ||
327 | return __crypto_ablkcipher_cast(tfm); | ||
328 | |||
329 | crypto_mod_put(alg); | ||
330 | err = PTR_ERR(tfm); | ||
331 | |||
332 | err: | ||
333 | if (err != -EAGAIN) | ||
334 | break; | ||
335 | if (signal_pending(current)) { | ||
336 | err = -EINTR; | ||
337 | break; | ||
338 | } | ||
339 | } | ||
340 | |||
341 | return ERR_PTR(err); | ||
342 | } | ||
343 | EXPORT_SYMBOL_GPL(crypto_alloc_ablkcipher); | ||
344 | |||
108 | MODULE_LICENSE("GPL"); | 345 | MODULE_LICENSE("GPL"); |
109 | MODULE_DESCRIPTION("Asynchronous block chaining cipher type"); | 346 | MODULE_DESCRIPTION("Asynchronous block chaining cipher type"); |