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

Cache object: aef0e1ac840ebb4858fd886b25ceabc5


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