1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * authencesn.c - AEAD wrapper for IPsec with extended sequence numbers,
4 * derived from authenc.c
6 * Copyright (C) 2010 secunet Security Networks AG
7 * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.com>
8 * Copyright (c) 2015 Herbert Xu <herbert@gondor.apana.org.au>
11 #include <crypto/internal/aead.h>
12 #include <crypto/internal/hash.h>
13 #include <crypto/internal/skcipher.h>
14 #include <crypto/authenc.h>
15 #include <crypto/null.h>
16 #include <crypto/scatterwalk.h>
17 #include <linux/err.h>
18 #include <linux/init.h>
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/rtnetlink.h>
22 #include <linux/slab.h>
23 #include <linux/spinlock.h>
25 struct authenc_esn_instance_ctx
{
26 struct crypto_ahash_spawn auth
;
27 struct crypto_skcipher_spawn enc
;
30 struct crypto_authenc_esn_ctx
{
32 struct crypto_ahash
*auth
;
33 struct crypto_skcipher
*enc
;
34 struct crypto_sync_skcipher
*null
;
37 struct authenc_esn_request_ctx
{
38 struct scatterlist src
[2];
39 struct scatterlist dst
[2];
43 static void authenc_esn_request_complete(struct aead_request
*req
, int err
)
45 if (err
!= -EINPROGRESS
)
46 aead_request_complete(req
, err
);
49 static int crypto_authenc_esn_setauthsize(struct crypto_aead
*authenc_esn
,
50 unsigned int authsize
)
52 if (authsize
> 0 && authsize
< 4)
58 static int crypto_authenc_esn_setkey(struct crypto_aead
*authenc_esn
, const u8
*key
,
61 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
62 struct crypto_ahash
*auth
= ctx
->auth
;
63 struct crypto_skcipher
*enc
= ctx
->enc
;
64 struct crypto_authenc_keys keys
;
67 if (crypto_authenc_extractkeys(&keys
, key
, keylen
) != 0)
70 crypto_ahash_clear_flags(auth
, CRYPTO_TFM_REQ_MASK
);
71 crypto_ahash_set_flags(auth
, crypto_aead_get_flags(authenc_esn
) &
73 err
= crypto_ahash_setkey(auth
, keys
.authkey
, keys
.authkeylen
);
77 crypto_skcipher_clear_flags(enc
, CRYPTO_TFM_REQ_MASK
);
78 crypto_skcipher_set_flags(enc
, crypto_aead_get_flags(authenc_esn
) &
80 err
= crypto_skcipher_setkey(enc
, keys
.enckey
, keys
.enckeylen
);
82 memzero_explicit(&keys
, sizeof(keys
));
86 static int crypto_authenc_esn_genicv_tail(struct aead_request
*req
,
89 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
90 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
91 u8
*hash
= areq_ctx
->tail
;
92 unsigned int authsize
= crypto_aead_authsize(authenc_esn
);
93 unsigned int assoclen
= req
->assoclen
;
94 unsigned int cryptlen
= req
->cryptlen
;
95 struct scatterlist
*dst
= req
->dst
;
98 /* Move high-order bits of sequence number back. */
99 scatterwalk_map_and_copy(tmp
, dst
, 4, 4, 0);
100 scatterwalk_map_and_copy(tmp
+ 1, dst
, assoclen
+ cryptlen
, 4, 0);
101 scatterwalk_map_and_copy(tmp
, dst
, 0, 8, 1);
103 scatterwalk_map_and_copy(hash
, dst
, assoclen
+ cryptlen
, authsize
, 1);
107 static void authenc_esn_geniv_ahash_done(void *data
, int err
)
109 struct aead_request
*req
= data
;
111 err
= err
?: crypto_authenc_esn_genicv_tail(req
, 0);
112 aead_request_complete(req
, err
);
115 static int crypto_authenc_esn_genicv(struct aead_request
*req
,
118 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
119 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
120 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
121 struct crypto_ahash
*auth
= ctx
->auth
;
122 u8
*hash
= areq_ctx
->tail
;
123 struct ahash_request
*ahreq
= (void *)(areq_ctx
->tail
+ ctx
->reqoff
);
124 unsigned int authsize
= crypto_aead_authsize(authenc_esn
);
125 unsigned int assoclen
= req
->assoclen
;
126 unsigned int cryptlen
= req
->cryptlen
;
127 struct scatterlist
*dst
= req
->dst
;
133 /* Move high-order bits of sequence number to the end. */
134 scatterwalk_map_and_copy(tmp
, dst
, 0, 8, 0);
135 scatterwalk_map_and_copy(tmp
, dst
, 4, 4, 1);
136 scatterwalk_map_and_copy(tmp
+ 1, dst
, assoclen
+ cryptlen
, 4, 1);
138 sg_init_table(areq_ctx
->dst
, 2);
139 dst
= scatterwalk_ffwd(areq_ctx
->dst
, dst
, 4);
141 ahash_request_set_tfm(ahreq
, auth
);
142 ahash_request_set_crypt(ahreq
, dst
, hash
, assoclen
+ cryptlen
);
143 ahash_request_set_callback(ahreq
, flags
,
144 authenc_esn_geniv_ahash_done
, req
);
146 return crypto_ahash_digest(ahreq
) ?:
147 crypto_authenc_esn_genicv_tail(req
, aead_request_flags(req
));
151 static void crypto_authenc_esn_encrypt_done(void *data
, int err
)
153 struct aead_request
*areq
= data
;
156 err
= crypto_authenc_esn_genicv(areq
, 0);
158 authenc_esn_request_complete(areq
, err
);
161 static int crypto_authenc_esn_copy(struct aead_request
*req
, unsigned int len
)
163 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
164 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
165 SYNC_SKCIPHER_REQUEST_ON_STACK(skreq
, ctx
->null
);
167 skcipher_request_set_sync_tfm(skreq
, ctx
->null
);
168 skcipher_request_set_callback(skreq
, aead_request_flags(req
),
170 skcipher_request_set_crypt(skreq
, req
->src
, req
->dst
, len
, NULL
);
172 return crypto_skcipher_encrypt(skreq
);
175 static int crypto_authenc_esn_encrypt(struct aead_request
*req
)
177 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
178 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
179 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
180 struct skcipher_request
*skreq
= (void *)(areq_ctx
->tail
+
182 struct crypto_skcipher
*enc
= ctx
->enc
;
183 unsigned int assoclen
= req
->assoclen
;
184 unsigned int cryptlen
= req
->cryptlen
;
185 struct scatterlist
*src
, *dst
;
188 sg_init_table(areq_ctx
->src
, 2);
189 src
= scatterwalk_ffwd(areq_ctx
->src
, req
->src
, assoclen
);
192 if (req
->src
!= req
->dst
) {
193 err
= crypto_authenc_esn_copy(req
, assoclen
);
197 sg_init_table(areq_ctx
->dst
, 2);
198 dst
= scatterwalk_ffwd(areq_ctx
->dst
, req
->dst
, assoclen
);
201 skcipher_request_set_tfm(skreq
, enc
);
202 skcipher_request_set_callback(skreq
, aead_request_flags(req
),
203 crypto_authenc_esn_encrypt_done
, req
);
204 skcipher_request_set_crypt(skreq
, src
, dst
, cryptlen
, req
->iv
);
206 err
= crypto_skcipher_encrypt(skreq
);
210 return crypto_authenc_esn_genicv(req
, aead_request_flags(req
));
213 static int crypto_authenc_esn_decrypt_tail(struct aead_request
*req
,
216 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
217 unsigned int authsize
= crypto_aead_authsize(authenc_esn
);
218 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
219 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
220 struct skcipher_request
*skreq
= (void *)(areq_ctx
->tail
+
222 struct crypto_ahash
*auth
= ctx
->auth
;
223 u8
*ohash
= areq_ctx
->tail
;
224 unsigned int cryptlen
= req
->cryptlen
- authsize
;
225 unsigned int assoclen
= req
->assoclen
;
226 struct scatterlist
*dst
= req
->dst
;
227 u8
*ihash
= ohash
+ crypto_ahash_digestsize(auth
);
233 /* Move high-order bits of sequence number back. */
234 scatterwalk_map_and_copy(tmp
, dst
, 4, 4, 0);
235 scatterwalk_map_and_copy(tmp
+ 1, dst
, assoclen
+ cryptlen
, 4, 0);
236 scatterwalk_map_and_copy(tmp
, dst
, 0, 8, 1);
238 if (crypto_memneq(ihash
, ohash
, authsize
))
243 sg_init_table(areq_ctx
->dst
, 2);
244 dst
= scatterwalk_ffwd(areq_ctx
->dst
, dst
, assoclen
);
246 skcipher_request_set_tfm(skreq
, ctx
->enc
);
247 skcipher_request_set_callback(skreq
, flags
,
248 req
->base
.complete
, req
->base
.data
);
249 skcipher_request_set_crypt(skreq
, dst
, dst
, cryptlen
, req
->iv
);
251 return crypto_skcipher_decrypt(skreq
);
254 static void authenc_esn_verify_ahash_done(void *data
, int err
)
256 struct aead_request
*req
= data
;
258 err
= err
?: crypto_authenc_esn_decrypt_tail(req
, 0);
259 authenc_esn_request_complete(req
, err
);
262 static int crypto_authenc_esn_decrypt(struct aead_request
*req
)
264 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
265 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
266 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
267 struct ahash_request
*ahreq
= (void *)(areq_ctx
->tail
+ ctx
->reqoff
);
268 unsigned int authsize
= crypto_aead_authsize(authenc_esn
);
269 struct crypto_ahash
*auth
= ctx
->auth
;
270 u8
*ohash
= areq_ctx
->tail
;
271 unsigned int assoclen
= req
->assoclen
;
272 unsigned int cryptlen
= req
->cryptlen
;
273 u8
*ihash
= ohash
+ crypto_ahash_digestsize(auth
);
274 struct scatterlist
*dst
= req
->dst
;
278 cryptlen
-= authsize
;
280 if (req
->src
!= dst
) {
281 err
= crypto_authenc_esn_copy(req
, assoclen
+ cryptlen
);
286 scatterwalk_map_and_copy(ihash
, req
->src
, assoclen
+ cryptlen
,
292 /* Move high-order bits of sequence number to the end. */
293 scatterwalk_map_and_copy(tmp
, dst
, 0, 8, 0);
294 scatterwalk_map_and_copy(tmp
, dst
, 4, 4, 1);
295 scatterwalk_map_and_copy(tmp
+ 1, dst
, assoclen
+ cryptlen
, 4, 1);
297 sg_init_table(areq_ctx
->dst
, 2);
298 dst
= scatterwalk_ffwd(areq_ctx
->dst
, dst
, 4);
300 ahash_request_set_tfm(ahreq
, auth
);
301 ahash_request_set_crypt(ahreq
, dst
, ohash
, assoclen
+ cryptlen
);
302 ahash_request_set_callback(ahreq
, aead_request_flags(req
),
303 authenc_esn_verify_ahash_done
, req
);
305 err
= crypto_ahash_digest(ahreq
);
310 return crypto_authenc_esn_decrypt_tail(req
, aead_request_flags(req
));
313 static int crypto_authenc_esn_init_tfm(struct crypto_aead
*tfm
)
315 struct aead_instance
*inst
= aead_alg_instance(tfm
);
316 struct authenc_esn_instance_ctx
*ictx
= aead_instance_ctx(inst
);
317 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(tfm
);
318 struct crypto_ahash
*auth
;
319 struct crypto_skcipher
*enc
;
320 struct crypto_sync_skcipher
*null
;
323 auth
= crypto_spawn_ahash(&ictx
->auth
);
325 return PTR_ERR(auth
);
327 enc
= crypto_spawn_skcipher(&ictx
->enc
);
332 null
= crypto_get_default_null_skcipher();
335 goto err_free_skcipher
;
341 ctx
->reqoff
= 2 * crypto_ahash_digestsize(auth
);
343 crypto_aead_set_reqsize(
345 sizeof(struct authenc_esn_request_ctx
) +
348 crypto_ahash_reqsize(auth
) +
349 sizeof(struct ahash_request
),
350 sizeof(struct skcipher_request
) +
351 crypto_skcipher_reqsize(enc
)));
356 crypto_free_skcipher(enc
);
358 crypto_free_ahash(auth
);
362 static void crypto_authenc_esn_exit_tfm(struct crypto_aead
*tfm
)
364 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(tfm
);
366 crypto_free_ahash(ctx
->auth
);
367 crypto_free_skcipher(ctx
->enc
);
368 crypto_put_default_null_skcipher();
371 static void crypto_authenc_esn_free(struct aead_instance
*inst
)
373 struct authenc_esn_instance_ctx
*ctx
= aead_instance_ctx(inst
);
375 crypto_drop_skcipher(&ctx
->enc
);
376 crypto_drop_ahash(&ctx
->auth
);
380 static int crypto_authenc_esn_create(struct crypto_template
*tmpl
,
384 struct aead_instance
*inst
;
385 struct authenc_esn_instance_ctx
*ctx
;
386 struct skcipher_alg_common
*enc
;
387 struct hash_alg_common
*auth
;
388 struct crypto_alg
*auth_base
;
391 err
= crypto_check_attr_type(tb
, CRYPTO_ALG_TYPE_AEAD
, &mask
);
395 inst
= kzalloc(sizeof(*inst
) + sizeof(*ctx
), GFP_KERNEL
);
398 ctx
= aead_instance_ctx(inst
);
400 err
= crypto_grab_ahash(&ctx
->auth
, aead_crypto_instance(inst
),
401 crypto_attr_alg_name(tb
[1]), 0, mask
);
404 auth
= crypto_spawn_ahash_alg(&ctx
->auth
);
405 auth_base
= &auth
->base
;
407 err
= crypto_grab_skcipher(&ctx
->enc
, aead_crypto_instance(inst
),
408 crypto_attr_alg_name(tb
[2]), 0, mask
);
411 enc
= crypto_spawn_skcipher_alg_common(&ctx
->enc
);
414 if (snprintf(inst
->alg
.base
.cra_name
, CRYPTO_MAX_ALG_NAME
,
415 "authencesn(%s,%s)", auth_base
->cra_name
,
416 enc
->base
.cra_name
) >= CRYPTO_MAX_ALG_NAME
)
419 if (snprintf(inst
->alg
.base
.cra_driver_name
, CRYPTO_MAX_ALG_NAME
,
420 "authencesn(%s,%s)", auth_base
->cra_driver_name
,
421 enc
->base
.cra_driver_name
) >= CRYPTO_MAX_ALG_NAME
)
424 inst
->alg
.base
.cra_priority
= enc
->base
.cra_priority
* 10 +
425 auth_base
->cra_priority
;
426 inst
->alg
.base
.cra_blocksize
= enc
->base
.cra_blocksize
;
427 inst
->alg
.base
.cra_alignmask
= enc
->base
.cra_alignmask
;
428 inst
->alg
.base
.cra_ctxsize
= sizeof(struct crypto_authenc_esn_ctx
);
430 inst
->alg
.ivsize
= enc
->ivsize
;
431 inst
->alg
.chunksize
= enc
->chunksize
;
432 inst
->alg
.maxauthsize
= auth
->digestsize
;
434 inst
->alg
.init
= crypto_authenc_esn_init_tfm
;
435 inst
->alg
.exit
= crypto_authenc_esn_exit_tfm
;
437 inst
->alg
.setkey
= crypto_authenc_esn_setkey
;
438 inst
->alg
.setauthsize
= crypto_authenc_esn_setauthsize
;
439 inst
->alg
.encrypt
= crypto_authenc_esn_encrypt
;
440 inst
->alg
.decrypt
= crypto_authenc_esn_decrypt
;
442 inst
->free
= crypto_authenc_esn_free
;
444 err
= aead_register_instance(tmpl
, inst
);
447 crypto_authenc_esn_free(inst
);
452 static struct crypto_template crypto_authenc_esn_tmpl
= {
453 .name
= "authencesn",
454 .create
= crypto_authenc_esn_create
,
455 .module
= THIS_MODULE
,
458 static int __init
crypto_authenc_esn_module_init(void)
460 return crypto_register_template(&crypto_authenc_esn_tmpl
);
463 static void __exit
crypto_authenc_esn_module_exit(void)
465 crypto_unregister_template(&crypto_authenc_esn_tmpl
);
468 subsys_initcall(crypto_authenc_esn_module_init
);
469 module_exit(crypto_authenc_esn_module_exit
);
471 MODULE_LICENSE("GPL");
472 MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
473 MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers");
474 MODULE_ALIAS_CRYPTO("authencesn");