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

Cache object: bdd29aabaef51d4fc9646efa3f1411af


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