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        unsigned int authkeylen;
  63        unsigned int enckeylen;
  64        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
  65        struct crypto_ahash *auth = ctx->auth;
  66        struct crypto_ablkcipher *enc = ctx->enc;
  67        struct rtattr *rta = (void *)key;
  68        struct crypto_authenc_key_param *param;
  69        int err = -EINVAL;
  70
  71        if (!RTA_OK(rta, keylen))
  72                goto badkey;
  73        if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
  74                goto badkey;
  75        if (RTA_PAYLOAD(rta) < sizeof(*param))
  76                goto badkey;
  77
  78        param = RTA_DATA(rta);
  79        enckeylen = be32_to_cpu(param->enckeylen);
  80
  81        key += RTA_ALIGN(rta->rta_len);
  82        keylen -= RTA_ALIGN(rta->rta_len);
  83
  84        if (keylen < enckeylen)
  85                goto badkey;
  86
  87        authkeylen = keylen - enckeylen;
  88
  89        crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
  90        crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc_esn) &
  91                                     CRYPTO_TFM_REQ_MASK);
  92        err = crypto_ahash_setkey(auth, key, authkeylen);
  93        crypto_aead_set_flags(authenc_esn, crypto_ahash_get_flags(auth) &
  94                                           CRYPTO_TFM_RES_MASK);
  95
  96        if (err)
  97                goto out;
  98
  99        crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK);
 100        crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc_esn) &
 101                                         CRYPTO_TFM_REQ_MASK);
 102        err = crypto_ablkcipher_setkey(enc, key + authkeylen, enckeylen);
 103        crypto_aead_set_flags(authenc_esn, crypto_ablkcipher_get_flags(enc) &
 104                                           CRYPTO_TFM_RES_MASK);
 105
 106out:
 107        return err;
 108
 109badkey:
 110        crypto_aead_set_flags(authenc_esn, CRYPTO_TFM_RES_BAD_KEY_LEN);
 111        goto out;
 112}
 113
 114static void authenc_esn_geniv_ahash_update_done(struct crypto_async_request *areq,
 115                                                int err)
 116{
 117        struct aead_request *req = areq->data;
 118        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 119        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 120        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 121        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
 122
 123        if (err)
 124                goto out;
 125
 126        ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
 127                                areq_ctx->cryptlen);
 128        ahash_request_set_callback(ahreq, aead_request_flags(req) &
 129                                          CRYPTO_TFM_REQ_MAY_SLEEP,
 130                                   areq_ctx->update_complete2, req);
 131
 132        err = crypto_ahash_update(ahreq);
 133        if (err)
 134                goto out;
 135
 136        ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
 137                                areq_ctx->trailen);
 138        ahash_request_set_callback(ahreq, aead_request_flags(req) &
 139                                          CRYPTO_TFM_REQ_MAY_SLEEP,
 140                                   areq_ctx->complete, req);
 141
 142        err = crypto_ahash_finup(ahreq);
 143        if (err)
 144                goto out;
 145
 146        scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
 147                                 areq_ctx->cryptlen,
 148                                 crypto_aead_authsize(authenc_esn), 1);
 149
 150out:
 151        authenc_esn_request_complete(req, err);
 152}
 153
 154static void authenc_esn_geniv_ahash_update_done2(struct crypto_async_request *areq,
 155                                                 int err)
 156{
 157        struct aead_request *req = areq->data;
 158        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 159        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 160        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 161        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
 162
 163        if (err)
 164                goto out;
 165
 166        ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
 167                                areq_ctx->trailen);
 168        ahash_request_set_callback(ahreq, aead_request_flags(req) &
 169                                          CRYPTO_TFM_REQ_MAY_SLEEP,
 170                                   areq_ctx->complete, req);
 171
 172        err = crypto_ahash_finup(ahreq);
 173        if (err)
 174                goto out;
 175
 176        scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
 177                                 areq_ctx->cryptlen,
 178                                 crypto_aead_authsize(authenc_esn), 1);
 179
 180out:
 181        authenc_esn_request_complete(req, err);
 182}
 183
 184
 185static void authenc_esn_geniv_ahash_done(struct crypto_async_request *areq,
 186                                         int err)
 187{
 188        struct aead_request *req = areq->data;
 189        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 190        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 191        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 192        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
 193
 194        if (err)
 195                goto out;
 196
 197        scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
 198                                 areq_ctx->cryptlen,
 199                                 crypto_aead_authsize(authenc_esn), 1);
 200
 201out:
 202        aead_request_complete(req, err);
 203}
 204
 205
 206static void authenc_esn_verify_ahash_update_done(struct crypto_async_request *areq,
 207                                                 int err)
 208{
 209        u8 *ihash;
 210        unsigned int authsize;
 211        struct ablkcipher_request *abreq;
 212        struct aead_request *req = areq->data;
 213        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 214        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 215        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 216        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
 217        unsigned int cryptlen = req->cryptlen;
 218
 219        if (err)
 220                goto out;
 221
 222        ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
 223                                areq_ctx->cryptlen);
 224
 225        ahash_request_set_callback(ahreq,
 226                                   aead_request_flags(req) &
 227                                   CRYPTO_TFM_REQ_MAY_SLEEP,
 228                                   areq_ctx->update_complete2, req);
 229
 230        err = crypto_ahash_update(ahreq);
 231        if (err)
 232                goto out;
 233
 234        ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
 235                                areq_ctx->trailen);
 236        ahash_request_set_callback(ahreq, aead_request_flags(req) &
 237                                          CRYPTO_TFM_REQ_MAY_SLEEP,
 238                                   areq_ctx->complete, req);
 239
 240        err = crypto_ahash_finup(ahreq);
 241        if (err)
 242                goto out;
 243
 244        authsize = crypto_aead_authsize(authenc_esn);
 245        cryptlen -= authsize;
 246        ihash = ahreq->result + authsize;
 247        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
 248                                 authsize, 0);
 249
 250        err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
 251        if (err)
 252                goto out;
 253
 254        abreq = aead_request_ctx(req);
 255        ablkcipher_request_set_tfm(abreq, ctx->enc);
 256        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
 257                                        req->base.complete, req->base.data);
 258        ablkcipher_request_set_crypt(abreq, req->src, req->dst,
 259                                     cryptlen, req->iv);
 260
 261        err = crypto_ablkcipher_decrypt(abreq);
 262
 263out:
 264        authenc_esn_request_complete(req, err);
 265}
 266
 267static void authenc_esn_verify_ahash_update_done2(struct crypto_async_request *areq,
 268                                                  int err)
 269{
 270        u8 *ihash;
 271        unsigned int authsize;
 272        struct ablkcipher_request *abreq;
 273        struct aead_request *req = areq->data;
 274        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 275        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 276        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 277        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
 278        unsigned int cryptlen = req->cryptlen;
 279
 280        if (err)
 281                goto out;
 282
 283        ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
 284                                areq_ctx->trailen);
 285        ahash_request_set_callback(ahreq, aead_request_flags(req) &
 286                                          CRYPTO_TFM_REQ_MAY_SLEEP,
 287                                   areq_ctx->complete, req);
 288
 289        err = crypto_ahash_finup(ahreq);
 290        if (err)
 291                goto out;
 292
 293        authsize = crypto_aead_authsize(authenc_esn);
 294        cryptlen -= authsize;
 295        ihash = ahreq->result + authsize;
 296        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
 297                                 authsize, 0);
 298
 299        err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
 300        if (err)
 301                goto out;
 302
 303        abreq = aead_request_ctx(req);
 304        ablkcipher_request_set_tfm(abreq, ctx->enc);
 305        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
 306                                        req->base.complete, req->base.data);
 307        ablkcipher_request_set_crypt(abreq, req->src, req->dst,
 308                                     cryptlen, req->iv);
 309
 310        err = crypto_ablkcipher_decrypt(abreq);
 311
 312out:
 313        authenc_esn_request_complete(req, err);
 314}
 315
 316
 317static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
 318                                          int err)
 319{
 320        u8 *ihash;
 321        unsigned int authsize;
 322        struct ablkcipher_request *abreq;
 323        struct aead_request *req = areq->data;
 324        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 325        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 326        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 327        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
 328        unsigned int cryptlen = req->cryptlen;
 329
 330        if (err)
 331                goto out;
 332
 333        authsize = crypto_aead_authsize(authenc_esn);
 334        cryptlen -= authsize;
 335        ihash = ahreq->result + authsize;
 336        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
 337                                 authsize, 0);
 338
 339        err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
 340        if (err)
 341                goto out;
 342
 343        abreq = aead_request_ctx(req);
 344        ablkcipher_request_set_tfm(abreq, ctx->enc);
 345        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
 346                                        req->base.complete, req->base.data);
 347        ablkcipher_request_set_crypt(abreq, req->src, req->dst,
 348                                     cryptlen, req->iv);
 349
 350        err = crypto_ablkcipher_decrypt(abreq);
 351
 352out:
 353        authenc_esn_request_complete(req, err);
 354}
 355
 356static u8 *crypto_authenc_esn_ahash(struct aead_request *req,
 357                                    unsigned int flags)
 358{
 359        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 360        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 361        struct crypto_ahash *auth = ctx->auth;
 362        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 363        struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
 364        u8 *hash = areq_ctx->tail;
 365        int err;
 366
 367        hash = (u8 *)ALIGN((unsigned long)hash + crypto_ahash_alignmask(auth),
 368                            crypto_ahash_alignmask(auth) + 1);
 369
 370        ahash_request_set_tfm(ahreq, auth);
 371
 372        err = crypto_ahash_init(ahreq);
 373        if (err)
 374                return ERR_PTR(err);
 375
 376        ahash_request_set_crypt(ahreq, areq_ctx->hsg, hash, areq_ctx->headlen);
 377        ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
 378                                   areq_ctx->update_complete, req);
 379
 380        err = crypto_ahash_update(ahreq);
 381        if (err)
 382                return ERR_PTR(err);
 383
 384        ahash_request_set_crypt(ahreq, areq_ctx->sg, hash, areq_ctx->cryptlen);
 385        ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
 386                                   areq_ctx->update_complete2, req);
 387
 388        err = crypto_ahash_update(ahreq);
 389        if (err)
 390                return ERR_PTR(err);
 391
 392        ahash_request_set_crypt(ahreq, areq_ctx->tsg, hash,
 393                                areq_ctx->trailen);
 394        ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
 395                                   areq_ctx->complete, req);
 396
 397        err = crypto_ahash_finup(ahreq);
 398        if (err)
 399                return ERR_PTR(err);
 400
 401        return hash;
 402}
 403
 404static int crypto_authenc_esn_genicv(struct aead_request *req, u8 *iv,
 405                                     unsigned int flags)
 406{
 407        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 408        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 409        struct scatterlist *dst = req->dst;
 410        struct scatterlist *assoc = req->assoc;
 411        struct scatterlist *cipher = areq_ctx->cipher;
 412        struct scatterlist *hsg = areq_ctx->hsg;
 413        struct scatterlist *tsg = areq_ctx->tsg;
 414        struct scatterlist *assoc1;
 415        struct scatterlist *assoc2;
 416        unsigned int ivsize = crypto_aead_ivsize(authenc_esn);
 417        unsigned int cryptlen = req->cryptlen;
 418        struct page *dstp;
 419        u8 *vdst;
 420        u8 *hash;
 421
 422        dstp = sg_page(dst);
 423        vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;
 424
 425        if (ivsize) {
 426                sg_init_table(cipher, 2);
 427                sg_set_buf(cipher, iv, ivsize);
 428                scatterwalk_crypto_chain(cipher, dst, vdst == iv + ivsize, 2);
 429                dst = cipher;
 430                cryptlen += ivsize;
 431        }
 432
 433        if (sg_is_last(assoc))
 434                return -EINVAL;
 435
 436        assoc1 = assoc + 1;
 437        if (sg_is_last(assoc1))
 438                return -EINVAL;
 439
 440        assoc2 = assoc + 2;
 441        if (!sg_is_last(assoc2))
 442                return -EINVAL;
 443
 444        sg_init_table(hsg, 2);
 445        sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset);
 446        sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset);
 447
 448        sg_init_table(tsg, 1);
 449        sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
 450
 451        areq_ctx->cryptlen = cryptlen;
 452        areq_ctx->headlen = assoc->length + assoc2->length;
 453        areq_ctx->trailen = assoc1->length;
 454        areq_ctx->sg = dst;
 455
 456        areq_ctx->complete = authenc_esn_geniv_ahash_done;
 457        areq_ctx->update_complete = authenc_esn_geniv_ahash_update_done;
 458        areq_ctx->update_complete2 = authenc_esn_geniv_ahash_update_done2;
 459
 460        hash = crypto_authenc_esn_ahash(req, flags);
 461        if (IS_ERR(hash))
 462                return PTR_ERR(hash);
 463
 464        scatterwalk_map_and_copy(hash, dst, cryptlen,
 465                                 crypto_aead_authsize(authenc_esn), 1);
 466        return 0;
 467}
 468
 469
 470static void crypto_authenc_esn_encrypt_done(struct crypto_async_request *req,
 471                                            int err)
 472{
 473        struct aead_request *areq = req->data;
 474
 475        if (!err) {
 476                struct crypto_aead *authenc_esn = crypto_aead_reqtfm(areq);
 477                struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 478                struct ablkcipher_request *abreq = aead_request_ctx(areq);
 479                u8 *iv = (u8 *)(abreq + 1) +
 480                         crypto_ablkcipher_reqsize(ctx->enc);
 481
 482                err = crypto_authenc_esn_genicv(areq, iv, 0);
 483        }
 484
 485        authenc_esn_request_complete(areq, err);
 486}
 487
 488static int crypto_authenc_esn_encrypt(struct aead_request *req)
 489{
 490        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 491        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 492        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 493        struct crypto_ablkcipher *enc = ctx->enc;
 494        struct scatterlist *dst = req->dst;
 495        unsigned int cryptlen = req->cryptlen;
 496        struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
 497                                                    + ctx->reqoff);
 498        u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(enc);
 499        int err;
 500
 501        ablkcipher_request_set_tfm(abreq, enc);
 502        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
 503                                        crypto_authenc_esn_encrypt_done, req);
 504        ablkcipher_request_set_crypt(abreq, req->src, dst, cryptlen, req->iv);
 505
 506        memcpy(iv, req->iv, crypto_aead_ivsize(authenc_esn));
 507
 508        err = crypto_ablkcipher_encrypt(abreq);
 509        if (err)
 510                return err;
 511
 512        return crypto_authenc_esn_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
 513}
 514
 515static void crypto_authenc_esn_givencrypt_done(struct crypto_async_request *req,
 516                                               int err)
 517{
 518        struct aead_request *areq = req->data;
 519
 520        if (!err) {
 521                struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
 522
 523                err = crypto_authenc_esn_genicv(areq, greq->giv, 0);
 524        }
 525
 526        authenc_esn_request_complete(areq, err);
 527}
 528
 529static int crypto_authenc_esn_givencrypt(struct aead_givcrypt_request *req)
 530{
 531        struct crypto_aead *authenc_esn = aead_givcrypt_reqtfm(req);
 532        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 533        struct aead_request *areq = &req->areq;
 534        struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
 535        u8 *iv = req->giv;
 536        int err;
 537
 538        skcipher_givcrypt_set_tfm(greq, ctx->enc);
 539        skcipher_givcrypt_set_callback(greq, aead_request_flags(areq),
 540                                       crypto_authenc_esn_givencrypt_done, areq);
 541        skcipher_givcrypt_set_crypt(greq, areq->src, areq->dst, areq->cryptlen,
 542                                    areq->iv);
 543        skcipher_givcrypt_set_giv(greq, iv, req->seq);
 544
 545        err = crypto_skcipher_givencrypt(greq);
 546        if (err)
 547                return err;
 548
 549        return crypto_authenc_esn_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
 550}
 551
 552static int crypto_authenc_esn_verify(struct aead_request *req)
 553{
 554        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 555        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 556        u8 *ohash;
 557        u8 *ihash;
 558        unsigned int authsize;
 559
 560        areq_ctx->complete = authenc_esn_verify_ahash_done;
 561        areq_ctx->update_complete = authenc_esn_verify_ahash_update_done;
 562
 563        ohash = crypto_authenc_esn_ahash(req, CRYPTO_TFM_REQ_MAY_SLEEP);
 564        if (IS_ERR(ohash))
 565                return PTR_ERR(ohash);
 566
 567        authsize = crypto_aead_authsize(authenc_esn);
 568        ihash = ohash + authsize;
 569        scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
 570                                 authsize, 0);
 571        return memcmp(ihash, ohash, authsize) ? -EBADMSG : 0;
 572}
 573
 574static int crypto_authenc_esn_iverify(struct aead_request *req, u8 *iv,
 575                                      unsigned int cryptlen)
 576{
 577        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 578        struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
 579        struct scatterlist *src = req->src;
 580        struct scatterlist *assoc = req->assoc;
 581        struct scatterlist *cipher = areq_ctx->cipher;
 582        struct scatterlist *hsg = areq_ctx->hsg;
 583        struct scatterlist *tsg = areq_ctx->tsg;
 584        struct scatterlist *assoc1;
 585        struct scatterlist *assoc2;
 586        unsigned int ivsize = crypto_aead_ivsize(authenc_esn);
 587        struct page *srcp;
 588        u8 *vsrc;
 589
 590        srcp = sg_page(src);
 591        vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;
 592
 593        if (ivsize) {
 594                sg_init_table(cipher, 2);
 595                sg_set_buf(cipher, iv, ivsize);
 596                scatterwalk_crypto_chain(cipher, src, vsrc == iv + ivsize, 2);
 597                src = cipher;
 598                cryptlen += ivsize;
 599        }
 600
 601        if (sg_is_last(assoc))
 602                return -EINVAL;
 603
 604        assoc1 = assoc + 1;
 605        if (sg_is_last(assoc1))
 606                return -EINVAL;
 607
 608        assoc2 = assoc + 2;
 609        if (!sg_is_last(assoc2))
 610                return -EINVAL;
 611
 612        sg_init_table(hsg, 2);
 613        sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset);
 614        sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset);
 615
 616        sg_init_table(tsg, 1);
 617        sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
 618
 619        areq_ctx->cryptlen = cryptlen;
 620        areq_ctx->headlen = assoc->length + assoc2->length;
 621        areq_ctx->trailen = assoc1->length;
 622        areq_ctx->sg = src;
 623
 624        areq_ctx->complete = authenc_esn_verify_ahash_done;
 625        areq_ctx->update_complete = authenc_esn_verify_ahash_update_done;
 626        areq_ctx->update_complete2 = authenc_esn_verify_ahash_update_done2;
 627
 628        return crypto_authenc_esn_verify(req);
 629}
 630
 631static int crypto_authenc_esn_decrypt(struct aead_request *req)
 632{
 633        struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
 634        struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
 635        struct ablkcipher_request *abreq = aead_request_ctx(req);
 636        unsigned int cryptlen = req->cryptlen;
 637        unsigned int authsize = crypto_aead_authsize(authenc_esn);
 638        u8 *iv = req->iv;
 639        int err;
 640
 641        if (cryptlen < authsize)
 642                return -EINVAL;
 643        cryptlen -= authsize;
 644
 645        err = crypto_authenc_esn_iverify(req, iv, cryptlen);
 646        if (err)
 647                return err;
 648
 649        ablkcipher_request_set_tfm(abreq, ctx->enc);
 650        ablkcipher_request_set_callback(abreq, aead_request_flags(req),
 651                                        req->base.complete, req->base.data);
 652        ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, iv);
 653
 654        return crypto_ablkcipher_decrypt(abreq);
 655}
 656
 657static int crypto_authenc_esn_init_tfm(struct crypto_tfm *tfm)
 658{
 659        struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
 660        struct authenc_esn_instance_ctx *ictx = crypto_instance_ctx(inst);
 661        struct crypto_authenc_esn_ctx *ctx = crypto_tfm_ctx(tfm);
 662        struct crypto_ahash *auth;
 663        struct crypto_ablkcipher *enc;
 664        int err;
 665
 666        auth = crypto_spawn_ahash(&ictx->auth);
 667        if (IS_ERR(auth))
 668                return PTR_ERR(auth);
 669
 670        enc = crypto_spawn_skcipher(&ictx->enc);
 671        err = PTR_ERR(enc);
 672        if (IS_ERR(enc))
 673                goto err_free_ahash;
 674
 675        ctx->auth = auth;
 676        ctx->enc = enc;
 677
 678        ctx->reqoff = ALIGN(2 * crypto_ahash_digestsize(auth) +
 679                            crypto_ahash_alignmask(auth),
 680                            crypto_ahash_alignmask(auth) + 1) +
 681                      crypto_ablkcipher_ivsize(enc);
 682
 683        tfm->crt_aead.reqsize = sizeof(struct authenc_esn_request_ctx) +
 684                                ctx->reqoff +
 685                                max_t(unsigned int,
 686                                crypto_ahash_reqsize(auth) +
 687                                sizeof(struct ahash_request),
 688                                sizeof(struct skcipher_givcrypt_request) +
 689                                crypto_ablkcipher_reqsize(enc));
 690
 691        return 0;
 692
 693err_free_ahash:
 694        crypto_free_ahash(auth);
 695        return err;
 696}
 697
 698static void crypto_authenc_esn_exit_tfm(struct crypto_tfm *tfm)
 699{
 700        struct crypto_authenc_esn_ctx *ctx = crypto_tfm_ctx(tfm);
 701
 702        crypto_free_ahash(ctx->auth);
 703        crypto_free_ablkcipher(ctx->enc);
 704}
 705
 706static struct crypto_instance *crypto_authenc_esn_alloc(struct rtattr **tb)
 707{
 708        struct crypto_attr_type *algt;
 709        struct crypto_instance *inst;
 710        struct hash_alg_common *auth;
 711        struct crypto_alg *auth_base;
 712        struct crypto_alg *enc;
 713        struct authenc_esn_instance_ctx *ctx;
 714        const char *enc_name;
 715        int err;
 716
 717        algt = crypto_get_attr_type(tb);
 718        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
 789out:
 790        crypto_mod_put(auth_base);
 791        return inst;
 792
 793err_drop_enc:
 794        crypto_drop_skcipher(&ctx->enc);
 795err_drop_auth:
 796        crypto_drop_ahash(&ctx->auth);
 797err_free_inst:
 798        kfree(inst);
 799out_put_auth:
 800        inst = ERR_PTR(err);
 801        goto out;
 802}
 803
 804static 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
 813static 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
 820static int __init crypto_authenc_esn_module_init(void)
 821{
 822        return crypto_register_template(&crypto_authenc_esn_tmpl);
 823}
 824
 825static void __exit crypto_authenc_esn_module_exit(void)
 826{
 827        crypto_unregister_template(&crypto_authenc_esn_tmpl);
 828}
 829
 830module_init(crypto_authenc_esn_module_init);
 831module_exit(crypto_authenc_esn_module_exit);
 832
 833MODULE_LICENSE("GPL");
 834MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
 835MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers");
 836
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.