The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/crypto/authencesn.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 
   28 struct authenc_esn_instance_ctx {
   29         struct crypto_ahash_spawn auth;
   30         struct crypto_skcipher_spawn enc;
   31 };
   32 
   33 struct crypto_authenc_esn_ctx {
   34         unsigned int reqoff;
   35         struct crypto_ahash *auth;
   36         struct crypto_ablkcipher *enc;
   37 };
   38 
   39 struct 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 
   53 static void authenc_esn_request_complete(struct aead_request *req, int err)
   54 {
   55         if (err != -EINPROGRESS)
   56                 aead_request_complete(req, err);
   57 }
   58 
   59 static 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 
  106 out:
  107         return err;
  108 
  109 badkey:
  110         crypto_aead_set_flags(authenc_esn, CRYPTO_TFM_RES_BAD_KEY_LEN);
  111         goto out;
  112 }
  113 
  114 static 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 
  150 out:
  151         authenc_esn_request_complete(req, err);
  152 }
  153 
  154 static 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 
  180 out:
  181         authenc_esn_request_complete(req, err);
  182 }
  183 
  184 
  185 static 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 
  201 out:
  202         aead_request_complete(req, err);
  203 }
  204 
  205 
  206 static 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 
  263 out:
  264         authenc_esn_request_complete(req, err);
  265 }
  266 
  267 static 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 
  312 out:
  313         authenc_esn_request_complete(req, err);
  314 }
  315 
  316 
  317 static 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 
  352 out:
  353         authenc_esn_request_complete(req, err);
  354 }
  355 
  356 static 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 
  404 static 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 
  470 static 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 
  488 static 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 
  515 static 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 
  529 static 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 
  552 static 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 
  574 static 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 
  631 static 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 
  657 static 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 
  693 err_free_ahash:
  694         crypto_free_ahash(auth);
  695         return err;
  696 }
  697 
  698 static 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 
  706 static 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         err = PTR_ERR(algt);
  719         if (IS_ERR(algt))
  720                 return ERR_PTR(err);
  721 
  722         if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
  723                 return ERR_PTR(-EINVAL);
  724 
  725         auth = ahash_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH,
  726                                CRYPTO_ALG_TYPE_AHASH_MASK);
  727         if (IS_ERR(auth))
  728                 return ERR_CAST(auth);
  729 
  730         auth_base = &auth->base;
  731 
  732         enc_name = crypto_attr_alg_name(tb[2]);
  733         err = PTR_ERR(enc_name);
  734         if (IS_ERR(enc_name))
  735                 goto out_put_auth;
  736 
  737         inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
  738         err = -ENOMEM;
  739         if (!inst)
  740                 goto out_put_auth;
  741 
  742         ctx = crypto_instance_ctx(inst);
  743 
  744         err = crypto_init_ahash_spawn(&ctx->auth, auth, inst);
  745         if (err)
  746                 goto err_free_inst;
  747 
  748         crypto_set_skcipher_spawn(&ctx->enc, inst);
  749         err = crypto_grab_skcipher(&ctx->enc, enc_name, 0,
  750                                    crypto_requires_sync(algt->type,
  751                                                         algt->mask));
  752         if (err)
  753                 goto err_drop_auth;
  754 
  755         enc = crypto_skcipher_spawn_alg(&ctx->enc);
  756 
  757         err = -ENAMETOOLONG;
  758         if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
  759                      "authencesn(%s,%s)", auth_base->cra_name, enc->cra_name) >=
  760             CRYPTO_MAX_ALG_NAME)
  761                 goto err_drop_enc;
  762 
  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)
  766                 goto err_drop_enc;
  767 
  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;
  775 
  776         inst->alg.cra_aead.ivsize = enc->cra_ablkcipher.ivsize;
  777         inst->alg.cra_aead.maxauthsize = auth->digestsize;
  778 
  779         inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_esn_ctx);
  780 
  781         inst->alg.cra_init = crypto_authenc_esn_init_tfm;
  782         inst->alg.cra_exit = crypto_authenc_esn_exit_tfm;
  783 
  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;
  788 
  789 out:
  790         crypto_mod_put(auth_base);
  791         return inst;
  792 
  793 err_drop_enc:
  794         crypto_drop_skcipher(&ctx->enc);
  795 err_drop_auth:
  796         crypto_drop_ahash(&ctx->auth);
  797 err_free_inst:
  798         kfree(inst);
  799 out_put_auth:
  800         inst = ERR_PTR(err);
  801         goto out;
  802 }
  803 
  804 static void crypto_authenc_esn_free(struct crypto_instance *inst)
  805 {
  806         struct authenc_esn_instance_ctx *ctx = crypto_instance_ctx(inst);
  807 
  808         crypto_drop_skcipher(&ctx->enc);
  809         crypto_drop_ahash(&ctx->auth);
  810         kfree(inst);
  811 }
  812 
  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,
  818 };
  819 
  820 static int __init crypto_authenc_esn_module_init(void)
  821 {
  822         return crypto_register_template(&crypto_authenc_esn_tmpl);
  823 }
  824 
  825 static void __exit crypto_authenc_esn_module_exit(void)
  826 {
  827         crypto_unregister_template(&crypto_authenc_esn_tmpl);
  828 }
  829 
  830 module_init(crypto_authenc_esn_module_init);
  831 module_exit(crypto_authenc_esn_module_exit);
  832 
  833 MODULE_LICENSE("GPL");
  834 MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
  835 MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers");

Cache object: 0550e50389173b40eedf87576faed189


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.