aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-12-12 06:23:36 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2008-01-10 16:16:51 -0500
commit5b6d2d7fdf806f2b5a9352416f9e670911fc4748 (patch)
treed2eda87839e1b5de18c691ecff6e6074a35c09f0
parentaedb30dc49eeecd48558b601c47e0b3f9e42c602 (diff)
[CRYPTO] aead: Add aead_geniv_alloc/aead_geniv_free
This patch creates the infrastructure to help the construction of IV generator templates that wrap around AEAD algorithms by adding an IV generator to them. This is useful for AEAD algorithms with no built-in IV generator or to replace their built-in generator. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/aead.c216
-rw-r--r--include/crypto/internal/aead.h77
-rw-r--r--include/linux/crypto.h11
3 files changed, 297 insertions, 7 deletions
diff --git a/crypto/aead.c b/crypto/aead.c
index 15335ed9010a..9f7aca891926 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -12,14 +12,16 @@
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/slab.h> 20#include <linux/slab.h>
21#include <linux/seq_file.h> 21#include <linux/seq_file.h>
22 22
23#include "internal.h"
24
23static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key, 25static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key,
24 unsigned int keylen) 26 unsigned int keylen)
25{ 27{
@@ -55,18 +57,20 @@ static int setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
55 57
56int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize) 58int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
57{ 59{
60 struct aead_tfm *crt = crypto_aead_crt(tfm);
58 int err; 61 int err;
59 62
60 if (authsize > crypto_aead_alg(tfm)->maxauthsize) 63 if (authsize > crypto_aead_alg(tfm)->maxauthsize)
61 return -EINVAL; 64 return -EINVAL;
62 65
63 if (crypto_aead_alg(tfm)->setauthsize) { 66 if (crypto_aead_alg(tfm)->setauthsize) {
64 err = crypto_aead_alg(tfm)->setauthsize(tfm, authsize); 67 err = crypto_aead_alg(tfm)->setauthsize(crt->base, authsize);
65 if (err) 68 if (err)
66 return err; 69 return err;
67 } 70 }
68 71
69 crypto_aead_crt(tfm)->authsize = authsize; 72 crypto_aead_crt(crt->base)->authsize = authsize;
73 crt->authsize = authsize;
70 return 0; 74 return 0;
71} 75}
72EXPORT_SYMBOL_GPL(crypto_aead_setauthsize); 76EXPORT_SYMBOL_GPL(crypto_aead_setauthsize);
@@ -90,11 +94,13 @@ static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
90 if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8) 94 if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
91 return -EINVAL; 95 return -EINVAL;
92 96
93 crt->setkey = setkey; 97 crt->setkey = tfm->__crt_alg->cra_flags & CRYPTO_ALG_GENIV ?
98 alg->setkey : setkey;
94 crt->encrypt = alg->encrypt; 99 crt->encrypt = alg->encrypt;
95 crt->decrypt = alg->decrypt; 100 crt->decrypt = alg->decrypt;
96 crt->givencrypt = alg->givencrypt ?: no_givcrypt; 101 crt->givencrypt = alg->givencrypt ?: no_givcrypt;
97 crt->givdecrypt = alg->givdecrypt ?: no_givcrypt; 102 crt->givdecrypt = alg->givdecrypt ?: no_givcrypt;
103 crt->base = __crypto_aead_cast(tfm);
98 crt->ivsize = alg->ivsize; 104 crt->ivsize = alg->ivsize;
99 crt->authsize = alg->maxauthsize; 105 crt->authsize = alg->maxauthsize;
100 106
@@ -111,6 +117,7 @@ static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
111 seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); 117 seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
112 seq_printf(m, "ivsize : %u\n", aead->ivsize); 118 seq_printf(m, "ivsize : %u\n", aead->ivsize);
113 seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize); 119 seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize);
120 seq_printf(m, "geniv : %s\n", aead->geniv ?: "<built-in>");
114} 121}
115 122
116const struct crypto_type crypto_aead_type = { 123const struct crypto_type crypto_aead_type = {
@@ -122,5 +129,204 @@ const struct crypto_type crypto_aead_type = {
122}; 129};
123EXPORT_SYMBOL_GPL(crypto_aead_type); 130EXPORT_SYMBOL_GPL(crypto_aead_type);
124 131
132static int aead_null_givencrypt(struct aead_givcrypt_request *req)
133{
134 return crypto_aead_encrypt(&req->areq);
135}
136
137static int aead_null_givdecrypt(struct aead_givcrypt_request *req)
138{
139 return crypto_aead_decrypt(&req->areq);
140}
141
142static int crypto_init_nivaead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
143{
144 struct aead_alg *alg = &tfm->__crt_alg->cra_aead;
145 struct aead_tfm *crt = &tfm->crt_aead;
146
147 if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
148 return -EINVAL;
149
150 crt->setkey = setkey;
151 crt->encrypt = alg->encrypt;
152 crt->decrypt = alg->decrypt;
153 if (!alg->ivsize) {
154 crt->givencrypt = aead_null_givencrypt;
155 crt->givdecrypt = aead_null_givdecrypt;
156 }
157 crt->base = __crypto_aead_cast(tfm);
158 crt->ivsize = alg->ivsize;
159 crt->authsize = alg->maxauthsize;
160
161 return 0;
162}
163
164static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
165 __attribute__ ((unused));
166static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
167{
168 struct aead_alg *aead = &alg->cra_aead;
169
170 seq_printf(m, "type : nivaead\n");
171 seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
172 seq_printf(m, "ivsize : %u\n", aead->ivsize);
173 seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize);
174 seq_printf(m, "geniv : %s\n", aead->geniv);
175}
176
177const struct crypto_type crypto_nivaead_type = {
178 .ctxsize = crypto_aead_ctxsize,
179 .init = crypto_init_nivaead_ops,
180#ifdef CONFIG_PROC_FS
181 .show = crypto_nivaead_show,
182#endif
183};
184EXPORT_SYMBOL_GPL(crypto_nivaead_type);
185
186static int crypto_grab_nivaead(struct crypto_aead_spawn *spawn,
187 const char *name, u32 type, u32 mask)
188{
189 struct crypto_alg *alg;
190 int err;
191
192 type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
193 type |= CRYPTO_ALG_TYPE_AEAD;
194 mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV;
195
196 alg = crypto_alg_mod_lookup(name, type, mask);
197 if (IS_ERR(alg))
198 return PTR_ERR(alg);
199
200 err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
201 crypto_mod_put(alg);
202 return err;
203}
204
205struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl,
206 struct rtattr **tb, u32 type,
207 u32 mask)
208{
209 const char *name;
210 struct crypto_aead_spawn *spawn;
211 struct crypto_attr_type *algt;
212 struct crypto_instance *inst;
213 struct crypto_alg *alg;
214 int err;
215
216 algt = crypto_get_attr_type(tb);
217 err = PTR_ERR(algt);
218 if (IS_ERR(algt))
219 return ERR_PTR(err);
220
221 if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV)) &
222 algt->mask)
223 return ERR_PTR(-EINVAL);
224
225 name = crypto_attr_alg_name(tb[1]);
226 err = PTR_ERR(name);
227 if (IS_ERR(name))
228 return ERR_PTR(err);
229
230 inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
231 if (!inst)
232 return ERR_PTR(-ENOMEM);
233
234 spawn = crypto_instance_ctx(inst);
235
236 /* Ignore async algorithms if necessary. */
237 mask |= crypto_requires_sync(algt->type, algt->mask);
238
239 crypto_set_aead_spawn(spawn, inst);
240 err = crypto_grab_nivaead(spawn, name, type, mask);
241 if (err)
242 goto err_free_inst;
243
244 alg = crypto_aead_spawn_alg(spawn);
245
246 err = -EINVAL;
247 if (!alg->cra_aead.ivsize)
248 goto err_drop_alg;
249
250 /*
251 * This is only true if we're constructing an algorithm with its
252 * default IV generator. For the default generator we elide the
253 * template name and double-check the IV generator.
254 */
255 if (algt->mask & CRYPTO_ALG_GENIV) {
256 if (strcmp(tmpl->name, alg->cra_aead.geniv))
257 goto err_drop_alg;
258
259 memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
260 memcpy(inst->alg.cra_driver_name, alg->cra_driver_name,
261 CRYPTO_MAX_ALG_NAME);
262 } else {
263 err = -ENAMETOOLONG;
264 if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
265 "%s(%s)", tmpl->name, alg->cra_name) >=
266 CRYPTO_MAX_ALG_NAME)
267 goto err_drop_alg;
268 if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
269 "%s(%s)", tmpl->name, alg->cra_driver_name) >=
270 CRYPTO_MAX_ALG_NAME)
271 goto err_drop_alg;
272 }
273
274 inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV;
275 inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
276 inst->alg.cra_priority = alg->cra_priority;
277 inst->alg.cra_blocksize = alg->cra_blocksize;
278 inst->alg.cra_alignmask = alg->cra_alignmask;
279 inst->alg.cra_type = &crypto_aead_type;
280
281 inst->alg.cra_aead.ivsize = alg->cra_aead.ivsize;
282 inst->alg.cra_aead.maxauthsize = alg->cra_aead.maxauthsize;
283 inst->alg.cra_aead.geniv = alg->cra_aead.geniv;
284
285 inst->alg.cra_aead.setkey = alg->cra_aead.setkey;
286 inst->alg.cra_aead.setauthsize = alg->cra_aead.setauthsize;
287 inst->alg.cra_aead.encrypt = alg->cra_aead.encrypt;
288 inst->alg.cra_aead.decrypt = alg->cra_aead.decrypt;
289
290out:
291 return inst;
292
293err_drop_alg:
294 crypto_drop_aead(spawn);
295err_free_inst:
296 kfree(inst);
297 inst = ERR_PTR(err);
298 goto out;
299}
300EXPORT_SYMBOL_GPL(aead_geniv_alloc);
301
302void aead_geniv_free(struct crypto_instance *inst)
303{
304 crypto_drop_aead(crypto_instance_ctx(inst));
305 kfree(inst);
306}
307EXPORT_SYMBOL_GPL(aead_geniv_free);
308
309int aead_geniv_init(struct crypto_tfm *tfm)
310{
311 struct crypto_instance *inst = (void *)tfm->__crt_alg;
312 struct crypto_aead *aead;
313
314 aead = crypto_spawn_aead(crypto_instance_ctx(inst));
315 if (IS_ERR(aead))
316 return PTR_ERR(aead);
317
318 tfm->crt_aead.base = aead;
319 tfm->crt_aead.reqsize += crypto_aead_reqsize(aead);
320
321 return 0;
322}
323EXPORT_SYMBOL_GPL(aead_geniv_init);
324
325void aead_geniv_exit(struct crypto_tfm *tfm)
326{
327 crypto_free_aead(tfm->crt_aead.base);
328}
329EXPORT_SYMBOL_GPL(aead_geniv_exit);
330
125MODULE_LICENSE("GPL"); 331MODULE_LICENSE("GPL");
126MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)"); 332MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)");
diff --git a/include/crypto/internal/aead.h b/include/crypto/internal/aead.h
new file mode 100644
index 000000000000..eb4eee7a7804
--- /dev/null
+++ b/include/crypto/internal/aead.h
@@ -0,0 +1,77 @@
1/*
2 * AEAD: Authenticated Encryption with Associated Data
3 *
4 * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 */
12
13#ifndef _CRYPTO_INTERNAL_AEAD_H
14#define _CRYPTO_INTERNAL_AEAD_H
15
16#include <crypto/aead.h>
17#include <crypto/algapi.h>
18#include <linux/types.h>
19
20struct rtattr;
21
22struct crypto_aead_spawn {
23 struct crypto_spawn base;
24};
25
26extern const struct crypto_type crypto_nivaead_type;
27
28static inline void crypto_set_aead_spawn(
29 struct crypto_aead_spawn *spawn, struct crypto_instance *inst)
30{
31 crypto_set_spawn(&spawn->base, inst);
32}
33
34static inline void crypto_drop_aead(struct crypto_aead_spawn *spawn)
35{
36 crypto_drop_spawn(&spawn->base);
37}
38
39static inline struct crypto_alg *crypto_aead_spawn_alg(
40 struct crypto_aead_spawn *spawn)
41{
42 return spawn->base.alg;
43}
44
45static inline struct crypto_aead *crypto_spawn_aead(
46 struct crypto_aead_spawn *spawn)
47{
48 return __crypto_aead_cast(
49 crypto_spawn_tfm(&spawn->base, CRYPTO_ALG_TYPE_AEAD,
50 CRYPTO_ALG_TYPE_MASK));
51}
52
53struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl,
54 struct rtattr **tb, u32 type,
55 u32 mask);
56void aead_geniv_free(struct crypto_instance *inst);
57int aead_geniv_init(struct crypto_tfm *tfm);
58void aead_geniv_exit(struct crypto_tfm *tfm);
59
60static inline struct crypto_aead *aead_geniv_base(struct crypto_aead *geniv)
61{
62 return crypto_aead_crt(geniv)->base;
63}
64
65static inline void *aead_givcrypt_reqctx(struct aead_givcrypt_request *req)
66{
67 return aead_request_ctx(&req->areq);
68}
69
70static inline void aead_givcrypt_complete(struct aead_givcrypt_request *req,
71 int err)
72{
73 aead_request_complete(&req->areq, err);
74}
75
76#endif /* _CRYPTO_INTERNAL_AEAD_H */
77
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 7524928bff93..639385a9672d 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -206,6 +206,8 @@ struct aead_alg {
206 int (*givencrypt)(struct aead_givcrypt_request *req); 206 int (*givencrypt)(struct aead_givcrypt_request *req);
207 int (*givdecrypt)(struct aead_givcrypt_request *req); 207 int (*givdecrypt)(struct aead_givcrypt_request *req);
208 208
209 const char *geniv;
210
209 unsigned int ivsize; 211 unsigned int ivsize;
210 unsigned int maxauthsize; 212 unsigned int maxauthsize;
211}; 213};
@@ -353,6 +355,9 @@ struct aead_tfm {
353 int (*decrypt)(struct aead_request *req); 355 int (*decrypt)(struct aead_request *req);
354 int (*givencrypt)(struct aead_givcrypt_request *req); 356 int (*givencrypt)(struct aead_givcrypt_request *req);
355 int (*givdecrypt)(struct aead_givcrypt_request *req); 357 int (*givdecrypt)(struct aead_givcrypt_request *req);
358
359 struct crypto_aead *base;
360
356 unsigned int ivsize; 361 unsigned int ivsize;
357 unsigned int authsize; 362 unsigned int authsize;
358 unsigned int reqsize; 363 unsigned int reqsize;
@@ -781,7 +786,9 @@ static inline void crypto_aead_clear_flags(struct crypto_aead *tfm, u32 flags)
781static inline int crypto_aead_setkey(struct crypto_aead *tfm, const u8 *key, 786static inline int crypto_aead_setkey(struct crypto_aead *tfm, const u8 *key,
782 unsigned int keylen) 787 unsigned int keylen)
783{ 788{
784 return crypto_aead_crt(tfm)->setkey(tfm, key, keylen); 789 struct aead_tfm *crt = crypto_aead_crt(tfm);
790
791 return crt->setkey(crt->base, key, keylen);
785} 792}
786 793
787int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize); 794int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize);
@@ -809,7 +816,7 @@ static inline unsigned int crypto_aead_reqsize(struct crypto_aead *tfm)
809static inline void aead_request_set_tfm(struct aead_request *req, 816static inline void aead_request_set_tfm(struct aead_request *req,
810 struct crypto_aead *tfm) 817 struct crypto_aead *tfm)
811{ 818{
812 req->base.tfm = crypto_aead_tfm(tfm); 819 req->base.tfm = crypto_aead_tfm(crypto_aead_crt(tfm)->base);
813} 820}
814 821
815static inline struct aead_request *aead_request_alloc(struct crypto_aead *tfm, 822static inline struct aead_request *aead_request_alloc(struct crypto_aead *tfm,