linux/net/ipv6/esp6.c
<<
>>
Prefs
   1/*
   2 * Copyright (C)2002 USAGI/WIDE Project
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License as published by
   6 * the Free Software Foundation; either version 2 of the License, or
   7 * (at your option) any later version.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write to the Free Software
  16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17 *
  18 * Authors
  19 *
  20 *      Mitsuru KANDA @USAGI       : IPv6 Support
  21 *      Kazunori MIYAZAWA @USAGI   :
  22 *      Kunihiro Ishiguro <kunihiro@ipinfusion.com>
  23 *
  24 *      This file is derived from net/ipv4/esp.c
  25 */
  26
  27#include <crypto/aead.h>
  28#include <crypto/authenc.h>
  29#include <linux/err.h>
  30#include <linux/module.h>
  31#include <net/ip.h>
  32#include <net/xfrm.h>
  33#include <net/esp.h>
  34#include <linux/scatterlist.h>
  35#include <linux/kernel.h>
  36#include <linux/pfkeyv2.h>
  37#include <linux/random.h>
  38#include <linux/slab.h>
  39#include <linux/spinlock.h>
  40#include <net/icmp.h>
  41#include <net/ipv6.h>
  42#include <net/protocol.h>
  43#include <linux/icmpv6.h>
  44
  45struct esp_skb_cb {
  46        struct xfrm_skb_cb xfrm;
  47        void *tmp;
  48};
  49
  50#define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0]))
  51
  52static u32 esp6_get_mtu(struct xfrm_state *x, int mtu);
  53
  54/*
  55 * Allocate an AEAD request structure with extra space for SG and IV.
  56 *
  57 * For alignment considerations the IV is placed at the front, followed
  58 * by the request and finally the SG list.
  59 *
  60 * TODO: Use spare space in skb for this where possible.
  61 */
  62static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags)
  63{
  64        unsigned int len;
  65
  66        len = crypto_aead_ivsize(aead);
  67        if (len) {
  68                len += crypto_aead_alignmask(aead) &
  69                       ~(crypto_tfm_ctx_alignment() - 1);
  70                len = ALIGN(len, crypto_tfm_ctx_alignment());
  71        }
  72
  73        len += sizeof(struct aead_givcrypt_request) + crypto_aead_reqsize(aead);
  74        len = ALIGN(len, __alignof__(struct scatterlist));
  75
  76        len += sizeof(struct scatterlist) * nfrags;
  77
  78        return kmalloc(len, GFP_ATOMIC);
  79}
  80
  81static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp)
  82{
  83        return crypto_aead_ivsize(aead) ?
  84               PTR_ALIGN((u8 *)tmp, crypto_aead_alignmask(aead) + 1) : tmp;
  85}
  86
  87static inline struct aead_givcrypt_request *esp_tmp_givreq(
  88        struct crypto_aead *aead, u8 *iv)
  89{
  90        struct aead_givcrypt_request *req;
  91
  92        req = (void *)PTR_ALIGN(iv + crypto_aead_ivsize(aead),
  93                                crypto_tfm_ctx_alignment());
  94        aead_givcrypt_set_tfm(req, aead);
  95        return req;
  96}
  97
  98static inline struct aead_request *esp_tmp_req(struct crypto_aead *aead, u8 *iv)
  99{
 100        struct aead_request *req;
 101
 102        req = (void *)PTR_ALIGN(iv + crypto_aead_ivsize(aead),
 103                                crypto_tfm_ctx_alignment());
 104        aead_request_set_tfm(req, aead);
 105        return req;
 106}
 107
 108static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead,
 109                                             struct aead_request *req)
 110{
 111        return (void *)ALIGN((unsigned long)(req + 1) +
 112                             crypto_aead_reqsize(aead),
 113                             __alignof__(struct scatterlist));
 114}
 115
 116static inline struct scatterlist *esp_givreq_sg(
 117        struct crypto_aead *aead, struct aead_givcrypt_request *req)
 118{
 119        return (void *)ALIGN((unsigned long)(req + 1) +
 120                             crypto_aead_reqsize(aead),
 121                             __alignof__(struct scatterlist));
 122}
 123
 124static void esp_output_done(struct crypto_async_request *base, int err)
 125{
 126        struct sk_buff *skb = base->data;
 127
 128        kfree(ESP_SKB_CB(skb)->tmp);
 129        xfrm_output_resume(skb, err);
 130}
 131
 132static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
 133{
 134        int err;
 135        struct ip_esp_hdr *esph;
 136        struct crypto_aead *aead;
 137        struct aead_givcrypt_request *req;
 138        struct scatterlist *sg;
 139        struct scatterlist *asg;
 140        struct sk_buff *trailer;
 141        void *tmp;
 142        int blksize;
 143        int clen;
 144        int alen;
 145        int plen;
 146        int tfclen;
 147        int nfrags;
 148        u8 *iv;
 149        u8 *tail;
 150        struct esp_data *esp = x->data;
 151
 152        /* skb is pure payload to encrypt */
 153        err = -ENOMEM;
 154
 155        aead = esp->aead;
 156        alen = crypto_aead_authsize(aead);
 157
 158        tfclen = 0;
 159        if (x->tfcpad) {
 160                struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb);
 161                u32 padto;
 162
 163                padto = min(x->tfcpad, esp6_get_mtu(x, dst->child_mtu_cached));
 164                if (skb->len < padto)
 165                        tfclen = padto - skb->len;
 166        }
 167        blksize = ALIGN(crypto_aead_blocksize(aead), 4);
 168        clen = ALIGN(skb->len + 2 + tfclen, blksize);
 169        if (esp->padlen)
 170                clen = ALIGN(clen, esp->padlen);
 171        plen = clen - skb->len - tfclen;
 172
 173        err = skb_cow_data(skb, tfclen + plen + alen, &trailer);
 174        if (err < 0)
 175                goto error;
 176        nfrags = err;
 177
 178        tmp = esp_alloc_tmp(aead, nfrags + 1);
 179        if (!tmp)
 180                goto error;
 181
 182        iv = esp_tmp_iv(aead, tmp);
 183        req = esp_tmp_givreq(aead, iv);
 184        asg = esp_givreq_sg(aead, req);
 185        sg = asg + 1;
 186
 187        /* Fill padding... */
 188        tail = skb_tail_pointer(trailer);
 189        if (tfclen) {
 190                memset(tail, 0, tfclen);
 191                tail += tfclen;
 192        }
 193        do {
 194                int i;
 195                for (i = 0; i < plen - 2; i++)
 196                        tail[i] = i + 1;
 197        } while (0);
 198        tail[plen - 2] = plen - 2;
 199        tail[plen - 1] = *skb_mac_header(skb);
 200        pskb_put(skb, trailer, clen - skb->len + alen);
 201
 202        skb_push(skb, -skb_network_offset(skb));
 203        esph = ip_esp_hdr(skb);
 204        *skb_mac_header(skb) = IPPROTO_ESP;
 205
 206        esph->spi = x->id.spi;
 207        esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output);
 208
 209        sg_init_table(sg, nfrags);
 210        skb_to_sgvec(skb, sg,
 211                     esph->enc_data + crypto_aead_ivsize(aead) - skb->data,
 212                     clen + alen);
 213        sg_init_one(asg, esph, sizeof(*esph));
 214
 215        aead_givcrypt_set_callback(req, 0, esp_output_done, skb);
 216        aead_givcrypt_set_crypt(req, sg, sg, clen, iv);
 217        aead_givcrypt_set_assoc(req, asg, sizeof(*esph));
 218        aead_givcrypt_set_giv(req, esph->enc_data,
 219                              XFRM_SKB_CB(skb)->seq.output);
 220
 221        ESP_SKB_CB(skb)->tmp = tmp;
 222        err = crypto_aead_givencrypt(req);
 223        if (err == -EINPROGRESS)
 224                goto error;
 225
 226        if (err == -EBUSY)
 227                err = NET_XMIT_DROP;
 228
 229        kfree(tmp);
 230
 231error:
 232        return err;
 233}
 234
 235static int esp_input_done2(struct sk_buff *skb, int err)
 236{
 237        struct xfrm_state *x = xfrm_input_state(skb);
 238        struct esp_data *esp = x->data;
 239        struct crypto_aead *aead = esp->aead;
 240        int alen = crypto_aead_authsize(aead);
 241        int hlen = sizeof(struct ip_esp_hdr) + crypto_aead_ivsize(aead);
 242        int elen = skb->len - hlen;
 243        int hdr_len = skb_network_header_len(skb);
 244        int padlen;
 245        u8 nexthdr[2];
 246
 247        kfree(ESP_SKB_CB(skb)->tmp);
 248
 249        if (unlikely(err))
 250                goto out;
 251
 252        if (skb_copy_bits(skb, skb->len - alen - 2, nexthdr, 2))
 253                BUG();
 254
 255        err = -EINVAL;
 256        padlen = nexthdr[0];
 257        if (padlen + 2 + alen >= elen) {
 258                LIMIT_NETDEBUG(KERN_WARNING "ipsec esp packet is garbage "
 259                               "padlen=%d, elen=%d\n", padlen + 2, elen - alen);
 260                goto out;
 261        }
 262
 263        /* ... check padding bits here. Silly. :-) */
 264
 265        pskb_trim(skb, skb->len - alen - padlen - 2);
 266        __skb_pull(skb, hlen);
 267        skb_set_transport_header(skb, -hdr_len);
 268
 269        err = nexthdr[1];
 270
 271        /* RFC4303: Drop dummy packets without any error */
 272        if (err == IPPROTO_NONE)
 273                err = -EINVAL;
 274
 275out:
 276        return err;
 277}
 278
 279static void esp_input_done(struct crypto_async_request *base, int err)
 280{
 281        struct sk_buff *skb = base->data;
 282
 283        xfrm_input_resume(skb, esp_input_done2(skb, err));
 284}
 285
 286static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
 287{
 288        struct ip_esp_hdr *esph;
 289        struct esp_data *esp = x->data;
 290        struct crypto_aead *aead = esp->aead;
 291        struct aead_request *req;
 292        struct sk_buff *trailer;
 293        int elen = skb->len - sizeof(*esph) - crypto_aead_ivsize(aead);
 294        int nfrags;
 295        int ret = 0;
 296        void *tmp;
 297        u8 *iv;
 298        struct scatterlist *sg;
 299        struct scatterlist *asg;
 300
 301        if (!pskb_may_pull(skb, sizeof(*esph) + crypto_aead_ivsize(aead))) {
 302                ret = -EINVAL;
 303                goto out;
 304        }
 305
 306        if (elen <= 0) {
 307                ret = -EINVAL;
 308                goto out;
 309        }
 310
 311        if ((nfrags = skb_cow_data(skb, 0, &trailer)) < 0) {
 312                ret = -EINVAL;
 313                goto out;
 314        }
 315
 316        ret = -ENOMEM;
 317        tmp = esp_alloc_tmp(aead, nfrags + 1);
 318        if (!tmp)
 319                goto out;
 320
 321        ESP_SKB_CB(skb)->tmp = tmp;
 322        iv = esp_tmp_iv(aead, tmp);
 323        req = esp_tmp_req(aead, iv);
 324        asg = esp_req_sg(aead, req);
 325        sg = asg + 1;
 326
 327        skb->ip_summed = CHECKSUM_NONE;
 328
 329        esph = (struct ip_esp_hdr *)skb->data;
 330
 331        /* Get ivec. This can be wrong, check against another impls. */
 332        iv = esph->enc_data;
 333
 334        sg_init_table(sg, nfrags);
 335        skb_to_sgvec(skb, sg, sizeof(*esph) + crypto_aead_ivsize(aead), elen);
 336        sg_init_one(asg, esph, sizeof(*esph));
 337
 338        aead_request_set_callback(req, 0, esp_input_done, skb);
 339        aead_request_set_crypt(req, sg, sg, elen, iv);
 340        aead_request_set_assoc(req, asg, sizeof(*esph));
 341
 342        ret = crypto_aead_decrypt(req);
 343        if (ret == -EINPROGRESS)
 344                goto out;
 345
 346        ret = esp_input_done2(skb, ret);
 347
 348out:
 349        return ret;
 350}
 351
 352static u32 esp6_get_mtu(struct xfrm_state *x, int mtu)
 353{
 354        struct esp_data *esp = x->data;
 355        u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4);
 356        u32 align = max_t(u32, blksize, esp->padlen);
 357        u32 rem;
 358
 359        mtu -= x->props.header_len + crypto_aead_authsize(esp->aead);
 360        rem = mtu & (align - 1);
 361        mtu &= ~(align - 1);
 362
 363        if (x->props.mode != XFRM_MODE_TUNNEL) {
 364                u32 padsize = ((blksize - 1) & 7) + 1;
 365                mtu -= blksize - padsize;
 366                mtu += min_t(u32, blksize - padsize, rem);
 367        }
 368
 369        return mtu - 2;
 370}
 371
 372static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 373                     u8 type, u8 code, int offset, __be32 info)
 374{
 375        struct net *net = dev_net(skb->dev);
 376        struct ipv6hdr *iph = (struct ipv6hdr*)skb->data;
 377        struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data + offset);
 378        struct xfrm_state *x;
 379
 380        if (type != ICMPV6_DEST_UNREACH &&
 381            type != ICMPV6_PKT_TOOBIG)
 382                return;
 383
 384        x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6);
 385        if (!x)
 386                return;
 387        printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%pI6\n",
 388                        ntohl(esph->spi), &iph->daddr);
 389        xfrm_state_put(x);
 390}
 391
 392static void esp6_destroy(struct xfrm_state *x)
 393{
 394        struct esp_data *esp = x->data;
 395
 396        if (!esp)
 397                return;
 398
 399        crypto_free_aead(esp->aead);
 400        kfree(esp);
 401}
 402
 403static int esp_init_aead(struct xfrm_state *x)
 404{
 405        struct esp_data *esp = x->data;
 406        struct crypto_aead *aead;
 407        int err;
 408
 409        aead = crypto_alloc_aead(x->aead->alg_name, 0, 0);
 410        err = PTR_ERR(aead);
 411        if (IS_ERR(aead))
 412                goto error;
 413
 414        esp->aead = aead;
 415
 416        err = crypto_aead_setkey(aead, x->aead->alg_key,
 417                                 (x->aead->alg_key_len + 7) / 8);
 418        if (err)
 419                goto error;
 420
 421        err = crypto_aead_setauthsize(aead, x->aead->alg_icv_len / 8);
 422        if (err)
 423                goto error;
 424
 425error:
 426        return err;
 427}
 428
 429static int esp_init_authenc(struct xfrm_state *x)
 430{
 431        struct esp_data *esp = x->data;
 432        struct crypto_aead *aead;
 433        struct crypto_authenc_key_param *param;
 434        struct rtattr *rta;
 435        char *key;
 436        char *p;
 437        char authenc_name[CRYPTO_MAX_ALG_NAME];
 438        unsigned int keylen;
 439        int err;
 440
 441        err = -EINVAL;
 442        if (x->ealg == NULL)
 443                goto error;
 444
 445        err = -ENAMETOOLONG;
 446        if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)",
 447                     x->aalg ? x->aalg->alg_name : "digest_null",
 448                     x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME)
 449                goto error;
 450
 451        aead = crypto_alloc_aead(authenc_name, 0, 0);
 452        err = PTR_ERR(aead);
 453        if (IS_ERR(aead))
 454                goto error;
 455
 456        esp->aead = aead;
 457
 458        keylen = (x->aalg ? (x->aalg->alg_key_len + 7) / 8 : 0) +
 459                 (x->ealg->alg_key_len + 7) / 8 + RTA_SPACE(sizeof(*param));
 460        err = -ENOMEM;
 461        key = kmalloc(keylen, GFP_KERNEL);
 462        if (!key)
 463                goto error;
 464
 465        p = key;
 466        rta = (void *)p;
 467        rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM;
 468        rta->rta_len = RTA_LENGTH(sizeof(*param));
 469        param = RTA_DATA(rta);
 470        p += RTA_SPACE(sizeof(*param));
 471
 472        if (x->aalg) {
 473                struct xfrm_algo_desc *aalg_desc;
 474
 475                memcpy(p, x->aalg->alg_key, (x->aalg->alg_key_len + 7) / 8);
 476                p += (x->aalg->alg_key_len + 7) / 8;
 477
 478                aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
 479                BUG_ON(!aalg_desc);
 480
 481                err = -EINVAL;
 482                if (aalg_desc->uinfo.auth.icv_fullbits/8 !=
 483                    crypto_aead_authsize(aead)) {
 484                        NETDEBUG(KERN_INFO "ESP: %s digestsize %u != %hu\n",
 485                                 x->aalg->alg_name,
 486                                 crypto_aead_authsize(aead),
 487                                 aalg_desc->uinfo.auth.icv_fullbits/8);
 488                        goto free_key;
 489                }
 490
 491                err = crypto_aead_setauthsize(
 492                        aead, x->aalg->alg_trunc_len / 8);
 493                if (err)
 494                        goto free_key;
 495        }
 496
 497        param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8);
 498        memcpy(p, x->ealg->alg_key, (x->ealg->alg_key_len + 7) / 8);
 499
 500        err = crypto_aead_setkey(aead, key, keylen);
 501
 502free_key:
 503        kfree(key);
 504
 505error:
 506        return err;
 507}
 508
 509static int esp6_init_state(struct xfrm_state *x)
 510{
 511        struct esp_data *esp;
 512        struct crypto_aead *aead;
 513        u32 align;
 514        int err;
 515
 516        if (x->encap)
 517                return -EINVAL;
 518
 519        esp = kzalloc(sizeof(*esp), GFP_KERNEL);
 520        if (esp == NULL)
 521                return -ENOMEM;
 522
 523        x->data = esp;
 524
 525        if (x->aead)
 526                err = esp_init_aead(x);
 527        else
 528                err = esp_init_authenc(x);
 529
 530        if (err)
 531                goto error;
 532
 533        aead = esp->aead;
 534
 535        esp->padlen = 0;
 536
 537        x->props.header_len = sizeof(struct ip_esp_hdr) +
 538                              crypto_aead_ivsize(aead);
 539        switch (x->props.mode) {
 540        case XFRM_MODE_BEET:
 541                if (x->sel.family != AF_INET6)
 542                        x->props.header_len += IPV4_BEET_PHMAXLEN +
 543                                               (sizeof(struct ipv6hdr) - sizeof(struct iphdr));
 544                break;
 545        case XFRM_MODE_TRANSPORT:
 546                break;
 547        case XFRM_MODE_TUNNEL:
 548                x->props.header_len += sizeof(struct ipv6hdr);
 549                break;
 550        default:
 551                goto error;
 552        }
 553
 554        align = ALIGN(crypto_aead_blocksize(aead), 4);
 555        if (esp->padlen)
 556                align = max_t(u32, align, esp->padlen);
 557        x->props.trailer_len = align + 1 + crypto_aead_authsize(esp->aead);
 558
 559error:
 560        return err;
 561}
 562
 563static const struct xfrm_type esp6_type =
 564{
 565        .description    = "ESP6",
 566        .owner          = THIS_MODULE,
 567        .proto          = IPPROTO_ESP,
 568        .flags          = XFRM_TYPE_REPLAY_PROT,
 569        .init_state     = esp6_init_state,
 570        .destructor     = esp6_destroy,
 571        .get_mtu        = esp6_get_mtu,
 572        .input          = esp6_input,
 573        .output         = esp6_output,
 574        .hdr_offset     = xfrm6_find_1stfragopt,
 575};
 576
 577static const struct inet6_protocol esp6_protocol = {
 578        .handler        =       xfrm6_rcv,
 579        .err_handler    =       esp6_err,
 580        .flags          =       INET6_PROTO_NOPOLICY,
 581};
 582
 583static int __init esp6_init(void)
 584{
 585        if (xfrm_register_type(&esp6_type, AF_INET6) < 0) {
 586                printk(KERN_INFO "ipv6 esp init: can't add xfrm type\n");
 587                return -EAGAIN;
 588        }
 589        if (inet6_add_protocol(&esp6_protocol, IPPROTO_ESP) < 0) {
 590                printk(KERN_INFO "ipv6 esp init: can't add protocol\n");
 591                xfrm_unregister_type(&esp6_type, AF_INET6);
 592                return -EAGAIN;
 593        }
 594
 595        return 0;
 596}
 597
 598static void __exit esp6_fini(void)
 599{
 600        if (inet6_del_protocol(&esp6_protocol, IPPROTO_ESP) < 0)
 601                printk(KERN_INFO "ipv6 esp close: can't remove protocol\n");
 602        if (xfrm_unregister_type(&esp6_type, AF_INET6) < 0)
 603                printk(KERN_INFO "ipv6 esp close: can't remove xfrm type\n");
 604}
 605
 606module_init(esp6_init);
 607module_exit(esp6_fini);
 608
 609MODULE_LICENSE("GPL");
 610MODULE_ALIAS_XFRM_TYPE(AF_INET6, XFRM_PROTO_ESP);
 611