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>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2 of the License, or (at your option)
15 #include <crypto/aead.h>
16 #include <crypto/internal/hash.h>
17 #include <crypto/internal/skcipher.h>
18 #include <crypto/authenc.h>
19 #include <crypto/scatterwalk.h>
20 #include <linux/err.h>
21 #include <linux/init.h>
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/rtnetlink.h>
25 #include <linux/slab.h>
26 #include <linux/spinlock.h>
28 struct authenc_esn_instance_ctx
{
29 struct crypto_ahash_spawn auth
;
30 struct crypto_skcipher_spawn enc
;
33 struct crypto_authenc_esn_ctx
{
35 struct crypto_ahash
*auth
;
36 struct crypto_ablkcipher
*enc
;
39 struct authenc_esn_request_ctx
{
40 unsigned int cryptlen
;
43 struct scatterlist
*sg
;
44 struct scatterlist hsg
[2];
45 struct scatterlist tsg
[1];
46 struct scatterlist cipher
[2];
47 crypto_completion_t complete
;
48 crypto_completion_t update_complete
;
49 crypto_completion_t update_complete2
;
53 static void authenc_esn_request_complete(struct aead_request
*req
, int err
)
55 if (err
!= -EINPROGRESS
)
56 aead_request_complete(req
, err
);
59 static int crypto_authenc_esn_setkey(struct crypto_aead
*authenc_esn
, const u8
*key
,
62 unsigned int authkeylen
;
63 unsigned int enckeylen
;
64 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
65 struct crypto_ahash
*auth
= ctx
->auth
;
66 struct crypto_ablkcipher
*enc
= ctx
->enc
;
67 struct rtattr
*rta
= (void *)key
;
68 struct crypto_authenc_key_param
*param
;
71 if (!RTA_OK(rta
, keylen
))
73 if (rta
->rta_type
!= CRYPTO_AUTHENC_KEYA_PARAM
)
75 if (RTA_PAYLOAD(rta
) < sizeof(*param
))
78 param
= RTA_DATA(rta
);
79 enckeylen
= be32_to_cpu(param
->enckeylen
);
81 key
+= RTA_ALIGN(rta
->rta_len
);
82 keylen
-= RTA_ALIGN(rta
->rta_len
);
84 if (keylen
< enckeylen
)
87 authkeylen
= keylen
- enckeylen
;
89 crypto_ahash_clear_flags(auth
, CRYPTO_TFM_REQ_MASK
);
90 crypto_ahash_set_flags(auth
, crypto_aead_get_flags(authenc_esn
) &
92 err
= crypto_ahash_setkey(auth
, key
, authkeylen
);
93 crypto_aead_set_flags(authenc_esn
, crypto_ahash_get_flags(auth
) &
99 crypto_ablkcipher_clear_flags(enc
, CRYPTO_TFM_REQ_MASK
);
100 crypto_ablkcipher_set_flags(enc
, crypto_aead_get_flags(authenc_esn
) &
101 CRYPTO_TFM_REQ_MASK
);
102 err
= crypto_ablkcipher_setkey(enc
, key
+ authkeylen
, enckeylen
);
103 crypto_aead_set_flags(authenc_esn
, crypto_ablkcipher_get_flags(enc
) &
104 CRYPTO_TFM_RES_MASK
);
110 crypto_aead_set_flags(authenc_esn
, CRYPTO_TFM_RES_BAD_KEY_LEN
);
114 static void authenc_esn_geniv_ahash_update_done(struct crypto_async_request
*areq
,
117 struct aead_request
*req
= areq
->data
;
118 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
119 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
120 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
121 struct ahash_request
*ahreq
= (void *)(areq_ctx
->tail
+ ctx
->reqoff
);
126 ahash_request_set_crypt(ahreq
, areq_ctx
->sg
, ahreq
->result
,
128 ahash_request_set_callback(ahreq
, aead_request_flags(req
) &
129 CRYPTO_TFM_REQ_MAY_SLEEP
,
130 areq_ctx
->update_complete2
, req
);
132 err
= crypto_ahash_update(ahreq
);
136 ahash_request_set_crypt(ahreq
, areq_ctx
->tsg
, ahreq
->result
,
138 ahash_request_set_callback(ahreq
, aead_request_flags(req
) &
139 CRYPTO_TFM_REQ_MAY_SLEEP
,
140 areq_ctx
->complete
, req
);
142 err
= crypto_ahash_finup(ahreq
);
146 scatterwalk_map_and_copy(ahreq
->result
, areq_ctx
->sg
,
148 crypto_aead_authsize(authenc_esn
), 1);
151 authenc_esn_request_complete(req
, err
);
154 static void authenc_esn_geniv_ahash_update_done2(struct crypto_async_request
*areq
,
157 struct aead_request
*req
= areq
->data
;
158 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
159 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
160 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
161 struct ahash_request
*ahreq
= (void *)(areq_ctx
->tail
+ ctx
->reqoff
);
166 ahash_request_set_crypt(ahreq
, areq_ctx
->tsg
, ahreq
->result
,
168 ahash_request_set_callback(ahreq
, aead_request_flags(req
) &
169 CRYPTO_TFM_REQ_MAY_SLEEP
,
170 areq_ctx
->complete
, req
);
172 err
= crypto_ahash_finup(ahreq
);
176 scatterwalk_map_and_copy(ahreq
->result
, areq_ctx
->sg
,
178 crypto_aead_authsize(authenc_esn
), 1);
181 authenc_esn_request_complete(req
, err
);
185 static void authenc_esn_geniv_ahash_done(struct crypto_async_request
*areq
,
188 struct aead_request
*req
= areq
->data
;
189 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
190 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
191 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
192 struct ahash_request
*ahreq
= (void *)(areq_ctx
->tail
+ ctx
->reqoff
);
197 scatterwalk_map_and_copy(ahreq
->result
, areq_ctx
->sg
,
199 crypto_aead_authsize(authenc_esn
), 1);
202 aead_request_complete(req
, err
);
206 static void authenc_esn_verify_ahash_update_done(struct crypto_async_request
*areq
,
210 unsigned int authsize
;
211 struct ablkcipher_request
*abreq
;
212 struct aead_request
*req
= areq
->data
;
213 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
214 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
215 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
216 struct ahash_request
*ahreq
= (void *)(areq_ctx
->tail
+ ctx
->reqoff
);
217 unsigned int cryptlen
= req
->cryptlen
;
222 ahash_request_set_crypt(ahreq
, areq_ctx
->sg
, ahreq
->result
,
225 ahash_request_set_callback(ahreq
,
226 aead_request_flags(req
) &
227 CRYPTO_TFM_REQ_MAY_SLEEP
,
228 areq_ctx
->update_complete2
, req
);
230 err
= crypto_ahash_update(ahreq
);
234 ahash_request_set_crypt(ahreq
, areq_ctx
->tsg
, ahreq
->result
,
236 ahash_request_set_callback(ahreq
, aead_request_flags(req
) &
237 CRYPTO_TFM_REQ_MAY_SLEEP
,
238 areq_ctx
->complete
, req
);
240 err
= crypto_ahash_finup(ahreq
);
244 authsize
= crypto_aead_authsize(authenc_esn
);
245 cryptlen
-= authsize
;
246 ihash
= ahreq
->result
+ authsize
;
247 scatterwalk_map_and_copy(ihash
, areq_ctx
->sg
, areq_ctx
->cryptlen
,
250 err
= memcmp(ihash
, ahreq
->result
, authsize
) ? -EBADMSG
: 0;
254 abreq
= aead_request_ctx(req
);
255 ablkcipher_request_set_tfm(abreq
, ctx
->enc
);
256 ablkcipher_request_set_callback(abreq
, aead_request_flags(req
),
257 req
->base
.complete
, req
->base
.data
);
258 ablkcipher_request_set_crypt(abreq
, req
->src
, req
->dst
,
261 err
= crypto_ablkcipher_decrypt(abreq
);
264 authenc_esn_request_complete(req
, err
);
267 static void authenc_esn_verify_ahash_update_done2(struct crypto_async_request
*areq
,
271 unsigned int authsize
;
272 struct ablkcipher_request
*abreq
;
273 struct aead_request
*req
= areq
->data
;
274 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
275 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
276 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
277 struct ahash_request
*ahreq
= (void *)(areq_ctx
->tail
+ ctx
->reqoff
);
278 unsigned int cryptlen
= req
->cryptlen
;
283 ahash_request_set_crypt(ahreq
, areq_ctx
->tsg
, ahreq
->result
,
285 ahash_request_set_callback(ahreq
, aead_request_flags(req
) &
286 CRYPTO_TFM_REQ_MAY_SLEEP
,
287 areq_ctx
->complete
, req
);
289 err
= crypto_ahash_finup(ahreq
);
293 authsize
= crypto_aead_authsize(authenc_esn
);
294 cryptlen
-= authsize
;
295 ihash
= ahreq
->result
+ authsize
;
296 scatterwalk_map_and_copy(ihash
, areq_ctx
->sg
, areq_ctx
->cryptlen
,
299 err
= memcmp(ihash
, ahreq
->result
, authsize
) ? -EBADMSG
: 0;
303 abreq
= aead_request_ctx(req
);
304 ablkcipher_request_set_tfm(abreq
, ctx
->enc
);
305 ablkcipher_request_set_callback(abreq
, aead_request_flags(req
),
306 req
->base
.complete
, req
->base
.data
);
307 ablkcipher_request_set_crypt(abreq
, req
->src
, req
->dst
,
310 err
= crypto_ablkcipher_decrypt(abreq
);
313 authenc_esn_request_complete(req
, err
);
317 static void authenc_esn_verify_ahash_done(struct crypto_async_request
*areq
,
321 unsigned int authsize
;
322 struct ablkcipher_request
*abreq
;
323 struct aead_request
*req
= areq
->data
;
324 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
325 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
326 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
327 struct ahash_request
*ahreq
= (void *)(areq_ctx
->tail
+ ctx
->reqoff
);
328 unsigned int cryptlen
= req
->cryptlen
;
333 authsize
= crypto_aead_authsize(authenc_esn
);
334 cryptlen
-= authsize
;
335 ihash
= ahreq
->result
+ authsize
;
336 scatterwalk_map_and_copy(ihash
, areq_ctx
->sg
, areq_ctx
->cryptlen
,
339 err
= memcmp(ihash
, ahreq
->result
, authsize
) ? -EBADMSG
: 0;
343 abreq
= aead_request_ctx(req
);
344 ablkcipher_request_set_tfm(abreq
, ctx
->enc
);
345 ablkcipher_request_set_callback(abreq
, aead_request_flags(req
),
346 req
->base
.complete
, req
->base
.data
);
347 ablkcipher_request_set_crypt(abreq
, req
->src
, req
->dst
,
350 err
= crypto_ablkcipher_decrypt(abreq
);
353 authenc_esn_request_complete(req
, err
);
356 static u8
*crypto_authenc_esn_ahash(struct aead_request
*req
,
359 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
360 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
361 struct crypto_ahash
*auth
= ctx
->auth
;
362 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
363 struct ahash_request
*ahreq
= (void *)(areq_ctx
->tail
+ ctx
->reqoff
);
364 u8
*hash
= areq_ctx
->tail
;
367 hash
= (u8
*)ALIGN((unsigned long)hash
+ crypto_ahash_alignmask(auth
),
368 crypto_ahash_alignmask(auth
) + 1);
370 ahash_request_set_tfm(ahreq
, auth
);
372 err
= crypto_ahash_init(ahreq
);
376 ahash_request_set_crypt(ahreq
, areq_ctx
->hsg
, hash
, areq_ctx
->headlen
);
377 ahash_request_set_callback(ahreq
, aead_request_flags(req
) & flags
,
378 areq_ctx
->update_complete
, req
);
380 err
= crypto_ahash_update(ahreq
);
384 ahash_request_set_crypt(ahreq
, areq_ctx
->sg
, hash
, areq_ctx
->cryptlen
);
385 ahash_request_set_callback(ahreq
, aead_request_flags(req
) & flags
,
386 areq_ctx
->update_complete2
, req
);
388 err
= crypto_ahash_update(ahreq
);
392 ahash_request_set_crypt(ahreq
, areq_ctx
->tsg
, hash
,
394 ahash_request_set_callback(ahreq
, aead_request_flags(req
) & flags
,
395 areq_ctx
->complete
, req
);
397 err
= crypto_ahash_finup(ahreq
);
404 static int crypto_authenc_esn_genicv(struct aead_request
*req
, u8
*iv
,
407 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
408 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
409 struct scatterlist
*dst
= req
->dst
;
410 struct scatterlist
*assoc
= req
->assoc
;
411 struct scatterlist
*cipher
= areq_ctx
->cipher
;
412 struct scatterlist
*hsg
= areq_ctx
->hsg
;
413 struct scatterlist
*tsg
= areq_ctx
->tsg
;
414 struct scatterlist
*assoc1
;
415 struct scatterlist
*assoc2
;
416 unsigned int ivsize
= crypto_aead_ivsize(authenc_esn
);
417 unsigned int cryptlen
= req
->cryptlen
;
423 vdst
= PageHighMem(dstp
) ? NULL
: page_address(dstp
) + dst
->offset
;
426 sg_init_table(cipher
, 2);
427 sg_set_buf(cipher
, iv
, ivsize
);
428 scatterwalk_crypto_chain(cipher
, dst
, vdst
== iv
+ ivsize
, 2);
433 if (sg_is_last(assoc
))
437 if (sg_is_last(assoc1
))
441 if (!sg_is_last(assoc2
))
444 sg_init_table(hsg
, 2);
445 sg_set_page(hsg
, sg_page(assoc
), assoc
->length
, assoc
->offset
);
446 sg_set_page(hsg
+ 1, sg_page(assoc2
), assoc2
->length
, assoc2
->offset
);
448 sg_init_table(tsg
, 1);
449 sg_set_page(tsg
, sg_page(assoc1
), assoc1
->length
, assoc1
->offset
);
451 areq_ctx
->cryptlen
= cryptlen
;
452 areq_ctx
->headlen
= assoc
->length
+ assoc2
->length
;
453 areq_ctx
->trailen
= assoc1
->length
;
456 areq_ctx
->complete
= authenc_esn_geniv_ahash_done
;
457 areq_ctx
->update_complete
= authenc_esn_geniv_ahash_update_done
;
458 areq_ctx
->update_complete2
= authenc_esn_geniv_ahash_update_done2
;
460 hash
= crypto_authenc_esn_ahash(req
, flags
);
462 return PTR_ERR(hash
);
464 scatterwalk_map_and_copy(hash
, dst
, cryptlen
,
465 crypto_aead_authsize(authenc_esn
), 1);
470 static void crypto_authenc_esn_encrypt_done(struct crypto_async_request
*req
,
473 struct aead_request
*areq
= req
->data
;
476 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(areq
);
477 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
478 struct ablkcipher_request
*abreq
= aead_request_ctx(areq
);
479 u8
*iv
= (u8
*)(abreq
+ 1) +
480 crypto_ablkcipher_reqsize(ctx
->enc
);
482 err
= crypto_authenc_esn_genicv(areq
, iv
, 0);
485 authenc_esn_request_complete(areq
, err
);
488 static int crypto_authenc_esn_encrypt(struct aead_request
*req
)
490 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
491 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
492 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
493 struct crypto_ablkcipher
*enc
= ctx
->enc
;
494 struct scatterlist
*dst
= req
->dst
;
495 unsigned int cryptlen
= req
->cryptlen
;
496 struct ablkcipher_request
*abreq
= (void *)(areq_ctx
->tail
498 u8
*iv
= (u8
*)abreq
- crypto_ablkcipher_ivsize(enc
);
501 ablkcipher_request_set_tfm(abreq
, enc
);
502 ablkcipher_request_set_callback(abreq
, aead_request_flags(req
),
503 crypto_authenc_esn_encrypt_done
, req
);
504 ablkcipher_request_set_crypt(abreq
, req
->src
, dst
, cryptlen
, req
->iv
);
506 memcpy(iv
, req
->iv
, crypto_aead_ivsize(authenc_esn
));
508 err
= crypto_ablkcipher_encrypt(abreq
);
512 return crypto_authenc_esn_genicv(req
, iv
, CRYPTO_TFM_REQ_MAY_SLEEP
);
515 static void crypto_authenc_esn_givencrypt_done(struct crypto_async_request
*req
,
518 struct aead_request
*areq
= req
->data
;
521 struct skcipher_givcrypt_request
*greq
= aead_request_ctx(areq
);
523 err
= crypto_authenc_esn_genicv(areq
, greq
->giv
, 0);
526 authenc_esn_request_complete(areq
, err
);
529 static int crypto_authenc_esn_givencrypt(struct aead_givcrypt_request
*req
)
531 struct crypto_aead
*authenc_esn
= aead_givcrypt_reqtfm(req
);
532 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
533 struct aead_request
*areq
= &req
->areq
;
534 struct skcipher_givcrypt_request
*greq
= aead_request_ctx(areq
);
538 skcipher_givcrypt_set_tfm(greq
, ctx
->enc
);
539 skcipher_givcrypt_set_callback(greq
, aead_request_flags(areq
),
540 crypto_authenc_esn_givencrypt_done
, areq
);
541 skcipher_givcrypt_set_crypt(greq
, areq
->src
, areq
->dst
, areq
->cryptlen
,
543 skcipher_givcrypt_set_giv(greq
, iv
, req
->seq
);
545 err
= crypto_skcipher_givencrypt(greq
);
549 return crypto_authenc_esn_genicv(areq
, iv
, CRYPTO_TFM_REQ_MAY_SLEEP
);
552 static int crypto_authenc_esn_verify(struct aead_request
*req
)
554 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
555 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
558 unsigned int authsize
;
560 areq_ctx
->complete
= authenc_esn_verify_ahash_done
;
561 areq_ctx
->update_complete
= authenc_esn_verify_ahash_update_done
;
563 ohash
= crypto_authenc_esn_ahash(req
, CRYPTO_TFM_REQ_MAY_SLEEP
);
565 return PTR_ERR(ohash
);
567 authsize
= crypto_aead_authsize(authenc_esn
);
568 ihash
= ohash
+ authsize
;
569 scatterwalk_map_and_copy(ihash
, areq_ctx
->sg
, areq_ctx
->cryptlen
,
571 return memcmp(ihash
, ohash
, authsize
) ? -EBADMSG
: 0;
574 static int crypto_authenc_esn_iverify(struct aead_request
*req
, u8
*iv
,
575 unsigned int cryptlen
)
577 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
578 struct authenc_esn_request_ctx
*areq_ctx
= aead_request_ctx(req
);
579 struct scatterlist
*src
= req
->src
;
580 struct scatterlist
*assoc
= req
->assoc
;
581 struct scatterlist
*cipher
= areq_ctx
->cipher
;
582 struct scatterlist
*hsg
= areq_ctx
->hsg
;
583 struct scatterlist
*tsg
= areq_ctx
->tsg
;
584 struct scatterlist
*assoc1
;
585 struct scatterlist
*assoc2
;
586 unsigned int ivsize
= crypto_aead_ivsize(authenc_esn
);
591 vsrc
= PageHighMem(srcp
) ? NULL
: page_address(srcp
) + src
->offset
;
594 sg_init_table(cipher
, 2);
595 sg_set_buf(cipher
, iv
, ivsize
);
596 scatterwalk_crypto_chain(cipher
, src
, vsrc
== iv
+ ivsize
, 2);
601 if (sg_is_last(assoc
))
605 if (sg_is_last(assoc1
))
609 if (!sg_is_last(assoc2
))
612 sg_init_table(hsg
, 2);
613 sg_set_page(hsg
, sg_page(assoc
), assoc
->length
, assoc
->offset
);
614 sg_set_page(hsg
+ 1, sg_page(assoc2
), assoc2
->length
, assoc2
->offset
);
616 sg_init_table(tsg
, 1);
617 sg_set_page(tsg
, sg_page(assoc1
), assoc1
->length
, assoc1
->offset
);
619 areq_ctx
->cryptlen
= cryptlen
;
620 areq_ctx
->headlen
= assoc
->length
+ assoc2
->length
;
621 areq_ctx
->trailen
= assoc1
->length
;
624 areq_ctx
->complete
= authenc_esn_verify_ahash_done
;
625 areq_ctx
->update_complete
= authenc_esn_verify_ahash_update_done
;
626 areq_ctx
->update_complete2
= authenc_esn_verify_ahash_update_done2
;
628 return crypto_authenc_esn_verify(req
);
631 static int crypto_authenc_esn_decrypt(struct aead_request
*req
)
633 struct crypto_aead
*authenc_esn
= crypto_aead_reqtfm(req
);
634 struct crypto_authenc_esn_ctx
*ctx
= crypto_aead_ctx(authenc_esn
);
635 struct ablkcipher_request
*abreq
= aead_request_ctx(req
);
636 unsigned int cryptlen
= req
->cryptlen
;
637 unsigned int authsize
= crypto_aead_authsize(authenc_esn
);
641 if (cryptlen
< authsize
)
643 cryptlen
-= authsize
;
645 err
= crypto_authenc_esn_iverify(req
, iv
, cryptlen
);
649 ablkcipher_request_set_tfm(abreq
, ctx
->enc
);
650 ablkcipher_request_set_callback(abreq
, aead_request_flags(req
),
651 req
->base
.complete
, req
->base
.data
);
652 ablkcipher_request_set_crypt(abreq
, req
->src
, req
->dst
, cryptlen
, iv
);
654 return crypto_ablkcipher_decrypt(abreq
);
657 static int crypto_authenc_esn_init_tfm(struct crypto_tfm
*tfm
)
659 struct crypto_instance
*inst
= crypto_tfm_alg_instance(tfm
);
660 struct authenc_esn_instance_ctx
*ictx
= crypto_instance_ctx(inst
);
661 struct crypto_authenc_esn_ctx
*ctx
= crypto_tfm_ctx(tfm
);
662 struct crypto_ahash
*auth
;
663 struct crypto_ablkcipher
*enc
;
666 auth
= crypto_spawn_ahash(&ictx
->auth
);
668 return PTR_ERR(auth
);
670 enc
= crypto_spawn_skcipher(&ictx
->enc
);
678 ctx
->reqoff
= ALIGN(2 * crypto_ahash_digestsize(auth
) +
679 crypto_ahash_alignmask(auth
),
680 crypto_ahash_alignmask(auth
) + 1) +
681 crypto_ablkcipher_ivsize(enc
);
683 tfm
->crt_aead
.reqsize
= sizeof(struct authenc_esn_request_ctx
) +
686 crypto_ahash_reqsize(auth
) +
687 sizeof(struct ahash_request
),
688 sizeof(struct skcipher_givcrypt_request
) +
689 crypto_ablkcipher_reqsize(enc
));
694 crypto_free_ahash(auth
);
698 static void crypto_authenc_esn_exit_tfm(struct crypto_tfm
*tfm
)
700 struct crypto_authenc_esn_ctx
*ctx
= crypto_tfm_ctx(tfm
);
702 crypto_free_ahash(ctx
->auth
);
703 crypto_free_ablkcipher(ctx
->enc
);
706 static struct crypto_instance
*crypto_authenc_esn_alloc(struct rtattr
**tb
)
708 struct crypto_attr_type
*algt
;
709 struct crypto_instance
*inst
;
710 struct hash_alg_common
*auth
;
711 struct crypto_alg
*auth_base
;
712 struct crypto_alg
*enc
;
713 struct authenc_esn_instance_ctx
*ctx
;
714 const char *enc_name
;
717 algt
= crypto_get_attr_type(tb
);
722 if ((algt
->type
^ CRYPTO_ALG_TYPE_AEAD
) & algt
->mask
)
723 return ERR_PTR(-EINVAL
);
725 auth
= ahash_attr_alg(tb
[1], CRYPTO_ALG_TYPE_HASH
,
726 CRYPTO_ALG_TYPE_AHASH_MASK
);
728 return ERR_CAST(auth
);
730 auth_base
= &auth
->base
;
732 enc_name
= crypto_attr_alg_name(tb
[2]);
733 err
= PTR_ERR(enc_name
);
734 if (IS_ERR(enc_name
))
737 inst
= kzalloc(sizeof(*inst
) + sizeof(*ctx
), GFP_KERNEL
);
742 ctx
= crypto_instance_ctx(inst
);
744 err
= crypto_init_ahash_spawn(&ctx
->auth
, auth
, inst
);
748 crypto_set_skcipher_spawn(&ctx
->enc
, inst
);
749 err
= crypto_grab_skcipher(&ctx
->enc
, enc_name
, 0,
750 crypto_requires_sync(algt
->type
,
755 enc
= crypto_skcipher_spawn_alg(&ctx
->enc
);
758 if (snprintf(inst
->alg
.cra_name
, CRYPTO_MAX_ALG_NAME
,
759 "authencesn(%s,%s)", auth_base
->cra_name
, enc
->cra_name
) >=
763 if (snprintf(inst
->alg
.cra_driver_name
, CRYPTO_MAX_ALG_NAME
,
764 "authencesn(%s,%s)", auth_base
->cra_driver_name
,
765 enc
->cra_driver_name
) >= CRYPTO_MAX_ALG_NAME
)
768 inst
->alg
.cra_flags
= CRYPTO_ALG_TYPE_AEAD
;
769 inst
->alg
.cra_flags
|= enc
->cra_flags
& CRYPTO_ALG_ASYNC
;
770 inst
->alg
.cra_priority
= enc
->cra_priority
*
771 10 + auth_base
->cra_priority
;
772 inst
->alg
.cra_blocksize
= enc
->cra_blocksize
;
773 inst
->alg
.cra_alignmask
= auth_base
->cra_alignmask
| enc
->cra_alignmask
;
774 inst
->alg
.cra_type
= &crypto_aead_type
;
776 inst
->alg
.cra_aead
.ivsize
= enc
->cra_ablkcipher
.ivsize
;
777 inst
->alg
.cra_aead
.maxauthsize
= auth
->digestsize
;
779 inst
->alg
.cra_ctxsize
= sizeof(struct crypto_authenc_esn_ctx
);
781 inst
->alg
.cra_init
= crypto_authenc_esn_init_tfm
;
782 inst
->alg
.cra_exit
= crypto_authenc_esn_exit_tfm
;
784 inst
->alg
.cra_aead
.setkey
= crypto_authenc_esn_setkey
;
785 inst
->alg
.cra_aead
.encrypt
= crypto_authenc_esn_encrypt
;
786 inst
->alg
.cra_aead
.decrypt
= crypto_authenc_esn_decrypt
;
787 inst
->alg
.cra_aead
.givencrypt
= crypto_authenc_esn_givencrypt
;
790 crypto_mod_put(auth_base
);
794 crypto_drop_skcipher(&ctx
->enc
);
796 crypto_drop_ahash(&ctx
->auth
);
804 static void crypto_authenc_esn_free(struct crypto_instance
*inst
)
806 struct authenc_esn_instance_ctx
*ctx
= crypto_instance_ctx(inst
);
808 crypto_drop_skcipher(&ctx
->enc
);
809 crypto_drop_ahash(&ctx
->auth
);
813 static struct crypto_template crypto_authenc_esn_tmpl
= {
814 .name
= "authencesn",
815 .alloc
= crypto_authenc_esn_alloc
,
816 .free
= crypto_authenc_esn_free
,
817 .module
= THIS_MODULE
,
820 static int __init
crypto_authenc_esn_module_init(void)
822 return crypto_register_template(&crypto_authenc_esn_tmpl
);
825 static void __exit
crypto_authenc_esn_module_exit(void)
827 crypto_unregister_template(&crypto_authenc_esn_tmpl
);
830 module_init(crypto_authenc_esn_module_init
);
831 module_exit(crypto_authenc_esn_module_exit
);
833 MODULE_LICENSE("GPL");
834 MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
835 MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers");