Commit a5079d084f8be781aae8a635cab4b179cfea4ebd

Authored by Steffen Klassert
Committed by David S. Miller
1 parent 27b61ae2d7

crypto: authencesn - Add algorithm to handle IPsec extended sequence numbers

ESP with separate encryption/authentication algorithms needs a special
treatment for the associated data. This patch add a new algorithm that
handles esp with extended sequence numbers.

Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 2 changed files with 836 additions and 1 deletions Side-by-side Diff

... ... @@ -78,7 +78,7 @@
78 78 obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o
79 79 obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
80 80 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
81   -obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o
  81 +obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
82 82 obj-$(CONFIG_CRYPTO_LZO) += lzo.o
83 83 obj-$(CONFIG_CRYPTO_RNG2) += rng.o
84 84 obj-$(CONFIG_CRYPTO_RNG2) += krng.o
  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");