2 * authencesn.c - AEAD wrapper for IPsec with extended sequence numbers,
3 * derived from authenc.c
5 * Copyright (C) 2010 secunet Security Networks AG
6 * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.com>
7 * Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
16 #include <crypto/internal/aead.h>
17 #include <crypto/internal/hash.h>
18 #include <crypto/internal/skcipher.h>
19 #include <crypto/authenc.h>
20 #include <crypto/null.h>
21 #include <crypto/scatterwalk.h>
22 #include <linux/err.h>
23 #include <linux/init.h>
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/rtnetlink.h>
27 #include <linux/slab.h>
28 #include <linux/spinlock.h>
30 struct authenc_esn_instance_ctx
{
31 struct crypto_ahash_spawn auth
;
32 struct crypto_skcipher_spawn enc
;
35 struct crypto_authenc_esn_ctx
{
37 struct crypto_ahash
*auth
;
38 struct crypto_skcipher
*enc
;
39 struct crypto_skcipher
*null
;
42 struct authenc_esn_request_ctx
{
43 struct scatterlist src
[2];
44 struct scatterlist dst
[2];
48 static void authenc_esn_request_complete(struct aead_request
*req
, int err
)
50 if (err
!= -EINPROGRESS
)
51 aead_request_complete(req
, err
);
54 static int crypto_authenc_esn_setauthsize(struct crypto_aead
*authenc_esn
,
55 unsigned int authsize
)
57 if (authsize
> 0 && authsize
< 4)
63 static int crypto_authenc_esn_setkey(struct crypto_aead
*authenc_esn
, const u8
*key
,
66 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
67 struct crypto_ahash
*auth
= ctx
->auth
;
68 struct crypto_skcipher
*enc
= ctx
->enc
;
69 struct crypto_authenc_keys keys
;
72 if (crypto_authenc_extractkeys(&keys
, key
, keylen
) != 0)
75 crypto_ahash_clear_flags(auth
, CRYPTO_TFM_REQ_MASK
);
76 crypto_ahash_set_flags(auth
, crypto_aead_get_flags(authenc_esn
) &
78 err
= crypto_ahash_setkey(auth
, keys
.authkey
, keys
.authkeylen
);
79 crypto_aead_set_flags(authenc_esn
, crypto_ahash_get_flags(auth
) &
85 crypto_skcipher_clear_flags(enc
, CRYPTO_TFM_REQ_MASK
);
86 crypto_skcipher_set_flags(enc
, crypto_aead_get_flags(authenc_esn
) &
88 err
= crypto_skcipher_setkey(enc
, keys
.enckey
, keys
.enckeylen
);
89 crypto_aead_set_flags(authenc_esn
, crypto_skcipher_get_flags(enc
) &
93 memzero_explicit(&keys
, sizeof(keys
));
97 crypto_aead_set_flags(authenc_esn
, CRYPTO_TFM_RES_BAD_KEY_LEN
);
101 static int crypto_authenc_esn_genicv_tail(struct aead_request
*req
,
104 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
105 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
106 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
107 struct crypto_ahash
*auth
= ctx
->auth
;
108 u8
*hash
= PTR_ALIGN((u8
*)areq_ctx
->tail
,
109 crypto_ahash_alignmask(auth
) + 1);
110 unsigned int authsize
= crypto_aead_authsize(authenc_esn
);
111 unsigned int assoclen
= req
->assoclen
;
112 unsigned int cryptlen
= req
->cryptlen
;
113 struct scatterlist
*dst
= req
->dst
;
116 /* Move high-order bits of sequence number back. */
117 scatterwalk_map_and_copy(tmp
, dst
, 4, 4, 0);
118 scatterwalk_map_and_copy(tmp
+ 1, dst
, assoclen
+ cryptlen
, 4, 0);
119 scatterwalk_map_and_copy(tmp
, dst
, 0, 8, 1);
121 scatterwalk_map_and_copy(hash
, dst
, assoclen
+ cryptlen
, authsize
, 1);
125 static void authenc_esn_geniv_ahash_done(struct crypto_async_request
*areq
,
128 struct aead_request
*req
= areq
->data
;
130 err
= err
?: crypto_authenc_esn_genicv_tail(req
, 0);
131 aead_request_complete(req
, err
);
134 static int crypto_authenc_esn_genicv(struct aead_request
*req
,
137 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
138 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
139 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
140 struct crypto_ahash
*auth
= ctx
->auth
;
141 u8
*hash
= PTR_ALIGN((u8
*)areq_ctx
->tail
,
142 crypto_ahash_alignmask(auth
) + 1);
143 struct ahash_request
*ahreq
= (void *)(areq_ctx
->tail
+ ctx
->reqoff
);
144 unsigned int authsize
= crypto_aead_authsize(authenc_esn
);
145 unsigned int assoclen
= req
->assoclen
;
146 unsigned int cryptlen
= req
->cryptlen
;
147 struct scatterlist
*dst
= req
->dst
;
153 /* Move high-order bits of sequence number to the end. */
154 scatterwalk_map_and_copy(tmp
, dst
, 0, 8, 0);
155 scatterwalk_map_and_copy(tmp
, dst
, 4, 4, 1);
156 scatterwalk_map_and_copy(tmp
+ 1, dst
, assoclen
+ cryptlen
, 4, 1);
158 sg_init_table(areq_ctx
->dst
, 2);
159 dst
= scatterwalk_ffwd(areq_ctx
->dst
, dst
, 4);
161 ahash_request_set_tfm(ahreq
, auth
);
162 ahash_request_set_crypt(ahreq
, dst
, hash
, assoclen
+ cryptlen
);
163 ahash_request_set_callback(ahreq
, flags
,
164 authenc_esn_geniv_ahash_done
, req
);
166 return crypto_ahash_digest(ahreq
) ?:
167 crypto_authenc_esn_genicv_tail(req
, aead_request_flags(req
));
171 static void crypto_authenc_esn_encrypt_done(struct crypto_async_request
*req
,
174 struct aead_request
*areq
= req
->data
;
177 err
= crypto_authenc_esn_genicv(areq
, 0);
179 authenc_esn_request_complete(areq
, err
);
182 static int crypto_authenc_esn_copy(struct aead_request
*req
, unsigned int len
)
184 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
185 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
186 SKCIPHER_REQUEST_ON_STACK(skreq
, ctx
->null
);
188 skcipher_request_set_tfm(skreq
, ctx
->null
);
189 skcipher_request_set_callback(skreq
, aead_request_flags(req
),
191 skcipher_request_set_crypt(skreq
, req
->src
, req
->dst
, len
, NULL
);
193 return crypto_skcipher_encrypt(skreq
);
196 static int crypto_authenc_esn_encrypt(struct aead_request
*req
)
198 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
199 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
200 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
201 struct skcipher_request
*skreq
= (void *)(areq_ctx
->tail
+
203 struct crypto_skcipher
*enc
= ctx
->enc
;
204 unsigned int assoclen
= req
->assoclen
;
205 unsigned int cryptlen
= req
->cryptlen
;
206 struct scatterlist
*src
, *dst
;
209 sg_init_table(areq_ctx
->src
, 2);
210 src
= scatterwalk_ffwd(areq_ctx
->src
, req
->src
, assoclen
);
213 if (req
->src
!= req
->dst
) {
214 err
= crypto_authenc_esn_copy(req
, assoclen
);
218 sg_init_table(areq_ctx
->dst
, 2);
219 dst
= scatterwalk_ffwd(areq_ctx
->dst
, req
->dst
, assoclen
);
222 skcipher_request_set_tfm(skreq
, enc
);
223 skcipher_request_set_callback(skreq
, aead_request_flags(req
),
224 crypto_authenc_esn_encrypt_done
, req
);
225 skcipher_request_set_crypt(skreq
, src
, dst
, cryptlen
, req
->iv
);
227 err
= crypto_skcipher_encrypt(skreq
);
231 return crypto_authenc_esn_genicv(req
, aead_request_flags(req
));
234 static int crypto_authenc_esn_decrypt_tail(struct aead_request
*req
,
237 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
238 unsigned int authsize
= crypto_aead_authsize(authenc_esn
);
239 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
240 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
241 struct skcipher_request
*skreq
= (void *)(areq_ctx
->tail
+
243 struct crypto_ahash
*auth
= ctx
->auth
;
244 u8
*ohash
= PTR_ALIGN((u8
*)areq_ctx
->tail
,
245 crypto_ahash_alignmask(auth
) + 1);
246 unsigned int cryptlen
= req
->cryptlen
- authsize
;
247 unsigned int assoclen
= req
->assoclen
;
248 struct scatterlist
*dst
= req
->dst
;
249 u8
*ihash
= ohash
+ crypto_ahash_digestsize(auth
);
255 /* Move high-order bits of sequence number back. */
256 scatterwalk_map_and_copy(tmp
, dst
, 4, 4, 0);
257 scatterwalk_map_and_copy(tmp
+ 1, dst
, assoclen
+ cryptlen
, 4, 0);
258 scatterwalk_map_and_copy(tmp
, dst
, 0, 8, 1);
260 if (crypto_memneq(ihash
, ohash
, authsize
))
265 sg_init_table(areq_ctx
->dst
, 2);
266 dst
= scatterwalk_ffwd(areq_ctx
->dst
, dst
, assoclen
);
268 skcipher_request_set_tfm(skreq
, ctx
->enc
);
269 skcipher_request_set_callback(skreq
, flags
,
270 req
->base
.complete
, req
->base
.data
);
271 skcipher_request_set_crypt(skreq
, dst
, dst
, cryptlen
, req
->iv
);
273 return crypto_skcipher_decrypt(skreq
);
276 static void authenc_esn_verify_ahash_done(struct crypto_async_request
*areq
,
279 struct aead_request
*req
= areq
->data
;
281 err
= err
?: crypto_authenc_esn_decrypt_tail(req
, 0);
282 aead_request_complete(req
, err
);
285 static int crypto_authenc_esn_decrypt(struct aead_request
*req
)
287 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
288 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
289 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
290 struct ahash_request
*ahreq
= (void *)(areq_ctx
->tail
+ ctx
->reqoff
);
291 unsigned int authsize
= crypto_aead_authsize(authenc_esn
);
292 struct crypto_ahash
*auth
= ctx
->auth
;
293 u8
*ohash
= PTR_ALIGN((u8
*)areq_ctx
->tail
,
294 crypto_ahash_alignmask(auth
) + 1);
295 unsigned int assoclen
= req
->assoclen
;
296 unsigned int cryptlen
= req
->cryptlen
;
297 u8
*ihash
= ohash
+ crypto_ahash_digestsize(auth
);
298 struct scatterlist
*dst
= req
->dst
;
302 cryptlen
-= authsize
;
304 if (req
->src
!= dst
) {
305 err
= crypto_authenc_esn_copy(req
, assoclen
+ cryptlen
);
310 scatterwalk_map_and_copy(ihash
, req
->src
, assoclen
+ cryptlen
,
316 /* Move high-order bits of sequence number to the end. */
317 scatterwalk_map_and_copy(tmp
, dst
, 0, 8, 0);
318 scatterwalk_map_and_copy(tmp
, dst
, 4, 4, 1);
319 scatterwalk_map_and_copy(tmp
+ 1, dst
, assoclen
+ cryptlen
, 4, 1);
321 sg_init_table(areq_ctx
->dst
, 2);
322 dst
= scatterwalk_ffwd(areq_ctx
->dst
, dst
, 4);
324 ahash_request_set_tfm(ahreq
, auth
);
325 ahash_request_set_crypt(ahreq
, dst
, ohash
, assoclen
+ cryptlen
);
326 ahash_request_set_callback(ahreq
, aead_request_flags(req
),
327 authenc_esn_verify_ahash_done
, req
);
329 err
= crypto_ahash_digest(ahreq
);
334 return crypto_authenc_esn_decrypt_tail(req
, aead_request_flags(req
));
337 static int crypto_authenc_esn_init_tfm(struct crypto_aead
*tfm
)
339 struct aead_instance
*inst
= aead_alg_instance(tfm
);
340 struct authenc_esn_instance_ctx
*ictx
= aead_instance_ctx(inst
);
341 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(tfm
);
342 struct crypto_ahash
*auth
;
343 struct crypto_skcipher
*enc
;
344 struct crypto_skcipher
*null
;
347 auth
= crypto_spawn_ahash(&ictx
->auth
);
349 return PTR_ERR(auth
);
351 enc
= crypto_spawn_skcipher(&ictx
->enc
);
356 null
= crypto_get_default_null_skcipher();
359 goto err_free_skcipher
;
365 ctx
->reqoff
= ALIGN(2 * crypto_ahash_digestsize(auth
),
366 crypto_ahash_alignmask(auth
) + 1);
368 crypto_aead_set_reqsize(
370 sizeof(struct authenc_esn_request_ctx
) +
373 crypto_ahash_reqsize(auth
) +
374 sizeof(struct ahash_request
),
375 sizeof(struct skcipher_request
) +
376 crypto_skcipher_reqsize(enc
)));
381 crypto_free_skcipher(enc
);
383 crypto_free_ahash(auth
);
387 static void crypto_authenc_esn_exit_tfm(struct crypto_aead
*tfm
)
389 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(tfm
);
391 crypto_free_ahash(ctx
->auth
);
392 crypto_free_skcipher(ctx
->enc
);
393 crypto_put_default_null_skcipher();
396 static void crypto_authenc_esn_free(struct aead_instance
*inst
)
398 struct authenc_esn_instance_ctx
*ctx
= aead_instance_ctx(inst
);
400 crypto_drop_skcipher(&ctx
->enc
);
401 crypto_drop_ahash(&ctx
->auth
);
405 static int crypto_authenc_esn_create(struct crypto_template
*tmpl
,
408 struct crypto_attr_type
*algt
;
409 struct aead_instance
*inst
;
410 struct hash_alg_common
*auth
;
411 struct crypto_alg
*auth_base
;
412 struct skcipher_alg
*enc
;
413 struct authenc_esn_instance_ctx
*ctx
;
414 const char *enc_name
;
417 algt
= crypto_get_attr_type(tb
);
419 return PTR_ERR(algt
);
421 if ((algt
->type
^ CRYPTO_ALG_TYPE_AEAD
) & algt
->mask
)
424 auth
= ahash_attr_alg(tb
[1], CRYPTO_ALG_TYPE_HASH
,
425 CRYPTO_ALG_TYPE_AHASH_MASK
|
426 crypto_requires_sync(algt
->type
, algt
->mask
));
428 return PTR_ERR(auth
);
430 auth_base
= &auth
->base
;
432 enc_name
= crypto_attr_alg_name(tb
[2]);
433 err
= PTR_ERR(enc_name
);
434 if (IS_ERR(enc_name
))
437 inst
= kzalloc(sizeof(*inst
) + sizeof(*ctx
), GFP_KERNEL
);
442 ctx
= aead_instance_ctx(inst
);
444 err
= crypto_init_ahash_spawn(&ctx
->auth
, auth
,
445 aead_crypto_instance(inst
));
449 crypto_set_skcipher_spawn(&ctx
->enc
, aead_crypto_instance(inst
));
450 err
= crypto_grab_skcipher(&ctx
->enc
, enc_name
, 0,
451 crypto_requires_sync(algt
->type
,
456 enc
= crypto_spawn_skcipher_alg(&ctx
->enc
);
459 if (snprintf(inst
->alg
.base
.cra_name
, CRYPTO_MAX_ALG_NAME
,
460 "authencesn(%s,%s)", auth_base
->cra_name
,
461 enc
->base
.cra_name
) >= CRYPTO_MAX_ALG_NAME
)
464 if (snprintf(inst
->alg
.base
.cra_driver_name
, CRYPTO_MAX_ALG_NAME
,
465 "authencesn(%s,%s)", auth_base
->cra_driver_name
,
466 enc
->base
.cra_driver_name
) >= CRYPTO_MAX_ALG_NAME
)
469 inst
->alg
.base
.cra_flags
= (auth_base
->cra_flags
|
470 enc
->base
.cra_flags
) & CRYPTO_ALG_ASYNC
;
471 inst
->alg
.base
.cra_priority
= enc
->base
.cra_priority
* 10 +
472 auth_base
->cra_priority
;
473 inst
->alg
.base
.cra_blocksize
= enc
->base
.cra_blocksize
;
474 inst
->alg
.base
.cra_alignmask
= auth_base
->cra_alignmask
|
475 enc
->base
.cra_alignmask
;
476 inst
->alg
.base
.cra_ctxsize
= sizeof(struct crypto_authenc_esn_ctx
);
478 inst
->alg
.ivsize
= crypto_skcipher_alg_ivsize(enc
);
479 inst
->alg
.chunksize
= crypto_skcipher_alg_chunksize(enc
);
480 inst
->alg
.maxauthsize
= auth
->digestsize
;
482 inst
->alg
.init
= crypto_authenc_esn_init_tfm
;
483 inst
->alg
.exit
= crypto_authenc_esn_exit_tfm
;
485 inst
->alg
.setkey
= crypto_authenc_esn_setkey
;
486 inst
->alg
.setauthsize
= crypto_authenc_esn_setauthsize
;
487 inst
->alg
.encrypt
= crypto_authenc_esn_encrypt
;
488 inst
->alg
.decrypt
= crypto_authenc_esn_decrypt
;
490 inst
->free
= crypto_authenc_esn_free
,
492 err
= aead_register_instance(tmpl
, inst
);
497 crypto_mod_put(auth_base
);
501 crypto_drop_skcipher(&ctx
->enc
);
503 crypto_drop_ahash(&ctx
->auth
);
510 static struct crypto_template crypto_authenc_esn_tmpl
= {
511 .name
= "authencesn",
512 .create
= crypto_authenc_esn_create
,
513 .module
= THIS_MODULE
,
516 static int __init
crypto_authenc_esn_module_init(void)
518 return crypto_register_template(&crypto_authenc_esn_tmpl
);
521 static void __exit
crypto_authenc_esn_module_exit(void)
523 crypto_unregister_template(&crypto_authenc_esn_tmpl
);
526 module_init(crypto_authenc_esn_module_init
);
527 module_exit(crypto_authenc_esn_module_exit
);
529 MODULE_LICENSE("GPL");
530 MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
531 MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers");
532 MODULE_ALIAS_CRYPTO("authencesn");