2 * Authenc: Simple AEAD wrapper for IPsec
4 * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
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)
13 #include <crypto/algapi.h>
14 #include <crypto/authenc.h>
15 #include <crypto/scatterwalk.h>
16 #include <linux/err.h>
17 #include <linux/init.h>
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/rtnetlink.h>
21 #include <linux/slab.h>
22 #include <linux/spinlock.h>
24 struct authenc_instance_ctx
{
25 struct crypto_spawn auth
;
26 struct crypto_spawn enc
;
29 struct crypto_authenc_ctx
{
31 struct crypto_hash
*auth
;
32 struct crypto_ablkcipher
*enc
;
35 static int crypto_authenc_setkey(struct crypto_aead
*authenc
, const u8
*key
,
38 unsigned int authkeylen
;
39 unsigned int enckeylen
;
40 struct crypto_authenc_ctx
*ctx
= crypto_aead_ctx(authenc
);
41 struct crypto_hash
*auth
= ctx
->auth
;
42 struct crypto_ablkcipher
*enc
= ctx
->enc
;
43 struct rtattr
*rta
= (void *)key
;
44 struct crypto_authenc_key_param
*param
;
47 if (!RTA_OK(rta
, keylen
))
49 if (rta
->rta_type
!= CRYPTO_AUTHENC_KEYA_PARAM
)
51 if (RTA_PAYLOAD(rta
) < sizeof(*param
))
54 param
= RTA_DATA(rta
);
55 enckeylen
= be32_to_cpu(param
->enckeylen
);
57 key
+= RTA_ALIGN(rta
->rta_len
);
58 keylen
-= RTA_ALIGN(rta
->rta_len
);
60 if (keylen
< enckeylen
)
63 authkeylen
= keylen
- enckeylen
;
65 crypto_hash_clear_flags(auth
, CRYPTO_TFM_REQ_MASK
);
66 crypto_hash_set_flags(auth
, crypto_aead_get_flags(authenc
) &
68 err
= crypto_hash_setkey(auth
, key
, authkeylen
);
69 crypto_aead_set_flags(authenc
, crypto_hash_get_flags(auth
) &
75 crypto_ablkcipher_clear_flags(enc
, CRYPTO_TFM_REQ_MASK
);
76 crypto_ablkcipher_set_flags(enc
, crypto_aead_get_flags(authenc
) &
78 err
= crypto_ablkcipher_setkey(enc
, key
+ authkeylen
, enckeylen
);
79 crypto_aead_set_flags(authenc
, crypto_ablkcipher_get_flags(enc
) &
86 crypto_aead_set_flags(authenc
, CRYPTO_TFM_RES_BAD_KEY_LEN
);
90 static u8
*crypto_authenc_hash(struct aead_request
*req
, unsigned int flags
,
91 struct scatterlist
*cipher
,
92 unsigned int cryptlen
)
94 struct crypto_aead
*authenc
= crypto_aead_reqtfm(req
);
95 struct crypto_authenc_ctx
*ctx
= crypto_aead_ctx(authenc
);
96 struct crypto_hash
*auth
= ctx
->auth
;
97 struct hash_desc desc
= {
99 .flags
= aead_request_flags(req
) & flags
,
101 u8
*hash
= aead_request_ctx(req
);
104 hash
= (u8
*)ALIGN((unsigned long)hash
+ crypto_hash_alignmask(auth
),
105 crypto_hash_alignmask(auth
) + 1);
107 spin_lock_bh(&ctx
->auth_lock
);
108 err
= crypto_hash_init(&desc
);
112 err
= crypto_hash_update(&desc
, req
->assoc
, req
->assoclen
);
116 err
= crypto_hash_update(&desc
, cipher
, cryptlen
);
120 err
= crypto_hash_final(&desc
, hash
);
122 spin_unlock_bh(&ctx
->auth_lock
);
130 static int crypto_authenc_genicv(struct aead_request
*req
, unsigned int flags
)
132 struct crypto_aead
*authenc
= crypto_aead_reqtfm(req
);
133 struct scatterlist
*dst
= req
->dst
;
134 unsigned int cryptlen
= req
->cryptlen
;
137 hash
= crypto_authenc_hash(req
, flags
, dst
, cryptlen
);
139 return PTR_ERR(hash
);
141 scatterwalk_map_and_copy(hash
, dst
, cryptlen
,
142 crypto_aead_authsize(authenc
), 1);
146 static void crypto_authenc_encrypt_done(struct crypto_async_request
*req
,
150 err
= crypto_authenc_genicv(req
->data
, 0);
152 aead_request_complete(req
->data
, err
);
155 static int crypto_authenc_encrypt(struct aead_request
*req
)
157 struct crypto_aead
*authenc
= crypto_aead_reqtfm(req
);
158 struct crypto_authenc_ctx
*ctx
= crypto_aead_ctx(authenc
);
159 struct ablkcipher_request
*abreq
= aead_request_ctx(req
);
162 ablkcipher_request_set_tfm(abreq
, ctx
->enc
);
163 ablkcipher_request_set_callback(abreq
, aead_request_flags(req
),
164 crypto_authenc_encrypt_done
, req
);
165 ablkcipher_request_set_crypt(abreq
, req
->src
, req
->dst
, req
->cryptlen
,
168 err
= crypto_ablkcipher_encrypt(abreq
);
172 return crypto_authenc_genicv(req
, CRYPTO_TFM_REQ_MAY_SLEEP
);
175 static int crypto_authenc_verify(struct aead_request
*req
,
176 unsigned int cryptlen
)
178 struct crypto_aead
*authenc
= crypto_aead_reqtfm(req
);
181 struct scatterlist
*src
= req
->src
;
182 unsigned int authsize
;
184 ohash
= crypto_authenc_hash(req
, CRYPTO_TFM_REQ_MAY_SLEEP
, src
,
187 return PTR_ERR(ohash
);
189 authsize
= crypto_aead_authsize(authenc
);
190 ihash
= ohash
+ authsize
;
191 scatterwalk_map_and_copy(ihash
, src
, cryptlen
, authsize
, 0);
192 return memcmp(ihash
, ohash
, authsize
) ? -EBADMSG
: 0;
195 static void crypto_authenc_decrypt_done(struct crypto_async_request
*req
,
198 aead_request_complete(req
->data
, err
);
201 static int crypto_authenc_decrypt(struct aead_request
*req
)
203 struct crypto_aead
*authenc
= crypto_aead_reqtfm(req
);
204 struct crypto_authenc_ctx
*ctx
= crypto_aead_ctx(authenc
);
205 struct ablkcipher_request
*abreq
= aead_request_ctx(req
);
206 unsigned int cryptlen
= req
->cryptlen
;
207 unsigned int authsize
= crypto_aead_authsize(authenc
);
210 if (cryptlen
< authsize
)
212 cryptlen
-= authsize
;
214 err
= crypto_authenc_verify(req
, cryptlen
);
218 ablkcipher_request_set_tfm(abreq
, ctx
->enc
);
219 ablkcipher_request_set_callback(abreq
, aead_request_flags(req
),
220 crypto_authenc_decrypt_done
, req
);
221 ablkcipher_request_set_crypt(abreq
, req
->src
, req
->dst
, cryptlen
,
224 return crypto_ablkcipher_decrypt(abreq
);
227 static int crypto_authenc_init_tfm(struct crypto_tfm
*tfm
)
229 struct crypto_instance
*inst
= (void *)tfm
->__crt_alg
;
230 struct authenc_instance_ctx
*ictx
= crypto_instance_ctx(inst
);
231 struct crypto_authenc_ctx
*ctx
= crypto_tfm_ctx(tfm
);
232 struct crypto_hash
*auth
;
233 struct crypto_ablkcipher
*enc
;
236 auth
= crypto_spawn_hash(&ictx
->auth
);
238 return PTR_ERR(auth
);
240 enc
= crypto_spawn_ablkcipher(&ictx
->enc
);
247 tfm
->crt_aead
.reqsize
= max_t(unsigned int,
248 (crypto_hash_alignmask(auth
) &
249 ~(crypto_tfm_ctx_alignment() - 1)) +
250 crypto_hash_digestsize(auth
) * 2,
251 sizeof(struct ablkcipher_request
) +
252 crypto_ablkcipher_reqsize(enc
));
254 spin_lock_init(&ctx
->auth_lock
);
259 crypto_free_hash(auth
);
263 static void crypto_authenc_exit_tfm(struct crypto_tfm
*tfm
)
265 struct crypto_authenc_ctx
*ctx
= crypto_tfm_ctx(tfm
);
267 crypto_free_hash(ctx
->auth
);
268 crypto_free_ablkcipher(ctx
->enc
);
271 static struct crypto_instance
*crypto_authenc_alloc(struct rtattr
**tb
)
273 struct crypto_instance
*inst
;
274 struct crypto_alg
*auth
;
275 struct crypto_alg
*enc
;
276 struct authenc_instance_ctx
*ctx
;
279 err
= crypto_check_attr_type(tb
, CRYPTO_ALG_TYPE_AEAD
);
283 auth
= crypto_attr_alg(tb
[1], CRYPTO_ALG_TYPE_HASH
,
284 CRYPTO_ALG_TYPE_HASH_MASK
);
286 return ERR_PTR(PTR_ERR(auth
));
288 enc
= crypto_attr_alg(tb
[2], CRYPTO_ALG_TYPE_BLKCIPHER
,
289 CRYPTO_ALG_TYPE_BLKCIPHER_MASK
);
290 inst
= ERR_PTR(PTR_ERR(enc
));
294 inst
= kzalloc(sizeof(*inst
) + sizeof(*ctx
), GFP_KERNEL
);
300 if (snprintf(inst
->alg
.cra_name
, CRYPTO_MAX_ALG_NAME
,
301 "authenc(%s,%s)", auth
->cra_name
, enc
->cra_name
) >=
305 if (snprintf(inst
->alg
.cra_driver_name
, CRYPTO_MAX_ALG_NAME
,
306 "authenc(%s,%s)", auth
->cra_driver_name
,
307 enc
->cra_driver_name
) >= CRYPTO_MAX_ALG_NAME
)
310 ctx
= crypto_instance_ctx(inst
);
312 err
= crypto_init_spawn(&ctx
->auth
, auth
, inst
, CRYPTO_ALG_TYPE_MASK
);
316 err
= crypto_init_spawn(&ctx
->enc
, enc
, inst
, CRYPTO_ALG_TYPE_MASK
);
320 inst
->alg
.cra_flags
= CRYPTO_ALG_TYPE_AEAD
| CRYPTO_ALG_ASYNC
;
321 inst
->alg
.cra_priority
= enc
->cra_priority
* 10 + auth
->cra_priority
;
322 inst
->alg
.cra_blocksize
= enc
->cra_blocksize
;
323 inst
->alg
.cra_alignmask
= auth
->cra_alignmask
| enc
->cra_alignmask
;
324 inst
->alg
.cra_type
= &crypto_aead_type
;
326 inst
->alg
.cra_aead
.ivsize
= enc
->cra_ablkcipher
.ivsize
;
327 inst
->alg
.cra_aead
.maxauthsize
= auth
->cra_type
== &crypto_hash_type
?
328 auth
->cra_hash
.digestsize
:
329 auth
->cra_digest
.dia_digestsize
;
331 inst
->alg
.cra_ctxsize
= sizeof(struct crypto_authenc_ctx
);
333 inst
->alg
.cra_init
= crypto_authenc_init_tfm
;
334 inst
->alg
.cra_exit
= crypto_authenc_exit_tfm
;
336 inst
->alg
.cra_aead
.setkey
= crypto_authenc_setkey
;
337 inst
->alg
.cra_aead
.encrypt
= crypto_authenc_encrypt
;
338 inst
->alg
.cra_aead
.decrypt
= crypto_authenc_decrypt
;
343 crypto_mod_put(auth
);
347 crypto_drop_spawn(&ctx
->auth
);
355 static void crypto_authenc_free(struct crypto_instance
*inst
)
357 struct authenc_instance_ctx
*ctx
= crypto_instance_ctx(inst
);
359 crypto_drop_spawn(&ctx
->enc
);
360 crypto_drop_spawn(&ctx
->auth
);
364 static struct crypto_template crypto_authenc_tmpl
= {
366 .alloc
= crypto_authenc_alloc
,
367 .free
= crypto_authenc_free
,
368 .module
= THIS_MODULE
,
371 static int __init
crypto_authenc_module_init(void)
373 return crypto_register_template(&crypto_authenc_tmpl
);
376 static void __exit
crypto_authenc_module_exit(void)
378 crypto_unregister_template(&crypto_authenc_tmpl
);
381 module_init(crypto_authenc_module_init
);
382 module_exit(crypto_authenc_module_exit
);
384 MODULE_LICENSE("GPL");
385 MODULE_DESCRIPTION("Simple AEAD wrapper for IPsec");