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$       */
    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 <netinet6/esp_camellia.h>
   72 #include <netinet6/esp_aesctr.h>
   73 #include <net/pfkeyv2.h>
   74 #include <netkey/keydb.h>
   75 #include <netkey/key.h>
   76 
   77 #include <crypto/des/des.h>
   78 #include <crypto/blowfish/blowfish.h>
   79 
   80 #include <opencrypto/cast.h>
   81 #define cast128_key     cast_key
   82 #define cast128_setkey(key, rawkey, keybytes) \
   83         cast_setkey((key), (rawkey), (keybytes))
   84 #define cast128_encrypt(key, inblock, outblock) \
   85         cast_encrypt((key), (inblock), (outblock))
   86 #define cast128_decrypt(key, inblock, outblock) \
   87         cast_decrypt((key), (inblock), (outblock))
   88 
   89 #include <net/net_osdep.h>
   90 
   91 static int esp_null_mature __P((struct secasvar *));
   92 static int esp_null_decrypt __P((struct mbuf *, size_t,
   93         struct secasvar *, const struct esp_algorithm *, int));
   94 static int esp_null_encrypt __P((struct mbuf *, size_t, size_t,
   95         struct secasvar *, const struct esp_algorithm *, int));
   96 static int esp_descbc_mature __P((struct secasvar *));
   97 static int esp_descbc_ivlen __P((const struct esp_algorithm *,
   98         struct secasvar *));
   99 static int esp_des_schedule __P((const struct esp_algorithm *,
  100         struct secasvar *));
  101 static size_t esp_des_schedlen __P((const struct esp_algorithm *));
  102 static int esp_des_blockdecrypt __P((const struct esp_algorithm *,
  103         struct secasvar *, u_int8_t *, u_int8_t *));
  104 static int esp_des_blockencrypt __P((const struct esp_algorithm *,
  105         struct secasvar *, u_int8_t *, u_int8_t *));
  106 static int esp_cbc_mature __P((struct secasvar *));
  107 static int esp_blowfish_schedule __P((const struct esp_algorithm *,
  108         struct secasvar *));
  109 static size_t esp_blowfish_schedlen __P((const struct esp_algorithm *));
  110 static int esp_blowfish_blockdecrypt __P((const struct esp_algorithm *,
  111         struct secasvar *, u_int8_t *, u_int8_t *));
  112 static int esp_blowfish_blockencrypt __P((const struct esp_algorithm *,
  113         struct secasvar *, u_int8_t *, u_int8_t *));
  114 static int esp_cast128_schedule __P((const struct esp_algorithm *,
  115         struct secasvar *));
  116 static size_t esp_cast128_schedlen __P((const struct esp_algorithm *));
  117 static int esp_cast128_blockdecrypt __P((const struct esp_algorithm *,
  118         struct secasvar *, u_int8_t *, u_int8_t *));
  119 static int esp_cast128_blockencrypt __P((const struct esp_algorithm *,
  120         struct secasvar *, u_int8_t *, u_int8_t *));
  121 static int esp_3des_schedule __P((const struct esp_algorithm *,
  122         struct secasvar *));
  123 static size_t esp_3des_schedlen __P((const struct esp_algorithm *));
  124 static int esp_3des_blockdecrypt __P((const struct esp_algorithm *,
  125         struct secasvar *, u_int8_t *, u_int8_t *));
  126 static int esp_3des_blockencrypt __P((const struct esp_algorithm *,
  127         struct secasvar *, u_int8_t *, u_int8_t *));
  128 static int esp_common_ivlen __P((const struct esp_algorithm *,
  129         struct secasvar *));
  130 static int esp_cbc_decrypt __P((struct mbuf *, size_t,
  131         struct secasvar *, const struct esp_algorithm *, int));
  132 static int esp_cbc_encrypt __P((struct mbuf *, size_t, size_t,
  133         struct secasvar *, const struct esp_algorithm *, int));
  134 
  135 #define MAXIVLEN        16
  136 
  137 static const struct esp_algorithm esp_algorithms[] = {
  138         { 8, -1, esp_descbc_mature, 64, 64, esp_des_schedlen,
  139                 "des-cbc",
  140                 esp_descbc_ivlen, esp_cbc_decrypt,
  141                 esp_cbc_encrypt, esp_des_schedule,
  142                 esp_des_blockdecrypt, esp_des_blockencrypt, },
  143         { 8, 8, esp_cbc_mature, 192, 192, esp_3des_schedlen,
  144                 "3des-cbc",
  145                 esp_common_ivlen, esp_cbc_decrypt,
  146                 esp_cbc_encrypt, esp_3des_schedule,
  147                 esp_3des_blockdecrypt, esp_3des_blockencrypt, },
  148         { 1, 0, esp_null_mature, 0, 2048, NULL, "null",
  149                 esp_common_ivlen, esp_null_decrypt,
  150                 esp_null_encrypt, NULL, },
  151         { 8, 8, esp_cbc_mature, 40, 448, esp_blowfish_schedlen, "blowfish-cbc",
  152                 esp_common_ivlen, esp_cbc_decrypt,
  153                 esp_cbc_encrypt, esp_blowfish_schedule,
  154                 esp_blowfish_blockdecrypt, esp_blowfish_blockencrypt, },
  155         { 8, 8, esp_cbc_mature, 40, 128, esp_cast128_schedlen,
  156                 "cast128-cbc",
  157                 esp_common_ivlen, esp_cbc_decrypt,
  158                 esp_cbc_encrypt, esp_cast128_schedule,
  159                 esp_cast128_blockdecrypt, esp_cast128_blockencrypt, },
  160         { 16, 16, esp_cbc_mature, 128, 256, esp_rijndael_schedlen,
  161                 "rijndael-cbc",
  162                 esp_common_ivlen, esp_cbc_decrypt,
  163                 esp_cbc_encrypt, esp_rijndael_schedule,
  164                 esp_rijndael_blockdecrypt, esp_rijndael_blockencrypt },
  165         { 16, 8, esp_aesctr_mature, 160, 288, esp_aesctr_schedlen, "aes-ctr",
  166                 esp_common_ivlen, esp_aesctr_decrypt,
  167                 esp_aesctr_encrypt, esp_aesctr_schedule },
  168         { 16, 16, esp_cbc_mature, 128, 256, esp_camellia_schedlen,
  169                 "camellia-cbc",
  170                 esp_common_ivlen, esp_cbc_decrypt,
  171                 esp_cbc_encrypt, esp_camellia_schedule,
  172                 esp_camellia_blockdecrypt, esp_camellia_blockencrypt },
  173 };
  174 
  175 const struct esp_algorithm *
  176 esp_algorithm_lookup(idx)
  177         int idx;
  178 {
  179 
  180         switch (idx) {
  181         case SADB_EALG_DESCBC:
  182                 return &esp_algorithms[0];
  183         case SADB_EALG_3DESCBC:
  184                 return &esp_algorithms[1];
  185         case SADB_EALG_NULL:
  186                 return &esp_algorithms[2];
  187         case SADB_X_EALG_BLOWFISHCBC:
  188                 return &esp_algorithms[3];
  189         case SADB_X_EALG_CAST128CBC:
  190                 return &esp_algorithms[4];
  191         case SADB_X_EALG_RIJNDAELCBC:
  192                 return &esp_algorithms[5];
  193         case SADB_X_EALG_AESCTR:
  194                 return &esp_algorithms[6];
  195         case SADB_X_EALG_CAMELLIACBC:
  196                 return &esp_algorithms[7];
  197         default:
  198                 return NULL;
  199         }
  200 }
  201 
  202 int
  203 esp_max_ivlen()
  204 {
  205         int idx;
  206         int ivlen;
  207 
  208         ivlen = 0;
  209         for (idx = 0; idx < sizeof(esp_algorithms)/sizeof(esp_algorithms[0]);
  210              idx++) {
  211                 if (esp_algorithms[idx].ivlenval > ivlen)
  212                         ivlen = esp_algorithms[idx].ivlenval;
  213         }
  214         return ivlen;
  215 }
  216 
  217 int
  218 esp_schedule(algo, sav)
  219         const struct esp_algorithm *algo;
  220         struct secasvar *sav;
  221 {
  222         int error;
  223 
  224         /* check for key length */
  225         if (_KEYBITS(sav->key_enc) < algo->keymin ||
  226             _KEYBITS(sav->key_enc) > algo->keymax) {
  227                 ipseclog((LOG_ERR,
  228                     "esp_schedule %s: unsupported key length %d: "
  229                     "needs %d to %d bits\n", algo->name, _KEYBITS(sav->key_enc),
  230                     algo->keymin, algo->keymax));
  231                 return EINVAL;
  232         }
  233 
  234         /* already allocated */
  235         if (sav->sched && sav->schedlen != 0)
  236                 return 0;
  237         /* no schedule necessary */
  238         if (!algo->schedule || !algo->schedlen)
  239                 return 0;
  240 
  241         sav->schedlen = (*algo->schedlen)(algo);
  242         sav->sched = malloc(sav->schedlen, M_SECA, M_NOWAIT);
  243         if (!sav->sched) {
  244                 sav->schedlen = 0;
  245                 return ENOBUFS;
  246         }
  247 
  248         error = (*algo->schedule)(algo, sav);
  249         if (error) {
  250                 ipseclog((LOG_ERR, "esp_schedule %s: error %d\n",
  251                     algo->name, error));
  252                 bzero(sav->sched, sav->schedlen);
  253                 free(sav->sched, M_SECA);
  254                 sav->sched = NULL;
  255                 sav->schedlen = 0;
  256         }
  257         return error;
  258 }
  259 
  260 static int
  261 esp_null_mature(sav)
  262         struct secasvar *sav;
  263 {
  264 
  265         /* anything is okay */
  266         return 0;
  267 }
  268 
  269 static int
  270 esp_null_decrypt(m, off, sav, algo, ivlen)
  271         struct mbuf *m;
  272         size_t off;             /* offset to ESP header */
  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_null_encrypt(m, off, plen, sav, algo, ivlen)
  283         struct mbuf *m;
  284         size_t off;     /* offset to ESP header */
  285         size_t plen;    /* payload length (to be encrypted) */
  286         struct secasvar *sav;
  287         const struct esp_algorithm *algo;
  288         int ivlen;
  289 {
  290 
  291         return 0; /* do nothing */
  292 }
  293 
  294 static int
  295 esp_descbc_mature(sav)
  296         struct secasvar *sav;
  297 {
  298         const struct esp_algorithm *algo;
  299 
  300         if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) {
  301                 ipseclog((LOG_ERR, "esp_cbc_mature: "
  302                     "algorithm incompatible with 4 octets IV length\n"));
  303                 return 1;
  304         }
  305 
  306         if (!sav->key_enc) {
  307                 ipseclog((LOG_ERR, "esp_descbc_mature: no key is given.\n"));
  308                 return 1;
  309         }
  310 
  311         algo = esp_algorithm_lookup(sav->alg_enc);
  312         if (!algo) {
  313                 ipseclog((LOG_ERR,
  314                     "esp_descbc_mature: unsupported algorithm.\n"));
  315                 return 1;
  316         }
  317 
  318         if (_KEYBITS(sav->key_enc) < algo->keymin ||
  319             _KEYBITS(sav->key_enc) > algo->keymax) {
  320                 ipseclog((LOG_ERR,
  321                     "esp_descbc_mature: invalid key length %d.\n",
  322                     _KEYBITS(sav->key_enc)));
  323                 return 1;
  324         }
  325 
  326         /* weak key check */
  327         if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc))) {
  328                 ipseclog((LOG_ERR,
  329                     "esp_descbc_mature: weak key was passed.\n"));
  330                 return 1;
  331         }
  332 
  333         return 0;
  334 }
  335 
  336 static int
  337 esp_descbc_ivlen(algo, sav)
  338         const struct esp_algorithm *algo;
  339         struct secasvar *sav;
  340 {
  341 
  342         if (!sav)
  343                 return 8;
  344         if ((sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B))
  345                 return 4;
  346         if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_DERIV))
  347                 return 4;
  348         return 8;
  349 }
  350 
  351 static size_t
  352 esp_des_schedlen(algo)
  353         const struct esp_algorithm *algo;
  354 {
  355 
  356         return sizeof(des_key_schedule);
  357 }
  358 
  359 static int
  360 esp_des_schedule(algo, sav)
  361         const struct esp_algorithm *algo;
  362         struct secasvar *sav;
  363 {
  364 
  365         if (des_key_sched((des_cblock *)_KEYBUF(sav->key_enc),
  366             *(des_key_schedule *)sav->sched))
  367                 return EINVAL;
  368         else
  369                 return 0;
  370 }
  371 
  372 static int
  373 esp_des_blockdecrypt(algo, sav, s, d)
  374         const struct esp_algorithm *algo;
  375         struct secasvar *sav;
  376         u_int8_t *s;
  377         u_int8_t *d;
  378 {
  379 
  380         /* assumption: d has a good alignment */
  381         bcopy(s, d, sizeof(DES_LONG) * 2);
  382         des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
  383             *(des_key_schedule *)sav->sched, DES_DECRYPT);
  384         return 0;
  385 }
  386 
  387 static int
  388 esp_des_blockencrypt(algo, sav, s, d)
  389         const struct esp_algorithm *algo;
  390         struct secasvar *sav;
  391         u_int8_t *s;
  392         u_int8_t *d;
  393 {
  394 
  395         /* assumption: d has a good alignment */
  396         bcopy(s, d, sizeof(DES_LONG) * 2);
  397         des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
  398             *(des_key_schedule *)sav->sched, DES_ENCRYPT);
  399         return 0;
  400 }
  401 
  402 static int
  403 esp_cbc_mature(sav)
  404         struct secasvar *sav;
  405 {
  406         int keylen;
  407         const struct esp_algorithm *algo;
  408 
  409         if (sav->flags & SADB_X_EXT_OLD) {
  410                 ipseclog((LOG_ERR,
  411                     "esp_cbc_mature: algorithm incompatible with esp-old\n"));
  412                 return 1;
  413         }
  414         if (sav->flags & SADB_X_EXT_DERIV) {
  415                 ipseclog((LOG_ERR,
  416                     "esp_cbc_mature: algorithm incompatible with derived\n"));
  417                 return 1;
  418         }
  419 
  420         if (!sav->key_enc) {
  421                 ipseclog((LOG_ERR, "esp_cbc_mature: no key is given.\n"));
  422                 return 1;
  423         }
  424 
  425         algo = esp_algorithm_lookup(sav->alg_enc);
  426         if (!algo) {
  427                 ipseclog((LOG_ERR,
  428                     "esp_cbc_mature %s: unsupported algorithm.\n", algo->name));
  429                 return 1;
  430         }
  431 
  432         keylen = sav->key_enc->sadb_key_bits;
  433         if (keylen < algo->keymin || algo->keymax < keylen) {
  434                 ipseclog((LOG_ERR,
  435                     "esp_cbc_mature %s: invalid key length %d.\n",
  436                     algo->name, sav->key_enc->sadb_key_bits));
  437                 return 1;
  438         }
  439         switch (sav->alg_enc) {
  440         case SADB_EALG_3DESCBC:
  441                 /* weak key check */
  442                 if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc)) ||
  443                     des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 8)) ||
  444                     des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 16))) {
  445                         ipseclog((LOG_ERR,
  446                             "esp_cbc_mature %s: weak key was passed.\n",
  447                             algo->name));
  448                         return 1;
  449                 }
  450                 break;
  451         case SADB_X_EALG_BLOWFISHCBC:
  452         case SADB_X_EALG_CAST128CBC:
  453                 break;
  454         case SADB_X_EALG_RIJNDAELCBC:
  455         case SADB_X_EALG_CAMELLIACBC:
  456                 /* allows specific key sizes only */
  457                 if (!(keylen == 128 || keylen == 192 || keylen == 256)) {
  458                         ipseclog((LOG_ERR,
  459                             "esp_cbc_mature %s: invalid key length %d.\n",
  460                             algo->name, keylen));
  461                         return 1;
  462                 }
  463                 break;
  464         }
  465 
  466         return 0;
  467 }
  468 
  469 static size_t
  470 esp_blowfish_schedlen(algo)
  471         const struct esp_algorithm *algo;
  472 {
  473 
  474         return sizeof(BF_KEY);
  475 }
  476 
  477 static int
  478 esp_blowfish_schedule(algo, sav)
  479         const struct esp_algorithm *algo;
  480         struct secasvar *sav;
  481 {
  482 
  483         BF_set_key((BF_KEY *)sav->sched, _KEYLEN(sav->key_enc),
  484             _KEYBUF(sav->key_enc));
  485         return 0;
  486 }
  487 
  488 static int
  489 esp_blowfish_blockdecrypt(algo, sav, s, d)
  490         const struct esp_algorithm *algo;
  491         struct secasvar *sav;
  492         u_int8_t *s;
  493         u_int8_t *d;
  494 {
  495 
  496         BF_ecb_encrypt(s, d, (BF_KEY *)sav->sched, 0);
  497         return 0;
  498 }
  499 
  500 static int
  501 esp_blowfish_blockencrypt(algo, sav, s, d)
  502         const struct esp_algorithm *algo;
  503         struct secasvar *sav;
  504         u_int8_t *s;
  505         u_int8_t *d;
  506 {
  507 
  508         BF_ecb_encrypt(s, d, (BF_KEY *)sav->sched, 1);
  509         return 0;
  510 }
  511 
  512 static size_t
  513 esp_cast128_schedlen(algo)
  514         const struct esp_algorithm *algo;
  515 {
  516 
  517         return sizeof(cast128_key);
  518 }
  519 
  520 static int
  521 esp_cast128_schedule(algo, sav)
  522         const struct esp_algorithm *algo;
  523         struct secasvar *sav;
  524 {
  525 
  526         cast128_setkey((cast128_key *)sav->sched, _KEYBUF(sav->key_enc),
  527             _KEYLEN(sav->key_enc));
  528         return 0;
  529 }
  530 
  531 static int
  532 esp_cast128_blockdecrypt(algo, sav, s, d)
  533         const struct esp_algorithm *algo;
  534         struct secasvar *sav;
  535         u_int8_t *s;
  536         u_int8_t *d;
  537 {
  538 
  539         cast128_decrypt((cast128_key *)sav->sched, s, d);
  540         return 0;
  541 }
  542 
  543 static int
  544 esp_cast128_blockencrypt(algo, sav, s, d)
  545         const struct esp_algorithm *algo;
  546         struct secasvar *sav;
  547         u_int8_t *s;
  548         u_int8_t *d;
  549 {
  550 
  551         cast128_encrypt((cast128_key *)sav->sched, s, d);
  552         return 0;
  553 }
  554 
  555 static size_t
  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         u_int8_t *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, (caddr_t)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, (caddr_t)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, (caddr_t)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, (caddr_t)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, sizeof(sumbuf));
 1133         bcopy(sumbuf, sum, siz);        /* XXX */
 1134 
 1135         return 0;
 1136 }

Cache object: d1e9d15afbbe03e77f944a1161c91d01


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