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

Cache object: 4d7ef53699cf7b727dc21dfeec8b971b


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