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    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;
69    int err = -EINVAL;
70
71    if (!RTA_OK(rta, keylen))
72        goto badkey;
73    if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
74        goto badkey;
75    if (RTA_PAYLOAD(rta) < sizeof(*param))
76        goto badkey;
77
78    param = RTA_DATA(rta);
79    enckeylen = be32_to_cpu(param->enckeylen);
80
81    key += RTA_ALIGN(rta->rta_len);
82    keylen -= RTA_ALIGN(rta->rta_len);
83
84    if (keylen < enckeylen)
85        goto badkey;
86
87    authkeylen = keylen - enckeylen;
88
89    crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
90    crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc_esn) &
91                     CRYPTO_TFM_REQ_MASK);
92    err = crypto_ahash_setkey(auth, key, authkeylen);
93    crypto_aead_set_flags(authenc_esn, crypto_ahash_get_flags(auth) &
94                       CRYPTO_TFM_RES_MASK);
95
96    if (err)
97        goto out;
98
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);
105
106out:
107    return err;
108
109badkey:
110    crypto_aead_set_flags(authenc_esn, CRYPTO_TFM_RES_BAD_KEY_LEN);
111    goto out;
112}
113
114static void authenc_esn_geniv_ahash_update_done(struct crypto_async_request *areq,
115                        int err)
116{
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);
122
123    if (err)
124        goto out;
125
126    ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
127                areq_ctx->cryptlen);
128    ahash_request_set_callback(ahreq, aead_request_flags(req) &
129                      CRYPTO_TFM_REQ_MAY_SLEEP,
130                   areq_ctx->update_complete2, req);
131
132    err = crypto_ahash_update(ahreq);
133    if (err)
134        goto out;
135
136    ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
137                areq_ctx->trailen);
138    ahash_request_set_callback(ahreq, aead_request_flags(req) &
139                      CRYPTO_TFM_REQ_MAY_SLEEP,
140                   areq_ctx->complete, req);
141
142    err = crypto_ahash_finup(ahreq);
143    if (err)
144        goto out;
145
146    scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
147                 areq_ctx->cryptlen,
148                 crypto_aead_authsize(authenc_esn), 1);
149
150out:
151    authenc_esn_request_complete(req, err);
152}
153
154static void authenc_esn_geniv_ahash_update_done2(struct crypto_async_request *areq,
155                         int err)
156{
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);
162
163    if (err)
164        goto out;
165
166    ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
167                areq_ctx->trailen);
168    ahash_request_set_callback(ahreq, aead_request_flags(req) &
169                      CRYPTO_TFM_REQ_MAY_SLEEP,
170                   areq_ctx->complete, req);
171
172    err = crypto_ahash_finup(ahreq);
173    if (err)
174        goto out;
175
176    scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
177                 areq_ctx->cryptlen,
178                 crypto_aead_authsize(authenc_esn), 1);
179
180out:
181    authenc_esn_request_complete(req, err);
182}
183
184
185static void authenc_esn_geniv_ahash_done(struct crypto_async_request *areq,
186                     int err)
187{
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);
193
194    if (err)
195        goto out;
196
197    scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
198                 areq_ctx->cryptlen,
199                 crypto_aead_authsize(authenc_esn), 1);
200
201out:
202    aead_request_complete(req, err);
203}
204
205
206static void authenc_esn_verify_ahash_update_done(struct crypto_async_request *areq,
207                         int err)
208{
209    u8 *ihash;
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;
218
219    if (err)
220        goto out;
221
222    ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
223                areq_ctx->cryptlen);
224
225    ahash_request_set_callback(ahreq,
226                   aead_request_flags(req) &
227                   CRYPTO_TFM_REQ_MAY_SLEEP,
228                   areq_ctx->update_complete2, req);
229
230    err = crypto_ahash_update(ahreq);
231    if (err)
232        goto out;
233
234    ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
235                areq_ctx->trailen);
236    ahash_request_set_callback(ahreq, aead_request_flags(req) &
237                      CRYPTO_TFM_REQ_MAY_SLEEP,
238                   areq_ctx->complete, req);
239
240    err = crypto_ahash_finup(ahreq);
241    if (err)
242        goto out;
243
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,
248                 authsize, 0);
249
250    err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
251    if (err)
252        goto out;
253
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,
259                     cryptlen, req->iv);
260
261    err = crypto_ablkcipher_decrypt(abreq);
262
263out:
264    authenc_esn_request_complete(req, err);
265}
266
267static void authenc_esn_verify_ahash_update_done2(struct crypto_async_request *areq,
268                          int err)
269{
270    u8 *ihash;
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;
279
280    if (err)
281        goto out;
282
283    ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
284                areq_ctx->trailen);
285    ahash_request_set_callback(ahreq, aead_request_flags(req) &
286                      CRYPTO_TFM_REQ_MAY_SLEEP,
287                   areq_ctx->complete, req);
288
289    err = crypto_ahash_finup(ahreq);
290    if (err)
291        goto out;
292
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,
297                 authsize, 0);
298
299    err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
300    if (err)
301        goto out;
302
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,
308                     cryptlen, req->iv);
309
310    err = crypto_ablkcipher_decrypt(abreq);
311
312out:
313    authenc_esn_request_complete(req, err);
314}
315
316
317static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
318                      int err)
319{
320    u8 *ihash;
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;
329
330    if (err)
331        goto out;
332
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,
337                 authsize, 0);
338
339    err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
340    if (err)
341        goto out;
342
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,
348                     cryptlen, req->iv);
349
350    err = crypto_ablkcipher_decrypt(abreq);
351
352out:
353    authenc_esn_request_complete(req, err);
354}
355
356static u8 *crypto_authenc_esn_ahash(struct aead_request *req,
357                    unsigned int flags)
358{
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;
365    int err;
366
367    hash = (u8 *)ALIGN((unsigned long)hash + crypto_ahash_alignmask(auth),
368                crypto_ahash_alignmask(auth) + 1);
369
370    ahash_request_set_tfm(ahreq, auth);
371
372    err = crypto_ahash_init(ahreq);
373    if (err)
374        return ERR_PTR(err);
375
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);
379
380    err = crypto_ahash_update(ahreq);
381    if (err)
382        return ERR_PTR(err);
383
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);
387
388    err = crypto_ahash_update(ahreq);
389    if (err)
390        return ERR_PTR(err);
391
392    ahash_request_set_crypt(ahreq, areq_ctx->tsg, hash,
393                areq_ctx->trailen);
394    ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
395                   areq_ctx->complete, req);
396
397    err = crypto_ahash_finup(ahreq);
398    if (err)
399        return ERR_PTR(err);
400
401    return hash;
402}
403
404static int crypto_authenc_esn_genicv(struct aead_request *req, u8 *iv,
405                     unsigned int flags)
406{
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;
418    struct page *dstp;
419    u8 *vdst;
420    u8 *hash;
421
422    dstp = sg_page(dst);
423    vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;
424
425    if (ivsize) {
426        sg_init_table(cipher, 2);
427        sg_set_buf(cipher, iv, ivsize);
428        scatterwalk_crypto_chain(cipher, dst, vdst == iv + ivsize, 2);
429        dst = cipher;
430        cryptlen += ivsize;
431    }
432
433    if (sg_is_last(assoc))
434        return -EINVAL;
435
436    assoc1 = assoc + 1;
437    if (sg_is_last(assoc1))
438        return -EINVAL;
439
440    assoc2 = assoc + 2;
441    if (!sg_is_last(assoc2))
442        return -EINVAL;
443
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);
447
448    sg_init_table(tsg, 1);
449    sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
450
451    areq_ctx->cryptlen = cryptlen;
452    areq_ctx->headlen = assoc->length + assoc2->length;
453    areq_ctx->trailen = assoc1->length;
454    areq_ctx->sg = dst;
455
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;
459
460    hash = crypto_authenc_esn_ahash(req, flags);
461    if (IS_ERR(hash))
462        return PTR_ERR(hash);
463
464    scatterwalk_map_and_copy(hash, dst, cryptlen,
465                 crypto_aead_authsize(authenc_esn), 1);
466    return 0;
467}
468
469
470static void crypto_authenc_esn_encrypt_done(struct crypto_async_request *req,
471                        int err)
472{
473    struct aead_request *areq = req->data;
474
475    if (!err) {
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);
481
482        err = crypto_authenc_esn_genicv(areq, iv, 0);
483    }
484
485    authenc_esn_request_complete(areq, err);
486}
487
488static int crypto_authenc_esn_encrypt(struct aead_request *req)
489{
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
497                            + ctx->reqoff);
498    u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(enc);
499    int err;
500
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);
505
506    memcpy(iv, req->iv, crypto_aead_ivsize(authenc_esn));
507
508    err = crypto_ablkcipher_encrypt(abreq);
509    if (err)
510        return err;
511
512    return crypto_authenc_esn_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
513}
514
515static void crypto_authenc_esn_givencrypt_done(struct crypto_async_request *req,
516                           int err)
517{
518    struct aead_request *areq = req->data;
519
520    if (!err) {
521        struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
522
523        err = crypto_authenc_esn_genicv(areq, greq->giv, 0);
524    }
525
526    authenc_esn_request_complete(areq, err);
527}
528
529static int crypto_authenc_esn_givencrypt(struct aead_givcrypt_request *req)
530{
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);
535    u8 *iv = req->giv;
536    int err;
537
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,
542                    areq->iv);
543    skcipher_givcrypt_set_giv(greq, iv, req->seq);
544
545    err = crypto_skcipher_givencrypt(greq);
546    if (err)
547        return err;
548
549    return crypto_authenc_esn_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
550}
551
552static int crypto_authenc_esn_verify(struct aead_request *req)
553{
554    struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
555    struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
556    u8 *ohash;
557    u8 *ihash;
558    unsigned int authsize;
559
560    areq_ctx->complete = authenc_esn_verify_ahash_done;
561    areq_ctx->update_complete = authenc_esn_verify_ahash_update_done;
562
563    ohash = crypto_authenc_esn_ahash(req, CRYPTO_TFM_REQ_MAY_SLEEP);
564    if (IS_ERR(ohash))
565        return PTR_ERR(ohash);
566
567    authsize = crypto_aead_authsize(authenc_esn);
568    ihash = ohash + authsize;
569    scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
570                 authsize, 0);
571    return memcmp(ihash, ohash, authsize) ? -EBADMSG : 0;
572}
573
574static int crypto_authenc_esn_iverify(struct aead_request *req, u8 *iv,
575                      unsigned int cryptlen)
576{
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);
587    struct page *srcp;
588    u8 *vsrc;
589
590    srcp = sg_page(src);
591    vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;
592
593    if (ivsize) {
594        sg_init_table(cipher, 2);
595        sg_set_buf(cipher, iv, ivsize);
596        scatterwalk_crypto_chain(cipher, src, vsrc == iv + ivsize, 2);
597        src = cipher;
598        cryptlen += ivsize;
599    }
600
601    if (sg_is_last(assoc))
602        return -EINVAL;
603
604    assoc1 = assoc + 1;
605    if (sg_is_last(assoc1))
606        return -EINVAL;
607
608    assoc2 = assoc + 2;
609    if (!sg_is_last(assoc2))
610        return -EINVAL;
611
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);
615
616    sg_init_table(tsg, 1);
617    sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
618
619    areq_ctx->cryptlen = cryptlen;
620    areq_ctx->headlen = assoc->length + assoc2->length;
621    areq_ctx->trailen = assoc1->length;
622    areq_ctx->sg = src;
623
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;
627
628    return crypto_authenc_esn_verify(req);
629}
630
631static int crypto_authenc_esn_decrypt(struct aead_request *req)
632{
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);
638    u8 *iv = req->iv;
639    int err;
640
641    if (cryptlen < authsize)
642        return -EINVAL;
643    cryptlen -= authsize;
644
645    err = crypto_authenc_esn_iverify(req, iv, cryptlen);
646    if (err)
647        return err;
648
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);
653
654    return crypto_ablkcipher_decrypt(abreq);
655}
656
657static int crypto_authenc_esn_init_tfm(struct crypto_tfm *tfm)
658{
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;
664    int err;
665
666    auth = crypto_spawn_ahash(&ictx->auth);
667    if (IS_ERR(auth))
668        return PTR_ERR(auth);
669
670    enc = crypto_spawn_skcipher(&ictx->enc);
671    err = PTR_ERR(enc);
672    if (IS_ERR(enc))
673        goto err_free_ahash;
674
675    ctx->auth = auth;
676    ctx->enc = enc;
677
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);
682
683    tfm->crt_aead.reqsize = sizeof(struct authenc_esn_request_ctx) +
684                ctx->reqoff +
685                max_t(unsigned int,
686                crypto_ahash_reqsize(auth) +
687                sizeof(struct ahash_request),
688                sizeof(struct skcipher_givcrypt_request) +
689                crypto_ablkcipher_reqsize(enc));
690
691    return 0;
692
693err_free_ahash:
694    crypto_free_ahash(auth);
695    return err;
696}
697
698static void crypto_authenc_esn_exit_tfm(struct crypto_tfm *tfm)
699{
700    struct crypto_authenc_esn_ctx *ctx = crypto_tfm_ctx(tfm);
701
702    crypto_free_ahash(ctx->auth);
703    crypto_free_ablkcipher(ctx->enc);
704}
705
706static struct crypto_instance *crypto_authenc_esn_alloc(struct rtattr **tb)
707{
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;
715    int err;
716
717    algt = crypto_get_attr_type(tb);
718    if (IS_ERR(algt))
719        return ERR_CAST(algt);
720
721    if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
722        return ERR_PTR(-EINVAL);
723
724    auth = ahash_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH,
725                   CRYPTO_ALG_TYPE_AHASH_MASK);
726    if (IS_ERR(auth))
727        return ERR_CAST(auth);
728
729    auth_base = &auth->base;
730
731    enc_name = crypto_attr_alg_name(tb[2]);
732    err = PTR_ERR(enc_name);
733    if (IS_ERR(enc_name))
734        goto out_put_auth;
735
736    inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
737    err = -ENOMEM;
738    if (!inst)
739        goto out_put_auth;
740
741    ctx = crypto_instance_ctx(inst);
742
743    err = crypto_init_ahash_spawn(&ctx->auth, auth, inst);
744    if (err)
745        goto err_free_inst;
746
747    crypto_set_skcipher_spawn(&ctx->enc, inst);
748    err = crypto_grab_skcipher(&ctx->enc, enc_name, 0,
749                   crypto_requires_sync(algt->type,
750                            algt->mask));
751    if (err)
752        goto err_drop_auth;
753
754    enc = crypto_skcipher_spawn_alg(&ctx->enc);
755
756    err = -ENAMETOOLONG;
757    if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
758             "authencesn(%s,%s)", auth_base->cra_name, enc->cra_name) >=
759        CRYPTO_MAX_ALG_NAME)
760        goto err_drop_enc;
761
762    if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
763             "authencesn(%s,%s)", auth_base->cra_driver_name,
764             enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
765        goto err_drop_enc;
766
767    inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
768    inst->alg.cra_flags |= enc->cra_flags & CRYPTO_ALG_ASYNC;
769    inst->alg.cra_priority = enc->cra_priority *
770                 10 + auth_base->cra_priority;
771    inst->alg.cra_blocksize = enc->cra_blocksize;
772    inst->alg.cra_alignmask = auth_base->cra_alignmask | enc->cra_alignmask;
773    inst->alg.cra_type = &crypto_aead_type;
774
775    inst->alg.cra_aead.ivsize = enc->cra_ablkcipher.ivsize;
776    inst->alg.cra_aead.maxauthsize = auth->digestsize;
777
778    inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_esn_ctx);
779
780    inst->alg.cra_init = crypto_authenc_esn_init_tfm;
781    inst->alg.cra_exit = crypto_authenc_esn_exit_tfm;
782
783    inst->alg.cra_aead.setkey = crypto_authenc_esn_setkey;
784    inst->alg.cra_aead.encrypt = crypto_authenc_esn_encrypt;
785    inst->alg.cra_aead.decrypt = crypto_authenc_esn_decrypt;
786    inst->alg.cra_aead.givencrypt = crypto_authenc_esn_givencrypt;
787
788out:
789    crypto_mod_put(auth_base);
790    return inst;
791
792err_drop_enc:
793    crypto_drop_skcipher(&ctx->enc);
794err_drop_auth:
795    crypto_drop_ahash(&ctx->auth);
796err_free_inst:
797    kfree(inst);
798out_put_auth:
799    inst = ERR_PTR(err);
800    goto out;
801}
802
803static void crypto_authenc_esn_free(struct crypto_instance *inst)
804{
805    struct authenc_esn_instance_ctx *ctx = crypto_instance_ctx(inst);
806
807    crypto_drop_skcipher(&ctx->enc);
808    crypto_drop_ahash(&ctx->auth);
809    kfree(inst);
810}
811
812static struct crypto_template crypto_authenc_esn_tmpl = {
813    .name = "authencesn",
814    .alloc = crypto_authenc_esn_alloc,
815    .free = crypto_authenc_esn_free,
816    .module = THIS_MODULE,
817};
818
819static int __init crypto_authenc_esn_module_init(void)
820{
821    return crypto_register_template(&crypto_authenc_esn_tmpl);
822}
823
824static void __exit crypto_authenc_esn_module_exit(void)
825{
826    crypto_unregister_template(&crypto_authenc_esn_tmpl);
827}
828
829module_init(crypto_authenc_esn_module_init);
830module_exit(crypto_authenc_esn_module_exit);
831
832MODULE_LICENSE("GPL");
833MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
834MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers");
835

Archive Download this file



interactive