Root/crypto/authencesn.c

1/*
2 * authencesn.c - AEAD wrapper for IPsec with extended sequence numbers,
3 * derived from authenc.c
4 *
5 * Copyright (C) 2010 secunet Security Networks AG
6 * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.com>
7 *
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)
11 * any later version.
12 *
13 */
14
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>
27
28struct authenc_esn_instance_ctx {
29    struct crypto_ahash_spawn auth;
30    struct crypto_skcipher_spawn enc;
31};
32
33struct crypto_authenc_esn_ctx {
34    unsigned int reqoff;
35    struct crypto_ahash *auth;
36    struct crypto_ablkcipher *enc;
37};
38
39struct authenc_esn_request_ctx {
40    unsigned int cryptlen;
41    unsigned int headlen;
42    unsigned int trailen;
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;
50    char tail[];
51};
52
53static void authenc_esn_request_complete(struct aead_request *req, int err)
54{
55    if (err != -EINPROGRESS)
56        aead_request_complete(req, err);
57}
58
59static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 *key,
60                     unsigned int keylen)
61{
62    struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
63    struct crypto_ahash *auth = ctx->auth;
64    struct crypto_ablkcipher *enc = ctx->enc;
65    struct crypto_authenc_keys keys;
66    int err = -EINVAL;
67
68    if (crypto_authenc_extractkeys(&keys, key, keylen) != 0)
69        goto badkey;
70
71    crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
72    crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc_esn) &
73                     CRYPTO_TFM_REQ_MASK);
74    err = crypto_ahash_setkey(auth, keys.authkey, keys.authkeylen);
75    crypto_aead_set_flags(authenc_esn, crypto_ahash_get_flags(auth) &
76                       CRYPTO_TFM_RES_MASK);
77
78    if (err)
79        goto out;
80
81    crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK);
82    crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc_esn) &
83                     CRYPTO_TFM_REQ_MASK);
84    err = crypto_ablkcipher_setkey(enc, keys.enckey, keys.enckeylen);
85    crypto_aead_set_flags(authenc_esn, crypto_ablkcipher_get_flags(enc) &
86                       CRYPTO_TFM_RES_MASK);
87
88out:
89    return err;
90
91badkey:
92    crypto_aead_set_flags(authenc_esn, CRYPTO_TFM_RES_BAD_KEY_LEN);
93    goto out;
94}
95
96static void authenc_esn_geniv_ahash_update_done(struct crypto_async_request *areq,
97                        int err)
98{
99    struct aead_request *req = areq->data;
100    struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
101    struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
102    struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
103    struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
104
105    if (err)
106        goto out;
107
108    ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
109                areq_ctx->cryptlen);
110    ahash_request_set_callback(ahreq, aead_request_flags(req) &
111                      CRYPTO_TFM_REQ_MAY_SLEEP,
112                   areq_ctx->update_complete2, req);
113
114    err = crypto_ahash_update(ahreq);
115    if (err)
116        goto out;
117
118    ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
119                areq_ctx->trailen);
120    ahash_request_set_callback(ahreq, aead_request_flags(req) &
121                      CRYPTO_TFM_REQ_MAY_SLEEP,
122                   areq_ctx->complete, req);
123
124    err = crypto_ahash_finup(ahreq);
125    if (err)
126        goto out;
127
128    scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
129                 areq_ctx->cryptlen,
130                 crypto_aead_authsize(authenc_esn), 1);
131
132out:
133    authenc_esn_request_complete(req, err);
134}
135
136static void authenc_esn_geniv_ahash_update_done2(struct crypto_async_request *areq,
137                         int err)
138{
139    struct aead_request *req = areq->data;
140    struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
141    struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
142    struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
143    struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
144
145    if (err)
146        goto out;
147
148    ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
149                areq_ctx->trailen);
150    ahash_request_set_callback(ahreq, aead_request_flags(req) &
151                      CRYPTO_TFM_REQ_MAY_SLEEP,
152                   areq_ctx->complete, req);
153
154    err = crypto_ahash_finup(ahreq);
155    if (err)
156        goto out;
157
158    scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
159                 areq_ctx->cryptlen,
160                 crypto_aead_authsize(authenc_esn), 1);
161
162out:
163    authenc_esn_request_complete(req, err);
164}
165
166
167static void authenc_esn_geniv_ahash_done(struct crypto_async_request *areq,
168                     int err)
169{
170    struct aead_request *req = areq->data;
171    struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
172    struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
173    struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
174    struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
175
176    if (err)
177        goto out;
178
179    scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
180                 areq_ctx->cryptlen,
181                 crypto_aead_authsize(authenc_esn), 1);
182
183out:
184    aead_request_complete(req, err);
185}
186
187
188static void authenc_esn_verify_ahash_update_done(struct crypto_async_request *areq,
189                         int err)
190{
191    u8 *ihash;
192    unsigned int authsize;
193    struct ablkcipher_request *abreq;
194    struct aead_request *req = areq->data;
195    struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
196    struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
197    struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
198    struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
199    unsigned int cryptlen = req->cryptlen;
200
201    if (err)
202        goto out;
203
204    ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
205                areq_ctx->cryptlen);
206
207    ahash_request_set_callback(ahreq,
208                   aead_request_flags(req) &
209                   CRYPTO_TFM_REQ_MAY_SLEEP,
210                   areq_ctx->update_complete2, req);
211
212    err = crypto_ahash_update(ahreq);
213    if (err)
214        goto out;
215
216    ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
217                areq_ctx->trailen);
218    ahash_request_set_callback(ahreq, aead_request_flags(req) &
219                      CRYPTO_TFM_REQ_MAY_SLEEP,
220                   areq_ctx->complete, req);
221
222    err = crypto_ahash_finup(ahreq);
223    if (err)
224        goto out;
225
226    authsize = crypto_aead_authsize(authenc_esn);
227    cryptlen -= authsize;
228    ihash = ahreq->result + authsize;
229    scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
230                 authsize, 0);
231
232    err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
233    if (err)
234        goto out;
235
236    abreq = aead_request_ctx(req);
237    ablkcipher_request_set_tfm(abreq, ctx->enc);
238    ablkcipher_request_set_callback(abreq, aead_request_flags(req),
239                    req->base.complete, req->base.data);
240    ablkcipher_request_set_crypt(abreq, req->src, req->dst,
241                     cryptlen, req->iv);
242
243    err = crypto_ablkcipher_decrypt(abreq);
244
245out:
246    authenc_esn_request_complete(req, err);
247}
248
249static void authenc_esn_verify_ahash_update_done2(struct crypto_async_request *areq,
250                          int err)
251{
252    u8 *ihash;
253    unsigned int authsize;
254    struct ablkcipher_request *abreq;
255    struct aead_request *req = areq->data;
256    struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
257    struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
258    struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
259    struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
260    unsigned int cryptlen = req->cryptlen;
261
262    if (err)
263        goto out;
264
265    ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
266                areq_ctx->trailen);
267    ahash_request_set_callback(ahreq, aead_request_flags(req) &
268                      CRYPTO_TFM_REQ_MAY_SLEEP,
269                   areq_ctx->complete, req);
270
271    err = crypto_ahash_finup(ahreq);
272    if (err)
273        goto out;
274
275    authsize = crypto_aead_authsize(authenc_esn);
276    cryptlen -= authsize;
277    ihash = ahreq->result + authsize;
278    scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
279                 authsize, 0);
280
281    err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
282    if (err)
283        goto out;
284
285    abreq = aead_request_ctx(req);
286    ablkcipher_request_set_tfm(abreq, ctx->enc);
287    ablkcipher_request_set_callback(abreq, aead_request_flags(req),
288                    req->base.complete, req->base.data);
289    ablkcipher_request_set_crypt(abreq, req->src, req->dst,
290                     cryptlen, req->iv);
291
292    err = crypto_ablkcipher_decrypt(abreq);
293
294out:
295    authenc_esn_request_complete(req, err);
296}
297
298
299static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
300                      int err)
301{
302    u8 *ihash;
303    unsigned int authsize;
304    struct ablkcipher_request *abreq;
305    struct aead_request *req = areq->data;
306    struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
307    struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
308    struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
309    struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
310    unsigned int cryptlen = req->cryptlen;
311
312    if (err)
313        goto out;
314
315    authsize = crypto_aead_authsize(authenc_esn);
316    cryptlen -= authsize;
317    ihash = ahreq->result + authsize;
318    scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
319                 authsize, 0);
320
321    err = crypto_memneq(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
322    if (err)
323        goto out;
324
325    abreq = aead_request_ctx(req);
326    ablkcipher_request_set_tfm(abreq, ctx->enc);
327    ablkcipher_request_set_callback(abreq, aead_request_flags(req),
328                    req->base.complete, req->base.data);
329    ablkcipher_request_set_crypt(abreq, req->src, req->dst,
330                     cryptlen, req->iv);
331
332    err = crypto_ablkcipher_decrypt(abreq);
333
334out:
335    authenc_esn_request_complete(req, err);
336}
337
338static u8 *crypto_authenc_esn_ahash(struct aead_request *req,
339                    unsigned int flags)
340{
341    struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
342    struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
343    struct crypto_ahash *auth = ctx->auth;
344    struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
345    struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
346    u8 *hash = areq_ctx->tail;
347    int err;
348
349    hash = (u8 *)ALIGN((unsigned long)hash + crypto_ahash_alignmask(auth),
350                crypto_ahash_alignmask(auth) + 1);
351
352    ahash_request_set_tfm(ahreq, auth);
353
354    err = crypto_ahash_init(ahreq);
355    if (err)
356        return ERR_PTR(err);
357
358    ahash_request_set_crypt(ahreq, areq_ctx->hsg, hash, areq_ctx->headlen);
359    ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
360                   areq_ctx->update_complete, req);
361
362    err = crypto_ahash_update(ahreq);
363    if (err)
364        return ERR_PTR(err);
365
366    ahash_request_set_crypt(ahreq, areq_ctx->sg, hash, areq_ctx->cryptlen);
367    ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
368                   areq_ctx->update_complete2, req);
369
370    err = crypto_ahash_update(ahreq);
371    if (err)
372        return ERR_PTR(err);
373
374    ahash_request_set_crypt(ahreq, areq_ctx->tsg, hash,
375                areq_ctx->trailen);
376    ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
377                   areq_ctx->complete, req);
378
379    err = crypto_ahash_finup(ahreq);
380    if (err)
381        return ERR_PTR(err);
382
383    return hash;
384}
385
386static int crypto_authenc_esn_genicv(struct aead_request *req, u8 *iv,
387                     unsigned int flags)
388{
389    struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
390    struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
391    struct scatterlist *dst = req->dst;
392    struct scatterlist *assoc = req->assoc;
393    struct scatterlist *cipher = areq_ctx->cipher;
394    struct scatterlist *hsg = areq_ctx->hsg;
395    struct scatterlist *tsg = areq_ctx->tsg;
396    struct scatterlist *assoc1;
397    struct scatterlist *assoc2;
398    unsigned int ivsize = crypto_aead_ivsize(authenc_esn);
399    unsigned int cryptlen = req->cryptlen;
400    struct page *dstp;
401    u8 *vdst;
402    u8 *hash;
403
404    dstp = sg_page(dst);
405    vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;
406
407    if (ivsize) {
408        sg_init_table(cipher, 2);
409        sg_set_buf(cipher, iv, ivsize);
410        scatterwalk_crypto_chain(cipher, dst, vdst == iv + ivsize, 2);
411        dst = cipher;
412        cryptlen += ivsize;
413    }
414
415    if (sg_is_last(assoc))
416        return -EINVAL;
417
418    assoc1 = assoc + 1;
419    if (sg_is_last(assoc1))
420        return -EINVAL;
421
422    assoc2 = assoc + 2;
423    if (!sg_is_last(assoc2))
424        return -EINVAL;
425
426    sg_init_table(hsg, 2);
427    sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset);
428    sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset);
429
430    sg_init_table(tsg, 1);
431    sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
432
433    areq_ctx->cryptlen = cryptlen;
434    areq_ctx->headlen = assoc->length + assoc2->length;
435    areq_ctx->trailen = assoc1->length;
436    areq_ctx->sg = dst;
437
438    areq_ctx->complete = authenc_esn_geniv_ahash_done;
439    areq_ctx->update_complete = authenc_esn_geniv_ahash_update_done;
440    areq_ctx->update_complete2 = authenc_esn_geniv_ahash_update_done2;
441
442    hash = crypto_authenc_esn_ahash(req, flags);
443    if (IS_ERR(hash))
444        return PTR_ERR(hash);
445
446    scatterwalk_map_and_copy(hash, dst, cryptlen,
447                 crypto_aead_authsize(authenc_esn), 1);
448    return 0;
449}
450
451
452static void crypto_authenc_esn_encrypt_done(struct crypto_async_request *req,
453                        int err)
454{
455    struct aead_request *areq = req->data;
456
457    if (!err) {
458        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(areq);
459        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
460        struct ablkcipher_request *abreq = aead_request_ctx(areq);
461        u8 *iv = (u8 *)(abreq + 1) +
462             crypto_ablkcipher_reqsize(ctx->enc);
463
464        err = crypto_authenc_esn_genicv(areq, iv, 0);
465    }
466
467    authenc_esn_request_complete(areq, err);
468}
469
470static int crypto_authenc_esn_encrypt(struct aead_request *req)
471{
472    struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
473    struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
474    struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
475    struct crypto_ablkcipher *enc = ctx->enc;
476    struct scatterlist *dst = req->dst;
477    unsigned int cryptlen = req->cryptlen;
478    struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
479                            + ctx->reqoff);
480    u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(enc);
481    int err;
482
483    ablkcipher_request_set_tfm(abreq, enc);
484    ablkcipher_request_set_callback(abreq, aead_request_flags(req),
485                    crypto_authenc_esn_encrypt_done, req);
486    ablkcipher_request_set_crypt(abreq, req->src, dst, cryptlen, req->iv);
487
488    memcpy(iv, req->iv, crypto_aead_ivsize(authenc_esn));
489
490    err = crypto_ablkcipher_encrypt(abreq);
491    if (err)
492        return err;
493
494    return crypto_authenc_esn_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
495}
496
497static void crypto_authenc_esn_givencrypt_done(struct crypto_async_request *req,
498                           int err)
499{
500    struct aead_request *areq = req->data;
501
502    if (!err) {
503        struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
504
505        err = crypto_authenc_esn_genicv(areq, greq->giv, 0);
506    }
507
508    authenc_esn_request_complete(areq, err);
509}
510
511static int crypto_authenc_esn_givencrypt(struct aead_givcrypt_request *req)
512{
513    struct crypto_aead *authenc_esn = aead_givcrypt_reqtfm(req);
514    struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
515    struct aead_request *areq = &req->areq;
516    struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
517    u8 *iv = req->giv;
518    int err;
519
520    skcipher_givcrypt_set_tfm(greq, ctx->enc);
521    skcipher_givcrypt_set_callback(greq, aead_request_flags(areq),
522                       crypto_authenc_esn_givencrypt_done, areq);
523    skcipher_givcrypt_set_crypt(greq, areq->src, areq->dst, areq->cryptlen,
524                    areq->iv);
525    skcipher_givcrypt_set_giv(greq, iv, req->seq);
526
527    err = crypto_skcipher_givencrypt(greq);
528    if (err)
529        return err;
530
531    return crypto_authenc_esn_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
532}
533
534static int crypto_authenc_esn_verify(struct aead_request *req)
535{
536    struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
537    struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
538    u8 *ohash;
539    u8 *ihash;
540    unsigned int authsize;
541
542    areq_ctx->complete = authenc_esn_verify_ahash_done;
543    areq_ctx->update_complete = authenc_esn_verify_ahash_update_done;
544
545    ohash = crypto_authenc_esn_ahash(req, CRYPTO_TFM_REQ_MAY_SLEEP);
546    if (IS_ERR(ohash))
547        return PTR_ERR(ohash);
548
549    authsize = crypto_aead_authsize(authenc_esn);
550    ihash = ohash + authsize;
551    scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
552                 authsize, 0);
553    return crypto_memneq(ihash, ohash, authsize) ? -EBADMSG : 0;
554}
555
556static int crypto_authenc_esn_iverify(struct aead_request *req, u8 *iv,
557                      unsigned int cryptlen)
558{
559    struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
560    struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
561    struct scatterlist *src = req->src;
562    struct scatterlist *assoc = req->assoc;
563    struct scatterlist *cipher = areq_ctx->cipher;
564    struct scatterlist *hsg = areq_ctx->hsg;
565    struct scatterlist *tsg = areq_ctx->tsg;
566    struct scatterlist *assoc1;
567    struct scatterlist *assoc2;
568    unsigned int ivsize = crypto_aead_ivsize(authenc_esn);
569    struct page *srcp;
570    u8 *vsrc;
571
572    srcp = sg_page(src);
573    vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;
574
575    if (ivsize) {
576        sg_init_table(cipher, 2);
577        sg_set_buf(cipher, iv, ivsize);
578        scatterwalk_crypto_chain(cipher, src, vsrc == iv + ivsize, 2);
579        src = cipher;
580        cryptlen += ivsize;
581    }
582
583    if (sg_is_last(assoc))
584        return -EINVAL;
585
586    assoc1 = assoc + 1;
587    if (sg_is_last(assoc1))
588        return -EINVAL;
589
590    assoc2 = assoc + 2;
591    if (!sg_is_last(assoc2))
592        return -EINVAL;
593
594    sg_init_table(hsg, 2);
595    sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset);
596    sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset);
597
598    sg_init_table(tsg, 1);
599    sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
600
601    areq_ctx->cryptlen = cryptlen;
602    areq_ctx->headlen = assoc->length + assoc2->length;
603    areq_ctx->trailen = assoc1->length;
604    areq_ctx->sg = src;
605
606    areq_ctx->complete = authenc_esn_verify_ahash_done;
607    areq_ctx->update_complete = authenc_esn_verify_ahash_update_done;
608    areq_ctx->update_complete2 = authenc_esn_verify_ahash_update_done2;
609
610    return crypto_authenc_esn_verify(req);
611}
612
613static int crypto_authenc_esn_decrypt(struct aead_request *req)
614{
615    struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
616    struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
617    struct ablkcipher_request *abreq = aead_request_ctx(req);
618    unsigned int cryptlen = req->cryptlen;
619    unsigned int authsize = crypto_aead_authsize(authenc_esn);
620    u8 *iv = req->iv;
621    int err;
622
623    if (cryptlen < authsize)
624        return -EINVAL;
625    cryptlen -= authsize;
626
627    err = crypto_authenc_esn_iverify(req, iv, cryptlen);
628    if (err)
629        return err;
630
631    ablkcipher_request_set_tfm(abreq, ctx->enc);
632    ablkcipher_request_set_callback(abreq, aead_request_flags(req),
633                    req->base.complete, req->base.data);
634    ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, iv);
635
636    return crypto_ablkcipher_decrypt(abreq);
637}
638
639static int crypto_authenc_esn_init_tfm(struct crypto_tfm *tfm)
640{
641    struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
642    struct authenc_esn_instance_ctx *ictx = crypto_instance_ctx(inst);
643    struct crypto_authenc_esn_ctx *ctx = crypto_tfm_ctx(tfm);
644    struct crypto_ahash *auth;
645    struct crypto_ablkcipher *enc;
646    int err;
647
648    auth = crypto_spawn_ahash(&ictx->auth);
649    if (IS_ERR(auth))
650        return PTR_ERR(auth);
651
652    enc = crypto_spawn_skcipher(&ictx->enc);
653    err = PTR_ERR(enc);
654    if (IS_ERR(enc))
655        goto err_free_ahash;
656
657    ctx->auth = auth;
658    ctx->enc = enc;
659
660    ctx->reqoff = ALIGN(2 * crypto_ahash_digestsize(auth) +
661                crypto_ahash_alignmask(auth),
662                crypto_ahash_alignmask(auth) + 1) +
663              crypto_ablkcipher_ivsize(enc);
664
665    tfm->crt_aead.reqsize = sizeof(struct authenc_esn_request_ctx) +
666                ctx->reqoff +
667                max_t(unsigned int,
668                crypto_ahash_reqsize(auth) +
669                sizeof(struct ahash_request),
670                sizeof(struct skcipher_givcrypt_request) +
671                crypto_ablkcipher_reqsize(enc));
672
673    return 0;
674
675err_free_ahash:
676    crypto_free_ahash(auth);
677    return err;
678}
679
680static void crypto_authenc_esn_exit_tfm(struct crypto_tfm *tfm)
681{
682    struct crypto_authenc_esn_ctx *ctx = crypto_tfm_ctx(tfm);
683
684    crypto_free_ahash(ctx->auth);
685    crypto_free_ablkcipher(ctx->enc);
686}
687
688static struct crypto_instance *crypto_authenc_esn_alloc(struct rtattr **tb)
689{
690    struct crypto_attr_type *algt;
691    struct crypto_instance *inst;
692    struct hash_alg_common *auth;
693    struct crypto_alg *auth_base;
694    struct crypto_alg *enc;
695    struct authenc_esn_instance_ctx *ctx;
696    const char *enc_name;
697    int err;
698
699    algt = crypto_get_attr_type(tb);
700    if (IS_ERR(algt))
701        return ERR_CAST(algt);
702
703    if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
704        return ERR_PTR(-EINVAL);
705
706    auth = ahash_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH,
707                   CRYPTO_ALG_TYPE_AHASH_MASK);
708    if (IS_ERR(auth))
709        return ERR_CAST(auth);
710
711    auth_base = &auth->base;
712
713    enc_name = crypto_attr_alg_name(tb[2]);
714    err = PTR_ERR(enc_name);
715    if (IS_ERR(enc_name))
716        goto out_put_auth;
717
718    inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
719    err = -ENOMEM;
720    if (!inst)
721        goto out_put_auth;
722
723    ctx = crypto_instance_ctx(inst);
724
725    err = crypto_init_ahash_spawn(&ctx->auth, auth, inst);
726    if (err)
727        goto err_free_inst;
728
729    crypto_set_skcipher_spawn(&ctx->enc, inst);
730    err = crypto_grab_skcipher(&ctx->enc, enc_name, 0,
731                   crypto_requires_sync(algt->type,
732                            algt->mask));
733    if (err)
734        goto err_drop_auth;
735
736    enc = crypto_skcipher_spawn_alg(&ctx->enc);
737
738    err = -ENAMETOOLONG;
739    if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
740             "authencesn(%s,%s)", auth_base->cra_name, enc->cra_name) >=
741        CRYPTO_MAX_ALG_NAME)
742        goto err_drop_enc;
743
744    if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
745             "authencesn(%s,%s)", auth_base->cra_driver_name,
746             enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
747        goto err_drop_enc;
748
749    inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
750    inst->alg.cra_flags |= enc->cra_flags & CRYPTO_ALG_ASYNC;
751    inst->alg.cra_priority = enc->cra_priority *
752                 10 + auth_base->cra_priority;
753    inst->alg.cra_blocksize = enc->cra_blocksize;
754    inst->alg.cra_alignmask = auth_base->cra_alignmask | enc->cra_alignmask;
755    inst->alg.cra_type = &crypto_aead_type;
756
757    inst->alg.cra_aead.ivsize = enc->cra_ablkcipher.ivsize;
758    inst->alg.cra_aead.maxauthsize = auth->digestsize;
759
760    inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_esn_ctx);
761
762    inst->alg.cra_init = crypto_authenc_esn_init_tfm;
763    inst->alg.cra_exit = crypto_authenc_esn_exit_tfm;
764
765    inst->alg.cra_aead.setkey = crypto_authenc_esn_setkey;
766    inst->alg.cra_aead.encrypt = crypto_authenc_esn_encrypt;
767    inst->alg.cra_aead.decrypt = crypto_authenc_esn_decrypt;
768    inst->alg.cra_aead.givencrypt = crypto_authenc_esn_givencrypt;
769
770out:
771    crypto_mod_put(auth_base);
772    return inst;
773
774err_drop_enc:
775    crypto_drop_skcipher(&ctx->enc);
776err_drop_auth:
777    crypto_drop_ahash(&ctx->auth);
778err_free_inst:
779    kfree(inst);
780out_put_auth:
781    inst = ERR_PTR(err);
782    goto out;
783}
784
785static void crypto_authenc_esn_free(struct crypto_instance *inst)
786{
787    struct authenc_esn_instance_ctx *ctx = crypto_instance_ctx(inst);
788
789    crypto_drop_skcipher(&ctx->enc);
790    crypto_drop_ahash(&ctx->auth);
791    kfree(inst);
792}
793
794static struct crypto_template crypto_authenc_esn_tmpl = {
795    .name = "authencesn",
796    .alloc = crypto_authenc_esn_alloc,
797    .free = crypto_authenc_esn_free,
798    .module = THIS_MODULE,
799};
800
801static int __init crypto_authenc_esn_module_init(void)
802{
803    return crypto_register_template(&crypto_authenc_esn_tmpl);
804}
805
806static void __exit crypto_authenc_esn_module_exit(void)
807{
808    crypto_unregister_template(&crypto_authenc_esn_tmpl);
809}
810
811module_init(crypto_authenc_esn_module_init);
812module_exit(crypto_authenc_esn_module_exit);
813
814MODULE_LICENSE("GPL");
815MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
816MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers");
817

Archive Download this file



interactive