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


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

FreeBSD/Linux Kernel Cross Reference
sys/bsd/netinet6/esp_core.c

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

    1 /*      $FreeBSD: src/sys/netinet6/esp_core.c,v 1.1.2.4 2002/03/26 10:12:29 ume Exp $   */
    2 /*      $KAME: esp_core.c,v 1.50 2000/11/02 12:27:38 itojun Exp $       */
    3 
    4 /*
    5  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. Neither the name of the project nor the names of its contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 #define _IP_VHL
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/malloc.h>
   38 #include <sys/mbuf.h>
   39 #include <sys/domain.h>
   40 #include <sys/protosw.h>
   41 #include <sys/socket.h>
   42 #include <sys/errno.h>
   43 #include <sys/time.h>
   44 #include <sys/kernel.h>
   45 #include <sys/syslog.h>
   46 
   47 #include <net/if.h>
   48 #include <net/route.h>
   49 
   50 #include <netinet/in.h>
   51 #include <netinet/in_var.h>
   52 #if INET6
   53 #include <netinet/ip6.h>
   54 #include <netinet6/ip6_var.h>
   55 #include <netinet/icmp6.h>
   56 #endif
   57 
   58 #include <netinet6/ipsec.h>
   59 #if INET6
   60 #include <netinet6/ipsec6.h>
   61 #endif
   62 #include <netinet6/ah.h>
   63 #if INET6
   64 #include <netinet6/ah6.h>
   65 #endif
   66 #include <netinet6/esp.h>
   67 #if INET6
   68 #include <netinet6/esp6.h>
   69 #endif
   70 #include <netinet6/esp_rijndael.h>
   71 #include <net/pfkeyv2.h>
   72 #include <netkey/keydb.h>
   73 #include <netkey/key.h>
   74 #include <crypto/des/des.h>
   75 #include <crypto/blowfish/blowfish.h>
   76 #include <crypto/cast128/cast128.h>
   77 
   78 #include <net/net_osdep.h>
   79 
   80 #include <sys/kdebug.h>
   81 #define DBG_LAYER_BEG           NETDBG_CODE(DBG_NETIPSEC, 1)
   82 #define DBG_LAYER_END           NETDBG_CODE(DBG_NETIPSEC, 3)
   83 #define DBG_FNC_ESPAUTH         NETDBG_CODE(DBG_NETIPSEC, (8 << 8))
   84 
   85 static int esp_null_mature __P((struct secasvar *));
   86 static int esp_null_decrypt __P((struct mbuf *, size_t,
   87         struct secasvar *, const struct esp_algorithm *, int));
   88 static int esp_null_encrypt __P((struct mbuf *, size_t, size_t,
   89         struct secasvar *, const struct esp_algorithm *, int));
   90 static int esp_descbc_mature __P((struct secasvar *));
   91 static int esp_descbc_ivlen __P((const struct esp_algorithm *,
   92         struct secasvar *));
   93 static int esp_des_schedule __P((const struct esp_algorithm *,
   94         struct secasvar *));
   95 static int esp_des_schedlen __P((const struct esp_algorithm *));
   96 static int esp_des_blockdecrypt __P((const struct esp_algorithm *,
   97         struct secasvar *, u_int8_t *, u_int8_t *));
   98 static int esp_des_blockencrypt __P((const struct esp_algorithm *,
   99         struct secasvar *, u_int8_t *, u_int8_t *));
  100 static int esp_cbc_mature __P((struct secasvar *));
  101 static int esp_blowfish_schedule __P((const struct esp_algorithm *,
  102         struct secasvar *));
  103 static int esp_blowfish_schedlen __P((const struct esp_algorithm *));
  104 static int esp_blowfish_blockdecrypt __P((const struct esp_algorithm *,
  105         struct secasvar *, u_int8_t *, u_int8_t *));
  106 static int esp_blowfish_blockencrypt __P((const struct esp_algorithm *,
  107         struct secasvar *, u_int8_t *, u_int8_t *));
  108 static int esp_cast128_schedule __P((const struct esp_algorithm *,
  109         struct secasvar *));
  110 static int esp_cast128_schedlen __P((const struct esp_algorithm *));
  111 static int esp_cast128_blockdecrypt __P((const struct esp_algorithm *,
  112         struct secasvar *, u_int8_t *, u_int8_t *));
  113 static int esp_cast128_blockencrypt __P((const struct esp_algorithm *,
  114         struct secasvar *, u_int8_t *, u_int8_t *));
  115 static int esp_3des_schedule __P((const struct esp_algorithm *,
  116         struct secasvar *));
  117 static int esp_3des_schedlen __P((const struct esp_algorithm *));
  118 static int esp_3des_blockdecrypt __P((const struct esp_algorithm *,
  119         struct secasvar *, u_int8_t *, u_int8_t *));
  120 static int esp_3des_blockencrypt __P((const struct esp_algorithm *,
  121         struct secasvar *, u_int8_t *, u_int8_t *));
  122 static int esp_common_ivlen __P((const struct esp_algorithm *,
  123         struct secasvar *));
  124 static int esp_cbc_decrypt __P((struct mbuf *, size_t,
  125         struct secasvar *, const struct esp_algorithm *, int));
  126 static int esp_cbc_encrypt __P((struct mbuf *, size_t, size_t,
  127         struct secasvar *, const struct esp_algorithm *, int));
  128 
  129 #define MAXIVLEN        16
  130 
  131 static const struct esp_algorithm esp_algorithms[] = {
  132         { 8, -1, esp_descbc_mature, 64, 64, esp_des_schedlen,
  133                 "des-cbc",
  134                 esp_descbc_ivlen, esp_cbc_decrypt,
  135                 esp_cbc_encrypt, esp_des_schedule,
  136                 esp_des_blockdecrypt, esp_des_blockencrypt, },
  137         { 8, 8, esp_cbc_mature, 192, 192, esp_3des_schedlen,
  138                 "3des-cbc",
  139                 esp_common_ivlen, esp_cbc_decrypt,
  140                 esp_cbc_encrypt, esp_3des_schedule,
  141                 esp_3des_blockdecrypt, esp_3des_blockencrypt, },
  142         { 1, 0, esp_null_mature, 0, 2048, 0, "null",
  143                 esp_common_ivlen, esp_null_decrypt,
  144                 esp_null_encrypt, NULL, },
  145         { 8, 8, esp_cbc_mature, 40, 448, esp_blowfish_schedlen, "blowfish-cbc",
  146                 esp_common_ivlen, esp_cbc_decrypt,
  147                 esp_cbc_encrypt, esp_blowfish_schedule,
  148                 esp_blowfish_blockdecrypt, esp_blowfish_blockencrypt, },
  149         { 8, 8, esp_cbc_mature, 40, 128, esp_cast128_schedlen,
  150                 "cast128-cbc",
  151                 esp_common_ivlen, esp_cbc_decrypt,
  152                 esp_cbc_encrypt, esp_cast128_schedule,
  153                 esp_cast128_blockdecrypt, esp_cast128_blockencrypt, },
  154         { 16, 16, esp_cbc_mature, 128, 256, esp_rijndael_schedlen,
  155                 "rijndael-cbc",
  156                 esp_common_ivlen, esp_cbc_decrypt,
  157                 esp_cbc_encrypt, esp_rijndael_schedule,
  158                 esp_rijndael_blockdecrypt, esp_rijndael_blockencrypt },
  159 };
  160 
  161 const struct esp_algorithm *
  162 esp_algorithm_lookup(idx)
  163         int idx;
  164 {
  165 
  166         switch (idx) {
  167         case SADB_EALG_DESCBC:
  168                 return &esp_algorithms[0];
  169         case SADB_EALG_3DESCBC:
  170                 return &esp_algorithms[1];
  171         case SADB_EALG_NULL:
  172                 return &esp_algorithms[2];
  173         case SADB_X_EALG_BLOWFISHCBC:
  174                 return &esp_algorithms[3];
  175         case SADB_X_EALG_CAST128CBC:
  176                 return &esp_algorithms[4];
  177         case SADB_X_EALG_RIJNDAELCBC:
  178                 return &esp_algorithms[5];
  179         default:
  180                 return NULL;
  181         }
  182 }
  183 
  184 int
  185 esp_max_ivlen()
  186 {
  187         int idx;
  188         int ivlen;
  189 
  190         ivlen = 0;
  191         for (idx = 0; idx < sizeof(esp_algorithms)/sizeof(esp_algorithms[0]);
  192              idx++) {
  193                 if (esp_algorithms[idx].ivlenval > ivlen)
  194                         ivlen = esp_algorithms[idx].ivlenval;
  195         }
  196 
  197         return ivlen;
  198 }
  199 
  200 int
  201 esp_schedule(algo, sav)
  202         const struct esp_algorithm *algo;
  203         struct secasvar *sav;
  204 {
  205         int error;
  206 
  207         /* check for key length */
  208         if (_KEYBITS(sav->key_enc) < algo->keymin ||
  209             _KEYBITS(sav->key_enc) > algo->keymax) {
  210                 ipseclog((LOG_ERR,
  211                     "esp_schedule %s: unsupported key length %d: "
  212                     "needs %d to %d bits\n", algo->name, _KEYBITS(sav->key_enc),
  213                     algo->keymin, algo->keymax));
  214                 return EINVAL;
  215         }
  216 
  217         /* already allocated */
  218         if (sav->sched && sav->schedlen != 0)
  219                 return 0;
  220         /* no schedule necessary */
  221         if (!algo->schedule || !algo->schedlen)
  222                 return 0;
  223 
  224         sav->schedlen = (*algo->schedlen)(algo);
  225         if (sav->schedlen < 0)
  226                 return EINVAL;
  227 
  228 //#### that malloc should be replaced by a saved buffer...
  229         sav->sched = _MALLOC(sav->schedlen, M_SECA, M_DONTWAIT);
  230         if (!sav->sched) {
  231                 sav->schedlen = 0;
  232                 return ENOBUFS;
  233         }
  234 
  235         error = (*algo->schedule)(algo, sav);
  236         if (error) {
  237                 ipseclog((LOG_ERR, "esp_schedule %s: error %d\n",
  238                     algo->name, error));
  239                 bzero(sav->sched, sav->schedlen);
  240                 FREE(sav->sched, M_SECA);
  241                 sav->sched = NULL;
  242                 sav->schedlen = 0;
  243         }
  244         return error;
  245 }
  246 
  247 static int
  248 esp_null_mature(sav)
  249         struct secasvar *sav;
  250 {
  251 
  252         /* anything is okay */
  253         return 0;
  254 }
  255 
  256 static int
  257 esp_null_decrypt(m, off, sav, algo, ivlen)
  258         struct mbuf *m;
  259         size_t off;             /* offset to ESP header */
  260         struct secasvar *sav;
  261         const struct esp_algorithm *algo;
  262         int ivlen;
  263 {
  264 
  265         return 0; /* do nothing */
  266 }
  267 
  268 static int
  269 esp_null_encrypt(m, off, plen, sav, algo, ivlen)
  270         struct mbuf *m;
  271         size_t off;     /* offset to ESP header */
  272         size_t plen;    /* payload length (to be encrypted) */
  273         struct secasvar *sav;
  274         const struct esp_algorithm *algo;
  275         int ivlen;
  276 {
  277 
  278         return 0; /* do nothing */
  279 }
  280 
  281 static int
  282 esp_descbc_mature(sav)
  283         struct secasvar *sav;
  284 {
  285         const struct esp_algorithm *algo;
  286 
  287         if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) {
  288                 ipseclog((LOG_ERR, "esp_cbc_mature: "
  289                     "algorithm incompatible with 4 octets IV length\n"));
  290                 return 1;
  291         }
  292 
  293         if (!sav->key_enc) {
  294                 ipseclog((LOG_ERR, "esp_descbc_mature: no key is given.\n"));
  295                 return 1;
  296         }
  297 
  298         algo = esp_algorithm_lookup(sav->alg_enc);
  299         if (!algo) {
  300                 ipseclog((LOG_ERR,
  301                     "esp_descbc_mature: unsupported algorithm.\n"));
  302                 return 1;
  303         }
  304 
  305         if (_KEYBITS(sav->key_enc) < algo->keymin ||
  306             _KEYBITS(sav->key_enc) > algo->keymax) {
  307                 ipseclog((LOG_ERR,
  308                     "esp_descbc_mature: invalid key length %d.\n",
  309                     _KEYBITS(sav->key_enc)));
  310                 return 1;
  311         }
  312 
  313         /* weak key check */
  314         if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc))) {
  315                 ipseclog((LOG_ERR,
  316                     "esp_descbc_mature: weak key was passed.\n"));
  317                 return 1;
  318         }
  319 
  320         return 0;
  321 }
  322 
  323 static int
  324 esp_descbc_ivlen(algo, sav)
  325         const struct esp_algorithm *algo;
  326         struct secasvar *sav;
  327 {
  328 
  329         if (!sav)
  330                 return 8;
  331         if ((sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B))
  332                 return 4;
  333         if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_DERIV))
  334                 return 4;
  335         return 8;
  336 }
  337 
  338 static int
  339 esp_des_schedlen(algo)
  340         const struct esp_algorithm *algo;
  341 {
  342 
  343         return sizeof(des_key_schedule);
  344 }
  345 
  346 static int
  347 esp_des_schedule(algo, sav)
  348         const struct esp_algorithm *algo;
  349         struct secasvar *sav;
  350 {
  351 
  352         if (des_key_sched((des_cblock *)_KEYBUF(sav->key_enc),
  353             *(des_key_schedule *)sav->sched))
  354                 return EINVAL;
  355         else
  356                 return 0;
  357 }
  358 
  359 static int
  360 esp_des_blockdecrypt(algo, sav, s, d)
  361         const struct esp_algorithm *algo;
  362         struct secasvar *sav;
  363         u_int8_t *s;
  364         u_int8_t *d;
  365 {
  366 
  367         /* assumption: d has a good alignment */
  368         bcopy(s, d, sizeof(DES_LONG) * 2);
  369         des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
  370             *(des_key_schedule *)sav->sched, DES_DECRYPT);
  371         return 0;
  372 }
  373 
  374 static int
  375 esp_des_blockencrypt(algo, sav, s, d)
  376         const struct esp_algorithm *algo;
  377         struct secasvar *sav;
  378         u_int8_t *s;
  379         u_int8_t *d;
  380 {
  381 
  382         /* assumption: d has a good alignment */
  383         bcopy(s, d, sizeof(DES_LONG) * 2);
  384         des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
  385             *(des_key_schedule *)sav->sched, DES_ENCRYPT);
  386         return 0;
  387 }
  388 
  389 static int
  390 esp_cbc_mature(sav)
  391         struct secasvar *sav;
  392 {
  393         int keylen;
  394         const struct esp_algorithm *algo;
  395 
  396         if (sav->flags & SADB_X_EXT_OLD) {
  397                 ipseclog((LOG_ERR,
  398                     "esp_cbc_mature: algorithm incompatible with esp-old\n"));
  399                 return 1;
  400         }
  401         if (sav->flags & SADB_X_EXT_DERIV) {
  402                 ipseclog((LOG_ERR,
  403                     "esp_cbc_mature: algorithm incompatible with derived\n"));
  404                 return 1;
  405         }
  406 
  407         if (!sav->key_enc) {
  408                 ipseclog((LOG_ERR, "esp_cbc_mature: no key is given.\n"));
  409                 return 1;
  410         }
  411 
  412         algo = esp_algorithm_lookup(sav->alg_enc);
  413         if (!algo) {
  414                 ipseclog((LOG_ERR,
  415                     "esp_cbc_mature %s: unsupported algorithm.\n", algo->name));
  416                 return 1;
  417         }
  418 
  419         keylen = sav->key_enc->sadb_key_bits;
  420         if (keylen < algo->keymin || algo->keymax < keylen) {
  421                 ipseclog((LOG_ERR,
  422                     "esp_cbc_mature %s: invalid key length %d.\n",
  423                     algo->name, sav->key_enc->sadb_key_bits));
  424                 return 1;
  425         }
  426         switch (sav->alg_enc) {
  427         case SADB_EALG_3DESCBC:
  428                 /* weak key check */
  429                 if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc)) ||
  430                     des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 8)) ||
  431                     des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 16))) {
  432                         ipseclog((LOG_ERR,
  433                             "esp_cbc_mature %s: weak key was passed.\n",
  434                             algo->name));
  435                         return 1;
  436                 }
  437                 break;
  438         case SADB_X_EALG_BLOWFISHCBC:
  439         case SADB_X_EALG_CAST128CBC:
  440                 break;
  441         case SADB_X_EALG_RIJNDAELCBC:
  442                 /* allows specific key sizes only */
  443                 if (!(keylen == 128 || keylen == 192 || keylen == 256)) {
  444                         ipseclog((LOG_ERR,
  445                             "esp_cbc_mature %s: invalid key length %d.\n",
  446                             algo->name, keylen));
  447                         return 1;
  448                 }
  449                 break;
  450         }
  451 
  452         return 0;
  453 }
  454 
  455 static int
  456 esp_blowfish_schedlen(algo)
  457         const struct esp_algorithm *algo;
  458 {
  459 
  460         return sizeof(BF_KEY);
  461 }
  462 
  463 static int
  464 esp_blowfish_schedule(algo, sav)
  465         const struct esp_algorithm *algo;
  466         struct secasvar *sav;
  467 {
  468 
  469         BF_set_key((BF_KEY *)sav->sched, _KEYLEN(sav->key_enc),
  470             _KEYBUF(sav->key_enc));
  471         return 0;
  472 }
  473 
  474 static int
  475 esp_blowfish_blockdecrypt(algo, sav, s, d)
  476         const struct esp_algorithm *algo;
  477         struct secasvar *sav;
  478         u_int8_t *s;
  479         u_int8_t *d;
  480 {
  481         /* HOLY COW!  BF_decrypt() takes values in host byteorder */
  482         BF_LONG t[2];
  483 
  484         bcopy(s, t, sizeof(t));
  485         t[0] = ntohl(t[0]);
  486         t[1] = ntohl(t[1]);
  487         BF_decrypt(t, (BF_KEY *)sav->sched);
  488         t[0] = htonl(t[0]);
  489         t[1] = htonl(t[1]);
  490         bcopy(t, d, sizeof(t));
  491         return 0;
  492 }
  493 
  494 static int
  495 esp_blowfish_blockencrypt(algo, sav, s, d)
  496         const struct esp_algorithm *algo;
  497         struct secasvar *sav;
  498         u_int8_t *s;
  499         u_int8_t *d;
  500 {
  501         /* HOLY COW!  BF_encrypt() takes values in host byteorder */
  502         BF_LONG t[2];
  503 
  504         bcopy(s, t, sizeof(t));
  505         t[0] = ntohl(t[0]);
  506         t[1] = ntohl(t[1]);
  507         BF_encrypt(t, (BF_KEY *)sav->sched);
  508         t[0] = htonl(t[0]);
  509         t[1] = htonl(t[1]);
  510         bcopy(t, d, sizeof(t));
  511         return 0;
  512 }
  513 
  514 static int
  515 esp_cast128_schedlen(algo)
  516         const struct esp_algorithm *algo;
  517 {
  518 
  519         return sizeof(u_int32_t) * 32;
  520 }
  521 
  522 static int
  523 esp_cast128_schedule(algo, sav)
  524         const struct esp_algorithm *algo;
  525         struct secasvar *sav;
  526 {
  527 
  528         set_cast128_subkey((u_int32_t *)sav->sched, _KEYBUF(sav->key_enc),
  529                 _KEYLEN(sav->key_enc));
  530         return 0;
  531 }
  532 
  533 static int
  534 esp_cast128_blockdecrypt(algo, sav, s, d)
  535         const struct esp_algorithm *algo;
  536         struct secasvar *sav;
  537         u_int8_t *s;
  538         u_int8_t *d;
  539 {
  540 
  541         if (_KEYLEN(sav->key_enc) <= 80 / 8)
  542                 cast128_decrypt_round12(d, s, (u_int32_t *)sav->sched);
  543         else
  544                 cast128_decrypt_round16(d, s, (u_int32_t *)sav->sched);
  545         return 0;
  546 }
  547 
  548 static int
  549 esp_cast128_blockencrypt(algo, sav, s, d)
  550         const struct esp_algorithm *algo;
  551         struct secasvar *sav;
  552         u_int8_t *s;
  553         u_int8_t *d;
  554 {
  555 
  556         if (_KEYLEN(sav->key_enc) <= 80 / 8)
  557                 cast128_encrypt_round12(d, s, (u_int32_t *)sav->sched);
  558         else
  559                 cast128_encrypt_round16(d, s, (u_int32_t *)sav->sched);
  560         return 0;
  561 }
  562 
  563 static int
  564 esp_3des_schedlen(algo)
  565         const struct esp_algorithm *algo;
  566 {
  567 
  568         return sizeof(des_key_schedule) * 3;
  569 }
  570 
  571 static int
  572 esp_3des_schedule(algo, sav)
  573         const struct esp_algorithm *algo;
  574         struct secasvar *sav;
  575 {
  576         int error;
  577         des_key_schedule *p;
  578         int i;
  579         char *k;
  580 
  581         p = (des_key_schedule *)sav->sched;
  582         k = _KEYBUF(sav->key_enc);
  583         for (i = 0; i < 3; i++) {
  584                 error = des_key_sched((des_cblock *)(k + 8 * i), p[i]);
  585                 if (error)
  586                         return EINVAL;
  587         }
  588         return 0;
  589 }
  590 
  591 static int
  592 esp_3des_blockdecrypt(algo, sav, s, d)
  593         const struct esp_algorithm *algo;
  594         struct secasvar *sav;
  595         u_int8_t *s;
  596         u_int8_t *d;
  597 {
  598         des_key_schedule *p;
  599 
  600         /* assumption: d has a good alignment */
  601         p = (des_key_schedule *)sav->sched;
  602         bcopy(s, d, sizeof(DES_LONG) * 2);
  603         des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d, 
  604                          p[0], p[1], p[2], DES_DECRYPT);
  605         return 0;
  606 }
  607 
  608 static int
  609 esp_3des_blockencrypt(algo, sav, s, d)
  610         const struct esp_algorithm *algo;
  611         struct secasvar *sav;
  612         u_int8_t *s;
  613         u_int8_t *d;
  614 {
  615         des_key_schedule *p;
  616 
  617         /* assumption: d has a good alignment */
  618         p = (des_key_schedule *)sav->sched;
  619         bcopy(s, d, sizeof(DES_LONG) * 2);
  620         des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d, 
  621                          p[0], p[1], p[2], DES_ENCRYPT);
  622         return 0;
  623 }
  624 
  625 static int
  626 esp_common_ivlen(algo, sav)
  627         const struct esp_algorithm *algo;
  628         struct secasvar *sav;
  629 {
  630 
  631         if (!algo)
  632                 panic("esp_common_ivlen: unknown algorithm");
  633         return algo->ivlenval;
  634 }
  635 
  636 static int
  637 esp_cbc_decrypt(m, off, sav, algo, ivlen)
  638         struct mbuf *m;
  639         size_t off;
  640         struct secasvar *sav;
  641         const struct esp_algorithm *algo;
  642         int ivlen;
  643 {
  644         struct mbuf *s;
  645         struct mbuf *d, *d0, *dp;
  646         int soff, doff; /* offset from the head of chain, to head of this mbuf */
  647         int sn, dn;     /* offset from the head of the mbuf, to meat */
  648         size_t ivoff, bodyoff;
  649         u_int8_t iv[MAXIVLEN], *ivp;
  650         u_int8_t sbuf[MAXIVLEN], *sp;
  651         u_int8_t *p, *q;
  652         struct mbuf *scut;
  653         int scutoff;
  654         int i;
  655         int blocklen;
  656         int derived;
  657 
  658         if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
  659                 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
  660                     "unsupported ivlen %d\n", algo->name, ivlen));
  661                 m_freem(m);
  662                 return EINVAL;
  663         }
  664 
  665         /* assumes blocklen == padbound */
  666         blocklen = algo->padbound;
  667 
  668 #if DIAGNOSTIC
  669         if (blocklen > sizeof(iv)) {
  670                 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
  671                     "unsupported blocklen %d\n", algo->name, blocklen));
  672                 m_freem(m);
  673                 return EINVAL;
  674         }
  675 #endif
  676 
  677         if (sav->flags & SADB_X_EXT_OLD) {
  678                 /* RFC 1827 */
  679                 ivoff = off + sizeof(struct esp);
  680                 bodyoff = off + sizeof(struct esp) + ivlen;
  681                 derived = 0;
  682         } else {
  683                 /* RFC 2406 */
  684                 if (sav->flags & SADB_X_EXT_DERIV) {
  685                         /*
  686                          * draft-ietf-ipsec-ciph-des-derived-00.txt
  687                          * uses sequence number field as IV field.
  688                          */
  689                         ivoff = off + sizeof(struct esp);
  690                         bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
  691                         ivlen = sizeof(u_int32_t);
  692                         derived = 1;
  693                 } else {
  694                         ivoff = off + sizeof(struct newesp);
  695                         bodyoff = off + sizeof(struct newesp) + ivlen;
  696                         derived = 0;
  697                 }
  698         }
  699 
  700         /* grab iv */
  701         m_copydata(m, ivoff, ivlen, iv);
  702 
  703         /* extend iv */
  704         if (ivlen == blocklen)
  705                 ;
  706         else if (ivlen == 4 && blocklen == 8) {
  707                 bcopy(&iv[0], &iv[4], 4);
  708                 iv[4] ^= 0xff;
  709                 iv[5] ^= 0xff;
  710                 iv[6] ^= 0xff;
  711                 iv[7] ^= 0xff;
  712         } else {
  713                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
  714                     "unsupported ivlen/blocklen: %d %d\n",
  715                     algo->name, ivlen, blocklen));
  716                 m_freem(m);
  717                 return EINVAL;
  718         }
  719 
  720         if (m->m_pkthdr.len < bodyoff) {
  721                 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: bad len %d/%lu\n",
  722                     algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
  723                 m_freem(m);
  724                 return EINVAL;
  725         }
  726         if ((m->m_pkthdr.len - bodyoff) % blocklen) {
  727                 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
  728                     "payload length must be multiple of %d\n",
  729                     algo->name, blocklen));
  730                 m_freem(m);
  731                 return EINVAL;
  732         }
  733 
  734         s = m;
  735         d = d0 = dp = NULL;
  736         soff = doff = sn = dn = 0;
  737         ivp = sp = NULL;
  738 
  739         /* skip bodyoff */
  740         while (soff < bodyoff) {
  741                 if (soff + s->m_len > bodyoff) {
  742                         sn = bodyoff - soff;
  743                         break;
  744                 }
  745 
  746                 soff += s->m_len;
  747                 s = s->m_next;
  748         }
  749         scut = s;
  750         scutoff = sn;
  751 
  752         /* skip over empty mbuf */
  753         while (s && s->m_len == 0)
  754                 s = s->m_next;
  755 
  756         while (soff < m->m_pkthdr.len) {
  757                 /* source */
  758                 if (sn + blocklen <= s->m_len) {
  759                         /* body is continuous */
  760                         sp = mtod(s, u_int8_t *) + sn;
  761                 } else {
  762                         /* body is non-continuous */
  763                         m_copydata(s, sn, blocklen, sbuf);
  764                         sp = sbuf;
  765                 }
  766 
  767                 /* destination */
  768                 if (!d || dn + blocklen > d->m_len) {
  769                         if (d)
  770                                 dp = d;
  771                         MGET(d, M_DONTWAIT, MT_DATA);
  772                         i = m->m_pkthdr.len - (soff + sn);
  773                         if (d && i > MLEN) {
  774                                 MCLGET(d, M_DONTWAIT);
  775                                 if ((d->m_flags & M_EXT) == 0) {
  776                                         m_free(d);
  777                                         d = NULL;
  778                                 }
  779                         }
  780                         if (!d) {
  781                                 m_freem(m);
  782                                 if (d0)
  783                                         m_freem(d0);
  784                                 return ENOBUFS;
  785                         }
  786                         if (!d0)
  787                                 d0 = d;
  788                         if (dp)
  789                                 dp->m_next = d;
  790                         d->m_len = 0;
  791                         d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
  792                         if (d->m_len > i)
  793                                 d->m_len = i;
  794                         dn = 0;
  795                 }
  796 
  797                 /* decrypt */
  798                 (*algo->blockdecrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
  799 
  800                 /* xor */
  801                 p = ivp ? ivp : iv;
  802                 q = mtod(d, u_int8_t *) + dn;
  803                 for (i = 0; i < blocklen; i++)
  804                         q[i] ^= p[i];
  805 
  806                 /* next iv */
  807                 if (sp == sbuf) {
  808                         bcopy(sbuf, iv, blocklen);
  809                         ivp = NULL;
  810                 } else
  811                         ivp = sp;
  812 
  813                 sn += blocklen;
  814                 dn += blocklen;
  815 
  816                 /* find the next source block */
  817                 while (s && sn >= s->m_len) {
  818                         sn -= s->m_len;
  819                         soff += s->m_len;
  820                         s = s->m_next;
  821                 }
  822 
  823                 /* skip over empty mbuf */
  824                 while (s && s->m_len == 0)
  825                         s = s->m_next;
  826         }
  827 
  828         m_freem(scut->m_next);
  829         scut->m_len = scutoff;
  830         scut->m_next = d0;
  831 
  832         /* just in case */
  833         bzero(iv, sizeof(iv));
  834         bzero(sbuf, sizeof(sbuf));
  835 
  836         return 0;
  837 }
  838 
  839 static int
  840 esp_cbc_encrypt(m, off, plen, sav, algo, ivlen)
  841         struct mbuf *m;
  842         size_t off;
  843         size_t plen;
  844         struct secasvar *sav;
  845         const struct esp_algorithm *algo;
  846         int ivlen;
  847 {
  848         struct mbuf *s;
  849         struct mbuf *d, *d0, *dp;
  850         int soff, doff; /* offset from the head of chain, to head of this mbuf */
  851         int sn, dn;     /* offset from the head of the mbuf, to meat */
  852         size_t ivoff, bodyoff;
  853         u_int8_t iv[MAXIVLEN], *ivp;
  854         u_int8_t sbuf[MAXIVLEN], *sp;
  855         u_int8_t *p, *q;
  856         struct mbuf *scut;
  857         int scutoff;
  858         int i;
  859         int blocklen;
  860         int derived;
  861 
  862         if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
  863                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
  864                     "unsupported ivlen %d\n", algo->name, ivlen));
  865                 m_freem(m);
  866                 return EINVAL;
  867         }
  868 
  869         /* assumes blocklen == padbound */
  870         blocklen = algo->padbound;
  871 
  872 #if DIAGNOSTIC
  873         if (blocklen > sizeof(iv)) {
  874                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
  875                     "unsupported blocklen %d\n", algo->name, blocklen));
  876                 m_freem(m);
  877                 return EINVAL;
  878         }
  879 #endif
  880 
  881         if (sav->flags & SADB_X_EXT_OLD) {
  882                 /* RFC 1827 */
  883                 ivoff = off + sizeof(struct esp);
  884                 bodyoff = off + sizeof(struct esp) + ivlen;
  885                 derived = 0;
  886         } else {
  887                 /* RFC 2406 */
  888                 if (sav->flags & SADB_X_EXT_DERIV) {
  889                         /*
  890                          * draft-ietf-ipsec-ciph-des-derived-00.txt
  891                          * uses sequence number field as IV field.
  892                          */
  893                         ivoff = off + sizeof(struct esp);
  894                         bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
  895                         ivlen = sizeof(u_int32_t);
  896                         derived = 1;
  897                 } else {
  898                         ivoff = off + sizeof(struct newesp);
  899                         bodyoff = off + sizeof(struct newesp) + ivlen;
  900                         derived = 0;
  901                 }
  902         }
  903 
  904         /* put iv into the packet.  if we are in derived mode, use seqno. */
  905         if (derived)
  906                 m_copydata(m, ivoff, ivlen, iv);
  907         else {
  908                 bcopy(sav->iv, iv, ivlen);
  909                 /* maybe it is better to overwrite dest, not source */
  910                 m_copyback(m, ivoff, ivlen, iv);
  911         }
  912 
  913         /* extend iv */
  914         if (ivlen == blocklen)
  915                 ;
  916         else if (ivlen == 4 && blocklen == 8) {
  917                 bcopy(&iv[0], &iv[4], 4);
  918                 iv[4] ^= 0xff;
  919                 iv[5] ^= 0xff;
  920                 iv[6] ^= 0xff;
  921                 iv[7] ^= 0xff;
  922         } else {
  923                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
  924                     "unsupported ivlen/blocklen: %d %d\n",
  925                     algo->name, ivlen, blocklen));
  926                 m_freem(m);
  927                 return EINVAL;
  928         }
  929 
  930         if (m->m_pkthdr.len < bodyoff) {
  931                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: bad len %d/%lu\n",
  932                     algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
  933                 m_freem(m);
  934                 return EINVAL;
  935         }
  936         if ((m->m_pkthdr.len - bodyoff) % blocklen) {
  937                 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
  938                     "payload length must be multiple of %lu\n",
  939                     algo->name, (unsigned long)algo->padbound));
  940                 m_freem(m);
  941                 return EINVAL;
  942         }
  943 
  944         s = m;
  945         d = d0 = dp = NULL;
  946         soff = doff = sn = dn = 0;
  947         ivp = sp = NULL;
  948 
  949         /* skip bodyoff */
  950         while (soff < bodyoff) {
  951                 if (soff + s->m_len > bodyoff) {
  952                         sn = bodyoff - soff;
  953                         break;
  954                 }
  955 
  956                 soff += s->m_len;
  957                 s = s->m_next;
  958         }
  959         scut = s;
  960         scutoff = sn;
  961 
  962         /* skip over empty mbuf */
  963         while (s && s->m_len == 0)
  964                 s = s->m_next;
  965 
  966         while (soff < m->m_pkthdr.len) {
  967                 /* source */
  968                 if (sn + blocklen <= s->m_len) {
  969                         /* body is continuous */
  970                         sp = mtod(s, u_int8_t *) + sn;
  971                 } else {
  972                         /* body is non-continuous */
  973                         m_copydata(s, sn, blocklen, sbuf);
  974                         sp = sbuf;
  975                 }
  976 
  977                 /* destination */
  978                 if (!d || dn + blocklen > d->m_len) {
  979                         if (d)
  980                                 dp = d;
  981                         MGET(d, M_DONTWAIT, MT_DATA);
  982                         i = m->m_pkthdr.len - (soff + sn);
  983                         if (d && i > MLEN) {
  984                                 MCLGET(d, M_DONTWAIT);
  985                                 if ((d->m_flags & M_EXT) == 0) {
  986                                         m_free(d);
  987                                         d = NULL;
  988                                 }
  989                         }
  990                         if (!d) {
  991                                 m_freem(m);
  992                                 if (d0)
  993                                         m_freem(d0);
  994                                 return ENOBUFS;
  995                         }
  996                         if (!d0)
  997                                 d0 = d;
  998                         if (dp)
  999                                 dp->m_next = d;
 1000                         d->m_len = 0;
 1001                         d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
 1002                         if (d->m_len > i)
 1003                                 d->m_len = i;
 1004                         dn = 0;
 1005                 }
 1006 
 1007                 /* xor */
 1008                 p = ivp ? ivp : iv;
 1009                 q = sp;
 1010                 for (i = 0; i < blocklen; i++)
 1011                         q[i] ^= p[i];
 1012 
 1013                 /* encrypt */
 1014                 (*algo->blockencrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
 1015 
 1016                 /* next iv */
 1017                 ivp = mtod(d, u_int8_t *) + dn;
 1018 
 1019                 sn += blocklen;
 1020                 dn += blocklen;
 1021 
 1022                 /* find the next source block */
 1023                 while (s && sn >= s->m_len) {
 1024                         sn -= s->m_len;
 1025                         soff += s->m_len;
 1026                         s = s->m_next;
 1027                 }
 1028 
 1029                 /* skip over empty mbuf */
 1030                 while (s && s->m_len == 0)
 1031                         s = s->m_next;
 1032         }
 1033 
 1034         m_freem(scut->m_next);
 1035         scut->m_len = scutoff;
 1036         scut->m_next = d0;
 1037 
 1038         /* just in case */
 1039         bzero(iv, sizeof(iv));
 1040         bzero(sbuf, sizeof(sbuf));
 1041 
 1042         key_sa_stir_iv(sav);
 1043 
 1044         return 0;
 1045 }
 1046 
 1047 /*------------------------------------------------------------*/
 1048 
 1049 /* does not free m0 on error */
 1050 int
 1051 esp_auth(m0, skip, length, sav, sum)
 1052         struct mbuf *m0;
 1053         size_t skip;    /* offset to ESP header */
 1054         size_t length;  /* payload length */
 1055         struct secasvar *sav;
 1056         u_char *sum;
 1057 {
 1058         struct mbuf *m;
 1059         size_t off;
 1060         struct ah_algorithm_state s;
 1061         u_char sumbuf[AH_MAXSUMSIZE];
 1062         const struct ah_algorithm *algo;
 1063         size_t siz;
 1064         int error;
 1065 
 1066         /* sanity checks */
 1067         if (m0->m_pkthdr.len < skip) {
 1068                 ipseclog((LOG_DEBUG, "esp_auth: mbuf length < skip\n"));
 1069                 return EINVAL;
 1070         }
 1071         if (m0->m_pkthdr.len < skip + length) {
 1072                 ipseclog((LOG_DEBUG,
 1073                     "esp_auth: mbuf length < skip + length\n"));
 1074                 return EINVAL;
 1075         }
 1076 
 1077         KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_START, skip,length,0,0,0);
 1078         /*
 1079          * length of esp part (excluding authentication data) must be 4n,
 1080          * since nexthdr must be at offset 4n+3.
 1081          */
 1082         if (length % 4) {
 1083                 ipseclog((LOG_ERR, "esp_auth: length is not multiple of 4\n"));
 1084                 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 1,0,0,0,0);
 1085                 return EINVAL;
 1086         }
 1087         if (!sav) {
 1088                 ipseclog((LOG_DEBUG, "esp_auth: NULL SA passed\n"));
 1089                 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 2,0,0,0,0);
 1090                 return EINVAL;
 1091         }
 1092         algo = ah_algorithm_lookup(sav->alg_auth);
 1093         if (!algo) {
 1094                 ipseclog((LOG_ERR,
 1095                     "esp_auth: bad ESP auth algorithm passed: %d\n",
 1096                     sav->alg_auth));
 1097                 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 3,0,0,0,0);
 1098                 return EINVAL;
 1099         }
 1100 
 1101         m = m0;
 1102         off = 0;
 1103 
 1104         siz = (((*algo->sumsiz)(sav) + 3) & ~(4 - 1));
 1105         if (sizeof(sumbuf) < siz) {
 1106                 ipseclog((LOG_DEBUG,
 1107                     "esp_auth: AH_MAXSUMSIZE is too small: siz=%lu\n",
 1108                     (u_long)siz));
 1109                 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 4,0,0,0,0);
 1110                 return EINVAL;
 1111         }
 1112 
 1113         /* skip the header */
 1114         while (skip) {
 1115                 if (!m)
 1116                         panic("mbuf chain?");
 1117                 if (m->m_len <= skip) {
 1118                         skip -= m->m_len;
 1119                         m = m->m_next;
 1120                         off = 0;
 1121                 } else {
 1122                         off = skip;
 1123                         skip = 0;
 1124                 }
 1125         }
 1126 
 1127         error = (*algo->init)(&s, sav);
 1128         if (error) {
 1129                 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 5,0,0,0,0);
 1130                 return error;
 1131         }
 1132 
 1133         while (0 < length) {
 1134                 if (!m)
 1135                         panic("mbuf chain?");
 1136 
 1137                 if (m->m_len - off < length) {
 1138                         (*algo->update)(&s, mtod(m, u_char *) + off,
 1139                                 m->m_len - off);
 1140                         length -= m->m_len - off;
 1141                         m = m->m_next;
 1142                         off = 0;
 1143                 } else {
 1144                         (*algo->update)(&s, mtod(m, u_char *) + off, length);
 1145                         break;
 1146                 }
 1147         }
 1148         (*algo->result)(&s, sumbuf);
 1149         bcopy(sumbuf, sum, siz);        /*XXX*/
 1150         
 1151         KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 6,0,0,0,0);
 1152         return 0;
 1153 }

Cache object: 84765a143f5d1f3ec69fca7973e061b9


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


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