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

Cache object: f7ea0a8e0a09ed02fe8bd7e4cfdde2c0


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