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
= req
->dst
;
88 unsigned int cryptlen
= req
->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 err
= crypto_hash_update(&desc
, dst
, cryptlen
);
107 err
= crypto_hash_final(&desc
, hash
);
109 spin_unlock_bh(&ctx
->auth_lock
);
114 scatterwalk_map_and_copy(hash
, dst
, cryptlen
, ictx
->authsize
, 1);
118 static void crypto_authenc_encrypt_done(struct crypto_async_request
*req
,
122 err
= crypto_authenc_hash(req
->data
);
124 aead_request_complete(req
->data
, err
);
127 static int crypto_authenc_encrypt(struct aead_request
*req
)
129 struct crypto_aead
*authenc
= crypto_aead_reqtfm(req
);
130 struct crypto_authenc_ctx
*ctx
= crypto_aead_ctx(authenc
);
131 struct ablkcipher_request
*abreq
= aead_request_ctx(req
);
134 ablkcipher_request_set_tfm(abreq
, ctx
->enc
);
135 ablkcipher_request_set_callback(abreq
, aead_request_flags(req
),
136 crypto_authenc_encrypt_done
, req
);
137 ablkcipher_request_set_crypt(abreq
, req
->src
, req
->dst
, req
->cryptlen
,
140 err
= crypto_ablkcipher_encrypt(abreq
);
144 return crypto_authenc_hash(req
);
147 static int crypto_authenc_verify(struct aead_request
*req
)
149 struct crypto_aead
*authenc
= crypto_aead_reqtfm(req
);
150 struct authenc_instance_ctx
*ictx
=
151 crypto_instance_ctx(crypto_aead_alg_instance(authenc
));
152 struct crypto_authenc_ctx
*ctx
= crypto_aead_ctx(authenc
);
153 struct crypto_hash
*auth
= ctx
->auth
;
154 struct hash_desc desc
= {
156 .flags
= aead_request_flags(req
),
158 u8
*ohash
= aead_request_ctx(req
);
160 struct scatterlist
*src
= req
->src
;
161 unsigned int cryptlen
= req
->cryptlen
;
162 unsigned int authsize
;
165 ohash
= (u8
*)ALIGN((unsigned long)ohash
+ crypto_hash_alignmask(auth
),
166 crypto_hash_alignmask(auth
) + 1);
167 ihash
= ohash
+ crypto_hash_digestsize(auth
);
169 spin_lock_bh(&ctx
->auth_lock
);
170 err
= crypto_hash_init(&desc
);
174 err
= crypto_hash_update(&desc
, req
->assoc
, req
->assoclen
);
178 err
= crypto_hash_update(&desc
, src
, cryptlen
);
182 err
= crypto_hash_final(&desc
, ohash
);
184 spin_unlock_bh(&ctx
->auth_lock
);
189 authsize
= ictx
->authsize
;
190 scatterwalk_map_and_copy(ihash
, src
, cryptlen
, authsize
, 0);
191 return memcmp(ihash
, ohash
, authsize
) ? -EINVAL
: 0;
194 static void crypto_authenc_decrypt_done(struct crypto_async_request
*req
,
197 aead_request_complete(req
->data
, err
);
200 static int crypto_authenc_decrypt(struct aead_request
*req
)
202 struct crypto_aead
*authenc
= crypto_aead_reqtfm(req
);
203 struct crypto_authenc_ctx
*ctx
= crypto_aead_ctx(authenc
);
204 struct ablkcipher_request
*abreq
= aead_request_ctx(req
);
207 err
= crypto_authenc_verify(req
);
211 ablkcipher_request_set_tfm(abreq
, ctx
->enc
);
212 ablkcipher_request_set_callback(abreq
, aead_request_flags(req
),
213 crypto_authenc_decrypt_done
, req
);
214 ablkcipher_request_set_crypt(abreq
, req
->src
, req
->dst
, req
->cryptlen
,
217 return crypto_ablkcipher_decrypt(abreq
);
220 static int crypto_authenc_init_tfm(struct crypto_tfm
*tfm
)
222 struct crypto_instance
*inst
= (void *)tfm
->__crt_alg
;
223 struct authenc_instance_ctx
*ictx
= crypto_instance_ctx(inst
);
224 struct crypto_authenc_ctx
*ctx
= crypto_tfm_ctx(tfm
);
225 struct crypto_hash
*auth
;
226 struct crypto_ablkcipher
*enc
;
227 unsigned int digestsize
;
230 auth
= crypto_spawn_hash(&ictx
->auth
);
232 return PTR_ERR(auth
);
235 digestsize
= crypto_hash_digestsize(auth
);
236 if (ictx
->authsize
> digestsize
)
239 enc
= crypto_spawn_ablkcipher(&ictx
->enc
);
246 tfm
->crt_aead
.reqsize
= max_t(unsigned int,
247 (crypto_hash_alignmask(auth
) &
248 ~(crypto_tfm_ctx_alignment() - 1)) +
250 sizeof(struct ablkcipher_request
) +
251 crypto_ablkcipher_reqsize(enc
));
253 spin_lock_init(&ctx
->auth_lock
);
258 crypto_free_hash(auth
);
262 static void crypto_authenc_exit_tfm(struct crypto_tfm
*tfm
)
264 struct crypto_authenc_ctx
*ctx
= crypto_tfm_ctx(tfm
);
266 crypto_free_hash(ctx
->auth
);
267 crypto_free_ablkcipher(ctx
->enc
);
270 static struct crypto_instance
*crypto_authenc_alloc(struct rtattr
**tb
)
272 struct crypto_instance
*inst
;
273 struct crypto_alg
*auth
;
274 struct crypto_alg
*enc
;
275 struct authenc_instance_ctx
*ctx
;
276 unsigned int authsize
;
277 unsigned int enckeylen
;
280 err
= crypto_check_attr_type(tb
, CRYPTO_ALG_TYPE_AEAD
);
284 auth
= crypto_attr_alg(tb
[1], CRYPTO_ALG_TYPE_HASH
,
285 CRYPTO_ALG_TYPE_HASH_MASK
);
287 return ERR_PTR(PTR_ERR(auth
));
289 err
= crypto_attr_u32(tb
[2], &authsize
);
294 enc
= crypto_attr_alg(tb
[3], CRYPTO_ALG_TYPE_BLKCIPHER
,
295 CRYPTO_ALG_TYPE_MASK
);
296 inst
= ERR_PTR(PTR_ERR(enc
));
300 err
= crypto_attr_u32(tb
[4], &enckeylen
);
304 inst
= kzalloc(sizeof(*inst
) + sizeof(*ctx
), GFP_KERNEL
);
310 if (snprintf(inst
->alg
.cra_name
, CRYPTO_MAX_ALG_NAME
,
311 "authenc(%s,%u,%s,%u)", auth
->cra_name
, authsize
,
312 enc
->cra_name
, enckeylen
) >= CRYPTO_MAX_ALG_NAME
)
315 if (snprintf(inst
->alg
.cra_driver_name
, CRYPTO_MAX_ALG_NAME
,
316 "authenc(%s,%u,%s,%u)", auth
->cra_driver_name
,
317 authsize
, enc
->cra_driver_name
, enckeylen
) >=
321 ctx
= crypto_instance_ctx(inst
);
322 ctx
->authsize
= authsize
;
323 ctx
->enckeylen
= enckeylen
;
325 err
= crypto_init_spawn(&ctx
->auth
, auth
, inst
, CRYPTO_ALG_TYPE_MASK
);
329 err
= crypto_init_spawn(&ctx
->enc
, enc
, inst
, CRYPTO_ALG_TYPE_MASK
);
333 inst
->alg
.cra_flags
= CRYPTO_ALG_TYPE_AEAD
| CRYPTO_ALG_ASYNC
;
334 inst
->alg
.cra_priority
= enc
->cra_priority
* 10 + auth
->cra_priority
;
335 inst
->alg
.cra_blocksize
= enc
->cra_blocksize
;
336 inst
->alg
.cra_alignmask
= max(auth
->cra_alignmask
, enc
->cra_alignmask
);
337 inst
->alg
.cra_type
= &crypto_aead_type
;
339 inst
->alg
.cra_aead
.ivsize
= enc
->cra_blkcipher
.ivsize
;
340 inst
->alg
.cra_aead
.authsize
= authsize
;
342 inst
->alg
.cra_ctxsize
= sizeof(struct crypto_authenc_ctx
);
344 inst
->alg
.cra_init
= crypto_authenc_init_tfm
;
345 inst
->alg
.cra_exit
= crypto_authenc_exit_tfm
;
347 inst
->alg
.cra_aead
.setkey
= crypto_authenc_setkey
;
348 inst
->alg
.cra_aead
.encrypt
= crypto_authenc_encrypt
;
349 inst
->alg
.cra_aead
.decrypt
= crypto_authenc_decrypt
;
354 crypto_mod_put(auth
);
358 crypto_drop_spawn(&ctx
->auth
);
366 static void crypto_authenc_free(struct crypto_instance
*inst
)
368 struct authenc_instance_ctx
*ctx
= crypto_instance_ctx(inst
);
370 crypto_drop_spawn(&ctx
->enc
);
371 crypto_drop_spawn(&ctx
->auth
);
375 static struct crypto_template crypto_authenc_tmpl
= {
377 .alloc
= crypto_authenc_alloc
,
378 .free
= crypto_authenc_free
,
379 .module
= THIS_MODULE
,
382 static int __init
crypto_authenc_module_init(void)
384 return crypto_register_template(&crypto_authenc_tmpl
);
387 static void __exit
crypto_authenc_module_exit(void)
389 crypto_unregister_template(&crypto_authenc_tmpl
);
392 module_init(crypto_authenc_module_init
);
393 module_exit(crypto_authenc_module_exit
);
395 MODULE_LICENSE("GPL");
396 MODULE_DESCRIPTION("Simple AEAD wrapper for IPsec");