diff options
Diffstat (limited to 'crypto/aead.c')
-rw-r--r-- | crypto/aead.c | 400 |
1 files changed, 394 insertions, 6 deletions
diff --git a/crypto/aead.c b/crypto/aead.c index 84a3501fb478..3a6f3f52c7c7 100644 --- a/crypto/aead.c +++ b/crypto/aead.c | |||
@@ -12,14 +12,17 @@ | |||
12 | * | 12 | * |
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <crypto/algapi.h> | 15 | #include <crypto/internal/aead.h> |
16 | #include <linux/errno.h> | 16 | #include <linux/err.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/rtnetlink.h> | ||
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
21 | #include <linux/seq_file.h> | 22 | #include <linux/seq_file.h> |
22 | 23 | ||
24 | #include "internal.h" | ||
25 | |||
23 | static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key, | 26 | static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key, |
24 | unsigned int keylen) | 27 | unsigned int keylen) |
25 | { | 28 | { |
@@ -53,25 +56,54 @@ static int setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) | |||
53 | return aead->setkey(tfm, key, keylen); | 56 | return aead->setkey(tfm, key, keylen); |
54 | } | 57 | } |
55 | 58 | ||
59 | int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize) | ||
60 | { | ||
61 | struct aead_tfm *crt = crypto_aead_crt(tfm); | ||
62 | int err; | ||
63 | |||
64 | if (authsize > crypto_aead_alg(tfm)->maxauthsize) | ||
65 | return -EINVAL; | ||
66 | |||
67 | if (crypto_aead_alg(tfm)->setauthsize) { | ||
68 | err = crypto_aead_alg(tfm)->setauthsize(crt->base, authsize); | ||
69 | if (err) | ||
70 | return err; | ||
71 | } | ||
72 | |||
73 | crypto_aead_crt(crt->base)->authsize = authsize; | ||
74 | crt->authsize = authsize; | ||
75 | return 0; | ||
76 | } | ||
77 | EXPORT_SYMBOL_GPL(crypto_aead_setauthsize); | ||
78 | |||
56 | static unsigned int crypto_aead_ctxsize(struct crypto_alg *alg, u32 type, | 79 | static unsigned int crypto_aead_ctxsize(struct crypto_alg *alg, u32 type, |
57 | u32 mask) | 80 | u32 mask) |
58 | { | 81 | { |
59 | return alg->cra_ctxsize; | 82 | return alg->cra_ctxsize; |
60 | } | 83 | } |
61 | 84 | ||
85 | static int no_givcrypt(struct aead_givcrypt_request *req) | ||
86 | { | ||
87 | return -ENOSYS; | ||
88 | } | ||
89 | |||
62 | static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask) | 90 | static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask) |
63 | { | 91 | { |
64 | struct aead_alg *alg = &tfm->__crt_alg->cra_aead; | 92 | struct aead_alg *alg = &tfm->__crt_alg->cra_aead; |
65 | struct aead_tfm *crt = &tfm->crt_aead; | 93 | struct aead_tfm *crt = &tfm->crt_aead; |
66 | 94 | ||
67 | if (max(alg->authsize, alg->ivsize) > PAGE_SIZE / 8) | 95 | if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8) |
68 | return -EINVAL; | 96 | return -EINVAL; |
69 | 97 | ||
70 | crt->setkey = setkey; | 98 | crt->setkey = tfm->__crt_alg->cra_flags & CRYPTO_ALG_GENIV ? |
99 | alg->setkey : setkey; | ||
71 | crt->encrypt = alg->encrypt; | 100 | crt->encrypt = alg->encrypt; |
72 | crt->decrypt = alg->decrypt; | 101 | crt->decrypt = alg->decrypt; |
102 | crt->givencrypt = alg->givencrypt ?: no_givcrypt; | ||
103 | crt->givdecrypt = alg->givdecrypt ?: no_givcrypt; | ||
104 | crt->base = __crypto_aead_cast(tfm); | ||
73 | crt->ivsize = alg->ivsize; | 105 | crt->ivsize = alg->ivsize; |
74 | crt->authsize = alg->authsize; | 106 | crt->authsize = alg->maxauthsize; |
75 | 107 | ||
76 | return 0; | 108 | return 0; |
77 | } | 109 | } |
@@ -83,9 +115,12 @@ static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg) | |||
83 | struct aead_alg *aead = &alg->cra_aead; | 115 | struct aead_alg *aead = &alg->cra_aead; |
84 | 116 | ||
85 | seq_printf(m, "type : aead\n"); | 117 | seq_printf(m, "type : aead\n"); |
118 | seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ? | ||
119 | "yes" : "no"); | ||
86 | seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); | 120 | seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); |
87 | seq_printf(m, "ivsize : %u\n", aead->ivsize); | 121 | seq_printf(m, "ivsize : %u\n", aead->ivsize); |
88 | seq_printf(m, "authsize : %u\n", aead->authsize); | 122 | seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize); |
123 | seq_printf(m, "geniv : %s\n", aead->geniv ?: "<built-in>"); | ||
89 | } | 124 | } |
90 | 125 | ||
91 | const struct crypto_type crypto_aead_type = { | 126 | const struct crypto_type crypto_aead_type = { |
@@ -97,5 +132,358 @@ const struct crypto_type crypto_aead_type = { | |||
97 | }; | 132 | }; |
98 | EXPORT_SYMBOL_GPL(crypto_aead_type); | 133 | EXPORT_SYMBOL_GPL(crypto_aead_type); |
99 | 134 | ||
135 | static int aead_null_givencrypt(struct aead_givcrypt_request *req) | ||
136 | { | ||
137 | return crypto_aead_encrypt(&req->areq); | ||
138 | } | ||
139 | |||
140 | static int aead_null_givdecrypt(struct aead_givcrypt_request *req) | ||
141 | { | ||
142 | return crypto_aead_decrypt(&req->areq); | ||
143 | } | ||
144 | |||
145 | static int crypto_init_nivaead_ops(struct crypto_tfm *tfm, u32 type, u32 mask) | ||
146 | { | ||
147 | struct aead_alg *alg = &tfm->__crt_alg->cra_aead; | ||
148 | struct aead_tfm *crt = &tfm->crt_aead; | ||
149 | |||
150 | if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8) | ||
151 | return -EINVAL; | ||
152 | |||
153 | crt->setkey = setkey; | ||
154 | crt->encrypt = alg->encrypt; | ||
155 | crt->decrypt = alg->decrypt; | ||
156 | if (!alg->ivsize) { | ||
157 | crt->givencrypt = aead_null_givencrypt; | ||
158 | crt->givdecrypt = aead_null_givdecrypt; | ||
159 | } | ||
160 | crt->base = __crypto_aead_cast(tfm); | ||
161 | crt->ivsize = alg->ivsize; | ||
162 | crt->authsize = alg->maxauthsize; | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg) | ||
168 | __attribute__ ((unused)); | ||
169 | static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg) | ||
170 | { | ||
171 | struct aead_alg *aead = &alg->cra_aead; | ||
172 | |||
173 | seq_printf(m, "type : nivaead\n"); | ||
174 | seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ? | ||
175 | "yes" : "no"); | ||
176 | seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); | ||
177 | seq_printf(m, "ivsize : %u\n", aead->ivsize); | ||
178 | seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize); | ||
179 | seq_printf(m, "geniv : %s\n", aead->geniv); | ||
180 | } | ||
181 | |||
182 | const struct crypto_type crypto_nivaead_type = { | ||
183 | .ctxsize = crypto_aead_ctxsize, | ||
184 | .init = crypto_init_nivaead_ops, | ||
185 | #ifdef CONFIG_PROC_FS | ||
186 | .show = crypto_nivaead_show, | ||
187 | #endif | ||
188 | }; | ||
189 | EXPORT_SYMBOL_GPL(crypto_nivaead_type); | ||
190 | |||
191 | static int crypto_grab_nivaead(struct crypto_aead_spawn *spawn, | ||
192 | const char *name, u32 type, u32 mask) | ||
193 | { | ||
194 | struct crypto_alg *alg; | ||
195 | int err; | ||
196 | |||
197 | type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); | ||
198 | type |= CRYPTO_ALG_TYPE_AEAD; | ||
199 | mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV; | ||
200 | |||
201 | alg = crypto_alg_mod_lookup(name, type, mask); | ||
202 | if (IS_ERR(alg)) | ||
203 | return PTR_ERR(alg); | ||
204 | |||
205 | err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask); | ||
206 | crypto_mod_put(alg); | ||
207 | return err; | ||
208 | } | ||
209 | |||
210 | struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl, | ||
211 | struct rtattr **tb, u32 type, | ||
212 | u32 mask) | ||
213 | { | ||
214 | const char *name; | ||
215 | struct crypto_aead_spawn *spawn; | ||
216 | struct crypto_attr_type *algt; | ||
217 | struct crypto_instance *inst; | ||
218 | struct crypto_alg *alg; | ||
219 | int err; | ||
220 | |||
221 | algt = crypto_get_attr_type(tb); | ||
222 | err = PTR_ERR(algt); | ||
223 | if (IS_ERR(algt)) | ||
224 | return ERR_PTR(err); | ||
225 | |||
226 | if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV)) & | ||
227 | algt->mask) | ||
228 | return ERR_PTR(-EINVAL); | ||
229 | |||
230 | name = crypto_attr_alg_name(tb[1]); | ||
231 | err = PTR_ERR(name); | ||
232 | if (IS_ERR(name)) | ||
233 | return ERR_PTR(err); | ||
234 | |||
235 | inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); | ||
236 | if (!inst) | ||
237 | return ERR_PTR(-ENOMEM); | ||
238 | |||
239 | spawn = crypto_instance_ctx(inst); | ||
240 | |||
241 | /* Ignore async algorithms if necessary. */ | ||
242 | mask |= crypto_requires_sync(algt->type, algt->mask); | ||
243 | |||
244 | crypto_set_aead_spawn(spawn, inst); | ||
245 | err = crypto_grab_nivaead(spawn, name, type, mask); | ||
246 | if (err) | ||
247 | goto err_free_inst; | ||
248 | |||
249 | alg = crypto_aead_spawn_alg(spawn); | ||
250 | |||
251 | err = -EINVAL; | ||
252 | if (!alg->cra_aead.ivsize) | ||
253 | goto err_drop_alg; | ||
254 | |||
255 | /* | ||
256 | * This is only true if we're constructing an algorithm with its | ||
257 | * default IV generator. For the default generator we elide the | ||
258 | * template name and double-check the IV generator. | ||
259 | */ | ||
260 | if (algt->mask & CRYPTO_ALG_GENIV) { | ||
261 | if (strcmp(tmpl->name, alg->cra_aead.geniv)) | ||
262 | goto err_drop_alg; | ||
263 | |||
264 | memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME); | ||
265 | memcpy(inst->alg.cra_driver_name, alg->cra_driver_name, | ||
266 | CRYPTO_MAX_ALG_NAME); | ||
267 | } else { | ||
268 | err = -ENAMETOOLONG; | ||
269 | if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, | ||
270 | "%s(%s)", tmpl->name, alg->cra_name) >= | ||
271 | CRYPTO_MAX_ALG_NAME) | ||
272 | goto err_drop_alg; | ||
273 | if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, | ||
274 | "%s(%s)", tmpl->name, alg->cra_driver_name) >= | ||
275 | CRYPTO_MAX_ALG_NAME) | ||
276 | goto err_drop_alg; | ||
277 | } | ||
278 | |||
279 | inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV; | ||
280 | inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC; | ||
281 | inst->alg.cra_priority = alg->cra_priority; | ||
282 | inst->alg.cra_blocksize = alg->cra_blocksize; | ||
283 | inst->alg.cra_alignmask = alg->cra_alignmask; | ||
284 | inst->alg.cra_type = &crypto_aead_type; | ||
285 | |||
286 | inst->alg.cra_aead.ivsize = alg->cra_aead.ivsize; | ||
287 | inst->alg.cra_aead.maxauthsize = alg->cra_aead.maxauthsize; | ||
288 | inst->alg.cra_aead.geniv = alg->cra_aead.geniv; | ||
289 | |||
290 | inst->alg.cra_aead.setkey = alg->cra_aead.setkey; | ||
291 | inst->alg.cra_aead.setauthsize = alg->cra_aead.setauthsize; | ||
292 | inst->alg.cra_aead.encrypt = alg->cra_aead.encrypt; | ||
293 | inst->alg.cra_aead.decrypt = alg->cra_aead.decrypt; | ||
294 | |||
295 | out: | ||
296 | return inst; | ||
297 | |||
298 | err_drop_alg: | ||
299 | crypto_drop_aead(spawn); | ||
300 | err_free_inst: | ||
301 | kfree(inst); | ||
302 | inst = ERR_PTR(err); | ||
303 | goto out; | ||
304 | } | ||
305 | EXPORT_SYMBOL_GPL(aead_geniv_alloc); | ||
306 | |||
307 | void aead_geniv_free(struct crypto_instance *inst) | ||
308 | { | ||
309 | crypto_drop_aead(crypto_instance_ctx(inst)); | ||
310 | kfree(inst); | ||
311 | } | ||
312 | EXPORT_SYMBOL_GPL(aead_geniv_free); | ||
313 | |||
314 | int aead_geniv_init(struct crypto_tfm *tfm) | ||
315 | { | ||
316 | struct crypto_instance *inst = (void *)tfm->__crt_alg; | ||
317 | struct crypto_aead *aead; | ||
318 | |||
319 | aead = crypto_spawn_aead(crypto_instance_ctx(inst)); | ||
320 | if (IS_ERR(aead)) | ||
321 | return PTR_ERR(aead); | ||
322 | |||
323 | tfm->crt_aead.base = aead; | ||
324 | tfm->crt_aead.reqsize += crypto_aead_reqsize(aead); | ||
325 | |||
326 | return 0; | ||
327 | } | ||
328 | EXPORT_SYMBOL_GPL(aead_geniv_init); | ||
329 | |||
330 | void aead_geniv_exit(struct crypto_tfm *tfm) | ||
331 | { | ||
332 | crypto_free_aead(tfm->crt_aead.base); | ||
333 | } | ||
334 | EXPORT_SYMBOL_GPL(aead_geniv_exit); | ||
335 | |||
336 | static int crypto_nivaead_default(struct crypto_alg *alg, u32 type, u32 mask) | ||
337 | { | ||
338 | struct rtattr *tb[3]; | ||
339 | struct { | ||
340 | struct rtattr attr; | ||
341 | struct crypto_attr_type data; | ||
342 | } ptype; | ||
343 | struct { | ||
344 | struct rtattr attr; | ||
345 | struct crypto_attr_alg data; | ||
346 | } palg; | ||
347 | struct crypto_template *tmpl; | ||
348 | struct crypto_instance *inst; | ||
349 | struct crypto_alg *larval; | ||
350 | const char *geniv; | ||
351 | int err; | ||
352 | |||
353 | larval = crypto_larval_lookup(alg->cra_driver_name, | ||
354 | CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV, | ||
355 | CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); | ||
356 | err = PTR_ERR(larval); | ||
357 | if (IS_ERR(larval)) | ||
358 | goto out; | ||
359 | |||
360 | err = -EAGAIN; | ||
361 | if (!crypto_is_larval(larval)) | ||
362 | goto drop_larval; | ||
363 | |||
364 | ptype.attr.rta_len = sizeof(ptype); | ||
365 | ptype.attr.rta_type = CRYPTOA_TYPE; | ||
366 | ptype.data.type = type | CRYPTO_ALG_GENIV; | ||
367 | /* GENIV tells the template that we're making a default geniv. */ | ||
368 | ptype.data.mask = mask | CRYPTO_ALG_GENIV; | ||
369 | tb[0] = &ptype.attr; | ||
370 | |||
371 | palg.attr.rta_len = sizeof(palg); | ||
372 | palg.attr.rta_type = CRYPTOA_ALG; | ||
373 | /* Must use the exact name to locate ourselves. */ | ||
374 | memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME); | ||
375 | tb[1] = &palg.attr; | ||
376 | |||
377 | tb[2] = NULL; | ||
378 | |||
379 | geniv = alg->cra_aead.geniv; | ||
380 | |||
381 | tmpl = crypto_lookup_template(geniv); | ||
382 | err = -ENOENT; | ||
383 | if (!tmpl) | ||
384 | goto kill_larval; | ||
385 | |||
386 | inst = tmpl->alloc(tb); | ||
387 | err = PTR_ERR(inst); | ||
388 | if (IS_ERR(inst)) | ||
389 | goto put_tmpl; | ||
390 | |||
391 | if ((err = crypto_register_instance(tmpl, inst))) { | ||
392 | tmpl->free(inst); | ||
393 | goto put_tmpl; | ||
394 | } | ||
395 | |||
396 | /* Redo the lookup to use the instance we just registered. */ | ||
397 | err = -EAGAIN; | ||
398 | |||
399 | put_tmpl: | ||
400 | crypto_tmpl_put(tmpl); | ||
401 | kill_larval: | ||
402 | crypto_larval_kill(larval); | ||
403 | drop_larval: | ||
404 | crypto_mod_put(larval); | ||
405 | out: | ||
406 | crypto_mod_put(alg); | ||
407 | return err; | ||
408 | } | ||
409 | |||
410 | static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type, | ||
411 | u32 mask) | ||
412 | { | ||
413 | struct crypto_alg *alg; | ||
414 | |||
415 | alg = crypto_alg_mod_lookup(name, type, mask); | ||
416 | if (IS_ERR(alg)) | ||
417 | return alg; | ||
418 | |||
419 | if (alg->cra_type == &crypto_aead_type) | ||
420 | return alg; | ||
421 | |||
422 | if (!alg->cra_aead.ivsize) | ||
423 | return alg; | ||
424 | |||
425 | return ERR_PTR(crypto_nivaead_default(alg, type, mask)); | ||
426 | } | ||
427 | |||
428 | int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name, | ||
429 | u32 type, u32 mask) | ||
430 | { | ||
431 | struct crypto_alg *alg; | ||
432 | int err; | ||
433 | |||
434 | type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); | ||
435 | type |= CRYPTO_ALG_TYPE_AEAD; | ||
436 | mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); | ||
437 | mask |= CRYPTO_ALG_TYPE_MASK; | ||
438 | |||
439 | alg = crypto_lookup_aead(name, type, mask); | ||
440 | if (IS_ERR(alg)) | ||
441 | return PTR_ERR(alg); | ||
442 | |||
443 | err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask); | ||
444 | crypto_mod_put(alg); | ||
445 | return err; | ||
446 | } | ||
447 | EXPORT_SYMBOL_GPL(crypto_grab_aead); | ||
448 | |||
449 | struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask) | ||
450 | { | ||
451 | struct crypto_tfm *tfm; | ||
452 | int err; | ||
453 | |||
454 | type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); | ||
455 | type |= CRYPTO_ALG_TYPE_AEAD; | ||
456 | mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV); | ||
457 | mask |= CRYPTO_ALG_TYPE_MASK; | ||
458 | |||
459 | for (;;) { | ||
460 | struct crypto_alg *alg; | ||
461 | |||
462 | alg = crypto_lookup_aead(alg_name, type, mask); | ||
463 | if (IS_ERR(alg)) { | ||
464 | err = PTR_ERR(alg); | ||
465 | goto err; | ||
466 | } | ||
467 | |||
468 | tfm = __crypto_alloc_tfm(alg, type, mask); | ||
469 | if (!IS_ERR(tfm)) | ||
470 | return __crypto_aead_cast(tfm); | ||
471 | |||
472 | crypto_mod_put(alg); | ||
473 | err = PTR_ERR(tfm); | ||
474 | |||
475 | err: | ||
476 | if (err != -EAGAIN) | ||
477 | break; | ||
478 | if (signal_pending(current)) { | ||
479 | err = -EINTR; | ||
480 | break; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | return ERR_PTR(err); | ||
485 | } | ||
486 | EXPORT_SYMBOL_GPL(crypto_alloc_aead); | ||
487 | |||
100 | MODULE_LICENSE("GPL"); | 488 | MODULE_LICENSE("GPL"); |
101 | MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)"); | 489 | MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)"); |