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