Root/crypto/authenc.c

1/*
2 * Authenc: Simple AEAD wrapper for IPsec
3 *
4 * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 */
12
13#include <crypto/aead.h>
14#include <crypto/internal/hash.h>
15#include <crypto/internal/skcipher.h>
16#include <crypto/authenc.h>
17#include <crypto/scatterwalk.h>
18#include <linux/err.h>
19#include <linux/init.h>
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/rtnetlink.h>
23#include <linux/slab.h>
24#include <linux/spinlock.h>
25
26typedef u8 *(*authenc_ahash_t)(struct aead_request *req, unsigned int flags);
27
28struct authenc_instance_ctx {
29    struct crypto_ahash_spawn auth;
30    struct crypto_skcipher_spawn enc;
31};
32
33struct crypto_authenc_ctx {
34    unsigned int reqoff;
35    struct crypto_ahash *auth;
36    struct crypto_ablkcipher *enc;
37};
38
39struct authenc_request_ctx {
40    unsigned int cryptlen;
41    struct scatterlist *sg;
42    struct scatterlist asg[2];
43    struct scatterlist cipher[2];
44    crypto_completion_t complete;
45    crypto_completion_t update_complete;
46    char tail[];
47};
48
49static void authenc_request_complete(struct aead_request *req, int err)
50{
51    if (err != -EINPROGRESS)
52        aead_request_complete(req, err);
53}
54
55static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
56                 unsigned int keylen)
57{
58    unsigned int authkeylen;
59    unsigned int enckeylen;
60    struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
61    struct crypto_ahash *auth = ctx->auth;
62    struct crypto_ablkcipher *enc = ctx->enc;
63    struct rtattr *rta = (void *)key;
64    struct crypto_authenc_key_param *param;
65    int err = -EINVAL;
66
67    if (!RTA_OK(rta, keylen))
68        goto badkey;
69    if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
70        goto badkey;
71    if (RTA_PAYLOAD(rta) < sizeof(*param))
72        goto badkey;
73
74    param = RTA_DATA(rta);
75    enckeylen = be32_to_cpu(param->enckeylen);
76
77    key += RTA_ALIGN(rta->rta_len);
78    keylen -= RTA_ALIGN(rta->rta_len);
79
80    if (keylen < enckeylen)
81        goto badkey;
82
83    authkeylen = keylen - enckeylen;
84
85    crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
86    crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc) &
87                    CRYPTO_TFM_REQ_MASK);
88    err = crypto_ahash_setkey(auth, key, authkeylen);
89    crypto_aead_set_flags(authenc, crypto_ahash_get_flags(auth) &
90                       CRYPTO_TFM_RES_MASK);
91
92    if (err)
93        goto out;
94
95    crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK);
96    crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc) &
97                     CRYPTO_TFM_REQ_MASK);
98    err = crypto_ablkcipher_setkey(enc, key + authkeylen, enckeylen);
99    crypto_aead_set_flags(authenc, crypto_ablkcipher_get_flags(enc) &
100                       CRYPTO_TFM_RES_MASK);
101
102out:
103    return err;
104
105badkey:
106    crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
107    goto out;
108}
109
110static void authenc_geniv_ahash_update_done(struct crypto_async_request *areq,
111                        int err)
112{
113    struct aead_request *req = areq->data;
114    struct crypto_aead *authenc = crypto_aead_reqtfm(req);
115    struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
116    struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
117    struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
118
119    if (err)
120        goto out;
121
122    ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
123                areq_ctx->cryptlen);
124    ahash_request_set_callback(ahreq, aead_request_flags(req) &
125                      CRYPTO_TFM_REQ_MAY_SLEEP,
126                   areq_ctx->complete, req);
127
128    err = crypto_ahash_finup(ahreq);
129    if (err)
130        goto out;
131
132    scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
133                 areq_ctx->cryptlen,
134                 crypto_aead_authsize(authenc), 1);
135
136out:
137    authenc_request_complete(req, err);
138}
139
140static void authenc_geniv_ahash_done(struct crypto_async_request *areq, int err)
141{
142    struct aead_request *req = areq->data;
143    struct crypto_aead *authenc = crypto_aead_reqtfm(req);
144    struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
145    struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
146    struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
147
148    if (err)
149        goto out;
150
151    scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
152                 areq_ctx->cryptlen,
153                 crypto_aead_authsize(authenc), 1);
154
155out:
156    aead_request_complete(req, err);
157}
158
159static void authenc_verify_ahash_update_done(struct crypto_async_request *areq,
160                         int err)
161{
162    u8 *ihash;
163    unsigned int authsize;
164    struct ablkcipher_request *abreq;
165    struct aead_request *req = areq->data;
166    struct crypto_aead *authenc = crypto_aead_reqtfm(req);
167    struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
168    struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
169    struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
170    unsigned int cryptlen = req->cryptlen;
171
172    if (err)
173        goto out;
174
175    ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
176                areq_ctx->cryptlen);
177    ahash_request_set_callback(ahreq, aead_request_flags(req) &
178                      CRYPTO_TFM_REQ_MAY_SLEEP,
179                   areq_ctx->complete, req);
180
181    err = crypto_ahash_finup(ahreq);
182    if (err)
183        goto out;
184
185    authsize = crypto_aead_authsize(authenc);
186    cryptlen -= authsize;
187    ihash = ahreq->result + authsize;
188    scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
189                 authsize, 0);
190
191    err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
192    if (err)
193        goto out;
194
195    abreq = aead_request_ctx(req);
196    ablkcipher_request_set_tfm(abreq, ctx->enc);
197    ablkcipher_request_set_callback(abreq, aead_request_flags(req),
198                    req->base.complete, req->base.data);
199    ablkcipher_request_set_crypt(abreq, req->src, req->dst,
200                     cryptlen, req->iv);
201
202    err = crypto_ablkcipher_decrypt(abreq);
203
204out:
205    authenc_request_complete(req, err);
206}
207
208static void authenc_verify_ahash_done(struct crypto_async_request *areq,
209                      int err)
210{
211    u8 *ihash;
212    unsigned int authsize;
213    struct ablkcipher_request *abreq;
214    struct aead_request *req = areq->data;
215    struct crypto_aead *authenc = crypto_aead_reqtfm(req);
216    struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
217    struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
218    struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
219    unsigned int cryptlen = req->cryptlen;
220
221    if (err)
222        goto out;
223
224    authsize = crypto_aead_authsize(authenc);
225    cryptlen -= authsize;
226    ihash = ahreq->result + authsize;
227    scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
228                 authsize, 0);
229
230    err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
231    if (err)
232        goto out;
233
234    abreq = aead_request_ctx(req);
235    ablkcipher_request_set_tfm(abreq, ctx->enc);
236    ablkcipher_request_set_callback(abreq, aead_request_flags(req),
237                    req->base.complete, req->base.data);
238    ablkcipher_request_set_crypt(abreq, req->src, req->dst,
239                     cryptlen, req->iv);
240
241    err = crypto_ablkcipher_decrypt(abreq);
242
243out:
244    authenc_request_complete(req, err);
245}
246
247static u8 *crypto_authenc_ahash_fb(struct aead_request *req, unsigned int flags)
248{
249    struct crypto_aead *authenc = crypto_aead_reqtfm(req);
250    struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
251    struct crypto_ahash *auth = ctx->auth;
252    struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
253    struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
254    u8 *hash = areq_ctx->tail;
255    int err;
256
257    hash = (u8 *)ALIGN((unsigned long)hash + crypto_ahash_alignmask(auth),
258                crypto_ahash_alignmask(auth) + 1);
259
260    ahash_request_set_tfm(ahreq, auth);
261
262    err = crypto_ahash_init(ahreq);
263    if (err)
264        return ERR_PTR(err);
265
266    ahash_request_set_crypt(ahreq, req->assoc, hash, req->assoclen);
267    ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
268                   areq_ctx->update_complete, req);
269
270    err = crypto_ahash_update(ahreq);
271    if (err)
272        return ERR_PTR(err);
273
274    ahash_request_set_crypt(ahreq, areq_ctx->sg, hash,
275                areq_ctx->cryptlen);
276    ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
277                   areq_ctx->complete, req);
278
279    err = crypto_ahash_finup(ahreq);
280    if (err)
281        return ERR_PTR(err);
282
283    return hash;
284}
285
286static u8 *crypto_authenc_ahash(struct aead_request *req, unsigned int flags)
287{
288    struct crypto_aead *authenc = crypto_aead_reqtfm(req);
289    struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
290    struct crypto_ahash *auth = ctx->auth;
291    struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
292    struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
293    u8 *hash = areq_ctx->tail;
294    int err;
295
296    hash = (u8 *)ALIGN((unsigned long)hash + crypto_ahash_alignmask(auth),
297               crypto_ahash_alignmask(auth) + 1);
298
299    ahash_request_set_tfm(ahreq, auth);
300    ahash_request_set_crypt(ahreq, areq_ctx->sg, hash,
301                areq_ctx->cryptlen);
302    ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
303                   areq_ctx->complete, req);
304
305    err = crypto_ahash_digest(ahreq);
306    if (err)
307        return ERR_PTR(err);
308
309    return hash;
310}
311
312static int crypto_authenc_genicv(struct aead_request *req, u8 *iv,
313                 unsigned int flags)
314{
315    struct crypto_aead *authenc = crypto_aead_reqtfm(req);
316    struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
317    struct scatterlist *dst = req->dst;
318    struct scatterlist *assoc = req->assoc;
319    struct scatterlist *cipher = areq_ctx->cipher;
320    struct scatterlist *asg = areq_ctx->asg;
321    unsigned int ivsize = crypto_aead_ivsize(authenc);
322    unsigned int cryptlen = req->cryptlen;
323    authenc_ahash_t authenc_ahash_fn = crypto_authenc_ahash_fb;
324    struct page *dstp;
325    u8 *vdst;
326    u8 *hash;
327
328    dstp = sg_page(dst);
329    vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;
330
331    if (ivsize) {
332        sg_init_table(cipher, 2);
333        sg_set_buf(cipher, iv, ivsize);
334        scatterwalk_crypto_chain(cipher, dst, vdst == iv + ivsize, 2);
335        dst = cipher;
336        cryptlen += ivsize;
337    }
338
339    if (sg_is_last(assoc)) {
340        authenc_ahash_fn = crypto_authenc_ahash;
341        sg_init_table(asg, 2);
342        sg_set_page(asg, sg_page(assoc), assoc->length, assoc->offset);
343        scatterwalk_crypto_chain(asg, dst, 0, 2);
344        dst = asg;
345        cryptlen += req->assoclen;
346    }
347
348    areq_ctx->cryptlen = cryptlen;
349    areq_ctx->sg = dst;
350
351    areq_ctx->complete = authenc_geniv_ahash_done;
352    areq_ctx->update_complete = authenc_geniv_ahash_update_done;
353
354    hash = authenc_ahash_fn(req, flags);
355    if (IS_ERR(hash))
356        return PTR_ERR(hash);
357
358    scatterwalk_map_and_copy(hash, dst, cryptlen,
359                 crypto_aead_authsize(authenc), 1);
360    return 0;
361}
362
363static void crypto_authenc_encrypt_done(struct crypto_async_request *req,
364                    int err)
365{
366    struct aead_request *areq = req->data;
367
368    if (!err) {
369        struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
370        struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
371        struct ablkcipher_request *abreq = aead_request_ctx(areq);
372        u8 *iv = (u8 *)(abreq + 1) +
373             crypto_ablkcipher_reqsize(ctx->enc);
374
375        err = crypto_authenc_genicv(areq, iv, 0);
376    }
377
378    authenc_request_complete(areq, err);
379}
380
381static int crypto_authenc_encrypt(struct aead_request *req)
382{
383    struct crypto_aead *authenc = crypto_aead_reqtfm(req);
384    struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
385    struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
386    struct crypto_ablkcipher *enc = ctx->enc;
387    struct scatterlist *dst = req->dst;
388    unsigned int cryptlen = req->cryptlen;
389    struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
390                            + ctx->reqoff);
391    u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(enc);
392    int err;
393
394    ablkcipher_request_set_tfm(abreq, enc);
395    ablkcipher_request_set_callback(abreq, aead_request_flags(req),
396                    crypto_authenc_encrypt_done, req);
397    ablkcipher_request_set_crypt(abreq, req->src, dst, cryptlen, req->iv);
398
399    memcpy(iv, req->iv, crypto_aead_ivsize(authenc));
400
401    err = crypto_ablkcipher_encrypt(abreq);
402    if (err)
403        return err;
404
405    return crypto_authenc_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
406}
407
408static void crypto_authenc_givencrypt_done(struct crypto_async_request *req,
409                       int err)
410{
411    struct aead_request *areq = req->data;
412
413    if (!err) {
414        struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
415
416        err = crypto_authenc_genicv(areq, greq->giv, 0);
417    }
418
419    authenc_request_complete(areq, err);
420}
421
422static int crypto_authenc_givencrypt(struct aead_givcrypt_request *req)
423{
424    struct crypto_aead *authenc = aead_givcrypt_reqtfm(req);
425    struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
426    struct aead_request *areq = &req->areq;
427    struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
428    u8 *iv = req->giv;
429    int err;
430
431    skcipher_givcrypt_set_tfm(greq, ctx->enc);
432    skcipher_givcrypt_set_callback(greq, aead_request_flags(areq),
433                       crypto_authenc_givencrypt_done, areq);
434    skcipher_givcrypt_set_crypt(greq, areq->src, areq->dst, areq->cryptlen,
435                    areq->iv);
436    skcipher_givcrypt_set_giv(greq, iv, req->seq);
437
438    err = crypto_skcipher_givencrypt(greq);
439    if (err)
440        return err;
441
442    return crypto_authenc_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
443}
444
445static int crypto_authenc_verify(struct aead_request *req,
446                 authenc_ahash_t authenc_ahash_fn)
447{
448    struct crypto_aead *authenc = crypto_aead_reqtfm(req);
449    struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
450    u8 *ohash;
451    u8 *ihash;
452    unsigned int authsize;
453
454    areq_ctx->complete = authenc_verify_ahash_done;
455    areq_ctx->update_complete = authenc_verify_ahash_update_done;
456
457    ohash = authenc_ahash_fn(req, CRYPTO_TFM_REQ_MAY_SLEEP);
458    if (IS_ERR(ohash))
459        return PTR_ERR(ohash);
460
461    authsize = crypto_aead_authsize(authenc);
462    ihash = ohash + authsize;
463    scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
464                 authsize, 0);
465    return memcmp(ihash, ohash, authsize) ? -EBADMSG : 0;
466}
467
468static int crypto_authenc_iverify(struct aead_request *req, u8 *iv,
469                  unsigned int cryptlen)
470{
471    struct crypto_aead *authenc = crypto_aead_reqtfm(req);
472    struct authenc_request_ctx *areq_ctx = aead_request_ctx(req);
473    struct scatterlist *src = req->src;
474    struct scatterlist *assoc = req->assoc;
475    struct scatterlist *cipher = areq_ctx->cipher;
476    struct scatterlist *asg = areq_ctx->asg;
477    unsigned int ivsize = crypto_aead_ivsize(authenc);
478    authenc_ahash_t authenc_ahash_fn = crypto_authenc_ahash_fb;
479    struct page *srcp;
480    u8 *vsrc;
481
482    srcp = sg_page(src);
483    vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;
484
485    if (ivsize) {
486        sg_init_table(cipher, 2);
487        sg_set_buf(cipher, iv, ivsize);
488        scatterwalk_crypto_chain(cipher, src, vsrc == iv + ivsize, 2);
489        src = cipher;
490        cryptlen += ivsize;
491    }
492
493    if (sg_is_last(assoc)) {
494        authenc_ahash_fn = crypto_authenc_ahash;
495        sg_init_table(asg, 2);
496        sg_set_page(asg, sg_page(assoc), assoc->length, assoc->offset);
497        scatterwalk_crypto_chain(asg, src, 0, 2);
498        src = asg;
499        cryptlen += req->assoclen;
500    }
501
502    areq_ctx->cryptlen = cryptlen;
503    areq_ctx->sg = src;
504
505    return crypto_authenc_verify(req, authenc_ahash_fn);
506}
507
508static int crypto_authenc_decrypt(struct aead_request *req)
509{
510    struct crypto_aead *authenc = crypto_aead_reqtfm(req);
511    struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
512    struct ablkcipher_request *abreq = aead_request_ctx(req);
513    unsigned int cryptlen = req->cryptlen;
514    unsigned int authsize = crypto_aead_authsize(authenc);
515    u8 *iv = req->iv;
516    int err;
517
518    if (cryptlen < authsize)
519        return -EINVAL;
520    cryptlen -= authsize;
521
522    err = crypto_authenc_iverify(req, iv, cryptlen);
523    if (err)
524        return err;
525
526    ablkcipher_request_set_tfm(abreq, ctx->enc);
527    ablkcipher_request_set_callback(abreq, aead_request_flags(req),
528                    req->base.complete, req->base.data);
529    ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, iv);
530
531    return crypto_ablkcipher_decrypt(abreq);
532}
533
534static int crypto_authenc_init_tfm(struct crypto_tfm *tfm)
535{
536    struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
537    struct authenc_instance_ctx *ictx = crypto_instance_ctx(inst);
538    struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm);
539    struct crypto_ahash *auth;
540    struct crypto_ablkcipher *enc;
541    int err;
542
543    auth = crypto_spawn_ahash(&ictx->auth);
544    if (IS_ERR(auth))
545        return PTR_ERR(auth);
546
547    enc = crypto_spawn_skcipher(&ictx->enc);
548    err = PTR_ERR(enc);
549    if (IS_ERR(enc))
550        goto err_free_ahash;
551
552    ctx->auth = auth;
553    ctx->enc = enc;
554
555    ctx->reqoff = ALIGN(2 * crypto_ahash_digestsize(auth) +
556                crypto_ahash_alignmask(auth),
557                crypto_ahash_alignmask(auth) + 1) +
558              crypto_ablkcipher_ivsize(enc);
559
560    tfm->crt_aead.reqsize = sizeof(struct authenc_request_ctx) +
561                ctx->reqoff +
562                max_t(unsigned int,
563                crypto_ahash_reqsize(auth) +
564                sizeof(struct ahash_request),
565                sizeof(struct skcipher_givcrypt_request) +
566                crypto_ablkcipher_reqsize(enc));
567
568    return 0;
569
570err_free_ahash:
571    crypto_free_ahash(auth);
572    return err;
573}
574
575static void crypto_authenc_exit_tfm(struct crypto_tfm *tfm)
576{
577    struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm);
578
579    crypto_free_ahash(ctx->auth);
580    crypto_free_ablkcipher(ctx->enc);
581}
582
583static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
584{
585    struct crypto_attr_type *algt;
586    struct crypto_instance *inst;
587    struct hash_alg_common *auth;
588    struct crypto_alg *auth_base;
589    struct crypto_alg *enc;
590    struct authenc_instance_ctx *ctx;
591    const char *enc_name;
592    int err;
593
594    algt = crypto_get_attr_type(tb);
595    err = PTR_ERR(algt);
596    if (IS_ERR(algt))
597        return ERR_PTR(err);
598
599    if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
600        return ERR_PTR(-EINVAL);
601
602    auth = ahash_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH,
603                   CRYPTO_ALG_TYPE_AHASH_MASK);
604    if (IS_ERR(auth))
605        return ERR_CAST(auth);
606
607    auth_base = &auth->base;
608
609    enc_name = crypto_attr_alg_name(tb[2]);
610    err = PTR_ERR(enc_name);
611    if (IS_ERR(enc_name))
612        goto out_put_auth;
613
614    inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
615    err = -ENOMEM;
616    if (!inst)
617        goto out_put_auth;
618
619    ctx = crypto_instance_ctx(inst);
620
621    err = crypto_init_ahash_spawn(&ctx->auth, auth, inst);
622    if (err)
623        goto err_free_inst;
624
625    crypto_set_skcipher_spawn(&ctx->enc, inst);
626    err = crypto_grab_skcipher(&ctx->enc, enc_name, 0,
627                   crypto_requires_sync(algt->type,
628                            algt->mask));
629    if (err)
630        goto err_drop_auth;
631
632    enc = crypto_skcipher_spawn_alg(&ctx->enc);
633
634    err = -ENAMETOOLONG;
635    if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
636             "authenc(%s,%s)", auth_base->cra_name, enc->cra_name) >=
637        CRYPTO_MAX_ALG_NAME)
638        goto err_drop_enc;
639
640    if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
641             "authenc(%s,%s)", auth_base->cra_driver_name,
642             enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
643        goto err_drop_enc;
644
645    inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
646    inst->alg.cra_flags |= enc->cra_flags & CRYPTO_ALG_ASYNC;
647    inst->alg.cra_priority = enc->cra_priority *
648                 10 + auth_base->cra_priority;
649    inst->alg.cra_blocksize = enc->cra_blocksize;
650    inst->alg.cra_alignmask = auth_base->cra_alignmask | enc->cra_alignmask;
651    inst->alg.cra_type = &crypto_aead_type;
652
653    inst->alg.cra_aead.ivsize = enc->cra_ablkcipher.ivsize;
654    inst->alg.cra_aead.maxauthsize = auth->digestsize;
655
656    inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_ctx);
657
658    inst->alg.cra_init = crypto_authenc_init_tfm;
659    inst->alg.cra_exit = crypto_authenc_exit_tfm;
660
661    inst->alg.cra_aead.setkey = crypto_authenc_setkey;
662    inst->alg.cra_aead.encrypt = crypto_authenc_encrypt;
663    inst->alg.cra_aead.decrypt = crypto_authenc_decrypt;
664    inst->alg.cra_aead.givencrypt = crypto_authenc_givencrypt;
665
666out:
667    crypto_mod_put(auth_base);
668    return inst;
669
670err_drop_enc:
671    crypto_drop_skcipher(&ctx->enc);
672err_drop_auth:
673    crypto_drop_ahash(&ctx->auth);
674err_free_inst:
675    kfree(inst);
676out_put_auth:
677    inst = ERR_PTR(err);
678    goto out;
679}
680
681static void crypto_authenc_free(struct crypto_instance *inst)
682{
683    struct authenc_instance_ctx *ctx = crypto_instance_ctx(inst);
684
685    crypto_drop_skcipher(&ctx->enc);
686    crypto_drop_ahash(&ctx->auth);
687    kfree(inst);
688}
689
690static struct crypto_template crypto_authenc_tmpl = {
691    .name = "authenc",
692    .alloc = crypto_authenc_alloc,
693    .free = crypto_authenc_free,
694    .module = THIS_MODULE,
695};
696
697static int __init crypto_authenc_module_init(void)
698{
699    return crypto_register_template(&crypto_authenc_tmpl);
700}
701
702static void __exit crypto_authenc_module_exit(void)
703{
704    crypto_unregister_template(&crypto_authenc_tmpl);
705}
706
707module_init(crypto_authenc_module_init);
708module_exit(crypto_authenc_module_exit);
709
710MODULE_LICENSE("GPL");
711MODULE_DESCRIPTION("Simple AEAD wrapper for IPsec");
712

Archive Download this file



interactive