The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet6/esp_core.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 6fa81f793ab3b40d4ece8cfb72590cb6


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