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 <linux/err.h>
15 #include <linux/init.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/slab.h>
19 #include <linux/spinlock.h>
21 #include "scatterwalk.h"
23 struct authenc_instance_ctx
{
24 struct crypto_spawn auth
;
25 struct crypto_spawn enc
;
27 unsigned int authsize
;
28 unsigned int enckeylen
;
31 struct crypto_authenc_ctx
{
33 struct crypto_hash
*auth
;
34 struct crypto_ablkcipher
*enc
;
37 static int crypto_authenc_setkey(struct crypto_aead
*authenc
, const u8
*key
,
40 struct authenc_instance_ctx
*ictx
=
41 crypto_instance_ctx(crypto_aead_alg_instance(authenc
));
42 unsigned int enckeylen
= ictx
->enckeylen
;
43 unsigned int authkeylen
;
44 struct crypto_authenc_ctx
*ctx
= crypto_aead_ctx(authenc
);
45 struct crypto_hash
*auth
= ctx
->auth
;
46 struct crypto_ablkcipher
*enc
= ctx
->enc
;
49 if (keylen
< enckeylen
) {
50 crypto_aead_set_flags(authenc
, CRYPTO_TFM_RES_BAD_KEY_LEN
);
53 authkeylen
= keylen
- enckeylen
;
55 crypto_hash_clear_flags(auth
, CRYPTO_TFM_REQ_MASK
);
56 crypto_hash_set_flags(auth
, crypto_aead_get_flags(authenc
) &
58 err
= crypto_hash_setkey(auth
, key
, authkeylen
);
59 crypto_aead_set_flags(authenc
, crypto_hash_get_flags(auth
) &
65 crypto_ablkcipher_clear_flags(enc
, CRYPTO_TFM_REQ_MASK
);
66 crypto_ablkcipher_set_flags(enc
, crypto_aead_get_flags(authenc
) &
68 err
= crypto_ablkcipher_setkey(enc
, key
+ authkeylen
, enckeylen
);
69 crypto_aead_set_flags(authenc
, crypto_ablkcipher_get_flags(enc
) &
76 static int crypto_authenc_hash(struct aead_request
*req
)
78 struct crypto_aead
*authenc
= crypto_aead_reqtfm(req
);
79 struct authenc_instance_ctx
*ictx
=
80 crypto_instance_ctx(crypto_aead_alg_instance(authenc
));
81 struct crypto_authenc_ctx
*ctx
= crypto_aead_ctx(authenc
);
82 struct crypto_hash
*auth
= ctx
->auth
;
83 struct hash_desc desc
= {
86 u8
*hash
= aead_request_ctx(req
);
87 struct scatterlist
*dst
;
88 unsigned int cryptlen
;
91 hash
= (u8
*)ALIGN((unsigned long)hash
+ crypto_hash_alignmask(auth
),
92 crypto_hash_alignmask(auth
) + 1);
94 spin_lock_bh(&ctx
->auth_lock
);
95 err
= crypto_hash_init(&desc
);
99 err
= crypto_hash_update(&desc
, req
->assoc
, req
->assoclen
);
103 cryptlen
= req
->cryptlen
;
105 err
= crypto_hash_update(&desc
, dst
, cryptlen
);
109 err
= crypto_hash_final(&desc
, hash
);
111 spin_unlock_bh(&ctx
->auth_lock
);
116 scatterwalk_map_and_copy(hash
, dst
, cryptlen
, ictx
->authsize
, 1);
120 static void crypto_authenc_encrypt_done(struct crypto_async_request
*req
,
124 err
= crypto_authenc_hash(req
->data
);
126 aead_request_complete(req
->data
, err
);
129 static int crypto_authenc_encrypt(struct aead_request
*req
)
131 struct crypto_aead
*authenc
= crypto_aead_reqtfm(req
);
132 struct crypto_authenc_ctx
*ctx
= crypto_aead_ctx(authenc
);
133 struct ablkcipher_request
*abreq
= aead_request_ctx(req
);
136 ablkcipher_request_set_tfm(abreq
, ctx
->enc
);
137 ablkcipher_request_set_callback(abreq
, aead_request_flags(req
),
138 crypto_authenc_encrypt_done
, req
);
139 ablkcipher_request_set_crypt(abreq
, req
->src
, req
->dst
, req
->cryptlen
,
142 err
= crypto_ablkcipher_encrypt(abreq
);
146 return crypto_authenc_hash(req
);
149 static int crypto_authenc_verify(struct aead_request
*req
)
151 struct crypto_aead
*authenc
= crypto_aead_reqtfm(req
);
152 struct authenc_instance_ctx
*ictx
=
153 crypto_instance_ctx(crypto_aead_alg_instance(authenc
));
154 struct crypto_authenc_ctx
*ctx
= crypto_aead_ctx(authenc
);
155 struct crypto_hash
*auth
= ctx
->auth
;
156 struct hash_desc desc
= {
158 .flags
= aead_request_flags(req
),
160 u8
*ohash
= aead_request_ctx(req
);
162 struct scatterlist
*src
;
163 unsigned int cryptlen
;
164 unsigned int authsize
;
167 ohash
= (u8
*)ALIGN((unsigned long)ohash
+ crypto_hash_alignmask(auth
),
168 crypto_hash_alignmask(auth
) + 1);
169 ihash
= ohash
+ crypto_hash_digestsize(auth
);
171 spin_lock_bh(&ctx
->auth_lock
);
172 err
= crypto_hash_init(&desc
);
176 err
= crypto_hash_update(&desc
, req
->assoc
, req
->assoclen
);
180 cryptlen
= req
->cryptlen
;
182 err
= crypto_hash_update(&desc
, src
, cryptlen
);
186 err
= crypto_hash_final(&desc
, ohash
);
188 spin_unlock_bh(&ctx
->auth_lock
);
193 authsize
= ictx
->authsize
;
194 scatterwalk_map_and_copy(ihash
, src
, cryptlen
, authsize
, 0);
195 return memcmp(ihash
, ohash
, authsize
) ? -EINVAL
: 0;
198 static void crypto_authenc_decrypt_done(struct crypto_async_request
*req
,
201 aead_request_complete(req
->data
, err
);
204 static int crypto_authenc_decrypt(struct aead_request
*req
)
206 struct crypto_aead
*authenc
= crypto_aead_reqtfm(req
);
207 struct crypto_authenc_ctx
*ctx
= crypto_aead_ctx(authenc
);
208 struct ablkcipher_request
*abreq
= aead_request_ctx(req
);
211 err
= crypto_authenc_verify(req
);
215 ablkcipher_request_set_tfm(abreq
, ctx
->enc
);
216 ablkcipher_request_set_callback(abreq
, aead_request_flags(req
),
217 crypto_authenc_decrypt_done
, req
);
218 ablkcipher_request_set_crypt(abreq
, req
->src
, req
->dst
, req
->cryptlen
,
221 return crypto_ablkcipher_decrypt(abreq
);
224 static int crypto_authenc_init_tfm(struct crypto_tfm
*tfm
)
226 struct crypto_instance
*inst
= (void *)tfm
->__crt_alg
;
227 struct authenc_instance_ctx
*ictx
= crypto_instance_ctx(inst
);
228 struct crypto_authenc_ctx
*ctx
= crypto_tfm_ctx(tfm
);
229 struct crypto_hash
*auth
;
230 struct crypto_ablkcipher
*enc
;
231 unsigned int digestsize
;
234 auth
= crypto_spawn_hash(&ictx
->auth
);
236 return PTR_ERR(auth
);
239 digestsize
= crypto_hash_digestsize(auth
);
240 if (ictx
->authsize
> digestsize
)
243 enc
= crypto_spawn_ablkcipher(&ictx
->enc
);
250 tfm
->crt_aead
.reqsize
= max_t(unsigned int,
251 (crypto_hash_alignmask(auth
) &
252 ~(crypto_tfm_ctx_alignment() - 1)) +
254 sizeof(struct ablkcipher_request
) +
255 crypto_ablkcipher_reqsize(enc
));
257 spin_lock_init(&ctx
->auth_lock
);
262 crypto_free_hash(auth
);
266 static void crypto_authenc_exit_tfm(struct crypto_tfm
*tfm
)
268 struct crypto_authenc_ctx
*ctx
= crypto_tfm_ctx(tfm
);
270 crypto_free_hash(ctx
->auth
);
271 crypto_free_ablkcipher(ctx
->enc
);
274 static struct crypto_instance
*crypto_authenc_alloc(struct rtattr
**tb
)
276 struct crypto_instance
*inst
;
277 struct crypto_alg
*auth
;
278 struct crypto_alg
*enc
;
279 struct authenc_instance_ctx
*ctx
;
280 unsigned int authsize
;
281 unsigned int enckeylen
;
284 err
= crypto_check_attr_type(tb
, CRYPTO_ALG_TYPE_AEAD
);
288 auth
= crypto_attr_alg(tb
[1], CRYPTO_ALG_TYPE_HASH
,
289 CRYPTO_ALG_TYPE_HASH_MASK
);
291 return ERR_PTR(PTR_ERR(auth
));
293 err
= crypto_attr_u32(tb
[2], &authsize
);
298 enc
= crypto_attr_alg(tb
[3], CRYPTO_ALG_TYPE_BLKCIPHER
,
299 CRYPTO_ALG_TYPE_MASK
);
300 inst
= ERR_PTR(PTR_ERR(enc
));
304 err
= crypto_attr_u32(tb
[4], &enckeylen
);
308 inst
= kzalloc(sizeof(*inst
) + sizeof(*ctx
), GFP_KERNEL
);
314 if (snprintf(inst
->alg
.cra_name
, CRYPTO_MAX_ALG_NAME
,
315 "authenc(%s,%u,%s,%u)", auth
->cra_name
, authsize
,
316 enc
->cra_name
, enckeylen
) >= CRYPTO_MAX_ALG_NAME
)
319 if (snprintf(inst
->alg
.cra_driver_name
, CRYPTO_MAX_ALG_NAME
,
320 "authenc(%s,%u,%s,%u)", auth
->cra_driver_name
,
321 authsize
, enc
->cra_driver_name
, enckeylen
) >=
325 ctx
= crypto_instance_ctx(inst
);
326 ctx
->authsize
= authsize
;
327 ctx
->enckeylen
= enckeylen
;
329 err
= crypto_init_spawn(&ctx
->auth
, auth
, inst
, CRYPTO_ALG_TYPE_MASK
);
333 err
= crypto_init_spawn(&ctx
->enc
, enc
, inst
, CRYPTO_ALG_TYPE_MASK
);
337 inst
->alg
.cra_flags
= CRYPTO_ALG_TYPE_AEAD
| CRYPTO_ALG_ASYNC
;
338 inst
->alg
.cra_priority
= enc
->cra_priority
* 10 + auth
->cra_priority
;
339 inst
->alg
.cra_blocksize
= enc
->cra_blocksize
;
340 inst
->alg
.cra_alignmask
= max(auth
->cra_alignmask
, enc
->cra_alignmask
);
341 inst
->alg
.cra_type
= &crypto_aead_type
;
343 inst
->alg
.cra_aead
.ivsize
= enc
->cra_blkcipher
.ivsize
;
344 inst
->alg
.cra_aead
.authsize
= authsize
;
346 inst
->alg
.cra_ctxsize
= sizeof(struct crypto_authenc_ctx
);
348 inst
->alg
.cra_init
= crypto_authenc_init_tfm
;
349 inst
->alg
.cra_exit
= crypto_authenc_exit_tfm
;
351 inst
->alg
.cra_aead
.setkey
= crypto_authenc_setkey
;
352 inst
->alg
.cra_aead
.encrypt
= crypto_authenc_encrypt
;
353 inst
->alg
.cra_aead
.decrypt
= crypto_authenc_decrypt
;
358 crypto_mod_put(auth
);
362 crypto_drop_spawn(&ctx
->auth
);
370 static void crypto_authenc_free(struct crypto_instance
*inst
)
372 struct authenc_instance_ctx
*ctx
= crypto_instance_ctx(inst
);
374 crypto_drop_spawn(&ctx
->enc
);
375 crypto_drop_spawn(&ctx
->auth
);
379 static struct crypto_template crypto_authenc_tmpl
= {
381 .alloc
= crypto_authenc_alloc
,
382 .free
= crypto_authenc_free
,
383 .module
= THIS_MODULE
,
386 static int __init
crypto_authenc_module_init(void)
388 return crypto_register_template(&crypto_authenc_tmpl
);
391 static void __exit
crypto_authenc_module_exit(void)
393 crypto_unregister_template(&crypto_authenc_tmpl
);
396 module_init(crypto_authenc_module_init
);
397 module_exit(crypto_authenc_module_exit
);
399 MODULE_LICENSE("GPL");
400 MODULE_DESCRIPTION("Simple AEAD wrapper for IPsec");