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

Cache object: 1f6d308adfec1b08dd79494009e094a3


[ 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.